308 lines
8.4 KiB
Python
308 lines
8.4 KiB
Python
"""
|
|
This module containts all the entry points for the redfish cli tools.
|
|
|
|
It uses argparse to add subparses.
|
|
|
|
All of this is developed and tested against Dell iDRACs at the moment. At some
|
|
point in its future there will be a lot of refactoring to deal with other OEMs
|
|
I expect.
|
|
"""
|
|
|
|
import json
|
|
import logging
|
|
import sys
|
|
|
|
# PYTHON_ARGCOMPLETE_OK
|
|
import argcomplete
|
|
|
|
from redfish_cli import api
|
|
from redfish_cli.api import storage
|
|
import redfish_cli.cli.jobs
|
|
|
|
|
|
from .parsers import parse_args
|
|
from .utils import error, table, write_output
|
|
|
|
|
|
def chassis(args):
|
|
"""Entry point: get the list of chassis"""
|
|
details = api.chassis(args.server, args.username, args.password)
|
|
write_output(details, output_format=args.format)
|
|
|
|
|
|
def chassis_details(args):
|
|
"""Entry point: get the details of a chassis"""
|
|
details = api.chassis_details(
|
|
args.server, args.username, args.password, args.chassis
|
|
)
|
|
write_output(details, output_format=args.format)
|
|
|
|
|
|
def create_logical_volume(args):
|
|
"""Stub for the create logical volume command"""
|
|
|
|
try:
|
|
result = storage.create_logical_volume(args)
|
|
write_output(result)
|
|
except api.exceptions.InvalidRaidLevel as exc:
|
|
error(exc.msg)
|
|
except api.exceptions.LogicalVolumeCreationFailure as exc:
|
|
error(json.dumps(exc.json, indent=2))
|
|
|
|
|
|
def delete_logical_volume(args):
|
|
"""Delete a logical volume"""
|
|
logging.debug(args)
|
|
|
|
try:
|
|
result = api.storage.delete_logical_volume(args)
|
|
write_output(
|
|
result,
|
|
output_format=args.format,
|
|
)
|
|
# except api.exceptions.FailedToGetJobID as exc:
|
|
# details = exc.msg
|
|
# error_msg = (
|
|
# "An error has occured. The usual cause is that the disk "
|
|
# f"specified ({args.disk}) does not exist\n"
|
|
# f"{details}"
|
|
# )
|
|
# error(error_msg)
|
|
|
|
except api.exceptions.ResponseNotOK as exc:
|
|
details = exc.response.text
|
|
error_msg = (
|
|
"An error has occured. The usual cause is that the disk "
|
|
f"specified ({args.disk}) does not exist\n"
|
|
f"{details}"
|
|
)
|
|
error(error_msg)
|
|
|
|
|
|
def configure_logging(args):
|
|
"""Configure logging for the cli"""
|
|
log_format = (
|
|
"%(asctime)s - %(pathname)s:%(funcName)s - %(levelname)s - %(message)s"
|
|
)
|
|
|
|
logging.basicConfig(
|
|
filename="redfish.log",
|
|
level=getattr(logging, args.log_level.upper()),
|
|
format=log_format,
|
|
)
|
|
|
|
|
|
def get(args):
|
|
"""
|
|
Write the results of an arbitrary get on the specified url to stdout (using
|
|
print).
|
|
|
|
Currently it always dumps the results as json, but it should respect the
|
|
the output format in the args.
|
|
|
|
It will also just exit with an error message if a url requires
|
|
authentication and no username and password is supplied. This could be
|
|
handled better.
|
|
|
|
"""
|
|
url = args.url
|
|
if url is None:
|
|
url = ""
|
|
|
|
if args.expand:
|
|
url += "?$expand=.($levels=1)"
|
|
try:
|
|
result = api.utils.get(
|
|
args.server,
|
|
url,
|
|
username=args.username,
|
|
password=args.password,
|
|
)
|
|
write_output(
|
|
result,
|
|
output_format=args.format,
|
|
)
|
|
|
|
except api.exceptions.Unauthorized:
|
|
error("This url requires authentication\n")
|
|
except api.exceptions.ResponseNotOK as exc:
|
|
error(json.dumps(json.loads(exc.response.text), indent=2))
|
|
|
|
|
|
def logical_volume(args):
|
|
"""
|
|
Entry point: get the details of a logical volume.
|
|
|
|
By default the first logical drive in the first storage controller of the
|
|
first system.
|
|
|
|
"""
|
|
logging.debug(
|
|
"server: %s username: %s system: %s controller: %s drive: %s",
|
|
args.server,
|
|
args.username,
|
|
args.system,
|
|
args.controller,
|
|
args.drive,
|
|
)
|
|
|
|
try:
|
|
write_output(
|
|
storage.logical_volume_details(args),
|
|
output_format=args.format,
|
|
)
|
|
except api.exceptions.ResponseNotOK as exc:
|
|
error(json.dumps(json.loads(exc.response.text), indent=2))
|
|
|
|
|
|
def logical_volumes(args):
|
|
"""
|
|
Entry point: get the list of logical volumes attached to a storage
|
|
controller (which in turn is part of a system)
|
|
"""
|
|
|
|
try:
|
|
result = storage.list_logical_volumes(args)
|
|
write_output(
|
|
result,
|
|
output_format=args.format,
|
|
)
|
|
except api.exceptions.ResponseNotOK as exc:
|
|
error(json.dumps(json.loads(exc.response.text), indent=2))
|
|
|
|
|
|
def physical_volume(args):
|
|
"""
|
|
Entry point: get the list of physical volumes attached to a storage
|
|
controller (which in turn is part of a system)
|
|
"""
|
|
data = storage.physical_volume(args)
|
|
|
|
# if args.format == "text":
|
|
# result = "\n".join([ f"{x['system']} {x['drive']}" for x in data])
|
|
# elif args.format == "json":
|
|
# result = data
|
|
# elif args.format == "table":
|
|
# if args.verbose:
|
|
# table = [ [x['system'], x['drive'], x['url']] for x in data]
|
|
# headers=["System", "Drive", "URL"]
|
|
# else:
|
|
# table = [ [x['system'], x['drive']] for x in data]
|
|
# headers=["System", "Drive"]
|
|
|
|
# result = tabulate(table, headers=headers, tablefmt="outline")
|
|
|
|
result = data
|
|
|
|
write_output(result, output_format=args.format)
|
|
|
|
|
|
def physical_volumes(args):
|
|
"""
|
|
Entry point: get the list of physical volumes attached to a storage
|
|
controller (which in turn is part of a system)
|
|
"""
|
|
data = storage.list_physical_volumes(args)
|
|
|
|
if args.format == "text":
|
|
result = "\n".join([f"{x['system']} {x['drive']}" for x in data])
|
|
elif args.format == "json":
|
|
result = data
|
|
elif args.format == "table":
|
|
if args.verbose:
|
|
data = [[x["system"], x["drive"], x["url"]] for x in data]
|
|
headers = ["System", "Drive", "URL"]
|
|
else:
|
|
data = [[x["system"], x["drive"]] for x in data]
|
|
headers = ["System", "Drive"]
|
|
|
|
result = table(data, headers=headers)
|
|
|
|
write_output(result, output_format=args.format)
|
|
|
|
|
|
def product(args):
|
|
"""Entry point: get the product name of a server"""
|
|
details = api.product(args.server)
|
|
write_output(details, output_format=args.format)
|
|
|
|
|
|
def redfish(args=None):
|
|
"""
|
|
Entrypoint: Base command, gets args from stdin unless they are passed in as
|
|
a parameter (which probably means we are being called from a test)
|
|
"""
|
|
if args is None:
|
|
args = parse_args(sys.argv[1:])
|
|
|
|
if args.debug:
|
|
args.log_level = "DEBUG"
|
|
|
|
configure_logging(args)
|
|
|
|
if "func" in args:
|
|
args.func(args)
|
|
else:
|
|
write_output(api.utils.get(args.server, ""), output_format=args.format)
|
|
|
|
|
|
def service_tag(args):
|
|
"""Entry point: get the service tag of a Dell server"""
|
|
try:
|
|
write_output(api.service_tag(args.server), output_format=args.format)
|
|
except api.exceptions.DellOnly:
|
|
error("Service tags are only available for Dell iDRACs")
|
|
|
|
|
|
def storage_controller(args):
|
|
"""Entry point: get the details of a storage controllers in a server"""
|
|
|
|
try:
|
|
result = storage.storage_controller_details(args)
|
|
write_output(
|
|
result,
|
|
output_format=args.format,
|
|
)
|
|
except api.exceptions.ResponseNotOK as exc:
|
|
error(json.dumps(json.loads(exc.response.text), indent=2))
|
|
|
|
|
|
def storage_controllers(args):
|
|
"""Entry point: get the list of storage controllers in a server"""
|
|
|
|
result = storage.list_storage_controllers(args)
|
|
|
|
if not args.verbose:
|
|
controller_list = []
|
|
for i in result["Members"]:
|
|
controller_list.append(i["@odata.id"].split("/")[-1])
|
|
|
|
result = controller_list
|
|
|
|
if args.format == "text":
|
|
result = "\n".join(result)
|
|
elif args.format == "table":
|
|
data = []
|
|
for row in result:
|
|
data.append([row])
|
|
result = table(data, headers=["Controller"])
|
|
|
|
write_output(
|
|
result,
|
|
output_format=args.format,
|
|
)
|
|
|
|
|
|
def system_details(args):
|
|
"""Entry point: get the details of a system in a server"""
|
|
details = api.power.system_details(
|
|
args.server, args.username, args.password, args.system
|
|
)
|
|
write_output(details, output_format=args.format)
|
|
|
|
|
|
def version(args):
|
|
"""Entry point: get the verion of redfish implemented by the BMC"""
|
|
redfish_version = api.redfish_version(args.server)
|
|
|
|
write_output(redfish_version, output_format=args.format)
|