コード例 #1
0
class DisplayHelpers(object):
    """ Helper functions for printing data to display on the console """
    output_dict = dict()

    def __init__(self, width=20):
        self.output_dict[OutputFormats.table] = self.print_table
        self.output_dict[OutputFormats.list] = self.print_list
        self.output_dict[OutputFormats.json] = self.output_to_json
        self.max_width = width
        self._ui = UI()

    def display_data(self, data_to_display, output_format, unique_id_property_name=None):
        """
        Wrapper function for displaying data in the proper format: table, list, json, etc.
        :param data_to_display: The data to display. Each object represents a row in a table
                or an item in a list.
        :type data_to_display: array of objects
        :param output_format: Specifies which output format to use
        :type output_format: enum
        :param unique_id_property_name: Specifies the property which acts as the identifier
        :type unique_id_property_name: string
        """
        if data_to_display is None or data_to_display == []:
            LOGGER.info("DCPMEM: Empty data")
            return None
        if output_format not in self.output_dict:
            LOGGER.info("Incorrect output format")
            return None
        self.output_dict[output_format](data_to_display, unique_id_property_name)
        return None

    def format_data(self, data, truncate=False):
        """
        Function to identify header properties and convert Redfish property names to friendly names.
        It also truncate strings whenever required
        :param data: The data from which header has to be identified.
        :type data: array of objects
        :param truncate: Specifies whether truncation of strings is to be done or not
        :type truncate: Boolean
        :return:2 arrays. First array is an array of properties.
        Second array is an array of objects.
        Each object is an array containing value of properties at corresponding index.
        """
        table = []
        for item in data:
            row = [':'.join(x.split(":")[1:]).strip() for x in item.split("\n")
                   if len(x.split(":")) >= 2]
            table.append(row)
        headers = [x.split(":")[0].strip() for x in data[0].split("\n") if len(x.split(":")) == 2]
        not_found = [x for x in data[0].split("\n") if len(x.split(":")) < 2]
        self._ui.printer("\n".join(not_found))
        if not truncate:
            return headers, table
        truncated_headers = [self.truncate_lengthy(str(x), self.max_width) for x in headers]
        truncated_data = [[self.truncate_lengthy(str(x), self.max_width) for x in row]
                          for row in table]
        return truncated_headers, truncated_data

    # pylint: disable=unused-argument
    def print_table(self, table_data, property_id=None):
        """
        This function prints data in table format
        :param table_data: data to be printed in table format
        :type array of objects
        :param property_id: Specifies the property which acts as the identifier
        :type string
        """
        headers, data = self.format_data(table_data, True)
        self._ui.printer(u"\n")
        self._ui.printer(tabulate(data, headers, tablefmt="plain"))
        self._ui.printer(u"\n\n")
        return

    def print_list(self, list_data, property_id=None):
        """
        This function prints data in list format
        :param list_data: data to be printed in list format
        :type array of objects
        :param property_id: Specifies the property which acts as the identifier
        :type string
        """

        headers, data = self.format_data(list_data)
        flag = 0
        counter = 0
        if property_id is None or property_id not in headers:
            flag = 1

        if flag == 0:
            property_id_index = headers.index(property_id)
            del headers[property_id_index]

        for item in data:
            if flag == 0:
                self._ui.printer("--- " + property_id + ": " + str(item[property_id_index]
                                                                                    + " ---"))
                item.remove(item[property_id_index])
            else:
                counter += 1
                self._ui.printer("--- " + str(counter) + " ---")
            for prop in enumerate(headers):
                self._ui.printer("\n" + headers[prop[0]] + ": " + str(item[prop[0]]))
            self._ui.printer(u"\n\n")
        return

    def print_properties(self, data):
        """
        This function prints the data in list format without any header
        :param data:data to be printed without header
        :type array of string
        """
        if not data:
            self._ui.printer(u"\n")
            return
        headers, data = self.format_data(data)
        for item in data:
            for prop in enumerate(headers):
                self._ui.printer("\n" + headers[prop[0]] + ": " + str(item[prop[0]]))
            self._ui.printer(u"\n")
        self._ui.printer(u"\n")
        return

    # pylint: disable=unused-argument
    def output_to_json(self, json_data, property_id=None):
        """
        This function prints data in json format
        :param json_data: data to be printed in json format
        :type json_data: array of objects
        :param property_id: Specifies the property which acts as the identifier
        :type property_id: string
        """
        self._ui.printer(u"\n")
        self._ui.print_out_json(json_data)
        self._ui.printer(u"\n")
        return

    @staticmethod
    def truncate_lengthy(stringin, max_length):
        """ Truncate lengthy strings to a maximum size
        :param stringin: string to truncate
        :type stringin: string
        :param max_length: maximum allowed length of a string
        :type max_length: int
        :return: return the truncated string
        :rtype: string
        """
        if stringin:
            if len(stringin) > max_length:
                return stringin[:(max_length - 2)] + ".."
            return stringin
        return ""
