Exemple #1
0
 def start_web_api(self):
     host = self._config.web.host
     port = self._config.web.port
     if self._web_api:
         logging.info("Shutting down web API")
         self._web_api.quit()
         self._web_api.join(3)
         if self._web_api.is_alive():
             logging.error(
                 "Failed to shut down the web API. Reload failed.")
     logging.info("Starting web API at http://{}:{}".format(host, port))
     self._web_api = WebApi(self, host, port)
     self._web_api.start()
Exemple #2
0
 def start_web_api(self):
     host = self._config.web.host
     port = self._config.web.port
     if self._web_api:
         logging.info("Shutting down web API")
         self._web_api.quit()
         self._web_api.join(3)
         if self._web_api.is_alive():
             logging.error("Failed to shut down the web API. Reload failed.")
     logging.info("Starting web API at http://{}:{}".format(host, port))
     self._web_api = WebApi(self, host, port)
     self._web_api.start()
 def setUp(self):
     self._server = Server()
     self._web_api = WebApi(self._server, port=8457)
     self._server.start()
     self._web_api.start()
     self._web_api.wait_ready()
class TestWebApi(unittest.TestCase):
    @property
    def _base_url(self):
        return "http://*****:*****@koloman.net>",
            "to": ["Martin Hammerschmied <*****@*****.**>"],
            "mime_type":
            "text/html",
            "subject":
            "{title} for {price}",
            "body":
            "I found a new ad ({datetime}):<br/><br/>\n<b>{title}</b><br/>\nfor € <b>{price}</b><br/><br/>\n<a href=\"{url}\">{url}</a><br/><br/>\nbye!"
        }
        notification_data_encoded = self._encode_object(notification_data)
        self._api_call("/api/observer/MyObserver/notification", "POST",
                       notification_data_encoded)
        notification = next(iter(observer.notifications))
        self.assertEqual(notification._host, smtp_settings["host"])
        self.assertEqual(notification._port, smtp_settings["port"])
        self.assertEqual(notification._user, smtp_settings["user"])
        self.assertEqual(notification._pwd, smtp_settings["pwd"])

    def test_commands_pause_resume_observer(self):
        observer = MockObserver("MyObserver")
        self._server.add_observer(observer)
        observer.state = Observer.RUNNING
        self._api_call("/api/observer/MyObserver/pause", "PUT")
        self.assertEqual(observer.state, Observer.PAUSED)
        self._api_call("/api/observer/MyObserver/resume", "PUT")
        self.assertEqual(observer.state, Observer.RUNNING)

    def test_command_observer_state(self):
        observer = MockObserver("MyObserver")
        self._server.add_observer(observer)
        observer.state = Observer.RUNNING
        data = self._api_call("/api/observer/MyObserver/state", "GET")
        self.assertDictEqual(data, {"state": "RUNNING"})
        observer.state = Observer.PAUSED
        data = self._api_call("/api/observer/MyObserver/state", "GET")
        self.assertDictEqual(data, {"state": "PAUSED"})

    def test_command_remove_observer(self):
        observer = MockObserver("MyObserver")
        self._server.add_observer(observer)
        self.assertIsInstance(self._server["MyObserver"], MockObserver)
        self._api_call("/api/observer/MyObserver", "DELETE")
        self.assertRaises(KeyError, lambda: self._server["MyObserver"])

    def test_command_list_commands(self):
        data = self._api_call("/api/list/commands", "GET")
        self.assertIsInstance(data, dict)
        self.assertIn("commands", data)
        self.assertGreater(len(data["commands"]), 0)
        for cmd in data["commands"]:
            self.assertIsInstance(cmd, str)

    def test_static_route(self):
        import tempfile, os.path
        root = tempfile.gettempdir()
        filepath = tempfile.mktemp()
        file = os.path.basename(filepath)
        content = "This is not the file you are looking for..."
        rel_url = "/showmethefile"
        url = "{}{}/{}".format(self._base_url, rel_url, file)
        with open(filepath, "w") as f:
            f.write(content)
        self._web_api.register_static_directory(root, rel_url)
        with urllib.request.urlopen(url) as f:
            content_get = f.read().decode("utf-8")
        self.assertEqual(content, content_get)
