Esempio n. 1
0
 def units_applicable(self, criteria, units):
     """
     Detemine and report which of the specified content units
     is applicable to consumers specified by the I{criteria}.
     @param criteria: The consumer selection criteria.
     @type criteria: list
     @param units: A list of content units to be installed.
     @type units: list of:
         { type_id:<str>, unit_key:<dict> }
     @return: A dict:
         {consumer_id:[<ApplicabilityReport>]}
     @rtype: list
     """
     result = {}
     conduit = ProfilerConduit()
     manager = managers.consumer_query_manager()
     ids = [c['id'] for c in manager.find_by_criteria(criteria)]
     manager = managers.consumer_profile_manager()
     profiles = manager.find_profiles(ids)
     for id in ids:
         for unit in units:
             typeid = unit['type_id']
             profiler, cfg = self.__profiler(typeid)
             pc = self.__profiled_consumer(id)
             report = profiler.unit_applicable(pc, unit, cfg, conduit)
             report.unit = unit
             ulist = result.setdefault(id, [])
             ulist.append(report)
     return result
Esempio n. 2
0
    def post(self, request, consumer_id):
        """
        Creates an async task to regenerate content applicability data for given consumer.

        :param request: WSGI request object
        :type request: django.core.handlers.wsgi.WSGIRequest
        :param consumer_id: The consumer ID.
        :type consumer_id: str

        :raises MissingResource: if some parameters are missing
        :raises OperationPostponed: when an async operation is performed.
        """

        consumer_query_manager = factory.consumer_query_manager()
        if consumer_query_manager.find_by_id(consumer_id) is None:
            raise MissingResource(consumer_id=consumer_id)
        consumer_criteria = Criteria(filters={'consumer_id': consumer_id})

        task_tags = [
            tags.action_tag('consumer_content_applicability_regeneration')
        ]
        async_result = regenerate_applicability_for_consumers.apply_async_with_reservation(
            tags.RESOURCE_CONSUMER_TYPE,
            consumer_id, (consumer_criteria.as_dict(), ),
            tags=task_tags)
        raise OperationPostponed(async_result)
Esempio n. 3
0
    def post(self, request, consumer_id):
        """
        Creates an async task to regenerate content applicability data for given consumer.

        :param request: WSGI request object
        :type request: django.core.handlers.wsgi.WSGIRequest
        :param consumer_id: The consumer ID.
        :type consumer_id: str

        :raises MissingResource: if some parameters are missing
        :raises OperationPostponed: when an async operation is performed.
        """

        consumer_query_manager = factory.consumer_query_manager()
        if consumer_query_manager.find_by_id(consumer_id) is None:
            raise MissingResource(consumer_id=consumer_id)
        consumer_criteria = Criteria(filters={'consumer_id': consumer_id})

        task_tags = [tags.action_tag('consumer_content_applicability_regeneration')]
        async_result = regenerate_applicability_for_consumers.apply_async_with_reservation(
            tags.RESOURCE_CONSUMER_TYPE,
            consumer_id,
            (consumer_criteria.as_dict(),),
            tags=task_tags)
        raise OperationPostponed(async_result)
Esempio n. 4
0
 def GET(self):
     params = web.input()
     manager = managers.consumer_query_manager()
     consumers = expand_consumers(params, manager.find_all())
     for c in consumers:
         href = serialization.link.child_link_obj(c['id'])
         c.update(href)
     return self.ok(consumers)
