예제 #1
0
파일: test_plugins.py 프로젝트: juwu/pulp
 def clean(self):
     Bind.get_collection().remove()
     Repo.get_collection().remove()
     RepoDistributor.get_collection().remove()
     RepoImporter.get_collection().remove()
     RepoContentUnit.get_collection().remove()
     unit_db.clean()
예제 #2
0
 def tearDown(self):
     PulpItineraryTests.tearDown(self)
     Consumer.get_collection().remove()
     Repo.get_collection().remove()
     RepoDistributor.get_collection().remove()
     Bind.get_collection().remove()
     mock_plugins.reset()
예제 #3
0
 def tearDown(self):
     super(ConsumerTest, self).tearDown()
     Consumer.get_collection().remove(safe=True)
     Repo.get_collection().remove(safe=True)
     RepoDistributor.get_collection().remove(safe=True)
     Bind.get_collection().remove(safe=True)
     mock_plugins.reset()
예제 #4
0
 def tearDown(self):
     super(BindManagerTests, self).tearDown()
     Consumer.get_collection().remove()
     Repo.get_collection().remove()
     RepoDistributor.get_collection().remove()
     Bind.get_collection().remove()
     mock_plugins.reset()
예제 #5
0
 def tearDown(self):
     base.PulpWebserviceTests.tearDown(self)
     Consumer.get_collection().remove()
     Repo.get_collection().remove()
     RepoDistributor.get_collection().remove()
     Bind.get_collection().remove()
     mock_plugins.reset()
예제 #6
0
파일: test_bind.py 프로젝트: alanoe/pulp
 def setUp(self):
     super(BindManagerTests, self).setUp()
     Consumer.get_collection().remove()
     model.Distributor.objects.delete()
     Bind.get_collection().remove()
     ConsumerHistoryEvent.get_collection().remove()
     plugin_api._create_manager()
     mock_plugins.install()
예제 #7
0
 def setUp(self):
     base.PulpWebserviceTests.setUp(self)
     Consumer.get_collection().remove()
     Repo.get_collection().remove()
     RepoDistributor.get_collection().remove()
     Bind.get_collection().remove()
     plugin_api._create_manager()
     mock_plugins.install()
 def tearDown(self):
     super(self.__class__, self).tearDown()
     Consumer.get_collection().remove()
     ConsumerGroup.get_collection().remove()
     Repo.get_collection().remove()
     RepoDistributor.get_collection().remove()
     Bind.get_collection().remove()
     mock_plugins.reset()
예제 #9
0
 def setUp(self):
     super(BindManagerTests, self).setUp()
     Consumer.get_collection().remove()
     Repo.get_collection().remove()
     RepoDistributor.get_collection().remove()
     Bind.get_collection().remove()
     plugin_api._create_manager()
     mock_plugins.install()
예제 #10
0
파일: test_bind.py 프로젝트: alanoe/pulp
 def tearDown(self):
     super(BindManagerTests, self).tearDown()
     Consumer.get_collection().remove()
     model.Repository.objects.delete()
     model.Distributor.objects.delete()
     Bind.get_collection().remove()
     ConsumerHistoryEvent.get_collection().remove()
     mock_plugins.reset()
예제 #11
0
 def setUp(self):
     PulpItineraryTests.setUp(self)
     Consumer.get_collection().remove()
     Repo.get_collection().remove()
     RepoDistributor.get_collection().remove()
     Bind.get_collection().remove()
     plugin_api._create_manager()
     mock_plugins.install()
     mock_agent.install()
 def setUp(self):
     super(self.__class__, self).setUp()
     Consumer.get_collection().remove()
     ConsumerGroup.get_collection().remove()
     Repo.get_collection().remove()
     RepoDistributor.get_collection().remove()
     Bind.get_collection().remove()
     plugin_api._create_manager()
     mock_plugins.install()
예제 #13
0
 def tearDown(self):
     super(BaseProfilerConduitTests, self).tearDown()
     Consumer.get_collection().remove()
     Repo.get_collection().remove()
     RepoDistributor.get_collection().remove()
     Bind.get_collection().remove()
     RepoContentUnit.get_collection().remove()
     UnitProfile.get_collection().remove()
     typedb.clean()
     factory.reset()
예제 #14
0
 def setUp(self):
     super(BaseProfilerConduitTests, self).setUp()
     Consumer.get_collection().remove()
     RepoDistributor.get_collection().remove()
     Bind.get_collection().remove()
     RepoContentUnit.get_collection().remove()
     UnitProfile.get_collection().remove()
     plugin_api._create_manager()
     typedb.update_database([self.TYPE_1_DEF, self.TYPE_2_DEF])
     mock_plugins.install()
예제 #15
0
 def tearDown(self):
     super(BaseProfilerConduitTests, self).tearDown()
     Consumer.get_collection().remove()
     model.Repository.objects.delete()
     model.Distributor.objects.delete()
     Bind.get_collection().remove()
     RepoContentUnit.get_collection().remove()
     UnitProfile.get_collection().remove()
     typedb.clean()
     factory.reset()
     mock_plugins.reset()
