def filter_out_overlapping(self, pools):
        entitled_product_ids_to_certs = self._get_entitled_product_to_cert_map(
        )
        filtered_pools = []
        for pool in pools:
            provided_ids = set(
                [p['productId'] for p in pool['providedProducts']])
            wrapped_pool = PoolWrapper(pool)
            # NOTE: We may have to check for other types or handle the case of a product with no type in the future
            if wrapped_pool.get_product_attributes('type')['type'] == 'SVC':
                provided_ids.add(pool['productId'])
            overlap = 0
            possible_overlap_pids = provided_ids.intersection(
                list(entitled_product_ids_to_certs.keys()))
            for productid in possible_overlap_pids:
                if self._dates_overlap(pool, entitled_product_ids_to_certs[productid]) \
                        and productid not in self.sorter.partially_valid_products:
                    overlap += 1
                else:
                    break
            if overlap != len(provided_ids) or wrapped_pool.get_stacking_id(
            ) in self.sorter.partial_stacks:
                filtered_pools.append(pool)

        return filtered_pools
 def _machine_type(self, pools):
     virt_only = None
     first = True
     for pool in pools:
         if first:
             virt_only = PoolWrapper(pool).is_virt_only()
             first = False
         else:
             if virt_only != PoolWrapper(pool).is_virt_only():
                 return None
     return virt_only
    def _do_update(self):
        result = {}
        if self.identity.is_valid():
            self.pool_cache.load_status(
                self.cp_provider.get_consumer_auth_cp(), self.identity.uuid)
            entitlement_list = self.pool_cache.server_status

            if entitlement_list is not None:
                for ent in entitlement_list:
                    pool = PoolWrapper(ent.get('pool', {}))
                    pool_type = pool.get_pool_type()
                    result[pool.get_id()] = pool_type

        self.pooltype_map.update(result)
    def _do_update(self):
        result = {}
        if self.identity.is_valid():
            self.pool_cache.load_status(self.cp_provider.get_consumer_auth_cp(),
                                        self.identity.uuid)
            entitlement_list = self.pool_cache.server_status

            if entitlement_list is not None:
                for ent in entitlement_list:
                    pool = PoolWrapper(ent.get('pool', {}))
                    pool_type = pool.get_pool_type()
                    result[pool.get_id()] = pool_type

        self.pooltype_map.update(result)
def get_available_entitlements(facts, get_all=False, active_on=None,
        overlapping=False, uninstalled=False, text=None):
    """
    Returns a list of entitlement pools from the server.

    Facts will be updated if appropriate before making the request, to ensure
    the rules on the server will pass if appropriate.

    The 'all' setting can be used to return all pools, even if the rules do
    not pass. (i.e. show pools that are incompatible for your hardware)
    """
    columns = ['id', 'quantity', 'consumed', 'endDate', 'productName',
            'providedProducts', 'productId', 'attributes', 'pool_type',
            'service_level', 'service_type', 'suggested', 'contractNumber']

    pool_stash = PoolStash(Facts(require(ENT_DIR), require(PROD_DIR)))
    dlist = pool_stash.get_filtered_pools_list(active_on, not get_all,
           overlapping, uninstalled, text)

    for pool in dlist:
        pool_wrapper = PoolWrapper(pool)
        pool['providedProducts'] = pool_wrapper.get_provided_products()
        if allows_multi_entitlement(pool):
            pool['multi-entitlement'] = "Yes"
        else:
            pool['multi-entitlement'] = "No"

        support_attrs = pool_wrapper.get_product_attributes("support_level",
                                                            "support_type")
        pool['service_level'] = support_attrs['support_level']
        pool['service_type'] = support_attrs['support_type']
        pool['suggested'] = pool_wrapper.get_suggested_quantity()
        pool['pool_type'] = pool_wrapper.get_pool_type()

        if pool['suggested'] is None:
            pool['suggested'] = ""

    # no default, so default is None if key not found
    data = [_sub_dict(pool, columns) for pool in dlist]
    for d in data:
        if int(d['quantity']) < 0:
            d['quantity'] = _('Unlimited')
        else:
            d['quantity'] = str(int(d['quantity']) - int(d['consumed']))

        d['endDate'] = format_date(isodate.parse_date(d['endDate']))
        del d['consumed']

    return data