Esempio n. 5
0
    def regenerate_applicability_for_consumers(consumer_criteria):
        """
        Regenerate and save applicability data for given updated consumers.

        :param consumer_criteria: The consumer selection criteria
        :type consumer_criteria: dict
        """
        consumer_criteria = Criteria.from_dict(consumer_criteria)
        consumer_query_manager = managers.consumer_query_manager()

        # Process consumer_criteria and get all the consumer ids satisfied by the criteria
        consumer_criteria.fields = ['id']
        consumer_ids = [
            c['id']
            for c in consumer_query_manager.find_by_criteria(consumer_criteria)
        ]

        # Following logic of checking existing applicability and getting required data
        # to generate applicability is a bit more complicated than what it could be 'by design'.
        # It is to optimize the number of db queries and improving applicability generation
        # performance. Please consider the implications for applicability generation time
        # when making any modifications to this code.

        consumer_profile_map = ApplicabilityRegenerationManager._get_consumer_profile_map(
            consumer_ids)

        repo_consumer_map = ApplicabilityRegenerationManager._get_repo_consumer_map(
            consumer_ids=consumer_ids)

        # Since there could be different types of profiles and they are related (at the moment
        # these are RPMs and Modulemds in the RPM plugin), it's important to calculate applicability
        # not per profile but for a combination of all profiles of one consumer,
        # all_profiles_hash identifies that set of profiles.

        # Iterate through each unique all_profiles_hash and regenerate applicability,
        # if it doesn't exist.
        for repo_id in repo_consumer_map:
            seen_hashes = set()
            for consumer_id in repo_consumer_map[repo_id]:
                if consumer_id in consumer_profile_map:
                    all_profiles_hash = consumer_profile_map[consumer_id][
                        'all_profiles_hash']
                    if all_profiles_hash in seen_hashes:
                        continue
                    profiles = consumer_profile_map[consumer_id]['profiles']
                    seen_hashes.add(all_profiles_hash)
                    if ApplicabilityRegenerationManager._is_existing_applicability(
                            repo_id, all_profiles_hash):
                        continue
                    # If applicability does not exist, generate applicability data for given
                    # profiles and repo id.
                    ApplicabilityRegenerationManager.regenerate_applicability(
                        all_profiles_hash, profiles, repo_id)
Esempio n. 6
0
    def get(self, request):
        """
        List the available consumers.

        :param request: WSGI request object
        :type request: django.core.handlers.wsgi.WSGIRequest

        :return: Response containing a list of consumers
        :rtype: django.http.HttpResponse
        """

        query_params = request.GET

        manager = factory.consumer_query_manager()
        consumers = expand_consumers(query_params, manager.find_all())
        for consumer in consumers:
            add_link(consumer)
        return generate_json_response_with_pulp_encoder(consumers)
Esempio n. 7
0
    def POST(self, consumer_id):
        """
        Creates an async task to regenerate content applicability data for given consumer.

        :param consumer_id: The consumer ID.
        :type consumer_id: basestring
        """
        consumer_query_manager = managers.consumer_query_manager()
        if consumer_query_manager.find_by_id(consumer_id) is None:
            raise MissingResource(consumer_id=consumer_id)
        consumer_criteria = Criteria(filters={'consumer_id': consumer_id})

        task_tags = [tags.action_tag('consumer_content_applicability_regeneration')]
        async_result = regenerate_applicability_for_consumers.apply_async_with_reservation(
            tags.RESOURCE_CONSUMER_TYPE,
            consumer_id,
            (consumer_criteria.as_dict(),),
            tags=task_tags)
        raise OperationPostponed(async_result)
