diff options
author | Matthew Sartori <msartori@chromium.org> | 2015-07-09 17:18:30 -0700 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-07-15 23:15:37 +0000 |
commit | af96c840889ef457c3f897e3f94e2ad9912ed833 (patch) | |
tree | 4912a4b711c137179536dad357d800c6153abcf6 /mobmonitor | |
parent | 355c6cee60e0a1abe8d7907ad4c186c6024a2e83 (diff) | |
download | chromite-af96c840889ef457c3f897e3f94e2ad9912ed833.tar.gz |
mobmonitor: Changes for deploying Mob* Monitor to moblab
This CL re-organizes the mobmonitor project so that all scripts
are located under the mobmonitor directory, rather than
under chromite/scripts. Mob* Monitor related executables have
been removed from chromite/bin. Some changes were made to account
for import path changes.
BUG=chromium:507898
TEST=Unittests.
Change-Id: Ieee4da6fcef59a18c63d612eb9efbea6f01734be
Reviewed-on: https://chromium-review.googlesource.com/284675
Reviewed-by: Matthew Sartori <msartori@chromium.org>
Tested-by: Matthew Sartori <msartori@chromium.org>
Commit-Queue: Matthew Sartori <msartori@chromium.org>
Diffstat (limited to 'mobmonitor')
-rw-r--r-- | mobmonitor/checkfile/manager_unittest.py | 6 | ||||
-rw-r--r-- | mobmonitor/scripts/__init__.py | 0 | ||||
-rwxr-xr-x | mobmonitor/scripts/mobmoncli.py | 77 | ||||
-rwxr-xr-x | mobmonitor/scripts/mobmonitor.py | 106 | ||||
l--------- | mobmonitor/scripts/mobmonitor_unittest | 1 | ||||
-rw-r--r-- | mobmonitor/scripts/mobmonitor_unittest.py | 83 |
6 files changed, 270 insertions, 3 deletions
diff --git a/mobmonitor/checkfile/manager_unittest.py b/mobmonitor/checkfile/manager_unittest.py index 66dea410d..be149f0d6 100644 --- a/mobmonitor/checkfile/manager_unittest.py +++ b/mobmonitor/checkfile/manager_unittest.py @@ -758,8 +758,8 @@ class CheckFileManagerTest(cros_test_lib.MockTestCase): class CheckFileModificationTest(cros_test_lib.MockTempDirTestCase): """Unittests for checking when live changes are made to a checkfile.""" - MOBMONITOR_BASENAME = 'chromite' - MOBMONITOR_REL_CMD = 'bin/mobmonitor' + MOBMONITOR_BASENAME = 'mobmonitor' + MOBMONITOR_REL_CMD = 'scripts/mobmonitor.py' SERVICE_DIR = 'test_service' CHECKFILE_REL_PATH = 'test_check.py' NOTACHECK_REL_PATH = 'notacheck.py' @@ -835,7 +835,7 @@ class CheckFileModificationTest(cros_test_lib.MockTempDirTestCase): while os.path.basename(path) != self.MOBMONITOR_BASENAME: path = os.path.dirname(path) path = os.path.join(path, self.MOBMONITOR_REL_CMD) - self.cmd = [path, '-d', self.checkdir] + self.cmd = ['python', path, '-d', self.checkdir] # Setup an rpc client for communicating with the Mob* Monitor. self.rpc = rpc.RpcExecutor() diff --git a/mobmonitor/scripts/__init__.py b/mobmonitor/scripts/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/mobmonitor/scripts/__init__.py diff --git a/mobmonitor/scripts/mobmoncli.py b/mobmonitor/scripts/mobmoncli.py new file mode 100755 index 000000000..909c014c2 --- /dev/null +++ b/mobmonitor/scripts/mobmoncli.py @@ -0,0 +1,77 @@ +#!/usr/bin/python2 +# 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. + +"""Command-line interface for the Mob* Monitor.""" + +from __future__ import print_function + +import sys + +from chromite.lib import commandline +from chromite.lib import remote_access +from chromite.mobmonitor.rpc import rpc + + +class MobMonCli(object): + """Provides command-line functionality for using the Mob* Monitor.""" + + def __init__(self, host='localhost', port=9999): + self.host = host + self.port = remote_access.NormalizePort(port) + + def ExecuteRequest(self, request, service, action): + """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. + action: The action to be performed. + """ + rpcexec = rpc.RpcExecutor(self.host, self.port) + + if not hasattr(rpcexec, request): + raise rpc.RpcError('The request "%s" is not recognized.' % request) + + if 'GetServiceList' == request: + return rpcexec.GetServiceList() + + if 'GetStatus' == request: + return rpcexec.GetStatus(service=service) + + if 'RepairService' == request: + return rpcexec.RepairService(service=service, action=action) + + +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('-a', '--action', help='The action to execute') + parser.add_argument('--host', default='localhost', + help='The hostname of the Mob* Monitor.') + parser.add_argument('-p', '--port', type=int, default=9999, + help='The Mob* Monitor port.') + + return parser.parse_args(argv) + + +def main(argv): + """Command line interface for the Mob* Monitor. + + The basic syntax is: + mobmon <request> [args] + mobmon --help + """ + options = ParseArguments(argv) + + cli = MobMonCli(options.host, options.port) + result = cli.ExecuteRequest(options.request, options.service, + options.action) + + print(result) + + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/mobmonitor/scripts/mobmonitor.py b/mobmonitor/scripts/mobmonitor.py new file mode 100755 index 000000000..329fac18f --- /dev/null +++ b/mobmonitor/scripts/mobmonitor.py @@ -0,0 +1,106 @@ +#!/usr/bin/python2 +# 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. + +"""The Mob* Monitor web interface.""" + +from __future__ import print_function + +import cherrypy +import json +import sys + +from chromite.lib import remote_access +from chromite.lib import commandline +from chromite.mobmonitor.checkfile import manager + + +class MobMonitorRoot(object): + """The central object supporting the Mob* Monitor web interface.""" + + def __init__(self, checkfile_manager): + self.checkfile_manager = checkfile_manager + + @cherrypy.expose + def index(self): + """Presents a welcome message.""" + return 'Welcome to the Mob* Monitor!' + + @cherrypy.expose + def GetServiceList(self): + """Return a list of the monitored services. + + Returns: + A list of the monitored services. + """ + return json.dumps(self.checkfile_manager.GetServiceList()) + + @cherrypy.expose + def GetStatus(self, service=None): + """Return the health status of the specified service. + + Args: + service: The service whose health status is being queried. If service + is None, return the health status of all monitored services. + + Returns: + A list of dictionaries. Each dictionary contains the keys: + service: The name of the service. + health: A boolean describing the overall service health. + healthchecks: A list of unhealthy or quasi-healthy health checks. + """ + service_statuses = self.checkfile_manager.GetStatus(service) + if not isinstance(service_statuses, list): + service_statuses = [service_statuses] + + result = [ + manager.MapServiceStatusToDict(status) for status in service_statuses] + return json.dumps(result) + + # TODO (msartori): Implement crbug.com/505066. + @cherrypy.expose + def RepairService(self, service, action): + """Execute the repair action on the specified service. + + Args: + service: The service that the specified action will be applied to. + action: The action to be applied. + """ + status = self.checkfile_manager.RepairService(service, action) + return json.dumps(manager.MapServiceStatusToDict(status)) + + +def ParseArguments(argv): + """Creates the argument parser.""" + parser = commandline.ArgumentParser(description=__doc__) + + parser.add_argument('-d', '--checkdir', + default='/etc/mobmonitor/checkfiles/', + help='The Mob* Monitor checkfile directory.') + parser.add_argument('-p', '--port', type=int, default=9999, + help='The Mob* Monitor port.') + + return parser.parse_args(argv) + + +def main(argv): + options = ParseArguments(argv) + options.Freeze() + + # Start the Mob* Monitor web interface. + cherrypy.config.update({'server.socket_port': + remote_access.NormalizePort(options.port)}) + + # Setup the mobmonitor + checkfile_manager = manager.CheckFileManager(checkdir=options.checkdir) + mobmonitor = MobMonitorRoot(checkfile_manager) + + # Start the checkfile collection and execution background task. + checkfile_manager.StartCollectionExecution() + + cherrypy.quickstart(mobmonitor) + + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/mobmonitor/scripts/mobmonitor_unittest b/mobmonitor/scripts/mobmonitor_unittest new file mode 120000 index 000000000..ef3e37b67 --- /dev/null +++ b/mobmonitor/scripts/mobmonitor_unittest @@ -0,0 +1 @@ +../../scripts/wrapper.py
\ No newline at end of file diff --git a/mobmonitor/scripts/mobmonitor_unittest.py b/mobmonitor/scripts/mobmonitor_unittest.py new file mode 100644 index 000000000..e2aa263b1 --- /dev/null +++ b/mobmonitor/scripts/mobmonitor_unittest.py @@ -0,0 +1,83 @@ +# 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 the main Mob* Monitor script.""" + +from __future__ import print_function + +import json + +from chromite.lib import cros_test_lib +from chromite.mobmonitor.checkfile import manager +from chromite.mobmonitor.scripts import mobmonitor + + +class MockCheckFileManager(object): + """Mock CheckFileManager object that returns 'real' responses for testing.""" + + def __init__(self): + failed_check = manager.HEALTHCHECK_STATUS('hc1', False, 'Failed', []) + + self.service_statuses = [ + manager.SERVICE_STATUS('service1', True, []), + manager.SERVICE_STATUS('service2', False, [failed_check])] + + def GetServiceList(self): + """Mock GetServiceList response.""" + return ['test_service_1', 'test_service_2'] + + def GetStatus(self, service=None): + """Mock GetStatus response.""" + if service is None: + return self.service_statuses + + return self.service_statuses[0] + + def RepairService(self, _service, _action): + """Mock RepairService response.""" + return self.service_statuses[0] + + +class MobMonitorRootTest(cros_test_lib.MockTestCase): + """Unittests for the MobMonitorRoot.""" + + def testGetServiceList(self): + """Test the GetServiceList RPC.""" + cfm = MockCheckFileManager() + root = mobmonitor.MobMonitorRoot(cfm) + self.assertEqual(cfm.GetServiceList(), json.loads(root.GetServiceList())) + + def testGetStatus(self): + """Test the GetStatus RPC.""" + cfm = MockCheckFileManager() + root = mobmonitor.MobMonitorRoot(cfm) + + # Test the result for a single service. + status = cfm.service_statuses[0] + expect = {'service': status.service, 'health': status.health, + 'healthchecks': []} + self.assertEquals([expect], json.loads(root.GetStatus(status.service))) + + # Test the result for multiple services. + status1, status2 = cfm.service_statuses + check = status2.healthchecks[0] + expect = [{'service': status1.service, 'health': status1.health, + 'healthchecks': []}, + {'service': status2.service, 'health': status2.health, + 'healthchecks': [{'name': check.name, 'health': check.health, + 'description': check.description, + 'actions': []}]}] + self.assertEquals(expect, json.loads(root.GetStatus())) + + def testRepairService(self): + """Test the RepairService RPC.""" + cfm = MockCheckFileManager() + root = mobmonitor.MobMonitorRoot(cfm) + + status = cfm.service_statuses[0] + expect = {'service': status.service, 'health': status.health, + 'healthchecks': []} + self.assertEquals(expect, + json.loads(root.RepairService('dummy_service', + 'dummy_action'))) |