Example #1
0
 def setUp(self):
     self.ctx = SessionDeviceContext()
     self.provider = mock.Mock(name='provider', spec_set=Provider1)
     self.unit = mock.Mock(name='unit', spec_set=UnitWithId)
     self.unit.provider = self.provider
     self.provider.unit_list = [self.unit]
     self.provider.problem_list = []
     self.job = mock.Mock(name='job', spec_set=JobDefinition, siblings=None)
     self.job.get_flag_set = mock.Mock(return_value=())
     self.job.Meta.name = 'job'
Example #2
0
    def create_with_state(cls, state, repo=None, legacy_mode=False):
        """
        Create a session manager by wrapping existing session state.

        This method populates the session storage with all of the well known
        directories (using :meth:`WellKnownDirsHelper.populate()`)

        :param stage:
            A pre-existing SessionState object.
        :param repo:
            If specified then this particular repository will be used to create
            the storage for this session. If left out, a new repository is
            constructed with the default location.
        :ptype repo:
            :class:`~plainbox.impl.session.storage.SessionStorageRepository`.
        :param legacy_mode:
            Propagated to
            :meth:`~plainbox.impl.session.storage.SessionStorage.create()`
            to ensure that legacy (single session) mode is used.
        :ptype legacy_mode:
            bool
        :return:
            fresh :class:`SessionManager` instance
        """
        logger.debug("SessionManager.create_with_state()")
        if repo is None:
            repo = SessionStorageRepository()
        storage = SessionStorage.create(repo.location, legacy_mode)
        WellKnownDirsHelper(storage).populate()
        context = SessionDeviceContext(state)
        return cls([context], storage)
    def create_with_unit_list(cls, unit_list=None, repo=None):
        """
        Create a session manager with a fresh session.

        This method populates the session storage with all of the well known
        directories (using :meth:`WellKnownDirsHelper.populate()`)

        :param unit_list:
            If specified then this will be the initial list of units known by
            the session state object.
        :param repo:
            If specified then this particular repository will be used to create
            the storage for this session. If left out, a new repository is
            constructed with the default location.
        :ptype repo:
            :class:`~plainbox.impl.session.storage.SessionStorageRepository`.
        :return:
            fresh :class:`SessionManager` instance
        """
        logger.debug("SessionManager.create_with_unit_list()")
        if unit_list is None:
            unit_list = []
        state = SessionState(unit_list)
        if repo is None:
            repo = SessionStorageRepository()
        storage = SessionStorage.create(repo.location)
        context = SessionDeviceContext(state)
        WellKnownDirsHelper(storage).populate()
        return cls([context], storage)
Example #4
0
    def add_local_device_context(self):
        """
        Create and add a SessionDeviceContext that describes the local device.

        The local device is always the device executing plainbox. Other devices
        may execute jobs or parts of plainbox but they don't need to store or
        run the full plainbox code.
        """
        return self.add_device_context(SessionDeviceContext())