Esempio n. 8
0
    def regenerate_applicability_for_consumers(consumer_criteria):
        """
        Regenerate and save applicability data for given updated consumers.

        :param consumer_criteria: The consumer selection criteria
        :type consumer_criteria: dict
        """
        consumer_criteria = Criteria.from_dict(consumer_criteria)
        consumer_query_manager = managers.consumer_query_manager()
        bind_manager = managers.consumer_bind_manager()
        consumer_profile_manager = managers.consumer_profile_manager()

        # Process consumer_criteria and get all the consumer ids satisfied by the criteria
        consumer_criteria.fields = ['id']
        consumer_ids = [c['id'] for c in consumer_query_manager.find_by_criteria(consumer_criteria)]

        # Following logic of checking existing applicability and getting required data
        # to generate applicability is a bit more complicated than what it could be 'by design'.
        # It is to optimize the number of db queries and improving applicability generation
        # performance. Please consider the implications for applicability generation time
        # when making any modifications to this code.

        # Get all unit profiles associated with given consumers
        unit_profile_criteria = Criteria(
            filters={'consumer_id': {'$in': consumer_ids}},
            fields=['consumer_id', 'profile_hash', 'content_type', 'id'])
        all_unit_profiles = consumer_profile_manager.find_by_criteria(unit_profile_criteria)

        # Create a consumer-profile map with consumer id as the key and list of tuples
        # with profile details as the value
        consumer_unit_profiles_map = {}
        # Also create a map of profile_id keyed by profile_hash for profile lookup.
        profile_hash_profile_id_map = {}
        for unit_profile in all_unit_profiles:
            profile_hash = unit_profile['profile_hash']
            content_type = unit_profile['content_type']
            consumer_id = unit_profile['consumer_id']
            profile_id = unit_profile['id']

            profile_tuple = (profile_hash, content_type)
            # Add this tuple to the list of profile tuples for a consumer
            consumer_unit_profiles_map.setdefault(consumer_id, []).append(profile_tuple)

            # We need just one profile_id per profile_hash to be used in regenerate_applicability
            # method to get the actual profile corresponding to given profile_hash.
            if profile_hash not in profile_hash_profile_id_map:
                profile_hash_profile_id_map[profile_hash] = profile_id

        # Get all repos bound to given consumers
        bind_criteria = Criteria(filters={'consumer_id': {'$in': consumer_ids}},
                                 fields=['repo_id', 'consumer_id'])
        all_repo_bindings = bind_manager.find_by_criteria(bind_criteria)

        # Create a repo-consumer map with repo_id as the key and consumer_id list as the value
        repo_consumers_map = {}
        for binding in all_repo_bindings:
            repo_consumers_map.setdefault(binding['repo_id'], []).append(binding['consumer_id'])

        # Create a set of (repo_id, (profile_hash, content_type))
        repo_profile_hashes = set()
        for repo_id, consumer_id_list in repo_consumers_map.items():
            for consumer_id in consumer_id_list:
                if consumer_id in consumer_unit_profiles_map:
                    for unit_profile_tuple in consumer_unit_profiles_map[consumer_id]:
                        repo_profile_hashes.add((repo_id, unit_profile_tuple))

        # Iterate through each tuple in repo_profile_hashes set and regenerate applicability,
        # if it doesn't exist. These are all guaranteed to be unique tuples because of the logic
        # used to create maps and sets above, eliminating multiple unnecessary queries
        # to check for existing applicability for same profiles.
        manager = managers.applicability_regeneration_manager()
        for repo_id, (profile_hash, content_type) in repo_profile_hashes:
            # Check if applicability for given profile_hash and repo_id already exists
            if ApplicabilityRegenerationManager._is_existing_applicability(repo_id, profile_hash):
                continue
            # If applicability does not exist, generate applicability data for given profile
            # and repo id.
            profile_id = profile_hash_profile_id_map[profile_hash]
            manager.regenerate_applicability(profile_hash, content_type, profile_id, repo_id)
