Package backend :: Package server :: Module rhnChannel
[hide private]
[frames] | no frames]

Source Code for Module backend.server.rhnChannel

   1  # 
   2  # Copyright (c) 2008--2018 Red Hat, Inc. 
   3  # 
   4  # This software is licensed to you under the GNU General Public License, 
   5  # version 2 (GPLv2). There is NO WARRANTY for this software, express or 
   6  # implied, including the implied warranties of MERCHANTABILITY or FITNESS 
   7  # FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 
   8  # along with this software; if not, see 
   9  # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 
  10  # 
  11  # Red Hat trademarks are not licensed under GPLv2. No permission is 
  12  # granted to use or replicate Red Hat trademarks that are incorporated 
  13  # in this software or its documentation. 
  14  # 
  15  # 
  16   
  17  import time 
  18  import string 
  19  import rpm 
  20  import sys 
  21  try: 
  22      #  python 2 
  23      import xmlrpclib 
  24  except ImportError: 
  25      #  python3 
  26      import xmlrpc.client as xmlrpclib 
  27   
  28  from spacewalk.common.usix import IntType 
  29   
  30  # common module 
  31  from spacewalk.common.usix import raise_with_tb 
  32  from spacewalk.common import rhnCache, rhnFlags 
  33  from spacewalk.common.rhnConfig import CFG 
  34  from spacewalk.common.rhnLog import log_debug, log_error 
  35  from spacewalk.common.rhnException import rhnFault, rhnException 
  36  from spacewalk.common.rhnTranslate import _ 
  37   
  38  # local module 
  39  import rhnUser 
  40  import rhnSQL 
  41  import rhnLib 
  42   
  43   