예제 #16
0
 def clean(self, units_only=False, plugins=False):
     RepoContentUnit.get_collection().remove()
     unit_db.clean()
     if units_only:
         return
     Bind.get_collection().remove()
     Repo.get_collection().remove()
     RepoDistributor.get_collection().remove()
     RepoImporter.get_collection().remove()
     if plugins:
         plugin_api._MANAGER.distributors.plugins = {}
예제 #17
0
 def tearDown(self):
     ServerTests.tearDown(self)
     shutil.rmtree(self.parentfs)
     shutil.rmtree(self.childfs)
     Consumer.get_collection().remove()
     Bind.get_collection().remove()
     model.Repository.objects.delete()
     model.Distributor.objects.delete()
     model.Importer.objects.delete()
     RepoContentUnit.get_collection().remove()
     unit_db.clean()
예제 #18
0
 def tearDown(self):
     WebTest.tearDown(self)
     shutil.rmtree(self.parentfs)
     shutil.rmtree(self.childfs)
     Consumer.get_collection().remove()
     Bind.get_collection().remove()
     Repo.get_collection().remove()
     RepoDistributor.get_collection().remove()
     RepoImporter.get_collection().remove()
     RepoContentUnit.get_collection().remove()
     unit_db.clean()
예제 #19
0
파일: test_plugins.py 프로젝트: bartwo/pulp
 def clean(self, just_units=False, purge_plugins=False):
     RepoContentUnit.get_collection().remove()
     unit_db.clean()
     if just_units:
         return
     Bind.get_collection().remove()
     Repo.get_collection().remove()
     RepoDistributor.get_collection().remove()
     RepoImporter.get_collection().remove()
     if purge_plugins:
         plugin_api._MANAGER.importers.plugins = {}
         plugin_api._MANAGER.distributors.plugins = {}
예제 #20
0
 def test_migration(self):
     # setup
     collection = Bind.get_collection()
     for n in range(0, MAX_BINDINGS):
         if n % 2 == 0:
             conf = {ID: n}
         else:
             conf = None
         binding = {
             ID: n,
             CONSUMER_ID: n,
             REPO_ID: n,
             DISTRIBUTOR_ID: n,
             BINDING_CONFIG: conf,
             NOTIFY_AGENT: True,
         }
         collection.save(binding, safe=True)
     # migrate
     module = MigrationModule(MIGRATION)._module
     module.migrate()
     # verify
     bindings = list(collection.find({}))
     self.assertEqual(len(bindings), MAX_BINDINGS)
     for binding in bindings:
         conf = binding[BINDING_CONFIG]
         bind_id = binding[ID]
         if bind_id % 2 == 0:
             # untouched
             self.assertEqual(conf, {ID: bind_id})
         else:
             # fixed
             self.assertEqual(conf, {})
예제 #21
0
파일: bind.py 프로젝트: nbetm/pulp
    def get_bind(consumer_id, repo_id, distributor_id):
        """
        Get a specific bind.
        This method ignores the deleted flag.

        :param consumer_id:     uniquely identifies the consumer.
        :type  consumer_id:     str
        :param repo_id:         uniquely identifies the repository.
        :type  repo_id:         str
        :param distributor_id:  uniquely identifies a distributor.
        :type  distributor_id:  str

        :return: A specific bind.
        :rtype:  SON

        :raise MissingResource: if the binding doesn't exist
        """
        collection = Bind.get_collection()
        bind_id = BindManager.bind_id(consumer_id, repo_id, distributor_id)
        bind = collection.find_one(bind_id)
        if bind is None:
            # If the binding doesn't exist, report which values are not present
            missing_values = BindManager._validate_consumer_repo(consumer_id, repo_id,
                                                                 distributor_id)
            if missing_values:
                raise MissingResource(**missing_values)
            else:
                # In this case, every resource is present, but the consumer isn't bound to that
                # repo/distributor
                raise MissingResource(bind_id=bind_id)
        return bind
예제 #22
0
파일: bind.py 프로젝트: pkilambi/pulp
 def action_pending(self, consumer_id, repo_id, distributor_id, action, action_id):
     """
     Add pending action for tracking.
     @param consumer_id: uniquely identifies the consumer.
     @type consumer_id: str
     @param repo_id: uniquely identifies the repository.
     @type repo_id: str
     @param distributor_id: uniquely identifies a distributor.
     @type distributor_id: str
     @param action: The action (bind|unbind).
     @type action: str
     @param action_id: The ID of the action to begin tracking.
     @type action_id: str
     @see Bind.Action
     """
     collection = Bind.get_collection()
     assert action in (Bind.Action.BIND, Bind.Action.UNBIND)
     bind_id = self.bind_id(consumer_id, repo_id, distributor_id)
     entry = dict(
         id=action_id,
         timestamp=time(),
         action=action,
         status=Bind.Status.PENDING)
     update = {'$push':{'consumer_actions':entry}}
     collection.update(bind_id, update, safe=True)
