def _subscribe_server_to_capable_channels(server_id, scheduler, capability):
    log_debug(4, server_id, scheduler, capability)
    # Look through the channels this server is already subscribed to
    h = rhnSQL.prepare(_query_lookup_subscribed_server_channels)
    h.execute(server_id=server_id)
    base_channel_id = None
    channels = []
    while 1:
        row = h.fetchone_dict()
        if not row:
            break
        channel_id = row['channel_id']
        if row['is_base_channel']:
            base_channel_id = channel_id
        channels.append((channel_id, 1))
    if base_channel_id is None:
        raise MissingBaseChannelError()

    org_id = rhnSQL.Table('rhnServer', 'id')[server_id]['org_id']

    # Get the child channels this system is *not* subscribed to
    h = rhnSQL.prepare(_query_lookup_unsubscribed_server_channels)
    h.execute(server_id=server_id,
              org_id=org_id,
              base_channel_id=base_channel_id)
    l = map(lambda x: (x['id'], 0), h.fetchall_dict() or [])
    channels.extend(l)
    # We now have a list of channels; look for one that provides the
    # capability
    for channel_id, is_subscribed in channels:
        log_debug(5, "Checking channel:", channel_id, "; subscribed:",
                  is_subscribed)
        packages = _channel_provides_capability(channel_id, capability)
        if packages:
            if is_subscribed:
                log_debug(4, "Already subscribed; found packages", packages)
                return packages

            # Try to subscribe to it
            try:
                rhnChannel._subscribe_sql(server_id, channel_id, 0)
            except rhnChannel.SubscriptionCountExceeded:
                # Try another one
                continue
            log_debug(4, "Subscribed to", channel_id, "Found packages",
                      packages)
            # We subscribed to this channel - we're done
            return packages

    # No channels provide this capability - we're done
    log_debug(4, "No channels to provide capability", capability)
    return None
Example #2
0
def _subscribe_server_to_capable_channels(server_id, scheduler, capability):
    log_debug(4, server_id, scheduler, capability)
    # Look through the channels this server is already subscribed to
    h = rhnSQL.prepare(_query_lookup_subscribed_server_channels)
    h.execute(server_id=server_id)
    base_channel_id = None
    channels = []
    while 1:
        row = h.fetchone_dict()
        if not row:
            break
        channel_id = row['channel_id']
        if row['is_base_channel']:
            base_channel_id = channel_id
        channels.append((channel_id, 1))
    if base_channel_id is None:
        raise MissingBaseChannelError()

    org_id = rhnSQL.Table('rhnServer', 'id')[server_id]['org_id']

    # Get the child channels this system is *not* subscribed to
    h = rhnSQL.prepare(_query_lookup_unsubscribed_server_channels)
    h.execute(server_id=server_id, org_id=org_id,
        base_channel_id=base_channel_id)
    l = map(lambda x: (x['id'], 0), h.fetchall_dict() or [])
    channels.extend(l)
    # We now have a list of channels; look for one that provides the
    # capability
    for channel_id, is_subscribed in channels:
        log_debug(5, "Checking channel:", channel_id, "; subscribed:",
            is_subscribed)
        packages = _channel_provides_capability(channel_id, capability)
        if packages:
            if is_subscribed:
                log_debug(4, "Already subscribed; found packages", packages)
                return packages

            # Try to subscribe to it
            try:
                rhnChannel._subscribe_sql(server_id, channel_id, 0)
            except rhnChannel.SubscriptionCountExceeded:
                # Try another one
                continue
            log_debug(4, "Subscribed to", channel_id,
                "Found packages", packages)
            # We subscribed to this channel - we're done
            return packages

    # No channels provide this capability - we're done
    log_debug(4, "No channels to provide capability", capability)
    return None