44 -class NoBaseChannelError(Exception):
45 pass
46 47
48 -class InvalidServerArchError(Exception):
49 pass
50 51
52 -class BaseChannelDeniedError(Exception):
53 pass
54 55
56 -class ChannelException(Exception):
57
58 - def __init__(self, channel_id=None, *args, **kwargs):
59 Exception.__init__(self, *args, **kwargs) 60 self.channel_id = channel_id 61 self.channel = None
62
63 -class ModifiedError(ChannelException):
64 pass
65 66
67 -class IncompatibilityError(Exception):
68 pass
69 70
71 -class InvalidDataError(Exception):
72 pass
73 74
75 -class ChannelNotFoundError(Exception):
76 pass
77 78
79 -class NoToolsChannel(Exception):
80 pass
81 82
83 -class NoChildChannels(Exception):
84 pass
85 86
87 -class InvalidChannel(Exception):
88 pass
89 90
91 -class BaseDatabaseObject:
92
93 - def __init__(self):
94 self._row = None
95
96 - def __getattr__(self, name):
97 if name.startswith('get_'): 98 return rhnLib.CallableObj(name[4:], self._get) 99 if name.startswith('set_'): 100 return rhnLib.CallableObj(name[4:], self._set) 101 raise AttributeError(name)
102
103 - def _set(self, name, val):
104 self._new_row() 105 self._row[name] = val
106
107 - def _get(self, name):
108 return self._row[name]
109
110 - def _new_row(self):
111 raise NotImplementedError()
112
113 - def save(self, with_updates=1):
114 try: 115 return self._save(with_updates=with_updates) 116 except: 117 rhnSQL.rollback() 118 raise
119
120 - def _save(self, with_updates=1):
121 try: 122 self._row.save(with_updates=with_updates) 123 except rhnSQL.ModifiedRowError: 124 raise_with_tb(ModifiedError(self._row['id']), sys.exc_info()[2])
125 126
127 -class BaseChannelObject(BaseDatabaseObject):
128 _table_name = None 129 _sequence_name = None 130 _generic_fields = [] 131
132 - def load_by_label(self, label):
133 self.__init__() 134 self._row = rhnSQL.Row(self._table_name, 'label') 135 self._row.load(label) 136 return self
137
138 - def load_by_id(self, obj_id):
139 self.__init__() 140 self._row = rhnSQL.Row(self._table_name, 'id') 141 self._row.load(obj_id) 142 return self
143
144 - def load_from_dict(self, dict):
145 # Re-init 146 self.__init__() 147 for f in self._generic_fields: 148 method = getattr(self, 'set_' + f) 149 method(dict.get(f)) 150 self._load_rest(dict) 151 return self
152
153 - def _load_rest(self, dict):
154 pass
155
156 - def exists(self):
157 if not self._row: 158 return 0 159 return self._row.real
160
161 - def get_org_id(self):
162 org_id = self._row['org_id'] 163 if org_id is None: 164 return None 165 row = self._lookup_org_id(org_id) 166 if row.real: 167 return row['login'] 168 return org_id
169
170 - def set_org_id(self, val):
171 self._new_row() 172 if val is None or isinstance(val, IntType): 173 self._row['org_id'] = val 174 return 175 row = self._lookup_org_by_login(val) 176 if not row.real: 177 raise InvalidDataError("No such org", val) 178 self._row['org_id'] = row['org_id']
179
180 - def _lookup_org_id(self, org_id):
181 row = rhnSQL.Row('web_contact', 'org_id') 182 row.load(org_id) 183 return row
184
185 - def _lookup_org_by_login(self, login):
186 row = rhnSQL.Row('web_contact', 'login') 187 row.load(login) 188 return row
189
190 - def _lookup_channel_family_by_id(self, channel_family_id):
191 row = rhnSQL.Row('rhnChannelFamily', 'id') 192 row.load(channel_family_id) 193 return row
194
195 - def _lookup_channel_family_by_label(self, channel_family):
196 row = rhnSQL.Row('rhnChannelFamily', 'label') 197 row.load(channel_family) 198 return row
199
200 - def _new_row(self):
201 if self._row is None: 202 self._row = rhnSQL.Row(self._table_name, 'id') 203 channel_id = rhnSQL.Sequence(self._sequence_name).next() 204 self._row.create(channel_id)
205
206 - def as_dict(self):
207 ret = {} 208 for f in self._generic_fields: 209 method = getattr(self, 'get_' + f) 210 val = method() 211 ret[f] = val 212 return ret
213 214 # Channel creation 215 216
217 -class Channel(BaseChannelObject):
218 _table_name = 'rhnChannel' 219 _sequence_name = 'rhn_channel_id_seq' 220 _generic_fields = ['label', 'name', 'summary', 'description', 'basedir', 221 'org_id', 'gpg_key_url', 'gpg_key_id', 'gpg_key_fp', 'end_of_life', 222 'channel_families', 'channel_arch', ] 223
224 - def __init__(self):
225 BaseChannelObject.__init__(self) 226 self._channel_families = [] 227 self._dists = {} 228 self._parent_channel_arch = None
229
230 - def load_by_label(self, label):
231 BaseChannelObject.load_by_label(self, label) 232 self._load_channel_families() 233 self._load_dists() 234 return self
235
236 - def load_by_id(self, label):
237 BaseChannelObject.load_by_id(self, label) 238 self._load_channel_families() 239 self._load_dists() 240 return self
241
242 - def _load_rest(self, dict):
243 dists = dict.get('dists') 244 if not dists: 245 return 246 for dist in dists: 247 release = dist.get('release') 248 os = dist.get('os') 249 self._dists[release] = os
250 251 _query_get_db_channel_families = rhnSQL.Statement(""" 252 select channel_family_id 253 from rhnChannelFamilyMembers 254 where channel_id = :channel_id 255 """) 256
257 - def _get_db_channel_families(self, channel_id):
258 if channel_id is None: 259 return [] 260 h = rhnSQL.prepare(self._query_get_db_channel_families) 261 h.execute(channel_id=channel_id) 262 return [x['channel_family_id'] for x in h.fetchall_dict() or []]
263
264 - def _load_channel_families(self):
265 channel_id = self._row.get('id') 266 self._channel_families = self._get_db_channel_families(channel_id) 267 return 1
268
269 - def _load_dists(self):
270 channel_id = self._row.get('id') 271 dists = self._get_db_dists(channel_id) 272 self.set_dists(dists)
273 274 _query_get_db_dists = rhnSQL.Statement(""" 275 select os, release 276 from rhnDistChannelMap 277 where channel_id = :channel_id 278 and org_id is null 279 """) 280
281 - def _get_db_dists(self, channel_id):
282 if channel_id is None: 283 return [] 284 h = rhnSQL.prepare(self._query_get_db_dists) 285 h.execute(channel_id=channel_id) 286 return h.fetchall_dict() or []
287 288 # Setters 289
290 - def set_channel_arch(self, val):
291 self._new_row() 292 arch = self._sanitize_arch(val) 293 row = self._lookup_channel_arch(arch) 294 if not row.real: 295 raise InvalidDataError("No such architecture", arch) 296 self._row['channel_arch_id'] = row['id']
297
298 - def _sanitize_arch(self, arch):
299 if arch == 'i386': 300 return 'channel-ia32' 301 p = 'channel-' 302 if arch[:len(p)] != p: 303 return p + arch 304 return arch
305
306 - def set_parent_channel(self, val):
307 self._new_row() 308 if val is None: 309 self._row['parent_channel'] = None 310 return 311 row = self._lookup_channel_by_label(val) 312 if not row.real: 313 raise InvalidDataError("Invalid parent channel", val) 314 self._row['parent_channel'] = row['id'] 315 self._parent_channel_arch = row['channel_arch_id']
316
317 - def set_channel_families(self, val):
318 self._new_row() 319 self._channel_families = [] 320 for cf_label in val: 321 self.add_channel_family(cf_label)
322
323 - def set_end_of_life(self, val):
324 self._new_row() 325 if val is None: 326 self._row['end_of_life'] = None 327 return 328 t = time.strptime(val, "%Y-%m-%d") 329 seconds = time.mktime(t) 330 t = rhnSQL.TimestampFromTicks(seconds) 331 self._row['end_of_life'] = t
332
333 - def add_channel_family(self, name):
334 self._new_row() 335 cf = self._lookup_channel_family_by_label(name) 336 if not cf.real: 337 raise InvalidDataError("Invalid channel family", name) 338 self._channel_families.append(cf['id'])
339
340 - def add_dist(self, release, os=None):
341 if os is None: 342 os = 'Red Hat Linux' 343 self._dists[release] = os
344
345 - def set_dists(self, val):
346 self._dists.clear() 347 for h in val: 348 release = h['release'] 349 os = h['os'] 350 self.add_dist(release, os)
351 352 # Getters 353
354 - def get_parent_channel(self):
355 pc_id = self._row['parent_channel'] 356 if pc_id is None: 357 return None 358 return self._lookup_channel_by_id(pc_id)['label']
359
360 - def get_channel_families(self):
361 cf_labels = [] 362 for cf_id in self._channel_families: 363 row = self._lookup_channel_family_by_id(cf_id) 364 if row.real: 365 cf_labels.append(row['label']) 366 return cf_labels
367
368 - def get_channel_arch(self):
369 channel_arch_id = self._row['channel_arch_id'] 370 row = self._lookup_channel_arch_by_id(channel_arch_id) 371 assert row.real 372 return row['label']
373
374 - def get_end_of_life(self):
375 date_obj = self._row['end_of_life'] 376 if date_obj is None: 377 return None 378 return "%s-%02d-%02d %02d:%02d:%02d" % ( 379 date_obj.year, date_obj.month, date_obj.day, 380 date_obj.hour, date_obj.minute, date_obj.second)
381
382 - def get_dists(self):
383 ret = [] 384 for release, os in self._dists.items(): 385 ret.append({'release': release, 'os': os}) 386 return ret
387
388 - def _lookup_channel_by_id(self, channel_id):
389 row = rhnSQL.Row('rhnChannel', 'id') 390 row.load(channel_id) 391 return row
392
393 - def _lookup_channel_by_label(self, channel):
394 row = rhnSQL.Row('rhnChannel', 'label') 395 row.load(channel) 396 return row
397
398 - def _lookup_channel_arch(self, channel_arch):
399 row = rhnSQL.Row('rhnChannelArch', 'label') 400 row.load(channel_arch) 401 return row
402
403 - def _lookup_channel_arch_by_id(self, channel_arch_id):
404 row = rhnSQL.Row('rhnChannelArch', 'id') 405 row.load(channel_arch_id) 406 return row
407
408 - def _save(self, with_updates=1):
409 if self._parent_channel_arch: 410 if not self._compatible_channel_arches(self._parent_channel_arch, 411 self._row['channel_arch_id']): 412 raise IncompatibilityError("Incompatible channel arches") 413 BaseChannelObject._save(self, with_updates=with_updates) 414 # Save channel families now 415 self._save_channel_families() 416 self._save_dists()
417 418 _query_remove_channel_families = rhnSQL.Statement(""" 419 delete from rhnChannelFamilyMembers 420 where channel_id = :channel_id 421 and channel_family_id = :channel_family_id 422 """) 423 _query_add_channel_families = rhnSQL.Statement(""" 424 insert into rhnChannelFamilyMembers (channel_id, channel_family_id) 425 values (:channel_id, :channel_family_id) 426 """) 427
428 - def _save_channel_families(self):
429 channel_id = self._row['id'] 430 db_cfids = self._get_db_channel_families(channel_id) 431 h = {} 432 for db_cfid in db_cfids: 433 h[db_cfid] = None 434 to_add = [] 435 for cfid in self._channel_families: 436 if cfid in h: 437 del h[cfid] 438 continue 439 to_add.append(cfid) 440 to_delete = list(h.keys()) 441 if to_delete: 442 h = rhnSQL.prepare(self._query_remove_channel_families) 443 cids = [channel_id] * len(to_delete) 444 h.executemany(channel_id=cids, channel_family_id=to_delete) 445 if to_add: 446 h = rhnSQL.prepare(self._query_add_channel_families) 447 cids = [channel_id] * len(to_add) 448 h.executemany(channel_id=cids, channel_family_id=to_add)
449
450 - def _save_dists(self):
451 channel_id = self._row['id'] 452 db_dists = self._get_db_dists(channel_id) 453 d = self._dists.copy() 454 to_add = [[], []] 455 to_remove = [] 456 to_update = [[], []] 457 for h in db_dists: 458 release = h['release'] 459 os = h['os'] 460 if release not in d: 461 to_remove.append(release) 462 continue 463 # Need to update? 464 m_os = d[release] 465 if m_os == os: 466 # Nothing to do 467 del d[release] 468 continue 469 to_update[0].append(release) 470 to_update[1].append(os) 471 # Everything else should be added 472 for release, os in list(d.items()): 473 to_add[0].append(release) 474 to_add[1].append(os) 475 self._remove_dists(to_remove) 476 self._update_dists(to_update[0], to_update[1]) 477 self._add_dists(to_add[0], to_add[1])
478 479 _query_add_dists = rhnSQL.Statement(""" 480 insert into rhnDistChannelMap 481 (channel_id, channel_arch_id, release, os, org_id) 482 values (:channel_id, :channel_arch_id, :release, :os, null) 483 """) 484
485 - def _add_dists(self, releases, oses):
486 self._modify_dists(self._query_add_dists, releases, oses)
487
488 - def _modify_dists(self, query, releases, oses):
489 if not releases: 490 return 491 count = len(releases) 492 channel_ids = [self._row['id']] * count 493 query_args = {'channel_id': channel_ids, 'release': releases} 494 if oses: 495 channel_arch_ids = [self._row['channel_arch_id']] * count 496 query_args.update({'channel_arch_id': channel_arch_ids, 497 'os': oses}) 498 h = rhnSQL.prepare(query) 499 h.executemany(**query_args)
500 501 _query_update_dists = rhnSQL.Statement(""" 502 update rhnDistChannelMap 503 set channel_arch_id = :channel_arch_id, 504 os = :os 505 where channel_id = :channel_id 506 and release = :release 507 and org_id is null 508 """) 509
510 - def _update_dists(self, releases, oses):
511 self._modify_dists(self._query_update_dists, releases, oses)
512 513 _query_remove_dists = rhnSQL.Statement(""" 514 delete from rhnDistChannelMap 515 where channel_id = :channel_id 516 and release = :release 517 and org_id is null 518 """) 519
520 - def _remove_dists(self, releases):
521 self._modify_dists(self._query_remove_dists, releases, None)
522
523 - def _compatible_channel_arches(self, parent_channel_arch, channel_arch):
524 # This could get more complicated later 525 return (parent_channel_arch == channel_arch)
526
527 - def as_dict(self):
528 ret = BaseChannelObject.as_dict(self) 529 ret['dists'] = self.get_dists() 530 return ret
531 532
533 -class ChannelFamily(BaseChannelObject):
534 _table_name = 'rhnChannelFamily' 535 _sequence_name = 'rhn_channel_family_id_seq' 536 _generic_fields = ['label', 'name', 'product_url']
537 538
539 -def _load_by_id(query, item_object, pattern=None):
540 qargs = {} 541 if pattern: 542 query += "and label like :pattern" 543 qargs['pattern'] = pattern 544 h = rhnSQL.prepare(query) 545 h.execute(**qargs) 546 ret = [] 547 while 1: 548 row = h.fetchone_dict() 549 if not row: 550 break 551 c = item_object.load_by_id(row['id']) 552 ret.append(c.as_dict()) 553 return ret
554 555
556 -def list_channel_families(pattern=None):
557 query = """ 558 select id 559 from rhnChannelFamily 560 where org_id is null 561 """ 562 return _load_by_id(query, ChannelFamily(), pattern)
563 564
565 -def list_channels(pattern=None):
566 query = """ 567 select id 568 from rhnChannel 569 where 1=1 570 """ 571 return _load_by_id(query, Channel(), pattern)
572 573 # makes sure there are no None values in dictionaries, etc. 574 575
576 -def __stringify(object):
577 if object is None: 578 return '' 579 if type(object) == type([]): 580 return list(map(__stringify, object)) 581 # We need to know __stringify converts immutable types into immutable 582 # types 583 if type(object) == type(()): 584 return tuple(map(__stringify, object)) 585 if type(object) == type({}): 586 ret = {} 587 for k, v in object.items(): 588 ret[__stringify(k)] = __stringify(v) 589 return ret 590 # by default, we just str() it 591 return str(object)
592 593 594 # return the channel information
595 -def channel_info(channel):
596 log_debug(3, channel) 597 598 # get the channel information 599 h = rhnSQL.prepare(""" 600 select 601 ca.label arch, 602 c.id, 603 c.parent_channel, 604 c.org_id, 605 c.label, 606 c.name, 607 c.summary, 608 c.description, 609 to_char(c.last_modified, 'YYYYMMDDHH24MISS') last_modified 610 from 611 rhnChannel c, 612 rhnChannelArch ca 613 where 614 c.channel_arch_id = ca.id 615 and c.label = :channel 616 """) 617 h.execute(channel=str(channel)) 618 ret = h.fetchone_dict() 619 return __stringify(ret)
620 621 # return information about a base channel for a server_id 622 623
624 -def get_base_channel(server_id, none_ok=0):
625 log_debug(3, server_id) 626 h = rhnSQL.prepare(""" 627 select 628 ca.label arch, 629 c.id, 630 c.parent_channel, 631 c.org_id, 632 c.label, 633 c.name, 634 c.summary, 635 c.description, 636 to_char(c.last_modified, 'YYYYMMDDHH24MISS') last_modified 637 from rhnChannel c, rhnChannelArch ca, rhnServerChannel sc 638 where sc.server_id = :server_id 639 and sc.channel_id = c.id 640 and c.channel_arch_id = ca.id 641 and c.parent_channel is NULL 642 """) 643 h.execute(server_id=str(server_id)) 644 ret = h.fetchone_dict() 645 if not ret: 646 if not none_ok: 647 log_error("Server not subscribed to a base channel!", server_id) 648 return None 649 return __stringify(ret)
650 651
652 -def channels_for_server(server_id):
653 """channel info list for all channels accessible by this server. 654 655 list channels a server_id is subscribed to 656 We DO NOT want to cache this one because we depend on getting 657 accurate information and the caching would only introduce more 658 overhead on an otherwise very fast query 659 """ 660 log_debug(3, server_id) 661 try: 662 server_id = int(server_id) 663 except: 664 raise_with_tb(rhnFault(8, server_id), sys.exc_info()[2]) # Invalid rhnServer.id 665 # XXX: need to return unsubsubcribed channels and a way to indicate 666 # they arent already subscribed 667 668 # list all the channels this server is subscribed to. We also want 669 # to know if any of those channels has local packages in it... A 670 # local package has a org_id set. 671 h = rhnSQL.prepare(""" 672 select 673 ca.label arch, 674 c.id, 675 c.parent_channel, 676 c.org_id, 677 c.label, 678 c.name, 679 c.summary, 680 c.description, 681 c.gpg_key_url, 682 case s.org_id when c.org_id then 1 else 0 end local_channel, 683 TO_CHAR(c.last_modified, 'YYYYMMDDHH24MISS') last_modified 684 from 685 rhnChannelArch ca, 686 rhnChannel c, 687 rhnServerChannel sc, 688 rhnServer s 689 where 690 c.id = sc.channel_id 691 and sc.server_id = :server_id 692 and s.id = :server_id 693 and ca.id = c.channel_arch_id 694 order by c.parent_channel nulls first 695 """) 696 h.execute(server_id=str(server_id)) 697 channels = h.fetchall_dict() 698 if not channels: 699 log_error("Server not subscribed to any channels", server_id) 700 channels = [] 701 return __stringify(channels)
702
703 -def getSubscribedChannels(server_id):
704 """ 705 Format the response from channels_for_server in the way that the 706 handlers expect. 707 """ 708 channelList = channels_for_server(server_id) 709 channels = [] 710 for each in channelList: 711 if 'last_modified' not in each: 712 # No last_modified attribute 713 # Probably an empty channel, so ignore 714 continue 715 channel = [each['label'], each['last_modified']] 716 # isBaseChannel 717 if each['parent_channel']: 718 flag = "0" 719 else: 720 flag = "1" 721 channel.append(flag) 722 723 # isLocalChannel 724 if each['local_channel']: 725 flag = "1" 726 else: 727 flag = "0" 728 channel.append(flag) 729 730 channels.append(channel) 731 return channels
732
733 -def isCustomChannel(channel_id):
734 """ 735 Input: channel_id (from DB Table rhnChannel.id) 736 Returns: True if this is a custom channel 737 False if this is not a custom channel 738 """ 739 log_debug(3, channel_id) 740 h = rhnSQL.prepare(""" 741 select 742 rcf.label 743 from 744 rhnChannelFamily rcf, 745 rhnChannelFamilyMembers rcfm 746 where 747 rcfm.channel_id = :channel_id 748 and rcfm.channel_family_id = rcf.id 749 and rcf.org_id is not null 750 """) 751 h.execute(channel_id=str(channel_id)) 752 label = h.fetchone() 753 if label: 754 if label[0].startswith("private-channel-family"): 755 log_debug(3, channel_id, "is a custom channel") 756 return True 757 return False
758 759 760 # Fetch base channel for a given release and arch
761 -def base_channel_for_rel_arch(release, server_arch, org_id=-1, 762 user_id=None):
763 log_debug(4, release, server_arch, org_id, user_id) 764 765 query = """ 766 select ca.label arch, 767 c.id, 768 c.parent_channel, 769 c.org_id, 770 c.label, 771 c.name, 772 c.summary, 773 c.description, 774 to_char(c.last_modified, 'YYYYMMDDHH24MISS') last_modified 775 from rhnChannel c, 776 rhnChannelArch ca 777 where c.channel_arch_id = ca.id 778 and c.id = rhn_channel.base_channel_for_release_arch( 779 :release, :server_arch, :org_id, :user_id) 780 """ 781 rhnSQL.transaction("base_channel_for_rel_arch") 782 h = rhnSQL.prepare(query) 783 try: 784 h.execute(release=str(release), server_arch=str(server_arch), 785 org_id=org_id, user_id=user_id) 786 except rhnSQL.SQLSchemaError: 787 e = sys.exc_info()[1] 788 rhnSQL.rollback("base_channel_for_rel_arch") 789 if e.errno == 20263: 790 # Insufficient permissions for subscription 791 log_debug(4, 'BaseChannelDeniedError') 792 raise_with_tb(BaseChannelDeniedError(), sys.exc_info()[2]) 793 if e.errno == 20244: 794 # Server architecture could not be found 795 log_debug(4, 'InvalidServerArchError') 796 raise_with_tb(InvalidServerArchError(str(server_arch)), sys.exc_info()[2]) 797 # Re-raise unknown eceptions 798 log_debug(4, 'unkown exception') 799 raise 800 801 log_debug(4, 'got past exceptions') 802 return h.fetchone_dict()
803 804
805 -def base_eus_channel_for_ver_rel_arch(version, release, server_arch, 806 org_id=-1, user_id=None):
807 """ 808 given a redhat-release version, release, and server arch, return a list 809 of dicts containing the details of the channel z streams either match the 810 version/release pair, or are greater. 811 """ 812 813 log_debug(4, version, release, server_arch, org_id, user_id) 814 815 eus_channels_query = """ 816 select c.id, 817 c.label, 818 c.name, 819 rcm.release, 820 c.receiving_updates 821 from 822 rhnChannelPermissions cp, 823 rhnChannel c, 824 rhnServerArch sa, 825 rhnServerChannelArchCompat scac, 826 rhnReleaseChannelMap rcm 827 where 828 rcm.version = :version 829 and scac.server_arch_id = sa.id 830 and sa.label = :server_arch 831 and scac.channel_arch_id = rcm.channel_arch_id 832 and rcm.channel_id = c.id 833 and cp.channel_id = c.id 834 and cp.org_id = :org_id 835 and rhn_channel.loose_user_role_check(c.id, :user_id, 836 'subscribe') = 1 837 """ 838 839 eus_channels_prepared = rhnSQL.prepare(eus_channels_query) 840 eus_channels_prepared.execute(version=version, 841 server_arch=server_arch, 842 user_id=user_id, 843 org_id=org_id) 844 845 channels = [] 846 while True: 847 channel = eus_channels_prepared.fetchone_dict() 848 if channel is None: 849 break 850 851 # the release part of redhat-release for rhel 4 is like 852 # 6.1 or 7; we just look at the first digit. 853 # for rhel 5 and up it's the full release number of rhel, followed by 854 # the true release number of the rpm, like 5.0.0.9 (for the 9th 855 # version of the redhat-release rpm, for RHEL GA) 856 db_release = channel['release'] 857 if version in ['4AS', '4ES']: 858 parts = 1 859 else: 860 parts = 2 861 862 server_rel = '.'.join(release.split('-')[0].split('.')[:parts]) 863 channel_rel = '.'.join(db_release.split('-')[0].split('.')[:parts]) 864 865 # XXX we're no longer using the is_default column from the db 866 if rpm.labelCompare(('0', server_rel, '0'), 867 ('0', channel_rel, '0')) == 0: 868 channel['is_default'] = 'Y' 869 channels.append(channel) 870 if rpm.labelCompare(('0', server_rel, '0'), 871 ('0', channel_rel, '0')) < 0: 872 channel['is_default'] = 'N' 873 channels.append(channel) 874 875 return channels
876 877
878 -def get_channel_for_release_arch(release, server_arch, org_id=None):
879 log_debug(3, release, server_arch) 880 881 server_arch = rhnLib.normalize_server_arch(str(server_arch)) 882 log_debug(3, 'normalized arch as %s' % server_arch) 883 884 if org_id is None: 885 query = """ 886 select distinct 887 ca.label arch, 888 c.id, 889 c.parent_channel, 890 c.org_id, 891 c.label, 892 c.name, 893 c.summary, 894 c.description, 895 to_char(c.last_modified, 'YYYYMMDDHH24MISS') last_modified 896 from rhnDistChannelMap dcm, 897 rhnChannel c, 898 rhnChannelArch ca, 899 rhnServerChannelArchCompat scac, 900 rhnServerArch sa 901 where scac.server_arch_id = sa.id 902 and sa.label = :server_arch 903 and scac.channel_arch_id = dcm.channel_arch_id 904 and dcm.release = :release 905 and dcm.channel_id = c.id 906 and dcm.channel_arch_id = c.channel_arch_id 907 and dcm.org_id is null 908 and c.parent_channel is null 909 and c.org_id is null 910 and c.channel_arch_id = ca.id 911 """ 912 else: 913 query = """ 914 select distinct 915 ca.label arch, 916 c.id, 917 c.parent_channel, 918 c.org_id, 919 c.label, 920 c.name, 921 c.summary, 922 c.description, 923 to_char(c.last_modified, 'YYYYMMDDHH24MISS') last_modified 924 from rhnOrgDistChannelMap odcm, 925 rhnChannel c, 926 rhnChannelArch ca, 927 rhnServerChannelArchCompat scac, 928 rhnServerArch sa 929 where scac.server_arch_id = sa.id 930 and sa.label = :server_arch 931 and scac.channel_arch_id = odcm.channel_arch_id 932 and odcm.release = :release 933 and odcm.channel_id = c.id 934 and odcm.channel_arch_id = c.channel_arch_id 935 and odcm.org_id = :org_id 936 and c.parent_channel is null 937 and c.org_id is null 938 and c.channel_arch_id = ca.id 939 """ 940 h = rhnSQL.prepare(query) 941 h.execute(release=str(release), server_arch=server_arch, org_id=org_id) 942 row = h.fetchone_dict() 943 if not row: 944 # No channles for this guy 945 log_debug(3, 'No channles for this guy') 946 return None 947 log_debug(3, 'row is %s' % str(row)) 948 return row
949 950
951 -def applet_channels_for_uuid(uuid):
952 log_debug(3, uuid) 953 954 query = """ 955 select distinct 956 ca.label arch, 957 c.id, 958 c.parent_channel, 959 c.org_id, 960 c.label, 961 c.name, 962 c.summary, 963 c.description, 964 to_char(c.last_modified, 'YYYYMMDDHH24MISS') last_modified, 965 to_char(s.channels_changed, 'YYYYMMDDHH24MISS') server_channels_changed 966 from rhnChannelArch ca, 967 rhnChannel c, 968 rhnServerChannel sc, 969 rhnServer s, 970 rhnServerUuid su 971 where su.uuid = :uuid 972 and su.server_id = s.id 973 and su.server_id = sc.server_id 974 and sc.channel_id = c.id 975 and c.channel_arch_id = ca.id 976 """ 977 h = rhnSQL.prepare(query) 978 h.execute(uuid=uuid) 979 rows = h.fetchall_dict() or [] 980 return rows
981 982 # retrieve a list of public channels for a given release and architecture 983 # we cannot cache this if it involves an org_id 984 # If a user_id is passed to this function, and all the available base channels 985 # for this server_arch/release combination are denied by the org admin, this 986 # function raises BaseChannelDeniedError 987 988
989 -def channels_for_release_arch(release, server_arch, org_id=-1, user_id=None):
990 if not org_id: 991 org_id = -1 992 993 org_id = string.strip(str(org_id)) 994 log_debug(3, release, server_arch, org_id) 995 996 # Can raise BaseChannelDeniedError or InvalidServerArchError 997 base_channel = base_channel_for_rel_arch(release, server_arch, 998 org_id=org_id, user_id=user_id) 999 1000 if not base_channel: 1001 raise NoBaseChannelError() 1002 1003 # At this point, base_channel is not null 1004 1005 # We assume here that subchannels are compatible with the base channels, 1006 # so there would be no need to check for arch compatibility from this 1007 # point 1008 h = rhnSQL.prepare(""" 1009 select 1010 ca.label arch, 1011 c.id, 1012 c.parent_channel, 1013 c.org_id, 1014 c.label, 1015 c.name, 1016 c.summary, 1017 c.description, 1018 to_char(c.last_modified, 'YYYYMMDDHH24MISS') last_modified, 1019 -- If user_id is null, then the channel is subscribable 1020 rhn_channel.loose_user_role_check(c.id, :user_id, 'subscribe') 1021 subscribable 1022 from 1023 rhnChannelPermissions cp, 1024 rhnOrgDistChannelMap odcm, 1025 rhnChannel c, 1026 rhnChannelArch ca 1027 where 1028 c.id = odcm.channel_id 1029 and odcm.os in ( 1030 'Powertools' 1031 ) 1032 and odcm.for_org_id = :org_id 1033 and c.channel_arch_id = ca.id 1034 and cp.channel_id = c.id 1035 and cp.org_id = :org_id 1036 and c.parent_channel = :parent_channel 1037 """) 1038 h.execute(org_id=org_id, 1039 parent_channel=base_channel['id'], user_id=user_id) 1040 1041 channels = [base_channel] 1042 while 1: 1043 row = h.fetchone_dict() 1044 if not row: 1045 break 1046 subscribable = row['subscribable'] 1047 del row['subscribable'] 1048 1049 if not subscribable: 1050 # Not allowed to subscribe to this channel 1051 continue 1052 1053 channels.append(row) 1054 1055 return __stringify(channels)
1056 1057 1058 _query_get_source_packages_from_ids = rhnSQL.Statement(""" 1059 select srpm.name 1060 from rhnChannelPackage cp, 1061 rhnPackage p, 1062 rhnSourceRPM srpm 1063 where cp.channel_id = :channel_id 1064 and cp.package_id = p.id 1065 and p.source_rpm_id = srpm.id 1066 """) 1067 1068
1069 -def list_packages_source(channel_id):
1070 ret = [] 1071 h = rhnSQL.prepare(_query_get_source_packages_from_ids) 1072 h.execute(channel_id=channel_id) 1073 results = h.fetchall_dict() 1074 if results: 1075 for r in results: 1076 r = r['name'] 1077 if string.find(r, ".rpm") != -1: 1078 r = string.replace(r, ".rpm", "") 1079 new_evr = rhnLib.make_evr(r, source=1) 1080 new_evr_list = [new_evr['name'], new_evr['version'], new_evr['release'], new_evr['epoch']] 1081 ret.append(new_evr_list) 1082 1083 return ret
1084 1085 # the latest packages from the specified channel 1086 _query_all_packages_from_channel_checksum = """ 1087 select 1088 p.id, 1089 pn.name, 1090 pevr.version, 1091 pevr.release, 1092 pevr.epoch, 1093 pa.label arch, 1094 p.package_size, 1095 ct.label as checksum_type, 1096 c.checksum 1097 from 1098 rhnChannelPackage cp, 1099 rhnPackage p, 1100 rhnPackageName pn, 1101 rhnPackageEVR pevr, 1102 rhnPackageArch pa, 1103 rhnChecksumType ct, 1104 rhnChecksum c 1105 where 1106 cp.channel_id = :channel_id 1107 and cp.package_id = p.id 1108 and p.name_id = pn.id 1109 and p.evr_id = pevr.id 1110 and p.package_arch_id = pa.id 1111 and p.checksum_id = c.id 1112 and c.checksum_type_id = ct.id 1113 order by pn.name, pevr.evr desc, pa.label 1114 """ 1115 1116 # This function executes the SQL call for listing packages with checksum info 1117 1118
1119 -def list_all_packages_checksum_sql(channel_id):
1120 log_debug(3, channel_id) 1121 h = rhnSQL.prepare(_query_all_packages_from_channel_checksum) 1122 h.execute(channel_id=str(channel_id)) 1123 ret = h.fetchall_dict() 1124 if not ret: 1125 return [] 1126 # process the results 1127 ret = [(a["name"], a["version"], a["release"], a["epoch"], 1128 a["arch"], a["package_size"], a['checksum_type'], 1129 a['checksum']) for a in __stringify(ret)] 1130 return ret
1131 1132 # This function executes the SQL call for listing latest packages with 1133 # checksum info 1134 1135
1136 -def list_packages_checksum_sql(channel_id):
1137 log_debug(3, channel_id) 1138 # return the latest packages from the specified channel 1139 query = """ 1140 select 1141 pn.name, 1142 pevr.version, 1143 pevr.release, 1144 pevr.epoch, 1145 pa.label arch, 1146 full_channel.package_size, 1147 full_channel.checksum_type, 1148 full_channel.checksum 1149 from 1150 rhnPackageArch pa, 1151 ( select 1152 p.name_id, 1153 max(pe.evr) evr 1154 from 1155 rhnChannelPackage cp, 1156 rhnPackage p, 1157 rhnPackageEVR pe 1158 where 1159 cp.channel_id = :channel_id 1160 and cp.package_id = p.id 1161 and p.evr_id = pe.id 1162 group by p.name_id 1163 ) listall, 1164 ( select distinct 1165 p.package_size, 1166 p.name_id, 1167 p.evr_id, 1168 p.package_arch_id, 1169 ct.label as checksum_type, 1170 c.checksum 1171 from 1172 rhnChannelPackage cp, 1173 rhnPackage p, 1174 rhnChecksumType ct, 1175 rhnChecksum c 1176 where 1177 cp.channel_id = :channel_id 1178 and cp.package_id = p.id 1179 and p.checksum_id = c.id 1180 and c.checksum_type_id = ct.id 1181 ) full_channel, 1182 -- Rank the package's arch 1183 ( select 1184 package_arch_id, 1185 count(*) rank 1186 from 1187 rhnServerPackageArchCompat 1188 group by package_arch_id 1189 ) arch_rank, 1190 rhnPackageName pn, 1191 rhnPackageEVR pevr 1192 where 1193 pn.id = listall.name_id 1194 -- link back to the specific package 1195 and full_channel.name_id = listall.name_id 1196 and full_channel.evr_id = pevr.id 1197 and pevr.evr = listall.evr 1198 and pa.id = full_channel.package_arch_id 1199 and pa.id = arch_rank.package_arch_id 1200 order by pn.name, arch_rank.rank desc 1201 """ 1202 h = rhnSQL.prepare(query) 1203 h.execute(channel_id=str(channel_id)) 1204 ret = h.fetchall_dict() 1205 if not ret: 1206 return [] 1207 # process the results 1208 ret = [(a["name"], a["version"], a["release"], a["epoch"], 1209 a["arch"], a["package_size"], a['checksum_type'], 1210 a['checksum']) for a in __stringify(ret)] 1211 return ret
1212 1213 # This function executes the SQL call for listing packages 1214 1215
1216 -def _list_packages_sql(query, channel_id):
1217 h = rhnSQL.prepare(query) 1218 h.execute(channel_id=str(channel_id)) 1219 ret = h.fetchall_dict() 1220 if not ret: 1221 return [] 1222 # process the results 1223 ret = [(a["name"], a["version"], a["release"], a["epoch"], 1224 a["arch"], a["package_size"]) for a in __stringify(ret)] 1225 return ret
1226 1227
1228 -def list_packages_sql(channel_id):
1229 log_debug(3, channel_id) 1230 # return the latest packages from the specified channel 1231 query = """ 1232 select 1233 pn.name, 1234 pevr.version, 1235 pevr.release, 1236 pevr.epoch, 1237 pa.label arch, 1238 full_channel.package_size 1239 from 1240 rhnPackageArch pa, 1241 ( select 1242 p.name_id, 1243 max(pe.evr) evr 1244 from 1245 rhnChannelPackage cp, 1246 rhnPackage p, 1247 rhnPackageEVR pe 1248 where 1249 cp.channel_id = :channel_id 1250 and cp.package_id = p.id 1251 and p.evr_id = pe.id 1252 group by p.name_id 1253 ) listall, 1254 ( select distinct 1255 p.package_size, 1256 p.name_id, 1257 p.evr_id, 1258 p.package_arch_id 1259 from 1260 rhnChannelPackage cp, 1261 rhnPackage p 1262 where 1263 cp.channel_id = :channel_id 1264 and cp.package_id = p.id 1265 ) full_channel, 1266 -- Rank the package's arch 1267 ( select 1268 package_arch_id, 1269 count(*) rank 1270 from 1271 rhnServerPackageArchCompat 1272 group by package_arch_id 1273 ) arch_rank, 1274 rhnPackageName pn, 1275 rhnPackageEVR pevr 1276 where 1277 pn.id = listall.name_id 1278 -- link back to the specific package 1279 and full_channel.name_id = listall.name_id 1280 and full_channel.evr_id = pevr.id 1281 and pevr.evr = listall.evr 1282 and pa.id = full_channel.package_arch_id 1283 and pa.id = arch_rank.package_arch_id 1284 order by pn.name, arch_rank.rank desc 1285 """ 1286 return _list_packages_sql(query, channel_id)
1287 1288 # the latest packages from the specified channel 1289 _query_latest_packages_from_channel = """ 1290 select 1291 p.id, 1292 pn.name, 1293 pevr.version, 1294 pevr.release, 1295 pevr.epoch, 1296 pa.label arch, 1297 p.package_size 1298 from 1299 rhnChannelPackage cp, 1300 rhnPackage p, 1301 rhnPackageName pn, 1302 rhnPackageEVR pevr, 1303 rhnPackageArch pa 1304 where 1305 cp.channel_id = :channel_id 1306 and cp.package_id = p.id 1307 and p.name_id = pn.id 1308 and p.evr_id = pevr.id 1309 and p.package_arch_id = pa.id 1310 order by pn.name, pevr.evr desc, pa.label 1311 """ 1312 1313 # This function executes the SQL call for listing packages 1314 1315
1316 -def list_all_packages_sql(channel_id):
1317 log_debug(3, channel_id) 1318 return _list_packages_sql(_query_latest_packages_from_channel, channel_id)
1319 1320 # This function executes the SQL call for listing packages with all the 1321 # dep information for each package also 1322 1323
1324 -def list_all_packages_complete_sql(channel_id):
1325 log_debug(3, channel_id) 1326 # return the latest packages from the specified channel 1327 h = rhnSQL.prepare(_query_latest_packages_from_channel) 1328 # This gathers the provides, requires, conflicts, obsoletes info 1329 g = rhnSQL.prepare(""" 1330 select 1331 pp.package_id, 1332 'provides' as capability_type, 1333 pp.capability_id, 1334 pp.sense, 1335 pc.name, 1336 pc.version 1337 from 1338 rhnPackageProvides pp, 1339 rhnPackageCapability pc 1340 where 1341 pp.package_id = :package_id 1342 and pp.capability_id = pc.id 1343 union all 1344 select 1345 pr.package_id, 1346 'requires' as capability_type, 1347 pr.capability_id, 1348 pr.sense, 1349 pc.name, 1350 pc.version 1351 from 1352 rhnPackageRequires pr, 1353 rhnPackageCapability pc 1354 where 1355 pr.package_id = :package_id 1356 and pr.capability_id = pc.id 1357 union all 1358 select 1359 prec.package_id, 1360 'recommends' as capability_type, 1361 prec.capability_id, 1362 prec.sense, 1363 pc.name, 1364 pc.version 1365 from 1366 rhnPackageRecommends prec, 1367 rhnPackageCapability pc 1368 where 1369 prec.package_id = :package_id 1370 and prec.capability_id = pc.id 1371 union all 1372 select 1373 sugg.package_id, 1374 'suggests' as capability_type, 1375 sugg.capability_id, 1376 sugg.sense, 1377 pc.name, 1378 pc.version 1379 from 1380 rhnPackageSuggests sugg, 1381 rhnPackageCapability pc 1382 where 1383 sugg.package_id = :package_id 1384 and sugg.capability_id = pc.id 1385 union all 1386 select 1387 supp.package_id, 1388 'supplements' as capability_type, 1389 supp.capability_id, 1390 supp.sense, 1391 pc.name, 1392 pc.version 1393 from 1394 rhnPackageSupplements supp, 1395 rhnPackageCapability pc 1396 where 1397 supp.package_id = :package_id 1398 and supp.capability_id = pc.id 1399 union all 1400 select 1401 enh.package_id, 1402 'enhances' as capability_type, 1403 enh.capability_id, 1404 enh.sense, 1405 pc.name, 1406 pc.version 1407 from 1408 rhnPackageEnhances enh, 1409 rhnPackageCapability pc 1410 where 1411 enh.package_id = :package_id 1412 and enh.capability_id = pc.id 1413 union all 1414 select 1415 pcon.package_id, 1416 'conflicts' as capability_type, 1417 pcon.capability_id, 1418 pcon.sense, 1419 pc.name, 1420 pc.version 1421 from 1422 rhnPackageConflicts pcon, 1423 rhnPackageCapability pc 1424 where 1425 pcon.package_id = :package_id 1426 and pcon.capability_id = pc.id 1427 union all 1428 select 1429 po.package_id, 1430 'obsoletes' as capability_type, 1431 po.capability_id, 1432 po.sense, 1433 pc.name, 1434 pc.version 1435 from 1436 rhnPackageObsoletes po, 1437 rhnPackageCapability pc 1438 where 1439 po.package_id = :package_id 1440 and po.capability_id = pc.id 1441 union all 1442 select 1443 brks.package_id, 1444 'breaks' as capability_type, 1445 brks.capability_id, 1446 brks.sense, 1447 pc.name, 1448 pc.version 1449 from 1450 rhnPackageBreaks brks, 1451 rhnPackageCapability pc 1452 where 1453 brks.package_id = :package_id 1454 and brks.capability_id = pc.id 1455 union all 1456 select 1457 pdep.package_id, 1458 'predepends' as capability_type, 1459 pdep.capability_id, 1460 pdep.sense, 1461 pc.name, 1462 pc.version 1463 from 1464 rhnPackagePredepends pdep, 1465 rhnPackageCapability pc 1466 where 1467 pdep.package_id = :package_id 1468 and pdep.capability_id = pc.id 1469 """) 1470 1471 h.execute(channel_id=str(channel_id)) 1472 # XXX This query has to order the architectures somehow; the 7.2 up2date 1473 # client was broken and was selecting the wrong architecture if athlons 1474 # are passed first. The rank ordering here should make sure that i386 1475 # kernels appear before athlons. 1476 ret = h.fetchall_dict() 1477 if not ret: 1478 return [] 1479 for pkgi in ret: 1480 pkgi['provides'] = [] 1481 pkgi['requires'] = [] 1482 pkgi['conflicts'] = [] 1483 pkgi['obsoletes'] = [] 1484 pkgi['recommends'] = [] 1485 pkgi['suggests'] = [] 1486 pkgi['supplements'] = [] 1487 pkgi['enhances'] = [] 1488 pkgi['breaks'] = [] 1489 pkgi['predepends'] = [] 1490 g.execute(package_id=pkgi["id"]) 1491 deps = g.fetchall_dict() or [] 1492 for item in deps: 1493 version = item['version'] or "" 1494 relation = "" 1495 if version: 1496 sense = item['sense'] or 0 1497 if sense & 2: 1498 relation = relation + "<" 1499 if sense & 4: 1500 relation = relation + ">" 1501 if sense & 8: 1502 relation = relation + "=" 1503 if relation: 1504 relation = " " + relation 1505 if version: 1506 version = " " + version 1507 dep = item['name'] + relation + version 1508 pkgi[item['capability_type']].append(dep) 1509 # process the results 1510 ret = [(a["name"], a["version"], a["release"], a["epoch"], 1511 a["arch"], a["package_size"], a['provides'], 1512 a['requires'], a['conflicts'], a['obsoletes'], a['recommends'], a['suggests'], a['supplements'], a['enhances'], a['breaks'], a['predepends']) for a in __stringify(ret)] 1513 return ret
1514 1515
1516 -def list_packages_path(channel_id):
1517 log_debug(3, channel_id) 1518 # return the latest packages from the specified channel 1519 h = rhnSQL.prepare(""" 1520 select 1521 p.path 1522 from 1523 rhnPackage p, 1524 rhnChannelPackage cp 1525 where 1526 cp.channel_id = :channel_id 1527 and cp.package_id = p.id 1528 """) 1529 h.execute(channel_id=str(channel_id)) 1530 ret = h.fetchall() 1531 if not ret: 1532 return [] 1533 # process the results 1534 # ret = map(lambda a: (a["path"]), 1535 # __stringify(ret)) 1536 return ret
1537 1538 1539 # list the latest packages for a channel
1540 -def list_packages(channel):
1541 return _list_packages(channel, cache_prefix="list_packages", 1542 function=list_packages_sql)
1543 1544 # list _all_ the packages for a channel 1545 1546
1547 -def list_all_packages(channel):
1548 return _list_packages(channel, cache_prefix="list_all_packages", 1549 function=list_all_packages_sql)
1550 1551 # list _all_ the packages for a channel, including checksum info 1552 1553
1554 -def list_all_packages_checksum(channel):
1555 return _list_packages(channel, cache_prefix="list_all_packages_checksum", 1556 function=list_all_packages_checksum_sql)
1557 1558 # list _all_ the packages for a channel 1559 1560
1561 -def list_all_packages_complete(channel):
1562 return _list_packages(channel, cache_prefix="list_all_packages_complete", 1563 function=list_all_packages_complete_sql)
1564 1565 # Common part of list_packages and list_all_packages* 1566 # cache_prefix is the prefix for the file name we're caching this request as 1567 # function is the generator function 1568 1569
1570 -def _list_packages(channel, cache_prefix, function):
1571 log_debug(3, channel, cache_prefix) 1572 1573 # try the caching thing first 1574 c_info = channel_info(channel) 1575 if not c_info: # unknown channel 1576 raise rhnFault(40, "could not find any data on channel '%s'" % channel) 1577 cache_entry = "%s-%s" % (cache_prefix, channel) 1578 ret = rhnCache.get(cache_entry, c_info["last_modified"]) 1579 if ret: # we scored a cache hit 1580 log_debug(4, "Scored cache hit", channel) 1581 # Mark the response as being already XMLRPC-encoded 1582 rhnFlags.set("XMLRPC-Encoded-Response", 1) 1583 return ret 1584 1585 ret = function(c_info["id"]) 1586 if not ret: 1587 # we assume that channels with no packages are very fast to list, 1588 # so we don't bother caching... 1589 log_error("No packages found in channel", 1590 c_info["id"], c_info["label"]) 1591 return [] 1592 # we need to append the channel label to the list 1593 ret = list(map(lambda a, c=channel: a + (c,), ret)) 1594 ret = xmlrpclib.dumps((ret, ), methodresponse=1) 1595 # Mark the response as being already XMLRPC-encoded 1596 rhnFlags.set("XMLRPC-Encoded-Response", 1) 1597 # set the cache 1598 rhnCache.set(cache_entry, ret, c_info["last_modified"]) 1599 return ret
1600 1601
1602 -def getChannelInfoForKickstart(kickstart):
1603 query = """ 1604 select c.label, 1605 to_char(c.last_modified, 'YYYYMMDDHH24MISS') last_modified 1606 from rhnChannel c, 1607 rhnKickstartableTree kt 1608 where c.id = kt.channel_id 1609 and kt.label = :kickstart_label 1610 """ 1611 h = rhnSQL.prepare(query) 1612 h.execute(kickstart_label=str(kickstart)) 1613 return h.fetchone_dict()
1614 1615
1616 -def getChannelInfoForKickstartOrg(kickstart, org_id):
1617 query = """ 1618 select c.label, 1619 to_char(c.last_modified, 'YYYYMMDDHH24MISS') last_modified 1620 from rhnChannel c, 1621 rhnKickstartableTree kt 1622 where c.id = kt.channel_id 1623 and kt.label = :kickstart_label 1624 and kt.org_id = :org_id 1625 """ 1626 h = rhnSQL.prepare(query) 1627 h.execute(kickstart_label=str(kickstart), org_id=int(org_id)) 1628 return h.fetchone_dict()
1629 1630
1631 -def getChannelInfoForKickstartSession(session):
1632 # decode the session string 1633 try: 1634 session_id = int(session.split('x')[0].split(':')[0]) 1635 except Exception: 1636 return None, None 1637 1638 query = """ 1639 select c.label, 1640 to_char(c.last_modified, 'YYYYMMDDHH24MISS') last_modified 1641 from rhnChannel c, 1642 rhnKickstartableTree kt, 1643 rhnKickstartSession ks 1644 where c.id = kt.channel_id 1645 and kt.id = ks.kstree_id 1646 and ks.id = :session_id 1647 """ 1648 h = rhnSQL.prepare(query) 1649 h.execute(session_id=session_id) 1650 return h.fetchone_dict()
1651 1652
1653 -def getChildChannelInfoForKickstart(kickstart, child):
1654 query = """ 1655 select c.label, 1656 to_char(c.last_modified, 'YYYYMMDDHH24MISS') last_modified 1657 from rhnChannel c, 1658 rhnKickstartableTree kt, 1659 rhnKickstartSession ks, 1660 rhnChannel c2 1661 where c2.id = kt.channel_id 1662 and kt.label = :kickstart_label 1663 and c.label = :child_label 1664 and c.parent_channel = c2.id 1665 """ 1666 h = rhnSQL.prepare(query) 1667 h.execute(kickstart_label=str(kickstart), child_label=str(child)) 1668 return h.fetchone_dict()
1669 1670
1671 -def getChannelInfoForTinyUrl(tinyurl):
1672 query = """ 1673 select tu.url 1674 from rhnTinyUrl tu 1675 where tu.enabled = 'Y' 1676 and tu.token = :tinyurl 1677 """ 1678 h = rhnSQL.prepare(query) 1679 h.execute(tinyurl=str(tinyurl)) 1680 return h.fetchone_dict()
1681 1682 # list the obsoletes for a channel 1683 1684
1685 -def list_obsoletes(channel):
1686 log_debug(3, channel) 1687 1688 # try the caching thing first 1689 c_info = channel_info(channel) 1690 if not c_info: # unknown channel 1691 raise rhnFault(40, "could not find any data on channel '%s'" % channel) 1692 cache_entry = "list_obsoletes-%s" % channel 1693 ret = rhnCache.get(cache_entry, c_info["last_modified"]) 1694 if ret: # we scored a cache hit 1695 log_debug(4, "Scored cache hit", channel) 1696 return ret 1697 1698 # Get the obsoleted packages 1699 h = rhnSQL.prepare(""" 1700 select distinct 1701 pn.name, 1702 pe.version, pe.release, pe.epoch, 1703 pa.label arch, 1704 pc.name obsolete_name, 1705 pc.version obsolete_version, 1706 p_info.sense 1707 from rhnPackageCapability pc, 1708 rhnPackageArch pa, 1709 rhnPackageEVR pe, 1710 rhnPackageName pn, 1711 rhnPackage p, 1712 ( select cp.channel_id, 1713 po.package_id, po.capability_id, po.sense 1714 from rhnPackageObsoletes po, 1715 rhnChannelPackage cp, 1716 rhnChannel c 1717 where 1=1 1718 and c.label = :channel 1719 and c.id = cp.channel_id 1720 and cp.package_id = po.package_id 1721 ) p_info 1722 where 1=1 1723 and p_info.package_id = p.id 1724 and p.name_id = pn.id 1725 and p.evr_id = pe.id 1726 and p.package_arch_id = pa.id 1727 and p_info.capability_id = pc.id 1728 """) 1729 h.execute(channel=str(channel)) 1730 # Store stuff in a dictionary to makes things simpler 1731 hash = {} 1732 while 1: 1733 row = h.fetchone_dict() 1734 if not row: 1735 break 1736 row = __stringify(row) 1737 key = (row['name'], row['version'], row['release'], 1738 row["epoch"], row['arch']) 1739 value = key + (row['obsolete_name'], row['obsolete_version'], 1740 row['sense']) 1741 if key not in hash: 1742 hash[key] = [] 1743 hash[key].append(value) 1744 1745 # Now grab a listall and match it against what we got 1746 pkglist = list_packages_sql(c_info["id"]) 1747 result = [] 1748 for pkg in pkglist: 1749 key = tuple(pkg[:5]) 1750 if key in hash: 1751 for p in hash[key]: 1752 result.append(p) 1753 # we can cache this now 1754 rhnCache.set(cache_entry, result, c_info["last_modified"]) 1755 return result
1756 1757
1758 -def __auth_user(server_id, username, password):
1759 """ Auth if user can add/remove channel from given server """ 1760 log_debug(3, server_id, username) 1761 # check the username and password for compliance 1762 user = rhnUser.auth_username_password(username, password) 1763 # The user's password checks, verify that they have perms on that 1764 # server. 1765 h = rhnSQL.prepare(""" 1766 select 1 1767 from rhnUserServerPerms usp 1768 where usp.user_id = :user_id 1769 and usp.server_id = :server_id 1770 """) 1771 h.execute(user_id=str(user.getid()), server_id=str(server_id)) 1772 res = h.fetchone_dict() 1773 if not res: 1774 # Not allowed to perform administrative tasks on this server 1775 raise rhnFault(37) 1776 return 1
1777 1778 1779 # small wrapper around a PL/SQL function
1780 -def subscribe_sql(server_id, channel_id, commit=1):
1781 log_debug(3, server_id, channel_id, commit) 1782 subscribe_channel = rhnSQL.Procedure("rhn_channel.subscribe_server") 1783 try: 1784 # don't run the EC yet 1785 subscribe_channel(server_id, channel_id, 0) 1786 except rhnSQL.SQLSchemaError: 1787 e = sys.exc_info()[1] 1788 if e.errno == 20102: # channel_server_one_base 1789 log_error("Channel subscribe failed, " 1790 "%s already subscribed to %s (?)" % (server_id, channel_id)) 1791 raise_with_tb(rhnFault(38, "Server already subscribed to %s" % channel_id), sys.exc_info()[2]) 1792 # If we got here, it's an unknown error; ISE (for now) 1793 log_error("SQLSchemaError", e) 1794 raise_with_tb(rhnException(e), sys.exc_info()[2]) 1795 except rhnSQL.SQLError: 1796 e = sys.exc_info()[1] 1797 # If we got here, it's an unknown error; ISE (for now) 1798 log_error("SQLError", e) 1799 raise_with_tb(rhnException(e), sys.exc_info()[2]) 1800 if commit: 1801 rhnSQL.commit() 1802 return 1
1803 1804 _query_channel_details = rhnSQL.Statement(""" 1805 select c.id, c.label, c.parent_channel 1806 from rhnChannel c 1807 where c.label = :channel 1808 """) 1809 1810 _query_server_parent_channel = rhnSQL.Statement(""" 1811 select pc.id, pc.label 1812 from rhnChannel c 1813 join rhnServerChannel sc on c.parent_channel = sc.channel_id 1814 join rhnChannel pc on c.parent_channel = pc.id 1815 where sc.server_id = :sid 1816 group by pc.id, pc.label 1817 """) 1818 1819 _query_can_subscribe = rhnSQL.Statement(""" 1820 select rhn_channel.user_role_check(:cid, wc.id, 'subscribe') as can_subscribe 1821 from web_contact wc 1822 where wc.login_uc = upper(:username) 1823 """) 1824 1825 # subscribe a server to a channel with authentication
1826 -def subscribe_channel(server_id, channel, username, password):
1827 log_debug(3, server_id, channel, username) 1828 # If auth doesn't blow up we're fine 1829 __auth_user(server_id, username, password) 1830 1831 # get channel details 1832 h = rhnSQL.prepare(_query_channel_details) 1833 h.execute(channel=str(channel)) 1834 channel_details = h.fetchone_dict() 1835 if not channel_details: 1836 log_error("Channel %s does not exist?" % channel) 1837 raise rhnFault(40, "Channel %s does not exist?" % channel) 1838 1839 # get server's parent channel 1840 h = rhnSQL.prepare(_query_server_parent_channel) 1841 h.execute(sid=server_id) 1842 server_parent_channel = h.fetchone_dict() 1843 1844 # Can't add more than one parent or child of parent channel to which server isn't subscibed 1845 if not channel_details['parent_channel'] and server_parent_channel: 1846 log_error("Cannot add parent channel %s. Server already subscribed to parent channel %s." % 1847 (channel, server_parent_channel['label'])) 1848 raise rhnFault(32, "Cannot add parent channel %s. Server already subscribed to parent channel %s." % 1849 (channel, server_parent_channel['label'])) 1850 else: 1851 if ( server_parent_channel and 1852 server_parent_channel['id'] != channel_details['parent_channel'] ): 1853 log_error("Server is not subscribed to parent of channel %s." % channel) 1854 raise rhnFault(32, "Server is not subscribed to parent of channel %s." % channel) 1855 1856 # check specific channel subscription permissions 1857 h = rhnSQL.prepare(_query_can_subscribe) 1858 h.execute(cid=channel_details['id'], username=username) 1859 ret = h.fetchone_dict() 1860 1861 if ret and ret['can_subscribe']: 1862 subscribe_sql(server_id, channel_details['id']) 1863 return 1 1864 1865 raise rhnFault(71)
1866 1867 1868 # This class is only a convenient encapsulation of a server's attributes: 1869 # server_id, org_id, release, arch, user_id. Sometimes we only pass the 1870 # server_id, and later down the road we have to message "no channel for 1871 # release foo, arch bar", but we don't know the release and arch anymore
1872 -class LiteServer:
1873 _attributes = ['id', 'org_id', 'release', 'arch'] 1874
1875 - def __init__(self, **kwargs):
1876 # Initialize attributes from **kwargs (set to None if value is not 1877 # present) 1878 for attr in self._attributes: 1879 setattr(self, attr, kwargs.get(attr))
1880
1881 - def init_from_server(self, server):
1882 self.id = server.getid() 1883 self.org_id = server.server['org_id'] 1884 self.release = server.server['release'] 1885 self.arch = server.archname 1886 return self
1887
1888 - def __repr__(self):
1889 dict = {} 1890 for attr in self._attributes: 1891 dict[attr] = getattr(self, attr) 1892 return "<%s instance at %s: attributes=%s>" % ( 1893 self.__class__.__name__, id(self), dict)
1894 1895 1896 # If raise_exceptions is set, BaseChannelDeniedError, NoBaseChannelError are 1897 # raised
1898 -def guess_channels_for_server(server, user_id=None, none_ok=0, 1899 raise_exceptions=0):
1900 log_debug(3, server) 1901 if not isinstance(server, LiteServer): 1902 raise rhnException("Server object is not a LiteServer") 1903 if None in (server.org_id, server.release, server.arch): 1904 # need to obtain the release and/or arch and/or org_id 1905 h = rhnSQL.prepare(""" 1906 select s.org_id, s.release, sa.label arch 1907 from rhnServer s, rhnServerArch sa 1908 where s.id = :server_id and s.server_arch_id = sa.id 1909 """) 1910 h.execute(server_id=server.id) 1911 ret = h.fetchone_dict() 1912 if not ret: 1913 log_error("Could not get the release/arch " 1914 "for server %s" % server.id) 1915 raise rhnFault(8, "Could not find the release/arch " 1916 "for server %s" % server.id) 1917 if server.org_id is None: 1918 server.org_id = ret["org_id"] 1919 if server.release is None: 1920 server.release = ret["release"] 1921 if server.arch is None: 1922 server.arch = ret["arch"] 1923 1924 if raise_exceptions and not none_ok: 1925 # Let exceptions pass through 1926 return channels_for_release_arch(server.release, server.arch, 1927 server.org_id, user_id=user_id) 1928 1929 try: 1930 return channels_for_release_arch(server.release, server.arch, 1931 server.org_id, user_id=user_id) 1932 except NoBaseChannelError: 1933 if none_ok: 1934 return [] 1935 1936 log_error("No available channels for (server, org)", 1937 (server.id, server.org_id), server.release, server.arch) 1938 msg = _("Your account does not have access to any channels matching " 1939 "(release='%(release)s', arch='%(arch)s')%(www_activation)s") 1940 1941 error_strings = { 1942 'release': server.release, 1943 'arch': server.arch, 1944 'www_activation': '' 1945 } 1946 1947 if CFG.REFER_TO_WWW: 1948 error_strings['www_activation'] = _("\nIf you have a " 1949 "registration number, please register with it first at " 1950 "http://www.redhat.com/apps/activate/ and then try again.\n\n") 1951 1952 raise_with_tb(rhnFault(19, msg % error_strings), sys.exc_info()[2]) 1953 except BaseChannelDeniedError: 1954 if none_ok: 1955 return [] 1956 1957 raise raise_with_tb(rhnFault(71, 1958 _("Insufficient subscription permissions for release (%s, %s") 1959 % (server.release, server.arch)), sys.exc_info()[2])
1960 1961 # Subscribes the server to channels 1962 # can raise BaseChannelDeniedError, NoBaseChannelError 1963 # Only used for new server registrations 1964 1965
1966 -def subscribe_server_channels(server, user_id=None, none_ok=0):
1967 s = LiteServer().init_from_server(server) 1968 1969 # bretm 02/19/2007 -- have to leave none_ok in here for now due to how 1970 # the code is setup for reg token crap; it'd be very nice to clean up that 1971 # path to eliminate any chance for a server to be registered and not have base 1972 # channels, excluding expiration of channel entitlements 1973 channels = guess_channels_for_server(s, user_id=user_id, none_ok=none_ok, 1974 raise_exceptions=1) 1975 rhnSQL.transaction('subscribe_server_channels') 1976 for c in channels: 1977 subscribe_sql(s.id, c["id"], 0) 1978 1979 return channels
1980 1981 # small wrapper around a PL/SQL function 1982 1983
1984 -def unsubscribe_sql(server_id, channel_id, commit=1):
1985 log_debug(3, server_id, channel_id, commit) 1986 unsubscribe_channel = rhnSQL.Procedure("rhn_channel.unsubscribe_server") 1987 try: 1988 # don't run the EC yet 1989 unsubscribe_channel(server_id, channel_id, 0) 1990 except rhnSQL.SQLError: 1991 log_error("Channel unsubscribe from %s failed for %s" % ( 1992 channel_id, server_id)) 1993 return 0 1994 if commit: 1995 rhnSQL.commit() 1996 return 1
1997 1998 # unsubscribe a server from a channel 1999 2000
2001 -def unsubscribe_channel(server_id, channel, username, password):
2002 log_debug(3, server_id, channel, username) 2003 # If auth doesn't blow up we're fine 2004 __auth_user(server_id, username, password) 2005 2006 # now get the id of the channel 2007 h = rhnSQL.prepare(""" 2008 select id, parent_channel from rhnChannel where label = :channel 2009 """) 2010 h.execute(channel=channel) 2011 ret = h.fetchone_dict() 2012 if not ret: 2013 log_error("Asked to unsubscribe server %s from non-existent channel %s" % ( 2014 server_id, channel)) 2015 raise rhnFault(40, "The specified channel '%s' does not exist." % channel) 2016 if not ret["parent_channel"]: 2017 log_error("Cannot unsubscribe %s from base channel %s" % ( 2018 server_id, channel)) 2019 raise rhnFault(72, "You can not unsubscribe %s from base channel %s." % ( 2020 server_id, channel)) 2021 2022 # check specific channel subscription permissions 2023 channel_id = ret['id'] 2024 h = rhnSQL.prepare(_query_can_subscribe) 2025 h.execute(cid=channel_id, username=username) 2026 ret = h.fetchone_dict() 2027 2028 if ret and ret['can_subscribe']: 2029 return unsubscribe_sql(server_id, channel_id) 2030 2031 raise rhnFault(71)
2032 2033 # unsubscribe from all channels 2034 2035
2036 -def unsubscribe_all_channels(server_id):
2037 log_debug(3, server_id) 2038 # We need to unsubscribe the children channels before the base ones. 2039 rhnSQL.transaction("unsub_all_channels") 2040 h = rhnSQL.prepare(""" 2041 select 2042 sc.channel_id id 2043 from 2044 rhnChannel c, 2045 rhnServerChannel sc 2046 where 2047 sc.server_id = :server_id 2048 and sc.channel_id = c.id 2049 order by c.parent_channel nulls last 2050 """) 2051 h.execute(server_id=str(server_id)) 2052 while 1: 2053 c = h.fetchone_dict() 2054 if not c: 2055 break 2056 ret = unsubscribe_sql(server_id, c["id"], 0) 2057 if not ret: 2058 rhnSQL.rollback("unsub_all_channels") 2059 raise rhnFault(36, "Could not unsubscribe server %s " 2060 "from existing channels" % (server_id,)) 2061 # finished unsubscribing 2062 return 1
2063 2064 # Unsubscribe the server from the channels in the list 2065 # A channel is a hash containing at least the keys: 2066 # [id, label, parent_channel] 2067 2068
2069 -def unsubscribe_channels(server_id, channels):
2070 log_debug(4, server_id, channels) 2071 if not channels: 2072 # Nothing to do 2073 return 1 2074 2075 # We need to unsubscribe the children channels before the base ones. 2076 rhnSQL.transaction("unsub_channels") 2077 2078 base_channels = [x for x in channels if not x['parent_channel']] 2079 child_channels = [x for x in channels if x['parent_channel']] 2080 2081 for channel in child_channels + base_channels: 2082 ret = unsubscribe_sql(server_id, channel["id"], 0) 2083 if not ret: 2084 rhnSQL.rollback("unsub_channels") 2085 raise rhnFault(36, "Could not unsubscribe server %s " 2086 "from channel %s" % (server_id, channel["label"])) 2087 2088 # finished unsubscribing 2089 return 1
2090 2091 # Subscribe the server to the channels in the list 2092 # A channel is a hash containing at least the keys: 2093 # [id, label, parent_channel] 2094 2095
2096 -def subscribe_channels(server_id, channels):
2097 log_debug(4, server_id, channels) 2098 if not channels: 2099 # Nothing to do 2100 return 1 2101 2102 # We need to subscribe the base channel before the child ones. 2103 base_channels = [x for x in channels if not x['parent_channel']] 2104 child_channels = [x for x in channels if x['parent_channel']] 2105 2106 for channel in base_channels + child_channels: 2107 subscribe_sql(server_id, channel["id"], 0) 2108 2109 # finished subscribing 2110 return 1
2111 2112 2113 # check if a server is subscribed to a channel
2114 -def is_subscribed(server_id, channel):
2115 log_debug(3, server_id, channel) 2116 h = rhnSQL.prepare(""" 2117 select 1 subscribed 2118 from rhnServerChannel sc, rhnChannel c 2119 where 2120 sc.channel_id = c.id 2121 and c.label = :channel 2122 and sc.server_id = :server_id 2123 """) 2124 h.execute(server_id=str(server_id), channel=str(channel)) 2125 ret = h.fetchone_dict() 2126 if not ret: 2127 # System not subscribed to channel 2128 return 0 2129 return 1
2130 2131 # Returns 0, "", "" if system does not need any message, or 2132 # (error_code, message_title, message) otherwise 2133 2134
2135 -def system_reg_message(server):
2136 server_id = server.server['id'] 2137 # Is this system subscribed to a channel? 2138 h = rhnSQL.prepare(""" 2139 select sc.channel_id 2140 from rhnServerChannel sc 2141 where sc.server_id = :server_id 2142 """) 2143 h.execute(server_id=server_id) 2144 ret = h.fetchone_dict() 2145 if not ret: 2146 # System not subscribed to any channel 2147 # 2148 return (-1, s_invalid_channel_title, 2149 s_invalid_channel_message % 2150 (server.server["release"], server.archname)) 2151 2152 # System does have a base channel; check entitlements 2153 from rhnServer import server_lib # having this on top, cause TB due circular imports 2154 entitlements = server_lib.check_entitlement(server_id) 2155 if not entitlements: 2156 # No entitlement 2157 # We don't have an autoentitle preference for now, so display just one 2158 # message 2159 templates = rhnFlags.get('templateOverrides') 2160 if templates and 'hostname' in templates: 2161 hostname = templates['hostname'] 2162 else: 2163 # Default to www 2164 hostname = "rhn.redhat.com" 2165 params = { 2166 'entitlement_url': "https://%s" 2167 "/rhn/systems/details/Edit.do?sid=%s" % 2168 (hostname, server_id) 2169 } 2170 return -1, no_entitlement_title, no_entitlement_message % params 2171 return 0, "", ""
2172 2173
2174 -def subscribe_to_tools_channel(server_id):
2175 """ 2176 Subscribes server_id to the RHN Tools channel associated with its base channel, if one exists. 2177 """ 2178 base_channel_dict = get_base_channel(server_id, none_ok=1) 2179 2180 if base_channel_dict is None: 2181 raise NoBaseChannelError("Server %s has no base channel." % 2182 str(server_id)) 2183 2184 lookup_child_channels = rhnSQL.Statement(""" 2185 select id, label, parent_channel 2186 from rhnChannel 2187 where parent_channel = :id 2188 """) 2189 2190 child_channel_data = rhnSQL.prepare(lookup_child_channels) 2191 child_channel_data.execute(id=base_channel_dict['id']) 2192 child_channels = child_channel_data.fetchall_dict() 2193 2194 if child_channels is None: 2195 raise NoChildChannels("Base channel id %s has no child channels associated with it." % 2196 base_channel_dict['id']) 2197 2198 tools_channel = None 2199 for channel in child_channels: 2200 if 'label' in channel: 2201 if 'rhn-tools' in channel['label']: 2202 tools_channel = channel 2203 2204 if tools_channel is None: 2205 raise NoToolsChannel("Base channel id %s does not have a RHN Tools channel as a child channel." % 2206 base_channel_dict['id']) 2207 else: 2208 if 'id' not in tools_channel: 2209 raise InvalidChannel("RHN Tools channel has no id.") 2210 if 'label' not in tools_channel: 2211 raise InvalidChannel("RHN Tools channel has no label.") 2212 if 'parent_channel' not in tools_channel: 2213 raise InvalidChannel("RHN Tools channel has no parent_channel.") 2214 2215 subscribe_channels(server_id, [tools_channel])
2216 2217 # Various messages that can be reused 2218 # 2219 # bretm 02/07/2007 -- when we have better old-client documentation, probably 2220 # will be safe to get rid of all this crap 2221 2222 h_invalid_channel_title = _("System Registered but Inactive") 2223 h_invalid_channel_message = _(""" 2224 Invalid Architecture and OS release combination (%s, %s). 2225 Your system has been registered, but will not receive updates 2226 because it is not subscribed to a channel. If you have not yet 2227 activated your product for service, please visit our website at: 2228 2229 http://www.redhat.com/apps/activate/ 2230 2231 ...to activate your product.""") 2232 2233 s_invalid_channel_title = _("System Registered but Inactive") 2234 s_invalid_channel_message = _(""" 2235 Invalid Architecture and OS release combination (%s, %s). 2236 Your system has been registered, but will not receive updates 2237 because it could not be subscribed to a base channel. 2238 Please contact your organization administrator for assistance. 2239 """) 2240 2241 no_autoentitlement_message = _(""" 2242 This system has been successfully registered, but is not yet entitled 2243 to service. To entitle this system to service, login to the web site at: 2244 2245 %(entitlement_url)s 2246 """) 2247 2248 no_entitlement_title = _("System Registered but Inactive") 2249 no_entitlement_message = _(""" 2250 This system has been successfully registered, but no service entitlements 2251 were available. To entitle this system to service, login to the web site at: 2252 2253 %(entitlement_url)s 2254 """) 2255