blob: 191a289b1af760a2b4290c97f23ed57b95173d8d [file] [log] [blame]
# -*- coding: utf-8 -*-
# Copyright 2015 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Unittests for Mob* Monitor checkfile manager."""
from __future__ import print_function
import imp
import mock
import os
import subprocess
import time
import threading
from cherrypy.process import plugins
from chromite.lib import cros_test_lib
from chromite.mobmonitor.checkfile import manager
# Test health check and related attributes
class TestHealthCheck(object):
"""Test health check."""
def Check(self):
"""Stub Check."""
return 0
def Diagnose(self, _errcode):
"""Stub Diagnose."""
return ('Unknown Error.', [])
class TestHealthCheckHasAttributes(object):
"""Test health check with attributes."""
CHECK_INTERVAL_SEC = 10
def Check(self):
"""Stub Check."""
return 0
def Diagnose(self, _errcode):
"""Stub Diagnose."""
return ('Unknown Error.', [])
class TestHealthCheckUnhealthy(object):
"""Unhealthy test health check."""
def __init__(self):
self.x = -1
def Check(self):
"""Stub Check."""
return self.x
def Diagnose(self, errcode):
"""Stub Diagnose."""
if errcode == -1:
return ('Stub Error.', [self.Repair])
return ('Unknown Error.', [])
def Repair(self):
self.x = 0
class TestHealthCheckMultipleActions(object):
"""Unhealthy check with many actions that have different parameters."""
def __init__(self):
self.x = -1
def Check(self):
"""Stub Check."""
return self.x
def Diagnose(self, errcode):
"""Stub Diagnose."""
if errcode == -1:
return ('Stub Error.', [self.NoParams, self.PositionalParams,
self.DefaultParams, self.MixedParams])
return ('Unknown Error.', [])
def NoParams(self):
"""NoParams Action."""
self.x = 0
# pylint: disable=unused-argument
def PositionalParams(self, x, y, z):
"""PositionalParams Action."""
self.x = 0
def DefaultParams(self, x=1, y=2, z=3):
"""DefaultParams Action."""
self.x = 0
def MixedParams(self, x, y, z=1):
"""MixedParams Action."""
self.x = 0
# pylint: enable=unused-argument
class TestHealthCheckQuasihealthy(object):
"""Quasi-healthy test health check."""
def Check(self):
"""Stub Check."""
return 1
def Diagnose(self, errcode):
"""Stub Diagnose."""
if errcode == 1:
return ('Stub Error.', [self.RepairStub])
return ('Unknown Error.', [])
def RepairStub(self):
"""Stub repair action."""
class TestHealthCheckBroken(object):
"""Broken test health check."""
def Check(self):
"""Stub Check."""
raise ValueError()
def Diagnose(self, _errcode):
"""A broken Diagnose function. A proper return should be a pair."""
raise ValueError()
def TestAction():
return True
TEST_SERVICE_NAME = 'test-service'
TEST_MTIME = 100
TEST_EXEC_TIME = 400
CHECKDIR = '.'
# Strings that are used to mock actual check modules.
CHECKFILE_MANY_SIMPLE = '''
SERVICE = 'test-service'
class MyHealthCheck2(object):
def Check(self):
return 0
def Diagnose(self, errcode):
return ('Unknown error.', [])
class MyHealthCheck3(object):
def Check(self):
return 0
def Diagnose(self, errcode):
return ('Unknown error.', [])
class MyHealthCheck4(object):
def Check(self):
return 0
def Diagnose(self, errcode):
return ('Unknown error.', [])
'''
CHECKFILE_MANY_SIMPLE_ONE_BAD = '''
SERVICE = 'test-service'
class MyHealthCheck(object):
def Check(self):
return 0
def Diagnose(self, errcode):
return ('Unknown error.', [])
class NotAHealthCheck(object):
def Diagnose(self, errcode):
return ('Unknown error.', [])
class MyHealthCheck2(object):
def Check(self):
return 0
def Diagnose(self, errcode):
return ('Unknown error.', [])
'''
NOT_A_CHECKFILE = '''
class NotAHealthCheck(object):
def NotCheckNorDiagnose(self):
return -1
'''
ANOTHER_NOT_A_CHECKFILE = '''
class AnotherNotAHealthCheck(object):
def AnotherNotCheckNorDiagnose(self):
return -2
'''
ACTION_FILE = '''
def TestAction():
return True
def AnotherAction():
return False
'''
class RunCommand(threading.Thread):
"""Helper class for executing the Mob* Monitor with a timeout."""
def __init__(self, cmd, timeout):
threading.Thread.__init__(self)
self.cmd = cmd
self.timeout = timeout
self.p = None
self.proc_stdout = None
self.proc_stderr = None
def run(self):
self.p = subprocess.Popen(self.cmd, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
self.proc_stdout, self.proc_stderr = self.p.communicate()
def Stop(self):
self.join(self.timeout)
if self.is_alive():
self.p.terminate()
self.join(self.timeout)
if self.is_alive():
self.p.kill()
self.join(self.timeout)
return self.proc_stdout
class CheckFileManagerHelperTest(cros_test_lib.MockTestCase):
"""Unittests for CheckFileManager helper functions."""
def testMapHealthcheckStatusToDict(self):
"""Test mapping a manager.HEALTHCHECK_STATUS to a dict."""
def _func():
pass
status = manager.HEALTHCHECK_STATUS('test', False, 'desc', [_func])
expect = {'name': 'test', 'health': False, 'description': 'desc',
'actions': ['_func']}
self.assertEquals(expect, manager.MapHealthcheckStatusToDict(status))
def testMapServiceStatusToDict(self):
"""Test mapping a manager.SERVICE_STATUS to a dict."""
def _func():
pass
hcstatus = manager.HEALTHCHECK_STATUS('test', False, 'desc', [_func])
hcexpect = {'name': 'test', 'health': False, 'description': 'desc',
'actions': ['_func']}
status = manager.SERVICE_STATUS('test-service', False, [hcstatus])
expect = {'service': 'test-service', 'health': False,
'healthchecks': [hcexpect]}
self.assertEquals(expect, manager.MapServiceStatusToDict(status))
def testMapActionInfoToDict(self):
"""Test mapping a manager.ACTION_INFO to a dict."""
actioninfo = manager.ACTION_INFO('test', 'test', [1], {'a': 1})
expect = {'action': 'test', 'info': 'test', 'args': [1],
'kwargs': {'a': 1}}
self.assertEquals(expect, manager.MapActionInfoToDict(actioninfo))
def testIsHealthcheckHealthy(self):
"""Test checking whether health check statuses are healthy."""
# Test a healthy health check.
hch = manager.HEALTHCHECK_STATUS('healthy', True, manager.NULL_DESCRIPTION,
manager.EMPTY_ACTIONS)
self.assertTrue(manager.isHealthcheckHealthy(hch))
# Test a quasi-healthy health check.
hcq = manager.HEALTHCHECK_STATUS('quasi-healthy', True, 'Quasi-Healthy',
['QuasiAction'])
self.assertFalse(manager.isHealthcheckHealthy(hcq))
# Test an unhealthy health check.
hcu = manager.HEALTHCHECK_STATUS('unhealthy', False, 'Unhealthy',
['UnhealthyAction'])
self.assertFalse(manager.isHealthcheckHealthy(hcu))
# Test an object that is not a health check status.
s = manager.SERVICE_STATUS('service_status', True, [])
self.assertFalse(manager.isHealthcheckHealthy(s))
def testIsServiceHealthy(self):
"""Test checking whether service statuses are healthy."""
# Define some health check statuses.
hch = manager.HEALTHCHECK_STATUS('healthy', True, manager.NULL_DESCRIPTION,
manager.EMPTY_ACTIONS)
hcq = manager.HEALTHCHECK_STATUS('quasi-healthy', True, 'Quasi-Healthy',
['QuasiAction'])
hcu = manager.HEALTHCHECK_STATUS('unhealthy', False, 'Unhealthy',
['UnhealthyAction'])
# Test a healthy service.
s = manager.SERVICE_STATUS('healthy', True, [])
self.assertTrue(manager.isServiceHealthy(s))
# Test a quasi-healthy service.
s = manager.SERVICE_STATUS('quasi-healthy', True, [hch, hcq])
self.assertFalse(manager.isServiceHealthy(s))
# Test an unhealthy service.
s = manager.SERVICE_STATUS('unhealthy', False, [hcu])
self.assertFalse(manager.isServiceHealthy(s))
# Test an object that is not a service status.
self.assertFalse(manager.isServiceHealthy(hch))
def testDetermineHealthcheckStatusHealthy(self):
"""Test DetermineHealthCheckStatus on a healthy check."""
hcname = TestHealthCheck.__name__
testhc = TestHealthCheck()
expected = manager.HEALTHCHECK_STATUS(hcname, True,
manager.NULL_DESCRIPTION,
manager.EMPTY_ACTIONS)
self.assertEquals(expected,
manager.DetermineHealthcheckStatus(hcname, testhc))
def testDeterminHealthcheckStatusUnhealthy(self):
"""Test DetermineHealthcheckStatus on an unhealthy check."""
hcname = TestHealthCheckUnhealthy.__name__
testhc = TestHealthCheckUnhealthy()
desc, actions = testhc.Diagnose(testhc.Check())
expected = manager.HEALTHCHECK_STATUS(hcname, False, desc, actions)
self.assertEquals(expected,
manager.DetermineHealthcheckStatus(hcname, testhc))
def testDetermineHealthcheckStatusQuasihealth(self):
"""Test DetermineHealthcheckStatus on a quasi-healthy check."""
hcname = TestHealthCheckQuasihealthy.__name__
testhc = TestHealthCheckQuasihealthy()
desc, actions = testhc.Diagnose(testhc.Check())
expected = manager.HEALTHCHECK_STATUS(hcname, True, desc, actions)
self.assertEquals(expected,
manager.DetermineHealthcheckStatus(hcname, testhc))
def testDetermineHealthcheckStatusBrokenCheck(self):
"""Test DetermineHealthcheckStatus raises on a broken health check."""
hcname = TestHealthCheckBroken.__name__
testhc = TestHealthCheckBroken()
result = manager.DetermineHealthcheckStatus(hcname, testhc)
self.assertEquals(hcname, result.name)
self.assertFalse(result.health)
self.assertFalse(result.actions)
def testIsHealthCheck(self):
"""Test that IsHealthCheck properly asserts the health check interface."""
class NoAttrs(object):
"""Test health check missing 'check' and 'diagnose' methods."""
class NoCheckAttr(object):
"""Test health check missing 'check' method."""
def Diagnose(self, errcode):
pass
class NoDiagnoseAttr(object):
"""Test health check missing 'diagnose' method."""
def Check(self):
pass
class GoodHealthCheck(object):
"""Test health check that implements 'check' and 'diagnose' methods."""
def Check(self):
pass
def Diagnose(self, errcode):
pass
self.assertFalse(manager.IsHealthCheck(NoAttrs()))
self.assertFalse(manager.IsHealthCheck(NoCheckAttr()))
self.assertFalse(manager.IsHealthCheck(NoDiagnoseAttr()))
self.assertTrue(manager.IsHealthCheck(GoodHealthCheck()))
def testApplyHealthCheckAttributesNoAttrs(self):
"""Test that we can apply attributes to a health check."""
testhc = TestHealthCheck()
result = manager.ApplyHealthCheckAttributes(testhc)
self.assertEquals(result.CHECK_INTERVAL_SEC,
manager.CHECK_INTERVAL_DEFAULT_SEC)
def testApplyHealthCheckAttributesHasAttrs(self):
"""Test that we do not override an acceptable attribute."""
testhc = TestHealthCheckHasAttributes()
check_interval = testhc.CHECK_INTERVAL_SEC
result = manager.ApplyHealthCheckAttributes(testhc)
self.assertEquals(result.CHECK_INTERVAL_SEC, check_interval)
def testImportFileAllHealthChecks(self):
"""Test that health checks and service name are collected."""
self.StartPatcher(mock.patch('os.path.splitext'))
os.path.splitext.return_value = '/path/to/test_check.py'
self.StartPatcher(mock.patch('os.path.getmtime'))
os.path.getmtime.return_value = TEST_MTIME
checkmodule = imp.new_module('test_check')
exec CHECKFILE_MANY_SIMPLE in checkmodule.__dict__
self.StartPatcher(mock.patch('imp.load_source'))
imp.load_source.return_value = checkmodule
healthchecks, mtime = manager.ImportFile(TEST_SERVICE_NAME, '/')
self.assertEquals(len(healthchecks), 3)
self.assertEquals(mtime, TEST_MTIME)
def testImportFileSomeHealthChecks(self):
"""Test importing when not all classes are actually health checks."""
self.StartPatcher(mock.patch('os.path.splitext'))
os.path.splitext.return_value = '/path/to/test_check.py'
self.StartPatcher(mock.patch('os.path.getmtime'))
os.path.getmtime.return_value = TEST_MTIME
checkmodule = imp.new_module('test_check')
exec CHECKFILE_MANY_SIMPLE_ONE_BAD in checkmodule.__dict__
self.StartPatcher(mock.patch('imp.load_source'))
imp.load_source.return_value = checkmodule
healthchecks, mtime = manager.ImportFile(TEST_SERVICE_NAME, '/')
self.assertEquals(len(healthchecks), 2)
self.assertEquals(mtime, TEST_MTIME)
class CheckFileManagerTest(cros_test_lib.MockTestCase):
"""Unittests for CheckFileManager."""
def testCollectionExecutionCallbackCheckfiles(self):
"""Test the CollectionExecutionCallback on collecting checkfiles."""
self.StartPatcher(mock.patch('os.walk'))
os.walk.return_value = iter([[CHECKDIR, [TEST_SERVICE_NAME], []]])
self.StartPatcher(mock.patch('os.listdir'))
os.listdir.return_value = ['test_check.py']
self.StartPatcher(mock.patch('os.path.isfile'))
os.path.isfile.return_value = True
self.StartPatcher(mock.patch('imp.find_module'))
imp.find_module.return_value = (None, None, None)
self.StartPatcher(mock.patch('imp.load_module'))
myobj = TestHealthCheck()
manager.ImportFile = mock.Mock(return_value=[[myobj], TEST_MTIME])
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
cfm.CollectionExecutionCallback()
manager.ImportFile.assert_called_once_with(
TEST_SERVICE_NAME, './%s/test_check.py' % TEST_SERVICE_NAME)
self.assertTrue(TEST_SERVICE_NAME in cfm.service_checks)
self.assertEquals(cfm.service_checks[TEST_SERVICE_NAME],
{myobj.__class__.__name__: (TEST_MTIME, myobj)})
def testCollectionExecutionCallbackNoChecks(self):
"""Test the CollectionExecutionCallback with no valid check files."""
self.StartPatcher(mock.patch('os.walk'))
os.walk.return_value = iter([['/checkdir/', [], ['test.py']]])
manager.ImportFile = mock.Mock(return_value=None)
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
cfm.CollectionExecutionCallback()
self.assertFalse(manager.ImportFile.called)
self.assertFalse(TEST_SERVICE_NAME in cfm.service_checks)
def testStartCollectionExecution(self):
"""Test the StartCollectionExecution method."""
plugins.Monitor = mock.Mock()
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
cfm.StartCollectionExecution()
self.assertTrue(plugins.Monitor.called)
def testUpdateExistingHealthCheck(self):
"""Test update when a health check exists and is not stale."""
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
myobj = TestHealthCheck()
cfm.service_checks[TEST_SERVICE_NAME] = {myobj.__class__.__name__:
(TEST_MTIME, myobj)}
myobj2 = TestHealthCheck()
cfm.Update(TEST_SERVICE_NAME, [myobj2], TEST_MTIME)
self.assertTrue(TEST_SERVICE_NAME in cfm.service_checks)
self.assertEquals(cfm.service_checks[TEST_SERVICE_NAME],
{myobj.__class__.__name__: (TEST_MTIME, myobj)})
def testUpdateNonExistingHealthCheck(self):
"""Test adding a new health check to the manager."""
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
cfm.service_checks = {}
myobj = TestHealthCheck()
cfm.Update(TEST_SERVICE_NAME, [myobj], TEST_MTIME)
self.assertTrue(TEST_SERVICE_NAME in cfm.service_checks)
self.assertEquals(cfm.service_checks[TEST_SERVICE_NAME],
{myobj.__class__.__name__: (TEST_MTIME, myobj)})
def testExecuteFresh(self):
"""Test executing a health check when the result is still fresh."""
self.StartPatcher(mock.patch('time.time'))
exec_time_offset = TestHealthCheckHasAttributes.CHECK_INTERVAL_SEC / 2
time.time.return_value = TEST_EXEC_TIME + exec_time_offset
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
cfm.service_checks = {TEST_SERVICE_NAME:
{TestHealthCheckHasAttributes.__name__:
(TEST_MTIME, TestHealthCheckHasAttributes())}}
cfm.service_check_results = {
TEST_SERVICE_NAME: {TestHealthCheckHasAttributes.__name__:
(manager.HCEXECUTION_COMPLETED, TEST_EXEC_TIME,
None)}}
cfm.Execute()
_, exec_time, _ = cfm.service_check_results[TEST_SERVICE_NAME][
TestHealthCheckHasAttributes.__name__]
self.assertEquals(exec_time, TEST_EXEC_TIME)
def testExecuteStale(self):
"""Test executing a health check when the result is stale."""
self.StartPatcher(mock.patch('time.time'))
exec_time_offset = TestHealthCheckHasAttributes.CHECK_INTERVAL_SEC * 2
time.time.return_value = TEST_EXEC_TIME + exec_time_offset
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
cfm.service_checks = {TEST_SERVICE_NAME:
{TestHealthCheckHasAttributes.__name__:
(TEST_MTIME, TestHealthCheckHasAttributes())}}
cfm.service_check_results = {
TEST_SERVICE_NAME: {TestHealthCheckHasAttributes.__name__:
(manager.HCEXECUTION_COMPLETED, TEST_EXEC_TIME,
None)}}
cfm.Execute()
_, exec_time, _ = cfm.service_check_results[TEST_SERVICE_NAME][
TestHealthCheckHasAttributes.__name__]
self.assertEquals(exec_time, TEST_EXEC_TIME + exec_time_offset)
def testExecuteNonExistent(self):
"""Test executing a health check when the result is nonexistent."""
self.StartPatcher(mock.patch('time.time'))
time.time.return_value = TEST_EXEC_TIME
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
cfm.service_checks = {TEST_SERVICE_NAME:
{TestHealthCheck.__name__:
(TEST_MTIME, TestHealthCheck())}}
cfm.Execute()
resultsdict = cfm.service_check_results.get(TEST_SERVICE_NAME)
self.assertTrue(resultsdict is not None)
exec_status, exec_time, _ = resultsdict.get(TestHealthCheck.__name__,
(None, None, None))
self.assertTrue(exec_status is not None)
self.assertTrue(exec_time is not None)
self.assertEquals(exec_status, manager.HCEXECUTION_COMPLETED)
self.assertEquals(exec_time, TEST_EXEC_TIME)
def testExecuteForce(self):
"""Test executing a health check by ignoring the check interval."""
self.StartPatcher(mock.patch('time.time'))
exec_time_offset = TestHealthCheckHasAttributes.CHECK_INTERVAL_SEC / 2
time.time.return_value = TEST_EXEC_TIME + exec_time_offset
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
cfm.service_checks = {TEST_SERVICE_NAME:
{TestHealthCheckHasAttributes.__name__:
(TEST_MTIME, TestHealthCheckHasAttributes())}}
cfm.service_check_results = {
TEST_SERVICE_NAME: {TestHealthCheckHasAttributes.__name__:
(manager.HCEXECUTION_COMPLETED, TEST_EXEC_TIME,
None)}}
cfm.Execute(force=True)
_, exec_time, _ = cfm.service_check_results[TEST_SERVICE_NAME][
TestHealthCheckHasAttributes.__name__]
self.assertEquals(exec_time, TEST_EXEC_TIME + exec_time_offset)
def testConsolidateServiceStatesUnhealthy(self):
"""Test consolidating state for a service with unhealthy checks."""
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
# Setup some test check results
hcname = TestHealthCheck.__name__
statuses = [
manager.HEALTHCHECK_STATUS(hcname, False, 'Failed', ['Repair']),
manager.HEALTHCHECK_STATUS(hcname, True, 'Quasi', ['RepairQuasi']),
manager.HEALTHCHECK_STATUS(hcname, True, '', [])]
cfm.service_check_results.setdefault(TEST_SERVICE_NAME, {})
for i, status in enumerate(statuses):
name = '%s_%s' % (hcname, i)
cfm.service_check_results[TEST_SERVICE_NAME][name] = (
manager.HCEXECUTION_COMPLETED, TEST_EXEC_TIME,
status)
# Run and check the results.
cfm.ConsolidateServiceStates()
self.assertTrue(TEST_SERVICE_NAME in cfm.service_states)
_, health, healthchecks = cfm.service_states[TEST_SERVICE_NAME]
self.assertFalse(health)
self.assertEquals(2, len(healthchecks))
self.assertTrue(all([x in healthchecks for x in statuses[:2]]))
def testConsolidateServiceStatesQuasiHealthy(self):
"""Test consolidating state for a service with quasi-healthy checks."""
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
# Setup some test check results
hcname = TestHealthCheck.__name__
statuses = [
manager.HEALTHCHECK_STATUS(hcname, True, 'Quasi', ['RepairQuasi']),
manager.HEALTHCHECK_STATUS(hcname, True, '', [])]
cfm.service_check_results.setdefault(TEST_SERVICE_NAME, {})
for i, status in enumerate(statuses):
name = '%s_%s' % (hcname, i)
cfm.service_check_results[TEST_SERVICE_NAME][name] = (
manager.HCEXECUTION_COMPLETED, TEST_EXEC_TIME,
status)
# Run and check the results.
cfm.ConsolidateServiceStates()
self.assertTrue(TEST_SERVICE_NAME in cfm.service_states)
_, health, healthchecks = cfm.service_states[TEST_SERVICE_NAME]
self.assertTrue(health)
self.assertEquals(1, len(healthchecks))
self.assertTrue(statuses[0] in healthchecks)
def testConsolidateServiceStatesHealthy(self):
"""Test consolidating state for a healthy service."""
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
# Setup some test check results
hcname = TestHealthCheck.__name__
hcname2 = '%s_2' % hcname
statuses = [
manager.HEALTHCHECK_STATUS(hcname, True, '', []),
manager.HEALTHCHECK_STATUS(hcname2, True, '', [])]
cfm.service_check_results.setdefault(TEST_SERVICE_NAME, {})
cfm.service_check_results[TEST_SERVICE_NAME][hcname] = (
manager.HCEXECUTION_COMPLETED, TEST_EXEC_TIME, statuses[0])
cfm.service_check_results[TEST_SERVICE_NAME][hcname2] = (
manager.HCEXECUTION_IN_PROGRESS, TEST_EXEC_TIME, statuses[1])
# Run and check.
cfm.ConsolidateServiceStates()
self.assertTrue(TEST_SERVICE_NAME in cfm.service_states)
_, health, healthchecks = cfm.service_states.get(TEST_SERVICE_NAME)
self.assertTrue(health)
self.assertEquals(0, len(healthchecks))
def testGetServiceList(self):
"""Test the GetServiceList RPC response."""
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
self.assertEquals([], cfm.GetServiceList())
status = manager.SERVICE_STATUS(TEST_SERVICE_NAME, True, [])
cfm.service_states[TEST_SERVICE_NAME] = status
self.assertEquals([TEST_SERVICE_NAME], cfm.GetServiceList())
def testGetStatusNonExistent(self):
"""Test the GetStatus RPC response when the service does not exist."""
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
self.assertFalse(TEST_SERVICE_NAME in cfm.service_states)
status = manager.SERVICE_STATUS(TEST_SERVICE_NAME, False, [])
self.assertEquals(status, cfm.GetStatus(TEST_SERVICE_NAME))
def testGetStatusSingleService(self):
"""Test the GetStatus RPC response for a single service."""
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
s1name = TEST_SERVICE_NAME
s2name = '%s_2' % s1name
status1 = manager.SERVICE_STATUS(s1name, True, [])
status2 = manager.SERVICE_STATUS(s2name, True, [])
cfm.service_states[s1name] = status1
cfm.service_states[s2name] = status2
self.assertEquals(status1, cfm.GetStatus(s1name))
self.assertEquals(status2, cfm.GetStatus(s2name))
def testGetStatusAllServices(self):
"""Test the GetStatus RPC response when no service is specified."""
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
s1name = TEST_SERVICE_NAME
s2name = '%s_2' % s1name
status1 = manager.SERVICE_STATUS(s1name, True, [])
status2 = manager.SERVICE_STATUS(s2name, True, [])
cfm.service_states[s1name] = status1
cfm.service_states[s2name] = status2
result = cfm.GetStatus('')
self.assertEquals(2, len(result))
self.assertTrue(all([x in result for x in [status1, status2]]))
def testRepairServiceHealthy(self):
"""Test the RepairService RPC when the service is healthy."""
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
healthy_status = manager.SERVICE_STATUS(TEST_SERVICE_NAME, True, [])
cfm.service_states[TEST_SERVICE_NAME] = healthy_status
self.assertEquals(healthy_status, cfm.RepairService(TEST_SERVICE_NAME,
'HealthcheckName',
'RepairFuncName',
[], {}))
def testRepairServiceNonExistent(self):
"""Test the RepairService RPC when the service does not exist."""
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
self.assertFalse(TEST_SERVICE_NAME in cfm.service_states)
expected = manager.SERVICE_STATUS(TEST_SERVICE_NAME, False, [])
result = cfm.RepairService(TEST_SERVICE_NAME, 'DummyHealthcheck',
'DummyAction', [], {})
self.assertEquals(expected, result)
def testRepairServiceInvalidAction(self):
"""Test the RepairService RPC when the action is not recognized."""
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
hcobj = TestHealthCheckUnhealthy()
cfm.service_checks[TEST_SERVICE_NAME] = {
hcobj.__class__.__name__: (TEST_MTIME, hcobj)}
unhealthy_status = manager.SERVICE_STATUS(
TEST_SERVICE_NAME, False,
[manager.HEALTHCHECK_STATUS(hcobj.__class__.__name__,
False, 'Always fails', [hcobj.Repair])])
cfm.service_states[TEST_SERVICE_NAME] = unhealthy_status
status = cfm.GetStatus(TEST_SERVICE_NAME)
self.assertFalse(status.health)
self.assertEquals(1, len(status.healthchecks))
status = cfm.RepairService(TEST_SERVICE_NAME, hcobj.__class__.__name__,
'Blah', [], {})
self.assertFalse(status.health)
self.assertEquals(1, len(status.healthchecks))
def testRepairServiceInvalidActionArguments(self):
"""Test the RepairService RPC when the action arguments are invalid."""
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
hcobj = TestHealthCheckUnhealthy()
cfm.service_checks[TEST_SERVICE_NAME] = {
hcobj.__class__.__name__: (TEST_MTIME, hcobj)}
unhealthy_status = manager.SERVICE_STATUS(
TEST_SERVICE_NAME, False,
[manager.HEALTHCHECK_STATUS(hcobj.__class__.__name__,
False, 'Always fails', [hcobj.Repair])])
cfm.service_states[TEST_SERVICE_NAME] = unhealthy_status
status = cfm.GetStatus(TEST_SERVICE_NAME)
self.assertFalse(status.health)
self.assertEquals(1, len(status.healthchecks))
status = cfm.RepairService(TEST_SERVICE_NAME, hcobj.__class__.__name__,
'Repair', [1, 2, 3], {})
self.assertFalse(status.health)
self.assertEquals(1, len(status.healthchecks))
def testRepairService(self):
"""Test the RepairService RPC to repair an unhealthy service."""
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
hcobj = TestHealthCheckUnhealthy()
cfm.service_checks[TEST_SERVICE_NAME] = {
hcobj.__class__.__name__: (TEST_MTIME, hcobj)}
unhealthy_status = manager.SERVICE_STATUS(
TEST_SERVICE_NAME, False,
[manager.HEALTHCHECK_STATUS(hcobj.__class__.__name__,
False, 'Always fails', [hcobj.Repair])])
cfm.service_states[TEST_SERVICE_NAME] = unhealthy_status
status = cfm.GetStatus(TEST_SERVICE_NAME)
self.assertFalse(status.health)
self.assertEquals(1, len(status.healthchecks))
status = cfm.RepairService(TEST_SERVICE_NAME,
hcobj.__class__.__name__,
hcobj.Repair.__name__,
[], {})
self.assertTrue(status.health)
self.assertEquals(0, len(status.healthchecks))
def testActionInfoServiceNonExistent(self):
"""Test the ActionInfo RPC when the service does not exist."""
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
self.assertFalse(TEST_SERVICE_NAME in cfm.service_states)
expect = manager.ACTION_INFO('test', 'Service not recognized.',
[], {})
result = cfm.ActionInfo(TEST_SERVICE_NAME, 'test', 'test')
self.assertEquals(expect, result)
def testActionInfoServiceHealthy(self):
"""Test the ActionInfo RPC when the service is healthy."""
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
healthy_status = manager.SERVICE_STATUS(TEST_SERVICE_NAME, True, [])
cfm.service_states[TEST_SERVICE_NAME] = healthy_status
expect = manager.ACTION_INFO('test', 'Service is healthy.',
[], {})
result = cfm.ActionInfo(TEST_SERVICE_NAME, 'test', 'test')
self.assertEquals(expect, result)
def testActionInfoActionNonExistent(self):
"""Test the ActionInfo RPC when the action does not exist."""
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
hcobj = TestHealthCheckUnhealthy()
cfm.service_checks[TEST_SERVICE_NAME] = {
hcobj.__class__.__name__: (TEST_MTIME, hcobj)}
unhealthy_status = manager.SERVICE_STATUS(
TEST_SERVICE_NAME, False,
[manager.HEALTHCHECK_STATUS(hcobj.__class__.__name__,
False, 'Always fails', [hcobj.Repair])])
cfm.service_states[TEST_SERVICE_NAME] = unhealthy_status
expect = manager.ACTION_INFO('test', 'Action not recognized.', [], {})
result = cfm.ActionInfo(TEST_SERVICE_NAME, hcobj.__class__.__name__,
'test')
self.assertEquals(expect, result)
def testActionInfo(self):
"""Test the ActionInfo RPC to collect information on a repair action."""
cfm = manager.CheckFileManager(checkdir=CHECKDIR)
hcobj = TestHealthCheckMultipleActions()
hcname = hcobj.__class__.__name__
actions = [hcobj.NoParams, hcobj.PositionalParams, hcobj.DefaultParams,
hcobj.MixedParams]
cfm.service_checks[TEST_SERVICE_NAME] = {hcname: (TEST_MTIME, hcobj)}
unhealthy_status = manager.SERVICE_STATUS(
TEST_SERVICE_NAME, False,
[manager.HEALTHCHECK_STATUS(hcname, False, 'Always fails', actions)])
cfm.service_states[TEST_SERVICE_NAME] = unhealthy_status
# Test ActionInfo when the action has no parameters.
expect = manager.ACTION_INFO('NoParams', 'NoParams Action.', [], {})
self.assertEquals(expect,
cfm.ActionInfo(TEST_SERVICE_NAME, hcname, 'NoParams'))
# Test ActionInfo when the action has only positional parameters.
expect = manager.ACTION_INFO('PositionalParams', 'PositionalParams Action.',
['x', 'y', 'z'], {})
self.assertEquals(expect,
cfm.ActionInfo(TEST_SERVICE_NAME,
hcname, 'PositionalParams'))
# Test ActionInfo when the action has only default parameters.
expect = manager.ACTION_INFO('DefaultParams', 'DefaultParams Action.',
[], {'x': 1, 'y': 2, 'z': 3})
self.assertEquals(expect,
cfm.ActionInfo(TEST_SERVICE_NAME,
hcname, 'DefaultParams'))
# Test ActionInfo when the action has positional and default parameters.
expect = manager.ACTION_INFO('MixedParams', 'MixedParams Action.',
['x', 'y'], {'z': 1})
self.assertEquals(expect, cfm.ActionInfo(TEST_SERVICE_NAME,
hcname, 'MixedParams'))