def getAvailableEntitlements(cpserver, consumer_uuid, facts, get_all=False, active_on=None):
    """
    Returns a list of entitlement pools from the server.

    Facts will be updated if appropriate before making the request, to ensure
    the rules on the server will pass if appropriate.

    The 'all' setting can be used to return all pools, even if the rules do
    not pass. (i.e. show pools that are incompatible for your hardware)
    """
    columns = [
        "id",
        "quantity",
        "consumed",
        "endDate",
        "productName",
        "providedProducts",
        "productId",
        "attributes",
        "multi-entitlement",
        "service_level",
        "service_type",
    ]

    dlist = list_pools(cpserver, consumer_uuid, facts, get_all, active_on)

    for pool in dlist:
        pool_wrapper = PoolWrapper(pool)
        if allows_multi_entitlement(pool):
            pool["multi-entitlement"] = "Yes"
        else:
            pool["multi-entitlement"] = "No"

        support_attrs = pool_wrapper.get_product_attributes("support_level", "support_type")
        pool["service_level"] = support_attrs["support_level"]
        pool["service_type"] = support_attrs["support_type"]

    data = [_sub_dict(pool, columns) for pool in dlist]
    for d in data:
        if int(d["quantity"]) < 0:
            d["quantity"] = "unlimited"
        else:
            d["quantity"] = str(int(d["quantity"]) - int(d["consumed"]))

        d["endDate"] = formatDate(parseDate(d["endDate"]))
        del d["consumed"]

    return data
Exemple #7
0
    def _create_wrapper(self,
                        add_is_virt_only=False,
                        is_virt_only_value="true",
                        add_stacking_id=False,
                        stacking_id=None,
                        pool_type=None,
                        add_management_enabled=False,
                        management_enabled_value="true"):
        attrs = {}
        if add_is_virt_only:
            attrs['virt_only'] = is_virt_only_value

        prod_attrs = {}
        if add_stacking_id:
            prod_attrs['stacking_id'] = stacking_id

        if add_management_enabled:
            prod_attrs['management_enabled'] = management_enabled_value

        calculatedAttributes = None
        if pool_type:
            calculatedAttributes = {'compliance_type': pool_type}
        pool = create_pool("pid",
                           "pname",
                           attributes=create_attribute_list(attrs),
                           productAttributes=create_attribute_list(prod_attrs),
                           calculatedAttributes=calculatedAttributes)
        return PoolWrapper(pool)
Exemple #8
0
def get_available_entitlements(cpserver,
                               consumer_uuid,
                               facts,
                               get_all=False,
                               active_on=None):
    """
    Returns a list of entitlement pools from the server.

    Facts will be updated if appropriate before making the request, to ensure
    the rules on the server will pass if appropriate.

    The 'all' setting can be used to return all pools, even if the rules do
    not pass. (i.e. show pools that are incompatible for your hardware)
    """
    columns = [
        'id', 'quantity', 'consumed', 'endDate', 'productName',
        'providedProducts', 'productId', 'attributes', 'multi-entitlement',
        'service_level', 'service_type'
    ]

    dlist = list_pools(cpserver, consumer_uuid, facts, get_all, active_on)

    for pool in dlist:
        pool_wrapper = PoolWrapper(pool)
        if allows_multi_entitlement(pool):
            pool['multi-entitlement'] = "Yes"
        else:
            pool['multi-entitlement'] = "No"

        support_attrs = pool_wrapper.get_product_attributes(
            "support_level", "support_type")
        pool['service_level'] = support_attrs['support_level']
        pool['service_type'] = support_attrs['support_type']

    data = [_sub_dict(pool, columns) for pool in dlist]
    for d in data:
        if int(d['quantity']) < 0:
            d['quantity'] = _('Unlimited')
        else:
            d['quantity'] = str(int(d['quantity']) - int(d['consumed']))

        d['endDate'] = format_date(isodate.parse_date(d['endDate']))
        del d['consumed']

    return data