Esempio n. 9
0
    def regenerate_applicability_for_consumers(consumer_criteria):
        """
        Regenerate and save applicability data for given updated consumers.

        :param consumer_criteria: The consumer selection criteria
        :type consumer_criteria: dict
        """
        consumer_criteria = Criteria.from_dict(consumer_criteria)
        consumer_query_manager = managers.consumer_query_manager()
        bind_manager = managers.consumer_bind_manager()
        consumer_profile_manager = managers.consumer_profile_manager()

        # Process consumer_criteria and get all the consumer ids satisfied by the criteria
        consumer_criteria.fields = ['id']
        consumer_ids = [
            c['id']
            for c in consumer_query_manager.find_by_criteria(consumer_criteria)
        ]

        # Following logic of checking existing applicability and getting required data
        # to generate applicability is a bit more complicated than what it could be 'by design'.
        # It is to optimize the number of db queries and improving applicability generation
        # performance. Please consider the implications for applicability generation time
        # when making any modifications to this code.

        # Get all unit profiles associated with given consumers
        unit_profile_criteria = Criteria(
            filters={'consumer_id': {
                '$in': consumer_ids
            }},
            fields=['consumer_id', 'profile_hash', 'content_type', 'id'])
        all_unit_profiles = consumer_profile_manager.find_by_criteria(
            unit_profile_criteria)

        # Create a consumer-profile map with consumer id as the key and list of tuples
        # with profile details as the value
        consumer_unit_profiles_map = {}
        # Also create a map of profile_id keyed by profile_hash for profile lookup.
        profile_hash_profile_id_map = {}
        for unit_profile in all_unit_profiles:
            profile_hash = unit_profile['profile_hash']
            content_type = unit_profile['content_type']
            consumer_id = unit_profile['consumer_id']
            profile_id = unit_profile['id']

            profile_tuple = (profile_hash, content_type)
            # Add this tuple to the list of profile tuples for a consumer
            consumer_unit_profiles_map.setdefault(consumer_id,
                                                  []).append(profile_tuple)

            # We need just one profile_id per profile_hash to be used in regenerate_applicability
            # method to get the actual profile corresponding to given profile_hash.
            if profile_hash not in profile_hash_profile_id_map:
                profile_hash_profile_id_map[profile_hash] = profile_id

        # Get all repos bound to given consumers
        bind_criteria = Criteria(
            filters={'consumer_id': {
                '$in': consumer_ids
            }},
            fields=['repo_id', 'consumer_id'])
        all_repo_bindings = bind_manager.find_by_criteria(bind_criteria)

        # Create a repo-consumer map with repo_id as the key and consumer_id list as the value
        repo_consumers_map = {}
        for binding in all_repo_bindings:
            repo_consumers_map.setdefault(binding['repo_id'],
                                          []).append(binding['consumer_id'])

        # Create a set of (repo_id, (profile_hash, content_type))
        repo_profile_hashes = set()
        for repo_id, consumer_id_list in repo_consumers_map.items():
            for consumer_id in consumer_id_list:
                if consumer_id in consumer_unit_profiles_map:
                    for unit_profile_tuple in consumer_unit_profiles_map[
                            consumer_id]:
                        repo_profile_hashes.add((repo_id, unit_profile_tuple))

        # Iterate through each tuple in repo_profile_hashes set and regenerate applicability,
        # if it doesn't exist. These are all guaranteed to be unique tuples because of the logic
        # used to create maps and sets above, eliminating multiple unnecessary queries
        # to check for existing applicability for same profiles.
        manager = managers.applicability_regeneration_manager()
        for repo_id, (profile_hash, content_type) in repo_profile_hashes:
            # Check if applicability for given profile_hash and repo_id already exists
            if ApplicabilityRegenerationManager._is_existing_applicability(
                    repo_id, profile_hash):
                continue
            # If applicability does not exist, generate applicability data for given profile
            # and repo id.
            profile_id = profile_hash_profile_id_map[profile_hash]
            manager.regenerate_applicability(profile_hash, content_type,
                                             profile_id, repo_id)
Esempio n. 10
0
 def __init__(self):
     super(ConsumerSearch, self).__init__(
         managers.consumer_query_manager().find_by_criteria)