예제 #23
0
파일: bind.py 프로젝트: pkilambi/pulp
 def bind(self, consumer_id, repo_id, distributor_id):
     """
     Bind consumer to a specific distributor associated with
     a repository.  This call is idempotent.
     @param consumer_id: uniquely identifies the consumer.
     @type consumer_id: str
     @param repo_id: uniquely identifies the repository.
     @type repo_id: str
     @param distributor_id: uniquely identifies a distributor.
     @type distributor_id: str
     @return: The Bind object
     @rtype: SON
     @raise MissingResource: when given consumer does not exist.
     """
     # ensure the consumer is valid
     manager = factory.consumer_manager()
     manager.get_consumer(consumer_id)
     # ensure the repository & distributor are valid
     manager = factory.repo_distributor_manager()
     manager.get_distributor(repo_id, distributor_id)
     # perform the bind
     collection = Bind.get_collection()
     try:
         bind = Bind(consumer_id, repo_id, distributor_id)
         collection.save(bind, safe=True)
     except DuplicateKeyError:
         self.__reset_bind(consumer_id, repo_id, distributor_id)
     # fetch the inserted/updated bind
     bind = self.get_bind(consumer_id, repo_id, distributor_id)
     # update history
     details = {'repo_id':repo_id, 'distributor_id':distributor_id}
     manager = factory.consumer_history_manager()
     manager.record_event(consumer_id, 'repo_bound', details)
     return bind
예제 #24
0
파일: bind.py 프로젝트: pkilambi/pulp
 def unbind(self, consumer_id, repo_id, distributor_id):
     """
     Unbind a consumer from a specific distributor associated with
     a repository.  This call is idempotent.
     @param consumer_id: uniquely identifies the consumer.
     @type consumer_id: str
     @param repo_id: uniquely identifies the repository.
     @type repo_id: str
     @param distributor_id: uniquely identifies a distributor.
     @type distributor_id: str
     @return: The Bind object
     @rtype: SON
     """
     collection = Bind.get_collection()
     query = self.bind_id(consumer_id, repo_id, distributor_id)
     query['deleted'] = False
     bind = collection.find_one(query)
     if bind is None:
         # idempotent
         return
     self.mark_deleted(consumer_id, repo_id, distributor_id)
     details = {
         'repo_id':repo_id,
         'distributor_id':distributor_id
     }
     manager = factory.consumer_history_manager()
     manager.record_event(consumer_id, 'repo_unbound', details)
     return bind
예제 #25
0
파일: bind.py 프로젝트: pkilambi/pulp
 def delete(self, consumer_id, repo_id, distributor_id, force=False):
     """
     Delete the bind.
     @param consumer_id: uniquely identifies the consumer.
     @type consumer_id: str
     @param repo_id: uniquely identifies the repository.
     @type repo_id: str
     @param distributor_id: uniquely identifies a distributor.
     @type distributor_id: str
     @param force: Delete without validation.
     @type force: bool
     """
     collection = Bind.get_collection()
     if not force:
         query = {
             'consumer_actions.status':{
                 '$in':[Bind.Status.PENDING, Bind.Status.FAILED]}
         }
         pending = collection.find(query)
         if len(list(pending)):
             raise Exception, 'outstanding actions, not deleted'
     query = self.bind_id(consumer_id, repo_id, distributor_id)
     if not force:
         query['deleted'] = True
     collection.remove(query, safe=True)
예제 #26
0
파일: bind.py 프로젝트: pkilambi/pulp
 def action_succeeded(self, consumer_id, repo_id, distributor_id, action_id):
     """
     A tracked consumer action has succeeded.
     Since consumer actions are queue to the agent and performed
     in the order, previous actions are considered irrelevant and thus purged.
     @param consumer_id: uniquely identifies the consumer.
     @type consumer_id: str
     @param repo_id: uniquely identifies the repository.
     @type repo_id: str
     @param distributor_id: uniquely identifies a distributor.
     @type distributor_id: str
     @param action_id: The ID of the action to begin tracking.
     @type action_id: str
     """
     collection = Bind.get_collection()
     bind_id = self.bind_id(consumer_id, repo_id, distributor_id)
     action = self.find_action(action_id)
     if action is None:
         _LOG.warn('action %s not found', action_id)
         return
     # delete the action
     update = {'$pull':{'consumer_actions':{'id':action_id}}}
     collection.update(bind_id, update, safe=True)
     # purge all previous actions
     update = {'$pull':
         {'consumer_actions':{'timestamp':{'$lt':action['timestamp']}}}
     }
     collection.update(bind_id, update, safe=True)
예제 #27
0
파일: bind.py 프로젝트: jlsherrill/pulp
 def bind(self, consumer_id, repo_id, distributor_id):
     """
     Bind consumer to a specific distributor associated with
     a repository.  This call is idempotent.
     @param consumer_id: uniquely identifies the consumer.
     @type consumer_id: str
     @param repo_id: uniquely identifies the repository.
     @type repo_id: str
     @param distributor_id: uniquely identifies a distributor.
     @type distributor_id: str
     @return: The Bind object
     @rtype: SON
     @raise MissingResource: when given consumer does not exist.
     """
     manager = factory.consumer_manager()
     manager.get_consumer(consumer_id)
     manager = factory.repo_distributor_manager()
     distributor = manager.get_distributor(repo_id, distributor_id)
     bind = Bind(consumer_id, repo_id, distributor_id)
     collection = Bind.get_collection()
     try:
         collection.save(bind, safe=True)
         bind = self.get_bind(consumer_id, repo_id, distributor_id)
     except DuplicateKeyError:
         # idempotent
         pass
     manager = factory.consumer_agent_manager()
     manager.bind(consumer_id, repo_id)
     consumer_event_details = {"repo_id": repo_id, "distributor_id": distributor_id}
     factory.consumer_history_manager().record_event(consumer_id, "repo_bound", consumer_event_details)
     return bind