Exemple #9
0
def get_available_entitlements(get_all=False, active_on=None, overlapping=False,
                               uninstalled=False, text=None, filter_string=None):
    """
    Returns a list of entitlement pools from the server.

    The 'all' setting can be used to return all pools, even if the rules do
    not pass. (i.e. show pools that are incompatible for your hardware)
    """
    columns = [
        'id',
        'quantity',
        'consumed',
        'endDate',
        'productName',
        'providedProducts',
        'productId',
        'attributes',
        'pool_type',
        'service_level',
        'service_type',
        'suggested',
        'contractNumber',
        'management_enabled'
    ]

    pool_stash = PoolStash()
    dlist = pool_stash.get_filtered_pools_list(active_on, not get_all,
           overlapping, uninstalled, text, filter_string)

    for pool in dlist:
        pool_wrapper = PoolWrapper(pool)
        pool['providedProducts'] = pool_wrapper.get_provided_products()
        if allows_multi_entitlement(pool):
            pool['multi-entitlement'] = "Yes"
        else:
            pool['multi-entitlement'] = "No"

        support_attrs = pool_wrapper.get_product_attributes("support_level",
                                                            "support_type")
        pool['service_level'] = support_attrs['support_level']
        pool['service_type'] = support_attrs['support_type']
        pool['suggested'] = pool_wrapper.get_suggested_quantity()
        pool['pool_type'] = pool_wrapper.get_pool_type()
        pool['management_enabled'] = pool_wrapper.management_enabled()

        if pool['suggested'] is None:
            pool['suggested'] = ""

    # no default, so default is None if key not found
    data = [_sub_dict(pool, columns) for pool in dlist]
    for d in data:
        if int(d['quantity']) < 0:
            d['quantity'] = _('Unlimited')
        else:
            d['quantity'] = str(int(d['quantity']) - int(d['consumed']))

        d['endDate'] = format_date(isodate.parse_date(d['endDate']))
        del d['consumed']

    return data
    def filter_out_overlapping(self, pools):
        entitled_product_ids_to_certs = self._get_entitled_product_to_cert_map()
        filtered_pools = []
        for pool in pools:
            provided_ids = set([p['productId'] for p in pool['providedProducts']])
            wrapped_pool = PoolWrapper(pool)
            # NOTE: We may have to check for other types or handle the case of a product with no type in the future
            if wrapped_pool.get_product_attributes('type')['type'] == 'SVC':
                provided_ids.add(pool['productId'])
            overlap = 0
            possible_overlap_pids = provided_ids.intersection(list(entitled_product_ids_to_certs.keys()))
            for productid in possible_overlap_pids:
                if self._dates_overlap(pool, entitled_product_ids_to_certs[productid]) \
                        and productid not in self.sorter.partially_valid_products:
                    overlap += 1
                else:
                    break
            if overlap != len(provided_ids) or wrapped_pool.get_stacking_id() in self.sorter.partial_stacks:
                filtered_pools.append(pool)

        return filtered_pools