Example #5
0
    def load_session(cls, unit_list, storage, early_cb=None, flags=None):
        """
        Load a previously checkpointed session.

        This method allows one to re-open a session that was previously
        created by :meth:`SessionManager.checkpoint()`

        :param unit_list:
            List of all known units. This argument is used to reconstruct the
            session from a dormant state. Since the suspended data cannot
            capture implementation details of each unit reliably, actual units
            need to be provided externally. Unlike in :meth:`create_session()`
            this list really needs to be complete, it must also include any
            generated units.
        :param storage:
            The storage that should be used for this particular session.
            The storage object holds references to existing directories
            in the file system. When restoring an existing dormant session
            it is important to use the correct storage object, the one that
            corresponds to the file system location used be the session
            before it was saved.
        :ptype storage:
            :class:`~plainbox.impl.session.storage.SessionStorage`
        :param early_cb:
            A callback that allows the caller to "see" the session object
            early, before the bulk of resume operation happens. This method can
            be used to register callbacks on the new session before this method
            call returns. The callback accepts one argument, session, which is
            being resumed. This is being passed directly to
            :meth:`plainbox.impl.session.resume.SessionResumeHelper.resume()`
        :param flags:
            An optional set of flags that may influence the resume process.
            Currently this is an internal implementation detail and no "public"
            flags are provided. Passing None here is a safe equvalent of using
            this API before it was introduced.
        :raises:
            Anything that can be raised by
            :meth:`~plainbox.impl.session.storage.SessionStorage.
            load_checkpoint()` and :meth:`~plainbox.impl.session.suspend.
            SessionResumeHelper.resume()`
        :returns:
            Fresh instance of :class:`SessionManager`
        """
        logger.debug("SessionManager.load_session()")
        try:
            data = storage.load_checkpoint()
        except IOError as exc:
            if exc.errno == errno.ENOENT:
                state = SessionState(unit_list)
            else:
                raise
        else:
            state = SessionResumeHelper(unit_list, flags,
                                        storage.location).resume(
                                            data, early_cb)
        context = SessionDeviceContext(state)
        return cls([context], storage)
Example #6
0
    def create_with_state(cls, state):
        """
        Create a session manager by wrapping existing session state.

        This method populates the session storage with all of the well known
        directories (using :meth:`WellKnownDirsHelper.populate()`)

        :param stage:
            A pre-existing SessionState object.
        :return:
            fresh :class:`SessionManager` instance
        """
        logger.debug("SessionManager.create_with_state()")
        storage = SessionStorage.create()
        context = SessionDeviceContext(state)
        return cls([context], storage)
Example #7
0
    def create_with_unit_list(cls, unit_list=None):
        """
        Create a session manager with a fresh session.

        This method populates the session storage with all of the well known
        directories (using :meth:`WellKnownDirsHelper.populate()`)

        :param unit_list:
            If specified then this will be the initial list of units known by
            the session state object.
        :return:
            fresh :class:`SessionManager` instance
        """
        logger.debug("SessionManager.create_with_unit_list()")
        if unit_list is None:
            unit_list = []
        state = SessionState(unit_list)
        storage = SessionStorage.create()
        context = SessionDeviceContext(state)
        return cls([context], storage)