Example #3
0
def token_channels(server, server_arch, tokens_obj):
    """ Handle channel subscriptions for the registration token """
    assert(isinstance(tokens_obj, ActivationTokens))

    server_id, server_arch_id = server['id'], server['server_arch_id']

    # what channels are associated with this token (filter only those
    # compatible with this server)
    h = rhnSQL.prepare("""
    select
        rtc.channel_id id, c.name, c.label, c.parent_channel
    from
        rhnRegTokenChannels rtc,
        rhnChannel c,
        rhnServerChannelArchCompat scac
    where rtc.token_id = :token_id
        and rtc.channel_id = c.id
        and c.channel_arch_id = scac.channel_arch_id
        and scac.server_arch_id = :server_arch_id
    """)

    chash = {}
    base_channel_token = None
    base_channel_id = None

    for token in tokens_obj.tokens:
        token_id = token['token_id']
        h.execute(token_id=token_id, server_arch_id=server_arch_id)
        while 1:
            row = h.fetchone_dict()
            if not row:
                break
            channel_id = row['id']
            chash[channel_id] = row
            if row['parent_channel'] is not None:
                # Not a base channel
                continue

            # We only allow for one base channel
            if base_channel_id is not None and channel_id != base_channel_id:
                # Base channels conflict - are they coming from the same
                # token?
                if base_channel_token == token:
                    log_error("Token has multiple base channels", token_id,
                              base_channel_id)
                    raise rhnFault(62,
                                   _("Token `%s' has more than one base channel assigned")
                                   % token['note'])
                raise rhnFault(63, _("Conflicting base channels"))
            base_channel_id = channel_id
            base_channel_token = token

    bc = chash.get(base_channel_id)
    log_debug(4, "base channel", bc)

    # get the base channel for this server
    # Note that we are hitting this codepath after newserver.__save() has been
    # run, which means we've already chosen a base channel
    # from rhnDistChannelMap
    sbc = rhnChannel.get_base_channel(server_id, none_ok=1)

    # prepare the return value
    ret = []

    # now try to figure out which base channel we prefer
    if bc is None:
        if sbc is None:
            # we need at least one base channel definition
            log_error("Server has invalid release and "
                      "token contains no base channels", server_id,
                      tokens_obj.tokens)
            ret.append("System registered without a base channel")
            ret.append("Unsupported release-architecture combination "
                       "(%s, %s)" % (server["release"], server_arch))
            return ret
    else:  # do we need to drop the one from sbc?
        if sbc and sbc["id"] != bc["id"]:  # we need to prefer the token one
            # unsubscribe from old channel(s)
            rhnChannel.unsubscribe_all_channels(server_id)
            sbc = None  # force true on the next test
        if sbc is None:
            # no base channel subscription at this point
            try:
                rhnChannel._subscribe_sql(server_id, bc["id"], commit=0)
            except rhnChannel.SubscriptionCountExceeded:
                ret.append("System registered without a base channel: "
                           "subscription count exceeded for channel %s (%s)" %
                           (bc["name"], bc["label"]))
                return ret

            ret.append("Subscribed to base channel '%s' (%s)" % (
                bc["name"], bc["label"]))
            sbc = bc

    # attempt to subscribe all non-base channels associated with this
    # token
    subscribe_channel = rhnSQL.Procedure("rhn_channel.subscribe_server")
    # Use a set here to ensure uniqueness of the
    # channel family ids used in the loop below.
    channel_family_ids = set()

    for c in filter(lambda a: a["parent_channel"], chash.values()):
        # make sure this channel has the right parent
        if str(c["parent_channel"]) != str(sbc["id"]):
            ret.append("NOT subscribed to channel '%s' "
                       "(not a child of '%s')" % (
                           c["name"], sbc["name"]))
            continue
        try:
            # don't run the EC yet
            # XXX: test return code when this one will start returning
            # a status
            subscribe_channel(server_id, c["id"], 0, None, 0)
            child = rhnChannel.Channel()
            child.load_by_id(c["id"])
            child._load_channel_families()
            cfamid = child._channel_families[0]
            channel_family_ids.add(cfamid)
        except rhnSQL.SQLError, e:
            log_error("Failed channel subscription", server_id,
                      c["id"], c["label"], c["name"])
            ret.append("FAILED to subscribe to channel '%s'" % c["name"])
        else:
            ret.append("Subscribed to channel '%s'" % c["name"])
Example #4
0
    def __save(self, channel):
        if self.server.real:
            server_id = self.server["id"]
            self.server.save()
        else:  # create new entry
            self.gen_secret()
            server_id = self.getid()
            org_id = self.server["org_id"]

            if self.user:
                user_id = self.user.getid()
            else:
                user_id = None

            # some more default values
            self.server["auto_update"] = "N"
            if self.user and not self.server.has_key("creator_id"):
                # save the link to the user that created it if we have
                # that information
                self.server["creator_id"] = self.user.getid()
            # and create the server entry
            self.server.create(server_id)
            server_lib.create_server_setup(server_id, org_id)

            have_reg_token = rhnFlags.test("registration_token")

            # Handle virtualization specific bits
            if self.virt_uuid is not None and \
               self.virt_type is not None:
                rhnVirtualization._notify_guest(self.getid(),
                                                self.virt_uuid, self.virt_type)

            # if we're using a token, then the following channel
            # subscription request can allow no matches since the
            # token code will fix up or fail miserably later.
            # subscribe the server to applicable channels

            # bretm 02/17/2007 -- TODO:  refactor activation key codepaths
            # to allow us to not have to pass in none_ok=1 in any case
            #
            # This can now throw exceptions which will be caught at a higher level
            if channel is not None:
                channel_info = dict(rhnChannel.channel_info(channel))
                log_debug(4, "eus channel id %s" % str(channel_info))
                rhnChannel._subscribe_sql(server_id, channel_info['id'])
            else:
                rhnChannel.subscribe_server_channels(self,
                                                     none_ok=have_reg_token,
                                                     user_id=user_id)

            if not have_reg_token:
                # Attempt to auto-entitle, can throw the following exceptions:
                #   rhnSystemEntitlementException
                #   rhnNoSystemEntitlementsException
                self.autoentitle()

                # If a new server that was registered by an user (i.e. not
                # with a registration token), look for this user's default
                # groups
                self.join_groups()

            server_lib.join_rhn(org_id)
        # Update the uuid - but don't commit yet
        self.update_uuid(self.uuid, commit=0)

        self.create_perm_cache()
        # And save the extra profile data...
        self.save_packages_byid(server_id, schedule=1)
        self.save_hardware_byid(server_id)
        self.save_history_byid(server_id)
        return 0