def get_available_entitlements(cpserver, consumer_uuid, facts, get_all=False, active_on=None):
    """
    Returns a list of entitlement pools from the server.

    Facts will be updated if appropriate before making the request, to ensure
    the rules on the server will pass if appropriate.

    The 'all' setting can be used to return all pools, even if the rules do
    not pass. (i.e. show pools that are incompatible for your hardware)
    """
    columns = ['id', 'quantity', 'consumed', 'endDate', 'productName',
            'providedProducts', 'productId', 'attributes', 'multi-entitlement',
            'service_level', 'service_type']

    dlist = list_pools(cpserver, consumer_uuid, facts, get_all, active_on)

    for pool in dlist:
        pool_wrapper = PoolWrapper(pool)
        if allows_multi_entitlement(pool):
            pool['multi-entitlement'] = "Yes"
        else:
            pool['multi-entitlement'] = "No"

        support_attrs = pool_wrapper.get_product_attributes("support_level",
                                                            "support_type")
        pool['service_level'] = support_attrs['support_level']
        pool['service_type'] = support_attrs['support_type']

    data = [_sub_dict(pool, columns) for pool in dlist]
    for d in data:
        if int(d['quantity']) < 0:
            d['quantity'] = _('Unlimited')
        else:
            d['quantity'] = str(int(d['quantity']) - int(d['consumed']))

        d['endDate'] = format_date(isodate.parse_date(d['endDate']))
        del d['consumed']

    return data
    def add_pool(self, pool, default_quantity_value):
        self.total_contracts += 1
        self.total_contracts_label.set_text(str(self.total_contracts))
        self.subscription_name_label.set_text(pool['productName'])

        # Use unlimited for -1 quanities
        quantity = pool['quantity']
        if quantity < 0:
            quantity = _('Unlimited')
            quantity_available = -1
        else:
            quantity_available = int(pool['quantity']) - int(pool['consumed'])

        # cap the default selected quantity at the max available
        # for that pool. See #855257. Watch out for quantity_available
        # being -1 (unlimited).
        if default_quantity_value > quantity_available and quantity_available >= 0:
            default_quantity_value = quantity_available

        quantity_increment = 1
        if 'calculatedAttributes' in pool:
            calculated_attrs = pool['calculatedAttributes']

            if 'quantity_increment' in calculated_attrs:
                quantity_increment = int(
                    calculated_attrs['quantity_increment'])

        self.model.add_map({
            'contract_number':
            pool['contractNumber'],
            'consumed_fraction':
            "%s / %s" % (pool['consumed'], quantity),
            'start_date':
            isodate.parse_date(pool['startDate']),
            'end_date':
            isodate.parse_date(pool['endDate']),
            'default_quantity':
            default_quantity_value,
            'product_name':
            pool['productName'],
            'pool':
            pool,
            'is_virt_only':
            PoolWrapper(pool).is_virt_only(),
            'multi_entitlement':
            allows_multi_entitlement(pool),
            'quantity_available':
            quantity_available,
            'quantity_increment':
            quantity_increment,
        })
Exemple #13
0
    def set_model(self):
        self._dry_run_result = self._parent.dry_run_result

        # Make sure that the store is cleared each time
        # the data is loaded into the screen.
        self.store.clear()
        self.sla_label.set_markup("<b>" + self._dry_run_result.service_level +
                                  "</b>")

        for pool_quantity in self._dry_run_result.json:
            self.store.append([
                pool_quantity['pool']['productName'],
                PoolWrapper(pool_quantity['pool']).is_virt_only(),
                pool_quantity['quantity']
            ])
    def _create_wrapper(self,
                        add_is_virt_only=False,
                        is_virt_only_value="true",
                        add_stacking_id=False,
                        stacking_id=None):
        attrs = {}
        if add_is_virt_only:
            attrs['virt_only'] = is_virt_only_value

        prod_attrs = {}
        if add_stacking_id:
            prod_attrs['stacking_id'] = stacking_id

        pool = create_pool("pid",
                           "pname",
                           attributes=create_attribute_list(attrs),
                           productAttributes=create_attribute_list(prod_attrs))
        return PoolWrapper(pool)
    def add_pool(self, pool, default_quantity_value):
        self.total_contracts += 1
        self.total_contracts_label.set_text(str(self.total_contracts))
        self.subscription_name_label.set_text(pool['productName'])

        # Use unlimited for -1 quanities
        quantity = pool['quantity']
        if quantity < 0:
            quantity = _('unlimited')
            quantity_available = -1
        else:
            quantity_available = int(pool['quantity']) - int(pool['consumed'])

        row = [pool['contractNumber'],
                "%s / %s" % (pool['consumed'], quantity),
               managerlib.parseDate(pool['startDate']),
               managerlib.parseDate(pool['endDate']),
               default_quantity_value,
               pool['productName'], pool,
               PoolWrapper(pool).is_virt_only(),
               allows_multi_entitlement(pool),
               quantity_available]
        self.model.append(row)
 def _get_stacking_id(self, merged_pool):
     return PoolWrapper(merged_pool.pools[0]).get_stacking_id()
 def update_from_pools(self, pool_map):
     # pool_map maps pool ids to pool json
     for pool_id in pool_map:
         self.pooltype_map[pool_id] = PoolWrapper(
             pool_map[pool_id]).get_pool_type()
