iLO-manager first main commitgit status
This commit is contained in:
1 parent
e6f4cc04ca
commit
599d8da562
3271 files changed
+550655
No files matched your search
@@ -0,0 +1,140 @@
|
||||
###
|
||||
# Copyright 2016-2021 Hewlett Packard Enterprise, Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
###
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Commit Command for RDMC"""
|
||||
|
||||
from redfish.ris.rmc_helper import NothingSelectedError
|
||||
|
||||
try:
|
||||
from rdmc_helper import (
|
||||
FailureDuringCommitError,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
NoChangesFoundOrMadeError,
|
||||
NoCurrentSessionEstablished,
|
||||
ReturnCodes,
|
||||
)
|
||||
except ImportError:
|
||||
from ilorest.rdmc_helper import (
|
||||
FailureDuringCommitError,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
NoChangesFoundOrMadeError,
|
||||
NoCurrentSessionEstablished,
|
||||
ReturnCodes,
|
||||
)
|
||||
|
||||
|
||||
class CommitCommand:
|
||||
"""Constructor"""
|
||||
|
||||
def __init__(self):
|
||||
self.ident = {
|
||||
"name": "commit",
|
||||
"usage": None,
|
||||
"description": "commit [OPTIONS]\n\n\tRun to apply all changes made during"
|
||||
" the current session\n\texample: commit",
|
||||
"summary": "Applies all the changes made during the current session.",
|
||||
"aliases": [],
|
||||
"auxcommands": ["LogoutCommand", "RebootCommand"],
|
||||
}
|
||||
self.cmdbase = None
|
||||
self.rdmc = None
|
||||
self.auxcommands = dict()
|
||||
|
||||
def commitfunction(self, options=None):
|
||||
"""Main commit worker function
|
||||
|
||||
:param options: command line options
|
||||
:type options: list.
|
||||
"""
|
||||
self.commitvalidation()
|
||||
|
||||
self.rdmc.ui.printer("Committing changes...\n")
|
||||
|
||||
if options:
|
||||
if options.biospassword:
|
||||
self.rdmc.app.current_client.bios_password = options.biospassword
|
||||
try:
|
||||
failure = False
|
||||
commit_opp = self.rdmc.app.commit()
|
||||
for path in commit_opp:
|
||||
if self.rdmc.opts.verbose:
|
||||
self.rdmc.ui.printer("Changes are being made to path: %s\n" % path)
|
||||
if next(commit_opp):
|
||||
failure = True
|
||||
except NothingSelectedError:
|
||||
raise NoChangesFoundOrMadeError("No changes found or made during commit operation.")
|
||||
else:
|
||||
if failure:
|
||||
raise FailureDuringCommitError(
|
||||
"One or more types failed to commit. Run the "
|
||||
"status command to see uncommitted data. "
|
||||
"if you wish to discard failed changes refresh the "
|
||||
"type using select with the --refresh flag."
|
||||
)
|
||||
|
||||
if options.reboot:
|
||||
self.auxcommands["reboot"].run(options.reboot)
|
||||
self.auxcommands["logout"].run("")
|
||||
|
||||
def run(self, line, help_disp=False):
|
||||
"""Wrapper function for commit main function
|
||||
|
||||
:param line: command line input
|
||||
:type line: string.
|
||||
"""
|
||||
if help_disp:
|
||||
self.parser.print_help()
|
||||
return ReturnCodes.SUCCESS
|
||||
try:
|
||||
(options, _) = self.rdmc.rdmc_parse_arglist(self, line)
|
||||
except (InvalidCommandLineErrorOPTS, SystemExit):
|
||||
if ("-h" in line) or ("--help" in line):
|
||||
return ReturnCodes.SUCCESS
|
||||
else:
|
||||
raise InvalidCommandLineErrorOPTS("")
|
||||
|
||||
self.commitfunction(options)
|
||||
|
||||
# Return code
|
||||
return ReturnCodes.SUCCESS
|
||||
|
||||
def commitvalidation(self):
|
||||
"""Commit method validation function"""
|
||||
|
||||
try:
|
||||
_ = self.rdmc.app.current_client
|
||||
except:
|
||||
raise NoCurrentSessionEstablished("Please login and make setting" " changes before using commit command.")
|
||||
|
||||
def definearguments(self, customparser):
|
||||
"""Wrapper function for new command main function
|
||||
|
||||
:param customparser: command line input
|
||||
:type customparser: parser.
|
||||
"""
|
||||
if not customparser:
|
||||
return
|
||||
|
||||
self.cmdbase.add_login_arguments_group(customparser)
|
||||
customparser.add_argument(
|
||||
"--reboot",
|
||||
dest="reboot",
|
||||
help="Use this flag to perform a reboot command function after"
|
||||
" completion of operations. For help with parameters and"
|
||||
" descriptions regarding the reboot flag, run help reboot.",
|
||||
default=None,
|
||||
)
|
||||
@@ -0,0 +1,212 @@
|
||||
###
|
||||
# Copyright 2016-2024 Hewlett Packard Enterprise, Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
###
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
"""DetectiLO Command for RDMC"""
|
||||
from redfish.hpilo.vnichpilo import AppAccount
|
||||
from redfish.rest.connections import ChifDriverMissingOrNotFound, VnicNotEnabledError
|
||||
import requests
|
||||
|
||||
try:
|
||||
from rdmc_helper import (
|
||||
UI,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
ReturnCodes,
|
||||
GenBeforeLoginError,
|
||||
VnicExistsError,
|
||||
)
|
||||
except ImportError:
|
||||
from ilorest.rdmc_helper import (
|
||||
UI,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
ReturnCodes,
|
||||
GenBeforeLoginError,
|
||||
VnicExistsError,
|
||||
)
|
||||
|
||||
|
||||
class DetectiLOCommand:
|
||||
"""Constructor"""
|
||||
|
||||
def __init__(self):
|
||||
self.ident = {
|
||||
"name": "detectilo",
|
||||
"usage": None,
|
||||
"description": "Provides the iLO generation of the currently logged-in server.\n\n"
|
||||
"If --ignore_session is specified, it retrieves the iLO generation of the IP mentioned in --url\n"
|
||||
"or attempts to determine the iLO generation of the current server.",
|
||||
"summary": "Retrieves the iLO generation of the server.",
|
||||
"aliases": [],
|
||||
"auxcommands": [],
|
||||
}
|
||||
self.cmdbase = None
|
||||
self.rdmc = None
|
||||
self.auxcommands = dict()
|
||||
|
||||
def run(self, line, help_disp=False):
|
||||
"""Main get worker function
|
||||
|
||||
:param line: command line input
|
||||
:type line: string.
|
||||
"""
|
||||
if help_disp:
|
||||
line.append("-h")
|
||||
try:
|
||||
(_, _) = self.rdmc.rdmc_parse_arglist(self, line)
|
||||
except:
|
||||
return ReturnCodes.SUCCESS
|
||||
return ReturnCodes.SUCCESS
|
||||
try:
|
||||
(options, _) = self.rdmc.rdmc_parse_arglist(self, line)
|
||||
except (InvalidCommandLineErrorOPTS, SystemExit):
|
||||
if ("-h" in line) or ("--help" in line):
|
||||
return ReturnCodes.SUCCESS
|
||||
else:
|
||||
raise InvalidCommandLineErrorOPTS("")
|
||||
|
||||
if not options.ignore_session and not options.url:
|
||||
client = self.detectilovalidation(options)
|
||||
if client:
|
||||
if not options.json:
|
||||
self.rdmc.ui.printer("Using the current logged in session information.\n")
|
||||
if not any(substring in client.base_url for substring in ("blobstore", "16.1.15.1")):
|
||||
options.url = client.base_url.split("/")[-1]
|
||||
|
||||
if options.url:
|
||||
if not options.json:
|
||||
self.rdmc.ui.printer("Detecting iLO for remote device %s\n" % options.url)
|
||||
retcode = self.detect_remote_ilotype(options)
|
||||
else:
|
||||
if not options.json:
|
||||
self.rdmc.ui.printer("Detecting iLO for this server.\n")
|
||||
retcode = self.detect_local_ilotype(options)
|
||||
return retcode
|
||||
|
||||
def detectilovalidation(self, options):
|
||||
"""detectilo validation function
|
||||
|
||||
:param options: command line options
|
||||
:type options: list.
|
||||
"""
|
||||
return self.rdmc.login_select_validation(self, options)
|
||||
|
||||
def detect_remote_ilotype(self, options):
|
||||
try:
|
||||
path = "https://" + options.url + "/redfish/v1"
|
||||
data = requests.get(path, verify=False)
|
||||
json_data = data.json()
|
||||
Oem_Hpe = json_data["Oem"]["Hpe"]
|
||||
if "ManagerType" in Oem_Hpe["Manager"][0]:
|
||||
ilo_ver = int(Oem_Hpe["Manager"][0]["ManagerType"].split(" ")[1])
|
||||
else:
|
||||
manager_data = Oem_Hpe["Moniker"]
|
||||
ilo_ver = int(manager_data["PRODGEN"].split(" ")[1])
|
||||
except Exception as excp:
|
||||
raise GenBeforeLoginError(
|
||||
"An error occurred while retrieving the iLO generation. "
|
||||
"Please ensure that the virtual NIC is enabled for iLO7 based "
|
||||
"servers, or that the CHIF driver is installed for iLO5 "
|
||||
"and iLO6 based servers.\n"
|
||||
)
|
||||
|
||||
if options.json:
|
||||
content = {"iLOType": ilo_ver}
|
||||
UI().print_out_json(content)
|
||||
else:
|
||||
self.rdmc.ui.printer("iLO Type: %s\n" % ilo_ver)
|
||||
|
||||
return ReturnCodes.SUCCESS
|
||||
|
||||
def detect_local_ilotype(self, options):
|
||||
app_obj = AppAccount(log_dir=self.rdmc.log_dir)
|
||||
security_state_dict = {
|
||||
0: "Error occurred while fetching the security state",
|
||||
1: "Factory",
|
||||
2: "Wipe",
|
||||
3: "Production",
|
||||
4: "HighSecurity",
|
||||
5: "FIPS",
|
||||
6: "SuiteB",
|
||||
}
|
||||
try:
|
||||
ilo_ver, sec_state = self.rdmc.app.getilover_beforelogin(app_obj)
|
||||
if options.json:
|
||||
contents = {"iLOType": str(ilo_ver)}
|
||||
if ilo_ver < 7:
|
||||
contents["SecurityState"] = security_state_dict[sec_state]
|
||||
UI().print_out_json(contents)
|
||||
else:
|
||||
self.rdmc.ui.printer("iLO Type: %s\n" % ilo_ver)
|
||||
if ilo_ver < 7:
|
||||
self.rdmc.ui.printer("Security State: %s\n" % security_state_dict[sec_state])
|
||||
return ReturnCodes.SUCCESS
|
||||
except ChifDriverMissingOrNotFound:
|
||||
if options.json:
|
||||
contents = {"iLOType": "5_6"}
|
||||
UI().print_out_json(contents)
|
||||
else:
|
||||
self.rdmc.ui.printer("iLO Type: Unable to find iLO generation\n")
|
||||
raise
|
||||
except VnicNotEnabledError:
|
||||
ilo_ver = 7
|
||||
if options.json:
|
||||
contents = {"iLOType": str(ilo_ver)}
|
||||
UI().print_out_json(contents)
|
||||
else:
|
||||
self.rdmc.ui.printer("iLO Type: %s\n" % ilo_ver)
|
||||
raise VnicExistsError(
|
||||
"Unable to access iLO using virtual NIC. "
|
||||
"Please ensure virtual NIC is enabled in iLO. "
|
||||
"Ensure that virtual NIC in the host OS is "
|
||||
"configured properly. Refer to documentation for more information.\n"
|
||||
)
|
||||
except Exception:
|
||||
raise GenBeforeLoginError(
|
||||
"An error occurred while retrieving the iLO generation. "
|
||||
"Please ensure that the virtual NIC is enabled for iLO7 based "
|
||||
"servers, or that the CHIF driver is installed for iLO5 and iLO6 "
|
||||
"based servers.\n"
|
||||
)
|
||||
|
||||
def definearguments(self, customparser):
|
||||
"""Wrapper function for new command main function
|
||||
:param customparser: command line input
|
||||
:type customparser: parser.
|
||||
"""
|
||||
if not customparser:
|
||||
return
|
||||
|
||||
self.cmdbase.add_login_arguments_group(customparser)
|
||||
|
||||
customparser.add_argument(
|
||||
"-j",
|
||||
"--json",
|
||||
dest="json",
|
||||
action="store_true",
|
||||
help="Optionally include this flag if you wish to change the"
|
||||
" displayed output to JSON format. Preserving the JSON data"
|
||||
" structure makes the information easier to parse.",
|
||||
default=False,
|
||||
)
|
||||
|
||||
customparser.add_argument(
|
||||
"--ignore_session",
|
||||
dest="ignore_session",
|
||||
action="store_true",
|
||||
help="Optionally include this flag if you wish to ignore any"
|
||||
" session that has been logged in, in order to perform detectilo",
|
||||
default=False,
|
||||
)
|
||||
@@ -0,0 +1,512 @@
|
||||
###
|
||||
# Copyright 2016-2023 Hewlett Packard Enterprise, Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
###
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Get Command for RDMC"""
|
||||
from collections import OrderedDict
|
||||
|
||||
import six
|
||||
import logging
|
||||
|
||||
import redfish.ris
|
||||
from redfish.ris.utils import iterateandclear
|
||||
|
||||
try:
|
||||
from rdmc_helper import (
|
||||
UI,
|
||||
InvalidCommandLineError,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
NoContentsFoundForOperationError,
|
||||
ReturnCodes,
|
||||
)
|
||||
except ImportError:
|
||||
from ilorest.rdmc_helper import (
|
||||
UI,
|
||||
InvalidCommandLineError,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
NoContentsFoundForOperationError,
|
||||
ReturnCodes,
|
||||
)
|
||||
try:
|
||||
from rdmc_helper import HARDCODEDLIST
|
||||
except ImportError:
|
||||
from ilorest.rdmc_helper import HARDCODEDLIST
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GetCommand:
|
||||
"""Constructor"""
|
||||
|
||||
def __init__(self):
|
||||
self.ident = {
|
||||
"name": "get",
|
||||
"usage": None,
|
||||
"description": "To retrieve all"
|
||||
" the properties run without arguments. \n\t*Note*: "
|
||||
"a type will need to be selected or this will return an "
|
||||
"error.\n\texample: get\n\n\tTo retrieve multiple "
|
||||
"properties use the following example\n\texample: "
|
||||
"get Temperatures/ReadingCelsius Fans/Name --selector=Thermal."
|
||||
"\n\n\tTo change output style format provide"
|
||||
" the json flag\n\texample: get --json",
|
||||
"summary": "Displays the current value(s) of a " "property(ies) within a selected type.",
|
||||
"aliases": [],
|
||||
"auxcommands": ["LogoutCommand"],
|
||||
}
|
||||
self.cmdbase = None
|
||||
self.rdmc = None
|
||||
self.auxcommands = dict()
|
||||
|
||||
def run(self, line, help_disp=False):
|
||||
"""Main get worker function
|
||||
|
||||
:param line: command line input
|
||||
:type line: string.
|
||||
"""
|
||||
if help_disp:
|
||||
self.parser.print_help()
|
||||
return ReturnCodes.SUCCESS
|
||||
try:
|
||||
(options, args) = self.rdmc.rdmc_parse_arglist(self, line)
|
||||
except (InvalidCommandLineErrorOPTS, SystemExit):
|
||||
if ("-h" in line) or ("--help" in line):
|
||||
return ReturnCodes.SUCCESS
|
||||
else:
|
||||
raise InvalidCommandLineErrorOPTS("")
|
||||
|
||||
if getattr(options, "json"):
|
||||
self.rdmc.json = True
|
||||
|
||||
selector = options.selector.lower() if options.selector else self.rdmc.app.selector.lower()
|
||||
|
||||
if "securityservice" in selector:
|
||||
self.cmdbase.login_validation(self, options)
|
||||
else:
|
||||
self.getvalidation(options)
|
||||
|
||||
filtr = (None, None)
|
||||
if options.filter:
|
||||
try:
|
||||
if (str(options.filter)[0] == str(options.filter)[-1]) and str(options.filter).startswith(("'", '"')):
|
||||
options.filter = options.filter[1:-1]
|
||||
|
||||
(sel, val) = options.filter.split("=")
|
||||
filtr = (sel.strip(), val.strip())
|
||||
|
||||
except (InvalidCommandLineError, SystemExit):
|
||||
raise InvalidCommandLineError("Invalid filter" " parameter format [filter_attribute]=[filter_value]")
|
||||
|
||||
self.getworkerfunction(
|
||||
args,
|
||||
options,
|
||||
results=None,
|
||||
uselist=True,
|
||||
filtervals=filtr,
|
||||
readonly=options.noreadonly,
|
||||
)
|
||||
|
||||
self.cmdbase.logout_routine(self, options)
|
||||
# Return code
|
||||
return ReturnCodes.SUCCESS
|
||||
|
||||
def getworkerfunction(
|
||||
self,
|
||||
args,
|
||||
options,
|
||||
readonly=False,
|
||||
filtervals=(None, None),
|
||||
results=None,
|
||||
uselist=False,
|
||||
):
|
||||
"""main get worker function
|
||||
|
||||
:param args: command line arguments
|
||||
:type args: list.
|
||||
:param options: command line options
|
||||
:type options: list.
|
||||
:param line: command line input
|
||||
:type line: string.
|
||||
:param readonly: remove readonly properties
|
||||
:type readonly: bool
|
||||
:param filtervals: filter key value pair (Key,Val)
|
||||
:type filtervals: tuple
|
||||
:param results: current results collected
|
||||
:type results: string.
|
||||
:param uselist: use reserved properties list to filter results
|
||||
:type uselist: boolean.
|
||||
"""
|
||||
nocontent = set()
|
||||
instances = None
|
||||
arg = None
|
||||
|
||||
# For rest redfish compatibility of bios.
|
||||
if hasattr(options, "selector") and options.selector:
|
||||
self.rdmc.app.selector = options.selector
|
||||
args = [args] if args and isinstance(args, six.string_types) else args
|
||||
if self.rdmc.app.selector and "." not in self.rdmc.app.selector:
|
||||
self.rdmc.app.selector = self.rdmc.app.selector + "."
|
||||
args = (
|
||||
[
|
||||
(
|
||||
"Attributes/" + arg
|
||||
if self.rdmc.app.selector
|
||||
and self.rdmc.app.selector.lower().startswith("bios.")
|
||||
and not (
|
||||
arg.lower() in ["id", "name", "attributeregistry", "attributes"] or "@odata" in arg.lower()
|
||||
)
|
||||
else arg
|
||||
)
|
||||
for arg in args
|
||||
]
|
||||
if args
|
||||
else args
|
||||
)
|
||||
if filtervals[0]:
|
||||
instances = self.rdmc.app.select(selector=self.rdmc.app.selector, fltrvals=filtervals)
|
||||
|
||||
try:
|
||||
if "securityservice" in self.rdmc.app.selector.lower():
|
||||
url = "/redfish/v1/Managers/1/SecurityService/"
|
||||
LOGGER.info("Fetching SecurityService data from: %s", url)
|
||||
contents = self.rdmc.app.get_handler(url, service=True, silent=True).dict
|
||||
security_contents = []
|
||||
if not args and not options.json:
|
||||
LOGGER.debug("Printing human-readable security service data.")
|
||||
UI().print_out_human_readable(contents)
|
||||
elif options and options.json and contents:
|
||||
LOGGER.debug("Printing JSON security service data.")
|
||||
UI().print_out_json(contents)
|
||||
else:
|
||||
attr = args[0]
|
||||
contents_lower = {k.lower(): v for k, v in contents.items()}
|
||||
security_contents.append({attr: contents_lower[attr.lower()]})
|
||||
if security_contents:
|
||||
UI().print_out_human_readable(security_contents)
|
||||
elif (
|
||||
"componentintegrity"
|
||||
in self.rdmc.app.selector.lower()
|
||||
# or "bios." in self.rdmc.app.selector.lower()
|
||||
):
|
||||
url = ""
|
||||
if "componentintegrity" in self.rdmc.app.selector.lower():
|
||||
url = "/redfish/v1/ComponentIntegrity/?$expand=."
|
||||
# elif "bios." in self.rdmc.app.selector.lower():
|
||||
# url = "/redfish/v1/systems/1/bios/?$expand=."
|
||||
|
||||
LOGGER.info("Fetching %s data from: %s", self.rdmc.app.selector, url)
|
||||
contents = self.get_content(url, args, uselist, options)
|
||||
else:
|
||||
LOGGER.debug("Handling general selector case.")
|
||||
skipnonsettingflag = True
|
||||
if "networkadapter" in self.rdmc.app.selector.lower():
|
||||
skipnonsettingflag = False
|
||||
|
||||
if "selector" in options:
|
||||
LOGGER.info("Fetching properties with selector: %s", options.selector)
|
||||
contents = self.rdmc.app.getprops(
|
||||
props=args,
|
||||
remread=readonly,
|
||||
selector=options.selector,
|
||||
nocontent=nocontent,
|
||||
insts=instances,
|
||||
skipnonsetting=skipnonsettingflag,
|
||||
)
|
||||
|
||||
if "networkadapter" in self.rdmc.app.selector.lower():
|
||||
unique_adapters = {}
|
||||
for entry in contents:
|
||||
# Remove keys @odata.id & Id if it contains "settings"
|
||||
adapter_id = entry.get("Id", "")
|
||||
odata_id = entry.get("@odata.id", "")
|
||||
if "settings" in odata_id.lower() or "settings" in adapter_id.lower():
|
||||
continue
|
||||
# Preventing deduplicates by Id
|
||||
if adapter_id:
|
||||
unique_adapters[adapter_id] = entry
|
||||
|
||||
if unique_adapters:
|
||||
contents = list(unique_adapters.values())
|
||||
|
||||
if (
|
||||
contents
|
||||
and "logentrycollection" in self.rdmc.app.selector.lower()
|
||||
and "@odata.id" in args
|
||||
and not uselist
|
||||
):
|
||||
# as per documentation
|
||||
# collection of LogEntry resource instances
|
||||
log_contents = self.rdmc.app.getprops(
|
||||
props=["entries/@odata.id"],
|
||||
remread=readonly,
|
||||
selector="logservice",
|
||||
nocontent=nocontent,
|
||||
insts=instances,
|
||||
skipnonsetting=skipnonsettingflag,
|
||||
)
|
||||
if log_contents:
|
||||
log_contents = [
|
||||
val["Entries"]
|
||||
for val in log_contents
|
||||
if "Entries" in val and "@odata.id" in val["Entries"]
|
||||
]
|
||||
|
||||
if log_contents:
|
||||
contents.extend(log_contents)
|
||||
# Removing duplicates
|
||||
contents = list({val["@odata.id"]: val for val in contents}.values())
|
||||
|
||||
else:
|
||||
LOGGER.info("Fetching properties without selector.")
|
||||
contents = self.rdmc.app.getprops(
|
||||
props=args, remread=readonly, nocontent=nocontent, insts=instances
|
||||
)
|
||||
uselist = False if readonly else uselist
|
||||
except redfish.ris.rmc_helper.EmptyRaiseForEAFP:
|
||||
LOGGER.error("EmptyRaiseForEAFP exception encountered, retrying getprops without remread.")
|
||||
contents = self.rdmc.app.getprops(props=args, nocontent=nocontent)
|
||||
for ind, content in enumerate(contents):
|
||||
if "bios." in self.rdmc.app.selector.lower() and "Attributes" in list(content.keys()):
|
||||
content.update(content["Attributes"])
|
||||
del content["Attributes"]
|
||||
LOGGER.debug("Flattened BIOS attributes in response.")
|
||||
contents[ind] = OrderedDict(sorted(list(content.items()), key=lambda x: x[0]))
|
||||
if len(args) > 0 and "Members" in args[0]:
|
||||
uselist = False
|
||||
if uselist:
|
||||
for item in contents:
|
||||
self.removereserved(item)
|
||||
if results:
|
||||
LOGGER.info("Returning retrieved contents.")
|
||||
return contents
|
||||
|
||||
contents = contents[0] if len(contents) == 1 else contents
|
||||
|
||||
if options and options.json and contents:
|
||||
LOGGER.debug("Printing output in JSON format.")
|
||||
UI().print_out_json(contents)
|
||||
elif contents:
|
||||
LOGGER.debug("Printing output in human-readable format.")
|
||||
UI().print_out_human_readable(contents)
|
||||
else:
|
||||
try:
|
||||
if nocontent or not any(next(iter(contents))):
|
||||
raise Exception()
|
||||
except Exception:
|
||||
strtoprint = ", ".join(str(val) for val in nocontent)
|
||||
if not strtoprint and arg:
|
||||
strtoprint = arg
|
||||
LOGGER.error("No contents found for entry: %s", strtoprint)
|
||||
raise NoContentsFoundForOperationError("No get contents found for entry: %s" % strtoprint)
|
||||
else:
|
||||
LOGGER.error("No contents found for selected type.")
|
||||
raise NoContentsFoundForOperationError("No get contents found for " "selected type.")
|
||||
if options.logout:
|
||||
LOGGER.info("Logging out.")
|
||||
self.auxcommands["logout"].run("")
|
||||
|
||||
def get_content(self, url, args, uselist, options):
|
||||
"""Get data from url"""
|
||||
contents = self.rdmc.app.get_handler(url, service=True, silent=True).dict
|
||||
if uselist:
|
||||
# for get command removing @odata.* properties
|
||||
args = [arg.lower() for arg in args if "@odata." not in arg.lower()]
|
||||
else:
|
||||
args = [arg.lower() for arg in args]
|
||||
|
||||
if contents and not args:
|
||||
contents = [contents]
|
||||
elif contents and args:
|
||||
collect_data = []
|
||||
for key, value in contents.items():
|
||||
# Collect top-level keys based on args
|
||||
if any(key.lower() == arg for arg in args):
|
||||
collect_data.append({key: value})
|
||||
|
||||
if "attributes" == key.lower() and isinstance(value, dict) and "attributes" not in args:
|
||||
attr_vals = {k.lower(): v for k, v in value.items()}
|
||||
val_dict = {arg: attr_vals[arg.lower()] for arg in args if arg.lower() in attr_vals}
|
||||
if val_dict:
|
||||
collect_data.append(val_dict)
|
||||
|
||||
if key == "Members" and isinstance(value, list):
|
||||
for member in value:
|
||||
# Loop through each dict of Members
|
||||
m_dict = {k.lower(): v for k, v in member.items()}
|
||||
val_dict = {arg: m_dict[arg.lower()] for arg in args if arg.lower() in m_dict}
|
||||
if val_dict:
|
||||
collect_data.append(val_dict)
|
||||
|
||||
# collect_data = [dict(t) for t in {tuple(d.items()) for d in collect_data}]
|
||||
contents = collect_data
|
||||
else:
|
||||
contents = []
|
||||
|
||||
return contents
|
||||
|
||||
def find_key_recursive(self, data, target_key):
|
||||
"""Recursively searches for a key in a nested dictionary (case-insensitive) and returns its value(s)."""
|
||||
target_key_lower = target_key.lower() # Convert target_key to lowercase for case-insensitive matching
|
||||
|
||||
if isinstance(data, dict):
|
||||
for key, value in data.items():
|
||||
if key.lower() == target_key_lower: # Convert dictionary key to lowercase before comparison
|
||||
yield value # Use yield to return multiple matches
|
||||
elif isinstance(value, (dict, list)):
|
||||
yield from self.find_key_recursive(value, target_key)
|
||||
|
||||
elif isinstance(data, list):
|
||||
for item in data:
|
||||
yield from self.find_key_recursive(item, target_key)
|
||||
|
||||
def removereserved(self, entry):
|
||||
"""function to remove reserved properties
|
||||
:param entry: dictionary to remove reserved properties from
|
||||
:type entry: dict.
|
||||
"""
|
||||
|
||||
for key, val in list(entry.items()):
|
||||
if key.lower() in HARDCODEDLIST or "@odata" in key.lower():
|
||||
del entry[key]
|
||||
elif isinstance(val, list):
|
||||
for item in entry[key]:
|
||||
if isinstance(item, dict) and item:
|
||||
self.removereserved(item)
|
||||
if all([True if not test else False for test in entry[key]]):
|
||||
del entry[key]
|
||||
elif isinstance(val, dict):
|
||||
self.removereserved(val)
|
||||
if all([True if not test else False for test in entry[key]]):
|
||||
del entry[key]
|
||||
|
||||
def checktoprint(self, options, contents, nocontent, arg):
|
||||
"""function to decide what/how to print
|
||||
:param options: list of options
|
||||
:type options: list.
|
||||
:param contents: dictionary value returned by getprops.
|
||||
:type contents: dict.
|
||||
:param nocontent: props not found are added to the list.
|
||||
:type nocontent: list.
|
||||
:param arg: string of args
|
||||
:type arg: string
|
||||
"""
|
||||
if options and options.json and contents:
|
||||
self.rdmc.ui.print_out_json(contents)
|
||||
elif contents:
|
||||
self.rdmc.ui.print_out_human_readable(contents)
|
||||
else:
|
||||
try:
|
||||
if nocontent or not any(next(iter(contents))):
|
||||
raise Exception()
|
||||
except Exception:
|
||||
strtoprint = ", ".join(str(val) for val in nocontent)
|
||||
if not strtoprint and arg:
|
||||
strtoprint = arg
|
||||
raise NoContentsFoundForOperationError("No get contents " "found for entry: %s" % strtoprint)
|
||||
else:
|
||||
raise NoContentsFoundForOperationError("No get contents " "found for selected type.")
|
||||
|
||||
def collectandclear(self, contents, key, values):
|
||||
"""function to find and remove unneeded values from contents dictionary
|
||||
:param contents: dictionary value returned by getprops
|
||||
:type contents: dict.
|
||||
:param key: string of keys
|
||||
:type key: string.
|
||||
:param values: list of values
|
||||
:type values: list.
|
||||
"""
|
||||
clearcontent = contents[0][key]
|
||||
if isinstance(clearcontent, dict):
|
||||
keyslist = list(clearcontent.keys())
|
||||
else:
|
||||
keyslist = [clearcontent]
|
||||
clearedlist = keyslist
|
||||
for arg in values:
|
||||
for keys in keyslist:
|
||||
if str(keys).lower() == str(arg).lower():
|
||||
clearedlist.remove(arg)
|
||||
contents = iterateandclear(contents, clearedlist)
|
||||
return contents
|
||||
|
||||
def getvalidation(self, options):
|
||||
"""get method validation function
|
||||
|
||||
:param options: command line options
|
||||
:type options: list.
|
||||
"""
|
||||
self.cmdbase.login_select_validation(self, options)
|
||||
|
||||
def definearguments(self, customparser):
|
||||
"""Wrapper function for new command main function
|
||||
|
||||
:param customparser: command line input
|
||||
:type customparser: parser.
|
||||
"""
|
||||
if not customparser:
|
||||
return
|
||||
|
||||
self.cmdbase.add_login_arguments_group(customparser)
|
||||
|
||||
customparser.add_argument(
|
||||
"--selector",
|
||||
dest="selector",
|
||||
help="Optionally include this flag to select a type to run"
|
||||
" the current command on. Use this flag when you wish to"
|
||||
" select a type without entering another command, or if you"
|
||||
" wish to work with a type that is different from the one"
|
||||
" you currently have selected.",
|
||||
default=None,
|
||||
)
|
||||
|
||||
customparser.add_argument(
|
||||
"--filter",
|
||||
dest="filter",
|
||||
help="Optionally set a filter value for a filter attribute."
|
||||
" This uses the provided filter for the currently selected"
|
||||
" type. Note: Use this flag to narrow down your results. For"
|
||||
" example, selecting a common type might return multiple"
|
||||
" objects that are all of that type. If you want to modify"
|
||||
" the properties of only one of those objects, use the filter"
|
||||
" flag to narrow down results based on properties."
|
||||
"\t\t\t\t\t Usage: --filter [ATTRIBUTE]=[VALUE]",
|
||||
default=None,
|
||||
)
|
||||
customparser.add_argument(
|
||||
"-j",
|
||||
"--json",
|
||||
dest="json",
|
||||
action="store_true",
|
||||
help="Optionally include this flag if you wish to change the"
|
||||
" displayed output to JSON format. Preserving the JSON data"
|
||||
" structure makes the information easier to parse.",
|
||||
default=False,
|
||||
)
|
||||
customparser.add_argument(
|
||||
"--noreadonly",
|
||||
dest="noreadonly",
|
||||
action="store_true",
|
||||
help="Optionally include this flag if you wish to only show"
|
||||
" properties that are not read-only. This is useful to see what "
|
||||
"is configurable with the selected type(s).",
|
||||
default=False,
|
||||
)
|
||||
customparser.add_argument(
|
||||
"--refresh",
|
||||
dest="ref",
|
||||
action="store_true",
|
||||
help="Optionally reload the data of selected type and clear " "patches from current selection.",
|
||||
default=False,
|
||||
)
|
||||
@@ -0,0 +1,183 @@
|
||||
###
|
||||
# Copyright 2016-2021 Hewlett Packard Enterprise, Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
###
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Info Command for RDMC"""
|
||||
|
||||
try:
|
||||
from rdmc_helper import (
|
||||
InfoMissingEntriesError,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
ReturnCodes,
|
||||
)
|
||||
except ImportError:
|
||||
from ilorest.rdmc_helper import (
|
||||
InfoMissingEntriesError,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
ReturnCodes,
|
||||
)
|
||||
|
||||
try:
|
||||
from rdmc_helper import HARDCODEDLIST
|
||||
except:
|
||||
from ilorest.rdmc_helper import HARDCODEDLIST
|
||||
|
||||
|
||||
class InfoCommand:
|
||||
"""Constructor"""
|
||||
|
||||
def __init__(self):
|
||||
self.ident = {
|
||||
"name": "info",
|
||||
"usage": None,
|
||||
"description": "Displays detailed "
|
||||
"information about a property within a selected type"
|
||||
"\n\texample: info property\n\n\tDisplays detailed "
|
||||
"information for several properties\n\twithin a selected "
|
||||
"type\n\texample: info property property/sub-property property\n\n\t"
|
||||
"Run without arguments to display properties \n\tthat "
|
||||
"are available for info command\n\texample: info",
|
||||
"summary": "Displays detailed information about a property within a selected type.",
|
||||
"aliases": [],
|
||||
"auxcommands": [],
|
||||
}
|
||||
|
||||
self.cmdbase = None
|
||||
self.rdmc = None
|
||||
self.auxcommands = dict()
|
||||
|
||||
def run(self, line, autotest=False, help_disp=False):
|
||||
"""Main info worker function
|
||||
|
||||
:param line: command line input
|
||||
:type line: string.
|
||||
:param autotest: flag to determine if running automatictesting
|
||||
:type autotest: bool.
|
||||
"""
|
||||
if help_disp:
|
||||
self.parser.print_help()
|
||||
return ReturnCodes.SUCCESS
|
||||
try:
|
||||
(options, args) = self.rdmc.rdmc_parse_arglist(self, line)
|
||||
except (InvalidCommandLineErrorOPTS, SystemExit):
|
||||
if ("-h" in line) or ("--help" in line):
|
||||
return ReturnCodes.SUCCESS
|
||||
else:
|
||||
raise InvalidCommandLineErrorOPTS("")
|
||||
|
||||
self.infovalidation(options)
|
||||
|
||||
if args:
|
||||
for item in args:
|
||||
if self.rdmc.app.selector.lower().startswith("bios.") and "attributes" not in item.lower():
|
||||
if not (item.lower() in HARDCODEDLIST or "@odata" in item.lower()):
|
||||
item = "Attributes/" + item
|
||||
|
||||
outdata = self.rdmc.app.info(props=item, dumpjson=options.json, latestschema=options.latestschema)
|
||||
|
||||
if autotest:
|
||||
return outdata
|
||||
if outdata and options.json:
|
||||
self.rdmc.ui.print_out_json(outdata)
|
||||
elif outdata:
|
||||
self.rdmc.ui.printer(outdata)
|
||||
|
||||
if not outdata:
|
||||
raise InfoMissingEntriesError("There are no valid " "entries for info in the current instance.")
|
||||
else:
|
||||
if len(args) > 1 and not item == args[-1]:
|
||||
self.rdmc.ui.printer("\n************************************" "**************\n")
|
||||
else:
|
||||
results = set()
|
||||
instances = self.rdmc.app.select()
|
||||
for instance in instances:
|
||||
currdict = instance.resp.dict
|
||||
currdict = (
|
||||
currdict["Attributes"]
|
||||
if instance.maj_type.startswith(self.rdmc.app.typepath.defs.biostype)
|
||||
and currdict.get("Attributes", None)
|
||||
else currdict
|
||||
)
|
||||
results.update([key for key in currdict if key not in HARDCODEDLIST and "@odata" not in key.lower()])
|
||||
|
||||
if results and autotest:
|
||||
return results
|
||||
elif results:
|
||||
self.rdmc.ui.printer("Info options:\n")
|
||||
for item in results:
|
||||
self.rdmc.ui.printer("%s\n" % item)
|
||||
else:
|
||||
raise InfoMissingEntriesError(
|
||||
"No info items available for this selected type." " Try running with the --latestschema flag."
|
||||
)
|
||||
|
||||
self.cmdbase.logout_routine(self, options)
|
||||
# Return code
|
||||
return ReturnCodes.SUCCESS
|
||||
|
||||
def infovalidation(self, options):
|
||||
"""Info method validation function
|
||||
|
||||
:param options: command line options
|
||||
:type options: list.
|
||||
"""
|
||||
|
||||
if self.rdmc.opts.latestschema:
|
||||
options.latestschema = True
|
||||
|
||||
self.cmdbase.login_select_validation(self, options)
|
||||
|
||||
def definearguments(self, customparser):
|
||||
"""Wrapper function for new command main function
|
||||
|
||||
:param customparser: command line input
|
||||
:type customparser: parser.
|
||||
"""
|
||||
if not customparser:
|
||||
return
|
||||
|
||||
self.cmdbase.add_login_arguments_group(customparser)
|
||||
|
||||
customparser.add_argument(
|
||||
"--selector",
|
||||
dest="selector",
|
||||
help="Optionally include this flag to select a type to run"
|
||||
" the current command on. Use this flag when you wish to"
|
||||
" select a type without entering another command, or if you"
|
||||
" wish to work with a type that is different from the one"
|
||||
" you currently have selected.",
|
||||
default=None,
|
||||
)
|
||||
|
||||
customparser.add_argument(
|
||||
"-j",
|
||||
"--json",
|
||||
dest="json",
|
||||
action="store_true",
|
||||
help="Optionally include this flag if you wish to change the"
|
||||
" displayed output to JSON format. Preserving the JSON data"
|
||||
" structure makes the information easier to parse.",
|
||||
default=False,
|
||||
)
|
||||
customparser.add_argument(
|
||||
"--latestschema",
|
||||
dest="latestschema",
|
||||
action="store_true",
|
||||
help="Optionally use the latest schema instead of the one "
|
||||
"requested by the file. Note: May cause errors in some data "
|
||||
"retrieval due to difference in schema versions.",
|
||||
default=None,
|
||||
)
|
||||
@@ -0,0 +1,180 @@
|
||||
###
|
||||
# Copyright 2016-2021 Hewlett Packard Enterprise, Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
###
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
"""List Command for RDMC"""
|
||||
|
||||
try:
|
||||
from rdmc_helper import (
|
||||
UI,
|
||||
InvalidCommandLineError,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
ReturnCodes,
|
||||
)
|
||||
except ImportError:
|
||||
from ilorest.rdmc_helper import (
|
||||
UI,
|
||||
InvalidCommandLineError,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
ReturnCodes,
|
||||
)
|
||||
|
||||
|
||||
class ListCommand:
|
||||
"""Constructor"""
|
||||
|
||||
def __init__(self):
|
||||
self.ident = {
|
||||
"name": "list",
|
||||
"usage": None,
|
||||
"description": "Displays the current values of the "
|
||||
"properties within\n\ta selected type including"
|
||||
" reserved properties\n\texample: list\n\n\tNOTE: If "
|
||||
"you wish to not list all the reserved properties\n\t "
|
||||
" run the get command instead",
|
||||
"summary": "Displays the current value(s) of a"
|
||||
" property(ies) within a selected type including"
|
||||
" reserved properties.",
|
||||
"aliases": ["ls"],
|
||||
"auxcommands": ["GetCommand"],
|
||||
}
|
||||
self.cmdbase = None
|
||||
self.rdmc = None
|
||||
self.auxcommands = dict()
|
||||
|
||||
def run(self, line, help_disp=False):
|
||||
"""Wrapper function for main list function
|
||||
|
||||
:param line: command line input
|
||||
:type line: string.
|
||||
"""
|
||||
if help_disp:
|
||||
self.parser.print_help()
|
||||
return ReturnCodes.SUCCESS
|
||||
try:
|
||||
(options, args) = self.rdmc.rdmc_parse_arglist(self, line)
|
||||
except (InvalidCommandLineErrorOPTS, SystemExit):
|
||||
if ("-h" in line) or ("--help" in line):
|
||||
return ReturnCodes.SUCCESS
|
||||
else:
|
||||
raise InvalidCommandLineErrorOPTS("")
|
||||
|
||||
selector = options.selector.lower() if options.selector else self.rdmc.app.selector.lower()
|
||||
|
||||
if "securityservice" in selector:
|
||||
self.cmdbase.login_validation(self, options)
|
||||
else:
|
||||
self.listvalidation(options)
|
||||
|
||||
fvals = (None, None)
|
||||
|
||||
if options.filter:
|
||||
try:
|
||||
if (str(options.filter)[0] == str(options.filter)[-1]) and str(options.filter).startswith(("'", '"')):
|
||||
options.filter = options.filter[1:-1]
|
||||
|
||||
(sel, val) = options.filter.split("=")
|
||||
fvals = (sel.strip(), val.strip())
|
||||
except:
|
||||
raise InvalidCommandLineError("Invalid filter" " parameter format [filter_attribute]=[filter_value]")
|
||||
if options.selector:
|
||||
if "storagecontroller." in options.selector.lower():
|
||||
options.selector = "storagecontrollercollection"
|
||||
self.rdmc.app.selector = options.selector
|
||||
elif self.rdmc.app.selector:
|
||||
options.selector = self.rdmc.app.selector
|
||||
if "securityservice" in options.selector.lower():
|
||||
url = "/redfish/v1/Managers/1/SecurityService/"
|
||||
contents = self.rdmc.app.get_handler(url, service=True, silent=True).dict
|
||||
security_contents = []
|
||||
|
||||
if options and options.json and contents:
|
||||
UI().print_out_json(contents)
|
||||
elif not args:
|
||||
UI().print_out_human_readable(contents)
|
||||
else:
|
||||
attr = args[0]
|
||||
contents_lower = {k.lower(): v for k, v in contents.items()}
|
||||
security_contents.append({attr: contents_lower[attr.lower()]})
|
||||
if security_contents:
|
||||
UI().print_out_human_readable(security_contents)
|
||||
else:
|
||||
self.auxcommands["get"].getworkerfunction(args, options, filtervals=fvals, uselist=False)
|
||||
|
||||
self.cmdbase.logout_routine(self, options)
|
||||
# Return code
|
||||
return ReturnCodes.SUCCESS
|
||||
|
||||
def listvalidation(self, options):
|
||||
"""List data validation function
|
||||
|
||||
:param options: command line options
|
||||
:type options: list.
|
||||
"""
|
||||
self.cmdbase.login_select_validation(self, options)
|
||||
|
||||
def definearguments(self, customparser):
|
||||
"""Wrapper function for new command main function
|
||||
|
||||
:param customparser: command line input
|
||||
:type customparser: parser.
|
||||
"""
|
||||
if not customparser:
|
||||
return
|
||||
|
||||
self.cmdbase.add_login_arguments_group(customparser)
|
||||
|
||||
customparser.add_argument(
|
||||
"--selector",
|
||||
dest="selector",
|
||||
help="Optionally include this flag to select a type to run"
|
||||
" the current command on. Use this flag when you wish to"
|
||||
" select a type without entering another command, or if you"
|
||||
" wish to work with a type that is different from the one"
|
||||
" you currently have selected.",
|
||||
default=None,
|
||||
)
|
||||
|
||||
customparser.add_argument(
|
||||
"--filter",
|
||||
dest="filter",
|
||||
help="Optionally set a filter value for a filter attribute."
|
||||
" This uses the provided filter for the currently selected"
|
||||
" type. Note: Use this flag to narrow down your results. For"
|
||||
" example, selecting a common type might return multiple"
|
||||
" objects that are all of that type. If you want to modify"
|
||||
" the properties of only one of those objects, use the filter"
|
||||
" flag to narrow down results based on properties."
|
||||
"\t\t\t\t\t Usage: --filter [ATTRIBUTE]=[VALUE]",
|
||||
default=None,
|
||||
)
|
||||
customparser.add_argument(
|
||||
"-j",
|
||||
"--json",
|
||||
dest="json",
|
||||
action="store_true",
|
||||
help="Optionally include this flag if you wish to change the"
|
||||
" displayed output to JSON format. Preserving the JSON data"
|
||||
" structure makes the information easier to parse.",
|
||||
default=False,
|
||||
)
|
||||
customparser.add_argument(
|
||||
"--refresh",
|
||||
dest="ref",
|
||||
action="store_true",
|
||||
help="Optionally reload the data of selected type and clear " "patches from current selection.",
|
||||
default=False,
|
||||
)
|
||||
@@ -0,0 +1,569 @@
|
||||
###
|
||||
# Copyright 2016-2023 Hewlett Packard Enterprise, Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
###
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Load Command for RDMC"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import shlex
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
from six.moves import queue
|
||||
|
||||
import redfish.ris
|
||||
from redfish.ris.rmc_helper import LoadSkipSettingError
|
||||
|
||||
try:
|
||||
from rdmc_helper import (
|
||||
Encryption,
|
||||
InvalidCommandLineError,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
InvalidFileFormattingError,
|
||||
InvalidFileInputError,
|
||||
InvalidMSCfileInputError,
|
||||
MultipleServerConfigError,
|
||||
NoChangesFoundOrMadeError,
|
||||
ReturnCodes,
|
||||
)
|
||||
except ImportError:
|
||||
from ilorest.rdmc_helper import (
|
||||
Encryption,
|
||||
InvalidCommandLineError,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
InvalidFileFormattingError,
|
||||
InvalidFileInputError,
|
||||
InvalidMSCfileInputError,
|
||||
MultipleServerConfigError,
|
||||
NoChangesFoundOrMadeError,
|
||||
ReturnCodes,
|
||||
)
|
||||
|
||||
try:
|
||||
from rdmc_helper import HARDCODEDLIST
|
||||
except:
|
||||
from ilorest.rdmc_helper import HARDCODEDLIST
|
||||
|
||||
# default file name
|
||||
__filename__ = "ilorest.json"
|
||||
|
||||
|
||||
class LoadCommand:
|
||||
"""Constructor"""
|
||||
|
||||
def __init__(self):
|
||||
self.ident = {
|
||||
"name": "load",
|
||||
"usage": None,
|
||||
"description": "Run to load the default configuration"
|
||||
" file\n\texample: load\n\n\tLoad configuration file from a "
|
||||
"different file\n\tif any property values have changed, the "
|
||||
"changes are committed and the user is logged out of the server"
|
||||
"\n\n\texample: load -f output.json\n\n\tLoad configurations to "
|
||||
"multiple servers\n\texample: load -m mpfilename.txt -f output."
|
||||
"json\n\n\tNote: multiple server file format (1 server per new "
|
||||
"line)\n\t--url <iLO url/hostname> -u admin -p password\n\t--url"
|
||||
" <iLO url/hostname> -u admin -p password\n\t--url <iLO url/"
|
||||
"hostname> -u admin -p password",
|
||||
"summary": "Loads the server configuration settings from a file.",
|
||||
"aliases": [],
|
||||
"auxcommands": ["CommitCommand", "SelectCommand", "RawPatchCommand"],
|
||||
}
|
||||
self.filenames = None
|
||||
self.mpfilename = None
|
||||
self.queue = queue.Queue()
|
||||
self.cmdbase = None
|
||||
self.rdmc = None
|
||||
self.auxcommands = dict()
|
||||
|
||||
def securebootremovereadonly(self, tmp):
|
||||
templist = [
|
||||
"SecureBootCurrentBoot",
|
||||
"@odata.etag",
|
||||
"Id",
|
||||
"AutoNeg",
|
||||
"FQDN",
|
||||
"FullDuplex",
|
||||
"HostName",
|
||||
"IPv6Addresses",
|
||||
"IPv6DefaultGateway",
|
||||
"LinkStatus",
|
||||
"MaxIPv6StaticAddresses",
|
||||
"Name",
|
||||
"NameServers",
|
||||
"PermanentMACAddress",
|
||||
"ConfigurationSettings",
|
||||
"InterfaceType",
|
||||
"NICSupportsIPv6",
|
||||
"DomainName",
|
||||
"IPV6",
|
||||
"DNSServers",
|
||||
"MACAddress",
|
||||
"VLAN",
|
||||
"SpeedMbps",
|
||||
"DateTime",
|
||||
]
|
||||
remove_data = self.rdmc.app.removereadonlyprops(tmp, False, True, templist)
|
||||
return remove_data
|
||||
|
||||
def run(self, line, help_disp=False):
|
||||
"""Main load worker function
|
||||
|
||||
:param line: command line input
|
||||
:type line: string.
|
||||
"""
|
||||
if help_disp:
|
||||
self.parser.print_help()
|
||||
return ReturnCodes.SUCCESS
|
||||
try:
|
||||
(options, _) = self.rdmc.rdmc_parse_arglist(self, line)
|
||||
except (InvalidCommandLineErrorOPTS, SystemExit):
|
||||
if ("-h" in line) or ("--help" in line):
|
||||
return ReturnCodes.SUCCESS
|
||||
else:
|
||||
raise InvalidCommandLineErrorOPTS("")
|
||||
|
||||
self.loadvalidation(options)
|
||||
returnvalue = False
|
||||
|
||||
if options.mpfilename:
|
||||
self.rdmc.ui.printer("Loading configuration for multiple servers...\n")
|
||||
else:
|
||||
self.rdmc.ui.printer("Loading configuration...\n")
|
||||
|
||||
for files in self.filenames:
|
||||
if not os.path.isfile(files):
|
||||
raise InvalidFileInputError(
|
||||
"File '%s' doesn't exist. Please create file by running save command." % files
|
||||
)
|
||||
if options.encryption:
|
||||
with open(files, "rb") as myfile:
|
||||
data = myfile.read()
|
||||
data = Encryption().decrypt_file(data, options.encryption)
|
||||
loadcontents = json.loads(data)
|
||||
else:
|
||||
try:
|
||||
with open(files, "r") as myfile:
|
||||
loadcontents = json.load(myfile)
|
||||
except:
|
||||
raise InvalidFileFormattingError("Invalid file formatting found in file %s" % files)
|
||||
|
||||
if options.mpfilename:
|
||||
mfile = options.mpfilename
|
||||
outputdir = None
|
||||
|
||||
if options.outdirectory:
|
||||
outputdir = options.outdirectory
|
||||
|
||||
if self.runmpfunc(mpfile=mfile, lfile=files, outputdir=outputdir):
|
||||
return ReturnCodes.SUCCESS
|
||||
else:
|
||||
raise MultipleServerConfigError("One or more servers failed to load given configuration.")
|
||||
|
||||
results = False
|
||||
eth_conf = False
|
||||
validation_errs = []
|
||||
|
||||
for loadcontent in loadcontents:
|
||||
for content, loaddict in loadcontent.items():
|
||||
inputlist = list()
|
||||
|
||||
if content == "Comments":
|
||||
continue
|
||||
|
||||
if "EthernetInterface" in content:
|
||||
if options.force_network_config:
|
||||
import platform
|
||||
import tempfile
|
||||
|
||||
patchpath = "/redfish/v1/Managers/1/EthernetInterfaces/1/"
|
||||
|
||||
try:
|
||||
payload = loadcontent[content][patchpath]
|
||||
except KeyError:
|
||||
continue
|
||||
|
||||
payload = loadcontent[content][patchpath]
|
||||
remove_odata = self.securebootremovereadonly(payload)
|
||||
payload.update(remove_odata)
|
||||
if "StaticNameServers" in payload:
|
||||
payload["StaticNameServers"] = [
|
||||
item for item in payload["StaticNameServers"] if item != "::"
|
||||
]
|
||||
tempdir = "/tmp" if platform.system() == "Darwin" else tempfile.gettempdir()
|
||||
temp_file = os.path.join(tempdir, "temp_patch.json")
|
||||
out_file = open(temp_file, "w")
|
||||
patch_payload = {patchpath: payload}
|
||||
json.dump(patch_payload, out_file, indent=6)
|
||||
out_file.close()
|
||||
self.auxcommands["rawpatch"].run(temp_file + " --service")
|
||||
os.remove(temp_file)
|
||||
eth_conf = True
|
||||
continue
|
||||
else:
|
||||
self.rdmc.ui.printer(
|
||||
"Skipping network configurations as" " --force_network_config is not included.\n"
|
||||
)
|
||||
continue
|
||||
|
||||
inputlist.append(content)
|
||||
if options.biospassword:
|
||||
inputlist.extend(["--biospassword", options.biospassword])
|
||||
|
||||
self.auxcommands["select"].selectfunction(inputlist)
|
||||
if self.rdmc.app.selector.lower() not in content.lower():
|
||||
raise InvalidCommandLineError("Selector not found.\n")
|
||||
|
||||
try:
|
||||
for _, items in loaddict.items():
|
||||
remove_odata = self.securebootremovereadonly(items)
|
||||
items.update(remove_odata)
|
||||
try:
|
||||
if self.rdmc.app.loadset(
|
||||
seldict=items,
|
||||
latestschema=options.latestschema,
|
||||
uniqueoverride=options.uniqueoverride,
|
||||
):
|
||||
results = True
|
||||
except LoadSkipSettingError:
|
||||
returnvalue = True
|
||||
results = True
|
||||
except:
|
||||
raise
|
||||
except redfish.ris.ValidationError as excp:
|
||||
errs = excp.get_errors()
|
||||
validation_errs.append({self.rdmc.app.selector: errs})
|
||||
except:
|
||||
raise
|
||||
|
||||
try:
|
||||
if results:
|
||||
self.auxcommands["commit"].commitfunction(options=options)
|
||||
reboot_needed = False
|
||||
for n in inputlist:
|
||||
n = n.lower()
|
||||
if "bios" in n or "boot" in n or "iscsi" in n:
|
||||
reboot_needed = True
|
||||
if reboot_needed:
|
||||
self.rdmc.ui.printer("Reboot is required for settings to take effect.\n")
|
||||
except NoChangesFoundOrMadeError as excp:
|
||||
if returnvalue:
|
||||
pass
|
||||
else:
|
||||
raise excp
|
||||
|
||||
if validation_errs:
|
||||
for validation_err in validation_errs:
|
||||
for err_type in validation_err:
|
||||
self.rdmc.ui.error("Validation error(s) in type %s:\n" % err_type)
|
||||
for err in validation_err[err_type]:
|
||||
if isinstance(err, redfish.ris.RegistryValidationError):
|
||||
self.rdmc.ui.error(err.message)
|
||||
try:
|
||||
if err.reg:
|
||||
self.rdmc.ui.error(str(err.sel))
|
||||
except:
|
||||
pass
|
||||
raise redfish.ris.ValidationError()
|
||||
|
||||
if not results:
|
||||
if eth_conf:
|
||||
continue
|
||||
else:
|
||||
self.rdmc.ui.printer("No differences found from current configuration.\n")
|
||||
|
||||
# Return code
|
||||
if returnvalue:
|
||||
return ReturnCodes.LOAD_SKIP_SETTING_ERROR
|
||||
|
||||
return ReturnCodes.SUCCESS
|
||||
|
||||
def loadvalidation(self, options):
|
||||
"""Load method validation function
|
||||
|
||||
:param options: command line options
|
||||
:type options: list.
|
||||
"""
|
||||
|
||||
if self.rdmc.opts.latestschema:
|
||||
options.latestschema = True
|
||||
|
||||
try:
|
||||
self.cmdbase.login_validation(self, options)
|
||||
except Exception:
|
||||
if options.mpfilename:
|
||||
pass
|
||||
else:
|
||||
raise
|
||||
|
||||
# filename validations and checks
|
||||
if options.filename:
|
||||
self.filenames = options.filename
|
||||
elif self.rdmc.config:
|
||||
if self.rdmc.config.defaultloadfilename:
|
||||
self.filenames = [self.rdmc.config.defaultloadfilename]
|
||||
|
||||
if not self.filenames:
|
||||
self.filenames = [__filename__]
|
||||
|
||||
def verify_file(self, filedata, inputfile):
|
||||
"""Function used to handle oddly named files and convert to JSON
|
||||
|
||||
:param filedata: input file data
|
||||
:type filedata: string.
|
||||
:param inputfile: current input file
|
||||
:type inputfile: string.
|
||||
"""
|
||||
try:
|
||||
tempholder = json.loads(filedata)
|
||||
return tempholder
|
||||
except:
|
||||
raise InvalidFileFormattingError("Invalid file formatting found in file %s" % inputfile)
|
||||
|
||||
def get_current_selector(self, path=None):
|
||||
"""Returns current selected content minus hard coded list
|
||||
|
||||
:param path: current path
|
||||
:type path: string.
|
||||
"""
|
||||
contents = self.rdmc.app.monolith.path[path]
|
||||
|
||||
if not contents:
|
||||
contents = list()
|
||||
|
||||
for content in contents:
|
||||
for k in list(content.keys()):
|
||||
if k.lower() in HARDCODEDLIST or "@odata" in k.lower():
|
||||
del content[k]
|
||||
|
||||
return contents
|
||||
|
||||
def runmpfunc(self, mpfile=None, lfile=None, outputdir=None):
|
||||
"""Main worker function for multi file command
|
||||
|
||||
:param mpfile: configuration file
|
||||
:type mpfile: string.
|
||||
:param lfile: custom file name
|
||||
:type lfile: string.
|
||||
:param outputdir: custom output directory
|
||||
:type outputdir: string.
|
||||
"""
|
||||
# self.logoutobj.run("")
|
||||
data = self.validatempfile(mpfile=mpfile, lfile=lfile)
|
||||
|
||||
if not data:
|
||||
return False
|
||||
|
||||
processes = []
|
||||
finalreturncode = True
|
||||
outputform = "%Y-%m-%d-%H-%M-%S"
|
||||
|
||||
if outputdir:
|
||||
if outputdir.endswith(('"', "'")) and outputdir.startswith(('"', "'")):
|
||||
outputdir = outputdir[1:-1]
|
||||
|
||||
if not os.path.isdir(outputdir):
|
||||
self.rdmc.ui.error("The give output folder path does not exist.\n")
|
||||
raise InvalidCommandLineErrorOPTS("")
|
||||
|
||||
dirpath = outputdir
|
||||
else:
|
||||
dirpath = os.getcwd()
|
||||
|
||||
dirname = "%s_%s" % (datetime.now().strftime(outputform), "MSClogs")
|
||||
createdir = os.path.join(dirpath, dirname)
|
||||
os.mkdir(createdir)
|
||||
|
||||
oofile = open(os.path.join(createdir, "CompleteOutputfile.txt"), "w+")
|
||||
self.rdmc.ui.printer("Create multiple processes to load configuration " "concurrently to all servers...\n")
|
||||
|
||||
while True:
|
||||
if not self.queue.empty():
|
||||
line = self.queue.get()
|
||||
else:
|
||||
break
|
||||
|
||||
finput = "\n" + "Output for " + line[line.index("--url") + 1] + ": \n\n"
|
||||
urlvar = line[line.index("--url") + 1]
|
||||
|
||||
if "python" in os.path.basename(sys.executable.lower()):
|
||||
# If we are running from source we have to add the python file to the command
|
||||
listargforsubprocess = [sys.executable, sys.argv[0]] + line
|
||||
else:
|
||||
listargforsubprocess = [sys.executable] + line
|
||||
|
||||
if os.name != "nt":
|
||||
listargforsubprocess = " ".join(listargforsubprocess)
|
||||
|
||||
urlfilename = urlvar.split("//")[-1]
|
||||
logfile = open(os.path.join(createdir, urlfilename + ".txt"), "w+")
|
||||
pinput = subprocess.Popen(listargforsubprocess, shell=True, stdout=logfile, stderr=logfile)
|
||||
|
||||
processes.append((pinput, finput, urlfilename, logfile))
|
||||
|
||||
for pinput, finput, urlfilename, logfile in processes:
|
||||
pinput.wait()
|
||||
returncode = pinput.returncode
|
||||
finalreturncode = finalreturncode and not returncode
|
||||
|
||||
logfile.close()
|
||||
logfile = open(os.path.join(createdir, urlfilename + ".txt"), "r+")
|
||||
oofile.write(finput + str(logfile.read()))
|
||||
oofile.write("-x+x-" * 16)
|
||||
logfile.close()
|
||||
|
||||
if returncode == 0:
|
||||
self.rdmc.ui.printer("Loading Configuration for {} : SUCCESS\n".format(urlfilename))
|
||||
else:
|
||||
self.rdmc.ui.error("Loading Configuration for {} : FAILED\n".format(urlfilename))
|
||||
self.rdmc.ui.error(
|
||||
"ILOREST return code : {}.\nFor more details please check "
|
||||
"{}.txt under {} directory.\n".format(returncode, urlfilename, createdir)
|
||||
)
|
||||
|
||||
oofile.close()
|
||||
|
||||
if finalreturncode:
|
||||
self.rdmc.ui.printer("All servers have been successfully configured.\n")
|
||||
|
||||
return finalreturncode
|
||||
|
||||
def validatempfile(self, mpfile=None, lfile=None):
|
||||
"""Validate temporary file
|
||||
|
||||
:param mpfile: configuration file
|
||||
:type mpfile: string.
|
||||
:param lfile: custom file name
|
||||
:type lfile: string.
|
||||
"""
|
||||
self.rdmc.ui.printer("Checking given server information...\n")
|
||||
|
||||
if not mpfile:
|
||||
return False
|
||||
|
||||
if not os.path.isfile(mpfile):
|
||||
raise InvalidFileInputError(
|
||||
"File '%s' doesn't exist, please " "create file by running save command." % mpfile
|
||||
)
|
||||
|
||||
try:
|
||||
with open(mpfile, "r") as myfile:
|
||||
data = list()
|
||||
cmdtorun = ["load"]
|
||||
cmdargs = ["-f", str(lfile)]
|
||||
globalargs = ["-v", "--nocache"]
|
||||
|
||||
while True:
|
||||
line = myfile.readline()
|
||||
|
||||
if not line:
|
||||
break
|
||||
|
||||
if line.endswith(os.linesep):
|
||||
line.rstrip(os.linesep)
|
||||
|
||||
args = shlex.split(line, posix=False)
|
||||
|
||||
if len(args) < 5:
|
||||
self.rdmc.ui.error("Incomplete data in input file: {}\n".format(line))
|
||||
raise InvalidMSCfileInputError("Please verify the " "contents of the %s file" % mpfile)
|
||||
else:
|
||||
linelist = globalargs + cmdtorun + args + cmdargs
|
||||
line = str(line).replace("\n", "")
|
||||
self.queue.put(linelist)
|
||||
data.append(linelist)
|
||||
except Exception as excp:
|
||||
raise excp
|
||||
|
||||
if data:
|
||||
return data
|
||||
|
||||
return False
|
||||
|
||||
def definearguments(self, customparser):
|
||||
"""Wrapper function for new command main function
|
||||
|
||||
:param customparser: command line input
|
||||
:type customparser: parser.
|
||||
"""
|
||||
if not customparser:
|
||||
return
|
||||
|
||||
self.cmdbase.add_login_arguments_group(customparser)
|
||||
|
||||
customparser.add_argument(
|
||||
"-f",
|
||||
"--filename",
|
||||
dest="filename",
|
||||
help="Use this flag if you wish to use a different"
|
||||
" filename than the default one. The default filename is"
|
||||
" %s." % __filename__,
|
||||
action="append",
|
||||
default=None,
|
||||
)
|
||||
customparser.add_argument(
|
||||
"-m",
|
||||
"--multiprocessing",
|
||||
dest="mpfilename",
|
||||
help="""use the provided filename to obtain data""",
|
||||
default=None,
|
||||
)
|
||||
customparser.add_argument(
|
||||
"--outputdirectory",
|
||||
dest="outdirectory",
|
||||
help="""use the provided directory to output data for multiple server configuration""",
|
||||
default=None,
|
||||
)
|
||||
customparser.add_argument(
|
||||
"--latestschema",
|
||||
dest="latestschema",
|
||||
action="store_true",
|
||||
help="Optionally use the latest schema instead of the one "
|
||||
"requested by the file. Note: May cause errors in some data "
|
||||
"retrieval due to difference in schema versions.",
|
||||
default=None,
|
||||
)
|
||||
customparser.add_argument(
|
||||
"--uniqueoverride",
|
||||
dest="uniqueoverride",
|
||||
action="store_true",
|
||||
help="Override the measures stopping the tool from writing " "over items that are system unique.",
|
||||
default=False,
|
||||
)
|
||||
customparser.add_argument(
|
||||
"--encryption",
|
||||
dest="encryption",
|
||||
help="Optionally include this flag to encrypt/decrypt a file " "using the key provided.",
|
||||
default=None,
|
||||
)
|
||||
customparser.add_argument(
|
||||
"--reboot",
|
||||
dest="reboot",
|
||||
help="Use this flag to perform a reboot command function after"
|
||||
" completion of operations. For help with parameters and"
|
||||
" descriptions regarding the reboot flag, run help reboot.",
|
||||
default=None,
|
||||
)
|
||||
customparser.add_argument(
|
||||
"--force_network_config",
|
||||
dest="force_network_config",
|
||||
help="Use this flag to force set network configuration."
|
||||
"Network settings will be skipped if the flag is not included.",
|
||||
action="store_true",
|
||||
default=None,
|
||||
)
|
||||
@@ -0,0 +1,582 @@
|
||||
###
|
||||
# Copyright 2016-2021 Hewlett Packard Enterprise, Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
###
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Login Command for RDMC"""
|
||||
|
||||
import getpass
|
||||
import os
|
||||
import socket
|
||||
import redfish.ris
|
||||
from redfish.hpilo.vnichpilo import AppAccount
|
||||
from redfish.rest.connections import ChifDriverMissingOrNotFound, VnicNotEnabledError
|
||||
import requests
|
||||
from requests.exceptions import SSLError, RequestException
|
||||
import platform
|
||||
from argparse import SUPPRESS
|
||||
|
||||
try:
|
||||
from rdmc_helper import (
|
||||
Encryption,
|
||||
LOGGER,
|
||||
InvalidCommandLineError,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
PathUnavailableError,
|
||||
ReturnCodes,
|
||||
UsernamePasswordRequiredError,
|
||||
VnicExistsError,
|
||||
VnicLoginError,
|
||||
InactiveAppAccountTokenError,
|
||||
NoAppAccountError,
|
||||
GenBeforeLoginError,
|
||||
AppAccountExistsError,
|
||||
)
|
||||
except ModuleNotFoundError:
|
||||
from ilorest.rdmc_helper import (
|
||||
ReturnCodes,
|
||||
LOGGER,
|
||||
InvalidCommandLineError,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
PathUnavailableError,
|
||||
Encryption,
|
||||
UsernamePasswordRequiredError,
|
||||
VnicExistsError,
|
||||
VnicLoginError,
|
||||
InactiveAppAccountTokenError,
|
||||
NoAppAccountError,
|
||||
GenBeforeLoginError,
|
||||
AppAccountExistsError,
|
||||
)
|
||||
|
||||
from redfish.rest.v1 import ServerDownOrUnreachableError
|
||||
|
||||
|
||||
class LoginCommand:
|
||||
"""Constructor"""
|
||||
|
||||
def __init__(self):
|
||||
self.ident = {
|
||||
"name": "login",
|
||||
"usage": None,
|
||||
"description": "To login remotely run using iLO url and iLO credentials"
|
||||
"\n\texample: login <iLO url/hostname> -u <iLO username> "
|
||||
"-p <iLO password>\n\n\tTo login on a local server run without "
|
||||
"arguments\n\texample: login"
|
||||
"\n\n\tTo login through VNIC run using --force_vnic and iLO credentials "
|
||||
"\n\texample: login --force_vnic -u <iLO username> -p <iLO password>"
|
||||
"\n\nLogin using OTP can be done in 2 ways."
|
||||
"\n\n\t To login implicitly, use the tag --wait_for_otp."
|
||||
"\n\t\texample: login -u <iLO username> -p <iLO password> --wait_for_otp"
|
||||
"\n\n\n\t To login explicitly, use the tag -o/--otp and enter OTP after."
|
||||
"\n\t\texample: login -u <iLO username> -p <iLO password> -o <iLO OTP>"
|
||||
"\n\n\tNOTE: A [URL] can be specified with "
|
||||
"an IPv4, IPv6, or hostname address.",
|
||||
"summary": "Connects to a server, establishes a secure session," " and discovers data from iLO.",
|
||||
"aliases": [],
|
||||
"auxcommands": ["LogoutCommand"],
|
||||
"cert_data": {},
|
||||
}
|
||||
self.cmdbase = None
|
||||
self.rdmc = None
|
||||
self.url = None
|
||||
self.username = None
|
||||
self.password = None
|
||||
self.sessionid = None
|
||||
self.biospassword = None
|
||||
self.auxcommands = dict()
|
||||
self.cert_data = dict()
|
||||
self.login_otp = None
|
||||
self.ilo_gen = 6
|
||||
|
||||
def run(self, line, help_disp=False):
|
||||
"""wrapper function for main login function
|
||||
|
||||
:param line: command line input
|
||||
:type line: string.
|
||||
:param help_disp: flag to determine to display or not
|
||||
:type help_disp: boolean
|
||||
"""
|
||||
if help_disp:
|
||||
self.parser.print_help()
|
||||
return ReturnCodes.SUCCESS
|
||||
try:
|
||||
self.loginfunction(line)
|
||||
|
||||
if ("-h" in line) or ("--help" in line):
|
||||
return ReturnCodes.SUCCESS
|
||||
|
||||
if not self.rdmc.app.monolith._visited_urls:
|
||||
self.auxcommands["logout"].run("")
|
||||
raise PathUnavailableError("The path specified by the --path flag is unavailable.")
|
||||
except Exception:
|
||||
raise
|
||||
|
||||
# Return code
|
||||
return ReturnCodes.SUCCESS
|
||||
|
||||
def perform_login(self, options, skipbuild, user_ca_cert_data, args, app_obj):
|
||||
|
||||
ilo_ver = self.ilo_gen
|
||||
if ilo_ver < 7 or (ilo_ver >= 7 and (options.usechif or options.noapptoken or args)):
|
||||
login_response = self.rdmc.app.login(
|
||||
username=self.username,
|
||||
password=self.password,
|
||||
sessionid=self.sessionid,
|
||||
base_url=self.url,
|
||||
path=options.path,
|
||||
skipbuild=skipbuild,
|
||||
includelogs=options.includelogs,
|
||||
biospassword=self.biospassword,
|
||||
is_redfish=self.rdmc.opts.is_redfish,
|
||||
proxy=self.rdmc.opts.proxy,
|
||||
user_ca_cert_data=user_ca_cert_data,
|
||||
json_out=self.rdmc.json,
|
||||
login_otp=self.login_otp,
|
||||
log_dir=self.rdmc.log_dir,
|
||||
)
|
||||
else:
|
||||
if options.hostappname or options.hostappid or options.salt:
|
||||
if not (options.hostappname and options.hostappid and options.salt):
|
||||
raise InvalidCommandLineError("Please enter all the necessary host application information.\n")
|
||||
|
||||
# Code to check if vnic is enabled.
|
||||
vnic_enabled = self.rdmc.app.vexists(app_obj)
|
||||
if not vnic_enabled:
|
||||
raise VnicExistsError(
|
||||
"Unable to access iLO using virtual NIC. "
|
||||
"Please ensure virtual NIC is enabled in iLO. "
|
||||
"Ensure that virtual NIC in the host OS is "
|
||||
"configured properly. Refer to documentation for more information.\n"
|
||||
)
|
||||
|
||||
# To check if appaccount exists. If not, error out.
|
||||
try:
|
||||
apptoken_exists = self.rdmc.app.token_exists(app_obj)
|
||||
except Exception as excp:
|
||||
raise AppAccountExistsError("Error occurred while checking if app account exists.\n")
|
||||
|
||||
# If appaccount doesn't exist
|
||||
if not apptoken_exists:
|
||||
raise NoAppAccountError(
|
||||
"The app account is not available for this host application. "
|
||||
"Please retry using the --no_app_account option or generate "
|
||||
"an application account using the appaccount create command.\n"
|
||||
)
|
||||
|
||||
try:
|
||||
# Function will log in, retrieve session id, call build monolith, .save()
|
||||
login_response = self.rdmc.app.vnic_login(
|
||||
app_obj=app_obj,
|
||||
path=options.path,
|
||||
skipbuild=skipbuild,
|
||||
includelogs=options.includelogs,
|
||||
json_out=self.rdmc.json,
|
||||
base_url=self.url,
|
||||
username=self.username,
|
||||
password=self.password,
|
||||
log_dir=self.rdmc.log_dir,
|
||||
login_otp=self.login_otp,
|
||||
is_redfish=self.rdmc.opts.is_redfish,
|
||||
proxy=self.rdmc.opts.proxy,
|
||||
user_ca_cert_data=user_ca_cert_data,
|
||||
biospassword=self.biospassword,
|
||||
sessionid=self.sessionid,
|
||||
)
|
||||
except redfish.hpilo.vnichpilo.InactiveAppAccountTokenError:
|
||||
LOGGER.error("Login failed due to an inactive or expired App Account token.")
|
||||
raise InactiveAppAccountTokenError("Login failed due to an inactive or expired App Account token.")
|
||||
except Exception as excp:
|
||||
error_msg = """Error occurred while performing login using app account.
|
||||
Check if application account exists using 'appaccount details' command.
|
||||
Otherwise, try with --no_app_account option.\n"""
|
||||
LOGGER.error(error_msg)
|
||||
raise VnicLoginError(error_msg)
|
||||
|
||||
if options.session_id and login_response and hasattr(login_response, "_auth_key"):
|
||||
self.rdmc.ui.printer(f"\nSessionID:{login_response._auth_key}\n\n")
|
||||
|
||||
def loginfunction(self, line, skipbuild=None, json_out=False):
|
||||
"""Main worker function for login class
|
||||
|
||||
:param line: entered command line
|
||||
:type line: list.
|
||||
:param skipbuild: flag to determine if monolith should be build
|
||||
:type skipbuild: boolean.
|
||||
:param json_out: flag to determine if json output neededd
|
||||
:type skipbuild: boolean.
|
||||
"""
|
||||
try:
|
||||
(options, args) = self.rdmc.rdmc_parse_arglist(self, line)
|
||||
except (InvalidCommandLineErrorOPTS, SystemExit):
|
||||
if ("-h" in line) or ("--help" in line):
|
||||
return ReturnCodes.SUCCESS
|
||||
else:
|
||||
raise InvalidCommandLineError("Invalid command line arguments")
|
||||
|
||||
if platform.system() == "Darwin":
|
||||
# Mac OS
|
||||
app_obj = None
|
||||
self.ilo_gen = 6
|
||||
else:
|
||||
app_obj = AppAccount(
|
||||
appname=options.hostappname,
|
||||
appid=options.hostappid,
|
||||
salt=options.salt,
|
||||
username=options.user,
|
||||
password=options.password,
|
||||
log_dir=self.rdmc.log_dir,
|
||||
)
|
||||
|
||||
self.ilo_gen = self.get_ilover_beforelogin(args=args, app_obj=app_obj, options=options)
|
||||
|
||||
self.loginvalidation(options=options, args=args, app_obj=app_obj)
|
||||
|
||||
# if proxy server provided in command line as --useproxy, it will be used,
|
||||
# otherwise it will the environment variable setting.
|
||||
# else proxy will be set as None.
|
||||
if self.rdmc.opts.proxy:
|
||||
_ = self.rdmc.opts.proxy
|
||||
elif "https_proxy" in os.environ and os.environ["https_proxy"]:
|
||||
_ = os.environ["https_proxy"]
|
||||
elif "http_proxy" in os.environ and os.environ["http_proxy"]:
|
||||
_ = os.environ["http_proxy"]
|
||||
else:
|
||||
_ = self.rdmc.config.proxy
|
||||
|
||||
no_bundle = False
|
||||
|
||||
if getattr(options, "ca_cert_bundle", False):
|
||||
user_ca_cert_data = {"ca_certs": options.ca_cert_bundle}
|
||||
else:
|
||||
user_ca_cert_data = {}
|
||||
if getattr(options, "user_certificate", False):
|
||||
no_bundle = True
|
||||
user_ca_cert_data.update({"cert_file": options.user_certificate})
|
||||
if getattr(options, "user_root_ca_key", False):
|
||||
no_bundle = True
|
||||
user_ca_cert_data.update({"key_file": options.user_root_ca_key})
|
||||
if getattr(options, "user_root_ca_password", False):
|
||||
no_bundle = True
|
||||
user_ca_cert_data.update({"key_password": options.user_root_ca_password})
|
||||
|
||||
if not no_bundle:
|
||||
if hasattr(user_ca_cert_data, "ca_certs"):
|
||||
user_ca_cert_data.pop("ca_certs")
|
||||
|
||||
try:
|
||||
if getattr(options, "force_vnic", False):
|
||||
self.rdmc.ui.printer("\nAttempt to login with Vnic...\n")
|
||||
try:
|
||||
sock = socket.create_connection((args[0], 443))
|
||||
if sock:
|
||||
sock.close
|
||||
except:
|
||||
pass
|
||||
|
||||
self.sessionid = options.sessionid
|
||||
self.login_otp = options.login_otp
|
||||
|
||||
if self.url and "blobstore" in self.url and (options.waitforOTP or options.login_otp):
|
||||
options.waitforOTP = None
|
||||
options.login_otp = None
|
||||
self.rdmc.ui.printer(
|
||||
"Warning: For local inband mode, TFA is not supported, options --wait_for_otp "
|
||||
"and --otp will be ignored\n"
|
||||
)
|
||||
|
||||
if options.waitforOTP:
|
||||
try:
|
||||
self.perform_login(options, skipbuild, user_ca_cert_data, args, app_obj)
|
||||
except redfish.rest.connections.OneTimePasscodeError:
|
||||
self.rdmc.ui.printer("One Time Passcode Sent to registered email.\n")
|
||||
ans = input("Enter OTP: ")
|
||||
self.login_otp = ans
|
||||
self.perform_login(options, skipbuild, user_ca_cert_data, args, app_obj)
|
||||
else:
|
||||
self.perform_login(options, skipbuild, user_ca_cert_data, args, app_obj)
|
||||
except ServerDownOrUnreachableError as excp:
|
||||
self.rdmc.ui.printer("The following error occurred during login: '%s'\n" % str(excp.__class__.__name__))
|
||||
|
||||
self.username = None
|
||||
self.password = None
|
||||
|
||||
# Warning for cache enabled, since we save session in plain text
|
||||
if not self.rdmc.encoding:
|
||||
self.rdmc.ui.warn("Cache is activated. Session keys are stored in plaintext.")
|
||||
|
||||
if self.rdmc.opts.debug:
|
||||
self.rdmc.ui.warn("Logger is activated. Logging is stored in plaintext.")
|
||||
|
||||
if options.selector:
|
||||
try:
|
||||
self.rdmc.app.select(selector=options.selector)
|
||||
|
||||
if self.rdmc.opts.verbose:
|
||||
self.rdmc.ui.printer(("Selected option: '%s'\n" % options.selector))
|
||||
except Exception as excp:
|
||||
raise redfish.ris.InstanceNotFoundError(excp)
|
||||
|
||||
def loginvalidation(self, options, args, app_obj):
|
||||
"""Login helper function for login validations
|
||||
|
||||
:param options: command line options
|
||||
:type options: list.
|
||||
:param args: command line arguments
|
||||
:type args: list.
|
||||
"""
|
||||
# Fill user name/password from config file
|
||||
if not options.user:
|
||||
options.user = self.rdmc.config.username
|
||||
if not options.password:
|
||||
options.password = self.rdmc.config.password
|
||||
if not hasattr(options, "user_certificate"):
|
||||
options.user_certificate = self.rdmc.config.user_cert
|
||||
if not hasattr(options, "user_root_ca_key"):
|
||||
options.user_root_ca_key = self.rdmc.config.user_root_ca_key
|
||||
if not hasattr(options, "user_root_ca_password"):
|
||||
options.user_root_ca_password = self.rdmc.config.user_root_ca_password
|
||||
|
||||
ilo_ver = self.ilo_gen
|
||||
|
||||
if (
|
||||
options.user
|
||||
and not options.password
|
||||
and (
|
||||
not hasattr(options, "user_certificate")
|
||||
or not hasattr(options, "user_root_ca_key")
|
||||
or hasattr(options, "user_root_ca_password")
|
||||
)
|
||||
):
|
||||
# Option for interactive entry of password
|
||||
tempinput = getpass.getpass().rstrip()
|
||||
if tempinput:
|
||||
options.password = tempinput
|
||||
else:
|
||||
raise InvalidCommandLineError("Empty or invalid password was entered.")
|
||||
|
||||
if options.user:
|
||||
self.username = options.user
|
||||
|
||||
if options.password:
|
||||
self.password = options.password
|
||||
|
||||
if options.encode:
|
||||
self.username = Encryption.decode_credentials(self.username).decode("utf-8")
|
||||
self.password = Encryption.decode_credentials(self.password).decode("utf-8")
|
||||
|
||||
if options.biospassword:
|
||||
self.biospassword = options.biospassword
|
||||
|
||||
if ilo_ver >= 7:
|
||||
if not args:
|
||||
if self.username and self.password and not options.noapptoken and not options.usechif:
|
||||
options.noapptoken = True
|
||||
if options.noapptoken:
|
||||
if (
|
||||
not self.username or not self.password
|
||||
): # Add another check to see if username and password is present in environment variables
|
||||
raise UsernamePasswordRequiredError(
|
||||
"Please enter username and password in order to login without app account.\n"
|
||||
)
|
||||
options.force_vnic = True
|
||||
|
||||
# Assignment of url in case no url is entered
|
||||
if getattr(options, "force_vnic", False):
|
||||
if not (getattr(options, "ca_cert_bundle", False) or getattr(options, "user_certificate", False)):
|
||||
if not (self.username and self.password) and not options.sessionid:
|
||||
raise UsernamePasswordRequiredError("Please provide credentials to login with virtual NIC.\n")
|
||||
self.url = "https://16.1.15.1"
|
||||
else:
|
||||
if ilo_ver >= 7 and not options.usechif:
|
||||
# TO DO
|
||||
# self.url = self.rdmc.app.GetIPAddress()
|
||||
self.url = "https://16.1.15.1"
|
||||
else:
|
||||
self.url = "blobstore://."
|
||||
|
||||
if args:
|
||||
# Any argument should be treated as an URL
|
||||
self.url = args[0]
|
||||
|
||||
# Verify that URL is properly formatted for https://
|
||||
if "https://" not in self.url:
|
||||
self.url = "https://" + self.url
|
||||
|
||||
if not (
|
||||
hasattr(options, "user_certificate")
|
||||
or hasattr(options, "user_root_ca_key")
|
||||
or hasattr(options, "user_root_ca_password")
|
||||
):
|
||||
if not (options.user and options.password):
|
||||
raise InvalidCommandLineError("Empty username or password was entered.")
|
||||
else:
|
||||
# Check to see if there is a URL in config file
|
||||
if self.rdmc.config.url:
|
||||
self.url = self.rdmc.config.url
|
||||
|
||||
def get_ilover_beforelogin(self, args, app_obj, options):
|
||||
"""
|
||||
Attempts to retrieve the iLO version before login.
|
||||
|
||||
:param args: List of command-line arguments; expects iLO IP/hostname at index 0.
|
||||
:param app_obj: App object for fallback retrieval if args is empty.
|
||||
:param options: Options object, may include flags like 'force_vnic' or 'usechif'.
|
||||
:return: iLO version as an integer.
|
||||
:raises: GenBeforeLoginError, VnicExistsError, ChifDriverMissingOrNotFound, VnicNotEnabledError
|
||||
"""
|
||||
ip = path = None # Initialize to avoid UnboundLocalError
|
||||
try:
|
||||
if args:
|
||||
ip = args[0]
|
||||
path = f"https://{ip}/redfish/v1"
|
||||
|
||||
response = requests.get(path, verify=False, timeout=10)
|
||||
response.raise_for_status()
|
||||
|
||||
try:
|
||||
json_data = response.json()
|
||||
oem_data = json_data.get("Oem", {}).get("Hpe") or json_data.get("Oem", {}).get("Hp")
|
||||
if not oem_data:
|
||||
raise KeyError("Oem->Hpe or Oem->Hp block missing in response.")
|
||||
|
||||
manager = oem_data.get("Manager", [{}])[0]
|
||||
manager_type = manager.get("ManagerType")
|
||||
|
||||
if manager_type:
|
||||
ilo_ver = int(manager_type.split(" ")[1])
|
||||
else:
|
||||
moniker = oem_data.get("Moniker", {})
|
||||
prodgen = moniker.get("PRODGEN")
|
||||
if not prodgen:
|
||||
raise KeyError("PRODGEN key not found in Moniker.")
|
||||
ilo_ver = int(prodgen.split(" ")[1])
|
||||
except (KeyError, ValueError, IndexError) as e:
|
||||
raise GenBeforeLoginError(
|
||||
f"Failed to parse iLO version from response. Error: {e}\n"
|
||||
"Ensure the iLO firmware is Redfish-compliant and responds correctly.\n"
|
||||
)
|
||||
else:
|
||||
ilo_ver, _ = self.rdmc.app.getilover_beforelogin(app_obj)
|
||||
|
||||
return ilo_ver
|
||||
|
||||
except ChifDriverMissingOrNotFound:
|
||||
if getattr(options, "force_vnic", False):
|
||||
return 5
|
||||
raise
|
||||
|
||||
except VnicNotEnabledError:
|
||||
if getattr(options, "usechif", False):
|
||||
return 7
|
||||
raise VnicExistsError(
|
||||
"Unable to access iLO using virtual NIC.\n"
|
||||
"Please ensure that virtual NIC is enabled in iLO and "
|
||||
"properly configured in the host OS.\n"
|
||||
"Refer to the documentation for setup instructions.\n"
|
||||
)
|
||||
|
||||
except SSLError:
|
||||
raise GenBeforeLoginError(
|
||||
f"SSL Error: Unable to connect to the server at {ip or '[unknown IP]'}.\n"
|
||||
"Please verify the iLO IP and try accessing the GUI.\n"
|
||||
)
|
||||
|
||||
except RequestException as e:
|
||||
raise GenBeforeLoginError(
|
||||
f"Connection Error: Could not retrieve data from {path or '[unknown path]'}.\n" f"Details: {e}\n"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
raise GenBeforeLoginError(
|
||||
f"An unexpected error occurred while retrieving the iLO version.\n"
|
||||
f"Details: {e}\n"
|
||||
"Verify if virtual NIC is enabled for iLO7 or that the CHIF driver "
|
||||
"is installed for iLO5 and iLO6 based servers.\n"
|
||||
)
|
||||
|
||||
def definearguments(self, customparser):
|
||||
"""Wrapper function for new command main function
|
||||
|
||||
:param customparser: command line input
|
||||
:type customparser: parser.
|
||||
"""
|
||||
|
||||
def remove_argument(parser, arg):
|
||||
for action in parser._actions:
|
||||
opts = action.option_strings
|
||||
if (opts and opts[0] == arg) or action.dest == arg:
|
||||
parser._remove_action(action)
|
||||
break
|
||||
|
||||
for action in parser._action_groups:
|
||||
for group_action in action._group_actions:
|
||||
opts = group_action.option_strings
|
||||
if (opts and opts[0] == arg) or group_action.dest == arg:
|
||||
action._group_actions.remove(group_action)
|
||||
return
|
||||
|
||||
if not customparser:
|
||||
return
|
||||
|
||||
customparser.add_argument(
|
||||
"--wait_for_otp",
|
||||
dest="waitforOTP",
|
||||
help="Optionally include this flag to implicitly wait for OTP.",
|
||||
action="store_true",
|
||||
default=None,
|
||||
)
|
||||
self.cmdbase.add_login_arguments_group(customparser)
|
||||
remove_argument(customparser, "url")
|
||||
customparser.add_argument(
|
||||
"--selector",
|
||||
dest="selector",
|
||||
help="Optionally include this flag to select a type to run"
|
||||
" the current command on. Use this flag when you wish to"
|
||||
" select a type without entering another command, or if you"
|
||||
" wish to work with a type that is different from the one"
|
||||
" you currently have selected.",
|
||||
default=None,
|
||||
)
|
||||
customparser.add_argument(
|
||||
"--no_app_token",
|
||||
"--no_app_account",
|
||||
dest="noapptoken",
|
||||
help="Include this parameter in order to login to iLO7 and above with credentials and not app account.",
|
||||
default=None,
|
||||
action="store_true",
|
||||
)
|
||||
customparser.add_argument("--hostappid", dest="hostappid", help="Parameter to specify hostappid", default=None)
|
||||
customparser.add_argument(
|
||||
"--hostappname", dest="hostappname", help="Parameter to specify hostappname", default=None
|
||||
)
|
||||
customparser.add_argument(
|
||||
"--salt", dest="salt", help="Parameter to specify application owned salt", default=None
|
||||
)
|
||||
customparser.add_argument(
|
||||
"--use_chif",
|
||||
dest="usechif",
|
||||
help="Include this parameter in order to operate iLO7 and above using chif.",
|
||||
default=None,
|
||||
action="store_true",
|
||||
)
|
||||
customparser.add_argument(
|
||||
"--show_session_id",
|
||||
"-s",
|
||||
dest="session_id",
|
||||
help=SUPPRESS,
|
||||
default=None,
|
||||
action="store_true",
|
||||
)
|
||||
@@ -0,0 +1,79 @@
|
||||
###
|
||||
# Copyright 2016-2021 Hewlett Packard Enterprise, Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
###
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Logout Command for RDMC"""
|
||||
|
||||
try:
|
||||
from rdmc_helper import InvalidCommandLineErrorOPTS, ReturnCodes
|
||||
except ImportError:
|
||||
from ilorest.rdmc_helper import InvalidCommandLineErrorOPTS, ReturnCodes
|
||||
|
||||
|
||||
class LogoutCommand:
|
||||
"""Constructor"""
|
||||
|
||||
def __init__(self):
|
||||
self.ident = {
|
||||
"name": "logout",
|
||||
"usage": None,
|
||||
"description": "Run to end the current session and disconnect" " from the server\n\tExample: logout",
|
||||
"summary": "Ends the current session and disconnects from the server.",
|
||||
"aliases": [],
|
||||
"auxcommands": [],
|
||||
}
|
||||
self.cmdbase = None
|
||||
self.rdmc = None
|
||||
|
||||
def logoutfunction(self, line):
|
||||
"""Main logout worker function
|
||||
|
||||
:param line: command line input
|
||||
:type line: string.
|
||||
"""
|
||||
try:
|
||||
(_, _) = self.rdmc.rdmc_parse_arglist(self, line)
|
||||
except (InvalidCommandLineErrorOPTS, SystemExit):
|
||||
if ("-h" in line) or ("--help" in line):
|
||||
return ReturnCodes.SUCCESS
|
||||
else:
|
||||
raise InvalidCommandLineErrorOPTS("")
|
||||
|
||||
self.rdmc.app.logout("")
|
||||
|
||||
def run(self, line, help_disp=False):
|
||||
"""Wrapper function for main logout function
|
||||
|
||||
:param line: command line input
|
||||
:type line: string.
|
||||
"""
|
||||
if help_disp:
|
||||
self.parser.print_help()
|
||||
return ReturnCodes.SUCCESS
|
||||
self.rdmc.ui.printer("Logging session out.\n")
|
||||
self.logoutfunction(line)
|
||||
|
||||
# Return code
|
||||
return ReturnCodes.SUCCESS
|
||||
|
||||
def definearguments(self, customparser):
|
||||
"""Wrapper function for new command main function
|
||||
|
||||
:param customparser: command line input
|
||||
:type customparser: parser.
|
||||
"""
|
||||
if not customparser:
|
||||
return
|
||||
+201
@@ -0,0 +1,201 @@
|
||||
###
|
||||
# Copyright 2016-2021 Hewlett Packard Enterprise, Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
###
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Results Command for rdmc"""
|
||||
|
||||
import copy
|
||||
import json
|
||||
import sys
|
||||
|
||||
import jsondiff
|
||||
|
||||
try:
|
||||
from rdmc_helper import HARDCODEDLIST
|
||||
except:
|
||||
from ilorest.rdmc_helper import HARDCODEDLIST
|
||||
try:
|
||||
from rdmc_helper import (
|
||||
InvalidCommandLineError,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
ReturnCodes,
|
||||
)
|
||||
except ImportError:
|
||||
from ilorest.rdmc_helper import (
|
||||
InvalidCommandLineError,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
ReturnCodes,
|
||||
)
|
||||
|
||||
|
||||
class PendingChangesCommand:
|
||||
"""PendingChanges class command"""
|
||||
|
||||
def __init__(self):
|
||||
self.ident = {
|
||||
"name": "pending",
|
||||
"usage": None,
|
||||
"description": "Run to show pending committed changes "
|
||||
"that will be applied after a reboot.\n\texample: pending",
|
||||
"summary": "Show the pending changes that will be applied on reboot.",
|
||||
"aliases": [],
|
||||
"auxcommands": [],
|
||||
}
|
||||
|
||||
self.cmdbase = None
|
||||
self.rdmc = None
|
||||
self.auxcommands = dict()
|
||||
|
||||
def run(self, line, help_disp=False):
|
||||
"""Show pending changes of settings objects
|
||||
|
||||
:param line: string of arguments passed in
|
||||
:type line: str.
|
||||
"""
|
||||
if help_disp:
|
||||
self.parser.print_help()
|
||||
return ReturnCodes.SUCCESS
|
||||
try:
|
||||
(options, args) = self.rdmc.rdmc_parse_arglist(self, line)
|
||||
except (InvalidCommandLineErrorOPTS, SystemExit):
|
||||
if ("-h" in line) or ("--help" in line):
|
||||
return ReturnCodes.SUCCESS
|
||||
else:
|
||||
raise InvalidCommandLineErrorOPTS("")
|
||||
|
||||
if args:
|
||||
raise InvalidCommandLineError("Pending command does not take any arguments.")
|
||||
self.pendingvalidation(options)
|
||||
|
||||
self.pendingfunction()
|
||||
sys.stdout.write("\n")
|
||||
self.cmdbase.logout_routine(self, options)
|
||||
return ReturnCodes.SUCCESS
|
||||
|
||||
def pendingfunction(self):
|
||||
"""Main pending command worker function"""
|
||||
settingsuri = []
|
||||
ignorekeys = ["@odata.id", "@odata.etag", "@redfish.settings", "oem"]
|
||||
ignoreuri = [str("hpsut*")]
|
||||
ignorekeys.extend(HARDCODEDLIST)
|
||||
|
||||
resourcedir = self.rdmc.app.get_handler(self.rdmc.app.monolith._resourcedir, service=True, silent=True)
|
||||
|
||||
for resource in resourcedir.dict["Instances"]:
|
||||
if (resource["@odata.id"].split("/").__len__() - 1) > 4:
|
||||
splitstr = resource["@odata.id"].split("/")[5]
|
||||
for element in ignoreuri:
|
||||
if "/settings" in resource["@odata.id"] and not self.wildcard_str_match(element, splitstr):
|
||||
settingsuri.append(resource["@odata.id"])
|
||||
|
||||
self.rdmc.ui.printer("Current Pending Changes:\n")
|
||||
|
||||
for uri in settingsuri:
|
||||
diffprint = {}
|
||||
baseuri = uri.split("settings")[0]
|
||||
|
||||
base = self.rdmc.app.get_handler(baseuri, service=True, silent=True)
|
||||
settings = self.rdmc.app.get_handler(uri, service=True, silent=True)
|
||||
|
||||
typestring = self.rdmc.app.monolith.typepath.defs.typestring
|
||||
currenttype = ".".join(base.dict[typestring].split("#")[-1].split(".")[:-1])
|
||||
|
||||
differences = json.loads(jsondiff.diff(base.dict, settings.dict, syntax="symmetric", dump=True))
|
||||
|
||||
diffprint = self.recursdict(differences, ignorekeys)
|
||||
|
||||
self.rdmc.ui.printer("\n%s:" % currenttype)
|
||||
if not diffprint:
|
||||
self.rdmc.ui.printer("\nNo pending changes found.\n")
|
||||
else:
|
||||
self.rdmc.ui.pretty_human_readable(diffprint)
|
||||
|
||||
def wildcard_str_match(self, first, second):
|
||||
"""
|
||||
Recursive function for determining match between two strings. Accounts
|
||||
for wildcard characters
|
||||
|
||||
:param first: comparison string (may contain '*' or '?' for wildcards)
|
||||
:param type: str (unicode)
|
||||
:param second: string value to be compared (must not contain '*' or '?')
|
||||
:param type: str (unicode)
|
||||
"""
|
||||
|
||||
if not first and not second:
|
||||
return True
|
||||
if len(first) > 1 and first[0] == "*" and not second:
|
||||
return False
|
||||
if (len(first) > 1 and first[0] == "?") or (first and second and first[0] == second[0]):
|
||||
return self.wildcard_str_match(first[1:], second[1:])
|
||||
if first and first[0] == "*":
|
||||
return self.wildcard_str_match(first[1:], second) or self.wildcard_str_match(first, second[1:])
|
||||
|
||||
return False
|
||||
|
||||
def recursdict(self, diff, ignorekeys):
|
||||
"""Recursively get dict ready for printing
|
||||
|
||||
:param diff: diff dict
|
||||
:type options: dict.
|
||||
"""
|
||||
diffprint = copy.deepcopy(diff)
|
||||
for item in diff:
|
||||
if item.lower() in ignorekeys:
|
||||
diffprint.pop(item)
|
||||
elif item == "$delete":
|
||||
for ditem in diff[item]:
|
||||
if isinstance(diff[item], list):
|
||||
continue
|
||||
if isinstance(diff[item][ditem], dict):
|
||||
diffprint[item].pop(ditem)
|
||||
if ditem.lower() in ignorekeys or ditem.isdigit():
|
||||
continue
|
||||
else:
|
||||
diffprint.update({"removed": ditem})
|
||||
diffprint.pop(item)
|
||||
elif item == "$insert":
|
||||
for ditem in diff[item]:
|
||||
del diffprint[item][diffprint[item].index(ditem)]
|
||||
diffprint.update({"changed index position": ditem[1]})
|
||||
diffprint.pop(item)
|
||||
elif isinstance(diff[item], dict):
|
||||
diffprint[item] = self.recursdict(diff[item], ignorekeys)
|
||||
|
||||
elif isinstance(diff[item], list):
|
||||
diffprint.update({item: {"Current": diff[item][0], "Pending": diff[item][1]}})
|
||||
else:
|
||||
continue
|
||||
|
||||
return diffprint
|
||||
|
||||
def pendingvalidation(self, options):
|
||||
"""Pending method validation function
|
||||
|
||||
:param options: command line options
|
||||
:type options: list.
|
||||
"""
|
||||
self.cmdbase.login_select_validation(self, options)
|
||||
|
||||
def definearguments(self, customparser):
|
||||
"""Wrapper function for new command main function
|
||||
|
||||
:param customparser: command line input
|
||||
:type customparser: parser.
|
||||
"""
|
||||
if not customparser:
|
||||
return
|
||||
|
||||
self.cmdbase.add_login_arguments_group(customparser)
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
###
|
||||
# Copyright 2016-2021 Hewlett Packard Enterprise, Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
###
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Exit Command for rdmc"""
|
||||
|
||||
import sys
|
||||
|
||||
try:
|
||||
from rdmc_helper import InvalidCommandLineErrorOPTS, ReturnCodes
|
||||
except ImportError:
|
||||
from ilorest.rdmc_helper import InvalidCommandLineErrorOPTS, ReturnCodes
|
||||
|
||||
|
||||
class ExitCommand:
|
||||
"""Exit class to handle exiting from interactive mode"""
|
||||
|
||||
def __init__(self):
|
||||
self.ident = {
|
||||
"name": "exit",
|
||||
"usage": None,
|
||||
"description": "Run to exit from the interactive shell\n\texample: exit",
|
||||
"summary": "Exits from the interactive shell.",
|
||||
"aliases": ["quit"],
|
||||
"auxcommands": ["LogoutCommand"],
|
||||
}
|
||||
# self.rdmc = rdmcObj
|
||||
# self.logoutobj = rdmcObj.commands_dict["LogoutCommand"](rdmcObj)
|
||||
|
||||
self.cmdbase = None
|
||||
self.rdmc = None
|
||||
self.auxcommands = dict()
|
||||
|
||||
def run(self, line, help_disp=False):
|
||||
"""If an argument is present, print help else exit
|
||||
|
||||
:param line: command line input
|
||||
:type line: string.
|
||||
"""
|
||||
if help_disp:
|
||||
self.parser.print_help()
|
||||
return ReturnCodes.SUCCESS
|
||||
try:
|
||||
(_, args) = self.rdmc.rdmc_parse_arglist(self, line)
|
||||
except (InvalidCommandLineErrorOPTS, SystemExit):
|
||||
if ("-h" in line) or ("--help" in line):
|
||||
return ReturnCodes.SUCCESS
|
||||
else:
|
||||
raise InvalidCommandLineErrorOPTS("")
|
||||
|
||||
if not args or not line:
|
||||
self.auxcommands["logout"].run("")
|
||||
|
||||
# System exit
|
||||
sys.exit(ReturnCodes.SUCCESS)
|
||||
else:
|
||||
self.rdmc.ui.error("Exit command does not take any parameters.\n")
|
||||
raise InvalidCommandLineErrorOPTS("Invalid command line arguments.")
|
||||
|
||||
def definearguments(self, customparser):
|
||||
"""Wrapper function for new command main function
|
||||
|
||||
:param customparser: command line input
|
||||
:type customparser: parser.
|
||||
"""
|
||||
if not customparser:
|
||||
return
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
###
|
||||
# Copyright 2016-2021 Hewlett Packard Enterprise, Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
###
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Help Command for RDMC"""
|
||||
|
||||
try:
|
||||
from rdmc_base_classes import RdmcCommandBase, RdmcOptionParser
|
||||
except ImportError:
|
||||
from ilorest.rdmc_base_classes import RdmcCommandBase, RdmcOptionParser
|
||||
try:
|
||||
from rdmc_helper import (
|
||||
InvalidCommandLineError,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
ReturnCodes,
|
||||
)
|
||||
except ImportError:
|
||||
from ilorest.rdmc_helper import (
|
||||
InvalidCommandLineError,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
ReturnCodes,
|
||||
)
|
||||
|
||||
|
||||
class HelpCommand(RdmcCommandBase):
|
||||
"""Constructor"""
|
||||
|
||||
def __init__(self):
|
||||
self.ident = {
|
||||
"name": "help",
|
||||
"usage": None,
|
||||
"description": "help [COMMAND]\n\tFor more detailed command descriptions"
|
||||
" use the help command feature\n\texample: help login\n",
|
||||
"summary": "Displays command line syntax and help menus for individual commands." " Example: help login\n",
|
||||
"aliases": [],
|
||||
"auxcommands": [],
|
||||
}
|
||||
self.cmdbase = None
|
||||
self.rdmc = None
|
||||
self.auxcommands = dict()
|
||||
|
||||
def run(self, line, help_disp=False):
|
||||
"""Wrapper function for help main function
|
||||
:param line: command line input
|
||||
:type line: string.
|
||||
"""
|
||||
if help_disp:
|
||||
self.parser.print_help()
|
||||
return ReturnCodes.SUCCESS
|
||||
try:
|
||||
(options, args) = self.rdmc.rdmc_parse_arglist(self, line)
|
||||
except (InvalidCommandLineErrorOPTS, SystemExit):
|
||||
if ("-h" in line) or ("--help" in line):
|
||||
return ReturnCodes.SUCCESS
|
||||
else:
|
||||
raise InvalidCommandLineErrorOPTS("")
|
||||
|
||||
if not args or not line:
|
||||
RdmcOptionParser().print_help()
|
||||
if self.rdmc:
|
||||
cmddict = self.rdmc.get_commands()
|
||||
sorted_keys = sorted(list(cmddict.keys()))
|
||||
|
||||
for key in sorted_keys:
|
||||
if key[0] == "_":
|
||||
continue
|
||||
else:
|
||||
self.rdmc.ui.printer("\n%s\n" % key)
|
||||
for cmd in cmddict[key]:
|
||||
self.rdmc.ui.printer(
|
||||
"%-25s - %s\n"
|
||||
% (
|
||||
self.rdmc.commands_dict[cmd].ident["name"],
|
||||
self.rdmc.commands_dict[cmd].ident["summary"],
|
||||
)
|
||||
)
|
||||
else:
|
||||
if self.rdmc:
|
||||
cmddict = self.rdmc.get_commands()
|
||||
sorted_keys = list(cmddict.keys())
|
||||
|
||||
for key in sorted_keys:
|
||||
for cmd in cmddict[key]:
|
||||
cmd_s = cmd.split("Command")
|
||||
cmd_s = cmd_s[0]
|
||||
if args[0].lower() == cmd_s.lower():
|
||||
self.rdmc.ui.printer(self.rdmc.commands_dict[cmd].ident["description"] + "\n")
|
||||
return ReturnCodes.SUCCESS
|
||||
raise InvalidCommandLineError("Command '%s' not found." % args[0])
|
||||
# Return code
|
||||
return ReturnCodes.SUCCESS
|
||||
|
||||
def definearguments(self, customparser):
|
||||
"""Wrapper function for new command main function
|
||||
|
||||
:param customparser: command line input
|
||||
:type customparser: parser.
|
||||
"""
|
||||
if not customparser:
|
||||
return
|
||||
Whitespace-only changes.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,156 @@
|
||||
###
|
||||
# Copyright 2016-2021 Hewlett Packard Enterprise, Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
###
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Results Command for rdmc"""
|
||||
|
||||
from redfish.ris.resp_handler import ResponseHandler
|
||||
from redfish.ris.rmc_helper import EmptyRaiseForEAFP
|
||||
|
||||
try:
|
||||
from rdmc_helper import (
|
||||
InvalidCommandLineError,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
ReturnCodes,
|
||||
)
|
||||
except ImportError:
|
||||
from ilorest.rdmc_helper import (
|
||||
InvalidCommandLineError,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
ReturnCodes,
|
||||
)
|
||||
|
||||
|
||||
class ResultsCommand:
|
||||
"""Monolith class command"""
|
||||
|
||||
def __init__(self):
|
||||
self.ident = {
|
||||
"name": "results",
|
||||
"usage": None,
|
||||
"description": "Run to show the results of the last" " changes after a server reboot.\n\texample: results",
|
||||
"summary": "Show the results of changes which require a server reboot.",
|
||||
"aliases": [],
|
||||
"auxcommands": ["LoginCommand", "SelectCommand"],
|
||||
}
|
||||
|
||||
self.cmdbase = None
|
||||
self.rdmc = None
|
||||
self.auxcommands = dict()
|
||||
|
||||
def run(self, line, help_disp=False):
|
||||
"""Gather results of latest BIOS change
|
||||
|
||||
:param line: string of arguments passed in
|
||||
:type line: str.
|
||||
"""
|
||||
if help_disp:
|
||||
self.parser.print_help()
|
||||
return ReturnCodes.SUCCESS
|
||||
try:
|
||||
(options, args) = self.rdmc.rdmc_parse_arglist(self, line)
|
||||
except (InvalidCommandLineErrorOPTS, SystemExit):
|
||||
if ("-h" in line) or ("--help" in line):
|
||||
return ReturnCodes.SUCCESS
|
||||
else:
|
||||
raise InvalidCommandLineErrorOPTS("")
|
||||
|
||||
if args:
|
||||
raise InvalidCommandLineError("Results command does not take any arguments.")
|
||||
self.resultsvalidation(options)
|
||||
results = {}
|
||||
if self.rdmc.app.typepath.defs.biospath[-1] == "/":
|
||||
iscsipath = self.rdmc.app.typepath.defs.biospath + "iScsi/"
|
||||
bootpath = self.rdmc.app.typepath.defs.biospath + "Boot/"
|
||||
else:
|
||||
iscsipath = self.rdmc.app.typepath.defs.biospath + "/iScsi"
|
||||
bootpath = self.rdmc.app.typepath.defs.biospath + "/Boot"
|
||||
|
||||
try:
|
||||
self.auxcommands["select"].selectfunction("SmartStorageConfig")
|
||||
smartarray = self.rdmc.app.getprops()
|
||||
sapaths = [path["@odata.id"].split("settings")[0] for path in smartarray]
|
||||
except:
|
||||
sapaths = None
|
||||
|
||||
biosresults = self.rdmc.app.get_handler(self.rdmc.app.typepath.defs.biospath, service=True, silent=True)
|
||||
iscsiresults = self.rdmc.app.get_handler(iscsipath, service=True, silent=True)
|
||||
bootsresults = self.rdmc.app.get_handler(bootpath, service=True, silent=True)
|
||||
saresults = []
|
||||
if sapaths:
|
||||
saresults = [self.rdmc.app.get_handler(path, service=True, silent=True) for path in sapaths]
|
||||
try:
|
||||
results.update({"Bios:": biosresults.dict[self.rdmc.app.typepath.defs.biossettingsstring]["Messages"]})
|
||||
except Exception:
|
||||
results.update({"Bios:": None})
|
||||
|
||||
try:
|
||||
results.update({"Iscsi:": iscsiresults.dict[self.rdmc.app.typepath.defs.biossettingsstring]["Messages"]})
|
||||
except:
|
||||
results.update({"Iscsi:": None})
|
||||
|
||||
try:
|
||||
results.update({"Boot:": bootsresults.dict[self.rdmc.app.typepath.defs.biossettingsstring]["Messages"]})
|
||||
except:
|
||||
results.update({"Boot:": None})
|
||||
try:
|
||||
for result in saresults:
|
||||
loc = "SmartArray"
|
||||
if saresults.index(result) > 0:
|
||||
loc += " %d:" % saresults.index(result)
|
||||
else:
|
||||
loc += ":"
|
||||
results.update({loc: result.dict[self.rdmc.app.typepath.defs.biossettingsstring]["Messages"]})
|
||||
except:
|
||||
results.update({"SmartArray:": None})
|
||||
|
||||
self.rdmc.ui.printer("Results of the previous reboot changes:\n\n")
|
||||
|
||||
for result in results:
|
||||
self.rdmc.ui.printer("%s\n" % result)
|
||||
try:
|
||||
for msg in results[result]:
|
||||
_ = ResponseHandler(
|
||||
self.rdmc.app.validationmanager,
|
||||
self.rdmc.app.typepath.defs.messageregistrytype,
|
||||
).message_handler(response_data=msg, message_text="", verbosity=0, dl_reg=False)
|
||||
pass
|
||||
except EmptyRaiseForEAFP as exp:
|
||||
raise EmptyRaiseForEAFP(exp)
|
||||
except Exception:
|
||||
self.rdmc.ui.error("No messages found for %s.\n" % result[:-1])
|
||||
|
||||
self.cmdbase.logout_routine(self, options)
|
||||
return ReturnCodes.SUCCESS
|
||||
|
||||
def resultsvalidation(self, options):
|
||||
"""Results method validation function
|
||||
|
||||
:param options: command line options
|
||||
:type options: list.
|
||||
"""
|
||||
self.cmdbase.login_select_validation(self, options)
|
||||
|
||||
def definearguments(self, customparser):
|
||||
"""Wrapper function for new command main function
|
||||
|
||||
:param customparser: command line input
|
||||
:type customparser: parser.
|
||||
"""
|
||||
if not customparser:
|
||||
return
|
||||
|
||||
self.cmdbase.add_login_arguments_group(customparser)
|
||||
@@ -0,0 +1,424 @@
|
||||
###
|
||||
# Copyright 2016-2021 Hewlett Packard Enterprise, Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
###
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Save Command for RDMC"""
|
||||
|
||||
import json
|
||||
from collections import OrderedDict
|
||||
|
||||
import redfish.ris
|
||||
|
||||
try:
|
||||
from rdmc_helper import (
|
||||
Encryption,
|
||||
InvalidCommandLineError,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
InvalidFileFormattingError,
|
||||
ReturnCodes,
|
||||
iLORisCorruptionError,
|
||||
)
|
||||
except ImportError:
|
||||
from ilorest.rdmc_helper import (
|
||||
Encryption,
|
||||
InvalidCommandLineError,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
InvalidFileFormattingError,
|
||||
ReturnCodes,
|
||||
iLORisCorruptionError,
|
||||
)
|
||||
|
||||
# default file name
|
||||
__filename__ = "ilorest.json"
|
||||
|
||||
|
||||
class SaveCommand:
|
||||
"""Constructor"""
|
||||
|
||||
def __init__(self):
|
||||
self.ident = {
|
||||
"name": "save",
|
||||
"usage": None,
|
||||
"description": "Run to save a selected type to a file"
|
||||
"\n\texample: save --selector HpBios.\n\n\tChange the default "
|
||||
"output filename\n\texample: save --selector HpBios. -f "
|
||||
"output.json\n\n\tTo save multiple types in one file\n\texample: "
|
||||
"save --multisave Bios.,ComputerSystem.",
|
||||
"summary": "Saves the selected type's settings to a file.",
|
||||
"aliases": [],
|
||||
"auxcommands": ["SelectCommand"],
|
||||
}
|
||||
self.filename = __filename__
|
||||
self.cmdbase = None
|
||||
self.rdmc = None
|
||||
self.auxcommands = dict()
|
||||
|
||||
def run(self, line, help_disp=False):
|
||||
"""Main save worker function
|
||||
|
||||
:param line: command line input
|
||||
:type line: string.
|
||||
"""
|
||||
if help_disp:
|
||||
self.parser.print_help()
|
||||
return ReturnCodes.SUCCESS
|
||||
try:
|
||||
(options, args) = self.rdmc.rdmc_parse_arglist(self, line)
|
||||
except (InvalidCommandLineErrorOPTS, SystemExit):
|
||||
if ("-h" in line) or ("--help" in line):
|
||||
return ReturnCodes.SUCCESS
|
||||
else:
|
||||
raise InvalidCommandLineErrorOPTS("")
|
||||
|
||||
if options.multisave:
|
||||
options.selector = ""
|
||||
if (
|
||||
hasattr(options, "selector")
|
||||
and options.selector is not None
|
||||
and "hpbaseconfigs" not in options.selector.lower()
|
||||
and "hpebaseconfigs" not in options.selector.lower()
|
||||
and "bios" not in options.selector.lower()
|
||||
):
|
||||
self.savevalidation(options)
|
||||
else:
|
||||
# filename validations and checks
|
||||
self.cmdbase.login_validation(self, options)
|
||||
self.filename = None
|
||||
if options.filename and len(options.filename) > 1:
|
||||
raise InvalidCommandLineError("Save command doesn't support multiple filenames.")
|
||||
elif options.filename:
|
||||
self.filename = options.filename[0]
|
||||
elif self.rdmc.config:
|
||||
if self.rdmc.config.defaultsavefilename:
|
||||
self.filename = self.rdmc.config.defaultsavefilename
|
||||
|
||||
if not self.filename:
|
||||
self.filename = __filename__
|
||||
|
||||
# if args:
|
||||
# raise InvalidCommandLineError("Save command takes no arguments.")
|
||||
|
||||
self.rdmc.ui.printer("Saving configuration...\n")
|
||||
if options.filter:
|
||||
try:
|
||||
if (str(options.filter)[0] == str(options.filter)[-1]) and str(options.filter).startswith(("'", '"')):
|
||||
options.filter = options.filter[1:-1]
|
||||
|
||||
(sel, val) = options.filter.split("=")
|
||||
sel = sel.strip()
|
||||
val = val.strip()
|
||||
except:
|
||||
raise InvalidCommandLineError("Invalid filter" " parameter format [filter_attribute]=[filter_value]")
|
||||
|
||||
instances = self.rdmc.app.select(
|
||||
selector=self.rdmc.app.selector,
|
||||
fltrvals=(sel, val),
|
||||
path_refresh=True,
|
||||
)
|
||||
contents = self.saveworkerfunction(options, instances=instances)
|
||||
else:
|
||||
contents = self.saveworkerfunction(options)
|
||||
|
||||
if options.multisave:
|
||||
for select in options.multisave:
|
||||
try:
|
||||
self.auxcommands["select"].run(select)
|
||||
except:
|
||||
pass
|
||||
contents += self.saveworkerfunction(options)
|
||||
|
||||
if not contents:
|
||||
raise redfish.ris.NothingSelectedError
|
||||
else:
|
||||
# TODO: Maybe add this to the command. Not sure we use it elsewhere in the lib
|
||||
contents = self.add_save_file_header(contents)
|
||||
|
||||
if options.encryption:
|
||||
with open(self.filename, "wb") as outfile:
|
||||
outfile.write(
|
||||
Encryption().encrypt_file(
|
||||
json.dumps(contents, indent=2, cls=redfish.ris.JSONEncoder),
|
||||
options.encryption,
|
||||
)
|
||||
)
|
||||
else:
|
||||
with open(self.filename, "w") as outfile:
|
||||
outfile.write(json.dumps(contents, indent=2, cls=redfish.ris.JSONEncoder, sort_keys=True))
|
||||
self.rdmc.ui.printer("Configuration saved to: %s\n" % self.filename)
|
||||
|
||||
self.cmdbase.logout_routine(self, options)
|
||||
|
||||
# Return code
|
||||
return ReturnCodes.SUCCESS
|
||||
|
||||
def saveworkerfunction(self, options, instances=None):
|
||||
"""Returns the currently selected type for saving
|
||||
|
||||
:param instances: list of instances from select to save
|
||||
:type instances: list.
|
||||
"""
|
||||
try:
|
||||
if (
|
||||
options.selector is not None
|
||||
and (
|
||||
"bios" in options.selector.lower()
|
||||
or "hpbaseconfigs" in options.selector.lower()
|
||||
or "hpebaseconfigs" in options.selector.lower()
|
||||
)
|
||||
) and (options.multisave is None or options.multisave == ""):
|
||||
raise KeyError
|
||||
content = self.rdmc.app.getprops(insts=instances)
|
||||
try:
|
||||
contents = [{val[self.rdmc.app.typepath.defs.hrefstring]: val} for val in content]
|
||||
except KeyError:
|
||||
try:
|
||||
contents = [{val["links"]["self"][self.rdmc.app.typepath.defs.hrefstring]: val} for val in content]
|
||||
except KeyError:
|
||||
raise iLORisCorruptionError(
|
||||
"iLO Database seems to be corrupted. Please check. Reboot the server to " "restore\n"
|
||||
)
|
||||
except Exception:
|
||||
config_path = None
|
||||
contents = list()
|
||||
if options.selector is not None:
|
||||
if options.selector.lower() == "bios." or "bios.v" in options.selector.lower():
|
||||
config_path = ["/redfish/v1/systems/1/bios/settings/"]
|
||||
elif options.selector.lower() == "bios":
|
||||
config_path = [
|
||||
"/redfish/v1/systems/1/bios/settings/",
|
||||
"/redfish/v1/systems/1/bios/mappings/",
|
||||
"/redfish/v1/systems/1/bios/oem/hpe/mappings/",
|
||||
]
|
||||
elif "hpbaseconfigs" in options.selector.lower() or "hpebaseconfigs" in options.selector.lower():
|
||||
config_path = [
|
||||
"/redfish/v1/systems/1/bios/oem/hpe/baseconfigs/",
|
||||
"/redfish/v1/systems/1/bios/oem/hpe/nvmeof/baseconfigs/",
|
||||
"/redfish/v1/systems/1/bios/oem/hpe/iscsi/baseconfigs/",
|
||||
"/redfish/v1/systems/1/bios/oem/hpe/tlsconfig/baseconfigs/",
|
||||
"/redfish/v1/systems/1/bios/oem/hpe/serverconfiglock/baseconfigs/",
|
||||
"/redfish/v1/systems/1/bios/oem/hpe/kmsconfig/baseconfigs/",
|
||||
"/redfish/v1/systems/1/bios/oem/hpe/boot/baseconfigs/",
|
||||
"/redfish/v1/systems/1/bios/baseconfigs/",
|
||||
"/redfish/v1/systems/1/bios/nvmeof/baseconfigs/",
|
||||
"/redfish/v1/systems/1/bios/iscsi/baseconfigs/",
|
||||
"/redfish/v1/systems/1/bios/tlsconfig/baseconfigs/",
|
||||
"/redfish/v1/systems/1/bios/serverconfiglock/baseconfigs/",
|
||||
"/redfish/v1/systems/1/bios/kmsconfig/baseconfigs/",
|
||||
"/redfish/v1/systems/1/bios/boot/baseconfigs/",
|
||||
]
|
||||
elif "hpebiosmapping" in options.selector.lower():
|
||||
config_path = [
|
||||
"/redfish/v1/systems/1/bios/mappings",
|
||||
"/redfish/v1/systems/1/bios/oem/hpe/mappings/",
|
||||
]
|
||||
result = None
|
||||
for b in config_path:
|
||||
try:
|
||||
result = self.rdmc.app.get_handler(b, silent=True, service=True)
|
||||
except:
|
||||
pass
|
||||
if result is not None:
|
||||
if result.status == 200:
|
||||
d = {b: result.dict}
|
||||
contents.append(d)
|
||||
|
||||
type_string = self.rdmc.app.typepath.defs.typestring
|
||||
|
||||
templist = list()
|
||||
srnum_list = list()
|
||||
|
||||
for content in contents:
|
||||
typeselector = None
|
||||
pathselector = None
|
||||
|
||||
for path, values in content.items():
|
||||
# if "Managers/1/EthernetInterfaces/1" not in path:
|
||||
for dictentry in list(values.keys()):
|
||||
if dictentry == type_string:
|
||||
typeselector = values[dictentry]
|
||||
pathselector = path
|
||||
del values[dictentry]
|
||||
if dictentry in [
|
||||
"IPv4Addresses",
|
||||
"IPv6Addresses",
|
||||
"IPv6AddressPolicyTable",
|
||||
"MACAddress",
|
||||
"StaticNameServers",
|
||||
# "AutoNeg",
|
||||
# "FullDuplex",
|
||||
"SpeedMbps",
|
||||
]:
|
||||
del values[dictentry]
|
||||
if dictentry in [
|
||||
"IPv6StaticAddresses",
|
||||
"IPv6StaticDefaultGateways",
|
||||
"IPv4StaticAddresses",
|
||||
]:
|
||||
if values[dictentry]:
|
||||
del values[dictentry]
|
||||
if dictentry in ["IPv4", "IPv6", "DHCPv6", "DHCPv4"]:
|
||||
if "DNSServers" in values[dictentry]:
|
||||
del values[dictentry]["DNSServers"]
|
||||
del values["Oem"]["Hpe"][dictentry]["DNSServers"]
|
||||
if "UseDNSServers" in values[dictentry]:
|
||||
del values[dictentry]["UseDNSServers"]
|
||||
del values["Oem"]["Hpe"][dictentry]["UseDNSServers"]
|
||||
|
||||
if values:
|
||||
skip = False
|
||||
if "SerialNumber" in values and values["SerialNumber"] is not None and values["SerialNumber"] != "":
|
||||
if values["SerialNumber"] in srnum_list:
|
||||
skip = True
|
||||
else:
|
||||
srnum_list.append(values["SerialNumber"])
|
||||
tempcontents = dict()
|
||||
|
||||
if not skip:
|
||||
if typeselector and pathselector:
|
||||
tempcontents[typeselector] = {pathselector: values}
|
||||
else:
|
||||
raise InvalidFileFormattingError("Missing path or selector in input file.")
|
||||
|
||||
templist.append(tempcontents)
|
||||
|
||||
return templist
|
||||
|
||||
def nested_sort(self, data):
|
||||
"""Helper function to sort all dictionary key:value pairs
|
||||
|
||||
:param data: dictionary to sort
|
||||
:type data: dict.
|
||||
"""
|
||||
|
||||
for key, value in data.items():
|
||||
if isinstance(value, dict):
|
||||
data[key] = self.nested_sort(value)
|
||||
|
||||
data = OrderedDict(sorted(list(data.items()), key=lambda x: x[0]))
|
||||
|
||||
return data
|
||||
|
||||
def savevalidation(self, options):
|
||||
"""Save method validation function
|
||||
|
||||
:param options: command line options
|
||||
:type options: list.
|
||||
"""
|
||||
|
||||
if options.multisave:
|
||||
options.multisave = options.multisave.replace('"', "").replace("'", "")
|
||||
options.multisave = options.multisave.replace(" ", "").split(",")
|
||||
if not len(options.multisave) >= 1:
|
||||
raise InvalidCommandLineError("Invalid number of types in multisave option.")
|
||||
options.selector = options.multisave[0]
|
||||
options.multisave = options.multisave[1:]
|
||||
|
||||
self.cmdbase.login_select_validation(self, options)
|
||||
|
||||
# filename validations and checks
|
||||
self.filename = None
|
||||
|
||||
if options.filename and len(options.filename) > 1:
|
||||
raise InvalidCommandLineError("Save command doesn't support multiple filenames.")
|
||||
elif options.filename:
|
||||
self.filename = options.filename[0]
|
||||
elif self.rdmc.config:
|
||||
if self.rdmc.config.defaultsavefilename:
|
||||
self.filename = self.rdmc.config.defaultsavefilename
|
||||
|
||||
if not self.filename:
|
||||
self.filename = __filename__
|
||||
|
||||
def add_save_file_header(self, contents):
|
||||
"""Helper function to retrieve the comments for save file
|
||||
|
||||
:param contents: current save contents
|
||||
:type contents: list.
|
||||
"""
|
||||
templist = list()
|
||||
|
||||
headers = self.rdmc.app.create_save_header()
|
||||
templist.append(headers)
|
||||
|
||||
for content in contents:
|
||||
templist.append(content)
|
||||
|
||||
return templist
|
||||
|
||||
def definearguments(self, customparser):
|
||||
"""Wrapper function for new command main function
|
||||
|
||||
:param customparser: command line input
|
||||
:type customparser: parser.
|
||||
"""
|
||||
if not customparser:
|
||||
return
|
||||
|
||||
self.cmdbase.add_login_arguments_group(customparser)
|
||||
customparser.add_argument(
|
||||
"-f",
|
||||
"--filename",
|
||||
dest="filename",
|
||||
help="Use this flag if you wish to use a different filename than the default one. "
|
||||
"The default filename is %s." % __filename__,
|
||||
action="append",
|
||||
default=None,
|
||||
)
|
||||
|
||||
customparser.add_argument(
|
||||
"--selector",
|
||||
dest="selector",
|
||||
help="Optionally include this flag to select a type to run the current command on. "
|
||||
"Use this flag when you wish to select a type without entering another command, "
|
||||
"or if you wish to work with a type that is different from the one currently "
|
||||
"selected.",
|
||||
default=None,
|
||||
# required=True,
|
||||
)
|
||||
customparser.add_argument(
|
||||
"--multisave",
|
||||
dest="multisave",
|
||||
help="Optionally include this flag to save multiple types to a single file. "
|
||||
"Overrides the currently selected type.\n\t Usage: --multisave type1.,type2.,type3.",
|
||||
default="",
|
||||
)
|
||||
customparser.add_argument(
|
||||
"--filter",
|
||||
dest="filter",
|
||||
help="Optionally set a filter value for a filter attribute. This uses the provided "
|
||||
"filter for the currently selected type. Note: Use this flag to narrow down your "
|
||||
"results. For example, selecting a common type might return multiple objects that "
|
||||
"are all of that type. If you want to modify the properties of only one of those "
|
||||
"objects, use the filter flag to narrow down results based on properties."
|
||||
"\n\t Usage: --filter [ATTRIBUTE]=[VALUE]",
|
||||
default=None,
|
||||
)
|
||||
customparser.add_argument(
|
||||
"-j",
|
||||
"--json",
|
||||
dest="json",
|
||||
action="store_true",
|
||||
help="Optionally include this flag if you wish to change the displayed output to "
|
||||
"JSON format. Preserving the JSON data structure makes the information easier to "
|
||||
"parse.",
|
||||
default=False,
|
||||
)
|
||||
customparser.add_argument(
|
||||
"--encryption",
|
||||
dest="encryption",
|
||||
help="Optionally include this flag to encrypt/decrypt a file using the key provided.",
|
||||
default=None,
|
||||
)
|
||||
@@ -0,0 +1,143 @@
|
||||
###
|
||||
# Copyright 2016-2021 Hewlett Packard Enterprise, Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
###
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Select Command for RDMC"""
|
||||
|
||||
from redfish.ris import NothingSelectedError
|
||||
|
||||
try:
|
||||
from rdmc_helper import LOGGER, InvalidCommandLineErrorOPTS, ReturnCodes
|
||||
except ImportError:
|
||||
from ilorest.rdmc_helper import LOGGER, InvalidCommandLineErrorOPTS, ReturnCodes
|
||||
|
||||
|
||||
class SelectCommand:
|
||||
"""Constructor"""
|
||||
|
||||
def __init__(self):
|
||||
self.ident = {
|
||||
"name": "select",
|
||||
"usage": None,
|
||||
"description": "Selects the Redfish/HpRest type to be used.\nIn order to "
|
||||
"remove the need of including the version while selecting you"
|
||||
" can simply enter the type name until the first period\n\t"
|
||||
"example: select HpBios.\n"
|
||||
"Run without an argument to "
|
||||
"display the currently selected type\n\texample: select",
|
||||
"summary": "Selects the object type to be used.",
|
||||
"aliases": ["sel"],
|
||||
"auxcommands": ["LoginCommand"],
|
||||
}
|
||||
self.cmdbase = None
|
||||
self.rdmc = None
|
||||
self.auxcommands = dict()
|
||||
|
||||
def selectfunction(self, line):
|
||||
"""Main select worker function
|
||||
|
||||
:param line: command line input
|
||||
:type line: string.
|
||||
"""
|
||||
|
||||
try:
|
||||
(options, args) = self.rdmc.rdmc_parse_arglist(self, line)
|
||||
except (InvalidCommandLineErrorOPTS, SystemExit):
|
||||
if ("-h" in line) or ("--help" in line):
|
||||
return ReturnCodes.SUCCESS
|
||||
else:
|
||||
raise InvalidCommandLineErrorOPTS("")
|
||||
|
||||
self.selectvalidation(options)
|
||||
|
||||
if args:
|
||||
if options.ref:
|
||||
LOGGER.warning("Patches from current selection will be cleared.")
|
||||
selector = args[0]
|
||||
selections = self.rdmc.app.select(selector=selector, path_refresh=options.ref)
|
||||
|
||||
if "storage" in selector.lower():
|
||||
storage_url = "/redfish/v1/Systems/1/Storage/"
|
||||
list_storageid = self.rdmc.app.get_handler(storage_url, silent=True, service=True).dict["Members"]
|
||||
for val in list_storageid:
|
||||
storageid_fromurl = val["@odata.id"]
|
||||
ctr = self.rdmc.app.get_handler(storageid_fromurl, silent=True, service=True).dict
|
||||
if "Controllers" in ctr:
|
||||
ctr_url = ctr["Controllers"]["@odata.id"]
|
||||
self.rdmc.app.get_handler(ctr_url, silent=True, service=True).dict
|
||||
if self.rdmc.opts.verbose and selections:
|
||||
templist = list()
|
||||
self.rdmc.ui.printer("Selected option(s): ")
|
||||
|
||||
for item in selections:
|
||||
if item.type not in templist:
|
||||
templist.append(item.type)
|
||||
|
||||
self.rdmc.ui.printer("%s\n" % ", ".join(map(str, templist)))
|
||||
|
||||
else:
|
||||
selector = self.rdmc.app.selector
|
||||
|
||||
if selector:
|
||||
sellist = [sel for sel in self.rdmc.app.monolith.typesadded if selector.lower() in sel.lower()]
|
||||
self.rdmc.ui.printer("Current selection: ")
|
||||
self.rdmc.ui.printer("%s\n" % ", ".join(map(str, sellist)))
|
||||
else:
|
||||
raise NothingSelectedError
|
||||
|
||||
self.cmdbase.logout_routine(self, options)
|
||||
|
||||
def selectvalidation(self, options):
|
||||
"""Select data validation function
|
||||
|
||||
:param options: command line options
|
||||
:type options: list.
|
||||
"""
|
||||
|
||||
self.cmdbase.login_select_validation(self, options)
|
||||
|
||||
def run(self, line, help_disp=False):
|
||||
"""Wrapper function for main select function
|
||||
|
||||
:param line: entered command line
|
||||
:type line: list.
|
||||
"""
|
||||
if help_disp:
|
||||
self.parser.print_help()
|
||||
return ReturnCodes.SUCCESS
|
||||
self.selectfunction(line)
|
||||
|
||||
# Return code
|
||||
return ReturnCodes.SUCCESS
|
||||
|
||||
def definearguments(self, customparser):
|
||||
"""Wrapper function for new command main function
|
||||
|
||||
:param customparser: command line input
|
||||
:type customparser: parser.
|
||||
"""
|
||||
if not customparser:
|
||||
return
|
||||
|
||||
self.cmdbase.add_login_arguments_group(customparser)
|
||||
|
||||
customparser.add_argument(
|
||||
"--refresh",
|
||||
dest="ref",
|
||||
action="store_true",
|
||||
help="Optionally reload the data of selected type and clear " "patches from current selection.",
|
||||
default=False,
|
||||
)
|
||||
@@ -0,0 +1,472 @@
|
||||
###
|
||||
# Copyright 2016-2023 Hewlett Packard Enterprise, Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
###
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Set Command for RDMC"""
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
import redfish.ris
|
||||
|
||||
from redfish.rest.connections import SecurityStateError
|
||||
|
||||
try:
|
||||
from rdmc_helper import (
|
||||
InvalidCommandLineError,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
InvalidOrNothingChangedSettingsError,
|
||||
ReturnCodes,
|
||||
)
|
||||
except ImportError:
|
||||
from ilorest.rdmc_helper import (
|
||||
ReturnCodes,
|
||||
InvalidCommandLineError,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
InvalidOrNothingChangedSettingsError,
|
||||
)
|
||||
|
||||
from redfish.ris.rmc_helper import NothingSelectedError
|
||||
|
||||
|
||||
class SetCommand:
|
||||
"""Constructor"""
|
||||
|
||||
def __init__(self):
|
||||
self.ident = {
|
||||
"name": "set",
|
||||
"usage": None,
|
||||
"description": "Setting a "
|
||||
"single level property example:\n\tset property=value\n\n\t"
|
||||
"Setting multiple single level properties example:\n\tset "
|
||||
"property=value property=value property=value\n\n\t"
|
||||
"Setting a multi level property example:\n\tset property/"
|
||||
"subproperty=value",
|
||||
"summary": "Changes the value of a property within the" " currently selected type.",
|
||||
"aliases": [],
|
||||
"auxcommands": [
|
||||
"CommitCommand",
|
||||
"RebootCommand",
|
||||
"RawPatchCommand",
|
||||
"SelectCommand",
|
||||
"LogoutCommand",
|
||||
],
|
||||
}
|
||||
self.cmdbase = None
|
||||
self.rdmc = None
|
||||
self.auxcommands = dict()
|
||||
|
||||
def setfunction(self, line, skipprint=False):
|
||||
"""Main set worker function
|
||||
|
||||
:param line: command line input
|
||||
:type line: string.
|
||||
:param skipprint: boolean to determine output
|
||||
:type skipprint: boolean.
|
||||
"""
|
||||
|
||||
try:
|
||||
(options, args) = self.rdmc.rdmc_parse_arglist(self, line)
|
||||
except (InvalidCommandLineErrorOPTS, SystemExit):
|
||||
if ("-h" in line) or ("--help" in line):
|
||||
return ReturnCodes.SUCCESS
|
||||
else:
|
||||
raise InvalidCommandLineErrorOPTS("")
|
||||
|
||||
if not self.rdmc.interactive and not self.rdmc.app.cache:
|
||||
raise InvalidCommandLineError("The 'set' command is not useful in " "non-interactive and non-cache modes.")
|
||||
|
||||
self.setvalidation(options)
|
||||
ilover = self.rdmc.app.getiloversion()
|
||||
if ilover >= 7.000 and ("HighSecurity" in args[0] or "Production" in args[0]):
|
||||
self.rdmc.ui.error(
|
||||
"HighSecurity and Production modes are not supported on iLO 7 , Please use SecureStandard instead \n"
|
||||
)
|
||||
raise SecurityStateError(
|
||||
"HighSecurity and Production modes are not supported on iLO 7 , Please use SecureStandard instead"
|
||||
)
|
||||
else:
|
||||
if "SecureStandard" in args[0] and ilover < 7.000:
|
||||
self.rdmc.ui.error(
|
||||
"SecureStandard mode is not supported on iLO 6 and below , Please use HighSecurity instead \n"
|
||||
)
|
||||
raise SecurityStateError(
|
||||
"SecureStandard mode is not supported on iLO 6 and below , Please use HighSecurity instead \n"
|
||||
)
|
||||
_ = args[0].find("HighSecurity")
|
||||
if ilover >= 7.000:
|
||||
_ = args[0].find("SecureStandard")
|
||||
fsel = None
|
||||
fval = None
|
||||
if args:
|
||||
if "ethernetinterface" in self.rdmc.app.selector.lower() and "ipv4addresses" in args[0].lower():
|
||||
raise InvalidCommandLineError(
|
||||
"For security reasons this request is discarded. "
|
||||
"Use `rawpatch` or the `load --force_network_config` command "
|
||||
"to modify the IP configuration of the ilO.\n"
|
||||
)
|
||||
if options.filter:
|
||||
try:
|
||||
(fsel, fval) = str(options.filter).strip("'\" ").split("=")
|
||||
(fsel, fval) = (fsel.strip(), fval.strip())
|
||||
except:
|
||||
raise InvalidCommandLineError(
|
||||
"Invalid filter" " parameter format [filter_attribute]=[filter_value]"
|
||||
)
|
||||
|
||||
if any([s.lower().startswith("adminpassword=") for s in args]) and not any(
|
||||
[s.lower().startswith("oldadminpassword=") for s in args]
|
||||
):
|
||||
raise InvalidCommandLineError(
|
||||
"'OldAdminPassword' must also "
|
||||
"be set with the current password \nwhen "
|
||||
"changing 'AdminPassword' for security reasons."
|
||||
)
|
||||
count = 0
|
||||
for arg in args:
|
||||
if arg:
|
||||
if len(arg) > 2:
|
||||
if ('"' in arg[0] and '"' in arg[-1]) or ("'" in arg[0] and "'" in arg[-1]):
|
||||
args[count] = arg[1:-1]
|
||||
elif len(arg) == 2:
|
||||
if (arg[0] == '"' and arg[1] == '"') or (arg[0] == "'" and arg[1] == "'"):
|
||||
args[count] = None
|
||||
count += 1
|
||||
if not self.rdmc.app.selector:
|
||||
raise NothingSelectedError
|
||||
if "." not in self.rdmc.app.selector:
|
||||
self.rdmc.app.selector = self.rdmc.app.selector + "."
|
||||
if self.rdmc.app.selector:
|
||||
if self.rdmc.app.selector.lower().startswith("bios."):
|
||||
if "attributes" not in arg.lower():
|
||||
arg = "Attributes/" + arg
|
||||
|
||||
try:
|
||||
(sel, val) = arg.split("=")
|
||||
sel = sel.strip().lower()
|
||||
val = val.strip("\"'")
|
||||
|
||||
if val.lower() == "true" or val.lower() == "false":
|
||||
val = val.lower() in ("yes", "true", "t", "1")
|
||||
except:
|
||||
raise InvalidCommandLineError("Invalid set parameter format. [Key]=[Value]")
|
||||
|
||||
newargs = list()
|
||||
|
||||
if "/" in sel and "/" not in str(val):
|
||||
newargs = sel.split("/")
|
||||
elif "/" in sel:
|
||||
items = arg.split("=", 1)
|
||||
newargs = items[0].split("/")
|
||||
if not isinstance(val, bool):
|
||||
if val:
|
||||
if val[0] == "[" and val[-1] == "]":
|
||||
val = val[1:-1].split(",")
|
||||
payload = {newargs[-1]: val} if newargs else {sel: val}
|
||||
if newargs:
|
||||
for key in newargs[:-1][::-1]:
|
||||
payload = {key: payload}
|
||||
try:
|
||||
contents = self.rdmc.app.loadset(
|
||||
seldict=payload,
|
||||
latestschema=options.latestschema,
|
||||
fltrvals=(fsel, fval),
|
||||
uniqueoverride=options.uniqueoverride,
|
||||
)
|
||||
if not contents:
|
||||
if not sel.lower() == "oldadminpassword":
|
||||
raise InvalidOrNothingChangedSettingsError(
|
||||
"Nothing changed "
|
||||
"for attribute '%s'.\nPlease check if the attribute is Oem/Hpe Attribute or Read-only "
|
||||
"or System Unique property or the value trying to set is same or invalid" % sel
|
||||
)
|
||||
elif contents == "No entries found":
|
||||
raise InvalidOrNothingChangedSettingsError(
|
||||
"No " "entries found in the current " "selection for the setting '%s'." % sel
|
||||
)
|
||||
elif contents == "reverting":
|
||||
self.rdmc.ui.error("Removing previous patch and returning to the " "original value.\n")
|
||||
else:
|
||||
for content in contents:
|
||||
self.rdmc.ui.printer("Added the following patch:\n")
|
||||
self.rdmc.ui.print_out_json(content)
|
||||
|
||||
except redfish.ris.ValidationError as excp:
|
||||
errs = excp.get_errors()
|
||||
|
||||
for err in errs:
|
||||
if err.sel and err.sel.lower() == "adminpassword":
|
||||
types = self.rdmc.app.monolith.types
|
||||
|
||||
for item in types:
|
||||
for instance in types[item]["Instances"]:
|
||||
if "hpbios." in instance.maj_type.lower():
|
||||
_ = [
|
||||
instance.patches.remove(patch)
|
||||
for patch in instance.patches
|
||||
if patch.patch[0]["path"] == "/OldAdminPassword"
|
||||
]
|
||||
|
||||
if isinstance(err, redfish.ris.RegistryValidationError):
|
||||
self.rdmc.ui.printer(err.message)
|
||||
|
||||
raise redfish.ris.ValidationError(excp)
|
||||
|
||||
if options.commit:
|
||||
self.auxcommands["commit"].commitfunction(options)
|
||||
|
||||
if options.reboot and not options.commit:
|
||||
self.auxcommands["reboot"].run(options.reboot)
|
||||
|
||||
if options.logout:
|
||||
self.auxcommands["logout"].run("")
|
||||
|
||||
else:
|
||||
raise InvalidCommandLineError("Missing parameters for 'set' command.\n")
|
||||
|
||||
def patchfunction(self, line):
|
||||
"""Main set worker function
|
||||
:param line: command line input
|
||||
:type line: string.
|
||||
:param skipprint: boolean to determine output
|
||||
:type skipprint: boolean.
|
||||
"""
|
||||
import platform
|
||||
import tempfile
|
||||
|
||||
try:
|
||||
(options, args) = self.rdmc.rdmc_parse_arglist(self, line)
|
||||
except (InvalidCommandLineErrorOPTS, SystemExit):
|
||||
if ("-h" in line) or ("--help" in line):
|
||||
return ReturnCodes.SUCCESS
|
||||
else:
|
||||
raise InvalidCommandLineErrorOPTS("")
|
||||
|
||||
if not self.rdmc.interactive and not self.rdmc.app.cache:
|
||||
raise InvalidCommandLineError("The 'set' command is not useful in " "non-interactive and non-cache modes.")
|
||||
|
||||
_ = self.rdmc.app.selector
|
||||
self.setvalidation(options)
|
||||
if args:
|
||||
count = 0
|
||||
for arg in args:
|
||||
if arg:
|
||||
if len(arg) > 2:
|
||||
if ('"' in arg[0] and '"' in arg[-1]) or ("'" in arg[0] and "'" in arg[-1]):
|
||||
args[count] = arg[1:-1]
|
||||
elif len(arg) == 2:
|
||||
if (arg[0] == '"' and arg[1] == '"') or (arg[0] == "'" and arg[1] == "'"):
|
||||
args[count] = None
|
||||
count += 1
|
||||
if not self.rdmc.app.selector:
|
||||
raise NothingSelectedError
|
||||
if "." not in self.rdmc.app.selector:
|
||||
self.rdmc.app.selector = self.rdmc.app.selector + "."
|
||||
if self.rdmc.app.selector:
|
||||
if self.rdmc.app.selector.lower().startswith("bios."):
|
||||
if "attributes" not in arg.lower():
|
||||
arg = "Attributes/" + arg
|
||||
|
||||
try:
|
||||
(sel, val) = arg.split("=")
|
||||
sel = sel.strip()
|
||||
val = val.strip("\"'")
|
||||
|
||||
if val.lower() == "true" or val.lower() == "false":
|
||||
val = val.lower() in ("yes", "true", "t", "1")
|
||||
except:
|
||||
raise InvalidCommandLineError("Invalid set parameter format. [Key]=[Value]")
|
||||
|
||||
newargs = list()
|
||||
|
||||
if "/" in sel and "/" not in str(val):
|
||||
newargs = sel.split("/")
|
||||
elif "/" in sel:
|
||||
items = arg.split("=", 1)
|
||||
newargs = items[0].split("/")
|
||||
|
||||
if not isinstance(val, bool):
|
||||
if val:
|
||||
if val[0] == "[" and val[-1] == "]":
|
||||
val = val[1:-1].split(",")
|
||||
if val.isdigit():
|
||||
val = int(val)
|
||||
patch_data = dict()
|
||||
payload = {newargs[-1]: val} if newargs else {sel: val}
|
||||
if "drive" in self.rdmc.app.selector.lower():
|
||||
tempdir = "/tmp" if platform.system() == "Darwin" else tempfile.gettempdir()
|
||||
temp_file = os.path.join(tempdir, "temp_patch.json")
|
||||
out_file = open(temp_file, "w")
|
||||
if getattr(options, "filter", None):
|
||||
filt_arr = options.filter.split("=")
|
||||
patchpath = filt_arr[-1]
|
||||
else:
|
||||
sys.stdout.write("Please provide the actual drive to modify using filter option\n")
|
||||
return
|
||||
patch_payload = {patchpath: payload}
|
||||
json.dump(patch_payload, out_file, indent=6)
|
||||
out_file.close()
|
||||
sys.stdout.write("payload %s \n" % patch_payload)
|
||||
self.auxcommands["rawpatch"].run(temp_file + " --service")
|
||||
os.remove(temp_file)
|
||||
elif newargs:
|
||||
for key in newargs[:-1][::-1]:
|
||||
if key == "PowerControl":
|
||||
payload = {key: [payload]}
|
||||
else:
|
||||
payload = {key: payload}
|
||||
patch_data.update(payload)
|
||||
if "Oem" in key:
|
||||
if (
|
||||
"managernetworkprotocol." in self.rdmc.app.selector
|
||||
or "thermal." in self.rdmc.app.selector
|
||||
):
|
||||
tempdir = "/tmp" if platform.system() == "Darwin" else tempfile.gettempdir()
|
||||
temp_file = os.path.join(tempdir, "temp_patch.json")
|
||||
out_file = open(temp_file, "w")
|
||||
if "managernetworkprotocol." in self.rdmc.app.selector:
|
||||
patchpath = self.rdmc.app.typepath.defs.managerpath + "NetworkProtocol/"
|
||||
elif "thermal." in self.rdmc.app.selector:
|
||||
patchpath = "/redfish/v1/Chassis/1/Thermal/"
|
||||
patch_payload = {patchpath: payload}
|
||||
json.dump(patch_payload, out_file, indent=6)
|
||||
out_file.close()
|
||||
sys.stdout.write("payload %s \n" % patch_payload)
|
||||
self.auxcommands["rawpatch"].run(temp_file + " --service")
|
||||
self.auxcommands["select"].run(self.rdmc.app.selector + " --refresh")
|
||||
os.remove(temp_file)
|
||||
if "PowerControl" in payload.keys():
|
||||
import platform
|
||||
import tempfile
|
||||
|
||||
tempdir = "/tmp" if platform.system() == "Darwin" else tempfile.gettempdir()
|
||||
temp_file = os.path.join(tempdir, "temp_patch.json")
|
||||
out_file = open(temp_file, "w")
|
||||
patch_path = "/redfish/v1/Chassis/1/Power"
|
||||
patch_payload = {patch_path: payload}
|
||||
json.dump(patch_payload, out_file, indent=6)
|
||||
out_file.close()
|
||||
self.auxcommands["rawpatch"].run(temp_file + " --service")
|
||||
os.remove(temp_file)
|
||||
|
||||
def run(self, line, skipprint=False, help_disp=False):
|
||||
"""Main set function
|
||||
|
||||
:param line: command line input
|
||||
:type line: string.
|
||||
:param skipprint: boolean to determine output
|
||||
:type skipprint: boolean.
|
||||
"""
|
||||
if help_disp:
|
||||
self.parser.print_help()
|
||||
return ReturnCodes.SUCCESS
|
||||
if (
|
||||
("Oem/Hpe/EnhancedDownloadPerformanceEnabled" in line[0])
|
||||
or ("Oem/Hpe/ThermalConfiguration" in line[0])
|
||||
or ("Oem/Hpe/FanPercentMinimum" in line[0])
|
||||
or ("PowerControl" in line[0])
|
||||
or (self.rdmc.app.selector is not None and "drive" in self.rdmc.app.selector.lower())
|
||||
):
|
||||
self.patchfunction(line)
|
||||
else:
|
||||
try:
|
||||
self.setfunction(line, skipprint=skipprint)
|
||||
except SecurityStateError:
|
||||
return ReturnCodes.V1_SECURITY_STATE_ERROR
|
||||
# Return code
|
||||
return ReturnCodes.SUCCESS
|
||||
|
||||
def setvalidation(self, options):
|
||||
"""Set data validation function"""
|
||||
|
||||
if self.rdmc.opts.latestschema:
|
||||
options.latestschema = True
|
||||
if self.rdmc.config.commit.lower() == "true":
|
||||
options.commit = True
|
||||
try:
|
||||
self.cmdbase.login_select_validation(self, options)
|
||||
except redfish.ris.NothingSelectedError:
|
||||
raise redfish.ris.NothingSelectedSetError("")
|
||||
|
||||
def definearguments(self, customparser):
|
||||
"""Wrapper function for new command main function
|
||||
|
||||
:param customparser: command line input
|
||||
:type customparser: parser.
|
||||
"""
|
||||
if not customparser:
|
||||
return
|
||||
|
||||
self.cmdbase.add_login_arguments_group(customparser)
|
||||
|
||||
customparser.add_argument(
|
||||
"--selector",
|
||||
dest="selector",
|
||||
help="Optionally include this flag to select a type to run"
|
||||
" the current command on. Use this flag when you wish to"
|
||||
" select a type without entering another command, or if you"
|
||||
" wish to work with a type that is different from the one"
|
||||
" you currently have selected.",
|
||||
default=None,
|
||||
)
|
||||
|
||||
customparser.add_argument(
|
||||
"--filter",
|
||||
dest="filter",
|
||||
help="Optionally set a filter value for a filter attribute."
|
||||
" This uses the provided filter for the currently selected"
|
||||
" type. Note: Use this flag to narrow down your results. For"
|
||||
" example, selecting a common type might return multiple"
|
||||
" objects that are all of that type. If you want to modify"
|
||||
" the properties of only one of those objects, use the filter"
|
||||
" flag to narrow down results based on properties."
|
||||
"\t\t\t\t\t Usage: --filter [ATTRIBUTE]=[VALUE]",
|
||||
default=None,
|
||||
)
|
||||
customparser.add_argument(
|
||||
"--commit",
|
||||
dest="commit",
|
||||
action="store_true",
|
||||
help="Use this flag when you are ready to commit all pending"
|
||||
" changes. Note that some changes made in this way will be updated"
|
||||
" instantly, while others will be reflected the next time the"
|
||||
" server is started.",
|
||||
default=None,
|
||||
)
|
||||
customparser.add_argument(
|
||||
"--reboot",
|
||||
dest="reboot",
|
||||
help="Use this flag to perform a reboot command function after"
|
||||
" completion of operations. For help with parameters and"
|
||||
" descriptions regarding the reboot flag, run help reboot.",
|
||||
default=None,
|
||||
)
|
||||
customparser.add_argument(
|
||||
"--latestschema",
|
||||
dest="latestschema",
|
||||
action="store_true",
|
||||
help="Optionally use the latest schema instead of the one "
|
||||
"requested by the file. Note: May cause errors in some data "
|
||||
"retrieval due to difference in schema versions.",
|
||||
default=None,
|
||||
)
|
||||
customparser.add_argument(
|
||||
"--uniqueoverride",
|
||||
dest="uniqueoverride",
|
||||
action="store_true",
|
||||
help="Override the measures stopping the tool from writing " "over items that are system unique.",
|
||||
default=None,
|
||||
)
|
||||
@@ -0,0 +1,203 @@
|
||||
###
|
||||
# Copyright 2016-2021 Hewlett Packard Enterprise, Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
###
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Status Command for RDMC"""
|
||||
|
||||
from functools import reduce
|
||||
|
||||
from redfish.ris.utils import merge_dict
|
||||
|
||||
try:
|
||||
from rdmc_helper import InvalidCommandLineErrorOPTS, ReturnCodes
|
||||
except ImportError:
|
||||
from ilorest.rdmc_helper import InvalidCommandLineErrorOPTS, ReturnCodes
|
||||
|
||||
|
||||
class StatusCommand:
|
||||
"""Constructor"""
|
||||
|
||||
def __init__(self):
|
||||
self.ident = {
|
||||
"name": "status",
|
||||
"usage": None,
|
||||
"description": "Run to display all pending changes within"
|
||||
" the currently\n\tselected type that need to be"
|
||||
" committed\n\texample: status",
|
||||
"summary": "Displays all pending changes within a selected type" " that need to be committed.",
|
||||
"aliases": [],
|
||||
"auxcommands": ["SelectCommand"],
|
||||
}
|
||||
self.cmdbase = None
|
||||
self.rdmc = None
|
||||
self.auxcommands = dict()
|
||||
|
||||
def run(self, line, help_disp=False):
|
||||
"""Main status worker function
|
||||
|
||||
:param line: command line input
|
||||
:type line: string.
|
||||
"""
|
||||
if help_disp:
|
||||
self.parser.print_help()
|
||||
return ReturnCodes.SUCCESS
|
||||
try:
|
||||
(options, _) = self.rdmc.rdmc_parse_arglist(self, line)
|
||||
except (InvalidCommandLineErrorOPTS, SystemExit):
|
||||
if ("-h" in line) or ("--help" in line):
|
||||
return ReturnCodes.SUCCESS
|
||||
else:
|
||||
raise InvalidCommandLineErrorOPTS("")
|
||||
|
||||
self.statusvalidation(options)
|
||||
contents = self.rdmc.app.status()
|
||||
selector = self.rdmc.app.selector
|
||||
|
||||
if contents and options.json:
|
||||
self.jsonout(contents)
|
||||
elif contents:
|
||||
self.outputpatches(contents, selector)
|
||||
else:
|
||||
self.rdmc.ui.printer("No changes found\n")
|
||||
|
||||
# Return code
|
||||
return ReturnCodes.SUCCESS
|
||||
|
||||
def jsonout(self, contents):
|
||||
"""Helper function to print json output of patches
|
||||
|
||||
:param contents: contents for the selection
|
||||
:type contents: string.
|
||||
"""
|
||||
self.rdmc.ui.printer("Current changes found:\n")
|
||||
createdict = lambda y, x: {x: y}
|
||||
totdict = {}
|
||||
for item in contents:
|
||||
for keypath, value in item.items():
|
||||
path = keypath.split("(")[1].strip("()")
|
||||
cont = {}
|
||||
totdict[path] = cont
|
||||
for content in value:
|
||||
val = (
|
||||
["List Manipulation"]
|
||||
if content["op"] == "move"
|
||||
else [content["value"].strip("\"'")] if len(content["value"]) else [""]
|
||||
)
|
||||
cont = reduce(
|
||||
createdict,
|
||||
reversed([path] + content["path"].strip("/").split("/") + val),
|
||||
)
|
||||
merge_dict(totdict, cont)
|
||||
self.rdmc.ui.print_out_json(totdict)
|
||||
|
||||
def outputpatches(self, contents, selector):
|
||||
"""Helper function for status for use in patches
|
||||
|
||||
:param contents: contents for the selection
|
||||
:type contents: string.
|
||||
:param selector: type selected
|
||||
:type selector: string.
|
||||
"""
|
||||
self.rdmc.ui.printer("Current changes found:\n")
|
||||
for item in contents:
|
||||
moveoperation = ""
|
||||
for key, value in item.items():
|
||||
if selector and key.lower().startswith(selector.lower()):
|
||||
self.rdmc.ui.printer("%s (Currently selected)\n" % key)
|
||||
else:
|
||||
self.rdmc.ui.printer("%s\n" % key)
|
||||
|
||||
for content in value:
|
||||
try:
|
||||
if content["op"] == "move":
|
||||
moveoperation = "/".join(content["path"].split("/")[1:-1])
|
||||
continue
|
||||
except:
|
||||
if content[0]["op"] == "move":
|
||||
moveoperation = "/".join(content[0]["path"].split("/")[1:-1])
|
||||
continue
|
||||
try:
|
||||
if isinstance(content[0]["value"], int):
|
||||
self.rdmc.ui.printer("\t%s=%s" % (content[0]["path"][1:], content[0]["value"]))
|
||||
elif not isinstance(content[0]["value"], bool) and not len(content[0]["value"]) == 0:
|
||||
if content[0]["value"][0] == '"' and content[0]["value"][-1] == '"':
|
||||
self.rdmc.ui.printer(
|
||||
"\t%s=%s"
|
||||
% (
|
||||
content[0]["path"][1:],
|
||||
content[0]["value"][1:-1],
|
||||
)
|
||||
)
|
||||
else:
|
||||
self.rdmc.ui.printer("\t%s=%s" % (content[0]["path"][1:], content[0]["value"]))
|
||||
else:
|
||||
output = content[0]["value"]
|
||||
|
||||
if not isinstance(output, bool):
|
||||
if len(output) == 0:
|
||||
output = '""'
|
||||
|
||||
self.rdmc.ui.printer("\t%s=%s" % (content[0]["path"][1:], output))
|
||||
except:
|
||||
if isinstance(content["value"], int):
|
||||
self.rdmc.ui.printer("\t%s=%s" % (content["path"][1:], content["value"]))
|
||||
elif (
|
||||
content["value"]
|
||||
and not isinstance(content["value"], bool)
|
||||
and not len(content["value"]) == 0
|
||||
):
|
||||
if content["value"][0] == '"' and content["value"][-1] == '"':
|
||||
self.rdmc.ui.printer("\t%s=%s" % (content["path"][1:], content["value"]))
|
||||
else:
|
||||
self.rdmc.ui.printer("\t%s=%s" % (content["path"][1:], content["value"]))
|
||||
else:
|
||||
output = content["value"]
|
||||
|
||||
if output and not isinstance(output, bool):
|
||||
if len(output) == 0:
|
||||
output = '""'
|
||||
|
||||
self.rdmc.ui.printer("\t%s=%s" % (content["path"][1:], output))
|
||||
self.rdmc.ui.printer("\n")
|
||||
if moveoperation:
|
||||
self.rdmc.ui.printer("\t%s=List Manipulation\n" % moveoperation)
|
||||
|
||||
def statusvalidation(self, options):
|
||||
"""Status method validation function"""
|
||||
|
||||
self.cmdbase.login_select_validation(self, options)
|
||||
|
||||
def definearguments(self, customparser):
|
||||
"""Wrapper function for new command main function
|
||||
|
||||
:param customparser: command line input
|
||||
:type customparser: parser.
|
||||
"""
|
||||
if not customparser:
|
||||
return
|
||||
|
||||
self.cmdbase.add_login_arguments_group(customparser)
|
||||
|
||||
customparser.add_argument(
|
||||
"-j",
|
||||
"--json",
|
||||
dest="json",
|
||||
action="store_true",
|
||||
help="Optionally include this flag if you wish to change the"
|
||||
" displayed output to JSON format. Preserving the JSON data"
|
||||
" structure makes the information easier to parse.",
|
||||
default=False,
|
||||
)
|
||||
@@ -0,0 +1,125 @@
|
||||
###
|
||||
# Copyright 2016-2021 Hewlett Packard Enterprise, Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
###
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Types Command for RDMC"""
|
||||
|
||||
try:
|
||||
from rdmc_helper import (
|
||||
InvalidCommandLineError,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
ReturnCodes,
|
||||
)
|
||||
except ImportError:
|
||||
from ilorest.rdmc_helper import (
|
||||
InvalidCommandLineError,
|
||||
InvalidCommandLineErrorOPTS,
|
||||
ReturnCodes,
|
||||
)
|
||||
|
||||
|
||||
class TypesCommand:
|
||||
"""Constructor"""
|
||||
|
||||
def __init__(self):
|
||||
self.ident = {
|
||||
"name": "types",
|
||||
"usage": None,
|
||||
"description": "Run to display currently " "available selectable types\n\tExample: types",
|
||||
"summary": "Displays all selectable types within the currently logged in server.",
|
||||
"aliases": [],
|
||||
"auxcommands": [],
|
||||
}
|
||||
self.cmdbase = None
|
||||
self.rdmc = None
|
||||
self.auxcommands = dict()
|
||||
|
||||
def typesfunction(self, line, returntypes=False):
|
||||
"""Main types worker function
|
||||
|
||||
:param line: command line input
|
||||
:type line: string.
|
||||
:param returntypes: flag to determine if types should be printed
|
||||
:type returntypes: boolean.
|
||||
"""
|
||||
try:
|
||||
(options, args) = self.rdmc.rdmc_parse_arglist(self, line)
|
||||
except (InvalidCommandLineErrorOPTS, SystemExit):
|
||||
if ("-h" in line) or ("--help" in line):
|
||||
return ReturnCodes.SUCCESS
|
||||
else:
|
||||
raise InvalidCommandLineErrorOPTS("")
|
||||
|
||||
self.typesvalidation(options)
|
||||
|
||||
if not args:
|
||||
typeslist = list()
|
||||
typeslist = sorted(set(self.rdmc.app.types(options.fulltypes)))
|
||||
|
||||
if not returntypes:
|
||||
self.rdmc.ui.printer("Type options:\n")
|
||||
|
||||
for item in typeslist:
|
||||
self.rdmc.ui.printer("%s\n" % item)
|
||||
else:
|
||||
return typeslist
|
||||
else:
|
||||
raise InvalidCommandLineError("The 'types' command does not take any arguments.")
|
||||
|
||||
self.cmdbase.logout_routine(self, options)
|
||||
|
||||
def run(self, line, help_disp=False):
|
||||
"""Wrapper function for types main function
|
||||
|
||||
:param line: command line input
|
||||
:type line: string.
|
||||
"""
|
||||
if help_disp:
|
||||
self.parser.print_help()
|
||||
return ReturnCodes.SUCCESS
|
||||
self.typesfunction(line)
|
||||
|
||||
# Return code
|
||||
return ReturnCodes.SUCCESS
|
||||
|
||||
def typesvalidation(self, options):
|
||||
"""types method validation function
|
||||
|
||||
:param options: command line options
|
||||
:type options: list.
|
||||
"""
|
||||
self.cmdbase.login_select_validation(self, options)
|
||||
|
||||
def definearguments(self, customparser):
|
||||
"""Wrapper function for new command main function
|
||||
|
||||
:param customparser: command line input
|
||||
:type customparser: parser.
|
||||
"""
|
||||
if not customparser:
|
||||
return
|
||||
|
||||
self.cmdbase.add_login_arguments_group(customparser)
|
||||
|
||||
customparser.add_argument(
|
||||
"--fulltypes",
|
||||
dest="fulltypes",
|
||||
action="store_true",
|
||||
help="Optionally include this flag if you would prefer to "
|
||||
"return the full type name instead of the simplified versions"
|
||||
" (Redfish only option).",
|
||||
default=None,
|
||||
)
|
||||
Whitespace-only changes.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Reference in new issue
Block a user