Ejemplo n.º 1
0
    def run(self):
        log.info("starting on port {}".format(port))
        plugin = WebSocketPlugin(cherrypy.engine)
        plugin.subscribe()
        cherrypy.tools.websocket = WebSocketTool()

        p.events.on("switch", self.dispatch_device, priority=True)
        p.events.on("coil", self.dispatch_device, priority=True)
        p.events.on("lamp", self.dispatch_device, priority=True)
        p.events.on("flasher", self.dispatch_device, priority=True)
        p.events.on("gi", self.dispatch_device, priority=True)
        p.events.on("notice", self.dispatch_notice, priority=True)

        cherrypy.quickstart(Root(), "/", config={
            "/": {
                "tools.staticdir.on": True,
                "tools.staticdir.root": os.path.abspath(os.path.join(
                        os.path.dirname(__file__), "..", "..", "web")),
                "tools.staticdir.index": "index.html",
                "tools.staticdir.dir": ""
            },
            "/console": {
                "tools.staticdir.on": True,
                "tools.staticdir.dir": "console"
            },
            "/ws": {
                "tools.websocket.on": True,
                "tools.websocket.handler_cls": WebSocketHandler
            }
        })
        self.done(plugin)
Ejemplo n.º 2
0
def _configure_server(restarting=False):
    global websocket_plugin

    # Configure server error log
    cherrypy.config.update({'log.error_file': 'cherrypy.error.log'})

    # Configure server url
    cherrypy.config.update({'server.socket_host': utils.s2n(autosubliminal.WEBSERVERIP),
                            'server.socket_port': int(autosubliminal.WEBSERVERPORT)
                            })

    # Disable engine plugins (no need for autoreload plugin)
    cherrypy.config.update({'engine.autoreload.on': False})

    # Configure authentication in if a username and password is set by the user
    if autosubliminal.USERNAME and autosubliminal.PASSWORD:
        users = {utils.s2n(autosubliminal.USERNAME): utils.s2n(autosubliminal.PASSWORD)}
        cherrypy.config.update({'tools.auth_digest.on': True,
                                'tools.auth_digest.realm': 'Auto-Subliminal website',
                                'tools.auth_digest.get_ha1': auth_digest.get_ha1_dict_plain(users),
                                'tools.auth_digest.key': 'yek.tsegid_htua.lanimilbuS-otuA'  # Can be any random string
                                })

    if not restarting:
        # Enable websocket plugin
        websocket_plugin = WebSocketPlugin(cherrypy.engine)
        websocket_plugin.subscribe()
        cherrypy.tools.websocket = WebSocketTool()
    else:
        # When restarting we need to create a new websocket manager thread (you cannot start the same thread twice!)
        websocket_plugin.manager = WebSocketManager()
        # When restarting we need to clear the httpserver to force the creation of a new one (needed for ip/port change)
        cherrypy.server.httpserver = None
Ejemplo n.º 3
0
 def extend_server_configuration(cls, engine, config):
     """Extend the server configuration."""
     cp_plugin = WebSocketPlugin(engine)
     cp_plugin.subscribe()
     cherrypy.tools.websocket = WebSocketTool()
     for handler in cls.handlers:
         config.update({
             handler.ws_point: {
                 'tools.websocket.on': True,
                 'tools.websocket.handler_cls': handler,
             },
         })
Ejemplo n.º 4
0
 def extend_server_configuration(cls, engine, config):
     """Extend the server configuration."""
     cp_plugin = WebSocketPlugin(engine)
     cp_plugin.subscribe()
     cherrypy.tools.websocket = WebSocketTool()
     for handler in cls.handlers:
         config.update({
             handler.ws_point: {
                 'tools.websocket.on': True,
                 'tools.websocket.handler_cls': handler,
             },
         })
Ejemplo n.º 5
0
def _configure_server(restarting=False):
    global websocket_plugin

    # Configure server error log
    cherrypy.config.update({'log.error_file': 'cherrypy.error.log'})

    # Configure server url
    cherrypy.config.update({
        'server.socket_host':
        s2n(autosubliminal.WEBSERVERIP),
        'server.socket_port':
        int(autosubliminal.WEBSERVERPORT)
    })

    # Disable engine plugins (no need for autoreload plugin)
    cherrypy.config.update({'engine.autoreload.on': False})

    # Read and store cherrypy server version (if not set, it returns CherryPy/Unknown because it's not installed)
    server_header = 'CherryPy/%s' % get_library_version('cherrypy')
    cherrypy.config.update({'response.headers.server': server_header})

    # Configure authentication in if a username and password is set by the user
    if autosubliminal.USERNAME and autosubliminal.PASSWORD:
        users = {s2n(autosubliminal.USERNAME): s2n(autosubliminal.PASSWORD)}
        cherrypy.config.update({
            'tools.auth_digest.on':
            True,
            'tools.auth_digest.realm':
            'Auto-Subliminal website',
            'tools.auth_digest.get_ha1':
            auth_digest.get_ha1_dict_plain(users),
            'tools.auth_digest.key':
            'yek.tsegid_htua.lanimilbuS-otuA'  # Can be any random string
        })

    # Configure our custom json_out_handler (Uncomment if it should be used for any @cherrypy.tools.json_out())
    # cherrypy.config.update({'tools.json_out.handler': json_out_handler})

    if not restarting:
        # Enable websocket plugin
        websocket_plugin = WebSocketPlugin(cherrypy.engine)
        websocket_plugin.subscribe()
        cherrypy.tools.websocket = WebSocketTool()
    else:
        # When restarting we need to create a new websocket manager thread (you cannot start the same thread twice!)
        websocket_plugin.manager = WebSocketManager()
        # When restarting we need to clear the httpserver to force the creation of a new one (needed for ip/port change)
        cherrypy.server.httpserver = None