Exemple #5
0
class Server(Thread):
    
    def __init__(self):
        super(Server, self).__init__()
        self._config = self._create_config()
        self._observers = list()
        self._command_queue = Queue()
        self._quit = False
        self._web_api = None
        self.name = "Server"

    def _create_config(self):
        """
        These are all available config values. The configuration is fixed. New values can not be added afterwards.
        """
        return Config({
            'smtp': {
                'host': None,
                'port': None,
                'auth': True,
                'user': None,
                'pwd': None
            },
            'web': {
                'host': 'localhost',
                'port': 8118
            }
        }, fixed=True)

    def add_observer(self, observer):
        if (observer.name in [other.name for other in self._observers]):
            logging.info("Replacing observer '{}' on server".format(observer.name))
            self.remove_observer(observer.name)
        else:
            logging.info("Adding observer '{}' to server".format(observer.name))
            
        self._observers.append(observer)
        observer.start()
    
    def remove_observer(self, name):
        try:
            observer = next(observer for observer in self._observers if observer.name == name)
            observer.quit()
            self._observers.remove(observer)
        except StopIteration:
            raise ServerError("No observer with the name of '{}'".format(name))

    def observers(self):
        observer_names = [obs.name for obs in self._observers]
        return observer_names

    def enqueue_command(self, command):
        self._command_queue.put_nowait(command)

    def start_web_api(self):
        host = self._config.web.host
        port = self._config.web.port
        if self._web_api:
            logging.info("Shutting down web API")
            self._web_api.quit()
            self._web_api.join(3)
            if self._web_api.is_alive():
                logging.error("Failed to shut down the web API. Reload failed.")
        logging.info("Starting web API at http://{}:{}".format(host, port))
        self._web_api = WebApi(self, host, port)
        self._web_api.start()

    def register_client(self, client_root, default_file="index.html"):
        if not self._web_api:
            raise ServerError("Web API must be started before a client can be registered")
        self._web_api.register_static_directory(client_root, "", default_file)

    def run(self):
        """
        run() is called after everything is set up. It just waits for commands
        to come in and executes them. Usually commands are put into the queue
        by CommandApis like the WebApi or a JsonScript.
        """
        while True:

            # spin the queue. checking for a quit signal every second
            while True:
                if self._quit:
                    self._shutdown()
                    return
                try:
                    command = self._command_queue.get(block=True, timeout=1)
                    break   # received command!
                except Empty:
                    pass

            # process the command
            command.server = self
            command.condition.acquire()
            try:
                command.response = self._process_command(command)
                command.condition.notify_all()
            finally:
                command.condition.release()

    def quit(self):
        self._quit = True
    
    def __getitem__(self, key):
        if type(key) is not str:
            raise TypeError("The key must be a string containing the observer name.")
        try:
            return next(observer for observer in self._observers if observer.name == key)
        except StopIteration:
            raise KeyError("Observer '{}' not found".format(key))
    
    def __iter__(self):
        return self._observers.__iter__()
    
    def _process_command(self, command):
        try:
            logging.info("Processing command '{}'".format(command.name))
            logging.debug("Command info: {}".format(command._cmd_info))
            response = command.execute()
            response_message = {"status": "OK"}
            response_message["response"] = response
            return response_message
        except (ServerError, CommandError) as ex:
            args_text = "; ".join(["{}".format(arg) for arg in ex.args])
            return {"status": "ERROR", "message": args_text}

    def _shutdown(self):
        logging.info("Shutting down all services")
        if self._web_api:
            self._web_api.quit()
        for observer in self._observers:
            observer.quit()
        if self._web_api:
            self._web_api.join(timeout=3)
            if self._web_api.is_alive():
                logging.warning("Timeout while waiting for web API to shut down")
            else:
                logging.info("Web API successfully shut down")
        for observer in self._observers:
            observer.join(timeout=3)
            if observer.is_alive():
                logging.warning("Timeout while waiting for observer '{}' to shut down".format(observer.name))
            else:
                logging.info("Observer '{}' successfully shut down".format(observer.name))

    @property
    def config(self):
        return self._config
    
    @property
    def command_queue(self):
        return self._command_queue
        
 def setUp(self):
     self._server = Server()
     self._web_api = WebApi(self._server, port=8457)
     self._server.start()
     self._web_api.start()
     self._web_api.wait_ready()