Esempio n. 11
0
    def find_applicable_units(self, consumer_criteria=None, repo_criteria=None, unit_criteria=None, override_config=None):
        """
        Determine and report which of the content units specified by the unit_criteria
        are applicable to consumers specified by the consumer_criteria
        with repos specified by repo_criteria. If consumer_criteria is None,
        all consumers registered to the Pulp server are checked for applicability.
        If repo_criteria is None, all repos bound to the consumer are taken
        into consideration. If unit_criteria contains an empty list for a specific type,
        all units with specific type in the repos bound to the consumer
        are taken into consideration. 

        :param consumer_criteria: The consumer selection criteria.
        :type consumer_criteria: dict

        :param repo_criteria: The repo selection criteria.
        :type repo_criteria: dict

        :param unit_criteria: A dictionary of type_id : unit selection criteria
        :type units: dict
                {<type_id1> : <unit_criteria_for_type_id1>,
                 <type_id2> : <unit_criteria_for_type_id2>}
      
        :param override_config: Additional configuration options to be accepted from user
        :type override_config: dict

        :return: applicability reports dictionary keyed by content type id
        :rtype: dict
        """
        result = {}
        conduit = ProfilerConduit()
        consumer_query_manager = managers.consumer_query_manager()
        bind_manager = managers.consumer_bind_manager()

        # Process Repo Criteria
        if repo_criteria:
            # Get repo ids satisfied by specified repo criteria
            repo_query_manager = managers.repo_query_manager()
            repo_criteria_ids = [r['id'] for r in repo_query_manager.find_by_criteria(repo_criteria)]
            # if repo_criteria is specified and there are no repos satisfying the criteria, return empty result
            if not repo_criteria_ids:
                return result
        else:
            repo_criteria_ids = None

        # Process Consumer Criteria
        if consumer_criteria:
            # Get consumer ids satisfied by specified consumer criteria
            consumer_ids = [c['id'] for c in consumer_query_manager.find_by_criteria(consumer_criteria)]
        else:
            if repo_criteria_ids:
                # If repo_criteria is specified, get all the consumers bound to the repos
                # satisfied by repo_criteria
                bind_criteria = Criteria(filters={"repo_id": {"$in": repo_criteria_ids}})
                consumer_ids = [b['consumer_id'] for b in bind_manager.find_by_criteria(bind_criteria)]
                # Remove duplicate consumer ids
                consumer_ids = list(set(consumer_ids))
            else:
                # Get all consumer ids registered to the Pulp server
                consumer_ids = [c['id'] for c in consumer_query_manager.find_all()]
        # if there are no relevant consumers, return empty result
        if not consumer_ids:
            return result
        else:
            # Based on the consumers, get all the repos bound to the consumers in consideration
            # and find intersection of repo_criteria_ids and consumer_repo_ids
            bind_criteria = Criteria(filters={"consumer_id": {"$in": consumer_ids}})
            consumer_repo_ids = [b['repo_id'] for b in bind_manager.find_by_criteria(bind_criteria)]
            if not repo_criteria_ids:
                repo_criteria_ids = list(set(consumer_repo_ids))
            else:
                repo_criteria_ids = list(set(consumer_repo_ids) & set(repo_criteria_ids))
            if not repo_criteria_ids:
                return result

        # Process Unit Criteria
        if unit_criteria:
            # If unit_criteria is specified, get unit ids satisfied by the criteria for each content type
            # and save them in a dictionary keyed by the content type
            unit_ids_by_type = {}
            content_query_manager = managers.content_query_manager()
            for type_id, criteria in unit_criteria.items():
                if criteria:
                    criteria_ids = [u['_id'] for u in content_query_manager.find_by_criteria(type_id, criteria)]
                    # If there are no units satisfied by the criteria, skip adding it to the dictionary
                    if criteria_ids:
                        unit_ids_by_type[type_id] = criteria_ids
                else:
                    # If criteria for a content type id is None or empty dictionary, add it to the dictionary
                    # with empty list as a value. This will be interpreted as all units of that specific type
                    unit_ids_by_type[type_id] = []
        else:
            # If unit_criteria is not specified set unit_ids_by_type to None to differentiate between
            # considering all units vs considering 0 units since no units were found satisfying given criteria
            unit_ids_by_type = None

        # Create a dictionary with consumer profile and repo_ids bound to the consumer keyed by consumer id
        consumer_profile_and_repo_ids = {}
        all_relevant_repo_ids = set()
        for consumer_id in consumer_ids:
            # Find repos bound to the consumer in consideration and find an intersection of bound repos to the
            # repos specified by repo_criteria
            consumer_bound_repo_ids = [b['repo_id'] for b in bind_manager.find_by_consumer(consumer_id)]
            consumer_bound_repo_ids = list(set(consumer_bound_repo_ids))
            # If repo_criteria is not specified, use repos bound to the consumer, else take intersection 
            # of repos specified in the criteria and repos bound to the consumer.
            if repo_criteria_ids is None:
                repo_ids = consumer_bound_repo_ids
            else:
                repo_ids = list(set(consumer_bound_repo_ids) & set(repo_criteria_ids))

            if repo_ids:
                # Save all eligible repo ids to get relevant plugin unit keys when unit_criteria is not specified
                all_relevant_repo_ids = (all_relevant_repo_ids | set(repo_ids))
                consumer_profile_and_repo_ids[consumer_id] = {'repo_ids': repo_ids}
                consumer_profile_and_repo_ids[consumer_id]['profiled_consumer'] = self.__profiled_consumer(consumer_id)

        # Get relevant units if unit_criteria is not specified
        units = self.__populate_units(unit_ids_by_type, list(all_relevant_repo_ids))

        if units:
            # Call respective profiler api according to the unit type to check for applicability
            for typeid, unit_ids in units.items():
                # if unit_ids is None or empty, continue to the next type id
                if not unit_ids:
                    continue
                # Find a profiler for each type id and find units applicable using that profiler.
                profiler, cfg = self.__profiler(typeid)
                call_config = PluginCallConfiguration(plugin_config=cfg, repo_plugin_config=None,
                                                      override_config=override_config)
                try:
                    report_list = profiler.find_applicable_units(consumer_profile_and_repo_ids, typeid, unit_ids, call_config, conduit)
                except PulpExecutionException:
                    report_list = None

                if report_list is None:
                    _LOG.warn("Profiler for unit type [%s] is not returning applicability reports" % typeid)
                else:
                    result[typeid] = report_list

        return result
