| Index: tools/telemetry/telemetry/core/local_server.py
|
| diff --git a/tools/telemetry/telemetry/core/local_server.py b/tools/telemetry/telemetry/core/local_server.py
|
| deleted file mode 100644
|
| index 5c20c455f425a3fec67bd9aeacb2dbc9d992e8c4..0000000000000000000000000000000000000000
|
| --- a/tools/telemetry/telemetry/core/local_server.py
|
| +++ /dev/null
|
| @@ -1,224 +0,0 @@
|
| -# Copyright 2014 The Chromium Authors. All rights reserved.
|
| -# Use of this source code is governed by a BSD-style license that can be
|
| -# found in the LICENSE file.
|
| -
|
| -# TODO(aiolos): this should be moved to catapult/base after the repo move.
|
| -# It is used by tracing in tvcm/browser_controller.
|
| -import collections
|
| -import json
|
| -import os
|
| -import re
|
| -import subprocess
|
| -import sys
|
| -
|
| -from telemetry.core import util
|
| -from telemetry.internal import forwarders
|
| -
|
| -NamedPort = collections.namedtuple('NamedPort', ['name', 'port'])
|
| -
|
| -
|
| -class LocalServerBackend(object):
|
| -
|
| - def __init__(self):
|
| - pass
|
| -
|
| - def StartAndGetNamedPorts(self, args):
|
| - """Starts the actual server and obtains any sockets on which it
|
| - should listen.
|
| -
|
| - Returns a list of NamedPort on which this backend is listening.
|
| - """
|
| - raise NotImplementedError()
|
| -
|
| - def ServeForever(self):
|
| - raise NotImplementedError()
|
| -
|
| -
|
| -class LocalServer(object):
|
| -
|
| - def __init__(self, server_backend_class):
|
| - assert LocalServerBackend in server_backend_class.__bases__
|
| - server_module_name = server_backend_class.__module__
|
| - assert server_module_name in sys.modules, \
|
| - 'The server class\' module must be findable via sys.modules'
|
| - assert getattr(sys.modules[server_module_name],
|
| - server_backend_class.__name__), \
|
| - 'The server class must getattrable from its __module__ by its __name__'
|
| -
|
| - self._server_backend_class = server_backend_class
|
| - self._subprocess = None
|
| - self._devnull = None
|
| - self._local_server_controller = None
|
| - self.forwarder = None
|
| - self.host_ip = None
|
| -
|
| - def Start(self, local_server_controller):
|
| - assert self._subprocess == None
|
| - self._local_server_controller = local_server_controller
|
| -
|
| - self.host_ip = local_server_controller.host_ip
|
| -
|
| - server_args = self.GetBackendStartupArgs()
|
| - server_args_as_json = json.dumps(server_args)
|
| - server_module_name = self._server_backend_class.__module__
|
| -
|
| - self._devnull = open(os.devnull, 'w')
|
| - cmd = [
|
| - sys.executable,
|
| - '-m',
|
| - __name__,
|
| - 'run_backend',
|
| - server_module_name,
|
| - self._server_backend_class.__name__,
|
| - server_args_as_json,
|
| - ]
|
| -
|
| - env = os.environ.copy()
|
| - env['PYTHONPATH'] = os.pathsep.join(sys.path)
|
| -
|
| - self._subprocess = subprocess.Popen(cmd,
|
| - cwd=util.GetTelemetryDir(),
|
| - env=env,
|
| - stdout=subprocess.PIPE)
|
| -
|
| - named_ports = self._GetNamedPortsFromBackend()
|
| - named_port_pair_map = {'http': None, 'https': None, 'dns': None}
|
| - for name, port in named_ports:
|
| - assert name in named_port_pair_map, '%s forwarding is unsupported' % name
|
| - named_port_pair_map[name] = (forwarders.PortPair(
|
| - port, local_server_controller.GetRemotePort(port)))
|
| - self.forwarder = local_server_controller.CreateForwarder(
|
| - forwarders.PortPairs(**named_port_pair_map))
|
| -
|
| - def _GetNamedPortsFromBackend(self):
|
| - named_ports_json = None
|
| - named_ports_re = re.compile('LocalServerBackend started: (?P<port>.+)')
|
| - # TODO: This will hang if the subprocess doesn't print the correct output.
|
| - while self._subprocess.poll() == None:
|
| - m = named_ports_re.match(self._subprocess.stdout.readline())
|
| - if m:
|
| - named_ports_json = m.group('port')
|
| - break
|
| -
|
| - if not named_ports_json:
|
| - raise Exception('Server process died prematurely ' +
|
| - 'without giving us port pairs.')
|
| - return [NamedPort(**pair) for pair in json.loads(named_ports_json.lower())]
|
| -
|
| - @property
|
| - def is_running(self):
|
| - return self._subprocess != None
|
| -
|
| - def __enter__(self):
|
| - return self
|
| -
|
| - def __exit__(self, *args):
|
| - self.Close()
|
| -
|
| - def __del__(self):
|
| - self.Close()
|
| -
|
| - def Close(self):
|
| - if self.forwarder:
|
| - self.forwarder.Close()
|
| - self.forwarder = None
|
| - if self._subprocess:
|
| - # TODO(tonyg): Should this block until it goes away?
|
| - self._subprocess.kill()
|
| - self._subprocess = None
|
| - if self._devnull:
|
| - self._devnull.close()
|
| - self._devnull = None
|
| - if self._local_server_controller:
|
| - self._local_server_controller.ServerDidClose(self)
|
| - self._local_server_controller = None
|
| -
|
| - def GetBackendStartupArgs(self):
|
| - """Returns whatever arguments are required to start up the backend"""
|
| - raise NotImplementedError()
|
| -
|
| -
|
| -class LocalServerController(object):
|
| - """Manages the list of running servers
|
| -
|
| - This class manages the running servers, but also provides an isolation layer
|
| - to prevent LocalServer subclasses from accessing the browser backend directly.
|
| -
|
| - """
|
| -
|
| - def __init__(self, platform_backend):
|
| - self._platform_backend = platform_backend
|
| - self._local_servers_by_class = {}
|
| - self.host_ip = self._platform_backend.forwarder_factory.host_ip
|
| -
|
| - def StartServer(self, server):
|
| - assert not server.is_running, 'Server already started'
|
| - assert isinstance(server, LocalServer)
|
| - if server.__class__ in self._local_servers_by_class:
|
| - raise Exception(
|
| - 'Canont have two servers of the same class running at once. ' +
|
| - 'Locate the existing one and use it, or call Close() on it.')
|
| -
|
| - server.Start(self)
|
| - self._local_servers_by_class[server.__class__] = server
|
| -
|
| - def GetRunningServer(self, server_class, default_value):
|
| - return self._local_servers_by_class.get(server_class, default_value)
|
| -
|
| - @property
|
| - def local_servers(self):
|
| - return self._local_servers_by_class.values()
|
| -
|
| - def Close(self):
|
| - while len(self._local_servers_by_class):
|
| - server = self._local_servers_by_class.itervalues().next()
|
| - try:
|
| - server.Close()
|
| - except Exception:
|
| - import traceback
|
| - traceback.print_exc()
|
| -
|
| - def CreateForwarder(self, port_pairs):
|
| - return self._platform_backend.forwarder_factory.Create(port_pairs)
|
| -
|
| - def GetRemotePort(self, port):
|
| - return self._platform_backend.GetRemotePort(port)
|
| -
|
| - def ServerDidClose(self, server):
|
| - del self._local_servers_by_class[server.__class__]
|
| -
|
| -
|
| -def _LocalServerBackendMain(args):
|
| - assert len(args) == 4
|
| - (cmd, server_module_name, server_backend_class_name,
|
| - server_args_as_json) = args[:4]
|
| - assert cmd == 'run_backend'
|
| - server_module = __import__(server_module_name, fromlist=[True])
|
| - server_backend_class = getattr(server_module, server_backend_class_name)
|
| - server = server_backend_class()
|
| -
|
| - server_args = json.loads(server_args_as_json)
|
| -
|
| - named_ports = server.StartAndGetNamedPorts(server_args)
|
| - assert isinstance(named_ports, list)
|
| - for named_port in named_ports:
|
| - assert isinstance(named_port, NamedPort)
|
| -
|
| - # Note: This message is scraped by the parent process'
|
| - # _GetNamedPortsFromBackend(). Do **not** change it.
|
| - # pylint: disable=protected-access
|
| - print 'LocalServerBackend started: %s' % json.dumps([pair._asdict()
|
| - for pair in named_ports])
|
| - sys.stdout.flush()
|
| -
|
| - return server.ServeForever()
|
| -
|
| -
|
| -if __name__ == '__main__':
|
| - # This trick is needed because local_server.NamedPort is not the
|
| - # same as sys.modules['__main__'].NamedPort. The module itself is loaded
|
| - # twice, basically.
|
| - from telemetry.core import local_server # pylint: disable=import-self
|
| - sys.exit(
|
| - local_server._LocalServerBackendMain( # pylint: disable=protected-access
|
| - sys.argv[1:]))
|
|
|