예제 #28
0
파일: bind.py 프로젝트: jlsherrill/pulp
 def unbind(self, consumer_id, repo_id, distributor_id):
     """
     Unbind consumer to a specifiec distirbutor associated with
     a repository.  This call is idempotent.
     @param consumer_id: uniquely identifies the consumer.
     @type consumer_id: str
     @param repo_id: uniquely identifies the repository.
     @type repo_id: str
     @param distributor_id: uniquely identifies a distributor.
     @type distributor_id: str
     @return: The Bind object
     @rtype: SON
     """
     query = dict(consumer_id=consumer_id, repo_id=repo_id, distributor_id=distributor_id)
     collection = Bind.get_collection()
     bind = collection.find_one(query)
     if bind is None:
         # idempotent
         return
     collection.remove(bind, safe=True)
     manager = factory.consumer_agent_manager()
     manager.unbind(consumer_id, repo_id)
     consumer_event_details = {"repo_id": repo_id, "distributor_id": distributor_id}
     factory.consumer_history_manager().record_event(consumer_id, "repo_unbound", consumer_event_details)
     return bind
예제 #29
0
    def test_upgrade_idempotency(self):
        """
        Simplest way to check the migration can run twice is simply to run it twice. The
        primary goal is to make sure an exception isn't raised.
        """

        # Setup
        coll = Bind.get_collection()

        for counter in range(0, 3):
            bind_dict = {
                'consumer_id': 'consumer_%s' % counter,
                'repo_id': 'repo_%s' % counter,
                'distributor_id': 'distributor_%s' % counter,
            }

            coll.insert(bind_dict)

        # Test
        module = MigrationModule('pulp.server.db.migrations.0003_bind_additions')._module
        module.migrate()
        module.migrate()

        # Verify
        bindings = coll.find()
        for b in bindings:
            self.assertTrue('notify_agent' in b)
            self.assertEqual(b['notify_agent'], True)
            self.assertTrue('binding_config' in b)
            self.assertEqual(b['binding_config'], None)
예제 #30
0
    def test_forced_unbind_agent_not_notified(self):

        # Setup
        self.populate()
        manager = factory.consumer_bind_manager()
        bind = manager.bind(self.CONSUMER_ID, self.REPO_ID, self.DISTRIBUTOR_ID,
                            False, self.BINDING_CONFIG)

        # Test
        options = {}
        itinerary = forced_unbind_itinerary(
            self.CONSUMER_ID,
            self.REPO_ID,
            self.DISTRIBUTOR_ID,
            options)

        call_reports = self.coordinator.execute_multiple_calls(itinerary)

        # Verify
        self.assertEqual(len(call_reports), 1)
        self.assertEqual(call_reports[0].call_request_tags, self.UNBIND_TAGS)
        for call in call_reports:
            self.assertNotEqual(call.state, dispatch_constants.CALL_REJECTED_RESPONSE)

        # run task #1 (actual delete)
        self.run_next()

        # verify bind deleted
        collection = Bind.get_collection()
        bind = collection.find_one(self.QUERY)
        self.assertTrue(bind is None)

        # verify agent notified
        self.assertFalse(mock_agent.Consumer.unbind.called)
예제 #31
0
 def setUp(self):
     ServerTests.setUp(self)
     self.parentfs = self.tmpdir('parent-')
     self.childfs = self.tmpdir('child-')
     self.alias = (self.parentfs, self.parentfs)
     Consumer.get_collection().remove()
     Bind.get_collection().remove()
     Repo.get_collection().remove()
     RepoDistributor.get_collection().remove()
     RepoImporter.get_collection().remove()
     RepoContentUnit.get_collection().remove()
     unit_db.clean()
     self.define_plugins()
     plugin_api._create_manager()
     imp_conf = dict(strategy=constants.MIRROR_STRATEGY)
     plugin_api._MANAGER.importers.add_plugin(constants.HTTP_IMPORTER,
                                              NodesHttpImporter, imp_conf)
     plugin_api._MANAGER.distributors.add_plugin(constants.HTTP_DISTRIBUTOR,
                                                 NodesHttpDistributor, {})
     plugin_api._MANAGER.distributors.add_plugin(FAKE_DISTRIBUTOR,
                                                 FakeDistributor,
                                                 FAKE_DISTRIBUTOR_CONFIG)
     plugin_api._MANAGER.profilers.add_plugin(constants.PROFILER_ID,
                                              NodeProfiler, {})