コード例 #2
0
class RdmcCommand(RdmcCommandBase):
    """ Constructor """
    def __init__(self, name, usage, summary, aliases, argparser, Args=None):
        super().__init__(name, usage, summary, aliases, argparser)
        self._commands = collections.OrderedDict()
        self.ui = UI(1)
        self.commands_dict = dict()
        self.interactive = False
        self._progname = '%s : %s' % (versioning.__shortname__, \
                                      versioning.__longname__)
        self.opts = None
        self.encoding = None
        self.config = RdmcConfig()
        self.app = redfish.ris.RmcApp(showwarnings=True)
        self.retcode = 0
        self.candidates = dict()
        self.comm_map = dict()  #point command id names or alias to handle
        self.commlist = list()
        self._redobj = None
        self.loaded_commands = []

        #import all extensions dynamically
        for name in extensions.classNames:
            pkgName, cName = name.rsplit('.', 1)
            pkgName = 'extensions' + pkgName
            try:
                if '__pycache__' not in pkgName and 'Command' in cName:
                    self.commands_dict[cName] = getattr(
                        importlib.import_module(pkgName), cName)()
                    sName = pkgName.split('.')[1]
                    self.add_command(cName, section=sName)
            except cliutils.ResourceAllocationError as excp:
                self.ui.error(excp)
                retcode = ReturnCodes.RESOURCE_ALLOCATION_ISSUES_ERROR
                self.ui.error("Unable to allocate more resources.")
                self.ui.printer(("ILOREST return code: %s\n" % retcode))
                sys.exit(retcode)
            except Exception as excp:
                self.ui.error(("loading command: %s" % cName), None)

        #command mapping
        commands_to_remove = []
        for command in self.commands_dict:
            try:
                self.comm_map[self.commands_dict[command].ident.get(
                    'name')] = command
                for alias in self.commands_dict[command].ident.get('aliases'):
                    self.comm_map[alias] = command
            except Exception as excp:
                self.ui.command_not_enabled(("Command \'%s\' unable to be "\
                    "initialized...Removing" % command), excp)
                commands_to_remove.append(command)

        # removing commands marked for deletion
        for cmd in commands_to_remove:
            del self.commands_dict[cmd]
        del commands_to_remove

        #---------End of imports---------

    def add_command(self, command_name, section=None):
        """ Handles to addition of new commands

        :param command_name: command name
        :type command_name: str.
        :param section: section for the new command
        :type section: str.
        """
        if section not in self._commands:
            self._commands[section] = list()

        self._commands[section].append(command_name)

    def get_commands(self):
        """ Retrieves dictionary of commands """
        return self._commands

    def search_commands(self, cmdname):
        """ Function to see if command exist in added commands

        :param cmdname: command to be searched
        :type cmdname: str.
        """

        try:
            tmp = self.comm_map.get(cmdname)
            if not tmp:
                tmp = cmdname
            return self.commands_dict[tmp]
        except KeyError:
            raise cliutils.CommandNotFoundException(cmdname)

    def load_command(self, cmd):
        """ Fully Loads command and returns the class instance

        :param cmd: command identifier
        :type opts: class
        :returns: defined class instance

        """
        try:
            cmd.cmdbase = RdmcCommandBase(cmd.ident['name'], cmd.ident['usage'], \
                                          cmd.ident['summary'], cmd.ident['aliases'])
            cmd.parser = ArgumentParser(prog=cmd.ident['name'], usage=cmd.ident['usage'], \
                                        description=cmd.ident['summary'])
            cmd.rdmc = self
            cmd.definearguments(cmd.parser)
            for auxcmd in cmd.ident['auxcommands']:
                auxcmd = self.search_commands(auxcmd)
                if auxcmd not in self.loaded_commands:
                    self.loaded_commands.append(auxcmd)
                    cmd.auxcommands[auxcmd.ident['name']] = self.load_command(
                        auxcmd)
                else:
                    cmd.auxcommands[auxcmd.ident['name']] = self.commands_dict[self.comm_map\
                                                                        [auxcmd.ident['name']]]
            return cmd
        except Exception as excp:
            raise RdmcError("Unable to load command {}: {}".format(
                cmd.ident['name'], excp))

    def _run_command(self, opts, args):
        """ Calls the commands run function

        :param opts: command options
        :type opts: options.
        :param args: list of the entered arguments
        :type args: list.
        """
        cmd = self.search_commands(args[0])
        #may conserve memory to have the parser initialized here

        self.load_command(cmd)

        if opts.debug:
            LOGGER.setLevel(logging.DEBUG)
            LERR.setLevel(logging.DEBUG)

        if not opts.nologo and not self.interactive:
            #sys.stdout.write(FIPSSTR) #purpose of this?
            CLI.version(self._progname, versioning.__version__,
                        versioning.__extracontent__)
        if len(args) > 1:
            return cmd.run(args[1:])

        return cmd.run([])

    def run(self, line):
        """ Main rdmc command worker function

        :param line: entered command line
        :type line: list.
        """
        if os.name == 'nt':
            if not ctypes.windll.shell32.IsUserAnAdmin() != 0:
                self.app.typepath.adminpriv = False
        elif not os.getuid() == 0:
            self.app.typepath.adminpriv = False

        if "--version" in line or "-V" in line:
            CLI.printer("%s %s\n" %
                        (versioning.__longname__, versioning.__version__))
            sys.exit(self.retcode)

        all_opts = True
        help_indx = None
        help_list = ['-h', '--help', 'help']
        for indx, elem in enumerate(line):
            if elem in help_list:
                help_indx = indx
            if '-' in elem:
                continue
            else:
                all_opts = False
        if all_opts and ('-h' in line) or ('--help' in line):
            line = ['-h']
        elif help_indx:
            del line[help_indx]

        (self.opts, nargv) = self.parser.parse_known_args(line)

        if self.opts.redirect:
            try:
                sys.stdout = open("console.log", 'w')
            except:
                print("Unable to re-direct output for STDOUT.\n")
            else:
                print("Start of stdout file.\n\n")
            try:
                sys.stderr = open("console_err.log", 'w')
            except IOError:
                print("Unable to re-direct output for STDERR.\n")
            else:
                print("Start of stderr file.\n\n")

        self.app.verbose = self.ui.verbosity = self.opts.verbose

        try:
            #Test encoding functions are there
            Encryption.encode_credentials('test')
            self.app.set_encode_funct(Encryption.encode_credentials)
            self.app.set_decode_funct(Encryption.decode_credentials)
            self.encoding = True
        except redfish.hpilo.risblobstore2.ChifDllMissingError:
            self.encoding = False

        if self.opts.config is not None and len(self.opts.config) > 0:
            if not os.path.isfile(self.opts.config):
                self.retcode = ReturnCodes.CONFIGURATION_FILE_ERROR
                sys.exit(self.retcode)

            self.config.configfile = self.opts.config
        else:
            # Default locations: Windows: executed directory Linux: /etc/ilorest/redfish.conf
            self.config.configfile = os.path.join(os.path.dirname(sys.executable), \
             'redfish.conf') if os.name == 'nt' else '/etc/ilorest/redfish.conf'

        if not os.path.isfile(self.config.configfile):
            LOGGER.warning("Config file '%s' not found\n\n",
                           self.config.configfile)

        self.config.load()

        cachedir = None
        if not self.opts.nocache:
            self.config.cachedir = os.path.join(self.opts.config_dir, 'cache')
            cachedir = self.config.cachedir

        if cachedir:
            self.app.cachedir = cachedir
            try:
                os.makedirs(cachedir)
            except OSError as ex:
                if ex.errno == errno.EEXIST:
                    pass
                else:
                    raise

        if self.opts.logdir and self.opts.debug:
            logdir = self.opts.logdir
        else:
            logdir = self.config.logdir

        if logdir and self.opts.debug:
            try:
                os.makedirs(logdir)
            except OSError as ex:
                if ex.errno == errno.EEXIST:
                    pass
                else:
                    raise

        if self.opts.debug:
            logfile = os.path.join(logdir, versioning.__shortname__ + '.log')

            # Create a file logger since we got a logdir
            lfile = logging.FileHandler(filename=logfile)
            formatter = logging.Formatter(
                "%(asctime)s %(levelname)s\t: %(message)s")

            lfile.setFormatter(formatter)
            lfile.setLevel(logging.DEBUG)
            LOGGER.addHandler(lfile)
            self.app.LOGGER = LOGGER

        if ("login" in line or any(x.startswith("--url") for x in line) or not line)\
                        and not (any(x.startswith(("-h", "--h")) for x in nargv) or "help" in line):
            self.app.logout()
        else:
            creds, enc = self._pull_creds(nargv)
            self.app.restore(creds=creds, enc=enc)
            self.opts.is_redfish = self.app.typepath.updatedefinesflag(\
                                                                redfishflag=self.opts.is_redfish)

        if nargv:
            try:
                self.retcode = self._run_command(self.opts, nargv)
                if self.app.cache:
                    if ("logout" not in line) and ("--logout" not in line):
                        self.app.save()
                        self.app.redfishinst = None
                else:
                    self.app.logout()
            except Exception as excp:
                self.handle_exceptions(excp)

            return self.retcode
        else:
            self.cmdloop(self.opts)

            if self.app.cache:
                self.app.save()
            else:
                self.app.logout()

    def cmdloop(self, opts):
        """ Interactive mode worker function

        :param opts: command options
        :type opts: options.
        """
        self.interactive = True

        if not opts.nologo:
            sys.stdout.write(FIPSSTR)
            CLI.version(self._progname, versioning.__version__,
                        versioning.__extracontent__)

        if not self.app.typepath.adminpriv:
            self.ui.user_not_admin()

        if opts.debug:
            LOGGER.setLevel(logging.DEBUG)
            LERR.setLevel(logging.DEBUG)

        for command, values in self.commands_dict.items():
            self.commlist.append(values.ident['name'])

        for item in self.commlist:
            if item == "help":
                self.candidates[item] = self.commlist
            else:
                self.candidates[item] = []

        self._redobj = TabAndHistoryCompletionClass(dict(self.candidates))
        try:
            session = PromptSession(completer=self._redobj, \
                                                        complete_style=CompleteStyle.READLINE_LIKE)

        except:
            LOGGER.info("Console error: Tab complete is unavailable.")
            session = None

        while True:
            try:
                prompt_string = str(versioning.__shortname__) + ' > '
                if session:
                    if self.opts.notoolbar:
                        line = session.prompt(prompt_string)
                    else:
                        line = session.prompt(
                            prompt_string,
                            bottom_toolbar=self._redobj.bottom_toolbar)
                else:
                    line = input(prompt_string)

            except (EOFError, KeyboardInterrupt) as error:
                line = "quit\n"

            if not len(line):
                continue
            elif line.endswith(os.linesep):
                line.rstrip(os.linesep)

            nargv = shlex.split(line, posix=False)

            try:
                if not (any(x.startswith("-h") for x in nargv) or \
                    any(x.startswith("--h") for x in nargv) or "help" in line):
                    if "login " in line or line == 'login' or \
                        any(x.startswith("--url") for x in nargv):
                        self.app.logout()
                self.retcode = self._run_command(opts, nargv)
                self.check_for_tab_lists(nargv)
            except Exception as excp:
                self.handle_exceptions(excp)

            if self.opts.verbose:
                sys.stdout.write("iLOrest return code: %s\n" % self.retcode)

        return self.retcode

    def handle_exceptions(self, excp):
        """ Main exception handler for both shell and interactive modes

        :param excp: captured exception to be handled
        :type excp: exception.
        """
        # pylint: disable=redefined-argument-from-local
        try:
            if excp:
                errorstr = "Exception: {0}".format(excp.__class__.__name__)
                errorstr = errorstr+"({0})".format(excp.message) if \
                                hasattr(excp, "message") else errorstr
                LOGGER.info(errorstr)
            raise
        # ****** RDMC ERRORS ******
        except ConfigurationFileError as excp:
            self.retcode = ReturnCodes.CONFIGURATION_FILE_ERROR
            self.ui.error(excp)
            sys.exit(excp.errcode)
        except InvalidCommandLineError as excp:
            self.retcode = ReturnCodes.INVALID_COMMAND_LINE_ERROR
            self.ui.invalid_commmand_line(excp)
        except NoCurrentSessionEstablished as excp:
            self.retcode = ReturnCodes.NO_CURRENT_SESSION_ESTABLISHED
            self.ui.error(excp)
        except NoChangesFoundOrMadeError as excp:
            self.retcode = ReturnCodes.NO_CHANGES_MADE_OR_FOUND
            self.ui.invalid_commmand_line(excp)
        except StandardBlobErrorHandler as excp:
            self.retcode = ReturnCodes.GENERAL_ERROR
            self.ui.standard_blob_error(excp)
        except InvalidFileInputError as excp:
            self.retcode = ReturnCodes.INVALID_FILE_INPUT_ERROR
            self.ui.invalid_commmand_line(excp)
        except InvalidCommandLineErrorOPTS as excp:
            self.retcode = ReturnCodes.INVALID_COMMAND_LINE_ERROR
        except InvalidFileFormattingError as excp:
            self.retcode = ReturnCodes.INVALID_FILE_FORMATTING_ERROR
            self.ui.invalid_file_formatting(excp)
        except NoContentsFoundForOperationError as excp:
            self.retcode = ReturnCodes.NO_CONTENTS_FOUND_FOR_OPERATION
            self.ui.no_contents_found_for_operation(excp)
        except InfoMissingEntriesError as excp:
            self.retcode = ReturnCodes.NO_VALID_INFO_ERROR
            self.ui.error(excp)
        except (InvalidOrNothingChangedSettingsError, redfish.ris.rmc_helper.\
                                                IncorrectPropValue) as excp:
            self.retcode = ReturnCodes.SAME_SETTINGS_ERROR
            self.ui.error(excp)
        except NoDifferencesFoundError as excp:
            self.retcode = ReturnCodes.NO_CHANGES_MADE_OR_FOUND
            self.ui.no_differences_found(excp)
        except MultipleServerConfigError as excp:
            self.retcode = ReturnCodes.MULTIPLE_SERVER_CONFIG_FAIL
            self.ui.multiple_server_config_fail(excp)
        except InvalidMSCfileInputError as excp:
            self.retcode = ReturnCodes.MULTIPLE_SERVER_INPUT_FILE_ERROR
            self.ui.multiple_server_config_input_file(excp)
        except FirmwareUpdateError as excp:
            self.retcode = ReturnCodes.FIRMWARE_UPDATE_ERROR
            self.ui.error(excp)
        except FailureDuringCommitError as excp:
            self.retcode = ReturnCodes.FAILURE_DURING_COMMIT_OPERATION
            self.ui.error(excp)
        except BootOrderMissingEntriesError as excp:
            self.retcode = ReturnCodes.BOOT_ORDER_ENTRY_ERROR
            self.ui.error(excp)
        except NicMissingOrConfigurationError as excp:
            self.retcode = ReturnCodes.NIC_MISSING_OR_INVALID_ERROR
            self.ui.error(excp)
        except (IncompatibleiLOVersionError, redfish.ris.rmc_helper.\
                                IncompatibleiLOVersionError) as excp:
            self.retcode = ReturnCodes.INCOMPATIBLE_ILO_VERSION_ERROR
            self.ui.printer(excp)
        except IncompatableServerTypeError as excp:
            self.retcode = ReturnCodes.INCOMPATIBLE_SERVER_TYPE
            self.ui.printer(excp)
        except IloLicenseError as excp:
            self.ui.printer(excp)
            self.retcode = ReturnCodes.ILO_LICENSE_ERROR
        except InvalidCListFileError as excp:
            self.retcode = ReturnCodes.INVALID_CLIST_FILE_ERROR
            self.ui.error(excp)
        except PartitionMoutingError as excp:
            self.retcode = ReturnCodes.UNABLE_TO_MOUNT_BB_ERROR
            self.ui.error(excp)
        except TimeOutError as excp:
            self.retcode = ReturnCodes.UPDATE_SERVICE_BUSY
            self.ui.error(excp)
        except DownloadError as excp:
            self.retcode = ReturnCodes.FAILED_TO_DOWNLOAD_COMPONENT
            self.ui.error(excp)
        except UploadError as excp:
            self.retcode = ReturnCodes.FAILED_TO_UPLOAD_COMPONENT
            self.ui.error(excp)
        except BirthcertParseError as excp:
            self.retcode = ReturnCodes.BIRTHCERT_PARSE_ERROR
            self.ui.error(excp)
        except ResourceExists as excp:
            self.retcode = ReturnCodes.RESOURCE_EXISTS_ERROR
            self.ui.error(excp)
        except InvalidKeyError as excp:
            self.retcode = ReturnCodes.ENCRYPTION_ERROR
            self.ui.error(
                "Invalid key has been entered for encryption/decryption.")
        except UnableToDecodeError as excp:
            self.retcode = ReturnCodes.ENCRYPTION_ERROR
            self.ui.error(excp)
        except UnabletoFindDriveError as excp:
            self.retcode = ReturnCodes.DRIVE_MISSING_ERROR
            self.ui.error(excp)
            self.ui.printer("Error occurred while reading device labels.")
        except PathUnavailableError as excp:
            self.retcode = ReturnCodes.PATH_UNAVAILABLE_ERROR
            if excp:
                self.ui.error(excp)
            else:
                self.ui.printer("Requested path is unavailable.")
        except TaskQueueError as excp:
            self.retcode = ReturnCodes.TASKQUEUE_ERROR
            self.ui.error(excp)
        # ****** CLI ERRORS ******
        except (CommandNotEnabledError,
                cliutils.CommandNotFoundException) as excp:
            self.retcode = ReturnCodes.UI_CLI_COMMAND_NOT_FOUND_EXCEPTION
            self.ui.command_not_found(excp)
            try:
                self.commands_dict['HelpCommand'].run('-h')
            except KeyError:
                pass

        # ****** RMC/RIS ERRORS ******
        except redfish.ris.UndefinedClientError:
            self.retcode = ReturnCodes.RIS_UNDEFINED_CLIENT_ERROR
            self.ui.error("Please login before making a selection.")
        except (redfish.ris.InstanceNotFoundError, redfish.ris.\
                RisInstanceNotFoundError) as excp:
            self.retcode = ReturnCodes.RIS_INSTANCE_NOT_FOUND_ERROR
            self.ui.printer(excp)
        except redfish.ris.CurrentlyLoggedInError as excp:
            self.retcode = ReturnCodes.RIS_CURRENTLY_LOGGED_IN_ERROR
            self.ui.error(excp)
        except redfish.ris.NothingSelectedError as excp:
            self.retcode = ReturnCodes.RIS_NOTHING_SELECTED_ERROR
            self.ui.nothing_selected()
        except redfish.ris.NothingSelectedFilterError as excp:
            self.retcode = ReturnCodes.RIS_NOTHING_SELECTED_FILTER_ERROR
            self.ui.nothing_selected_filter()
        except redfish.ris.NothingSelectedSetError as excp:
            self.retcode = ReturnCodes.RIS_NOTHING_SELECTED_SET_ERROR
            self.ui.nothing_selected_set()
        except redfish.ris.InvalidSelectionError as excp:
            self.retcode = ReturnCodes.RIS_INVALID_SELECTION_ERROR
            self.ui.error(excp)
        except redfish.ris.rmc_helper.UnableToObtainIloVersionError as excp:
            self.retcode = ReturnCodes.INCOMPATIBLE_ILO_VERSION_ERROR
            self.ui.error(excp)
        except redfish.ris.IdTokenError as excp:
            if hasattr(excp, 'message'):
                self.ui.printer(excp.message)
            else:
                self.ui.printer("Logged-in account does not have the privilege"\
                              " required to fulfill the request or a required"\
                              " token is missing."\
                              "\nEX: biospassword flag if bios password present "\
                              "or tpmenabled flag if TPM module present.")
            self.retcode = ReturnCodes.RIS_MISSING_ID_TOKEN
        except redfish.ris.SessionExpired as excp:
            self.retcode = ReturnCodes.RIS_SESSION_EXPIRED
            self.app.logout()
            self.ui.printer("Current session has expired or is invalid, "\
                    "please login again with proper credentials to continue.\n")
        except redfish.ris.ValidationError as excp:
            self.retcode = ReturnCodes.RIS_VALIDATION_ERROR
        except redfish.ris.ValueChangedError as excp:
            self.retcode = ReturnCodes.RIS_VALUE_CHANGED_ERROR
        except redfish.ris.ris.SchemaValidationError as excp:
            self.ui.printer("Error found in schema, try running with the "\
                          "--latestschema flag.")
            self.retcode = ReturnCodes.RIS_SCHEMA_PARSE_ERROR
        # ****** RMC/RIS ERRORS ******
        except redfish.rest.connections.RetriesExhaustedError as excp:
            self.retcode = ReturnCodes.V1_RETRIES_EXHAUSTED_ERROR
            self.ui.retries_exhausted_attemps()
        except redfish.rest.v1.InvalidCredentialsError as excp:
            self.retcode = ReturnCodes.V1_INVALID_CREDENTIALS_ERROR
            self.ui.invalid_credentials(excp)
        except redfish.rest.v1.JsonDecodingError as excp:
            self.retcode = ReturnCodes.JSON_DECODE_ERROR
            self.ui.error(excp)
        except redfish.rest.v1.ServerDownOrUnreachableError as excp:
            self.retcode = \
                    ReturnCodes.V1_SERVER_DOWN_OR_UNREACHABLE_ERROR
            self.ui.error(excp)
        except redfish.rest.connections.ChifDriverMissingOrNotFound as excp:
            self.retcode = ReturnCodes.V1_CHIF_DRIVER_MISSING_ERROR
            self.ui.printer("Chif driver not found, please check that the iLO channel interface"\
                             " driver (Chif) is installed.")
        except redfish.rest.connections.SecurityStateError as excp:
            self.retcode = ReturnCodes.V1_SECURITY_STATE_ERROR
            self.ui.printer("High security mode [%s] has been enabled. " \
                              "Please provide credentials.\n" % str(excp))
        except redfish.hpilo.risblobstore2.ChifDllMissingError as excp:
            self.retcode = ReturnCodes.REST_ILOREST_CHIF_DLL_MISSING_ERROR
            self.ui.printer("iLOrest Chif dll not found, please check that the "\
                                            "chif dll is present.")
        except redfish.hpilo.risblobstore2.UnexpectedResponseError as excp:
            self.retcode = ReturnCodes.REST_ILOREST_UNEXPECTED_RESPONSE_ERROR
            self.ui.printer("Unexpected data received from iLO.")
        except redfish.hpilo.risblobstore2.HpIloError as excp:
            self.retcode = ReturnCodes.REST_ILOREST_ILO_ERROR
            self.ui.printer("iLO returned a failed error code.")
        except redfish.hpilo.risblobstore2.Blob2CreateError as excp:
            self.retcode = ReturnCodes.REST_ILOREST_CREATE_BLOB_ERROR
            self.ui.printer("Blob create operation failed.")
        except redfish.hpilo.risblobstore2.Blob2ReadError as excp:
            self.retcode = ReturnCodes.REST_ILOREST_READ_BLOB_ERROR
            self.ui.printer("Blob read operation failed.")
        except redfish.hpilo.risblobstore2.Blob2WriteError as excp:
            self.retcode = ReturnCodes.REST_ILOREST_WRITE_BLOB_ERROR
            self.ui.printer("Blob write operation failed.")
        except redfish.hpilo.risblobstore2.Blob2DeleteError as excp:
            self.retcode = ReturnCodes.REST_ILOREST_BLOB_DELETE_ERROR
            self.ui.printer("Blob delete operation failed.")
        except redfish.hpilo.risblobstore2.Blob2OverrideError as excp:
            self.retcode = ReturnCodes.REST_ILOREST_BLOB_OVERRIDE_ERROR
            self.ui.error(excp)
            self.ui.printer("\nBlob was overwritten by another user. Please " \
                  "ensure only one user is making changes at a time locally.")
        except redfish.hpilo.risblobstore2.BlobRetriesExhaustedError as excp:
            self.retcode = ReturnCodes.REST_BLOB_RETRIES_EXHAUSETED_ERROR
            self.ui.printer("\nBlob operation still fails after max retries.")
        except redfish.hpilo.risblobstore2.Blob2FinalizeError as excp:
            self.retcode = ReturnCodes.REST_ILOREST_BLOB_FINALIZE_ERROR
            self.ui.printer("Blob finalize operation failed.")
        except redfish.hpilo.risblobstore2.BlobNotFoundError as excp:
            self.retcode = ReturnCodes.REST_ILOREST_BLOB_NOT_FOUND_ERROR
            self.ui.printer("Blob not found with key and namespace provided.")
        except redfish.ris.rmc_helper.InvalidPathError as excp:
            self.retcode = ReturnCodes.RIS_REF_PATH_NOT_FOUND_ERROR
            self.ui.printer("Reference path not found.")
        except redfish.ris.rmc_helper.IloResponseError as excp:
            self.retcode = ReturnCodes.RIS_ILO_RESPONSE_ERROR
        except redfish.ris.rmc_helper.UserNotAdminError as excp:
            self.ui.user_not_admin()
            self.retcode = ReturnCodes.USER_NOT_ADMIN
        except redfish.hpilo.rishpilo.HpIloInitialError as excp:
            self.ui.error(excp)
            self.retcode = ReturnCodes.RIS_ILO_INIT_ERROR
        except redfish.hpilo.rishpilo.HpIloWriteError as excp:
            self.ui.error(excp)
            self.retcode = ReturnCodes.RESOURCE_ALLOCATION_ISSUES_ERROR
        except redfish.hpilo.rishpilo.HpIloReadError as excp:
            self.ui.error(excp)
            self.retcode = ReturnCodes.RESOURCE_ALLOCATION_ISSUES_ERROR
        # ****** RIS OBJECTS ERRORS ******
        except redfish.ris.ris.BiosUnregisteredError as excp:
            self.retcode = ReturnCodes.RIS_RIS_BIOS_UNREGISTERED_ERROR
            self.ui.bios_unregistered_error()
        # ****** FILE/IO ERRORS ******
        except IOError:
            self.retcode = ReturnCodes.INVALID_FILE_INPUT_ERROR
            self.ui.printer("Error accessing the file path. Verify the file path is correct and " \
                                                                    "you have proper permissions.")
        # ****** GENERAL ERRORS ******
        except SystemExit:
            self.retcode = ReturnCodes.GENERAL_ERROR
            raise
        except Exception as excp:
            self.retcode = ReturnCodes.GENERAL_ERROR
            sys.stderr.write('ERROR: %s\n' % excp)

            if self.opts.debug:
                traceback.print_exc(file=sys.stderr)

    def check_for_tab_lists(self, command=None):
        """ Function to generate available options for tab tab

        :param command: command for auto tab completion
        :type command: string.
        """
        #TODO: don't always update, only when we have a different selector.
        #Try to use args to get specific nested posibilities?
        changes = dict()

        # select options
        typeslist = list()
        select_not_required_commands = [
            'login', 'logout', 'createlogicaldrive', 'deletelogicaldrive',
            'drivesanitize', 'factoryresetcontroller', 'types', 'status',
            'serverinfo', 'uploadcomp', 'downloadcomp', 'rawpatch',
            'clearcontrollerconfig', 'rawpost', 'rawget', 'rawput',
            'rawdelete', 'rawhead', 'ethernet', 'iloaccounts', 'taskqueue',
            'smartarray', 'ilofederation', 'showpmm', 'ahsdiag', 'smbios',
            'directory', 'securitystatus', 'maintenancewindow', 'setpassword',
            'makeinstallset', 'installset', 'hpgooey', 'provisionpmm',
            'applypmmconfig', 'clearpmmpendingconfig', 'pmmsecuritystate',
            'showpmmpendingconfig', 'showrecommendedpmmconfig'
        ]

        select_required = True
        for s in select_not_required_commands:
            if s == command[0]:
                select_required = False
        try:
            typeslist = sorted(set(self.app.types()))
            changes["select"] = typeslist

            # get/set/info options
            getlist = list()

            if self.app.typepath.defs:
                typestr = self.app.typepath.defs.typestring
            templist = self.app.getprops()
            dictcopy = copy.copy(templist[0])

            for content in templist:
                for k in list(content.keys()):
                    if k.lower() in HARDCODEDLIST or '@odata' in k.lower():
                        del content[k]
            if 'Bios.' in dictcopy[typestr]:
                if hasattr(
                        templist[0],
                        'Attributes',
                ):
                    templist = templist[0]['Attributes']
                else:
                    templist = templist[0]
            else:
                templist = templist[0]
            for key, _ in templist.items():
                getlist.append(key)

            getlist.sort()

            # if select command, get possible values
            infovals = dict()

            if 'select' in command:

                if typestr in dictcopy:
                    (_, attributeregistry) = self.app.get_selection(
                        setenable=True)
                    schema, reg = self.app.get_model(dictcopy,
                                                     attributeregistry)

                    if reg:
                        reg = reg['Attributes']
                        for item in getlist:
                            for attribute in reg:
                                if item == attribute:
                                    infovals.update({item: reg[attribute]})
                                    break

                        changes["nestedinfo"] = infovals

                    elif schema:
                        changes["nestedinfo"] = schema

            changes["get"] = getlist
            changes["nestedprop"] = dictcopy[
                'Attributes'] if 'Attributes' in dictcopy else dictcopy
            changes["set"] = getlist
            changes["info"] = getlist
            changes["val"] = []

            if changes:
                self._redobj.updates_tab_completion_lists(changes)

        except NothingSelectedError:
            try:
                if not select_required and self.app.current_client:
                    pass
                else:
                    raise NothingSelectedError
            except UndefinedClientError:
                pass

    def _pull_creds(self, args):
        """Pull creds from the arguments for blobstore"""
        cred_args = {}
        enc = False
        arg_iter = iter(args)
        try:
            for arg in arg_iter:
                if arg in ('--enc', '-e'):
                    enc = True
                if arg in ('-u', '--user'):
                    cred_args['username'] = next(arg_iter)
                elif arg in ('-p', '--password'):
                    cred_args['password'] = next(arg_iter)
        except StopIteration:
            return {}, False
        return cred_args, enc

    def rdmc_parse_arglist(self, cmdinstance, line=None, default=False):
        """
        parses line into arguments taking special consideration
        of quote characters
        :param cmdinstance: command instance to be referenced
        :type cmdinstance: class object
        :param line: string of arguments passed in
        :type line: str.
        :param default: Flag to determine if the parsed command requires the default workaround for
                        argparse in Python 2. Argparse incorrectly assumes a sub-command is always
                        required, so we have to include a default sub-command for no arguments.
        :type default: bool
        :returns: args list
        """
        def checkargs(argopts):
            """Check for optional args"""
            (_, args) = argopts
            for arg in args:
                if arg.startswith('-') or arg.startswith('--'):
                    try:
                        cmdinstance.parser.error("The option %s is not available for %s" % \
                                                            (arg, cmdinstance.ident['name']))
                    except SystemExit:
                        raise InvalidCommandLineErrorOPTS("")
            return argopts

        if line is None:
            return checkargs(cmdinstance.parser.parse_known_args(line))

        arglist = []
        if isinstance(line, six.string_types):
            arglist = shlex.split(line, posix=False)

            for ind, val in enumerate(arglist):
                arglist[ind] = val.strip('"\'')
        elif isinstance(line, list):
            arglist = line

        exarglist = []
        if os.name == 'nt':
            # need to glob for windows
            for arg in arglist:
                try:
                    gob = glob.glob(arg)

                    if gob and len(gob) > 0:
                        exarglist.extend(gob)
                    else:
                        exarglist.append(arg)
                except:
                    if not arg:
                        continue
                    else:
                        exarglist.append(arg)
        else:
            for arg in arglist:
                if arg:
                    exarglist.append(arg)
        # insert the 'default' positional argument when the first argument is an optional
        #chicken and egg problem. Would be nice to figure out if a help option has been
        #referenced; however, I may not be able to parse the exarglist (line in array form)
        #in the event it is empty (appears there is no way to test parse and subsequently catch
        #the error for flow control)

        found_help = False
        for _opt in exarglist:
            if _opt in ['-h', '--h', '-help', '--help']:
                found_help = True
                break
        if not found_help and default:
            exarglist.insert(0, 'default')
        return checkargs(cmdinstance.parser.parse_known_args(exarglist))