class Action(object): """ Action class representing a single action for a cli command @ivar name: action's name @ivar parser: optparse.OptionParser instance @ivar opts: options returned from parsing command line @ivar args: arguments returned from parsing command line """ def __init__(self): self.cmd = None self.name = None self.opts = None self.args = None self.optErrors = [] self.printer = None self.parser = OptionParser(option_class=KatelloOption) self.parser.add_option('-g', dest='grep', action="store_true", help=_("grep friendly output")) self.parser.add_option('-v', dest='verbose', action="store_true", help=_("verbose, more structured output")) self.parser.add_option('-d', dest='delimiter', default="", help=_("grep friendly output column delimiter")) self.setup_parser() @property def usage(self): """ Return a string for this action's usage """ if self.cmd: data = (self.cmd.cli.name, self.cmd.name, self.name) else: data = (os.path.basename(sys.argv[0]), self.name, "") return '%s <options> %s %s <options>' % data @property def description(self): """ Return a string for this action's description """ return _('no description available') def get_option(self, opt_dest): """ Get an option from opts or from the config file Options from opts take precedence. @type opt: str @param opt: name of option to get @return: value of the option or None if the option is no present """ attr = getattr(self.opts, opt_dest, None) if not attr: option = self.parser.get_option_by_dest(opt_dest) if option != None: opt_name = option.get_name() if Config.parser.has_option('options', opt_name): attr = Config.parser.get('options', opt_name) return u_obj(attr) def has_option(self, opt): """ Check if option is present @type opt: str @param opt: name of option to check @return True if the option was set, otherwise False """ return self.get_option(opt) != None def get_option_string(self, opt_dest): opt = self.parser.get_option_by_dest(opt_dest) if opt != None: flag = opt.get_opt_string() else: flag = '--' + opt_dest return flag def require_option(self, opt_dest): """ Add option error if an option is not present. @type opt_dest: str @param opt: name of option or option destination to check """ if (not self.option_specified(opt_dest)): flag = self.get_option_string(opt_dest) self.add_option_error(_('Option %s is required; please see --help') % flag) return def require_one_of_options(self, *opt_dests): """ Add option error if one of the options is not present. @type opt_dests: str @param opt_dests: name of option or option destination to check """ flags = [] param_count = 0 for opt_dest in opt_dests: if self.option_specified(opt_dest): param_count += 1 flag = self.get_option_string(opt_dest) flags.append(flag) if not param_count == 1: self.add_option_error(_('One of %s is required; please see --help') % ', '.join(flags)) return def option_specified(self, opt): return self.has_option(opt) and self.get_option(opt) != "" def add_option_error(self, errorMsg): """ Add option error to the error stack @type errorMsg: str @param errorMsg: error message """ self.optErrors.append(errorMsg) def setup_parser(self): """ Add custom options to the parser @note: this method should be overridden to add per-action options """ self.parser.set_usage(self.usage) def run(self): """ Action's functionality @note: override this method to implement the actoin's functionality @raise NotImplementedError: if this method is not overridden """ raise NotImplementedError('Base class method called') def check_options(self): """ Add custom option requirements @note: this method should be overridden to check for required options """ return def output_mode(self): if (self.has_option('grep') or (Config.parser.has_option('interface', 'force_grep_friendly') and Config.parser.get('interface', 'force_grep_friendly').lower() == 'true')): return Printer.OUTPUT_FORCE_GREP elif (self.has_option('verbose') or (Config.parser.has_option('interface', 'force_verbose') and Config.parser.get('interface', 'force_verbose').lower() == 'true')): return Printer.OUTPUT_FORCE_VERBOSE else: return Printer.OUTPUT_FORCE_NONE def process_options(self, args): """ This method setups up the parser, parses the arguments, checks options and prints argument errors. """ self.opts, self.args = self.parser.parse_args(args) self.printer = Printer(self.output_mode(), self.get_option('delimiter')) self.optErrors = [] self.check_options() if len(self.optErrors) > 0: if len(self.optErrors) == 1: self.parser.error(self.optErrors[0]) else: self.parser.error(self.optErrors) # this method exists so that an action can run like a command # it supports having single name actions (e.g. katello shell) def extract_action(self, args): pass def require_credentials(self): """ if True, credentials are required when calling the command. @note: this method should be overriden, if credentials should not be checked for action """ return True def error(self, errorMsg): errorMsg = u_str(errorMsg) _log.error("error: %s" % errorMsg) if errorMsg == '': msg = _('error: operation failed') else: msg = errorMsg print >> sys.stderr, msg def main(self, args): """ Main execution of the action This method setups up the parser, parses the arguments, and calls run() in a try/except block, handling RestlibExceptions and general errors @warning: this method should only be overridden with care """ try: self.process_options(args) return self.run() except SSL.Checker.WrongHost, wh: print _("ERROR: The server hostname you have configured in /etc/katello/client.conf does not match the") print _("hostname returned from the katello server you are connecting to. ") print "" print _("You have: [%s] configured but got: [%s] from the server.") % (wh.expectedHost, wh.actualHost) print "" print _("Please correct the host in the /etc/katello/client.conf file") sys.exit(1) except ServerRequestError, re: try: if "displayMessage" in re.args[1]: msg = re.args[1]["displayMessage"] else: msg = ", ".join(re.args[1]["errors"]) except: msg = re.args[1] if re.args[0] == 401: msg = _("Invalid credentials or unable to authenticate") self.error(msg) return re.args[0]