예제 #32
0
파일: bind.py 프로젝트: taftsanders/pulp
    def _update_binding(consumer_id, repo_id, distributor_id, notify_agent, binding_config):
        """
        Workaround to the way bindings rely on a duplicate key error for supporting rebind.
        This call makes sure the existing binding is updated with the new values for
        notifying the agent and the binding's configuration.

        The parameters are the values passed to the bind() call.
        """

        collection = Bind.get_collection()
        query = BindManager.bind_id(consumer_id, repo_id, distributor_id)
        binding = collection.find_one(query)
        binding['notify_agent'] = notify_agent
        binding['binding_config'] = binding_config
        collection.save(binding)
예제 #33
0
 def find_action(self, action_id):
     """
     Find a consumer action by ID.
     @param action_id: An action ID.
     @type action_id: str
     @return: The action if found, else None
     """
     collection = Bind.get_collection()
     query = {'consumer_actions.id': action_id}
     binding = collection.find_one(query)
     if binding is None:
         return
     for action in binding['consumer_actions']:
         if action['id'] == action_id:
             return action
예제 #34
0
    def bind(consumer_id, repo_id, distributor_id, notify_agent, binding_config):
        """
        Bind consumer to a specific distributor associated with
        a repository.  This call is idempotent.
        :param consumer_id: uniquely identifies the consumer.
        :type  consumer_id: str
        :param repo_id: uniquely identifies the repository.
        :type  repo_id: str
        :param distributor_id: uniquely identifies a distributor.
        :type  distributor_id: str

        :return: The Bind object
        :rtype:  SON

        :raise MissingResource: when given consumer does not exist.
        :raise InvalidValid:    when the repository or distributor id is invalid, or
        if the notify_agent value is invalid
        """
        # Validation
        missing_values = BindManager._validate_consumer_repo(consumer_id, repo_id, distributor_id)
        if missing_values:
            if 'consumer_id' in missing_values:
                # This is passed in via the URL so a 404 should be raised
                raise MissingResource(consumer_id=missing_values['consumer_id'])
            else:
                # Everything else is a parameter so raise a 400
                raise InvalidValue(missing_values.keys())

        # ensure notify_agent is a boolean
        if not isinstance(notify_agent, bool):
            raise InvalidValue(['notify_agent'])

        # perform the bind
        collection = Bind.get_collection()
        try:
            bind = Bind(consumer_id, repo_id, distributor_id, notify_agent, binding_config)
            collection.save(bind)
        except DuplicateKeyError:
            BindManager._update_binding(consumer_id, repo_id, distributor_id, notify_agent,
                                        binding_config)
            BindManager._reset_bind(consumer_id, repo_id, distributor_id)
        # fetch the inserted/updated bind
        bind = BindManager.get_bind(consumer_id, repo_id, distributor_id)
        # update history
        details = {'repo_id': repo_id, 'distributor_id': distributor_id}
        manager = factory.consumer_history_manager()
        manager.record_event(consumer_id, 'repo_bound', details)
        return bind
예제 #35
0
파일: test_bind.py 프로젝트: zjhuntin/pulp
 def test_hard_delete(self, mock_repo_qs):
     self.populate()
     manager = factory.consumer_bind_manager()
     manager.bind(self.CONSUMER_ID, self.REPO_ID, self.DISTRIBUTOR_ID,
                  self.NOTIFY_AGENT, self.BINDING_CONFIG)
     # Test
     manager.delete(self.CONSUMER_ID, self.REPO_ID, self.DISTRIBUTOR_ID)
     manager.action_pending(self.CONSUMER_ID, self.REPO_ID,
                            self.DISTRIBUTOR_ID, Bind.Action.BIND, '0')
     manager.delete(self.CONSUMER_ID, self.REPO_ID, self.DISTRIBUTOR_ID,
                    True)
     collection = Bind.get_collection()
     bind_id = manager.bind_id(self.CONSUMER_ID, self.REPO_ID,
                               self.DISTRIBUTOR_ID)
     bind = collection.find_one(bind_id)
     self.assertTrue(bind is None)
예제 #36
0
 def test_bind(self):
     # Setup
     self.populate()
     # Test
     manager = factory.consumer_bind_manager()
     manager.bind(self.CONSUMER_ID, self.REPO_ID, self.DISTRIBUTOR_ID,
                  self.NOTIFY_AGENT, self.BINDING_CONFIG)
     # Verify
     collection = Bind.get_collection()
     bind = collection.find_one(self.QUERY)
     self.assertTrue(bind is not None)
     self.assertEqual(bind['consumer_id'], self.CONSUMER_ID)
     self.assertEqual(bind['repo_id'], self.REPO_ID)
     self.assertEqual(bind['distributor_id'], self.DISTRIBUTOR_ID)
     self.assertEqual(bind['notify_agent'], self.NOTIFY_AGENT)
     self.assertEqual(bind['binding_config'], self.BINDING_CONFIG)