Ejemplo n.º 6
0
def start_cherrypy_debug_server(htdocs_path,
                                http_host, http_port,
                                mpd_host, mpd_port=6600, mpd_password=None):

    # set cherrypy configuration.
    cherrypy.config.update({'server.socket_port': http_port})
    cherrypy.config.update({'server.socket_host': http_host})

    if (not os.path.isdir(htdocs_path)):
        print("=" * 80 + """
  The ympd htdocs dir is not available: perhaps the git submodule is missing?
""" + "=" * 80)
        sys.exit(1)

    # Add the websocket requirements.
    a = WebSocketPlugin(cherrypy.engine)
    a.manager = WebSocketManager()
    a.subscribe()
    cherrypy.tools.websocket = WebSocketTool()


    web_root = Root()

    # get a function to instantiate the websocket with the correct settings.
    ympd_websocket = ympdWebSocket_wrap(mpd_host, mpd_port, mpd_password)

    # Run a no-websocket alternative at http://hostname:port/nows/
    nowebsocket = ympdNoWebSocket_wrap(mpd_host, mpd_port, mpd_password)
    web_root.nows = nowebsocket(htdocs_path)
    # this implementation uses POST requests communicate.
    # Takes a little bit longer for the UI to update, but it should get through
    # firewalls and proxies where the websocket cannot.

    cherrypy.quickstart(web_root, '/', config={
                '/ws': {'tools.websocket.on': True,
                        'tools.websocket.handler_cls': ympd_websocket},
                '/': {'tools.staticdir.on': True,
                      'tools.staticdir.dir': os.path.join(htdocs_path),
                      "tools.staticdir.index": "index.html"},
            }
            )
Ejemplo n.º 7
0
def _configure_server(restarting=False):
    global websocket_plugin

    # Configure server error log
    cherrypy.config.update({'log.error_file': 'cherrypy.error.log'})

    # Configure server url
    cherrypy.config.update({'server.socket_host': s2n(autosubliminal.WEBSERVERIP),
                            'server.socket_port': int(autosubliminal.WEBSERVERPORT)
                            })

    # Disable engine plugins (no need for autoreload plugin)
    cherrypy.config.update({'engine.autoreload.on': False})

    # Read and store cherrypy server version (if not set, it returns CherryPy/Unknown because it's not installed)
    server_header = 'CherryPy/%s' % get_library_version('cherrypy')
    cherrypy.config.update({'response.headers.server': server_header})

    # Configure authentication in if a username and password is set by the user
    if autosubliminal.USERNAME and autosubliminal.PASSWORD:
        users = {s2n(autosubliminal.USERNAME): s2n(autosubliminal.PASSWORD)}
        cherrypy.config.update({'tools.auth_digest.on': True,
                                'tools.auth_digest.realm': 'Auto-Subliminal website',
                                'tools.auth_digest.get_ha1': auth_digest.get_ha1_dict_plain(users),
                                'tools.auth_digest.key': 'yek.tsegid_htua.lanimilbuS-otuA'  # Can be any random string
                                })

    # Configure our custom json_out_handler (Uncomment if it should be used for any @cherrypy.tools.json_out())
    # cherrypy.config.update({'tools.json_out.handler': json_out_handler})

    if not restarting:
        # Enable websocket plugin
        websocket_plugin = WebSocketPlugin(cherrypy.engine)
        websocket_plugin.subscribe()
        cherrypy.tools.websocket = WebSocketTool()
    else:
        # When restarting we need to create a new websocket manager thread (you cannot start the same thread twice!)
        websocket_plugin.manager = WebSocketManager()
        # When restarting we need to clear the httpserver to force the creation of a new one (needed for ip/port change)
        cherrypy.server.httpserver = None