class TestWebApi(unittest.TestCase):

    @property
    def _base_url(self):
        return "http://*****:*****@koloman.net>",
                             "to": [ "Martin Hammerschmied <*****@*****.**>" ],
                             "mime_type": "text/html",
                             "subject": "{title} for {price}",
                             "body": "I found a new ad ({datetime}):<br/><br/>\n<b>{title}</b><br/>\nfor € <b>{price}</b><br/><br/>\n<a href=\"{url}\">{url}</a><br/><br/>\nbye!"
        }
        notification_data_encoded = self._encode_object(notification_data)
        self._api_call("/api/observer/MyObserver/notification", "POST", notification_data_encoded)
        notification = next(iter(observer.notifications))
        self.assertEqual(notification._host, smtp_settings["host"])
        self.assertEqual(notification._port, smtp_settings["port"])
        self.assertEqual(notification._user, smtp_settings["user"])
        self.assertEqual(notification._pwd, smtp_settings["pwd"])

    def test_commands_pause_resume_observer(self):
        observer = MockObserver("MyObserver")
        self._server.add_observer(observer)
        observer.state = Observer.RUNNING
        self._api_call("/api/observer/MyObserver/pause", "PUT")
        self.assertEqual(observer.state, Observer.PAUSED)
        self._api_call("/api/observer/MyObserver/resume", "PUT")
        self.assertEqual(observer.state, Observer.RUNNING)

    def test_command_observer_state(self):
        observer = MockObserver("MyObserver")
        self._server.add_observer(observer)
        observer.state = Observer.RUNNING
        data = self._api_call("/api/observer/MyObserver/state", "GET")
        self.assertDictEqual(data, {"state": "RUNNING"})
        observer.state = Observer.PAUSED
        data = self._api_call("/api/observer/MyObserver/state", "GET")
        self.assertDictEqual(data, {"state": "PAUSED"})

    def test_command_remove_observer(self):
        observer = MockObserver("MyObserver")
        self._server.add_observer(observer)
        self.assertIsInstance(self._server["MyObserver"], MockObserver)
        self._api_call("/api/observer/MyObserver", "DELETE")
        self.assertRaises(KeyError, lambda: self._server["MyObserver"])

    def test_command_list_commands(self):
        data = self._api_call("/api/list/commands", "GET")
        self.assertIsInstance(data, dict)
        self.assertIn("commands", data)
        self.assertGreater(len(data["commands"]), 0)
        for cmd in data["commands"]:
            self.assertIsInstance(cmd, str)

    def test_static_route(self):
        import tempfile, os.path
        root = tempfile.gettempdir()
        filepath = tempfile.mktemp()
        file = os.path.basename(filepath)
        content = "This is not the file you are looking for..."
        rel_url = "/showmethefile"
        url = "{}{}/{}".format(self._base_url, rel_url, file)
        with open(filepath, "w") as f:
            f.write(content)
        self._web_api.register_static_directory(root, rel_url)
        with urllib.request.urlopen(url) as f:
            content_get = f.read().decode("utf-8")
        self.assertEqual(content, content_get)