Exemple #18
0
def get_available_entitlements(
    get_all=False,
    active_on=None,
    overlapping=False,
    uninstalled=False,
    text=None,
    filter_string=None,
    future=None,
    after_date=None,
    page=0,
    items_per_page=0,
    iso_dates=False,
):
    """
    Returns a list of entitlement pools from the server.

    The 'all' setting can be used to return all pools, even if the rules do
    not pass. (i.e. show pools that are incompatible for your hardware)
    """
    columns = [
        "id",
        "quantity",
        "consumed",
        "startDate",
        "endDate",
        "productName",
        "providedProducts",
        "productId",
        "roles",
        "attributes",
        "pool_type",
        "service_level",
        "service_type",
        "usage",
        "addons",
        "suggested",
        "contractNumber",
        "management_enabled",
    ]

    pool_stash = PoolStash()
    dlist = pool_stash.get_filtered_pools_list(
        active_on,
        not get_all,
        overlapping,
        uninstalled,
        text,
        filter_string,
        future=future,
        after_date=after_date,
        page=page,
        items_per_page=items_per_page,
    )

    if iso_dates:
        date_formatter = format_iso8601_date
    else:
        date_formatter = format_date

    for pool in dlist:
        pool_wrapper = PoolWrapper(pool)
        pool["providedProducts"] = pool_wrapper.get_provided_products()
        if allows_multi_entitlement(pool):
            pool["multi-entitlement"] = "Yes"
        else:
            pool["multi-entitlement"] = "No"

        support_attrs = pool_wrapper.get_product_attributes(
            "support_level", "support_type", "roles", "usage", "addons"
        )
        pool["service_level"] = support_attrs["support_level"]
        pool["service_type"] = support_attrs["support_type"]
        pool["roles"] = support_attrs["roles"]
        pool["usage"] = support_attrs["usage"]
        pool["addons"] = support_attrs["addons"]
        pool["suggested"] = pool_wrapper.get_suggested_quantity()
        pool["pool_type"] = pool_wrapper.get_pool_type()
        pool["management_enabled"] = pool_wrapper.management_enabled()

        if pool["suggested"] is None:
            pool["suggested"] = ""

    # no default, so default is None if key not found
    data = [_sub_dict(pool, columns) for pool in dlist]
    for d in data:
        if int(d["quantity"]) < 0:
            d["quantity"] = _("Unlimited")
        else:
            d["quantity"] = str(int(d["quantity"]) - int(d["consumed"]))

        d["startDate"] = date_formatter(isodate.parse_date(d["startDate"]))
        d["endDate"] = date_formatter(isodate.parse_date(d["endDate"]))
        del d["consumed"]

    return data