Ejemplo n.º 8
0
class ZuulWeb(object):
    log = logging.getLogger("zuul.web.ZuulWeb")

    def __init__(self, listen_address, listen_port,
                 gear_server, gear_port,
                 ssl_key=None, ssl_cert=None, ssl_ca=None,
                 static_cache_expiry=3600,
                 connections=None,
                 info=None,
                 static_path=None):
        self.start_time = time.time()
        self.listen_address = listen_address
        self.listen_port = listen_port
        self.event_loop = None
        self.term = None
        self.server = None
        self.static_cache_expiry = static_cache_expiry
        self.info = info
        self.static_path = os.path.abspath(static_path or STATIC_DIR)
        # instanciate handlers
        self.rpc = zuul.rpcclient.RPCClient(gear_server, gear_port,
                                            ssl_key, ssl_cert, ssl_ca)
        self.connections = connections
        self.stream_manager = StreamManager()

        route_map = cherrypy.dispatch.RoutesDispatcher()
        api = ZuulWebAPI(self)
        tenant_static = TenantStaticHandler(self.static_path)
        root_static = RootStaticHandler(self.static_path)
        route_map.connect('api', '/api/info',
                          controller=api, action='info')
        route_map.connect('api', '/api/tenants',
                          controller=api, action='tenants')
        route_map.connect('api', '/api/tenant/{tenant}/info',
                          controller=api, action='tenant_info')
        route_map.connect('api', '/api/tenant/{tenant}/status',
                          controller=api, action='status')
        route_map.connect('api', '/api/tenant/{tenant}/status/change/{change}',
                          controller=api, action='status_change')
        route_map.connect('api', '/api/tenant/{tenant}/jobs',
                          controller=api, action='jobs')
        route_map.connect('api', '/api/tenant/{tenant}/key/{project:.*}.pub',
                          controller=api, action='key')
        route_map.connect('api', '/api/tenant/{tenant}/console-stream',
                          controller=api, action='console_stream')
        route_map.connect('api', '/api/tenant/{tenant}/builds',
                          controller=api, action='builds')
        route_map.connect('api', '/api/tenant/{tenant}/config-errors',
                          controller=api, action='config_errors')

        for connection in connections.connections.values():
            controller = connection.getWebController(self)
            if controller:
                cherrypy.tree.mount(
                    controller,
                    '/api/connection/%s' % connection.connection_name)

        # Add fallthrough routes at the end for the static html/js files
        route_map.connect('root_static', '/{path:.*}',
                          controller=root_static, action='default')
        route_map.connect('tenant_static', '/t/{tenant}/{path:.*}',
                          controller=tenant_static, action='default')

        conf = {
            '/': {
                'request.dispatch': route_map
            }
        }
        cherrypy.config.update({
            'global': {
                'environment': 'production',
                'server.socket_host': listen_address,
                'server.socket_port': int(listen_port),
            },
        })

        cherrypy.tree.mount(api, '/', config=conf)

    @property
    def port(self):
        return cherrypy.server.bound_addr[1]

    def start(self):
        self.log.debug("ZuulWeb starting")
        self.stream_manager.start()
        self.wsplugin = WebSocketPlugin(cherrypy.engine)
        self.wsplugin.subscribe()
        cherrypy.engine.start()

    def stop(self):
        self.log.debug("ZuulWeb stopping")
        self.rpc.shutdown()
        cherrypy.engine.exit()
        # Not strictly necessary, but without this, if the server is
        # started again (e.g., in the unit tests) it will reuse the
        # same host/port settings.
        cherrypy.server.httpserver = None
        self.wsplugin.unsubscribe()
        self.stream_manager.stop()
Ejemplo n.º 9
0
            self.stream_mux.active_in = json['stream_source']


class RobotWebApp:
    @cherrypy.expose
    def index(self):
        raise cherrypy.InternalRedirect('/static/index.html')

    @cherrypy.expose
    def ws(self):
        pass


cherrypy.tools.websocket = WebSocketTool()
websocket_plugin = WebSocketPlugin(cherrypy.engine)
websocket_plugin.subscribe()


class StreamBroadcaster(Thread):
    def __init__(self, stream, websockets):
        super().__init__(daemon=True, name="StreamBroadcaster")
        self.stream = stream
        self.websockets = websockets

    def run(self):
        try:
            while True:
                buf = self.stream.read1(32768)
                self.websockets.broadcast(buf, binary=True)
        except ValueError:
            pass