Exemple #8
0
class Server(Thread):
    def __init__(self):
        super(Server, self).__init__()
        self._config = self._create_config()
        self._observers = list()
        self._command_queue = Queue()
        self._quit = False
        self._web_api = None
        self.name = "Server"

    def _create_config(self):
        """
        These are all available config values. The configuration is fixed. New values can not be added afterwards.
        """
        return Config(
            {
                'smtp': {
                    'host': None,
                    'port': None,
                    'auth': True,
                    'user': None,
                    'pwd': None
                },
                'web': {
                    'host': 'localhost',
                    'port': 8118
                }
            },
            fixed=True)

    def add_observer(self, observer):
        if (observer.name in [other.name for other in self._observers]):
            logging.info("Replacing observer '{}' on server".format(
                observer.name))
            self.remove_observer(observer.name)
        else:
            logging.info("Adding observer '{}' to server".format(
                observer.name))

        self._observers.append(observer)
        observer.start()

    def remove_observer(self, name):
        try:
            observer = next(observer for observer in self._observers
                            if observer.name == name)
            observer.quit()
            self._observers.remove(observer)
        except StopIteration:
            raise ServerError("No observer with the name of '{}'".format(name))

    def observers(self):
        observer_names = [obs.name for obs in self._observers]
        return observer_names

    def enqueue_command(self, command):
        self._command_queue.put_nowait(command)

    def start_web_api(self):
        host = self._config.web.host
        port = self._config.web.port
        if self._web_api:
            logging.info("Shutting down web API")
            self._web_api.quit()
            self._web_api.join(3)
            if self._web_api.is_alive():
                logging.error(
                    "Failed to shut down the web API. Reload failed.")
        logging.info("Starting web API at http://{}:{}".format(host, port))
        self._web_api = WebApi(self, host, port)
        self._web_api.start()

    def register_client(self, client_root, default_file="index.html"):
        if not self._web_api:
            raise ServerError(
                "Web API must be started before a client can be registered")
        self._web_api.register_static_directory(client_root, "", default_file)

    def run(self):
        """
        run() is called after everything is set up. It just waits for commands
        to come in and executes them. Usually commands are put into the queue
        by CommandApis like the WebApi or a JsonScript.
        """
        while True:

            # spin the queue. checking for a quit signal every second
            while True:
                if self._quit:
                    self._shutdown()
                    return
                try:
                    command = self._command_queue.get(block=True, timeout=1)
                    break  # received command!
                except Empty:
                    pass

            # process the command
            command.server = self
            command.condition.acquire()
            try:
                command.response = self._process_command(command)
                command.condition.notify_all()
            finally:
                command.condition.release()

    def quit(self):
        self._quit = True

    def __getitem__(self, key):
        if type(key) is not str:
            raise TypeError(
                "The key must be a string containing the observer name.")
        try:
            return next(observer for observer in self._observers
                        if observer.name == key)
        except StopIteration:
            raise KeyError("Observer '{}' not found".format(key))

    def __iter__(self):
        return self._observers.__iter__()

    def _process_command(self, command):
        try:
            logging.info("Processing command '{}'".format(command.name))
            logging.debug("Command info: {}".format(command._cmd_info))
            response = command.execute()
            response_message = {"status": "OK"}
            response_message["response"] = response
            return response_message
        except (ServerError, CommandError) as ex:
            args_text = "; ".join(["{}".format(arg) for arg in ex.args])
            return {"status": "ERROR", "message": args_text}

    def _shutdown(self):
        logging.info("Shutting down all services")
        if self._web_api:
            self._web_api.quit()
        for observer in self._observers:
            observer.quit()
        if self._web_api:
            self._web_api.join(timeout=3)
            if self._web_api.is_alive():
                logging.warning(
                    "Timeout while waiting for web API to shut down")
            else:
                logging.info("Web API successfully shut down")
        for observer in self._observers:
            observer.join(timeout=3)
            if observer.is_alive():
                logging.warning(
                    "Timeout while waiting for observer '{}' to shut down".
                    format(observer.name))
            else:
                logging.info("Observer '{}' successfully shut down".format(
                    observer.name))

    @property
    def config(self):
        return self._config

    @property
    def command_queue(self):
        return self._command_queue