Package backend :: Package server :: Package handlers :: Package xmlrpc :: Module registration
[hide private]
[frames] | no frames]

Source Code for Module backend.server.handlers.xmlrpc.registration

   1  # 
   2  # Copyright (c) 2008--2020 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  # system modules 
  17  import sys 
  18   
  19  from spacewalk.common.usix import raise_with_tb 
  20  from spacewalk.common import rhnFlags, rhnMail 
  21  from spacewalk.common.rhnLog import log_debug, log_error 
  22  from spacewalk.common.rhnConfig import CFG 
  23  from spacewalk.common.rhnException import rhnFault 
  24  from spacewalk.common.rhnTranslate import _, cat 
  25  from spacewalk.common.rhnLib import checkValue 
  26  from spacewalk.server.rhnLib import normalize_server_arch 
  27  from spacewalk.server.rhnServer import server_route, server_lib 
  28  from spacewalk.server.rhnServer.server_certificate import Certificate 
  29  from spacewalk.server.rhnHandler import rhnHandler 
  30  from spacewalk.server import rhnUser, rhnServer, rhnSQL, rhnCapability, \ 
  31      rhnChannel, rhnVirtualization 
  32  from spacewalk.common.rhnTB import add_to_seclist 
  33   
  34   
35 -def hash_validate(data, *keylist):
36 """ verify that a hash has all the keys and those have actual values """ 37 for k in keylist: 38 if k not in data: 39 return 0 40 l = data[k] 41 if l is None: 42 return 0 43 if type(l) == type("") and len(l) == 0: 44 return 0 45 return 1
46 47
48 -def parse_smbios(smbios):
49 vendor = smbios.get('smbios.bios.vendor') 50 serial = smbios.get('smbios.system.serial', '') 51 manufacturer = smbios.get('smbios.system.manufacturer') 52 product = smbios.get('smbios.system.product') 53 54 # XXX need to worry about uuid being none for other virt types and 55 # available subs check 56 uuid = None 57 if 'smbios.system.uuid' in smbios: 58 uuid = smbios['smbios.system.uuid'] 59 uuid = uuid.replace('-', '') 60 61 virttype = None 62 if uuid is not None and ( 63 vendor == "QEMU" 64 or manufacturer == 'QEMU' 65 or (manufacturer == 'Bochs' and product == 'Bochs') # Bochs is a virtual SUSE KVM machine 66 or (manufacturer == 'RDO' and product == 'OpenStack Compute') # Openstack compute 67 or (manufacturer == 'Google' and product == 'Google Compute Engine') # Google Compute Engine 68 or (manufacturer == 'Red Hat' and product in ('KVM', 'RHEV Hypervisor', 'OpenStack Compute')) 69 or (product == 'OpenStack Nova' and (manufacturer in ('Fedora Project', 'RDO Project') or 70 manufacturer and manufacturer.startswith('Red Hat'))) 71 or (manufacturer == 'oVirt' and product in ('oVirt Node', 'RHEV Hypervisor')) 72 or (manufacturer == 'Nutanix' and product == 'AHV')): 73 virttype = rhnVirtualization.VirtualizationType.QEMU 74 else: 75 if manufacturer == 'Microsoft Corporation' and product == 'Virtual Machine': 76 virttype = rhnVirtualization.VirtualizationType.HYPERV 77 elif serial.startswith('VMware-'): 78 virttype = rhnVirtualization.VirtualizationType.VMWARE 79 elif manufacturer == 'HITACHI' and product.endswith(' HVM LPAR'): 80 virttype = rhnVirtualization.VirtualizationType.VIRTAGE 81 if uuid is None: 82 uuid = "flex-guest" 83 84 if virttype: 85 return (virttype, uuid) 86 return (None, None)
87 88
89 -class Registration(rhnHandler):
90 91 """ encapsulate functions that we will provide for the outside world """ 92
93 - def __init__(self):
94 rhnHandler.__init__(self) 95 self.functions.append("activate_registration_number") 96 self.functions.append("activate_hardware_info") 97 self.functions.append("available_eus_channels") 98 self.functions.append("add_hw_profile") 99 self.functions.append("add_packages") 100 self.functions.append("anonymous") 101 self.functions.append("delete_packages") 102 self.functions.append("delta_packages") 103 self.functions.append("finish_message") 104 self.functions.append("get_possible_orgs") 105 self.functions.append("new_system") 106 self.functions.append("new_system_user_pass") 107 # self.functions.append("new_system_activation_key") 108 self.functions.append("new_user") # obsoleted 109 self.functions.append("privacy_statement") 110 self.functions.append("refresh_hw_profile") 111 self.functions.append("register_osad") 112 self.functions.append("register_osad_jid") 113 self.functions.append("register_product") 114 self.functions.append("remaining_subscriptions") # obsoleted 115 self.functions.append("reserve_user") # obsoleted 116 self.functions.append("send_serial") 117 self.functions.append("upgrade_version") 118 self.functions.append("update_contact_info") # obsoleted 119 self.functions.append("update_packages") 120 self.functions.append("update_systemid") 121 self.functions.append("update_transactions") 122 self.functions.append("virt_notify") 123 self.functions.append("welcome_message") 124 125 # defaults for the authentication section 126 self.load_user = 0 127 self.check_entitlement = 0 128 self.throttle = 0 129 130 # a mapping between vendor and asset tags or serial numbers. 131 # if we want to support other vendors for re 132 self.vendor_tags = {'DELL': 'smbios.system.serial'}
133
134 - def reserve_user(self, username, password):
135 """ 136 Get an username and a password and create a record for this user. 137 Eventually mark it as such. 138 Additionaly this method is used to verify login and password in early 139 stage of rhn_register. 140 141 Returns true value if user is reserved, otherwise fault is raised. 142 """ 143 144 add_to_seclist(password) 145 146 log_debug(1, username) 147 # check user login/password and if not CFG.disallow_user_creation 148 # then reserver the user 149 ret = rhnUser.reserve_user(username, password) 150 log_debug(3, "rhnUser.reserve_user returned: " + str(ret)) 151 if ret < 0: 152 raise rhnFault(3) 153 return ret
154
155 - def new_user(self, username, password, email=None, 156 org_id=None, org_password=None):
157 """ 158 Finish off creating the user. 159 160 The user has to exist (must be already reserved), the password must 161 match and we set the e-mail address if one is given 162 163 Return true if success 164 """ 165 166 log_debug(1, username, email) 167 # email has to be a string or nothing 168 if not checkValue(email, None, "", type("")): 169 raise rhnFault(30, _faultValueString(email, "email")) 170 # be somewhat drastic about the org values 171 if org_id and org_password: 172 org_password = str(org_password) 173 try: 174 org_id = int(str(org_id)) 175 except ValueError: 176 raise_with_tb(rhnFault(30, _faultValueString(org_id, "org_id")), sys.exc_info()[2]) 177 else: 178 org_id = org_password = None 179 username, password = rhnUser.check_user_password(username, password) 180 email = rhnUser.check_email(email) 181 # now create this user 182 ret = rhnUser.new_user(username, password, email, org_id, org_password) 183 # rhnUser.new_user will raise it's own faults. 184 return ret
185
186 - def validate_system_input(self, data):
187 """ check the input data """ 188 if not hash_validate(data, "os_release", "architecture", "profile_name"): 189 log_error("Incomplete data hash") 190 raise rhnFault(21, _("Required data missing")) 191 # we require either a username and a password or a token 192 if not hash_validate(data, "username", "password") and \ 193 not hash_validate(data, "token"): 194 raise rhnFault(21, _("Required members missing"))
195
196 - def validate_system_user(self, username, password):
197 username, password = rhnUser.check_user_password(username, 198 password) 199 user = rhnUser.search(username) 200 201 if user is None: 202 log_error("Can't register server to non-existent user") 203 raise rhnFault(2, _("Attempt to register a system to an invalid username")) 204 205 # This check validates username and password 206 if not user.check_password(password): 207 log_error("User password check failed", username) 208 raise rhnFault(2) 209 210 if rhnUser.is_user_disabled(username): 211 msg = _(""" 212 %s Account has been deactivated on this server. 213 Please contact your Org administrator for more help.""") 214 raise rhnFault(1, msg % username, explain=0) 215 216 return user
217
218 - def create_system(self, user, profile_name, release_version, 219 architecture, data):
220 """ 221 Create a system based on the input parameters. 222 223 Return dict containing a server object for now. 224 Called by new_system (< rhel5) 225 and new_system_user_pass | new_system_activation_key (>= rhel5) 226 """ 227 228 if profile_name is not None and not \ 229 rhnFlags.test("re_registration_token") and \ 230 len(profile_name) < 1: 231 raise rhnFault(800) 232 233 # log entry point 234 if "token" in data: 235 log_item = "token = '%s'" % data["token"] 236 else: 237 log_item = "username = '%s'" % user.username 238 239 log_debug(1, log_item, release_version, architecture) 240 241 # Fetch the applet's UUID 242 if "uuid" in data: 243 applet_uuid = data['uuid'] 244 log_debug(3, "applet uuid", applet_uuid) 245 else: 246 applet_uuid = None 247 248 # Fetch the up2date UUID 249 if "rhnuuid" in data: 250 up2date_uuid = data['rhnuuid'] 251 log_debug(3, "up2date uuid", up2date_uuid) 252 # XXX Should somehow check the uuid uniqueness 253 #raise rhnFault(105, "A system cannot be registered multiple times") 254 else: 255 up2date_uuid = None 256 257 release = str(release_version) 258 259 if 'token' in data: 260 token_string = data['token'] 261 # Look the token up; if the token does not exist or is invalid, 262 # stop right here (search_token raises the appropriate rhnFault) 263 tokens_obj = rhnServer.search_token(token_string) 264 log_user_id = tokens_obj.get_user_id() 265 else: 266 # user should not be null here 267 log_user_id = user.getid() 268 tokens_obj = rhnServer.search_org_token(user.contact["org_id"]) 269 log_debug(3, "universal_registration_token set as %s" % 270 str(tokens_obj.get_tokens())) 271 rhnFlags.set("universal_registration_token", tokens_obj) 272 273 if 'channel' in data and len(data['channel']) > 0: 274 channel = data['channel'] 275 log_debug(3, "requested EUS channel: %s" % str(channel)) 276 else: 277 channel = None 278 279 newserv = None 280 if tokens_obj: 281 # Only set registration_token if we have token(s) available. 282 # server_token.ActivationTokens.__nonzero__ should do the right 283 # thing of filtering the case of no tokens 284 rhnFlags.set("registration_token", tokens_obj) 285 # Is the token associated with a server? 286 if tokens_obj.is_rereg_token: 287 # Also flag it's a re-registration token 288 rhnFlags.set("re_registration_token", tokens_obj) 289 # Load the server object 290 newserv = rhnServer.search(tokens_obj.get_server_id()) 291 newserv.disable_token() 292 # The old hardware info no longer applies 293 newserv.delete_hardware() 294 # Update the arch - it may have changed; we know the field was 295 # provided for us 296 newserv.set_arch(architecture) 297 # if no creator_id use the activation key owner, else keep 298 if not newserv.server['creator_id']: 299 newserv.user = user 300 else: 301 newserv.user = rhnUser.User("", "") 302 newserv.user.reload(newserv.server['creator_id']) 303 # Generate a new secret for this server 304 newserv.gen_secret() 305 # Get rid of the old package profile - it's bogus in this case 306 newserv.dispose_packages() 307 # The new server may have a different base channel 308 newserv.change_base_channel(release) 309 310 if newserv is None: 311 # Not a re-registration token, we need a fresh server object 312 rhnSQL.set_log_auth(log_user_id) 313 newserv = rhnServer.Server(user, architecture) 314 315 # Proceed with using the rest of the data 316 newserv.server["release"] = release 317 if 'release_name' in data: 318 newserv.server["os"] = data['release_name'] 319 320 # add the package list 321 if 'packages' in data: 322 for package in data['packages']: 323 newserv.add_package(package) 324 # add the hardware profile 325 if 'hardware_profile' in data: 326 for hw in data['hardware_profile']: 327 newserv.add_hardware(hw) 328 # fill in the other details from the data dictionary 329 if profile_name is not None and not \ 330 rhnFlags.test("re_registration_token"): 331 newserv.server["name"] = profile_name[:128] 332 if 'os' in data: 333 newserv.server["os"] = data["os"][:64] 334 if 'description' in data: 335 newserv.server["description"] = data["description"][:256] 336 else: 337 newserv.default_description() 338 339 # Check for virt params 340 # Get the uuid, if there is one. 341 if 'virt_uuid' in data: 342 virt_uuid = data['virt_uuid'] 343 if virt_uuid is not None \ 344 and not rhnVirtualization.is_host_uuid(virt_uuid): 345 # If we don't have a virt_type key, we'll assume PARA. 346 virt_type = None 347 if 'virt_type' in data: 348 virt_type = data['virt_type'] 349 if virt_type == 'para': 350 virt_type = rhnVirtualization.VirtualizationType.PARA 351 elif virt_type == 'fully': 352 virt_type = rhnVirtualization.VirtualizationType.FULLY 353 else: 354 raise Exception( 355 "Unknown virtualization type: %s" % virt_type) 356 else: 357 raise Exception("Virtualization type not provided") 358 newserv.virt_uuid = virt_uuid 359 newserv.virt_type = virt_type 360 else: 361 newserv.virt_uuid = None 362 newserv.virt_type = None 363 else: 364 newserv.virt_uuid = None 365 newserv.virt_type = None 366 367 # If we didn't find virt info from xen, check smbios 368 if 'smbios' in data and newserv.virt_uuid is None: 369 (newserv.virt_type, newserv.virt_uuid) = \ 370 parse_smbios(data['smbios']) 371 372 if tokens_obj.forget_rereg_token: 373 # At this point we retained the server with re-activation 374 # let the stacked activation keys do their magic 375 tokens_obj.is_rereg_token = 0 376 rhnFlags.set("re_registration_token", 0) 377 378 # now if we have a token, load the extra registration 379 # information from the token 380 if rhnFlags.test("registration_token"): 381 # Keep the original "info" field 382 newserv.load_token() 383 # we need to flush the registration information into the 384 # database so we can proceed with processing the rest of 385 # the token information (like subscribing the server to 386 # groups, channels, etc) 387 388 # bretm 02/19/2007 -- this shouldn't throw any of the following: 389 # BaseChannelDeniedError 390 # NoBaseChannelError 391 # since we have the token object, and underneath the hood, we have none_ok=have_token 392 393 # BUT - it does. So catch them and throw. this will make rhnreg_ks 394 # die out, but oh well. at least they don't end up registered, and 395 # without a base channel. 396 try: 397 # don't commit 398 newserv.save(0, channel) 399 except (rhnChannel.NoBaseChannelError), channel_error: 400 raise_with_tb(rhnFault(70), sys.exc_info()[2]) 401 except rhnChannel.BaseChannelDeniedError, channel_error: 402 raise_with_tb(rhnFault(71), sys.exc_info()[2]) 403 except server_lib.rhnSystemEntitlementException: 404 e = sys.exc_info()[1] 405 raise_with_tb(rhnFault(90), sys.exc_info()[2]) 406 407 # Process any kickstart data associated with this server 408 # Do this before using/processing the token, as the 409 # potential pkg delta shadow action should happen first 410 log_debug(3, "reg token process_kickstart_info") 411 newserv.process_kickstart_info() 412 413 # now do the rest of the processing for the token registration 414 newserv.use_token() 415 else: 416 # Some information 417 newserv.server["info"] = "rhn_register by %s" % log_item 418 log_debug(3, "rhn_register process_kickstart_info") 419 newserv.process_kickstart_info() 420 421 # Update the uuid if necessary 422 if up2date_uuid: 423 newserv.uuid = up2date_uuid 424 425 # save it 426 # Commits to the db. 427 # 428 # bretm 02/19/2007 -- this *can* now throw any of the following: 429 # rhnChannel.BaseChannelDeniedError 430 # rhnChannel.NoBaseChannelError 431 # rhnSystemEntitlementException 432 # | 433 # +--rhnNoSystemEntitlementsException 434 try: 435 newserv.save(1, channel) 436 except (rhnChannel.NoBaseChannelError), channel_error: 437 raise_with_tb(rhnFault(70), sys.exc_info()[2]) 438 except rhnChannel.BaseChannelDeniedError, channel_error: 439 raise_with_tb(rhnFault(71), sys.exc_info()[2]) 440 except server_lib.rhnSystemEntitlementException: 441 e = sys.exc_info()[1] 442 # right now, don't differentiate between general ent issues & rhnNoSystemEntitlementsException 443 raise_with_tb(rhnFault(90), sys.exc_info()[2]) 444 445 if CFG.SEND_EOL_MAIL and user and newserv.base_channel_is_eol(): 446 self.attempt_eol_mailing(user, newserv) 447 448 # XXX: until this is complete, bug: 449 # http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=112450 450 # store route in DB (schema for RHN 3.1+ only!) 451 server_route.store_client_route(newserv.getid()) 452 453 return {'server': newserv, }
454
455 - def new_system(self, data):
456 """ 457 This function expects at the INPUT a dictionary that has at least 458 the following members: username, password, os_release, email 459 If the username does not exist, it is created. If the username 460 exists, then password is checked for a match. 461 If all is well, we send back a server certificate. 462 -- 463 Hash 464 -- 465 Struct 466 467 Starting with RHEL 5, the client will use activate_registration_number, 468 activate_hardware_info, new_system_user_pass, and/or 469 new_system_activation_key instead of this. 470 471 In hosted, RHEL 4 and earlier will also call 472 activate_registration_number 473 """ 474 475 if "password" in data: 476 add_to_seclist(data["password"]) 477 478 # Validate we got the minimum necessary input. 479 self.validate_system_input(data) 480 481 # Authorize username and password, if used. 482 # Store the user object in user. 483 user = None 484 if 'token' not in data: 485 user = self.validate_system_user(data["username"], 486 data["password"]) 487 488 release_version = data['os_release'] 489 profile_name = data['profile_name'] 490 architecture = data['architecture'] 491 492 # Create the system and get back the rhnServer object. 493 # 494 # bretm 02/19/2007 -- the following things get thrown underneath, 495 # but we issue the faults in create_system for uniformity: 496 # 497 # rhnChannel.BaseChannelDeniedError 498 # rhnChannel.NoBaseChannelError 499 # rhnSystemEntitlementException 500 # | 501 # +--rhnNoSystemEntitlementsException 502 server_data = self.create_system(user, profile_name, 503 release_version, 504 architecture, data) 505 newserv = server_data['server'] 506 507 system_certificate = newserv.system_id() 508 509 # Return the server certificate file down to the client. 510 return system_certificate
511
512 - def new_system_user_pass(self, profile_name, os_release_name, 513 version, arch, username, 514 password, other):
515 """ Registers a new system to an org specified by a username, password, and 516 optionally an org id. 517 518 New for RHEL 5. 519 520 All args are strings except other. 521 other is a dict with: 522 * org_id - optional. Must be a string that contains the number. If it's 523 not given, the default org is used. 524 525 If a profile is created it will return a dict with: 526 * system_id - the same xml as was previously returned 527 * channels - a list of the channels (as strings) the system was 528 subscribed to 529 * failed_channels - a list of channels (as strings) that 530 the system should have been subscribed to but couldn't be because they 531 don't have the necessary entitlements available. Can contain all the 532 channels including the base channel. 533 * system_slots - a list of the system slots used (as strings). 534 * failed_system_slots - a list of system slots (as strings) that they 535 should have used but couldn't because there weren't available 536 entitlements 537 * universal_activation_key - a list of universal default activation keys 538 (as strings) that were used while registering. 539 The call will try to use the highest system slot available. An entry will 540 be added to failed_system_slots for each one that is tried and fails and 541 system_slots will contain the one that succeeded if any. 542 543 If an error occurs which prevents the creation of a profile, a fault will 544 be raised: 545 TODO 546 """ 547 548 add_to_seclist(password) 549 550 log_debug(4, 'in new_system_user_pass') 551 552 # release_name wasn't required in the old call, so I'm just going to 553 # add it to other 554 other['release_name'] = os_release_name 555 556 # Authorize the username and password. Save the returned user object. 557 user = self.validate_system_user(username, password) 558 559 # This creates the rhnServer record and commits it to the db. 560 # It also assigns the system a base channel. 561 server_data = self.create_system(user, profile_name, 562 version, 563 arch, 564 other) 565 # Save the returned Server object 566 newserv = server_data['server'] 567 568 # Get the server db id. 569 server_id = newserv.getid() 570 571 # Get the server certificate file 572 system_certificate = newserv.system_id() 573 574 log_debug(4, 'Server id created as %s' % server_id) 575 576 failures = [] 577 unknowns = [] 578 579 # Build our return values. 580 attempted_channels = [] 581 successful_channels = [] 582 failed_channels = [] 583 584 actual_channels = rhnChannel.channels_for_server(server_id) 585 for channel in actual_channels: 586 successful_channels.append(channel['label']) 587 588 # If we don't have any successful channels, we know the base channel 589 # failed. 590 if len(successful_channels) == 0: 591 log_debug(4, 'System %s not subscribed to any channels' % server_id) 592 593 # Look up the base channel, and store it as a failure. 594 try: 595 base = rhnChannel.get_channel_for_release_arch( 596 version, 597 arch, newserv['org_id']) 598 failed_channels.append(base['label']) 599 # We want to swallow exceptions here as we are just generating data 600 # for the review screen in rhn_register. 601 except: 602 pass 603 604 # Store any of our child channel failures 605 failed_channels = failed_channels + failures 606 607 attempted_system_slots = ['enterprise_entitled'] 608 successful_system_slots = server_lib.check_entitlement(server_id) 609 successful_system_slots = list(successful_system_slots.keys()) 610 failed_system_slots = [] 611 612 # Check which entitlement level we got, starting with the highest. 613 i = 0 614 for slot in attempted_system_slots: 615 if slot in successful_system_slots: 616 break 617 i = i + 1 618 619 # Any entitlements we didn't have, we'll store as a failure. 620 failed_system_slots = attempted_system_slots[0:i] 621 622 universal_activation_key = [] 623 if rhnFlags.test("universal_registration_token"): 624 token = rhnFlags.get("universal_registration_token") 625 universal_activation_key = token.get_tokens() 626 627 return {'system_id': system_certificate, 628 'channels': successful_channels, 629 'failed_channels': failed_channels, 630 'failed_options': unknowns, 631 'system_slots': successful_system_slots, 632 'failed_system_slots': failed_system_slots, 633 'universal_activation_key': universal_activation_key 634 }
635 636 # Registers a new system to an org specified by an activation key. 637 # 638 # New for RHEL 5. 639 # 640 # See documentation for new_system_user_pass. This behaves the same way 641 # except it takes an activation key instead of username, password, and 642 # maybe org id. 643 # def new_system_activation_key(self, profile_name, os_release_name, 644 # os_release_version, arch, activation_key, other): 645 # return { 'system_id' : self.new_system({'profile_name' : profile_name, 646 # 'os_release' : os_release_version, 647 # 'release_name' : os_release_name, 648 # 'architecture' : arch, 649 # 'token' : activation_key, 650 # }), 651 # 'channels' : ['UNDER CONSTRUCTION'], 652 # 'failed_channels' : ['UNDER CONSTRUCTION'], 653 # 'system_slots' : ['UNDER CONSTRUCTION'], 654 # 'failed_system_slots' : ['UNDER CONSTRUCTION'], 655 # } 656
657 - def get_possible_orgs(self, username, password):
658 """ Gets all the orgs that a user belongs to. 659 In the OCS-future, users may belong to more than one org. 660 661 New for RHEL 5. 662 663 Returns a dict like: 664 { 665 'orgs': {'19': 'Engineering', '4009': 'Finance'}, 666 'default_org': '19' 667 } 668 'orgs' must have at least one pair and 'default_org' must exist and point 669 to something in 'orgs'. 670 671 TODO Pick fault number for this and document it here 672 Fault: 673 * Bad credentials 674 """ 675 user = rhnUser.auth_username_password(username, password) 676 677 # buzilla #229362, jslagle 678 # Clients currently are calling this method in hopes 679 # to one day support multi-org satellite. 680 # So, if we're running on a sat, return the default org 681 # for now. 682 org_id = user.contact["org_id"] 683 org_name = user.customer["name"] 684 orgs = {str(org_id): org_name} 685 default_org = str(org_id) 686 return {'orgs': orgs, 'default_org': default_org}
687
688 - def activate_registration_number(self, username, password, key, other):
689 """ Entitle a particular org using an entitlement number. 690 691 New for RHEL 5. 692 693 username, password, and key are strings. 694 other is a dict with: 695 * org_id - optional. If it's not given, the user's default org is used. 696 697 Returns a dict: 698 { 699 'status_code': <status code>, 700 'registration_number': 'EN for this system' 701 'channels' : channels, 702 'system_slots' : system_slots 703 } 704 'status_code' must be 0 for "we just activated the key" or 1 for "this 705 key was already activated." 706 'registration_number' will be the EN corresponding to this activation. If 707 we activated an EN we'll get the same thing back. If we activate an OEM 708 number (eg asset tag) and maybe a pre-rhel 5 subscription number, we'll 709 get back the EN that was generated from it. 710 'channels' is a dict of the channel susbscriptions that the key activated 711 the key/value pairs are label (string) / quantity (int) 712 'system_slots' is a dict of the system slots that the key activated 713 the key/value pairs are label (string) / quantity (int) 714 715 TODO Assign fault values and document them here 716 Faults: 717 * Invalid key (600) 718 * Bad credentials (?) - covers bad username and password, bad org id, and 719 user not in specified org 720 """ 721 # bugzilla# 236927, jslagle 722 # Clients are currently broken in that they try to activate 723 # installation numbers against a satellite. 724 # We can work around this by just raising the 'number is not 725 # entitling' fault. 726 raise rhnFault(602)
727
728 - def __findAssetTag(self, vendor, hardware_info):
729 """ Given some hardware information, we try to find the asset tag or 730 serial number. 731 732 See activate_hardware_info below for the structure of the 733 hardware_info 734 """ 735 736 if vendor in self.vendor_tags: 737 asset_value = "" 738 key = self.vendor_tags[vendor] 739 log_debug(5, "key: " + str(key)) 740 if key in hardware_info: 741 return hardware_info[key] 742 743 # nothing found 744 log_debug(5, "no tag found for vendor: " + str(vendor)) 745 return None
746
747 - def __transform_vendor_to_const(self, vendor):
748 if vendor in [None, "", "Not Available", "None", "N/A"]: 749 return None 750 751 if vendor.lower().startswith("dell"): 752 return "DELL" 753 else: 754 return None
755
756 - def activate_hardware_info(self, username, password, hardware_info, other):
757 """ 758 Given some hardware-based criteria per-vendor, try giving entitlements. 759 760 New for RHEL 5. 761 762 Mostly the same stuff as activate_registration_number. 763 hardware_info is a dict of stuff we get from hal from 764 Computer -> system.* and smbios.*. For example: 765 { 766 'system.product': '2687D8U ThinkPad T43', 767 'system.vendor': 'IBM', 768 'smbios.chassis.type': 'Notebook', 769 ... 770 } 771 """ 772 773 log_debug(5, username, hardware_info, other) 774 775 # bugzilla #236927, jslagle 776 # RHN clients are currently broken in that they always try to activate 777 # hardware info regardless of if they're pointed at satellite or hosted. 778 # To fix the satellite case, just raise the 'no entitlements tied to 779 # this hardware' fault. 780 raise rhnFault(601)
781
782 - def attempt_eol_mailing(self, user, server):
783 784 if not user: 785 raise Exception("user required to attempt eol mailing") 786 787 if "email" in user.info: 788 log_debug(4, "sending eol mail...") 789 body = EOL_EMAIL % {'server': server.server['name']} 790 headers = {} 791 headers['From'] = 'Red Hat Satellite <dev-null@rhn.redhat.com>' 792 headers['To'] = user.info['email'] 793 headers['Subject'] = 'End of Life RHN Channel Subscription' 794 rhnMail.send(headers, body)
795
796 - def send_serial(self, system_id, number, vendor=None):
797 """ 798 Receive a vendor serial number from the client and tag it to the server. 799 """ 800 log_debug(1, number, vendor) 801 # well, we don't do that anymore 802 return 0
803 804 # XXX: update this function to deal with the channels and stuff 805 # TODO: Is this useful? we think not. investigate and possibly replace 806 # with a NOOP.
807 - def upgrade_version(self, system_id, newver):
808 """ Upgrade a certificate's version to a different release. """ 809 log_debug(5, system_id, newver) 810 # we need to load the user because we will generate a new certificate 811 self.load_user = 1 812 server = self.auth_system(system_id) 813 newver = str(newver) 814 if not newver: 815 raise rhnFault(21, _("Invalid system release version requested")) 816 # log the entry 817 log_debug(1, server.getid(), newver) 818 ret = server.change_base_channel(newver) 819 server.save() 820 return server.system_id()
821
822 - def add_packages(self, system_id, packages):
823 """ Add one or more package to the server profile. """ 824 log_debug(5, system_id, packages) 825 if CFG.DISABLE_PACKAGES: 826 return 0 827 packages = self._normalize_packages(system_id, packages) 828 server = self.auth_system(system_id) 829 # log the entry 830 log_debug(1, server.getid(), "packages: %d" % len(packages)) 831 for package in packages: 832 server.add_package(package) 833 # XXX: check return code 834 server.save_packages() 835 return 0
836
837 - def delete_packages(self, system_id, packages):
838 """ Delete one or more packages from the server profile """ 839 log_debug(5, system_id, packages) 840 if CFG.DISABLE_PACKAGES: 841 return 0 842 packages = self._normalize_packages(system_id, packages) 843 server = self.auth_system(system_id) 844 # log the entry 845 log_debug(1, server.getid(), "packages: %d" % len(packages)) 846 for package in packages: 847 server.delete_package(package) 848 # XXX: check return code 849 server.save_packages() 850 return 0
851
852 - def delta_packages(self, system_id, packages):
853 log_debug(5, system_id, packages) 854 if CFG.DISABLE_PACKAGES: 855 return 0 856 if type(packages) != type({}): 857 log_error("Invalid argument type", type(packages)) 858 raise rhnFault(21) 859 added_packages = self._normalize_packages(system_id, packages.get('added'), allow_none=1) 860 removed_packages = self._normalize_packages(system_id, packages.get('deleted'), allow_none=1) 861 862 server = self.auth_system(system_id) 863 # log the entry 864 if added_packages is not None: 865 log_debug(1, self.server_id, "added: %d" % len(added_packages)) 866 if removed_packages is not None: 867 log_debug(1, self.server_id, "deleted: %d" % len(removed_packages)) 868 # Update the capabilities list 869 rhnCapability.update_client_capabilities(self.server_id) 870 for package in added_packages or []: 871 server.add_package(package) 872 for package in removed_packages or []: 873 server.delete_package(package) 874 server.save_packages() 875 return 0
876
877 - def virt_notify(self, system_id, actions):
878 """ This function fields virtualization-related notifications from the 879 client and delegates them out to the appropriate downstream handlers. 880 The 'actions' argument is formatted as follows: 881 882 actions = [ ( timestamp, event, target, properties ), ... ] 883 """ 884 log_debug(3, "Received virt notification:", system_id, actions) 885 886 # Authorize the client. 887 server = self.auth_system(system_id) 888 server_id = server.getid() 889 890 rhnVirtualization._virt_notify(server_id, actions) 891 892 rhnSQL.commit() 893 894 return 0
895
896 - def update_packages(self, system_id, packages):
897 """ This function will update the package list associated with a server 898 to be exactly the list of packages passed on the argument list 899 """ 900 log_debug(5, system_id, packages) 901 if CFG.DISABLE_PACKAGES: 902 return 0 903 packages = self._normalize_packages(system_id, packages) 904 905 server = self.auth_system(system_id) 906 # log the entry 907 log_debug(1, server.getid(), "packages: %d" % len(packages)) 908 server.dispose_packages() 909 for package in packages: 910 server.add_package(package) 911 server.save_packages() 912 return 0
913
914 - def _normalize_packages(self, system_id, packages, allow_none=0):
915 """ the function checks if list of packages is well formated 916 and also converts packages from old list of lists 917 (extended_profile >= 2) to new list of dicts (extended_profile = 2) 918 """ 919 920 if allow_none and packages is None: 921 return None 922 # we need to be paranoid about the format of the argument because 923 # if we accept wrong input then we might end up disposing in error 924 # of all packages registered here 925 if type(packages) != type([]): 926 log_error("Invalid argument type", type(packages)) 927 raise rhnFault(21) 928 929 # Update the capabilities list 930 server = self.auth_system(system_id) 931 rhnCapability.update_client_capabilities(self.server_id) 932 933 # old clients send packages as a list of arrays 934 # while new (capability packages.extended_profile >= {version: 2, value: 1}) 935 # use a list of dicts 936 client_caps = rhnCapability.get_client_capabilities() 937 package_is_dict = 0 938 packagesV2 = [] 939 if client_caps and 'packages.extended_profile' in client_caps: 940 cap_info = client_caps['packages.extended_profile'] 941 if cap_info and int(cap_info['version']) >= 2: 942 package_is_dict = 1 943 packagesV2 = packages 944 945 for package in packages: 946 if package_is_dict: 947 # extended_profile >= 2 948 if type(package) != type({}): 949 log_error("Invalid package spec for extended_profile >= 2", 950 type(package), "len = %d" % len(package)) 951 raise rhnFault(21) 952 else: 953 # extended_profile < 2 954 if (type(package) != type([]) or len(package) < 4): 955 log_error("Invalid package spec", type(package), 956 "len = %d" % len(package)) 957 raise rhnFault(21) 958 else: 959 p = {'name': package[0], 960 'version': package[1], 961 'release': package[2], 962 'epoch': package[3], 963 } 964 if len(package) > 4: 965 p['arch'] = package[4] 966 if len(package) > 5: 967 p['cookie'] = package[5] 968 packagesV2.append(p) 969 return packagesV2
970
971 - def __add_hw_profile_no_auth(self, server, hwlist):
972 """ Insert a new profile for the server, but do not authenticate """ 973 log_debug(1, server.getid(), "items: %d" % len(hwlist)) 974 for hardware in hwlist: 975 server.add_hardware(hardware) 976 # XXX: check return code 977 server.save_hardware()
978
979 - def add_hw_profile(self, system_id, hwlist):
980 """ Insert a new profile for the server """ 981 log_debug(5, system_id, hwlist) 982 server = self.auth_system(system_id) 983 self.__add_hw_profile_no_auth(server, hwlist) 984 # set primary interface to the one that is used to reach the server 985 sid = server.getid() 986 h = rhnSQL.prepare(""" 987 select * from rhnServerNetwork where server_id = :server_id 988 """) 989 h.execute(server_id=sid) 990 row = h.fetchone_dict() 991 if row: 992 ipaddr=row['ipaddr'] 993 ip6addr=row['ip6addr'] 994 primif=None 995 if ipaddr: 996 h = rhnSQL.prepare(""" 997 select interface_id from rhnServerNetAddress4 rsna4 left join rhnServerNetInterface rsni on rsna4.interface_id = rsni.id where address = :address and server_id = :server_id 998 """) 999 h.execute(address=ipaddr, server_id=sid) 1000 row = h.fetchone_dict() 1001 if row: 1002 primif=row['interface_id'] 1003 elif ip6addr: 1004 h = rhnSQL.prepare(""" 1005 select interface_id from rhnServerNetAddress6 rsna6 left join rhnServerNetInterface rsni on rsna6.interface_id = rsni.id where address = :address and server_id = :server_id 1006 """) 1007 h.execute(address=ip6addr, server_id=sid) 1008 row = h.fetchone_dict() 1009 if row: 1010 primif=row['interface_id'] 1011 if primif: 1012 h = rhnSQL.prepare(""" 1013 update rhnservernetinterface set is_primary = 'Y' where id = :id 1014 """) 1015 h.execute(id=primif) 1016 rhnSQL.commit() 1017 return 0
1018
1019 - def refresh_hw_profile(self, system_id, hwlist):
1020 """ Recreate the server HW profile """ 1021 log_debug(5, system_id, hwlist) 1022 server = self.auth_system(system_id) 1023 sid = server.getid() 1024 # clear out the existing list first 1025 # the only difference between add_hw_profile and refresh_hw_profile 1026 # make sure primary network interface does not get reset 1027 h = rhnSQL.prepare(""" 1028 select name from rhnservernetinterface where server_id = :server_id AND is_primary ='Y' 1029 """) 1030 h.execute(server_id=sid) 1031 row = h.fetchone_dict() 1032 server.delete_hardware() 1033 self.__add_hw_profile_no_auth(server, hwlist) 1034 if row: 1035 h = rhnSQL.prepare(""" 1036 update rhnservernetinterface set is_primary = 'Y' where server_id = :server_id AND name = :name 1037 """) 1038 h.execute(server_id=sid, name=row['name']) 1039 rhnSQL.commit() 1040 return 0
1041
1042 - def welcome_message(self, lang=None):
1043 """ returns string of welcome message """ 1044 log_debug(1, "lang: %s" % lang) 1045 if lang: 1046 cat.setlangs(lang) 1047 msg = _("Red Hat Satellite Welcome Message") 1048 # compress this one 1049 rhnFlags.set("compress_response", 1) 1050 return msg
1051
1052 - def privacy_statement(self, lang=None):
1053 """ returns string of privacy statement """ 1054 log_debug(1, "lang: %s" % lang) 1055 if lang: 1056 cat.setlangs(lang) 1057 msg = _("Red Hat Satellite Privacy Statement") 1058 # compress this one 1059 rhnFlags.set("compress_response", 1) 1060 return msg
1061
1062 - def register_product(self, system_id, product, oeminfo={}):
1063 """ register a product and record the data sent with the registration 1064 1065 bretm: hasn't registered a product or recorded anything since 2001, near 1066 as I can tell what it actually appears to be responsible for is 1067 protecting us against people registering systems from t7/t9 1068 countries 1069 1070 actual use of registration numbers has been moved into the 1071 server_class.__save stuff 1072 """ 1073 1074 log_debug(5, system_id, product, oeminfo) 1075 if type(product) != type({}): 1076 log_error("Invalid argument type", type(product)) 1077 raise rhnFault(21, _( 1078 "Expected a dictionary as a product argument")) 1079 log_debug(4, product) 1080 # As per bug 129996 using an activation key should not overwrite the 1081 # user's info. Also, the reg number stuff doesn't work anyway 1082 # Keep doing the authentication and then just bail out 1083 self.auth_system(system_id) 1084 return 0
1085
1086 - def update_contact_info(self, username, password, info={}):
1087 """ this API call is no longer used """ 1088 log_debug(5, username, info) 1089 username, password = str(username), str(password) 1090 user = rhnUser.search(username) 1091 if user is None: 1092 log_error("invalid username", username) 1093 raise rhnFault(2) 1094 1095 if not user.check_password(password): 1096 log_error("User password check failed", username) 1097 raise rhnFault(2) 1098 1099 return 0
1100
1101 - def update_transactions(self, system_id, timestamp, transactions_hash):
1102 """ Updates the RPM transactions """ 1103 log_debug(1) 1104 # Authenticate 1105 server = self.auth_system(system_id) 1106 # No op as of 20030923 1107 return 0
1108
1109 - def anonymous(self, release=None, arch=None):
1110 """ To reduce the number of tracebacks """ 1111 log_debug(1, "Disabled!", release, arch) 1112 raise rhnFault(28)
1113
1114 - def finish_message(self, system_id):
1115 """ Presents the client with a message to display 1116 Returns: 1117 (returnCode, titleText, messageText) 1118 titleText is the window's title, messageText is the message displayed in 1119 that window by the client 1120 1121 if returnCode is 1, the client 1122 will show the message in a window with the 1123 title of titleText, and allow the user to 1124 continue. 1125 if returnCode is -1, the client 1126 will show the message in a window with the 1127 title of titleText, and not allow the user 1128 to continue 1129 if returnCode is 0, no message 1130 screen will be shown. 1131 """ 1132 log_debug(1) 1133 # Authenticate 1134 self.auth_system(system_id) 1135 1136 return_code, text_title, text_message = \ 1137 self.server.fetch_registration_message() 1138 if return_code: 1139 return return_code, text_title, text_message 1140 1141 # If return_code is 0, check to see if we don't have a system-wide 1142 # message that we want to push 1143 return_code = int(CFG.REG_FINISH_MESSAGE_RETURN_CODE) 1144 if return_code == 0: 1145 # Nothing to display 1146 return (0, "", "") 1147 1148 # We need to send back something 1149 text_title = CFG.REG_FINISH_MESSAGE_TITLE or "" 1150 text_file = CFG.REG_FINISH_MESSAGE_TEXT_FILE 1151 try: 1152 text_message = open(text_file).read() 1153 except IOError: 1154 e = sys.exc_info()[1] 1155 log_error("reg_fishish_message_return_code is set, but file " 1156 "%s invalid: %s" % (text_file, e)) 1157 return (0, "", "") 1158 return (return_code, text_title, text_message)
1159 1160 _query_get_dispatchers = rhnSQL.Statement(""" 1161 select jabber_id from rhnPushDispatcher 1162 """) 1163
1164 - def _get_dispatchers(self):
1165 h = rhnSQL.prepare(self._query_get_dispatchers) 1166 h.execute() 1167 return [x['jabber_id'] for x in h.fetchall_dict() or []]
1168
1169 - def register_osad(self, system_id, args={}):
1170 log_debug(1) 1171 1172 # Authenticate 1173 server = self.auth_system(system_id) 1174 1175 jabber_server = CFG.JABBER_SERVER 1176 if not jabber_server: 1177 log_error("Jabber server not defined") 1178 return {} 1179 1180 server_timestamp, client_name, shared_key = \ 1181 server.register_push_client() 1182 1183 ret = args.copy() 1184 dispatchers = self._get_dispatchers() 1185 ret.update({ 1186 'client-name': client_name, 1187 'shared-key': shared_key, 1188 'server-timestamp': server_timestamp, 1189 'jabber-server': jabber_server, 1190 'dispatchers': dispatchers, 1191 }) 1192 return ret
1193
1194 - def register_osad_jid(self, system_id, args={}):
1195 log_debug(1) 1196 1197 # Authenticate 1198 server = self.auth_system(system_id) 1199 1200 if 'jabber-id' not in args: 1201 raise rhnFault(160, "No jabber-id specified", explain=0) 1202 1203 jid = args['jabber-id'] 1204 server.register_push_client_jid(jid) 1205 return {}
1206
1207 - def available_eus_channels(self, username, password, arch, 1208 version, release, other=None):
1209 ''' 1210 Given a server arch, redhat-release version, and redhat-release release 1211 returns the eligible channels for that system based on the entitlements 1212 in the org specified by username/password 1213 1214 Returns a dict of the available channels in the format: 1215 {'default_channel' : 'channel_label', 1216 'receiving_updates' : ['channel_label1', 'channel_label2'], 1217 'channels' : {'channel_label1' : 'channel_name1', 1218 'channel_lable2' : 'channel_name2'} 1219 } 1220 ''' 1221 1222 user = rhnUser.search(username) 1223 1224 if user is None: 1225 log_error("invalid username", username) 1226 raise rhnFault(2) 1227 1228 if not user.check_password(password): 1229 log_error("User password check failed", username) 1230 raise rhnFault(2) 1231 1232 server_arch = normalize_server_arch(arch) 1233 user_id = user.getid() 1234 org_id = user.contact['org_id'] 1235 1236 channels = rhnChannel.base_eus_channel_for_ver_rel_arch( 1237 version, release, server_arch, 1238 org_id, user_id) 1239 1240 log_debug(4, "EUS Channels are: %s" % str(channels)) 1241 1242 default_channel = '' 1243 eus_channels = {} 1244 receiving_updates = [] 1245 1246 if channels is not None: 1247 eus_channels = {} 1248 for channel in channels: 1249 eus_channels[channel['label']] = channel['name'] 1250 if channel['is_default'] == 'Y': 1251 default_channel = channel['label'] 1252 if channel['receiving_updates'] == 'Y': 1253 receiving_updates.append(channel['label']) 1254 1255 return {'default_channel': default_channel, 1256 'receiving_updates': receiving_updates, 1257 'channels': eus_channels}
1258
1259 - def remaining_subscriptions(self, username, password, arch, release):
1260 """ This is an obsoleted API call used in old RHEL5 clients to determine 1261 if they should show the "activate a subscription" page. 1262 """ 1263 return 1
1264
1265 - def update_systemid(self, system_id):
1266 """ update_systemid: update client server and certificate 1267 In case the calling system is not using a certificate with a SHA-256 1268 checksum, update its secret and issue it a new client certificate. 1269 """ 1270 server = self.auth_system(system_id) 1271 cert = Certificate() 1272 cert.reload(system_id) 1273 1274 # System already uses certificate with a SHA-256 checksum, 1275 # we'll just return current systemid back 1276 if len(server.server['secret']) == 64: 1277 return cert.certificate() 1278 else: # MD5 checksum 1279 server.set_arch(cert['architecture']) 1280 server.user = rhnUser.User("", "") 1281 server.user.reload(server.server['creator_id']) 1282 server.gen_secret() # create new SHA-256 server secret 1283 server.save() 1284 return server.system_id()
1285 1286
1287 -def _faultValueString(value, name):
1288 return _("Invalid value '%s' for %s (%s)") % ( 1289 str(value), str(name), type(value))
1290 1291 1292 EOL_EMAIL = """ 1293 Dear Red Hat Satellite User, 1294 1295 This email has been autogenerated to alert you that you recently subscribed the 1296 following system to an RHN channel related to a Red Hat Linux distribution that 1297 has reached End of Life: 1298 1299 %(server)s 1300 1301 Distributions that have reached End of Life are no longer receiving maintenance 1302 support (errata), which may make them unsuitable to your needs. 1303 1304 For more information regarding Red Hat Linux support, please go to: 1305 1306 http://www.redhat.com/apps/support/errata/ 1307 1308 If you are interested in a distribution of Red Hat with a longer release 1309 lifecycle, 5+ year maintenance period, ISV support, and enhanced functionality, 1310 check out Red Hat Enterprise Linux at: 1311 1312 http://www.redhat.com/software/rhel/ 1313 1314 1315 Thank you for using Red Hat Satellite. 1316 """ 1317 1318 1319 #------------------------------------------------------------------------------- 1320