Ejemplo n.º 10
0
def start_broker():
    """
    Starts the broker; Loads settings, connects to database, registers process and starts the web server.
    """

    global process_id, database_access, address, web_socket_plugin, repository_parent_folder, \
        web_config, schema_tools, namespaces, log_to_database_severity, plugins, settings

    process_id = str(ObjectId())


    of.common.logging.callback = log_locally

    write_srvc_dbg("=====Starting broker=============================")

    try:
        _cfg_filename = resolve_config_path()
        settings = JSONXPath(_cfg_filename)

    except Exception as e:
        if os.name == "nt":
            write_to_log(_data="Error loading settings from " + _cfg_filename,
                         _category=EC_SERVICE, _severity=SEV_FATAL)
        raise Exception("Error loading settings:" + str(e))

    if os.name != "nt":
        x_logger = logging.FileHandler("/var/log/of.log")

    of.common.logging.severity = of.common.logging.severity_identifiers.index(
        settings.get("broker/logging/severityLevel", _default="warning"))

    log_to_database_severity = of.common.logging.severity_identifiers.index(
        settings.get("broker/logging/databaseLevel", _default="warning"))

    write_srvc_dbg("Loaded settings from " + _cfg_filename)

    # An address is completely neccessary.
    address = settings.get("broker/address", _default=None)
    if not address or address == "":
        write_to_log(_data="Broker cannot start, missing [broker] address setting in configuration file.",
                     _category=EC_SERVICE, _severity=SEV_FATAL)
        raise Exception("Broker cannot start, missing address.")

    # TODO: Reorganize. It is likely that almost everything but external database credentials should be stored in the db PROD-105

    # Initialize schema tools (of_uri_handler is later replaced by the general one)
    schema_tools = SchemaTools(_json_schema_folders=[os.path.join(script_dir, "../schemas/namespaces/")],
                               _uri_handlers={"ref": of_uri_handler})

    namespaces = CumulativeDict(_default={"schemas": []})

    write_srvc_dbg("Load plugin data")
    # Find the plugin directory
    _plugins_folder = settings.get_path("broker/pluginsFolder", _default="plugins")

    # Load all plugin data
    plugins = CherryPyPlugins(_plugins_folder=_plugins_folder, _schema_tools=schema_tools, _namespaces=namespaces,
                               _process_id=process_id,
                              _no_package_name_override=settings.get("broker/packageNameOverride"))


    # Plugins may want to load settings or add globals
    plugins.call_hook("init_broker_scope", _broker_scope=globals(), _settings=settings)

    write_srvc_dbg("===Register signal handlers===")
    register_signals(stop_broker)
    plugins.call_hook("before_db_connect", _broker_scope=globals())
    # Connect to the database
    _host = settings.get("broker/database/host", _default="127.0.0.1")
    _user = settings.get("broker/database/username", _default=None)
    _password = settings.get("broker/database/password", _default=None)
    if _user:
        write_srvc_dbg("===Connecting to remote MongoDB backend " + _host + "===")
        # http://api.mongodb.org/python/current/examples/authentication.html
        _client = MongoClient("mongodb://" + _user + ":" + _password + "@" + _host)
    else:
        write_srvc_dbg("===Connecting to local MongoDB backend===")
        _client = MongoClient()

    _database_name = settings.get("broker/database/databaseName", _default="optimalframework")
    write_srvc_dbg("Using database name :" + _database_name)

    _database = _client[_database_name]
    database_access = DatabaseAccess(_database=_database, _schema_tools=schema_tools)
    of.common.logging.callback = log_to_database
    database_access.save(store_process_system_document(_process_id=process_id,
                                                       _name="Broker instance(" + address + ")"),
                         _user=None,
                         _allow_save_id=True)
    plugins.call_hook("after_db_connect", _broker_scope=globals())
    # TODO: It is possible that one would like to initialize, or at least read the plugins *before* trying to connect to the database

    # Must have a valid CherryPy version
    if hasattr(cherrypy.engine, "subscribe"):  # CherryPy >= 3.1
        pass
    else:
        write_to_log(_data="This application requires CherryPy >= 3.1 or higher.", _category=EC_SERVICE,
                     _severity=SEV_FATAL)
        raise Exception("Broker init: This application requires CherryPy >= 3.1 or higher.")
        # cherrypy.engine.on_stop_engine_list.append(_save_data)

    def ssl_path():
        # Figure out the path to the ssl-certificates
        # TODO: Load from database instead. Or not? (PROD-19)
        return os.path.dirname(_cfg_filename)

    # Initialize CherryPy:s global configuration; note that this could be moved into a configuration file
    cherrypy.config.update({
        "tools.encode.on": True,
        "tools.encode.encoding": "utf-8",
        "tools.decode.on": True,
        "tools.trailing_slash.on": True,
        "tools.staticdir.root": os.path.abspath(os.path.dirname(__file__)),
        "server.ssl_module": "builtin",
        # TODO: Remove this when this bug is fixed:
        # https://bitbucket.org/cherrypy/cherrypy/issue/1341/autoreloader-also-fails-if-six-is-present
        "engine.autoreload.on": False,
        'server.socket_host': '0.0.0.0',
        "server.ssl_certificate": os.path.join(ssl_path(), "optimalframework_test_cert.pem"),
        "server.ssl_private_key": os.path.join(ssl_path(), "optimalframework_test_privkey.pem"),
        "error_page.default": error_message_default
    })
    write_srvc_dbg("Starting CherryPy, ssl at " + os.path.join(ssl_path(), "optimalframework_test_privkey.pem"))

    web_config = {
        # The UI root
        "/": {
            "tools.staticdir.on": True,
            "tools.staticdir.dir": "ui",
            "tools.trailing_slash.on": True,
            "tools.staticdir.index": "index.html",
        },
        # Note that the web socket handling is put under /socket.
        "/socket": {
            "tools.websocket.on": True,
            "tools.websocket.handler_cls": BrokerWebSocket
        }
    }

    global web_root

    cherrypy._global_conf_alias.update(web_config)
    web_socket_plugin = WebSocketPlugin(cherrypy.engine)
    web_socket_plugin.subscribe()
    cherrypy.tools.websocket = WebSocketTool()

    cherrypy.engine.signals.bus.signal_handler.handlers = {'SIGUSR1': cherrypy.engine.signals.bus.graceful}

    # Initialize the decorator-based authentication framework
    init_authentication(MongoDBAuthBackend(database_access))

    # Initialize root UI
    web_root = CherryPyBroker(_process_id=process_id, _address=address, _database_access=database_access)
    # Initialize messaging
    of.common.messaging.websocket.monitor = Monitor(_handler=BrokerWebSocketHandler(process_id, _peers=web_root.peers,
                                                                                    _database_access=database_access,
                                                                                    _schema_tools=database_access.schema_tools,
                                                                                    _address=address))

    web_root.plugins = plugins
    # Generate the static content, initialisation
    plugins.call_hook("init_web", _broker_scope = globals())

    _web_config_debug = "Broker configured. Starting web server. Web config:\n"
    for _curr_key, _curr_config in web_config.items():
        if "tools.staticdir.dir" in _curr_config:
            _web_config_debug += "Path: " + _curr_key + " directory: " + _curr_config["tools.staticdir.dir"]
        else:
            _web_config_debug += "Path: " + _curr_key + " - no static dir"

    write_to_log(_web_config_debug, _category=EC_SERVICE, _severity=SEV_INFO)
    plugins.call_hook("pre_webserver_start", web_config=web_config, globals=globals())
    cherrypy.quickstart(web_root, "/", web_config)