Esempio n. 12
0
    def find_applicable_units(self,
                              consumer_criteria=None,
                              repo_criteria=None,
                              unit_criteria=None,
                              override_config=None):
        """
        Determine and report which of the content units specified by the unit_criteria
        are applicable to consumers specified by the consumer_criteria
        with repos specified by repo_criteria. If consumer_criteria is None,
        all consumers registered to the Pulp server are checked for applicability.
        If repo_criteria is None, all repos bound to the consumer are taken
        into consideration. If unit_criteria contains an empty list for a specific type,
        all units with specific type in the repos bound to the consumer
        are taken into consideration. 

        :param consumer_criteria: The consumer selection criteria.
        :type consumer_criteria: dict

        :param repo_criteria: The repo selection criteria.
        :type repo_criteria: dict

        :param unit_criteria: A dictionary of type_id : unit selection criteria
        :type units: dict
                {<type_id1> : <unit_criteria_for_type_id1>,
                 <type_id2> : <unit_criteria_for_type_id2>}
      
        :param override_config: Additional configuration options to be accepted from user
        :type override_config: dict

        :return: applicability reports dictionary keyed by content type id
        :rtype: dict
        """
        result = {}
        conduit = ProfilerConduit()
        consumer_query_manager = managers.consumer_query_manager()
        bind_manager = managers.consumer_bind_manager()

        # Process Repo Criteria
        if repo_criteria:
            # Get repo ids satisfied by specified repo criteria
            repo_query_manager = managers.repo_query_manager()
            repo_criteria_ids = [
                r['id']
                for r in repo_query_manager.find_by_criteria(repo_criteria)
            ]
            # if repo_criteria is specified and there are no repos satisfying the criteria, return empty result
            if not repo_criteria_ids:
                return result
        else:
            repo_criteria_ids = None

        # Process Consumer Criteria
        if consumer_criteria:
            # Get consumer ids satisfied by specified consumer criteria
            consumer_ids = [
                c['id'] for c in consumer_query_manager.find_by_criteria(
                    consumer_criteria)
            ]
        else:
            if repo_criteria_ids:
                # If repo_criteria is specified, get all the consumers bound to the repos
                # satisfied by repo_criteria
                bind_criteria = Criteria(
                    filters={"repo_id": {
                        "$in": repo_criteria_ids
                    }})
                consumer_ids = [
                    b['consumer_id']
                    for b in bind_manager.find_by_criteria(bind_criteria)
                ]
                # Remove duplicate consumer ids
                consumer_ids = list(set(consumer_ids))
            else:
                # Get all consumer ids registered to the Pulp server
                consumer_ids = [
                    c['id'] for c in consumer_query_manager.find_all()
                ]
        # if there are no relevant consumers, return empty result
        if not consumer_ids:
            return result
        else:
            # Based on the consumers, get all the repos bound to the consumers in consideration
            # and find intersection of repo_criteria_ids and consumer_repo_ids
            bind_criteria = Criteria(
                filters={"consumer_id": {
                    "$in": consumer_ids
                }})
            consumer_repo_ids = [
                b['repo_id']
                for b in bind_manager.find_by_criteria(bind_criteria)
            ]
            if not repo_criteria_ids:
                repo_criteria_ids = list(set(consumer_repo_ids))
            else:
                repo_criteria_ids = list(
                    set(consumer_repo_ids) & set(repo_criteria_ids))
            if not repo_criteria_ids:
                return result

        # Create a dictionary with consumer profile and repo_ids bound to the consumer keyed by consumer id
        consumer_profile_and_repo_ids = {}
        all_relevant_repo_ids = set()
        for consumer_id in consumer_ids:
            # Find repos bound to the consumer in consideration and find an intersection of bound repos to the
            # repos specified by repo_criteria
            consumer_bound_repo_ids = [
                b['repo_id']
                for b in bind_manager.find_by_consumer(consumer_id)
            ]
            consumer_bound_repo_ids = list(set(consumer_bound_repo_ids))
            # If repo_criteria is not specified, use repos bound to the consumer, else take intersection
            # of repos specified in the criteria and repos bound to the consumer.
            if repo_criteria_ids is None:
                repo_ids = consumer_bound_repo_ids
            else:
                repo_ids = list(
                    set(consumer_bound_repo_ids) & set(repo_criteria_ids))

            if repo_ids:
                # Save all eligible repo ids to get relevant plugin unit keys when unit_criteria is not specified
                all_relevant_repo_ids = (all_relevant_repo_ids | set(repo_ids))
                consumer_profile_and_repo_ids[consumer_id] = {
                    'repo_ids': repo_ids
                }
                consumer_profile_and_repo_ids[consumer_id][
                    'profiled_consumer'] = self.__profiled_consumer(
                        consumer_id)

        if not unit_criteria:
            return result

        # Call respective profiler api according to the unit type to check for applicability
        for unit_type_id, criteria in unit_criteria.items():
            # Find a profiler for each type id and find units applicable using that profiler.
            profiler, cfg = self.__profiler(unit_type_id)
            call_config = PluginCallConfiguration(
                plugin_config=cfg,
                repo_plugin_config=None,
                override_config=override_config)
            try:
                report_list = profiler.find_applicable_units(
                    consumer_profile_and_repo_ids, unit_type_id, criteria,
                    call_config, conduit)
            except PulpExecutionException:
                report_list = None

            if report_list is None:
                _LOG.warn(
                    "Profiler for unit type [%s] is not returning applicability reports"
                    % unit_type_id)
            else:
                result[unit_type_id] = report_list

        return result
