def setUp(self): ServerTests.setUp(self) self.parentfs = self.tmpdir('parent-') self.childfs = self.tmpdir('child-') self.alias = (self.parentfs, self.parentfs) self.temp_dir = tempfile.mkdtemp() 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() 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, {})
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()
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()
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()
def tearDown(self): base.PulpServerTests.tearDown(self) Consumer.get_collection().remove() Repo.get_collection().remove() RepoDistributor.get_collection().remove() Bind.get_collection().remove() mock_plugins.reset()
def setUp(self): super(ConsumerTest, self).setUp() Consumer.get_collection().remove(safe=True) Repo.get_collection().remove(safe=True) RepoDistributor.get_collection().remove(safe=True) Bind.get_collection().remove(safe=True) plugin_api._create_manager() mock_plugins.install()
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()
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()
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()
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()
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(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()
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()
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()
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()
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()
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, safe=True) 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
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, safe=True) # 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)
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) # 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)
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, {})
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)
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)
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() bind_id = self.bind_id(consumer_id, repo_id, distributor_id) if not force: query = { '$and': [ bind_id, { 'consumer_actions.status': { '$in': [Bind.Status.PENDING, Bind.Status.FAILED] } } ] } pending = collection.find(query) if len(list(pending)): raise Exception, 'outstanding actions, not deleted' if not force: bind_id['deleted'] = True collection.remove(bind_id, safe=True)
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
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
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
def migrate(*args, **kwargs): """ Set binding_config = {} on all bindings with binding_config of None. Earlier versions of pulp permitted the binding to be created with a binding_config of None. """ collection = Bind.get_collection() collection.update(QUERY, UPDATE, multi=True)
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
def consumer_deleted(self, consumer_id): """ Removes all bindings associated with the specified consumer. @param consumer_id: A consumer ID. @type consumer_id: str """ collection = Bind.get_collection() query = dict(consumer_id=consumer_id) collection.remove(query)