Example #8
0
class SessionDeviceContextTests(SignalTestCase):
    def setUp(self):
        self.ctx = SessionDeviceContext()
        self.provider = mock.Mock(name='provider', spec_set=Provider1)
        self.unit = mock.Mock(name='unit', spec_set=UnitWithId)
        self.unit.provider = self.provider
        self.provider.unit_list = [self.unit]
        self.provider.problem_list = []
        self.job = mock.Mock(name='job', spec_set=JobDefinition, siblings=None)
        self.job.get_flag_set = mock.Mock(return_value=())
        self.job.Meta.name = 'job'

    def test_smoke(self):
        """
        Ensure that you can create a session device context and that
        default values are what we expect
        """
        self.assertIsNone(self.ctx.device)
        self.assertIsInstance(self.ctx.state, SessionState)
        self.assertEqual(self.ctx.provider_list, [])
        self.assertEqual(self.ctx.unit_list, [])

    def test_add_provider(self):
        """
        Ensure that adding a provider works
        """
        self.ctx.add_provider(self.provider)
        self.assertIn(self.provider, self.ctx.provider_list)

    def test_add_provider_twice(self):
        """
        Ensure that you cannot add a provider twice
        """
        self.ctx.add_provider(self.provider)
        with self.assertRaises(ValueError):
            self.ctx.add_provider(self.provider)

    def test_add_provider__adds_units(self):
        """
        Ensure that adding a provider adds the unit it knows about
        """
        self.ctx.add_provider(self.provider)
        self.assertIn(self.unit, self.ctx.unit_list)

    def test_add_unit(self):
        """
        Ensure that adding an unit works
        """
        self.ctx.add_unit(self.unit)
        self.assertIn(self.unit, self.ctx.unit_list)
        self.assertIn(self.unit, self.ctx.state.unit_list)

    def test_add_unit__job_unit(self):
        """
        Ensure that adding a job unit works
        """
        self.ctx.add_unit(self.job)
        self.assertIn(self.job, self.ctx.unit_list)
        self.assertIn(self.job, self.ctx.state.unit_list)
        self.assertIn(self.job, self.ctx.state.job_list)

    def test_add_unit_twice(self):
        """
        Ensure that you cannot add an unit twice
        """
        self.ctx.add_unit(self.unit)
        with self.assertRaises(ValueError):
            self.ctx.add_unit(self.unit)

    def test_remove_unit(self):
        """
        Ensure that removing an unit works
        """
        self.ctx.add_unit(self.unit)
        self.ctx.remove_unit(self.unit)
        self.assertNotIn(self.unit, self.ctx.unit_list)
        self.assertNotIn(self.unit, self.ctx.state.unit_list)

    def test_remove_unit__missing(self):
        """
        Ensure that you cannot remove an unit that is not added first
        """
        with self.assertRaises(ValueError):
            self.ctx.remove_unit(self.unit)

    def test_remove_job_unit(self):
        """
        Ensure that removing a job unit works
        """
        self.ctx.add_unit(self.job)
        self.ctx.remove_unit(self.job)
        self.assertNotIn(self.job, self.ctx.unit_list)
        self.assertNotIn(self.job, self.ctx.state.unit_list)
        self.assertNotIn(self.job, self.ctx.state.job_list)
        self.assertNotIn(self.job.id, self.ctx.state.job_state_map)
        self.assertNotIn(self.job.id, self.ctx.state.resource_map)

    def test_on_unit_added__via_ctx(self):
        """
        Ensure that adding units produces same/correct signals
        regardless of how that unit is added. This test checks the scenario
        that happens when the context is used directly
        """
        self.watchSignal(self.ctx.on_unit_added)
        self.watchSignal(self.ctx.state.on_unit_added)
        self.watchSignal(self.ctx.state.on_job_added)
        self.ctx.add_unit(self.unit)
        sig1 = self.assertSignalFired(self.ctx.on_unit_added, self.unit)
        sig2 = self.assertSignalFired(self.ctx.state.on_unit_added, self.unit)
        self.assertSignalOrdering(sig1, sig2)
        self.assertSignalNotFired(self.ctx.state.on_job_added, self.unit)

    def test_on_unit_added__via_state(self):
        """
        Ensure that adding units produces same/correct signals
        regardless of how that unit is added. This test checks the scenario
        that happens when the session state is used.
        """
        self.watchSignal(self.ctx.on_unit_added)
        self.watchSignal(self.ctx.state.on_unit_added)
        self.watchSignal(self.ctx.state.on_job_added)
        self.ctx.state.add_unit(self.unit)
        sig1 = self.assertSignalFired(self.ctx.on_unit_added, self.unit)
        sig2 = self.assertSignalFired(self.ctx.state.on_unit_added, self.unit)
        self.assertSignalOrdering(sig1, sig2)
        self.assertSignalNotFired(self.ctx.state.on_job_added, self.unit)

    def test_on_job_added__via_ctx(self):
        """
        Ensure that adding job units produces same/correct signals
        regardless of how that job is added. This test checks the scenario
        that happens when the context is used directly
        """
        self.watchSignal(self.ctx.on_unit_added)
        self.watchSignal(self.ctx.state.on_unit_added)
        self.watchSignal(self.ctx.state.on_job_added)
        self.ctx.add_unit(self.job)
        sig1 = self.assertSignalFired(self.ctx.on_unit_added, self.job)
        sig2 = self.assertSignalFired(self.ctx.state.on_unit_added, self.job)
        sig3 = self.assertSignalFired(self.ctx.state.on_job_added, self.job)
        self.assertSignalOrdering(sig1, sig2, sig3)

    def test_on_job_added__via_state(self):
        """
        Ensure that adding job units produces same/correct signals
        regardless of how that job is added. This test checks the scenario
        that happens when the session state is used.
        """
        self.watchSignal(self.ctx.on_unit_added)
        self.watchSignal(self.ctx.state.on_unit_added)
        self.watchSignal(self.ctx.state.on_job_added)
        self.ctx.state.add_unit(self.job)
        sig1 = self.assertSignalFired(self.ctx.on_unit_added, self.job)
        sig2 = self.assertSignalFired(self.ctx.state.on_unit_added, self.job)
        sig3 = self.assertSignalFired(self.ctx.state.on_job_added, self.job)
        self.assertSignalOrdering(sig1, sig2, sig3)

    def test_on_unit_removed__via_ctx(self):
        """
        Ensure that removing units produces same/correct signals
        regardless of how that unit is removed. This test checks the scenario
        that happens when the context is used directly
        """
        self.ctx.add_unit(self.unit)
        self.watchSignal(self.ctx.on_unit_removed)
        self.watchSignal(self.ctx.state.on_unit_removed)
        self.watchSignal(self.ctx.state.on_job_removed)
        self.ctx.remove_unit(self.unit)
        sig1 = self.assertSignalFired(self.ctx.on_unit_removed, self.unit)
        sig2 = self.assertSignalFired(self.ctx.state.on_unit_removed,
                                      self.unit)
        self.assertSignalOrdering(sig1, sig2)
        self.assertSignalNotFired(self.ctx.state.on_job_removed, self.unit)

    def test_on_unit_removed__via_state(self):
        """
        Ensure that removing units produces same/correct signals
        regardless of how that unit is removed. This test checks the scenario
        that happens when the session state is used.
        """
        self.ctx.add_unit(self.unit)
        self.watchSignal(self.ctx.on_unit_removed)
        self.watchSignal(self.ctx.state.on_unit_removed)
        self.watchSignal(self.ctx.state.on_job_removed)
        self.ctx.state.remove_unit(self.unit)
        sig1 = self.assertSignalFired(self.ctx.on_unit_removed, self.unit)
        sig2 = self.assertSignalFired(self.ctx.state.on_unit_removed,
                                      self.unit)
        self.assertSignalOrdering(sig1, sig2)
        self.assertSignalNotFired(self.ctx.state.on_job_removed, self.unit)

    def test_on_job_removed__via_ctx(self):
        """
        Ensure that removing job units produces same/correct signals
        regardless of how that job is removed. This test checks the scenario
        that happens when the context is used directly
        """
        self.ctx.add_unit(self.job)
        self.watchSignal(self.ctx.on_unit_removed)
        self.watchSignal(self.ctx.state.on_unit_removed)
        self.watchSignal(self.ctx.state.on_job_removed)
        self.ctx.remove_unit(self.job)
        sig1 = self.assertSignalFired(self.ctx.on_unit_removed, self.job)
        sig2 = self.assertSignalFired(self.ctx.state.on_unit_removed, self.job)
        sig3 = self.assertSignalFired(self.ctx.state.on_job_removed, self.job)
        self.assertSignalOrdering(sig1, sig2, sig3)

    def test_on_job_removed__via_state(self):
        """
        Ensure that removing job units produces same/correct signals
        regardless of how that job is removed. This test checks the scenario
        that happens when the session state is used.
        """
        self.ctx.add_unit(self.job)
        self.watchSignal(self.ctx.on_unit_removed)
        self.watchSignal(self.ctx.state.on_unit_removed)
        self.watchSignal(self.ctx.state.on_job_removed)
        self.ctx.state.remove_unit(self.job)
        sig1 = self.assertSignalFired(self.ctx.on_unit_removed, self.job)
        sig2 = self.assertSignalFired(self.ctx.state.on_unit_removed, self.job)
        sig3 = self.assertSignalFired(self.ctx.state.on_job_removed, self.job)
        self.assertSignalOrdering(sig1, sig2, sig3)