예제 #37
0
파일: bind.py 프로젝트: sahwar/pulp
 def mark_deleted(self, consumer_id, repo_id, distributor_id):
     """
     Mark the bind as deleted.
     @param consumer_id: uniquely identifies the consumer.
     @type consumer_id: str
     @param repo_id: uniquely identifies the repository.
     @type repo_id: str
     @param distributor_id: uniquely identifies a distributor.
     @type distributor_id: str
     """
     # validate
     self.get_bind(consumer_id, repo_id, distributor_id)
     # update document
     collection = Bind.get_collection()
     query = self.bind_id(consumer_id, repo_id, distributor_id)
     collection.update(query, {'$set': {'deleted': True}}, safe=True)
예제 #38
0
파일: bind.py 프로젝트: sahwar/pulp
 def find_by_distributor(self, repo_id, distributor_id):
     """
     Find all non-deleted binds by Distributor ID.
     @param repo_id: A Repo ID.
     @type repo_id: str
     @param distributor_id: A Distributor ID.
     @type distributor_id: str
     @return: A list of Bind.
     @rtype: list
     """
     collection = Bind.get_collection()
     query = dict(repo_id=repo_id,
                  distributor_id=distributor_id,
                  deleted=False)
     cursor = collection.find(query)
     return list(cursor)
예제 #39
0
파일: bind.py 프로젝트: sahwar/pulp
 def __reset_bind(self, consumer_id, repo_id, distributor_id):
     """
     Reset the bind.
     This means resetting the deleted flag and consumer requests.
     Only deleted bindings will be reset.
     @param consumer_id: uniquely identifies the consumer.
     @type consumer_id: str
     @param repo_id: uniquely identifies the repository.
     @type repo_id: str
     @param distributor_id: uniquely identifies a distributor.
     @type distributor_id: str
     """
     collection = Bind.get_collection()
     query = self.bind_id(consumer_id, repo_id, distributor_id)
     query['deleted'] = True
     update = {'$set': {'deleted': False, 'consumer_actions': []}}
     collection.update(query, update, safe=True)
예제 #40
0
 def test_bind_missing_consumer(self, mock_repo_qs):
     self.populate()
     collection = Consumer.get_collection()
     collection.remove({})
     manager = factory.consumer_bind_manager()
     try:
         manager.bind(self.CONSUMER_ID, self.REPO_ID, self.DISTRIBUTOR_ID,
                      self.NOTIFY_AGENT, self.BINDING_CONFIG)
         self.fail(msg='MissingResource <Consumer>, expected')
     except MissingResource:
         # expected
         pass
         # Verify
     collection = Bind.get_collection()
     binds = collection.find({})
     binds = [b for b in binds]
     self.assertEqual(len(binds), 0)
예제 #41
0
파일: bind.py 프로젝트: sahwar/pulp
 def action_failed(self, consumer_id, repo_id, distributor_id, action_id):
     """
     A tracked consumer action has failed.
     @param consumer_id: uniquely identifies the consumer.
     @type consumer_id: str
     @param repo_id: uniquely identifies the repository.
     @type repo_id: str
     @param distributor_id: uniquely identifies a distributor.
     @type distributor_id: str
     @param action_id: The ID of the request to begin tracking.
     @type action_id: str
     """
     collection = Bind.get_collection()
     query = self.bind_id(consumer_id, repo_id, distributor_id)
     query['consumer_actions.id'] = action_id
     update = {'$set': {'consumer_actions.$.status': Bind.Status.FAILED}}
     collection.update(query, update, safe=True)
예제 #42
0
파일: bind.py 프로젝트: sahwar/pulp
 def find_by_consumer(self, id, repo_id=None):
     """
     Find all non-deleted bindings by Consumer ID.
     @param id: A consumer ID.
     @type id: str
     @param repo_id: An (optional) repository ID.
     @type repo_id: str
     @return: A list of Bind.
     @rtype: list
     """
     collection = Bind.get_collection()
     if repo_id:
         query = dict(consumer_id=id, repo_id=repo_id, deleted=False)
     else:
         query = dict(consumer_id=id, deleted=False)
     cursor = collection.find(query)
     return list(cursor)
예제 #43
0
파일: bind.py 프로젝트: sahwar/pulp
    def bind(self, consumer_id, repo_id, distributor_id, notify_agent,
             binding_config):
        """
        Bind consumer to a specific distributor associated with
        a repository.  This call is idempotent.
        @param consumer_id: uniquely identifies the consumer.
        @type consumer_id: str
        @param repo_id: uniquely identifies the repository.
        @type repo_id: str
        @param distributor_id: uniquely identifies a distributor.
        @type distributor_id: str
        @return: The Bind object
        @rtype: SON
        @raise MissingResource: when given consumer does not exist.
        """
        # Validation

        # ensure notify_agent is a boolean
        if not isinstance(notify_agent, bool):
            raise InvalidValue(['notify_agent'])

        # ensure the consumer is valid
        manager = factory.consumer_manager()
        manager.get_consumer(consumer_id)

        # ensure the repository & distributor are valid
        manager = factory.repo_distributor_manager()
        manager.get_distributor(repo_id, distributor_id)

        # perform the bind
        collection = Bind.get_collection()
        try:
            bind = Bind(consumer_id, repo_id, distributor_id, notify_agent,
                        binding_config)
            collection.save(bind, safe=True)
        except DuplicateKeyError:
            self._update_binding(consumer_id, repo_id, distributor_id,
                                 notify_agent, binding_config)
            self.__reset_bind(consumer_id, repo_id, distributor_id)
        # fetch the inserted/updated bind
        bind = self.get_bind(consumer_id, repo_id, distributor_id)
        # update history
        details = {'repo_id': repo_id, 'distributor_id': distributor_id}
        manager = factory.consumer_history_manager()
        manager.record_event(consumer_id, 'repo_bound', details)
        return bind