Esempio n. 13
0
    def units_applicable(self, consumer_criteria=None, repo_criteria=None, units=None):
        """
        Determine and report which of the specified content units
        are applicable to consumers specified by the I{consumer_criteria}
        with repos specified by I{repo_criteria}. If consumer_criteria is None, 
        all consumers registered to the Pulp server are checked for applicability. 
        If repo_criteria is None, all repos bound to the consumer are taken 
        into consideration. If units dictinary contains an empty list for a specific type, 
        all units with specific type in the repos bound to the consumer 
        are taken into consideration. Returns a dictionary with applicability reports 
        for each unit keyed by a consumer id and further keyed by unit type id  -

            {<consumer_id1>:
               { <unit_type_id1> : [<ApplicabilityReport>],
                 <unit_type_id1> : [<ApplicabilityReport>]},
             <consumer_id2>:
               { <unit_type_id1> : [<ApplicabilityReport>]}
            }

        :param consumer_criteria: The consumer selection criteria.
        :type consumer_criteria: dict

        :param repo_criteria: The repo selection criteria.
        :type repo_criteria: dict

        :param units: A dictionary of type_id : list of unit metadata
        :type units: dict
                {<type_id1> : [{<unit1_metadata>}, {<unit2_metadata>}, ..],
                 <type_id2> : [{<unit1_metadata>}, {<unit2_metadata>}, ..]}

        :return: a dictionary with applicability reports for each unit 
                 keyed by a consumer id and further keyed by unit type id.
                 See above for sample return report.
        :rtype: dict
        """
        result = {}
        conduit = ProfilerConduit()
        
        # Get repo ids satisfied by specified consumer criteria
        if repo_criteria:
            repo_query_manager = managers.repo_query_manager()
            repo_criteria_ids = [r['id'] for r in repo_query_manager.find_by_criteria(repo_criteria)]
        else:
            repo_criteria_ids = None

        consumer_query_manager = managers.consumer_query_manager()
        bind_manager = managers.consumer_bind_manager()
        
        if consumer_criteria:
            # Get consumer ids satisfied by specified consumer criteria
            consumer_ids = [c['id'] for c in consumer_query_manager.find_by_criteria(consumer_criteria)]
        else:
            if repo_criteria_ids is not None:
                # If repo_criteria is specified, get all the consumers bound to the repos
                # satisfied by repo_criteria
                bind_criteria = {"filters": {"repo_id": {"$in": repo_criteria_ids}}}
                consumer_ids = [b['consumer_id'] for b in bind_manager.find_by_criteria(bind_criteria)]
            else:
                # Get all consumer ids registered to the Pulp server
                consumer_ids = [c['id'] for c in consumer_query_manager.find_all()]

        # Iterate through each consumer to collect applicability reports
        for consumer_id in consumer_ids:
            result[consumer_id] = {}
            
            # Find repos bound to a consumer
            bindings = bind_manager.find_by_consumer(consumer_id)
            bound_repo_ids = [b['repo_id'] for b in bindings]

            # If repo_criteria is not specified, use repos bound to the consumer, else take intersection 
            # of repos specified in the criteria and repos bound to the consumer.
            if repo_criteria_ids is None:
                repo_ids = bound_repo_ids
            else:
                repo_ids = list(set(bound_repo_ids) & set(repo_criteria_ids))

            plugin_unit_keys = self.__parse_units(units, repo_ids)
            if plugin_unit_keys:
                pc = self.__profiled_consumer(consumer_id)
                for typeid, unit_keys in plugin_unit_keys.items():
                    # Find a profiler for each type id and find units applicable using that profiler.
                    profiler, cfg = self.__profiler(typeid)
                    try: 
                        report_list = profiler.units_applicable(pc, repo_ids, typeid, unit_keys, cfg, conduit)
                    except PulpExecutionException:
                        report_list = None

                    if report_list is not None:
                        result[consumer_id][typeid] = report_list
                    else: 
                        _LOG.warn("Profiler for unit type [%s] is not returning applicability reports" % typeid)

        return result