def regenerate_applicability(profile_hash, content_type, profile_id, bound_repo_id, existing_applicability=None): """ Regenerate and save applicability data for given profile and bound repo id. If existing_applicability is not None, replace it with the new applicability data. :param profile_hash: hash of the unit profile :type profile_hash: basestring :param content_type: profile (unit) type ID :type content_type: str :param profile_id: unique id of the unit profile :type profile_id: str :param bound_repo_id: repo id to be used to calculate applicability against the given unit profile :type bound_repo_id: str :param existing_applicability: existing RepoProfileApplicability object to be replaced :type existing_applicability: pulp.server.db.model.consumer.RepoProfileApplicability """ profiler_conduit = ProfilerConduit() # Get the profiler for content_type of given unit_profile profiler, profiler_cfg = ApplicabilityRegenerationManager._profiler( content_type) # Check if the profiler supports applicability, else return if profiler.calculate_applicable_units == Profiler.calculate_applicable_units: # If base class calculate_applicable_units method is called, # skip applicability regeneration return # Find out which content types have unit counts greater than zero in the bound repo repo_content_types = ApplicabilityRegenerationManager._get_existing_repo_content_types( bound_repo_id) # Get the intersection of existing types in the repo and the types that the profiler # handles. If the intersection is not empty, regenerate applicability if (set(repo_content_types) & set(profiler.metadata()['types'])): # Get the actual profile for existing_applicability or lookup using profile_id if existing_applicability: profile = existing_applicability.profile else: unit_profile = UnitProfile.get_collection().find_one( {'id': profile_id}, projection=['profile']) profile = unit_profile['profile'] call_config = PluginCallConfiguration(plugin_config=profiler_cfg, repo_plugin_config=None) try: applicability = profiler.calculate_applicable_units( profile, bound_repo_id, call_config, profiler_conduit) except NotImplementedError: msg = "Profiler for content type [%s] does not support applicability" % content_type _logger.debug(msg) return try: # Create a new RepoProfileApplicability object and save it in the db RepoProfileApplicability.objects.create( profile_hash, bound_repo_id, profile, applicability) except DuplicateKeyError: # Update existing applicability if not existing_applicability: applicability_dict = RepoProfileApplicability.get_collection( ).find_one({ 'repo_id': bound_repo_id, 'profile_hash': profile_hash }) existing_applicability = RepoProfileApplicability( **applicability_dict) existing_applicability.applicability = applicability existing_applicability.save()
def regenerate_applicability(profile_hash, content_type, profile_id, bound_repo_id, existing_applicability=None): """ Regenerate and save applicability data for given profile and bound repo id. If existing_applicability is not None, replace it with the new applicability data. :param profile_hash: hash of the unit profile :type profile_hash: basestring :param content_type: profile (unit) type ID :type content_type: str :param profile_id: unique id of the unit profile :type profile_id: str :param bound_repo_id: repo id to be used to calculate applicability against the given unit profile :type bound_repo_id: str :param existing_applicability: existing RepoProfileApplicability object to be replaced :type existing_applicability: pulp.server.db.model.consumer.RepoProfileApplicability """ profiler_conduit = ProfilerConduit() # Get the profiler for content_type of given unit_profile profiler, profiler_cfg = ApplicabilityRegenerationManager._profiler(content_type) # Check if the profiler supports applicability, else return if profiler.calculate_applicable_units == Profiler.calculate_applicable_units: # If base class calculate_applicable_units method is called, # skip applicability regeneration return # Find out which content types have unit counts greater than zero in the bound repo repo_content_types = ApplicabilityRegenerationManager._get_existing_repo_content_types( bound_repo_id) # Get the intersection of existing types in the repo and the types that the profiler # handles. If the intersection is not empty, regenerate applicability if (set(repo_content_types) & set(profiler.metadata()['types'])): # Get the actual profile for existing_applicability or lookup using profile_id if existing_applicability: profile = existing_applicability.profile else: unit_profile = UnitProfile.get_collection().find_one({'id': profile_id}, projection=['profile']) profile = unit_profile['profile'] call_config = PluginCallConfiguration(plugin_config=profiler_cfg, repo_plugin_config=None) try: applicability = profiler.calculate_applicable_units(profile, bound_repo_id, call_config, profiler_conduit) except NotImplementedError: msg = "Profiler for content type [%s] does not support applicability" % content_type _logger.debug(msg) return try: # Create a new RepoProfileApplicability object and save it in the db RepoProfileApplicability.objects.create(profile_hash, bound_repo_id, profile, applicability) except DuplicateKeyError: # Update existing applicability if not existing_applicability: applicability_dict = RepoProfileApplicability.get_collection().find_one( {'repo_id': bound_repo_id, 'profile_hash': profile_hash}) existing_applicability = RepoProfileApplicability(**applicability_dict) existing_applicability.applicability = applicability existing_applicability.save()
def regenerate_applicability(all_profiles_hash, profiles, bound_repo_id): """ Regenerate and save applicability data for given set of profiles and bound repo id. :param all_profiles_hash: hash of the consumer profiles :type all_profiles_hash: basestring :param profiles: profiles data: (profile_hash, content_type, profile_id) :type profiles: list of tuples :param bound_repo_id: repo id to be used to calculate applicability against the given unit profile :type bound_repo_id: str """ profiler_conduit = ProfilerConduit() # Get the profiler for content_type of given profiles. # The assumption is that the same profiler is used for all the content types, so different # profilers are not supported at the moment. # Take the content type from the first profile. content_type = profiles[0][1] profiler, profiler_cfg = ApplicabilityRegenerationManager._profiler( content_type) # Check if the profiler supports applicability, else return if profiler.calculate_applicable_units == Profiler.calculate_applicable_units: # If base class calculate_applicable_units method is called, # skip applicability regeneration return # Find out which content types have unit counts greater than zero in the bound repo repo_content_types = ApplicabilityRegenerationManager._get_existing_repo_content_types( bound_repo_id) # Get the intersection of existing types in the repo and the types that the profiler # handles. If the intersection is not empty, regenerate applicability if (set(repo_content_types) & set(profiler.metadata()['types'])): profile_ids = [p_id for _, _, p_id in profiles] unit_profiles = UnitProfile.get_collection().find( {'id': { '$in': profile_ids }}, projection=['profile', 'content_type', 'profile_hash']) try: profiles = [(p['profile_hash'], p['content_type'], p['profile']) for p in unit_profiles] except TypeError: # It means that p = None. # Consumer can be removed during applicability regeneration, # so it is possible that its profile no longer exists. It is harmless. return call_config = PluginCallConfiguration(plugin_config=profiler_cfg, repo_plugin_config=None) try: applicability = profiler.calculate_applicable_units( profiles, bound_repo_id, call_config, profiler_conduit) except NotImplementedError: msg = "Profiler for content type [%s] does not support applicability" % content_type _logger.debug(msg) return # Save applicability results on each of the profiles. The results are duplicated. # It's a compromise to have applicability data available in any applicability profile # record in the DB. for profile in profiles: profile_hash = profile[0] try: # Create a new RepoProfileApplicability object and save it in the db RepoProfileApplicability.objects.create( profile_hash=profile_hash, repo_id=bound_repo_id, # profiles can be large, the one in # repo_profile_applicability collection # is no longer used, # it's a duplicated data # from the consumer_unit_profiles # collection. profile=[], applicability=applicability, all_profiles_hash=all_profiles_hash) except DuplicateKeyError: applicability_dict = RepoProfileApplicability.get_collection( ).find_one({ 'repo_id': bound_repo_id, 'all_profiles_hash': all_profiles_hash, 'profile_hash': profile_hash }) existing_applicability = RepoProfileApplicability( **applicability_dict) existing_applicability.applicability = applicability existing_applicability.save()