Ejemplo n.º 11
0
    @cherrypy.expose
    def default(self):
        pass


class WebSocketChecker(WebSocketTool):
    def __init__(self):
        cherrypy.Tool.__init__(self, "before_handler", self.upgrade)

    def upgrade(self, **kwargs):
        try:
            kwargs["handler_cls"].check_authentication()
        except:
            raise cherrypy.HTTPError(401, "You must be logged in to establish a websocket connection.")
        else:
            return WebSocketTool.upgrade(self, **kwargs)


cherrypy.tools.websockets = WebSocketChecker()

websocket_plugin = WebSocketPlugin(cherrypy.engine)
websocket_plugin.subscribe()

broadcaster = Caller(WebSocketDispatcher.broadcast)
responder = Caller(WebSocketDispatcher.handle_message, threads=config['ws_thread_pool'])

cherrypy.engine.subscribe("stop", WebSocketDispatcher.close_all)
for _task in [broadcaster, responder]:
    cherrypy.engine.subscribe("start", _task.start, priority=99)
    cherrypy.engine.subscribe("stop", _task.stop)
Ejemplo n.º 12
0
class SpyDashServer(object):
    """
    Server class for the SpyDash

    This class encapsulates all the functionality for the SpyDash server.
    It loads available modules and handles communication over Websockets
    """
    def __init__(self):
        """
        Find and load modules in the modules package
        """
        self.wsplugin = None
        self.worker = set()
        pluginmanager.load_configs()

    def start(self):
        """
        Start the server. This blocks
        """

        # Setting up plugins
        pluginmanager.load_models()
        pluginmanager.load_plugin_roots(self)
        create_tables()

        self.wsplugin = WebSocketPlugin(cherrypy.engine)
        self.wsplugin.subscribe()
        cherrypy.tools.websocket = WebSocketTool()

        # cherrypy.config.update({"log.access_file": "access.log",
        #                         "log.error_file": "error.log"})

        cherrypy.engine.subscribe("receive", self.receive)

        self.start_updater()

        config = {"/ws": {"tools.websocket.on": True, "tools.websocket.handler_cls": WebSocketHandler}}
        cherrypy.quickstart(self, "/", config=config)

    def broadcast(self, data, module):
        """
        Broadcast a message to all connected clients
        :param data: Data to broadcast
        :param module: reference to the calling module
        """
        try:
            label = pluginmanager.get_containing_pluginconfig(module).label
        except AttributeError:
            return
        msg = {"module": label, "data": data}
        try:
            msg = json.dumps(msg, ensure_ascii=False)
        except TypeError:
            return
        self.wsplugin.broadcast(msg)

    def start_updater(self):
        def predicate(x):
            try:
                return x.updater
            except (TypeError, AttributeError):
                return False

        for plugin in pluginmanager.get_instances():
            try:
                for name, method in inspect.getmembers(plugin, predicate):
                    worker = BackgroundTask(method.interval, method)
                    self.worker.add(worker)
                    worker.start()
            except (TypeError, AttributeError, StopIteration):
                pass

    def cancel_updater(self, functions):
        """
        Cancel given updater functions or function
        :param functions: The updater functions to cancel, this can either be a set of functions to cancel or a singel function
        """
        try:
            workers = [worker for worker in self.worker if worker.function in functions]
        except TypeError:
            workers = [worker for worker in self.worker if worker.function == functions]
        for worker in workers:
            worker.cancel()

    def receive(self, client, message):
        try:
            payload = json.loads(str(message))
            plugin_name = payload["module"]
            command = payload["command"]
            if plugin_name == "system":
                attribute = getattr(self, command)
            else:
                plugin = pluginmanager.get_plugin_for_label(plugin_name)
                attribute = getattr(plugin, command)
            if attribute.socketexposed is True:
                try:
                    answer = attribute(**payload["data"])
                except (KeyError, TypeError):
                    answer = attribute()
                if answer is not None:
                    msg = json.dumps({"module": plugin_name, "data": answer}, ensure_ascii=False)
                    client.send(msg)
        except (json.JSONDecodeError, TypeError, AttributeError, KeyError):
            return

    @socketexpose
    def get_modules(self):
        response = [name for name in pluginmanager.get_labels()]
        return response

    def _cp_dispatch(self, vpath):
        path = deque(vpath)
        modulename = path.popleft()
        module = pluginmanager.get_plugin_for_label(modulename)
        if module is not None:
            return module
        else:
            return vpath

    @cherrypy.expose
    def index(self):
        return "HI"

    @cherrypy.expose
    def ws(self):
        pass
