summaryrefslogtreecommitdiff
path: root/mobmonitor
diff options
context:
space:
mode:
authorMatthew Sartori <msartori@google.com>2015-09-11 18:16:05 -0700
committerchrome-bot <chrome-bot@chromium.org>2015-09-14 17:10:20 -0700
commit00bee1914d326717386842e19b22ea7ba45266d2 (patch)
treec530b78a77abbf27d8da34d4a9dc3027cbd93677 /mobmonitor
parent6367f86371a3819ba8312355e7113d0467b85df4 (diff)
downloadchromite-00bee1914d326717386842e19b22ea7ba45266d2.tar.gz
mobmonitor: Fixes for the Mob* Monitor.
The Mob* Monitor assumed that repair actions were unique up to the service that they repaired. Recent work on the UI and checkfiles have introduced changes that make actions unique up to a healthcheck instead of up to a service. This CL updates the ActionInfo and RepairService RPCs to take a healthcheck name as a parameter. This does not introduce any useability changes for users of the web UI. From the perspective of the monitor, actions now repair a particular failed healthcheck of a service, rather than a service that has a failed healthcheck. BUG=None TEST=Unittests and tested on moblab. Change-Id: I47372c3c1b5181bd395402d6501b17bea633ffa1 Reviewed-on: https://chromium-review.googlesource.com/299540 Commit-Ready: Matthew Sartori <msartori@chromium.org> Tested-by: Matthew Sartori <msartori@chromium.org> Reviewed-by: Simran Basi <sbasi@chromium.org>
Diffstat (limited to 'mobmonitor')
-rw-r--r--mobmonitor/checkfile/manager.py48
-rw-r--r--mobmonitor/checkfile/manager_unittest.py40
-rw-r--r--mobmonitor/rpc/rpc.py35
-rwxr-xr-xmobmonitor/scripts/mobmoncli.py15
-rw-r--r--mobmonitor/scripts/mobmoncli_unittest.py11
-rwxr-xr-xmobmonitor/scripts/mobmonitor.py11
-rw-r--r--mobmonitor/scripts/mobmonitor_unittest.py9
-rw-r--r--mobmonitor/static/css/style.css3
-rw-r--r--mobmonitor/static/js/main.js9
-rw-r--r--mobmonitor/static/js/rpc.js11
-rw-r--r--mobmonitor/static/templates/healthstatuscontainer.html4
11 files changed, 122 insertions, 74 deletions
diff --git a/mobmonitor/checkfile/manager.py b/mobmonitor/checkfile/manager.py
index c0a305b69..3b09cf846 100644
--- a/mobmonitor/checkfile/manager.py
+++ b/mobmonitor/checkfile/manager.py
@@ -387,16 +387,19 @@ class CheckFileManager(object):
return self.service_states.get(service, SERVICE_STATUS(service, False, []))
- def ActionInfo(self, service, action):
+ def ActionInfo(self, service, healthcheck, action):
"""Describes a currently valid action for the given service and healthcheck.
An action is valid if the following hold:
The |service| is recognized and is in an unhealthy or quasi-healthy state.
+ The |healthcheck| is recognized and is in an unhealthy or quasi-healthy
+ state and it belongs to |service|.
The |action| is one specified as a suitable repair action by the
Diagnose method of some non-healthy healthcheck of |service|.
Args:
service: A string. The name of a service being monitored.
+ healthcheck: A string. The name of a healthcheck belonging to |service|.
action: A string. The name of an action returned by some healthcheck's
Diagnose method.
@@ -415,18 +418,20 @@ class CheckFileManager(object):
elif isServiceHealthy(status):
return ACTION_INFO(action, 'Service is healthy.', [], {})
- def FindAction():
- for hc in status.healthchecks:
- if isHealthcheckHealthy(hc):
- continue
- for a in hc.actions:
- if a.__name__ == action:
- return a
- return None
+ hc = [x for x in status.healthchecks if x.name == healthcheck]
+ if not hc:
+ return ACTION_INFO(action, 'Healthcheck not recognized.', [], {})
+ hc = hc[0]
+ if isHealthcheckHealthy(hc):
+ return ACTION_INFO(action, 'Healthcheck is healthy.', [], {})
- func = FindAction()
+ func = None
+ for a in hc.actions:
+ if a.__name__ == action:
+ func = a
+ break
- if not func:
+ if func is None:
return ACTION_INFO(action, 'Action not recognized.', [], {})
# Collect information on the repair action.
@@ -445,11 +450,12 @@ class CheckFileManager(object):
return ACTION_INFO(action, info, args, kwargs)
- def RepairService(self, service, action, args, kwargs):
+ def RepairService(self, service, healthcheck, action, args, kwargs):
"""Execute the repair action on the specified service.
Args:
service: The name of the service to be repaired.
+ healthcheck: The particular healthcheck we are repairing.
action: The name of the action to execute.
args: A list of positional arguments for the given repair action.
kwargs: A dictionary of keyword arguments for the given repair action.
@@ -464,14 +470,18 @@ class CheckFileManager(object):
elif isServiceHealthy(status):
return self.GetStatus(service)
- # Check that at least one unhealthy/quasi-healthy check specifies this
- # repair action. Actions are assumed to be service-centric at this point.
+ # No repair occurs if the healthcheck is not specifed or perfectly healthy.
+ hc = [x for x in status.healthchecks if x.name == healthcheck]
+ if not hc or isHealthcheckHealthy(hc[0]):
+ return SERVICE_STATUS(healthcheck, False, [])
+ hc = hc[0]
+
+ # Get the repair action from the healthcheck.
repair_func = None
- for hc in status.healthchecks:
- for action_func in hc.actions:
- if action == action_func.__name__:
- repair_func = action_func
- break
+ for a in hc.actions:
+ if a.__name__ == action:
+ repair_func = a
+ break
# TODO (msartori): Implement crbug.com/503373
if repair_func is not None:
diff --git a/mobmonitor/checkfile/manager_unittest.py b/mobmonitor/checkfile/manager_unittest.py
index aa71bbead..d666bb9d6 100644
--- a/mobmonitor/checkfile/manager_unittest.py
+++ b/mobmonitor/checkfile/manager_unittest.py
@@ -741,6 +741,7 @@ class CheckFileManagerTest(cros_test_lib.MockTestCase):
cfm.service_states[TEST_SERVICE_NAME] = healthy_status
self.assertEquals(healthy_status, cfm.RepairService(TEST_SERVICE_NAME,
+ 'HealthcheckName',
'RepairFuncName',
[], {}))
@@ -751,7 +752,8 @@ class CheckFileManagerTest(cros_test_lib.MockTestCase):
self.assertFalse(TEST_SERVICE_NAME in cfm.service_states)
expected = manager.SERVICE_STATUS(TEST_SERVICE_NAME, False, [])
- result = cfm.RepairService(TEST_SERVICE_NAME, 'DummyAction', [], {})
+ result = cfm.RepairService(TEST_SERVICE_NAME, 'DummyHealthcheck',
+ 'DummyAction', [], {})
self.assertEquals(expected, result)
def testRepairServiceInvalidAction(self):
@@ -772,7 +774,8 @@ class CheckFileManagerTest(cros_test_lib.MockTestCase):
self.assertFalse(status.health)
self.assertEquals(1, len(status.healthchecks))
- status = cfm.RepairService(TEST_SERVICE_NAME, 'Blah', [], {})
+ status = cfm.RepairService(TEST_SERVICE_NAME, hcobj.__class__.__name__,
+ 'Blah', [], {})
self.assertFalse(status.health)
self.assertEquals(1, len(status.healthchecks))
@@ -794,7 +797,8 @@ class CheckFileManagerTest(cros_test_lib.MockTestCase):
self.assertFalse(status.health)
self.assertEquals(1, len(status.healthchecks))
- status = cfm.RepairService(TEST_SERVICE_NAME, 'Repair', [1, 2, 3], {})
+ status = cfm.RepairService(TEST_SERVICE_NAME, hcobj.__class__.__name__,
+ 'Repair', [1, 2, 3], {})
self.assertFalse(status.health)
self.assertEquals(1, len(status.healthchecks))
@@ -816,7 +820,9 @@ class CheckFileManagerTest(cros_test_lib.MockTestCase):
self.assertFalse(status.health)
self.assertEquals(1, len(status.healthchecks))
- status = cfm.RepairService(TEST_SERVICE_NAME, hcobj.Repair.__name__,
+ status = cfm.RepairService(TEST_SERVICE_NAME,
+ hcobj.__class__.__name__,
+ hcobj.Repair.__name__,
[], {})
self.assertTrue(status.health)
self.assertEquals(0, len(status.healthchecks))
@@ -829,7 +835,7 @@ class CheckFileManagerTest(cros_test_lib.MockTestCase):
expect = manager.ACTION_INFO('test', 'Service not recognized.',
[], {})
- result = cfm.ActionInfo(TEST_SERVICE_NAME, 'test')
+ result = cfm.ActionInfo(TEST_SERVICE_NAME, 'test', 'test')
self.assertEquals(expect, result)
def testActionInfoServiceHealthy(self):
@@ -841,7 +847,7 @@ class CheckFileManagerTest(cros_test_lib.MockTestCase):
expect = manager.ACTION_INFO('test', 'Service is healthy.',
[], {})
- result = cfm.ActionInfo(TEST_SERVICE_NAME, 'test')
+ result = cfm.ActionInfo(TEST_SERVICE_NAME, 'test', 'test')
self.assertEquals(expect, result)
def testActionInfoActionNonExistent(self):
@@ -859,7 +865,8 @@ class CheckFileManagerTest(cros_test_lib.MockTestCase):
cfm.service_states[TEST_SERVICE_NAME] = unhealthy_status
expect = manager.ACTION_INFO('test', 'Action not recognized.', [], {})
- result = cfm.ActionInfo(TEST_SERVICE_NAME, 'test')
+ result = cfm.ActionInfo(TEST_SERVICE_NAME, hcobj.__class__.__name__,
+ 'test')
self.assertEquals(expect, result)
def testActionInfo(self):
@@ -867,38 +874,41 @@ class CheckFileManagerTest(cros_test_lib.MockTestCase):
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] = {
- hcobj.__class__.__name__: (TEST_MTIME, hcobj)}
+ cfm.service_checks[TEST_SERVICE_NAME] = {hcname: (TEST_MTIME, hcobj)}
unhealthy_status = manager.SERVICE_STATUS(
TEST_SERVICE_NAME, False,
- [manager.HEALTHCHECK_STATUS(hcobj.__class__.__name__,
- False, 'Always fails', actions)])
+ [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, 'NoParams'))
+ 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, 'PositionalParams'))
+ 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, 'DefaultParams'))
+ 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, 'MixedParams'))
+ self.assertEquals(expect, cfm.ActionInfo(TEST_SERVICE_NAME,
+ hcname, 'MixedParams'))
@cros_test_lib.NetworkTest()
diff --git a/mobmonitor/rpc/rpc.py b/mobmonitor/rpc/rpc.py
index 1b9140fcb..4d1b9d90f 100644
--- a/mobmonitor/rpc/rpc.py
+++ b/mobmonitor/rpc/rpc.py
@@ -105,7 +105,7 @@ class RpcExecutor(object):
return self.Execute('GetStatus', service=service)
- def ActionInfo(self, service=None, action=None):
+ def ActionInfo(self, service=None, healthcheck=None, action=None):
"""Collect argument and usage information for |action|.
See checkfile.manager.ActionInfo for more documentation on the
@@ -113,7 +113,8 @@ class RpcExecutor(object):
Args:
service: A string. The name of a service being monitored.
- action: A string. The name of an action returned by some healthcheck's
+ healthcheck: A string. The name of a healthcheck belonging to |service|.
+ action: A string. The name of an action returned by |healthcheck|'s
Diagnose method.
Returns:
@@ -123,18 +124,22 @@ class RpcExecutor(object):
args: A list of the positional arguments for |action|.
kwargs: A dictionary of default arguments for |action|.
"""
- if service is None or action is None:
- raise RpcError('ActionInfo requires both the service'
- ' and action to be provided.'
- ' Given: service=%s action=%s' % (service, action))
+ if any([x is None for x in [service, healthcheck, action]]):
+ raise RpcError('ActionInfo requires the service, the healthcheck'
+ ' and the action to be provided.'
+ ' Given: service=%s healthcheck=%s action=%s' % (
+ service, healthcheck, action))
- return self.Execute('ActionInfo', service=service, action=action)
+ return self.Execute('ActionInfo', service=service, healthcheck=healthcheck,
+ action=action)
- def RepairService(self, service=None, action=None, args=None, kwargs=None):
+ def RepairService(self, service=None, healthcheck=None, action=None,
+ args=None, kwargs=None):
"""Apply the specified action to the specified service.
Args:
service: A string. The service to repair.
+ healthcheck: A string. The healthcheck of |service| that we are fixing.
action: A string. The action to take.
args: The positional argument inputs to the repair action.
kwargs: The keyword argument inputs to the repair action.
@@ -142,13 +147,15 @@ class RpcExecutor(object):
Returns:
The same output of running get_status(service=service).
"""
- if service is None or action is None:
- raise RpcError('repair_service requires both the service'
- ' and action to be provided.'
- ' Given: service="%s" action="%s"' % (service, action))
+ if any([x is None for x in [service, healthcheck, action]]):
+ raise RpcError('RepairService requires the service, the healthcheck'
+ ' and the action to be provided.'
+ ' Given: service=%s healthcheck=%s action=%s' % (
+ service, healthcheck, action))
args = [] if args is None else args
kwargs = {} if kwargs is None else kwargs
- return self.Execute('RepairService', service=service, action=action,
- args=args, kwargs=kwargs)
+ return self.Execute('RepairService', service=service,
+ healthcheck=healthcheck, action=action, args=args,
+ kwargs=kwargs)
diff --git a/mobmonitor/scripts/mobmoncli.py b/mobmonitor/scripts/mobmoncli.py
index f69871984..45c42663a 100755
--- a/mobmonitor/scripts/mobmoncli.py
+++ b/mobmonitor/scripts/mobmoncli.py
@@ -56,12 +56,13 @@ class MobMonCli(object):
self.host = host
self.port = remote_access.NormalizePort(port)
- def ExecuteRequest(self, request, service, action, inputs):
+ def ExecuteRequest(self, request, service, healthcheck, action, inputs):
"""Execute the request if an appropriate RPC function is defined.
Args:
request: The name of the RPC.
service: The name of the service involved in the RPC.
+ healthcheck: The name of the healthcheck involved in the RPC.
action: The action to be performed.
inputs: A string. The inputs of the specified repair action.
"""
@@ -79,17 +80,20 @@ class MobMonCli(object):
return rpcexec.GetStatus(service=service)
if 'ActionInfo' == request:
- return rpcexec.ActionInfo(service=service, action=action)
+ return rpcexec.ActionInfo(service=service, healthcheck=healthcheck,
+ action=action)
if 'RepairService' == request:
- return rpcexec.RepairService(service=service, action=action, args=args,
- kwargs=kwargs)
+ return rpcexec.RepairService(service=service, healthcheck=healthcheck,
+ action=action, args=args, kwargs=kwargs)
def ParseArguments(argv):
parser = commandline.ArgumentParser()
parser.add_argument('request', choices=rpc.RPC_LIST)
parser.add_argument('-s', '--service', help='The service to act upon.')
+ parser.add_argument('-c', '--healthcheck',
+ help='The healthcheck to act upon.')
parser.add_argument('-a', '--action', help='The action to execute.')
parser.add_argument('--host', default='localhost',
help='The hostname of the Mob* Monitor.')
@@ -115,7 +119,8 @@ def main(argv):
cli = MobMonCli(options.host, options.port)
result = cli.ExecuteRequest(options.request, options.service,
- options.action, options.inputs)
+ options.healthcheck, options.action,
+ options.inputs)
print(result)
diff --git a/mobmonitor/scripts/mobmoncli_unittest.py b/mobmonitor/scripts/mobmoncli_unittest.py
index cd4ad3699..5e3857790 100644
--- a/mobmonitor/scripts/mobmoncli_unittest.py
+++ b/mobmonitor/scripts/mobmoncli_unittest.py
@@ -46,14 +46,14 @@ class MobMonCliTest(cros_test_lib.MockTestCase):
def testBadRequest(self):
"""Test that we error when an unrecognized request is passed."""
with self.assertRaises(rpc.RpcError):
- self.cli.ExecuteRequest('InvalidRequest', 'TestService', '', '')
+ self.cli.ExecuteRequest('InvalidRequest', 'TestService', '', '', '')
def testGetServiceList(self):
"""Test that we correctly execute a GetServiceList RPC."""
with mock.patch('chromite.mobmonitor.rpc.rpc.RpcExecutor') as rpc_executor:
mock_executor = mock.MagicMock()
rpc_executor.return_value = mock_executor
- self.cli.ExecuteRequest('GetServiceList', 'TestService', '', '')
+ self.cli.ExecuteRequest('GetServiceList', 'TestService', '', '', '')
self.assertTrue(mock_executor.GetServiceList.called)
def testGetStatus(self):
@@ -61,7 +61,7 @@ class MobMonCliTest(cros_test_lib.MockTestCase):
with mock.patch('chromite.mobmonitor.rpc.rpc.RpcExecutor') as rpc_executor:
mock_executor = mock.MagicMock()
rpc_executor.return_value = mock_executor
- self.cli.ExecuteRequest('GetStatus', 'TestService', '', '')
+ self.cli.ExecuteRequest('GetStatus', 'TestService', '', '', '')
self.assertTrue(mock_executor.GetStatus.called)
def testActionInfo(self):
@@ -69,7 +69,8 @@ class MobMonCliTest(cros_test_lib.MockTestCase):
with mock.patch('chromite.mobmonitor.rpc.rpc.RpcExecutor') as rpc_executor:
mock_executor = mock.MagicMock()
rpc_executor.return_value = mock_executor
- self.cli.ExecuteRequest('ActionInfo', 'TestService', 'action', '')
+ self.cli.ExecuteRequest('ActionInfo', 'TestService',
+ 'healthcheck', 'action', '')
self.assertTrue(mock_executor.ActionInfo.called)
def testRepairService(self):
@@ -77,5 +78,5 @@ class MobMonCliTest(cros_test_lib.MockTestCase):
with mock.patch('chromite.mobmonitor.rpc.rpc.RpcExecutor') as rpc_executor:
mock_executor = mock.MagicMock()
rpc_executor.return_value = mock_executor
- self.cli.ExecuteRequest('RepairService', 'TestService', '', '')
+ self.cli.ExecuteRequest('RepairService', 'TestService', '', '', '')
self.assertTrue(mock_executor.RepairService.called)
diff --git a/mobmonitor/scripts/mobmonitor.py b/mobmonitor/scripts/mobmonitor.py
index 64ba0f27f..2bc70b874 100755
--- a/mobmonitor/scripts/mobmonitor.py
+++ b/mobmonitor/scripts/mobmonitor.py
@@ -75,26 +75,28 @@ class MobMonitorRoot(object):
return json.dumps(result)
@cherrypy.expose
- def ActionInfo(self, service, action):
+ def ActionInfo(self, service, healthcheck, action):
"""Return usage and argument information for |action|.
Args:
service: A string. The name of a service being monitored.
+ healthcheck: A string. The name of the healthcheck the action belongs to.
action: A string. The name of an action specified by some healthcheck's
Diagnose method.
Returns:
TBD
"""
- result = self.checkfile_manager.ActionInfo(service, action)
+ result = self.checkfile_manager.ActionInfo(service, healthcheck, action)
return json.dumps(manager.MapActionInfoToDict(result))
@cherrypy.expose
- def RepairService(self, service, action, args, kwargs):
+ def RepairService(self, service, healthcheck, action, args, kwargs):
"""Execute the repair action on the specified service.
Args:
service: The service that the specified action will be applied to.
+ healthcheck: The particular healthcheck we are repairing.
action: The action to be applied.
args: A list of the positional arguments for the given repair action.
kwargs: A dictionary of keyword arguments for the given repair action.
@@ -105,7 +107,8 @@ class MobMonitorRoot(object):
args = json.loads(args.replace('\'', '"'))
kwargs = json.loads(kwargs.replace('\'', '"'))
- status = self.checkfile_manager.RepairService(service, action, args, kwargs)
+ status = self.checkfile_manager.RepairService(service, healthcheck, action,
+ args, kwargs)
return json.dumps(manager.MapServiceStatusToDict(status))
diff --git a/mobmonitor/scripts/mobmonitor_unittest.py b/mobmonitor/scripts/mobmonitor_unittest.py
index 731f63da7..6fc35b180 100644
--- a/mobmonitor/scripts/mobmonitor_unittest.py
+++ b/mobmonitor/scripts/mobmonitor_unittest.py
@@ -38,11 +38,11 @@ class MockCheckFileManager(object):
return self.service_statuses[0]
- def ActionInfo(self, _service, _action):
+ def ActionInfo(self, _service, _healthcheck, _action):
"""Mock ActionInfo response."""
return self.action_info
- def RepairService(self, _service, _action, _args, _kwargs):
+ def RepairService(self, _service, _healthcheck, _action, _args, _kwargs):
"""Mock RepairService response."""
return self.service_statuses[0]
@@ -93,7 +93,9 @@ class MobMonitorRootTest(cros_test_lib.MockTempDirTestCase):
expect = {'action': 'DummyAction', 'info': '', 'args': ['x'], 'kwargs': {}}
self.assertEquals(expect,
- json.loads(root.ActionInfo('service2', 'DummyAction')))
+ json.loads(root.ActionInfo('service2',
+ 'dummy_healthcheck',
+ 'DummyAction')))
def testRepairService(self):
"""Test the RepairService RPC."""
@@ -107,6 +109,7 @@ class MobMonitorRootTest(cros_test_lib.MockTempDirTestCase):
string_kwargs = '{"a": 1}'
self.assertEquals(expect,
json.loads(root.RepairService('dummy_service',
+ 'dummy_healthcheck',
'dummy_action',
string_args,
string_kwargs)))
diff --git a/mobmonitor/static/css/style.css b/mobmonitor/static/css/style.css
index 18becf5ed..1df111899 100644
--- a/mobmonitor/static/css/style.css
+++ b/mobmonitor/static/css/style.css
@@ -114,8 +114,7 @@ td {
width: 35%;
}
-.healthcheck {
- background-color: grey;
+.healthcheck-info {
}
.run-repair-action {
diff --git a/mobmonitor/static/js/main.js b/mobmonitor/static/js/main.js
index 40ba4e6aa..ec1fad689 100644
--- a/mobmonitor/static/js/main.js
+++ b/mobmonitor/static/js/main.js
@@ -26,6 +26,7 @@ $(document).ready(function() {
$(document).on('click', '.run-repair-action', function() {
// Retrieve the service and action for this repair button.
var action = $(this).attr('action');
+ var healthcheck = $(this).closest('.healthcheck-info').attr('hcname');
var service = $(this).closest('.health-container').attr('id');
if (service.indexOf(SERVICE_CONTAINER_PREFIX) === 0) {
service = service.replace(SERVICE_CONTAINER_PREFIX, '');
@@ -40,15 +41,17 @@ $(document).ready(function() {
$('#healthStatusDisplay').healthDisplay('markStale', response.service);
}
- rpcActionInfo(service, action, function(response) {
+ rpcActionInfo(service, healthcheck, action, function(response) {
if (isEmpty(response.args) && isEmpty(response.kwargs)) {
- rpcRepairService(service, action, [], {}, repairServiceCallback);
+ rpcRepairService(service, healthcheck, action,
+ [], {}, repairServiceCallback);
return;
}
var dialog = new ActionRepairDialog(service, response);
dialog.submitHandler = function(service, action, args, kwargs) {
- rpcRepairService(service, action, args, kwargs, repairServiceCallback);
+ rpcRepairService(service, healthcheck, action,
+ args, kwargs, repairServiceCallback);
};
dialog.open();
});
diff --git a/mobmonitor/static/js/rpc.js b/mobmonitor/static/js/rpc.js
index 1556c6e49..7b27e606e 100644
--- a/mobmonitor/static/js/rpc.js
+++ b/mobmonitor/static/js/rpc.js
@@ -13,27 +13,34 @@ function rpcGetStatus(service, callback) {
$.getJSON('/GetStatus', {service: service}, callback);
}
-function rpcActionInfo(service, action, callback) {
+function rpcActionInfo(service, healthcheck, action, callback) {
var data = {
service: service,
+ healthcheck: healthcheck,
action: action
};
$.getJSON('/ActionInfo', data, callback);
}
-function rpcRepairService(service, action, args, kwargs, callback) {
+function rpcRepairService(service, healthcheck, action,
+ args, kwargs, callback) {
if (isEmpty(service))
throw new InvalidRpcArgumentError(
'Must specify service in RepairService RPC');
+ if (isEmpty(healthcheck))
+ throw new InvalidRpcArgumentError(
+ 'Must specify healthcheck in RepairService RPC');
+
if (isEmpty(action))
throw new InvalidRpcArgumentError(
'Must specify action in RepairService RPC');
var data = {
service: service,
+ healthcheck: healthcheck,
action: action,
args: JSON.stringify(args),
kwargs: JSON.stringify(kwargs)
diff --git a/mobmonitor/static/templates/healthstatuscontainer.html b/mobmonitor/static/templates/healthstatuscontainer.html
index 607294a17..2840094c4 100644
--- a/mobmonitor/static/templates/healthstatuscontainer.html
+++ b/mobmonitor/static/templates/healthstatuscontainer.html
@@ -30,7 +30,7 @@
<td class="bold healthcheck-table-column2">Recommended Action(s)</td>
</tr>
{{#each errors}}
- <tr>
+ <tr class="healthcheck-info" hcname="{{name}}">
<td>{{description}}</td>
<td>
<ul>
@@ -58,7 +58,7 @@
<td class="bold healthcheck-table-column2">Recommended Action(s)</td>
</tr>
{{#each warnings}}
- <tr>
+ <tr class="healthcheck-info" hcname="{{name}}">
<td>{{description}}</td>
<td>
<ul>