Exemple #19
0
    def _do_command(self):
        """
        Executes the command.
        """
        self._validate_options()

        if self.options.installed and not self.options.pid_only:
            installed_products = products.InstalledProducts(self.cp).list(
                self.options.filter_string)

            if len(installed_products):
                print("+-------------------------------------------+")
                print(_("    Installed Product Status"))
                print("+-------------------------------------------+")

                for product in installed_products:
                    if is_simple_content_access(self.cp, self.identity):
                        print(
                            columnize(
                                INSTALLED_PRODUCT_STATUS_SCA,
                                none_wrap_columnize_callback,
                                product[0],  # Name
                                product[1],  # ID
                                product[2],  # Version
                                product[3],  # Arch
                            ) + "\n")
                    else:
                        status = STATUS_MAP[product[4]]
                        print(
                            columnize(
                                INSTALLED_PRODUCT_STATUS,
                                none_wrap_columnize_callback,
                                product[0],  # Name
                                product[1],  # ID
                                product[2],  # Version
                                product[3],  # Arch
                                status,  # Status
                                product[5],  # Status details
                                product[6],  # Start
                                product[7],  # End
                            ) + "\n")
            else:
                if self.options.filter_string:
                    print(
                        _('No installed products were found matching the expression "{filter}".'
                          ).format(filter=self.options.filter_string))
                else:
                    print(_("No installed products to list"))

        if self.options.available:
            self.assert_should_be_registered()
            on_date = None
            after_date = None
            if self.options.on_date:
                on_date = self._parse_date(self.options.on_date)
            elif self.options.after_date:
                after_date = self._parse_date(self.options.after_date)

            epools = entitlement.EntitlementService().get_available_pools(
                show_all=self.options.all,
                on_date=on_date,
                no_overlap=self.options.no_overlap,
                match_installed=self.options.match_installed,
                matches=self.options.filter_string,
                service_level=self.options.service_level,
                after_date=after_date,
            )

            if len(epools):
                if self.options.pid_only:
                    for data in epools:
                        print(data["id"])
                else:
                    print("+-------------------------------------------+")
                    print("    " + _("Available Subscriptions"))
                    print("+-------------------------------------------+")

                    for data in epools:
                        if PoolWrapper(data).is_virt_only():
                            entitlement_type = _("Virtual")
                        else:
                            entitlement_type = _("Physical")

                        if "management_enabled" in data and data[
                                "management_enabled"]:
                            data["management_enabled"] = _("Yes")
                        else:
                            data["management_enabled"] = _("No")

                        kwargs = {
                            "filter_string": self.options.filter_string,
                            "match_columns": AVAILABLE_SUBS_MATCH_COLUMNS,
                            "is_atty": sys.stdout.isatty(),
                        }
                        print(
                            columnize(
                                AVAILABLE_SUBS_LIST,
                                highlight_by_filter_string_columnize_cb,
                                data["productName"], data["providedProducts"],
                                data["productId"], data["contractNumber"]
                                or "", data["id"], data["management_enabled"],
                                data["quantity"], data["suggested"],
                                data["service_type"] or "",
                                self._split_mulit_value_field(
                                    data["roles"]), data["service_level"]
                                or "", data["usage"] or "",
                                self._split_mulit_value_field(data["addons"]),
                                data["pool_type"], data["startDate"],
                                data["endDate"], entitlement_type, **kwargs) +
                            "\n")
            elif not self.options.pid_only:
                if self.options.filter_string and self.options.service_level:
                    print(
                        _('No available subscription pools were found matching the expression "{filter}" and the service level "{level}".'
                          ).format(filter=self.options.filter_string,
                                   level=self.options.service_level))
                elif self.options.filter_string:
                    print(
                        _('No available subscription pools were found matching the expression "{filter}".'
                          ).format(filter=self.options.filter_string))
                elif self.options.service_level:
                    print(
                        _('No available subscription pools were found matching the service level "{level}".'
                          ).format(level=self.options.service_level))
                else:
                    print(_("No available subscription pools to list"))

        if self.options.consumed:
            self.print_consumed(
                service_level=self.options.service_level,
                filter_string=self.options.filter_string,
                pid_only=self.options.pid_only,
            )
    def display_pools(self):
        """
        Re-display the list of pools last queried, based on current filter options.
        """
        selection = self.top_view.get_selection()
        selected_pool_id = None
        itr = selection.get_selected()[1]
        if itr:
            selected_pool_id = self.store.get_value(itr, self.store['pool_id'])

        self.store.clear()

        # It may seem backwards that incompatible = self.filters.show_compatible
        # etc., but think of it like "if show_compatible is true, then
        # filter out all the incompatible products."
        merged_pools = self.pool_stash.merge_pools(
            incompatible=self.filters.show_compatible,
            overlapping=self.filters.show_no_overlapping,
            uninstalled=self.filters.show_installed,
            subscribed=True,
            text=self.get_filter_text())

        if self.pool_stash.all_pools_size() == 0:
            self.sub_details.clear()
            # If the date is None (now), use current time
            on_date = self.date_picker.date or datetime.datetime.now()
            self.display_message(
                _("No subscriptions are available on %s.") %
                on_date.strftime("%Y-%m-%d"))
            return

        if len(merged_pools) == 0:
            self.sub_details.clear()
            self.display_message(_("No subscriptions match current filters."))
            return

        # Hide the no subscriptions label and show the pools list:
        self.widget_switcher.set_active(1)

        sorter = managerlib.MergedPoolsStackingGroupSorter(
            list(merged_pools.values()))
        for group in sorter.groups:
            tree_iter = None
            if group.name and len(group.entitlements) > 1:
                tree_iter = self.store.add_map(
                    tree_iter, self._create_parent_map(group.name))

            for entry in group.entitlements:
                quantity_available = 0
                if entry.quantity < 0:
                    available = _('Unlimited')
                    quantity_available = -1
                else:
                    available = entry.quantity - entry.consumed
                    quantity_available = entry.quantity - entry.consumed

                pool = entry.pools[0]
                # Use the maximum suggested quantity, not the first one.  BZ 1022198
                # This is still incorrect when quantities from multiple merged pools are required
                suggested_quantity = max(
                    [self.calculate_default_quantity(p) for p in entry.pools])

                pool_type = PoolWrapper(pool).get_pool_type()

                attrs = self._product_attrs_to_dict(pool['productAttributes'])

                # Display support level and type if the attributes are present:
                support_level = ""
                support_type = ""
                if 'support_level' in attrs:
                    support_level = attrs['support_level']
                if 'support_type' in attrs:
                    support_type = attrs['support_type']

                quantity_increment = 1
                if 'calculatedAttributes' in pool:
                    calculated_attrs = pool['calculatedAttributes']

                    if 'quantity_increment' in calculated_attrs:
                        quantity_increment = int(
                            calculated_attrs['quantity_increment'])

                self.store.add_map(
                    tree_iter,
                    {
                        'virt_only':
                        self._machine_type(entry.pools),
                        'product_name':
                        str(entry.product_name),
                        'product_name_formatted':
                        apply_highlight(entry.product_name,
                                        self.get_filter_text()),
                        'quantity_to_consume':
                        suggested_quantity,
                        'available':
                        str(available),
                        'product_id':
                        str(entry.product_id),
                        'pool_id':
                        entry.pools[0]
                        ['id'],  # not displayed, just for lookup later
                        'merged_pools':
                        entry,  # likewise not displayed, for subscription
                        'align':
                        0.5,
                        'multi-entitlement':
                        allows_multi_entitlement(pool),
                        'background':
                        None,
                        'quantity_available':
                        quantity_available,
                        'support_level':
                        support_level,
                        'support_type':
                        support_type,
                        'quantity_increment':
                        quantity_increment,
                        'pool_type':
                        str(pool_type)
                    })

        # Ensure that all nodes are expanded in the tree view.
        self.top_view.expand_all()
        self._stripe_rows(None, self.store)

        # set the selection/details back to what they were, if possible
        def select_row(model, path, itr, data):
            if model.get_value(itr, model['pool_id']) == data[0]:
                data[1].set_cursor(path)
                return True

        # Attempt to re-select if there was a selection
        if selected_pool_id:
            self.store.foreach(select_row, (selected_pool_id, self.top_view))

        # If we don't have a selection, clear the sub_details view
        # TODO: is this conditional necessary?  If so, when?
        if not self.top_view.get_selection().get_selected()[1]:
            self.sub_details.clear()