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
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"])
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