Ejemplo n.º 13
0
class ZuulWeb(object):
    log = logging.getLogger("zuul.web.ZuulWeb")

    def __init__(self, listen_address, listen_port,
                 gear_server, gear_port,
                 ssl_key=None, ssl_cert=None, ssl_ca=None,
                 static_cache_expiry=3600,
                 connections=None,
                 info=None,
                 static_path=None,
                 zk_hosts=None):
        self.start_time = time.time()
        self.listen_address = listen_address
        self.listen_port = listen_port
        self.event_loop = None
        self.term = None
        self.server = None
        self.static_cache_expiry = static_cache_expiry
        self.info = info
        self.static_path = os.path.abspath(static_path or STATIC_DIR)
        # instanciate handlers
        self.rpc = zuul.rpcclient.RPCClient(gear_server, gear_port,
                                            ssl_key, ssl_cert, ssl_ca)
        self.zk = zuul.zk.ZooKeeper()
        if zk_hosts:
            self.zk.connect(hosts=zk_hosts, read_only=True)
        self.connections = connections
        self.stream_manager = StreamManager()

        route_map = cherrypy.dispatch.RoutesDispatcher()
        api = ZuulWebAPI(self)
        route_map.connect('api', '/api',
                          controller=api, action='index')
        route_map.connect('api', '/api/info',
                          controller=api, action='info')
        route_map.connect('api', '/api/connections',
                          controller=api, action='connections')
        route_map.connect('api', '/api/tenants',
                          controller=api, action='tenants')
        route_map.connect('api', '/api/tenant/{tenant}/info',
                          controller=api, action='tenant_info')
        route_map.connect('api', '/api/tenant/{tenant}/status',
                          controller=api, action='status')
        route_map.connect('api', '/api/tenant/{tenant}/status/change/{change}',
                          controller=api, action='status_change')
        route_map.connect('api', '/api/tenant/{tenant}/jobs',
                          controller=api, action='jobs')
        route_map.connect('api', '/api/tenant/{tenant}/job/{job_name}',
                          controller=api, action='job')
        route_map.connect('api', '/api/tenant/{tenant}/projects',
                          controller=api, action='projects')
        route_map.connect('api', '/api/tenant/{tenant}/project/{project:.*}',
                          controller=api, action='project')
        route_map.connect(
            'api',
            '/api/tenant/{tenant}/pipeline/{pipeline}'
            '/project/{project:.*}/branch/{branch:.*}/freeze-jobs',
            controller=api, action='project_freeze_jobs'
        )
        route_map.connect('api', '/api/tenant/{tenant}/pipelines',
                          controller=api, action='pipelines')
        route_map.connect('api', '/api/tenant/{tenant}/labels',
                          controller=api, action='labels')
        route_map.connect('api', '/api/tenant/{tenant}/nodes',
                          controller=api, action='nodes')
        route_map.connect('api', '/api/tenant/{tenant}/key/{project:.*}.pub',
                          controller=api, action='key')
        route_map.connect('api', '/api/tenant/{tenant}/'
                          'project-ssh-key/{project:.*}.pub',
                          controller=api, action='project_ssh_key')
        route_map.connect('api', '/api/tenant/{tenant}/console-stream',
                          controller=api, action='console_stream')
        route_map.connect('api', '/api/tenant/{tenant}/builds',
                          controller=api, action='builds')
        route_map.connect('api', '/api/tenant/{tenant}/build/{uuid}',
                          controller=api, action='build')
        route_map.connect('api', '/api/tenant/{tenant}/buildsets',
                          controller=api, action='buildsets')
        route_map.connect('api', '/api/tenant/{tenant}/buildset/{uuid}',
                          controller=api, action='buildset')
        route_map.connect('api', '/api/tenant/{tenant}/config-errors',
                          controller=api, action='config_errors')

        for connection in connections.connections.values():
            controller = connection.getWebController(self)
            if controller:
                cherrypy.tree.mount(
                    controller,
                    '/api/connection/%s' % connection.connection_name)

        # Add fallthrough routes at the end for the static html/js files
        route_map.connect(
            'root_static', '/{path:.*}',
            controller=StaticHandler(self.static_path),
            action='default')

        conf = {
            '/': {
                'request.dispatch': route_map
            }
        }
        cherrypy.config.update({
            'global': {
                'environment': 'production',
                'server.socket_host': listen_address,
                'server.socket_port': int(listen_port),
            },
        })

        cherrypy.tree.mount(api, '/', config=conf)

    @property
    def port(self):
        return cherrypy.server.bound_addr[1]

    def start(self):
        self.log.debug("ZuulWeb starting")
        self.stream_manager.start()
        self.wsplugin = WebSocketPlugin(cherrypy.engine)
        self.wsplugin.subscribe()
        cherrypy.engine.start()

    def stop(self):
        self.log.debug("ZuulWeb stopping")
        self.rpc.shutdown()
        cherrypy.engine.exit()
        # Not strictly necessary, but without this, if the server is
        # started again (e.g., in the unit tests) it will reuse the
        # same host/port settings.
        cherrypy.server.httpserver = None
        self.wsplugin.unsubscribe()
        self.stream_manager.stop()
        self.zk.disconnect()