예제 #44
0
def migrate(*args, **kwargs):
    """
    Add new fields needed for consumer action(s) tracking.
    """
    additions = (
        ('deleted', False),
        ('consumer_actions', []),
    )
    collection = Bind.get_collection()
    for bind in collection.find({}):
        dirty = False
        for key, value in additions:
            if key not in bind:
                bind[key] = value
                dirty = True
        if dirty:
            collection.save(bind)
예제 #45
0
    def test_unbind(self):
        # Setup
        self.populate()
        manager = factory.consumer_bind_manager()
        manager.bind(self.CONSUMER_ID, self.REPO_ID, self.DISTRIBUTOR_ID,
                     self.NOTIFY_AGENT, self.BINDING_CONFIG)
        # Test
        manager = factory.consumer_bind_manager()
        manager.unbind(self.CONSUMER_ID, self.REPO_ID, self.DISTRIBUTOR_ID)

        # Verify
        collection = Bind.get_collection()
        bind_id = dict(consumer_id=self.CONSUMER_ID,
                       repo_id=self.REPO_ID,
                       distributor_id=self.DISTRIBUTOR_ID)
        bind = collection.find_one(bind_id)
        self.assertTrue(bind is not None)
        self.assertTrue(bind['deleted'])
예제 #46
0
def migrate(*args, **kwargs):
    """
    Adds attributes needed for binding configurations. To maintain backward compatibility,
    the notify_agent field is set to True.
    """

    additions = (
        ('notify_agent', True),
        ('binding_config', None),
    )
    collection = Bind.get_collection()
    for bind in collection.find({}):
        dirty = False
        for key, value in additions:
            if key not in bind:
                bind[key] = value
                dirty = True
        if dirty:
            collection.save(bind)
예제 #47
0
def _add_repo_ids_to_consumer_map(consumer_ids, consumer_map):
    """
    Query for all bindings for the given list of consumer_ids, and for each one add the bound
    repo_ids to the consumer_map's entry for the consumer.

    :param consumer_ids: The list of consumer_ids. We could pull this from the consumer_map,
                         but since we already have this list it's probably more performant to
                         use it as is.
    :type  consumer_ids: list
    :param consumer_map: A dictionary mapping consumer_ids to a dictionary with key 'profiles',
                         which indexes a list that this method will append the found profiles
                         to.
    :type  consumer_map: dict
    """
    bindings = Bind.get_collection().find(
        {'consumer_id': {'$in': consumer_ids}},
        fields=['consumer_id', 'repo_id'])
    for b in bindings:
        consumer_map[b['consumer_id']]['repo_ids'].append(b['repo_id'])
예제 #48
0
파일: bind.py 프로젝트: sahwar/pulp
 def get_bind(self, consumer_id, repo_id, distributor_id):
     """
     Get a specific bind.
     This method ignores the deleted flag.
     @param consumer_id: uniquely identifies the consumer.
     @type consumer_id: str
     @param repo_id: uniquely identifies the repository.
     @type repo_id: str
     @param distributor_id: uniquely identifies a distributor.
     @type distributor_id: str
     @return: A specific bind.
     @rtype: SON
     @raise MissingResource: When not found
     """
     collection = Bind.get_collection()
     bind_id = self.bind_id(consumer_id, repo_id, distributor_id)
     bind = collection.find_one(bind_id)
     if bind is None:
         raise MissingResource(bind_id=bind_id)
     return bind
예제 #49
0
    def test_forced_unbind(self):

        # Setup
        self.populate()
        manager = factory.consumer_bind_manager()
        bind = manager.bind(self.CONSUMER_ID, self.REPO_ID, self.DISTRIBUTOR_ID,
                            self.NOTIFY_AGENT, self.BINDING_CONFIG)

        # Test
        options = {}
        itinerary = forced_unbind_itinerary(
            self.CONSUMER_ID,
            self.REPO_ID,
            self.DISTRIBUTOR_ID,
            options)
        call_reports = self.coordinator.execute_multiple_calls(itinerary)

        # Verify
        self.assertEqual(len(call_reports), 2)
        self.assertEqual(call_reports[0].call_request_tags, self.UNBIND_TAGS)
        self.assertEqual(call_reports[1].call_request_tags, self.AGENT_UNBIND_TAGS)
        for call in call_reports:
            self.assertNotEqual(call.state, dispatch_constants.CALL_REJECTED_RESPONSE)

        # run task #1 (actual delete)
        self.run_next()

        # verify bind marked deleted
        collection = Bind.get_collection()
        bind = collection.find_one(self.QUERY)
        self.assertTrue(bind is None)

        # run task #2 (notify consumer)
        self.run_next()

        # verify agent notified
        self.assertTrue(mock_agent.Consumer.unbind.called)
