def test_pickle(mock_abc):
    # Create a controller, with a running job and some threads etc.
    conn = Controller()
    try:
        conn.machines = {"m": simple_machine("m", 1, 2)}
        job_id = conn.create_job(None, owner="me", keepalive=60.0)
        time.sleep(0.05)
        assert conn.get_job_state(None, job_id).state == JobState.ready

        assert mock_abc.running_theads == 2
    finally:
        # Pickling the controller should succeed
        conn.stop()
        conn.join()

    assert mock_abc.running_theads == 0

    pickled_conn = pickle.dumps(conn)
    del conn

    # Unpickling should succeed
    conn2 = pickle.loads(pickled_conn)
    try:

        # And some BMP connections should be running again
        assert mock_abc.running_theads == 2

        # And our job should still be there
        assert conn2.get_job_state(None, job_id).state == JobState.ready
    finally:
        conn2.stop()
        conn2.join()
Beispiel #2
0
def conn(mock_abc, on_background_state_change):
    """Auto-stop a controller."""
    conn = Controller(max_retired_jobs=2,
                      on_background_state_change=on_background_state_change)
    try:
        yield conn
    finally:
        conn.stop()
        conn.join()
Beispiel #3
0
    def __init__(self, config_filename, cold_start=False, port=22244):
        """
        :param config_filename: \
            The filename of the config file for the server which describes the\
            machines to be controlled.
        :type config_filename: str
        :param cold_start: \
            If False (the default), the server will attempt to restore its\
            previous state, if True, the server will start from scratch.
        :type cold_start: bool
        :param port: Which port to listen on. Defaults to 22244.
        :type port: int
        """
        # ============ STATE THAT NEEDS TO BE ALWAYS DEFINED ============

        self._cold_start = cold_start
        self._port = port

        # Should the background thread terminate?
        self._stop = False

        # Flag for checking if the server is still alive
        self._running = False

        # Currently open sockets to clients. Once server started, should only
        # be accessed from the server thread.
        self._server_socket = None

        # The server core object that the object that is persisted
        self._controller = None

        # Buffered data received from each socket
        # {fd: buf, ...}
        self._client_buffers = {}

        # ============ SUPERCLASS INITIALISATION ============

        PollingServerCore.__init__(self)
        ConfigurationReloader.__init__(self, config_filename, self.wake)

        # ============ ACTIVE OBJECTS ============

        # The background thread in which the server will run
        self._server_thread = Thread(target=self._run, name="Server Thread")

        # The current server configuration options. Once server started, should
        # only be accessed from the server thread.
        self._configuration = Configuration()

        # Infer the saved-state location
        self._state_filename = self._get_state_filename(
            self.configuration_file)

        # Attempt to restore saved state if required
        if not self._cold_start and path.isfile(self._state_filename):
            try:
                with open(self._state_filename, "rb") as f:
                    self._controller = unpickle(f)
                log.info("Server warm-starting from %s.", self._state_filename)
            except Exception:
                # Some other error occurred during unpickling.
                log.exception("Server state could not be unpacked from %s.",
                              self._state_filename)
                self._controller = None

        # Perform cold-start if no saved state was loaded
        if self._controller is None:
            log.info("Server cold-starting.")
            self._controller = Controller()

        # Notify the background thread when something changes in the background
        # of the controller (e.g. power state changes).
        self._controller.on_background_state_change = self.wake

        # Read configuration file. This must succeed when the server is first
        # being started.
        if not self.read_config_file():
            self._controller.stop()
            raise Exception("Config file could not be loaded.")

        # Start the server
        self._server_thread.start()
        self._running = True