1#!/usr/bin/env python 2# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6"""XML RPC server for multimedia testing.""" 7 8import argparse 9import code 10import logging 11import xmlrpclib 12import traceback 13import common # pylint: disable=unused-import 14from autotest_lib.client.bin import utils 15from autotest_lib.client.common_lib import logging_config 16from autotest_lib.client.common_lib.cros import chrome 17from autotest_lib.client.cros import constants 18from autotest_lib.client.cros import xmlrpc_server 19from autotest_lib.client.cros.multimedia import audio_facade_native 20from autotest_lib.client.cros.multimedia import browser_facade_native 21from autotest_lib.client.cros.multimedia import display_facade_native 22from autotest_lib.client.cros.multimedia import system_facade_native 23from autotest_lib.client.cros.multimedia import usb_facade_native 24from autotest_lib.client.cros.multimedia import facade_resource 25 26 27class MultimediaXmlRpcDelegate(xmlrpc_server.XmlRpcDelegate): 28 """XML RPC delegate for multimedia testing.""" 29 30 def __init__(self, resource): 31 """Initializes the facade objects.""" 32 self._facades = { 33 'audio': audio_facade_native.AudioFacadeNative(resource), 34 'display': display_facade_native.DisplayFacadeNative(resource), 35 'system': system_facade_native.SystemFacadeNative(), 36 'usb': usb_facade_native.USBFacadeNative(), 37 'browser': browser_facade_native.BrowserFacadeNative(resource), 38 } 39 40 41 def __exit__(self, exception, value, traceback): 42 """Clean up the resources.""" 43 self._facades['audio'].cleanup() 44 45 46 def _dispatch(self, method, params): 47 """Dispatches the method to the proper facade. 48 49 We turn off allow_dotted_names option. The method handles the dot 50 and dispatches the method to the proper native facade, like 51 DisplayFacadeNative. 52 53 """ 54 try: 55 try: 56 if '.' not in method: 57 func = getattr(self, method) 58 else: 59 facade_name, method_name = method.split('.', 1) 60 if facade_name in self._facades: 61 func = getattr(self._facades[facade_name], method_name) 62 else: 63 raise Exception('unknown facade: %s' % facade_name) 64 except AttributeError: 65 raise Exception('method %s not supported' % method) 66 67 logging.info('Dispatching method %s with args %s', 68 str(func), str(params)) 69 return func(*params) 70 except: 71 # TODO(ihf): Try to return meaningful stacktraces from the client. 72 return traceback.format_exc() 73 74 75def config_logging(): 76 """Configs logging to be verbose and use console handler.""" 77 config = logging_config.LoggingConfig() 78 config.configure_logging(use_console=True, verbose=True) 79 80 81if __name__ == '__main__': 82 parser = argparse.ArgumentParser() 83 parser.add_argument('-d', '--debug', action='store_true', required=False, 84 help=('create a debug console with a ServerProxy "s" ' 85 'connecting to the XML RPC sever at localhost')) 86 parser.add_argument('--restart', action='store_true', required=False, 87 help=('restart the XML RPC server without clearing ' 88 'the previous state')) 89 args = parser.parse_args() 90 91 if args.debug: 92 s = xmlrpclib.ServerProxy('http://localhost:%d' % 93 constants.MULTIMEDIA_XMLRPC_SERVER_PORT, 94 allow_none=True) 95 code.interact(local=locals()) 96 else: 97 config_logging() 98 logging.debug('multimedia_xmlrpc_server main...') 99 100 101 # Restart Cras to clean up any audio activities. 102 utils.restart_job('cras') 103 104 with facade_resource.FacadeResource(restart=args.restart) as res: 105 server = xmlrpc_server.XmlRpcServer( 106 'localhost', constants.MULTIMEDIA_XMLRPC_SERVER_PORT) 107 server.register_delegate(MultimediaXmlRpcDelegate(res)) 108 server.run() 109