Ejemplo n.º 14
0
class ZuulWeb(object):
    log = logging.getLogger("zuul.web.ZuulWeb")

    def __init__(
        self,
        listen_address,
        listen_port,
        gear_server,
        gear_port,
        ssl_key=None,
        ssl_cert=None,
        ssl_ca=None,
        static_cache_expiry=3600,
        connections=None,
        info=None,
        static_path=None,
        zk_hosts=None,
        authenticators=None,
        command_socket=None,
    ):
        self.start_time = time.time()
        self.listen_address = listen_address
        self.listen_port = listen_port
        self.event_loop = None
        self.term = None
        self.server = None
        self.static_cache_expiry = static_cache_expiry
        self.info = info
        self.static_path = os.path.abspath(static_path or STATIC_DIR)
        # instanciate handlers
        self.rpc = zuul.rpcclient.RPCClient(gear_server, gear_port, ssl_key,
                                            ssl_cert, ssl_ca)
        self.zk = zuul.zk.ZooKeeper()
        if zk_hosts:
            self.zk.connect(hosts=zk_hosts, read_only=True)
        self.connections = connections
        self.authenticators = authenticators
        self.stream_manager = StreamManager()

        self.command_socket = commandsocket.CommandSocket(command_socket)

        self.repl = None

        self.command_map = {
            'stop': self.stop,
            'repl': self.start_repl,
            'norepl': self.stop_repl,
        }

        route_map = cherrypy.dispatch.RoutesDispatcher()
        api = ZuulWebAPI(self)
        route_map.connect('api', '/api', controller=api, action='index')
        route_map.connect('api', '/api/info', controller=api, action='info')
        route_map.connect('api',
                          '/api/connections',
                          controller=api,
                          action='connections')
        route_map.connect('api',
                          '/api/tenants',
                          controller=api,
                          action='tenants')
        route_map.connect('api',
                          '/api/tenant/{tenant}/info',
                          controller=api,
                          action='tenant_info')
        route_map.connect('api',
                          '/api/tenant/{tenant}/status',
                          controller=api,
                          action='status')
        route_map.connect('api',
                          '/api/tenant/{tenant}/status/change/{change}',
                          controller=api,
                          action='status_change')
        route_map.connect('api',
                          '/api/tenant/{tenant}/jobs',
                          controller=api,
                          action='jobs')
        route_map.connect('api',
                          '/api/tenant/{tenant}/job/{job_name}',
                          controller=api,
                          action='job')
        # if no auth configured, deactivate admin routes
        if self.authenticators.authenticators:
            # route order is important, put project actions before the more
            # generic tenant/{tenant}/project/{project} route
            route_map.connect(
                'api',
                '/api/tenant/{tenant}/project/{project:.*}/autohold',
                controller=api,
                action='autohold')
            route_map.connect(
                'api',
                '/api/tenant/{tenant}/project/{project:.*}/enqueue',
                controller=api,
                action='enqueue')
            route_map.connect(
                'api',
                '/api/tenant/{tenant}/project/{project:.*}/dequeue',
                controller=api,
                action='dequeue')
        route_map.connect('api',
                          '/api/tenant/{tenant}/autohold',
                          controller=api,
                          action='autohold_list')
        route_map.connect('api',
                          '/api/tenant/{tenant}/projects',
                          controller=api,
                          action='projects')
        route_map.connect('api',
                          '/api/tenant/{tenant}/project/{project:.*}',
                          controller=api,
                          action='project')
        route_map.connect(
            'api', '/api/tenant/{tenant}/pipeline/{pipeline}'
            '/project/{project:.*}/branch/{branch:.*}/freeze-jobs',
            controller=api,
            action='project_freeze_jobs')
        route_map.connect('api',
                          '/api/tenant/{tenant}/pipelines',
                          controller=api,
                          action='pipelines')
        route_map.connect('api',
                          '/api/tenant/{tenant}/labels',
                          controller=api,
                          action='labels')
        route_map.connect('api',
                          '/api/tenant/{tenant}/nodes',
                          controller=api,
                          action='nodes')
        route_map.connect('api',
                          '/api/tenant/{tenant}/key/{project:.*}.pub',
                          controller=api,
                          action='key')
        route_map.connect('api', '/api/tenant/{tenant}/'
                          'project-ssh-key/{project:.*}.pub',
                          controller=api,
                          action='project_ssh_key')
        route_map.connect('api',
                          '/api/tenant/{tenant}/console-stream',
                          controller=api,
                          action='console_stream')
        route_map.connect('api',
                          '/api/tenant/{tenant}/builds',
                          controller=api,
                          action='builds')
        route_map.connect('api',
                          '/api/tenant/{tenant}/build/{uuid}',
                          controller=api,
                          action='build')
        route_map.connect('api',
                          '/api/tenant/{tenant}/buildsets',
                          controller=api,
                          action='buildsets')
        route_map.connect('api',
                          '/api/tenant/{tenant}/buildset/{uuid}',
                          controller=api,
                          action='buildset')
        route_map.connect('api',
                          '/api/tenant/{tenant}/config-errors',
                          controller=api,
                          action='config_errors')

        for connection in connections.connections.values():
            controller = connection.getWebController(self)
            if controller:
                cherrypy.tree.mount(
                    controller,
                    '/api/connection/%s' % connection.connection_name)

        # Add fallthrough routes at the end for the static html/js files
        route_map.connect('root_static',
                          '/{path:.*}',
                          controller=StaticHandler(self.static_path),
                          action='default')

        conf = {'/': {'request.dispatch': route_map}}
        cherrypy.config.update({
            'global': {
                'environment': 'production',
                'server.socket_host': listen_address,
                'server.socket_port': int(listen_port),
            },
        })

        cherrypy.tree.mount(api, '/', config=conf)

    @property
    def port(self):
        return cherrypy.server.bound_addr[1]

    def start(self):
        self.log.debug("ZuulWeb starting")
        self.stream_manager.start()
        self.wsplugin = WebSocketPlugin(cherrypy.engine)
        self.wsplugin.subscribe()
        cherrypy.engine.start()

        self.log.debug("Starting command processor")
        self._command_running = True
        self.command_socket.start()
        self.command_thread = threading.Thread(target=self.runCommand,
                                               name='command')
        self.command_thread.daemon = True
        self.command_thread.start()

    def stop(self):
        self.log.debug("ZuulWeb stopping")
        self.rpc.shutdown()
        cherrypy.engine.exit()
        # Not strictly necessary, but without this, if the server is
        # started again (e.g., in the unit tests) it will reuse the
        # same host/port settings.
        cherrypy.server.httpserver = None
        self.wsplugin.unsubscribe()
        self.stream_manager.stop()
        self.zk.disconnect()
        self.stop_repl()
        self._command_running = False
        self.command_socket.stop()
        self.command_thread.join()

    def runCommand(self):
        while self._command_running:
            try:
                command = self.command_socket.get().decode('utf8')
                if command != '_stop':
                    self.command_map[command]()
            except Exception:
                self.log.exception("Exception while processing command")

    def start_repl(self):
        if self.repl:
            return
        self.repl = zuul.lib.repl.REPLServer(self)
        self.repl.start()

    def stop_repl(self):
        if not self.repl:
            return
        self.repl.stop()
        self.repl = None
Ejemplo n.º 15
0
                                  ' - %(message)s')
    ch.setFormatter(formatter)
    interface_logger.addHandler(ch)

    # create the preset folder if it does not exist:
    preset_dir = os.path.abspath(args.presetdir)
    if (not os.path.isdir(preset_dir)):
        print("Preset folder {} did not exist, creating.".format(preset_dir))
        os.makedirs(preset_dir)

    # Add the websocket requirements.
    cherrypy.tools.websocket = WebSocketTool()

    a = WebSocketPlugin(cherrypy.engine)
    a.manager = WebSocketManager()
    a.subscribe()

    stack_interface = interface.StackInterface()
    stack_interface.daemon = True
    stack_interface.start()
    server_tree = FocusStackRoot(stack_interface, preset_dir=preset_dir)

    # create a broadcast function which relays messages received over the
    # serial port to the websockets via the websocketmanager.
    def broadcaster():
        m = stack_interface.get_message()
        if m:
            payload = dict(m)
            payload["msg_type"] = message.msg_type_name[payload["msg_type"]]
            msg = ["serial", payload]
            a.manager.broadcast(json.dumps(msg))