Package up2date_client :: Module rhnreg
[hide private]
[frames] | no frames]

Source Code for Module up2date_client.rhnreg

  1  # 
  2  # RHN Registration Client 
  3  # Copyright (c) 2000--2016 Red Hat, Inc. 
  4  # 
  5  # Authors: 
  6  #     Adrian Likins <alikins@redhat.com> 
  7  #     Preston Brown <pbrown@redhat.com> 
  8  #     Daniel Benamy <dbenamy@redhat.com> 
  9   
 10  import os 
 11  import sys 
 12  import dbus 
 13   
 14  from up2date_client import up2dateUtils 
 15  from up2date_client import up2dateErrors 
 16  from up2date_client import rhnserver 
 17  from up2date_client import pkgUtils 
 18  from up2date_client import up2dateLog 
 19  from up2date_client import rhnreg_constants 
 20  from up2date_client import hardware 
 21  from up2date_client.rhnPackageInfo import convertPackagesFromHashToList 
 22  from up2date_client.pkgplatform import getPlatform 
 23  from rhn.i18n import ustr, sstr 
 24  from rhn.tb import raise_with_tb 
 25   
 26  try: # python2 
 27      import urlparse 
 28      import xmlrpclib 
 29      from types import ListType, TupleType, StringType, UnicodeType, DictType, DictionaryType 
 30  except ImportError: # python3 
 31      import urllib.parse as urlparse 
 32      import xmlrpc.client as xmlrpclib 
 33      ListType = list 
 34      TupleType = tuple 
 35      StringType = bytes 
 36      UnicodeType = str 
 37      DictType = dict 
 38      DictionaryType = dict 
 39      long = int 
 40   
 41  try: 
 42      from virtualization import support 
 43  except ImportError: 
 44      support = None 
 45   
 46  import gettext 
 47  t = gettext.translation('rhn-client-tools', fallback=True) 
 48  # Python 3 translations don't have a ugettext method 
 49  if not hasattr(t, 'ugettext'): 
 50      t.ugettext = t.gettext 
 51  _ = t.ugettext 
 52   
 53  # global variables 
 54  #SYSID_DIR = /tmp 
 55  SYSID_DIR = "/etc/sysconfig/rhn" 
 56  REMIND_FILE = "%s/rhn_register_remind" % SYSID_DIR 
 57   
 58  HW_CODE_FILE = "%s/hw-activation-code" % SYSID_DIR 
 59  RHSM_FILE = "/etc/pki/consumer/cert.pem" 
 60   
 61  from up2date_client import config 
 62  cfg = config.initUp2dateConfig() 
 63  log = up2dateLog.initLog() 
 64   
 65   
