示例#1
0
文件: base.py 项目: jsomara/katello
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]