def test_search_for_base_class_with_gaps(self): mapper = ExceptionMapper() expected_message = "RuntimeError message" mapper.message_map[RuntimeError] = (expected_message, mapper.format_default) err = MyRuntimeError("Logged Only") self.assertEquals(expected_message, mapper.get_message(err))
def test_single_mapped_exception(self): expected_message = "Single Exception Message" mapper = ExceptionMapper() mapper.message_map[RuntimeError] = (expected_message, mapper.format_default) err = RuntimeError("Testing") self.assertEqual(expected_message, mapper.get_message(err))
def test_can_support_old_style_classes(self): expected_message = "Old style class" mapper = ExceptionMapper() mapper.message_map[OldStyleClass] = (expected_message, mapper.format_default) err = OldStyleClass() self.assertEquals(expected_message, mapper.get_message(err))
def test_single_mapped_exception(self): expected_message = "Single Exception Message" mapper = ExceptionMapper() mapper.message_map[RuntimeError] = (expected_message, mapper.format_default) err = RuntimeError("Testing") self.assertEquals(expected_message, mapper.get_message(err))
def test_subclass_mapped_by_base_class(self): expected_message = "Single Exception Message" mapper = ExceptionMapper() mapper.message_map[RuntimeError] = (expected_message, mapper.format_default) err = MyRuntimeError("Testing base class") self.assertEquals(expected_message, mapper.get_message(err))
def test_search_for_base_class_with_gaps(self): mapper = ExceptionMapper() expected_message = "RuntimeError message" mapper.message_map[RuntimeError] = (expected_message, mapper.format_default) err = MyRuntimeError("Logged Only") self.assertEqual(expected_message, mapper.get_message(err))
def test_can_support_old_style_classes(self): expected_message = "Old style class" mapper = ExceptionMapper() mapper.message_map[OldStyleClass] = (expected_message, mapper.format_default) err = OldStyleClass() self.assertEqual(expected_message, mapper.get_message(err))
def test_subclass_mapped_by_base_class(self): expected_message = "Single Exception Message" mapper = ExceptionMapper() mapper.message_map[RuntimeError] = (expected_message, mapper.format_default) err = MyRuntimeError("Testing base class") self.assertEqual(expected_message, mapper.get_message(err))
def test_restlib_exception_uses_custom_message(self): expected_message = "Expected MESSAGE" mapper = ExceptionMapper() err = RestlibException(404, expected_message) self.assertEqual("HTTP error code 404: %s" % expected_message, mapper.get_message(err))
def test_subclass_preferred_over_base_class(self): expected_message = "Subclass Exception Message" mapper = ExceptionMapper() mapper.message_map[RuntimeError] = ("RuntimeError message", mapper.format_default) mapper.message_map[MyRuntimeErrorBase] = ("MyRuntimeErrorBase message", mapper.format_default) mapper.message_map[MyRuntimeError] = (expected_message, mapper.format_default) err = MyRuntimeError("Logged Only") self.assertEqual(expected_message, mapper.get_message(err))
def test_can_map_middle_sub_class(self): expected_message = "MyRuntimeErrorBase message" mapper = ExceptionMapper() mapper.message_map[RuntimeError] = ("RuntimeError message", mapper.format_default) mapper.message_map[MyRuntimeErrorBase] = (expected_message, mapper.format_default) mapper.message_map[MyRuntimeError] = ("MyRuntimeError message", mapper.format_default) err = MyRuntimeErrorBase("Logged Only") self.assertEqual(expected_message, mapper.get_message(err))
def _do_command(self): self._validate_options() try: # If we have a username/password, we're going to use that, otherwise # we'll use the identity certificate. We already know one or the other # exists: if self.options.token: self.cp = self.cp_provider.get_keycloak_auth_cp( self.options.token) elif self.options.username and self.options.password: self.cp_provider.set_user_pass(self.username, self.password) self.cp = self.cp_provider.get_basic_auth_cp() elif not self.is_registered() and self.options.show: pass else: # get an UEP as consumer self.cp = self.cp_provider.get_consumer_auth_cp() except connection.RestlibException as re: log.exception(re) log.error( "Error: Unable to retrieve service levels: {re}".format(re=re)) mapped_message: str = ExceptionMapper().get_message(re) system_exit(os.EX_SOFTWARE, mapped_message) except Exception as e: handle_exception(_("Error: Unable to retrieve service levels."), e) else: try: if self.options.unset: self.unset() elif self.options.set is not None: self.set() elif self.options.list: self.list_service_levels() elif self.options.show: self.show() else: self.show() except UnauthorizedException as uex: handle_exception(_(str(uex)), uex) except connection.GoneException as ge: raise ge except connection.RestlibException as re_err: log.exception(re_err) log.error( "Error: Unable to retrieve service levels: {err}".format( err=re_err)) mapped_message: str = ExceptionMapper().get_message(re_err) system_exit(os.EX_SOFTWARE, mapped_message) except ProxyException: system_exit( os.EX_UNAVAILABLE, _("Proxy connection failed, please check your settings."), )
def handle_gui_exception(e, msg, parent, format_msg=True, log_msg=None): """ Handles an exception for the gui by logging the stack trace and displaying a user-friendly internationalized message. e = either an exception or a tuple returned from sys.exc_info() msg = User friendly message to display in GUI. parent = Parent window where the error originates. log_msg = Optional message to be logged in addition to stack trace. format_msg = if true, string sub the exception error in the msg """ if isinstance(e, tuple): if not log_msg: log_msg = str(e[1]) log.error(log_msg, exc_info=e) # Get the class instance of the exception e = e[1] else: if log_msg: log.error(log_msg) log.exception(e) exception_mapper = ExceptionMapper() mapped_message = exception_mapper.get_message(e) if mapped_message: if isinstance(e, connection.RestlibException): # If this exception's code is in the 200 range (such as 202 ACCEPTED) # we're going to ignore the message we were given and just display # the message from the server as an info dialog. (not an error) if 200 < int(e.code) < 300: message = linkify(mapped_message) messageWindow.InfoDialog(messageWindow.wrap_text(message)) else: try: if format_msg: message = msg % linkify(mapped_message) else: message = linkify(mapped_message) except Exception: message = msg show_error_window(message, parent=parent) else: show_error_window(mapped_message, parent) else: #catch-all, try to interpolate and if it doesn't work out, just display the message try: interpolated_str = msg % e show_error_window(interpolated_str, parent=parent) except Exception: show_error_window(msg, parent=parent)
def handle_gui_exception(e, msg, parent, format_msg=True, log_msg=None): """ Handles an exception for the gui by logging the stack trace and displaying a user-friendly internationalized message. e = either an exception or a tuple returned from sys.exc_info() msg = User friendly message to display in GUI. parent = Parent window where the error originates. log_msg = Optional message to be logged in addition to stack trace. format_msg = if true, string sub the exception error in the msg """ if isinstance(e, tuple): if not log_msg: log_msg = str(e[1]) log.error(log_msg, exc_info=e) # Get the class instance of the exception e = e[1] else: if log_msg: log.error(log_msg) log.exception(e) exception_mapper = ExceptionMapper() mapped_message = exception_mapper.get_message(e) if mapped_message: if isinstance(e, connection.RestlibException): # If this exception's code is in the 200 range (such as 202 ACCEPTED) # we're going to ignore the message we were given and just display # the message from the server as an info dialog. (not an error) if 200 < int(e.code) < 300: message = linkify(mapped_message) messageWindow.InfoDialog(messageWindow.wrap_text(message)) else: try: if format_msg: message = msg % linkify(mapped_message) else: message = linkify(mapped_message) except Exception: message = msg show_error_window(message, parent=parent) else: show_error_window(mapped_message, parent) else: #catch-all, try to interpolate and if it doesn't work out, just display the message try: interpolated_str = msg % e show_error_window(interpolated_str, parent=parent) except Exception: show_error_window(msg, parent=parent)
def format_exception(e, msg, format_msg=True, log_msg=None): if isinstance(e, tuple): log.error(log_msg, exc_info=e) # Get the class instance of the exception e = e[1] message = None exception_mapper = ExceptionMapper() mapped_message = exception_mapper.get_message(e) if mapped_message: message = format_mapped_message(e, msg, mapped_message, format_msg=format_msg) else: message = format_interpolated_message(e, msg, mapped_message, format_msg=format_msg) return message
def format_exception(e, msg, format_msg=True, log_msg=None): if isinstance(e, tuple): log.error(log_msg, exc_info=e) # Get the class instance of the exception e = e[1] message = None exception_mapper = ExceptionMapper() mapped_message = exception_mapper.get_message(e) if mapped_message: message = format_mapped_message(e, msg, mapped_message, format_msg=format_msg) else: message = format_interpolated_message(e, msg, mapped_message, format_msg=format_msg) return message
def _get_valid_fields(self): """ Try to get valid fields from server :return: Dictionary with valid fields """ valid_fields = {} if self.is_registered(): # When system is registered, then try to get valid fields from cache file try: valid_fields = get_syspurpose_valid_fields(uep=self.cp, identity=self.identity) except ProxyException: system_exit(os.EX_UNAVAILABLE, _("Proxy connection failed, please check your settings.")) elif self.options.username and self.options.password and self.cp is not None: # Try to get current organization key. It is property of OrgCommand. # Every Syspurpose command has to be subclass of OrgCommand too # must have used credentials in command if not registered to proceed try: org_key = self.org server_response = self.cp.getOwnerSyspurposeValidFields(org_key) except connection.RestlibException as rest_err: log.warning( "Unable to get list of valid fields using REST API: {rest_err}".format(rest_err=rest_err) ) mapped_message: str = ExceptionMapper().get_message(rest_err) system_exit(os.EX_SOFTWARE, mapped_message) except ProxyException: system_exit(os.EX_UNAVAILABLE, _("Proxy connection failed, please check your settings.")) else: if "systemPurposeAttributes" in server_response: server_response = post_process_received_data(server_response) valid_fields = server_response["systemPurposeAttributes"] return valid_fields
def _do_command(self): self.assert_should_be_registered() try: # Also remove the content access mode cache to be sure we display # SCA or regular mode correctly content_access_mode = inj.require(inj.CONTENT_ACCESS_MODE_CACHE) if content_access_mode.exists(): content_access_mode.delete_cache() if self.options.force is True: # get current consumer identity consumer_identity = inj.require(inj.IDENTITY) # Force a regen of the entitlement certs for this consumer if not self.cp.regenEntitlementCertificates(consumer_identity.uuid, True): log.debug( "Warning: Unable to refresh entitlement certificates; service likely unavailable" ) self.entcertlib.update() log.debug("Refreshed local data") print(_("All local data refreshed")) except connection.RestlibException as re: log.error(re) mapped_message: str = ExceptionMapper().get_message(re) system_exit(os.EX_SOFTWARE, mapped_message) except Exception as e: handle_exception( _("Unable to perform refresh due to the following exception: {e}").format(e=e), e ) self._request_validity_check()
def _do_command(self): self._validate_options() facts = inj.require(inj.FACTS) if self.options.list: facts_dict = facts.get_facts() facts_keys = sorted(facts_dict.keys()) for key in facts_keys: value = facts_dict[key] if str(value).strip() == "": value = _("Unknown") print("{key}: {value}".format(key=key, value=value)) if self.options.update: identity = inj.require(inj.IDENTITY) try: facts.update_check(self.cp, identity.uuid, force=True) except connection.GoneException as ge: raise ge except connection.RestlibException as re: log.exception(re) mapped_message: str = ExceptionMapper().get_message(re) system_exit(os.EX_SOFTWARE, mapped_message) log.debug("Succesfully updated the system facts.") print(_("Successfully updated the system facts."))
def _do_auto_attach(self, consumer): """ Try to do auto-attach, when it was requested using --auto-attach CLI option :return: None """ # Do not try to do auto-attach, when simple content access mode is used # Only print info message to stdout if is_simple_content_access(uep=self.cp, identity=self.identity): self._print_ignore_auto_attach_mesage() return if "serviceLevel" not in consumer and self.options.service_level: system_exit( os.EX_UNAVAILABLE, _( "Error: The --servicelevel option is not supported " "by the server. Did not complete your request." ), ) try: # We don't call auto_attach with self.option.service_level, because it has been already # set during service.register() call attach.AttachService(self.cp).attach_auto(service_level=None) except connection.RestlibException as rest_lib_err: mapped_message: str = ExceptionMapper().get_message(rest_lib_err) print_error(mapped_message) except Exception: log.exception("Auto-attach failed") raise
def _do_command(self): self._validate_options() supported_resources = get_supported_resources() if "environments" not in supported_resources: system_exit(os.EX_UNAVAILABLE, _("Error: Server does not support environments.")) try: if self.options.token: self.cp = self.cp_provider.get_keycloak_auth_cp( self.options.token) else: if not self.options.enabled: if self.options.username is None or self.options.password is None: print(_("This operation requires user credentials")) self.cp_provider.set_user_pass(self.username, self.password) self.cp = self.cp_provider.get_basic_auth_cp() self.identity = require(IDENTITY) if self.options.set: self._set_environments() else: self._list_environments() except connection.RestlibException as re: log.exception(re) log.error( "Error: Unable to retrieve environment list from server: {re}". format(re=re)) mapped_message: str = ExceptionMapper().get_message(re) system_exit(os.EX_SOFTWARE, mapped_message) except Exception as e: handle_exception( _("Error: Unable to retrieve environment list from server"), e)
def _do_command(self): self._validate_options() self.cp = None try: # If we have a username/password, we're going to use that, otherwise # we'll use the identity certificate. We already know one or the other # exists: if self.options.token: try: self.cp = self.cp_provider.get_keycloak_auth_cp(self.options.token) except Exception as err: log.error( 'unable to connect to candlepin server using token: "{token}", err: {err}'.format( token=self.options.token, err=err ) ) print(_("Unable to connect to server using token")) elif self.options.username and self.options.password: self.cp_provider.set_user_pass(self.options.username, self.options.password) self.cp = self.cp_provider.get_basic_auth_cp() else: # get an UEP as consumer if self.is_registered(): self.cp = self.cp_provider.get_consumer_auth_cp() except connection.RestlibException as err: log.exception(err) if getattr(self.options, "list", None): log.error( "Error: Unable to retrieve {attr} from server: {err}".format(attr=self.attr, err=err) ) mapped_message: str = ExceptionMapper().get_message(err) system_exit(os.EX_SOFTWARE, mapped_message) else: log.debug( "Error: Unable to retrieve {attr} from server: {err}".format(attr=self.attr, err=err) ) except Exception as err: log.debug("Error: Unable to retrieve {attr} from server: {err}".format(attr=self.attr, err=err)) self.store = SyncedStore(uep=self.cp, consumer_uuid=self.identity.uuid) if getattr(self.options, "unset", None): self.unset() elif getattr(self.options, "set", None): self.set() elif hasattr(self.options, "to_add") and len(self.options.to_add) > 0: self.add() elif hasattr(self.options, "to_remove") and len(self.options.to_remove) > 0: self.remove() elif getattr(self.options, "list", None): self.list() elif getattr(self.options, "show", None): self.show() else: self.show()
def handle_exception(msg, ex): # On Python 2.4 and earlier, sys.exit triggers a SystemExit exception, # which can land us into this block of code. We do not want to handle # this or print any messages as the caller would already have done so, # so just re-throw and let Python have at it. if isinstance(ex, SystemExit): raise ex # GoneException will be handled uniformly for every command except unregister. if isinstance(ex, connection.GoneException): raise ex log.error(msg) log.exception(ex) exception_mapper = ExceptionMapper() mapped_message: str = exception_mapper.get_message(ex) system_exit(os.EX_SOFTWARE, mapped_message)
def test_subclass_preferred_over_base_class(self): expected_message = "Subclass Exception Message" mapper = ExceptionMapper() mapper.message_map[RuntimeError] = ("RuntimeError message", mapper.format_default) mapper.message_map[MyRuntimeErrorBase] = ("MyRuntimeErrorBase message", mapper.format_default) mapper.message_map[MyRuntimeError] = (expected_message, mapper.format_default) err = MyRuntimeError("Logged Only") self.assertEquals(expected_message, mapper.get_message(err))
def test_can_map_middle_sub_class(self): expected_message = "MyRuntimeErrorBase message" mapper = ExceptionMapper() mapper.message_map[RuntimeError] = ("RuntimeError message", mapper.format_default) mapper.message_map[MyRuntimeErrorBase] = (expected_message, mapper.format_default) mapper.message_map[MyRuntimeError] = ("MyRuntimeError message", mapper.format_default) err = MyRuntimeErrorBase("Logged Only") self.assertEquals(expected_message, mapper.get_message(err))
def list_service_levels(self): if self.is_registered(): org_key = self.cp.getOwner(self.identity.uuid)["key"] else: org_key = self.org try: slas = self.cp.getServiceLevelList(org_key) if len(slas): print("+-------------------------------------------+") print(" {label}".format( label=_("Available Service Levels"))) print("+-------------------------------------------+") for sla in slas: print(sla) else: print( _('There are no available values for the system purpose "{syspurpose_attr}" ' "from the available subscriptions in this " "organization.").format(syspurpose_attr="service_level")) except UnauthorizedException as e: raise e except connection.RemoteServerException: system_exit( os.EX_UNAVAILABLE, _("Error: The service-level command is not supported by the server." )) except connection.GoneException as ge: raise ge except connection.RestlibException as e: if e.code == 404 and e.msg.find("/servicelevels") > 0: system_exit( os.EX_UNAVAILABLE, _("Error: The service-level command is not supported by the server." )) elif e.code == 404: mapped_message: str = ExceptionMapper().get_message(e) system_exit(os.EX_DATAERR, mapped_message) else: raise e
def _do_command(self): try: # get a UEP if self.options.token: self.cp = self.cp_provider.get_keycloak_auth_cp( self.options.token) else: self.cp_provider.set_user_pass(self.username, self.password) self.cp = self.cp_provider.get_basic_auth_cp() owners = self.cp.getOwnerList(self.username) log.debug("Successfully retrieved org list from server.") if len(owners): print("+-------------------------------------------+") print(" {name} {label}".format( name=self.username, label=_("Organizations"))) print("+-------------------------------------------+") print("") for owner in owners: print( columnize(ORG_LIST, echo_columnize_callback, owner["displayName"], owner["key"]) + "\n") else: print( _("{username} cannot register with any organizations."). format(username=self.username)) except connection.RestlibException as re: log.exception(re) log.error( "Error: Unable to retrieve org list from server: {re}".format( re=re)) mapped_message: str = ExceptionMapper().get_message(re) system_exit(os.EX_SOFTWARE, mapped_message) except Exception as e: handle_exception( _("Error: Unable to retrieve org list from server"), e)
def _do_command(self): """ Executes the command. """ self._validate_options() return_code = 0 if self.is_registered(): ent_service = entitlement.EntitlementService(self.cp) try: if self.options.all: total = ent_service.remove_all_entitlements() # total will be None on older Candlepins that don't # support returning the number of subscriptions unsubscribed from if total is None: print(_("All subscriptions have been removed at the server.")) else: count = total["deletedRecords"] print( ungettext( "%s subscription removed at the server.", "%s subscriptions removed at the server.", count, ) % count ) else: # Try to remove subscriptions defined by pool IDs first (remove --pool=...) if self.options.pool_ids: ( removed_pools, unremoved_pools, removed_serials, ) = ent_service.remove_entilements_by_pool_ids(self.options.pool_ids) if not removed_pools: return_code = 1 self._print_unbind_ids_result(removed_pools, unremoved_pools, "pools") else: removed_serials = [] # Then try to remove subscriptions defined by serials (remove --serial=...) unremoved_serials = [] if self.options.serials: serials = unique_list_items(self.options.serials) # Don't remove serials already removed by a pool serials_to_remove = [serial for serial in serials if serial not in removed_serials] _removed_serials, unremoved_serials = ent_service.remove_entitlements_by_serials( serials_to_remove ) removed_serials.extend(_removed_serials) if not _removed_serials: return_code = 1 # Print final result of removing pools self._print_unbind_ids_result(removed_serials, unremoved_serials, "serial numbers") except connection.GoneException as ge: raise ge except connection.RestlibException as err: log.error(err) mapped_message: str = ExceptionMapper().get_message(err) system_exit(os.EX_SOFTWARE, mapped_message) except Exception as e: handle_exception( _("Unable to perform remove due to the following exception: {e}").format(e=e), e ) else: # We never got registered, just remove the cert try: if self.options.all: total = 0 for ent in self.entitlement_dir.list(): ent.delete() total = total + 1 print(_("{total} subscriptions removed from this system.").format(total=total)) else: if self.options.serials or self.options.pool_ids: serials = self.options.serials or [] pool_ids = self.options.pool_ids or [] count = 0 for ent in self.entitlement_dir.list(): ent_pool_id = str(getattr(ent.pool, "id", None) or "") if str(ent.serial) in serials or ent_pool_id in pool_ids: ent.delete() print( _( "Subscription with serial number {serial} removed from this system" ).format(serial=str(ent.serial)) ) count = count + 1 if count == 0: return_code = 1 except Exception as e: handle_exception( _("Unable to perform remove due to the following exception: {e}").format(e=e), e ) # it is okay to call this no matter what happens above, # it's just a notification to perform a check self._request_validity_check() return return_code
def test_returns_none_when_no_mapped_exception_present(self): mapper = ExceptionMapper() self.assertEqual(None, mapper.get_message(RuntimeError()))
def test_return_str_when_no_mapped_exception(self): expected_message = "Expected message" mapper = ExceptionMapper() err = RuntimeError(expected_message) self.assertEqual(expected_message, mapper.get_message(err))
def _do_command(self): # get current consumer identity identity = inj.require(inj.IDENTITY) # check for Classic before doing anything else if ClassicCheck().is_registered_with_classic(): if identity.is_valid(): print( _("server type: {type}").format( type=get_branding().REGISTERED_TO_BOTH_SUMMARY)) else: # no need to continue if user is only registered to Classic print( _("server type: {type}").format( type=get_branding().REGISTERED_TO_OTHER_SUMMARY)) return try: self._validate_options() consumerid = self.identity.uuid consumer_name = self.identity.name if not self.options.regenerate: owner = get_current_owner(self.cp, self.identity) ownername = owner["displayName"] ownerid = owner["key"] print( _("system identity: {consumerid}").format( consumerid=consumerid)) print( _("name: {consumer_name}").format( consumer_name=consumer_name)) print(_("org name: {ownername}").format(ownername=ownername)) print(_("org ID: {ownerid}").format(ownerid=ownerid)) supported_resources = get_supported_resources( self.cp, self.identity) if "environments" in supported_resources: consumer = self.cp.getConsumer(consumerid) evn_key = "environments" if self.cp.has_capability( MULTI_ENV) else "environment" environments = consumer[evn_key] if environments: if evn_key == "environment": environment_names = environments["name"] else: environment_names = ",".join([ environment["name"] for environment in environments ]) else: environment_names = _("None") print( ungettext( "environment name: {environment_name}", "environment names: {environment_name}", len(environment_names.split(",")), ).format(environment_name=environment_names)) else: if self.options.force: # get an UEP with basic auth or keycloak auth if self.options.token: self.cp = self.cp_provider.get_keycloak_auth_cp( self.options.token) else: self.cp_provider.set_user_pass(self.username, self.password) self.cp = self.cp_provider.get_basic_auth_cp() consumer = self.cp.regenIdCertificate(consumerid) managerlib.persist_consumer_cert(consumer) # do this in persist_consumer_cert? or some other # high level, "I just registered" thing self.identity.reload() print(_("Identity certificate has been regenerated.")) log.debug("Successfully generated a new identity from server.") except connection.GoneException as ge: # Gone exception is caught in CliCommand and a consistent message # is printed there for all commands raise ge except connection.RestlibException as re: log.exception(re) log.error( "Error: Unable to generate a new identity for the system: {re}" .format(re=re)) mapped_message: str = ExceptionMapper().get_message(re) system_exit(os.EX_SOFTWARE, mapped_message) except Exception as e: handle_exception( _("Error: Unable to generate a new identity for the system"), e)
def test_returns_none_when_no_mapped_exception_present(self): mapper = ExceptionMapper() self.assertEqual(None, mapper.get_message(RuntimeError()))
def test_restlib_exception_uses_custom_message(self): expected_message = "Expected MESSAGE" mapper = ExceptionMapper() err = RestlibException(404, expected_message) self.assertEqual("HTTP error code 404: %s" % expected_message, mapper.get_message(err))
def _do_command(self): """ Executes the command. """ self.log_client_version() # Always warn the user if registered to old RHN/Spacewalk if ClassicCheck().is_registered_with_classic(): print(get_branding().REGISTERED_TO_OTHER_WARNING) self._validate_options() # gather installed products info self.installed_mgr = inj.require(inj.INSTALLED_PRODUCTS_MANAGER) previously_registered = False if self.is_registered() and self.options.force: previously_registered = True # First let's try to un-register previous consumer; if this fails # we'll let the error bubble up, so that we don't blindly re-register. # managerlib.unregister handles the special case that the consumer has already been removed. old_uuid = self.identity.uuid print( _("Unregistering from: {hostname}:{port}{prefix}").format( hostname=conf["server"]["hostname"], port=conf["server"]["port"], prefix=conf["server"]["prefix"], ) ) try: unregister.UnregisterService(self.cp).unregister() self.entitlement_dir.__init__() self.product_dir.__init__() log.info("--force specified, unregistered old consumer: {old_uuid}".format(old_uuid=old_uuid)) print(_("The system with UUID {old_uuid} has been unregistered").format(old_uuid=old_uuid)) except ssl.SSLError as e: # since the user can override serverurl for register, a common use case is to try to switch servers # using register --force... However, this normally cannot successfully unregister since the servers # are different. handle_exception("Unregister failed: {e}".format(e=e), e) except Exception as e: handle_exception("Unregister failed", e) self.cp_provider.clean() if previously_registered: print(_("All local data removed")) # Proceed with new registration: try: if self.options.token: admin_cp = self.cp_provider.get_keycloak_auth_cp(self.options.token) elif not self.options.activation_keys: hostname = conf["server"]["hostname"] if ":" in hostname: normalized_hostname = "[{hostname}]".format(hostname=hostname) else: normalized_hostname = hostname print( _("Registering to: {hostname}:{port}{prefix}").format( hostname=normalized_hostname, port=conf["server"]["port"], prefix=conf["server"]["prefix"], ) ) self.cp_provider.set_user_pass(self.username, self.password) admin_cp = self.cp_provider.get_basic_auth_cp() else: admin_cp = self.cp_provider.get_no_auth_cp() # This is blocking and not async, which aside from blocking here, also # means things like following name owner changes gets weird. service = register.RegisterService(admin_cp) if self.options.consumerid: log.debug("Registering as existing consumer: {id}".format(id=self.options.consumerid)) consumer = service.register(None, consumerid=self.options.consumerid) else: if self.options.org: owner_key = self.options.org else: owner_key = service.determine_owner_key( username=self.username, get_owner_cb=self._get_owner_cb, no_owner_cb=self._no_owner_cb ) environment_ids = self._process_environments(admin_cp, owner_key) consumer = service.register( owner_key, activation_keys=self.options.activation_keys, environments=environment_ids, force=self.options.force, name=self.options.consumername, type=self.options.consumertype, service_level=self.options.service_level, ) except (connection.RestlibException, exceptions.ServiceError) as re: log.exception(re) mapped_message: str = ExceptionMapper().get_message(re) system_exit(os.EX_SOFTWARE, mapped_message) except Exception as e: handle_exception(_("Error during registration: {e}").format(e=e), e) else: consumer_info = identity.ConsumerIdentity(consumer["idCert"]["key"], consumer["idCert"]["cert"]) print(_("The system has been registered with ID: {id}").format(id=consumer_info.getConsumerId())) print(_("The registered system name is: {name}").format(name=consumer_info.getConsumerName())) if self.options.service_level: print(_("Service level set to: {level}").format(level=self.options.service_level)) # We have new credentials, restart virt-who restart_virt_who() # get a new UEP as the consumer self.cp = self.cp_provider.get_consumer_auth_cp() # log the version of the server we registered to self.log_server_version() facts = inj.require(inj.FACTS) # FIXME: can these cases be replaced with invoking # FactsLib (or a FactsManager?) # Must update facts to clear out the old ones: if self.options.consumerid: log.debug("Updating facts") # # FIXME: Need a ConsumerFacts.sync or update or something # TODO: We register, with facts, then update facts again...? # Are we trying to sync potential new or dynamic facts? facts.update_check(self.cp, consumer["uuid"], force=True) # Facts and installed products went out with the registration request, # manually write caches to disk: # facts service job now(soon) facts.write_cache() self.installed_mgr.update_check(self.cp, consumer["uuid"]) if self.options.release: # TODO: grab the list of valid options, and check self.cp.updateConsumer(consumer["uuid"], release=self.options.release) if self.autoattach: self._do_auto_attach(consumer) if ( self.options.consumerid or self.options.activation_keys or self.autoattach or self.cp.has_capability(CONTENT_ACCESS_CERT_CAPABILITY) ): log.debug("System registered, updating entitlements if needed") # update certs, repos, and caches. # FIXME: aside from the overhead, should this be cert_action_client.update? self.entcertlib.update() try: profile_mgr = inj.require(inj.PROFILE_MANAGER) # 767265: always force an upload of the packages when registering profile_mgr.update_check(self.cp, consumer["uuid"], True) except RemoteServerException as err: # When it is not possible to upload profile ATM, then print only error about this # to rhsm.log. The rhsmcertd will try to upload it next time. log.error("Unable to upload profile: {err}".format(err=str(err))) subscribed = 0 if self.options.activation_keys or self.autoattach: # update with latest cert info self.sorter = inj.require(inj.CERT_SORTER) self.sorter.force_cert_check() subscribed = show_autosubscribe_output(self.cp, self.identity) self._request_validity_check() return subscribed
def _do_command(self): self._validate_options() # Abort if not registered self.assert_should_be_registered() supported_resources = get_supported_resources() if "content_overrides" not in supported_resources: system_exit( os.EX_UNAVAILABLE, _("Error: The 'repo-override' command is not supported by the server." )) # update entitlement certificates if necessary. If we do have new entitlements # CertLib.update() will call RepoActionInvoker.update(). self.entcertlib.update() # make sure the EntitlementDirectory singleton is refreshed self._request_validity_check() overrides = Overrides() if not manage_repos_enabled(): print(_("Repositories disabled by configuration.")) if self.options.list: results = overrides.get_overrides(self.identity.uuid) if results: self._list(results, self.options.repos) else: print( _("This system does not have any content overrides applied to it." )) return if self.options.additions: repo_ids = [ repo.id for repo in overrides.repo_lib.get_repos(apply_overrides=False) ] to_add = [ Override(repo, name, value) for repo in self.options.repos for name, value in list(self.options.additions.items()) ] try: results = overrides.add_overrides(self.identity.uuid, to_add) except connection.RestlibException as ex: if ex.code == 400: # blocklisted overrides specified. # Print message and return a less severe code. mapped_message: str = ExceptionMapper().get_message(ex) system_exit(1, mapped_message) else: raise ex # Print out warning messages if the specified repo does not exist in the repo file. for repo in self.options.repos: if repo not in repo_ids: print( _("Repository '{repo}' does not currently exist, but the override has been added." ).format(repo=repo)) if self.options.removals: to_remove = [ Override(repo, item) for repo in self.options.repos for item in self.options.removals ] results = overrides.remove_overrides(self.identity.uuid, to_remove) if self.options.remove_all: results = overrides.remove_all_overrides(self.identity.uuid, self.options.repos) # Update the cache and refresh the repo file. overrides.update(results)
def _do_command(self): """ Executes the command. """ self.assert_should_be_registered() self._validate_options() # --pool or --file turns off default auto attach if self.options.pool or self.options.file: self.auto_attach = False # Do not try to do auto-attach, when simple content access mode is used # BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1826300 # if is_simple_content_access(uep=self.cp, identity=self.identity): if self.auto_attach is True: self._print_ignore_auto_attach_mesage() else: self._print_ignore_attach_message() return 0 installed_products_num = 0 return_code = 0 report = None # TODO: change to if self.auto_attach: else: pool/file stuff try: cert_action_client = ActionClient(skips=[PackageProfileActionInvoker]) cert_action_client.update() cert_update = True attach_service = attach.AttachService(self.cp) if self.options.pool: subscribed = False for pool in self.options.pool: # odd html strings will cause issues, reject them here. if pool.find("#") >= 0: system_exit(os.EX_USAGE, _("Please enter a valid numeric pool ID.")) try: ents = attach_service.attach_pool(pool, self.options.quantity) # Usually just one, but may as well be safe: for ent in ents: pool_json = ent["pool"] print( _("Successfully attached a subscription for: {name}").format( name=pool_json["productName"] ) ) log.debug( "Attached a subscription for {name}".format(name=pool_json["productName"]) ) subscribed = True except connection.RestlibException as re: log.exception(re) exception_mapper = ExceptionMapper() mapped_message = exception_mapper.get_message(re) if re.code == 403: print(mapped_message) # already subscribed. elif re.code == 400 or re.code == 404: print(mapped_message) # no such pool. else: system_exit(os.EX_SOFTWARE, mapped_message) # some other error.. don't try again if not subscribed: return_code = 1 # must be auto else: installed_products_num = len(products.InstalledProducts(self.cp).list()) # if we are green, we don't need to go to the server self.sorter = inj.require(inj.CERT_SORTER) if self.sorter.is_valid(): if not installed_products_num: print(_("No Installed products on system. " "No need to attach subscriptions.")) else: print( _( "All installed products are covered by valid entitlements. " "No need to update subscriptions at this time." ) ) cert_update = False else: # If service level specified, make an additional request to # verify service levels are supported on the server: if self.options.service_level: consumer = self.cp.getConsumer(self.identity.uuid) if "serviceLevel" not in consumer: system_exit( os.EX_UNAVAILABLE, _( "Error: The --servicelevel option is not " "supported by the server. Did not " "complete your request." ), ) attach_service.attach_auto(self.options.service_level) if self.options.service_level is not None: # RHBZ 1632797 we should only save the sla if the sla was actually # specified. The uep and consumer_uuid are None, because service_level was sent # to candlepin server using attach_service.attach_auto() save_sla_to_syspurpose_metadata( uep=None, consumer_uuid=None, service_level=self.options.service_level ) print(_("Service level set to: {}").format(self.options.service_level)) if cert_update: report = self.entcertlib.update() profile_action_client = ProfileActionClient() profile_action_client.update() if report and report.exceptions(): print(_("Entitlement Certificate(s) update failed due to the following reasons:")) for e in report.exceptions(): print("\t-", str(e)) elif self.auto_attach: if not installed_products_num: return_code = 1 else: self.sorter.force_cert_check() # Make sure that we get fresh status of installed products status_cache = inj.require(inj.ENTITLEMENT_STATUS_CACHE) status_cache.load_status( self.sorter.cp_provider.get_consumer_auth_cp(), self.sorter.identity.uuid, self.sorter.on_date, ) self.sorter.load() # run this after entcertlib update, so we have the new entitlements return_code = show_autosubscribe_output(self.cp, self.identity) except Exception as e: handle_exception("Unable to attach: {e}".format(e=e), e) # it is okay to call this no matter what happens above, # it's just a notification to perform a check self._request_validity_check() return return_code