예제 #50
0
    def unbind(consumer_id, repo_id, distributor_id):
        """
        Unbind a consumer from a specific distributor associated with
        a repository.  This call is idempotent.

        :param consumer_id:     uniquely identifies the consumer.
        :type  consumer_id:     str
        :param repo_id:         uniquely identifies the repository.
        :type  repo_id:         str
        :param distributor_id:  uniquely identifies a distributor.
        :type  distributor_id:  str

        :return: The Bind object
        :rtype:  SON

        :raise MissingResource: if the binding does not exist
        """
        # Validate that the binding exists at all before continuing.
        # This will raise an exception if it it does not.
        BindManager.get_bind(consumer_id, repo_id, distributor_id)

        collection = Bind.get_collection()
        query = BindManager.bind_id(consumer_id, repo_id, distributor_id)
        query['deleted'] = False
        bind = collection.find_one(query)
        if bind is None:
            # idempotent
            return
        BindManager.mark_deleted(consumer_id, repo_id, distributor_id)
        details = {
            'repo_id': repo_id,
            'distributor_id': distributor_id
        }
        manager = factory.consumer_history_manager()
        manager.record_event(consumer_id, 'repo_unbound', details)
        return bind
예제 #51
0
    def test_upgrade(self):
        # Setup
        coll = Bind.get_collection()

        for counter in range(0, 3):
            bind_dict = {
                'consumer_id' : 'consumer_%s' % counter,
                'repo_id' : 'repo_%s' % counter,
                'distributor_id' : 'distributor_%s' % counter,
            }

            coll.insert(bind_dict, safe=True)

        # Test
        module = MigrationModule('pulp.server.db.migrations.0003_bind_additions')._module
        module.migrate()

        # Verify
        bindings = coll.find()
        for b in bindings:
            self.assertTrue('notify_agent' in b)
            self.assertEqual(b['notify_agent'], True)
            self.assertTrue('binding_config' in b)
            self.assertEqual(b['binding_config'], None)
예제 #52
0
    def test_unbind_failed_on_consumer(self):

        # Setup
        self.populate()
        manager = factory.consumer_bind_manager()
        bind = manager.bind(self.CONSUMER_ID, self.REPO_ID, self.DISTRIBUTOR_ID,
                            self.NOTIFY_AGENT, self.BINDING_CONFIG)

        # Test
        options = {}
        itinerary = unbind_itinerary(
            self.CONSUMER_ID,
            self.REPO_ID,
            self.DISTRIBUTOR_ID,
            options)
        call_reports = self.coordinator.execute_multiple_calls(itinerary)

        # Verify
        self.assertEqual(len(call_reports), 3)
        for call in call_reports:
            self.assertNotEqual(call.state, dispatch_constants.CALL_REJECTED_RESPONSE)

        # run task #1 (actual unbind)
        self.run_next()

        # verify bind marked deleted
        collection = Bind.get_collection()
        bind = collection.find_one(self.QUERY)
        self.assertTrue(bind['deleted'])

        # run task #2 (notify consumer)
        self.run_next()

        # verify agent notified
        self.assertTrue(mock_agent.Consumer.unbind.called)

        # verify consumer request (pending)
        request_id = call_reports[1].call_request_id
        collection = Bind.get_collection()
        bind = collection.find_one(self.QUERY)
        self.assertTrue(bind is not None)
        actions = bind['consumer_actions']
        self.assertEqual(len(actions), 1)
        self.assertEqual(actions[0]['id'], request_id)
        self.assertEqual(actions[0]['action'], Bind.Action.UNBIND)
        self.assertEqual(actions[0]['status'], Bind.Status.PENDING)
        self.assertTrue(isinstance(actions[0]['timestamp'], float))

        # simulated asynchronous task result
        report = DispatchReport()
        report.succeeded = False
        self.coordinator.complete_call_success(request_id, report.dict())

        # verify not found (marked deleted)
        binds = manager.find_by_consumer(self.CONSUMER_ID)
        self.assertEquals(len(binds), 0)

        # run task #3 (bind actually deleted)
        self.run_next()

        # verify bind not deleted
        collection = Bind.get_collection()
        bind = collection.find_one(self.QUERY)
        self.assertTrue(bind is not None)
        actions = bind['consumer_actions']
        self.assertEqual(len(actions), 1)
        self.assertEqual(actions[0]['id'], request_id)
        self.assertEqual(actions[0]['action'], Bind.Action.UNBIND)
        self.assertEqual(actions[0]['status'], Bind.Status.FAILED)
        self.assertTrue(isinstance(actions[0]['timestamp'], float))
예제 #53
0
    def clean(self):
        super(BindAdditionMigrationTests, self).clean()

        Bind.get_collection().remove()
예제 #54
0
 def tearDown(self):
     super(TestMigration_0006, self).tearDown()
     collection = Bind.get_collection()
     collection.remove()
예제 #55
0
 def setUp(self):
     self.clean()
     super(TestMigration_0006, self).setUp()
     collection = Bind.get_collection()
     collection.remove()