66 -def startRhnsd():
67 # successful registration. Try to start rhnsd if it isn't running. 68 if os.access("/usr/sbin/rhnsd", os.R_OK|os.X_OK): 69 # test for UsrMerge systemd environment 70 systemd_system_unitdir = "/usr/lib/systemd/system" 71 systemd_systemctl = "/usr/bin/systemctl" 72 if not os.access(systemd_systemctl, os.R_OK|os.X_OK): 73 if os.access("/bin/systemctl", os.R_OK|os.X_OK): 74 systemd_systemctl = "/bin/systemctl" 75 systemd_system_unitdir = "/lib/systemd/system" 76 if os.access("%s/rhnsd.service" % systemd_system_unitdir, os.R_OK): 77 # systemd 78 if os.access(systemd_systemctl, os.R_OK|os.X_OK): 79 os.system("%s enable rhnsd > /dev/null" % systemd_systemctl); 80 os.system("%s start rhnsd > /dev/null" % systemd_systemctl); 81 else: 82 print(_("Warning: unable to enable rhnsd with systemd")) 83 else: 84 # SysV init scripts 85 if os.access("/sbin/chkconfig", os.R_OK|os.X_OK): 86 os.system("/sbin/chkconfig rhnsd on > /dev/null"); 87 else: 88 print(_("Warning: unable to enable rhnsd with chkconfig")) 89 90 service_path = "/sbin/service" 91 if not os.access(service_path, os.R_OK|os.X_OK): 92 if os.access("/usr/sbin/service", os.R_OK|os.X_OK): 93 service_path = "/usr/sbin/service" 94 95 rc = os.system("%s rhnsd status > /dev/null" % service_path) 96 if rc: 97 os.system("%s rhnsd start > /dev/null" % service_path)
98
99 -def getOemInfo():
100 configFile = cfg["oemInfoFile"] or "/etc/sysconfig/rhn/oeminfo" 101 102 if not os.access(configFile, os.R_OK): 103 return {} 104 105 fd = open(configFile, "r") 106 L = fd.readlines() 107 108 info = {} 109 for i in L: 110 i = i.strip() 111 if i == "": 112 continue 113 try: 114 (key, value) = i.split(':') 115 except ValueError: 116 raise_with_tb(up2dateErrors.OemInfoFileError(i)) 117 118 info[key] = value.strip() 119 120 return info
121
122 -def rhsm_registered():
123 """ Returns true if system is registred using subscription manager """ 124 if os.access(RHSM_FILE, os.R_OK): 125 statinfo = os.stat(RHSM_FILE) 126 return statinfo.st_size > 0 127 else: 128 return False
129
130 -def registered():
131 return os.access(cfg['systemIdPath'], os.R_OK)
132
133 -def createSystemRegisterRemindFile():
134 if not os.access(REMIND_FILE, os.R_OK): 135 # touch the file to tell the applet it needs to remind 136 # the user to register 137 fd = open(REMIND_FILE, "w+") 138 fd.close()
139
140 -def removeSystemRegisterRemindFile():
141 if os.access(REMIND_FILE, os.R_OK): 142 os.unlink(REMIND_FILE)
143
144 -def _write_secure_file(secure_file, file_contents):
145 """ Write a file to disk that is not readable by other users. """ 146 dir_name = os.path.dirname(secure_file) 147 if not os.access(dir_name, os.W_OK): 148 return False 149 150 if os.access(secure_file, os.F_OK): 151 # already have file there; let's back it up 152 try: 153 os.rename(secure_file, secure_file + '.save') 154 except: 155 return False 156 157 fd = os.open(secure_file, os.O_WRONLY | os.O_CREAT, int('0600', 8)) 158 fd_file = os.fdopen(fd, 'w') 159 try: 160 fd_file.write(sstr(file_contents)) 161 finally: 162 fd_file.close() 163 164 return True
165
166 -def writeSystemId(systemId):
167 res = _write_secure_file(cfg['systemIdPath'], systemId) 168 169 # newer registratio clients will create a file indicating that 170 # we need to remind the user to register, this removes it 171 if res: 172 removeSystemRegisterRemindFile() 173 174 updateRhsmStatus() 175 176 return res
177
178 -def writeHWCode(hw_activation_code):
179 """Returns True if the write is successful or False if it fails.""" 180 return _write_secure_file(HW_CODE_FILE, hw_activation_code + '\n')
181
182 -def get_virt_info():
183 """ 184 This function returns the UUID and virtualization type of this system, if 185 it is a guest. Otherwise, it returns None. To figure this out, we'll 186 use a number of heuristics (list in order of precedence): 187 188 1. Check /proc/xen/xsd_port. If exists, we know the system is a 189 host; exit. 190 2. Check SMBIOS. If vendor='Xen' and UUID is non-zero, we know the 191 system is a fully-virt guest; exit. 192 3. Check /sys/hypervisor/uuid. If exists and is non-zero, we know 193 the system is a para-virt guest; exit. 194 4. If non of the above checks worked; we know we have a 195 non-xen-enabled system; exit. 196 """ 197 198 # First, check whether /proc/xen/xsd_port exists. If so, we know this is 199 # a host system. 200 try: 201 if os.path.exists("/proc/xen/xsd_port"): 202 # Ok, we know this is *at least* a host system. However, it may 203 # also be a fully-virt guest. Check for that next. If it is, we'll 204 # just report that instead since we only support one level of 205 # virtualization. 206 (uuid, virt_type) = get_fully_virt_info() 207 return (uuid, virt_type) 208 except IOError: 209 # Failed. Move on to next strategy. 210 pass 211 212 # This is not a virt host system. Check if it's a fully-virt guest. 213 (uuid, virt_type) = get_fully_virt_info() 214 if uuid is not None: 215 return (uuid, virt_type) 216 217 # This is not a fully virt guest system. Check if it's a para-virt guest. 218 (uuid, virt_type) = get_para_virt_info() 219 if uuid is not None: 220 return (uuid, virt_type) 221 222 # If we got here, we have a system that does not have virtualization 223 # enabled. 224 return (None, None)
225
226 -def get_para_virt_info():
227 """ 228 This function checks /sys/hypervisor/uuid to see if the system is a 229 para-virt guest. It returns a (uuid, virt_type) tuple. 230 """ 231 try: 232 uuid_file = open('/sys/hypervisor/uuid', 'r') 233 uuid = uuid_file.read() 234 uuid_file.close() 235 uuid = uuid.lower().replace('-', '').rstrip("\r\n") 236 virt_type = "para" 237 return (uuid, virt_type) 238 except IOError: 239 # Failed; must not be para-virt. 240 pass 241 242 return (None, None)
243
244 -def get_fully_virt_info():
245 """ 246 This function looks in the SMBIOS area to determine if this is a 247 fully-virt guest. It returns a (uuid, virt_type) tuple. 248 """ 249 vendor = hardware.dmi_vendor() 250 uuid = hardware.dmi_system_uuid() 251 if vendor.lower() == "xen": 252 uuid = uuid.lower().replace('-', '') 253 virt_type = "fully" 254 return (uuid, virt_type) 255 else: 256 return (None, None)
257
258 -def _is_host_uuid(uuid):
259 uuid = eval('0x%s' % uuid) 260 return long(uuid) == long(0)
261
262 -def welcomeText():
263 s = rhnserver.RhnServer() 264 265 return s.registration.welcome_message()
266 267
268 -def getCaps():
269 s = rhnserver.RhnServer() 270 # figure out if were missing any needed caps 271 s.capabilities.validate()
272
273 -def reserveUser(username, password):
274 s = rhnserver.RhnServer() 275 return s.registration.reserve_user(username, password)
276 277
278 -class RegistrationResult:
279 - def __init__(self, systemId, channels, failedChannels, systemSlots, 280 failedSystemSlots, universalActivationKey, rawDict=None):
281 # TODO Get rid of rawDict 282 self._systemId = systemId 283 self._channels = channels 284 self._failedChannels = failedChannels 285 self._systemSlots = systemSlots 286 self._failedSystemSlots = failedSystemSlots 287 if len(universalActivationKey) > 0: 288 self._universalActivationKey = universalActivationKey 289 else: 290 self._universalActivationKey = None 291 self.rawDict = rawDict
292
293 - def getSystemId(self):
294 return self._systemId
295
296 - def getChannels(self):
297 return self._channels
298
299 - def getFailedChannels(self):
300 return self._failedChannels
301
302 - def getSystemSlots(self):
303 return self._systemSlots
304
306 return [self._getSlotDescription(s) for s in self._systemSlots]
307
309 return [self._getFailedSlotDescription(s) for s in self._failedSystemSlots]
310
312 """Returns None if no universal activation key was used.""" 313 return self._universalActivationKey
314
315 - def hasBaseAndUpdates(self):
316 """Returns True if the system was subscribed to at least one channel 317 and was given any type of system slot so it will get updates. In other 318 words, returns True if the system will be getting at least basic 319 updates. 320 321 """ 322 # If it was subscribed to at least one channel, that must include a 323 # base channel. 324 return len(self._channels) > 0 and len(self._systemSlots) > 0
325
326 - def _getFailedSlotDescription(self, slot):
327 if slot == 'virtualization_host': 328 return rhnreg_constants.VIRT + " " + rhnreg_constants.VIRT_FAILED 329 else: 330 return self._getSlotDescription(slot)
331
332 - def _getSlotDescription(self, slot):
333 if slot == 'enterprise_entitled': 334 return rhnreg_constants.MANAGEMENT 335 elif slot == 'virtualization_host': 336 return rhnreg_constants.VIRT 337 else: 338 return slot
339 340
341 -def registerSystem(username = None, password = None, 342 profileName = None, 343 token = None, other = None):
344 """Wrapper for the old xmlrpc to register a system. Activates subscriptions 345 if a reg num is given. 346 347 """ 348 auth_dict = { "profile_name" : profileName, 349 "os_release" : up2dateUtils.getVersion(), 350 "release_name" : up2dateUtils.getOSRelease(), 351 "architecture" : up2dateUtils.getArch() } 352 # dict of other bits to send 353 if other: 354 for (key, item) in other.items(): 355 auth_dict[key] = item 356 if token: 357 auth_dict["token"] = token 358 else: 359 auth_dict["username"] = username 360 auth_dict["password"] = password 361 362 if cfg['supportsSMBIOS']: 363 auth_dict["smbios"] = _encode_characters(hardware.get_smbios()) 364 365 s = rhnserver.RhnServer() 366 ret = s.registration.new_system(auth_dict) 367 368 return ret
369
370 -def updateRhsmStatus():
371 try: 372 bus = dbus.SystemBus() 373 validity_obj = bus.ProxyObjectClass(bus, 'com.redhat.SubscriptionManager', 374 '/EntitlementStatus', introspect=False) 375 validity_iface = dbus.Interface(validity_obj, 376 dbus_interface='com.redhat.SubscriptionManager.EntitlementStatus') 377 except dbus.DBusException: 378 # we can't connect to dbus. it's not running, likely from a minimal 379 # install. we can't do anything here, so just ignore it. 380 return 381 382 try: 383 validity_iface.check_status() 384 except dbus.DBusException: 385 # the call timed out, or something similar. we don't really care 386 # about a timely reply or what the result might be, we just want 387 # the method to run. So we can safely ignore this. 388 pass
389 390
391 -def getAvailableChannels(username, password):
392 s = rhnserver.RhnServer() 393 server_arch = up2dateUtils.getArch() 394 server_version = up2dateUtils.getVersion() 395 server_release = up2dateUtils.getRelease() 396 397 availableChannels = None 398 399 try: 400 availableChannels = s.registration.available_eus_channels( 401 username, password, 402 server_arch, server_version, 403 server_release) 404 except xmlrpclib.Fault: 405 f = sys.exc_info()[1] 406 if f.faultCode == 99: 407 raise_with_tb(up2dateErrors.DelayError(f.faultString)) 408 else: 409 raise 410 411 return availableChannels
412 413 414 415
416 -def registerSystem2(username = None, password = None, 417 profileName = None, packages = None, 418 activationKey = None, other = {}):
419 """Uses the new xmlrpcs to register a system. Returns a dict instead of just 420 system id. 421 422 The main differences between this and registerSystem and that this doesn't 423 do activation and does child channel subscriptions if possible. See the 424 documentation for the xmlrpc handlers in backend for more detail. 425 426 If nothing is going to be in other, it can be {} or None. 427 428 New in RHEL 5. 429 430 """ 431 if other is None: 432 other = {} 433 434 if activationKey: 435 assert username is None 436 assert password is None 437 assert activationKey is not None 438 else: 439 assert username is not None 440 assert password is not None 441 assert activationKey is None 442 for key in other.keys(): 443 assert key in ['registration_number', 444 'org_id', 445 'virt_uuid', 446 'virt_type', 447 'channel'] 448 449 if cfg['supportsSMBIOS']: 450 other["smbios"] = _encode_characters(hardware.get_smbios()) 451 452 s = rhnserver.RhnServer() 453 454 if activationKey: 455 info = s.registration.new_system_activation_key(profileName, 456 up2dateUtils.getOSRelease(), 457 up2dateUtils.getVersion(), 458 up2dateUtils.getArch(), 459 activationKey, 460 other) 461 else: 462 info = s.registration.new_system_user_pass(profileName, 463 up2dateUtils.getOSRelease(), 464 up2dateUtils.getVersion(), 465 up2dateUtils.getArch(), 466 username, 467 password, 468 other) 469 log.log_debug("Returned:\n%s" % info) 470 result = RegistrationResult(info['system_id'], 471 info['channels'], info['failed_channels'], 472 info['system_slots'], info['failed_system_slots'], 473 info['universal_activation_key'], 474 rawDict=info) 475 return result
476
477 -def server_supports_eus():
478 return cfg["supportsEUS"]
479
480 -def sendHardware(systemId, hardwareList):
481 def remove_ip6addr(x): 482 if x['class'] == 'NETINFO' and 'ip6addr' in x: 483 del x['ip6addr'] 484 return x
485 s = rhnserver.RhnServer() 486 if not s.capabilities.hasCapability('ipv6', 1): 487 hardwareList = [remove_ip6addr(i) for i in hardwareList] 488 s.registration.add_hw_profile(systemId, _encode_characters(hardwareList)) 489
490 -def sendPackages(systemId, packageList):
491 s = rhnserver.RhnServer() 492 if not s.capabilities.hasCapability('xmlrpc.packages.extended_profile', 2): 493 # for older satellites and hosted - convert to old format 494 packageList = convertPackagesFromHashToList(packageList) 495 s.registration.add_packages(systemId, packageList)
496
497 -def sendVirtInfo(systemId):
498 if support is not None: 499 support.refresh()
500
501 -def listPackages(systemId):
502 s = rhnserver.RhnServer() 503 print(s.registration.list_packages,systemId())
504
505 -def makeNiceServerUrl(server):
506 """Raises up2dateErrors.InvalidProtocolError if the server url has a 507 protocol specified and it's not http or https. 508 509 """ 510 protocol, host, path, parameters, query, fragmentIdentifier = urlparse.urlparse(server) 511 if protocol is None or protocol == '': 512 server = 'https://' + server 513 # We must call it again because if there wasn't a protocol the 514 # host will be in path 515 protocol, host, path, parameters, query, fragmentIdentifier = urlparse.urlparse(server) 516 if protocol not in ['https', 'http']: 517 raise up2dateErrors.InvalidProtocolError("You specified an invalid " 518 "protocol. Only https and " 519 "http are allowed.") 520 if path is None or path == '' or path == '/': 521 path = '/XMLRPC' 522 server = urlparse.urlunparse((protocol, host, path, parameters, query, 523 fragmentIdentifier)) 524 # TODO Raise an exception if url isn't valid 525 return server
526
527 -def getServerType(serverUrl=None):
528 """Returns 'hosted' if the url points to a known hosted server. Otherwise 529 returns 'satellite'. 530 """ 531 return 'satellite'
532 533
534 -class ActivationResult:
535 ACTIVATED_NOW = 0 536 ALREADY_USED = 1 537
538 - def __init__(self, status, registrationNumber, channels={}, systemSlots={}):
539 """channels and systemSlots are dicts where the key/value pairs are 540 label (string) / quantity (int). 541 542 """ 543 self._status = status 544 # TODO Validate reg num 545 self._regNum = registrationNumber 546 self._channels = channels 547 self._systemSlots = systemSlots
548
549 - def getStatus(self):
550 return self._status
551
552 - def getRegistrationNumber(self):
553 return self._regNum
554
555 - def getChannelsActivated(self):
556 """Returns a dict- the key/value pairs are label/quantity.""" 557 return self._channels
558
559 - def getSystemSlotsActivated(self):
560 """Returns a dict- the key/value pairs are label/quantity.""" 561 return self._systemSlots
562
563 -def _encode_characters(*args):
564 """ All the data we gathered from dmi, bios, gudev are in utf-8, 565 we need to convert characters beyond ord(127) - e.g \xae to unicode. 566 """ 567 result=[] 568 for item in args: 569 item_type = type(item) 570 if item_type == StringType: 571 item = ustr(item) 572 elif item_type == TupleType: 573 item = tuple(_encode_characters(i) for i in item) 574 elif item_type == ListType: 575 item = [_encode_characters(i) for i in item] 576 elif item_type == DictType or item_type == DictionaryType: 577 item = dict([(_encode_characters(name, val)) for name, val in item.items()]) 578 # else: numbers or UnicodeType - are safe 579 result.append(item) 580 if len(result) == 1: 581 return result[0] 582 else: 583 return tuple(result)
584
585 -def _activate_hardware(login, password):
586 587 # Read the asset code from the hardware. 588 activateHWResult = None 589 hardwareInfo = None 590 hw_activation_code = None 591 try: 592 hardwareInfo = hardware.get_hal_system_and_smbios() 593 hardwareInfo = _encode_characters(hardwareInfo) 594 except: 595 log.log_me("There was an error while reading the hardware " 596 "info from the bios. Traceback:\n") 597 log.log_exception(*sys.exc_info()) 598 599 if hardwareInfo is not None: 600 try: 601 activateHWResult = activateHardwareInfo( 602 login, password, hardwareInfo) 603 if activateHWResult.getStatus() == ActivationResult.ACTIVATED_NOW: 604 hw_activation_code = activateHWResult.getRegistrationNumber() 605 writeHWCode(hw_activation_code) 606 except up2dateErrors.NotEntitlingError: 607 log.log_debug('There are are no entitlements associated ' 608 'with this hardware.') 609 except up2dateErrors.InvalidRegistrationNumberError: 610 log.log_debug('The hardware id was not recognized as valid.') 611 return hw_activation_code
612
613 -def activateHardwareInfo(username, password, hardwareInfo, orgId=None):
614 """Tries to activate an entitlement linked to the hardware info that we 615 read from the bios. 616 617 Returns an ActivationResult. 618 Can raise: 619 Invalid number. 620 Hardware info is not entitling. 621 Communication errors, etc 622 623 """ 624 ## import pprint 625 ## pprint.pprint(hardwareInfo) 626 627 other = {} 628 if orgId: 629 other = {'org_id': orgId} 630 631 server = rhnserver.RhnServer() 632 result = server.registration.activate_hardware_info(username, password, 633 hardwareInfo, other) 634 statusCode = result['status_code'] 635 regNum = result['registration_number'] 636 log.log_debug('Server returned status code %s' % statusCode) 637 if statusCode == 0: 638 return ActivationResult(ActivationResult.ACTIVATED_NOW, regNum) 639 elif statusCode == 1: 640 return ActivationResult(ActivationResult.ALREADY_USED, regNum) 641 else: 642 message = "The server returned unknown status code %s while activating" \ 643 " the hardware info." % statusCode 644 raise up2dateErrors.CommunicationError(message)
645 646
647 -def spawnRhnCheckForUI():
648 if os.access("/usr/sbin/rhn_check", os.R_OK|os.X_OK): 649 from subprocess import Popen, PIPE 650 p = Popen(["/usr/sbin/rhn_check"], stdin=PIPE, stdout=PIPE, \ 651 stderr=PIPE) 652 map(lambda x:log.log_me(x), p.stdout.readlines() + \ 653 p.stderr.readlines()) 654 else: 655 log.log_me("Warning: unable to run rhn_check")
656 657 if getPlatform() == 'deb':
658 - def pluginEnable():
659 """On Debian no extra action for plugin is needed""" 660 return 1, 0
661 else: 662 from up2date_client.pmPlugin import pluginEnable 663