integ/bmc/redfishtool/files/v1.1.8/redfishtoollib/Chassis.py

844 lines
40 KiB
Python

# Copyright Notice:
# Copyright 2016 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/Redfishtool/blob/main/LICENSE.md
# redfishtool: Chassis.py
#
# contains Chassis subCommands and access functions
#
# Class RfSystemsMain
# - functions init, displayUsage, displayHelp, displayOperations,
# - runOperation - Chassis command table, dispatch of operation eg get, reset
# - ChassisMain - called from redfishMain, enforce legal option combinations,
# and call runOperation to run Chassis operations (sub-sub-command)
#
# Class RfChassisOperations
# All of the Chassis sub-command operations eg: get, setIndicatorLed, etc
# - hello - test cmd
# - getCollection - return the Chassis collection
# - get - get a member of a collection -or property of the member
# - list - show of list of collection members and key idetifying properties
# (Id, AssetTag, UriPath)
# - patch - raw subcommand to patch a Chassis Member, with etag support
# - setAssetTag -- patches the assetTag of Chassis instance w/ etag support
# - setIndicatorLed --sets id LED to a specified value w/ etag support
# - getPower - get Processors collection, processor instance, or all
# - getSensors - get all sensors
# - getThermal - get Ethernet collection, instance, all
# - setPowerLimit - Set the PowerLimit for a member of the powerControl array
# - getPowerReading [consumed] - get the powerControl array, or ConsumedWatts from pwrCntl[0]
# - getLogService - get LogService collection, instance, all
# - clearLog -- clears a specified log (not implemented yet)
# - examples --prints some example apis
#
from .redfishtoolTransport import RfTransport
import requests
import json
import getopt
import re
import sys
from .ServiceRoot import RfServiceRoot
from urllib.parse import urljoin
class RfChassisMain():
def __init__(self):
# operation string and remaining args
self.operation=None
self.args=None
self.argnum=0
self.nonIdCommands=None
def displayUsage(self,rft):
if(rft.quiet): return(0)
print(" Usage:")
print(" {} [OPTNS] Chassis <operation> [<args>] -- perform <operation> on the Chassis specified ".format(rft.program))
def displayHelp(self,rft):
self.displayUsage(rft)
self.displayOperations(rft)
print(" ")
def displayOperations(self,rft):
print(" <operations>:")
print(" [collection] -- get the main Chassis collection. (Default operation if no member specified)")
print(" [get] -- get the Chassis object. (Default operation if collection member specified)")
print(" list -- list information about the Chassis collection members(\"Id\", URI, and AssetTag)")
print(" patch {A: B,C: D,...} -- patch the json-formatted {prop: value...} data to the object")
print(" setAssetTag <assetTag> -- set the Chassis's asset tag ")
print(" setIndicatorLed <state> -- set the indicator LED. <state>=redfish defined values: Off, Lit, Blinking")
print(" Power -- get the full Power resource under a specified Chassis instance.")
print(" Thermal -- get the full Thermal resource under a specified Chassis instance.")
print(" Sensors -- get all sensors.")
print("")
print(" getPowerReading [-i<indx>] [consumed]-- get powerControl resource w/ power capacity, PowerConsumed, and power limits")
print(" if \"consumed\" keyword is added, then only current usage of powerControl[indx] is returned")
print(" <indx> is the powerControl array index. default is 0. normally, 0 is the only entry")
print(" setPowerLimit [-i<indx>] <limit> [<exception> [<correctionTime>]] -- set powerLimit control properties")
print(" <limit>=null disables power limiting. <indx> is the powerControl array indx (dflt=0)")
print("")
print(" Logs [list] -- get the Chassis \"LogServices\" collection , or list \"id\" and URI of members.")
print(" Logs [IDOPTN] -- get the member specified by IDOPTN: -i<id>, -m<prop>:<val>, -l<link>, -a #all")
print(" clearLog <id> -- clears the log defined by <id>")
print(" examples -- example commands with syntax")
print(" hello -- Chassis hello -- debug command")
return(0)
def runOperation(self,rft):
# instantiate ChassisOperations class
op=RfChassisOperations()
# dispatch table for each subcommand: "cmdName": cmdClass.cmdFunction"
operationTable = {
"collection": op.getCollection,
"get": op.get,
"list": op.clist,
"patch": op.patch,
"setAssetTag": op.setAssetTag,
"setIndicatorLed": op.setIndicatorLed,
"Power": op.getPower,
"Thermal": op.getThermal,
"Sensors": op.getSensors,
"setPowerLimit": op.setPowerLimit,
"getPowerReading": op.getPowerReading,
"Logs": op.getLogService,
"-clearLog": op.clearLog,
"hello": op.hello,
"examples": op.examples
}
rft.printVerbose(5,"Chassis:runOperation: operation: {}".format(self.operation))
rft.printVerbose(5,"Chassis:runOperation: args: {}".format(self.args))
if self.operation in operationTable:
rft.printVerbose(5,"Chassis:runOperation: found Oper: {} in table. executing".format(rft.subcommand))
rc,r,j,d=operationTable[self.operation](self, op, rft, cmdTop=True)
return(rc,r,j,d)
else: # invalid operation
rft.printErr("Chassis: Invalid operation: {}".format(self.operation))
return(2,None,False,None)
def ChassisMain(self,rft,cmdTop=False):
rft.printVerbose(4,"ChassisMain: subcommand: {}".format(rft.subcommand))
if( rft.help ):
self.displayHelp(rft)
return(0,None,False,None)
# we will validate usage of -P and -a in action processing
# actually, if a non 'get' action is specified, -P and -a are just ignored :)
args=rft.subcommandArgv[0:]
#if no args, then if no member Id was specified (with -I|-M|-1|-F) then assume it is a "collection" operation
# if a -IM1F was specified, then assume it is a "get" operation for that member
if( len(args) < 2 ):
if( rft.IdOptnCount==0 ):
self.operation="collection"
else:
self.operation="get"
self.args= None
else:
self.operation=args[1]
self.args = args[1:] # now args points to the 1st argument
self.argnum =len(self.args)
rft.printVerbose(5,"Chassis: operation={}, args={}".format(self.operation,self.args))
# check if the command requires a collection member target -I|-M|-L|-1|-F eg sysIdoptn
nonIdCommands = ["collection", "list", "examples", "hello"]
if( ( not self.operation in nonIdCommands ) and (rft.IdOptnCount==0) ):
# default to --One if no Id option specified
rft.oneOptn = True
rft.IdOptnCount += 1
# now execute the operation.
rc,r,j,d = self.runOperation(rft)
if(rc !=0 ):
rft.printVerbose(5,"Chassis: operation returned with error: rc={}".format(rc))
return(rc,r,False,None)
#else, if here, the subcommand executed without error. Return with 0 exit code
rft.printVerbose(5,"Chassis: operation exited OK")
return(rc,r,j,d)
#
# contains operations related to the Chassis subCommand
#
class RfChassisOperations():
def __init__(self):
self.chassisPath=None
self.chassisCollectionDict=None
def hello(self,sc,op,rft,cmdTop=False):
rft.printVerbose(4,"in hello")
rft.printVerbose(4," subcmd:{}, operation:{}, args:{}".format(rft.subcommand,sc.operation,sc.args))
print("hello world from Chassis")
return(0,None,False,None)
def getCollection(self,sc,op,rft,cmdTop=False, prop=None):
rft.printVerbose(4,"{}:{}: in getCollection".format(rft.subcommand,sc.operation))
# 1st get serviceRoot
svcRoot=RfServiceRoot()
rc,r,j,d = svcRoot.getServiceRoot(rft)
if( rc != 0 ):
rft.printErr("getCollection: Error getting service root, aborting")
return(rc,r,False,None)
# get the link to the Systems collection
# need to test we got good data
if (("Chassis" in d) and ("@odata.id" in d["Chassis"])):
systemsLink=d["Chassis"]["@odata.id"]
else:
rft.printErr("Error: service root does not have a Chassis link")
return(4)
rft.printVerbose(4,"Chassis:getCollection: link is: {}".format(systemsLink))
# if a -a option was entered with "Chassis" or "Chassis collection" operation,
# then return all members of the Chassis collection expanded
if((cmdTop is True) and (rft.allOptn is True) ):
collName="Chassis"
rft.printVerbose(4,"Expand Chassis collection to return ALL Chassis collection members fully expanded in response")
rc,r,j,d=rft.getAllCollectionMembers(rft, r.url, relPath=systemsLink)
if(rc==0):
rft.printVerbose(1," Get ALL {} Collection Members".format(collName,skip1=True, printV12=cmdTop))
# otherwise, just return the collection
# now read the /Chassis collection
# use the returned url as the base url to read the Chassis collection
else:
if cmdTop is True: prop=rft.prop
rc,r,j,d=rft.rftSendRecvRequest(rft.AUTHENTICATED_API, 'GET', r.url, relPath=systemsLink, prop=prop)
if(rc==0):
rft.printVerbose(1," Chassis Collection:",skip1=True, printV12=cmdTop)
return(rc,r,j,d)
def get(self,sc,op,rft, cmdTop=False, prop=None):
rft.printVerbose(4,"{}:{}: in operation".format(rft.subcommand,sc.operation))
# getCollection
rc,r,j,d=op.getCollection(sc,op, rft)
if( rc != 0): return(rc,r,False,None)
collUrl=r.url
# search collection to find path to system
sysPath,rc,r,j,d=rft.getPathBy(rft, r, d, prop)
if( rc !=0 ): #if a path was not found, its an error
return(rc,r,j,d)
rft.printVerbose(4,"ChassisOperations:get: got a path, now get entries")
if cmdTop is True: prop=rft.prop
#if here, rc=0
#if sysPath returned a response but we need to extract the property do it here
if( (r is not None) and (prop is not None) ):
rc,r,j,d=rft.getPropFromDict(rft,r,d,prop)
# otherwise, we need to do a GET to get the Chassis, if -P show property, else show full response
elif( r is None ):
rc,r,j,d=rft.rftSendRecvRequest(rft.AUTHENTICATED_API, 'GET', collUrl, relPath=sysPath, prop=prop)
if(rc==0): rft.printVerbose(1," Chassis Resource:",skip1=True, printV12=cmdTop)
return(rc,r,j,d)
def clist(self,sc,op,rft, cmdTop=False, prop=None):
rft.printVerbose(4,"{}:{}: in operation".format(rft.subcommand,sc.operation))
# getCollection
collName="Chassis"
rc,r,j,d=op.getCollection(sc,op, rft)
if( rc != 0): return(rc,r,False,None)
#loop through the members and create the list sub-operation response
rc,r,j,d=rft.listCollection(rft, r, d, prop="AssetTag")
if(rc==0):
rft.printVerbose(1," list {} Collection member info: Id, URI, AssetTag".format(collName,skip1=True, printV12=cmdTop))
return(rc,r,j,d)
def iterate_op(self, run_single, sc, op, rft, cmdTop=False, prop=None):
# Wrapper method to handle issuing commands to a single chassis or to all chassis in the collection
if rft.allOptn:
# Issue command to all chassis in collection
# get the list of chassis
rc, r, j, d = op.clist(sc, op, rft, cmdTop=cmdTop, prop=prop)
if rc != 0 or not j or d is None or not isinstance(d, dict) or 'Members' not in d:
rft.printErr("Unable to get list of Chassis; return code = {}, list data = {}".format(rc, d))
return rc, r, j, d
# save existing rft options
saved_allOptn = rft.allOptn
saved_Link = rft.Link
saved_gotIdOptn = rft.gotIdOptn
saved_IdOptnCount = rft.IdOptnCount
# set rft options to process a single item
rft.allOptn = False
rft.gotIdOptn = True
rft.IdOptnCount = 1
# iterate through chassis and run operation on each based on the link (@odata.id value)
members = d.get('Members')
rc, r, j, d = 8, None, False, None
for member in members:
if '@odata.id' in member:
link = member.get('@odata.id')
# set rft.Link to point to the target chassis
rft.Link = link
# perform the operation
rc, r, j, d = run_single(sc, op, rft, cmdTop=cmdTop, prop=prop)
else:
rft.printErr("No '@odata.id' found in chassis member: {}".format(member))
# restore existing rft options
rft.allOptn = saved_allOptn
rft.Link = saved_Link
rft.gotIdOptn = saved_gotIdOptn
rft.IdOptnCount = saved_IdOptnCount
return rc, r, j, d
else:
# Issue command to single specified chassis
return run_single(sc, op, rft, cmdTop=cmdTop, prop=prop)
def patch_single(self,sc,op,rft,cmdTop=False, prop=None, patchData=None, r=None):
rft.printVerbose(4,"{}:{}: in operation".format(rft.subcommand,sc.operation))
# verify we have got an argument which is the patch structure
# its in form '{ "AssetTag": <val>, "IndicatorLed": <val> }'
##print("patchData: {}".format(patchData))
if( len( sc.args) == 2):
##print("data:{}".format(sc.args[1]))
try:
patchData=json.loads(sc.args[1])
except ValueError:
rft.printErr("Patch: invalid Json input data:{}".format(sc.args[1]))
return(5,None,False,None)
##print("patchData: {}".format(patchData))
else:
rft.printErr("Patch: error: invalid argument format")
rft.printErr(" : args={}".format(sc.args))
rft.printErr(" : expect: Systems patch \"{ <prop>: <value> }\"")
return(4,None,False,None)
# read the Chassis resource
# this is used by the generic rft.patchResource() function to see if there is an etag in the response
# if an etag is in response hdr, then we must include the etag on the patch, so this get is required
# note: the format of etag header for redfish is: ETag: W/"<string>" or "<string"
rc,r,j,d=op.get(sc,op,rft)
if( rc != 0):
return(rc,r,False,None)
# now call the generic patch function to send the patch
rc,r,j,d=rft.patchResource(rft, r, patchData)
if(rc==0): rft.printVerbose(1," Chassis Patch:",skip1=True, printV12=cmdTop)
return(rc,r,j,d)
def patch(self, sc, op, rft, cmdTop=False, prop=None):
return op.iterate_op(op.patch_single, sc, op, rft, cmdTop=cmdTop, prop=prop)
def setAssetTag_single(self,sc,op,rft,cmdTop=False, prop=None):
rft.printVerbose(4,"{}:{}: in operation".format(rft.subcommand,sc.operation))
propName="AssetTag"
# get the asset tag from args
if(len(sc.args) < 2 ):
rft.printErr("Error, no assetTag value specified")
rft.printErr("Syntax: {} [options] Chassis setAssetTag \"string\" ".format(rft.program))
return(8,None,False,None)
assetTag=sc.args[1]
patchData={propName: assetTag}
# get the resource to verify it includes AssetTag,
# the response will also be used by Patch() to check for etag
rc,r,j,d=op.get(sc,op,rft)
if( rc != 0): return(rc,r,False,None)
if( not propName in d ):
rft.printErr("Chassis resource does not have a {} property.".format(propName))
return(8,r,False,None)
rc,r,j,d=rft.patchResource(rft, r, patchData)
if(rc==0):
rft.printVerbose(1," Chassis setAssetTag:",skip1=True, printV12=cmdTop)
assetTag={propName: d[propName]}
return(rc,r,j,assetTag)
else: return(rc,r,False,None)
def setAssetTag(self, sc, op, rft, cmdTop=False, prop=None):
return op.iterate_op(op.setAssetTag_single, sc, op, rft, cmdTop=cmdTop, prop=prop)
def setIndicatorLed_single(self,sc,op,rft,cmdTop=False, prop=None):
rft.printVerbose(4,"{}:{}: in operation".format(rft.subcommand,sc.operation))
propName="IndicatorLED"
# get the asset tag from args
validLedStates=["Lit","Blinking","Off"]
if(len(sc.args) < 2 ):
rft.printErr("Error, no ledState value specified")
rft.printErr("Syntax: {} [options] Chassis setIndicatorLed <Lit|Off|Blinking>".format(rft.program))
return(8,None,False,None)
targLedState=sc.args[1]
if not targLedState in validLedStates:
rft.printErr("Error, invalid LED state specified")
return(8,None,False,None)
patchData={propName: targLedState}
# get the resource to verify it includes IndicatorLED,
# the response will also be used by Patch() to check for etag
rc,r,j,d=op.get(sc,op,rft)
if( rc != 0): return(rc,r,False,None)
if( not propName in d ):
rft.printErr("System resource does not have a {} property.".format(propName))
return(8,r,False,None)
rc,r,j,d=rft.patchResource(rft, r, patchData)
if(rc==0):
rft.printVerbose(1," Chassis setIndicatorLed:",skip1=True, printV12=cmdTop)
ledState={"IndicatorLED": d["IndicatorLED"]}
return(rc,r,j,ledState)
else: return(rc,r,False,None)
def setIndicatorLed(self, sc, op, rft, cmdTop=False, prop=None):
return op.iterate_op(op.setIndicatorLed_single, sc, op, rft, cmdTop=cmdTop, prop=prop)
def getPower(self,sc,op, rft, cmdTop=False, prop=None):
rft.printVerbose(4,"{}:{}: in operation".format(rft.subcommand,sc.operation))
resName="Power"
# get the Chassis resource first
rc,r,j,d=op.get(sc, op, rft, cmdTop, resName)
if( rc != 0): return(rc,r,False,None)
# get the link to the Power resource under Chassis
if ((resName in d) and ("@odata.id" in d[resName])):
resLink=d[resName]["@odata.id"]
else:
rft.printErr("Error: Chassis resource does not have a {} link".format(resName))
return(6,None,False,None)
if cmdTop is True: prop=rft.prop
rc,r,j,d=rft.rftSendRecvRequest(rft.AUTHENTICATED_API, 'GET', r.url, relPath=resLink, prop=prop)
if(rc==0):
rft.printVerbose(1," {} Resource ".format(resName,skip1=True, printV12=cmdTop))
return(rc,r,j,d)
def getThermal(self,sc,op,rft,cmdTop=False, prop=None):
rft.printVerbose(4,"{}:{}: in operation".format(rft.subcommand,sc.operation))
resName="Thermal"
# get the Chassis resource first
rc,r,j,d=op.get(sc, op, rft, cmdTop, resName)
if( rc != 0): return(rc,r,False,None)
# get the link to the Thermal resource under Chassis
if ((resName in d) and ("@odata.id" in d[resName])):
resLink=d[resName]["@odata.id"]
else:
rft.printErr("Error: Chassis resource does not have a {} link".format(resName))
return(6,None,False,None)
if cmdTop is True: prop=rft.prop
rc,r,j,d=rft.rftSendRecvRequest(rft.AUTHENTICATED_API, 'GET', r.url, relPath=resLink, prop=prop)
if(rc==0):
rft.printVerbose(1," {} Resource ".format(resName,skip1=True, printV12=cmdTop))
return(rc,r,j,d)
def getPowerReading(self,sc,op,rft,cmdTop=False, prop=None):
rft.printVerbose(4,"{}:{}: in operation".format(rft.subcommand,sc.operation))
if cmdTop is True: prop=rft.prop
# check if there is an arg for the operation
if( sc.argnum > 1 ):
if( sc.args[1] == 'consumed' ):
prop="PowerConsumedWatts"
else:
rft.printErr("Error: getPowerReading: invalid argument: {}".format(sc.args[1]))
rft.printErr("Syntax: getPowerReading [-i<indx>] [consumed]")
return(4,None,False,None)
# get the Chassis Power resource
rc,r,j,d=op.getPower(sc,op, rft)
if( rc != 0): return(rc,r,False,None)
# get the Power Control Object
if ("PowerControl" in d ):
powerControl=d["PowerControl"]
powerControlMembers=len(powerControl)
else:
rft.printErr("Error: Chassis resource does not have a PowerControl resource")
return(4,None,False,None)
if(powerControlMembers == 0 ):
rft.printErr("Error: Chassis PowerControl array is empty")
return(4,None,False,None)
# get the powerControl array index
if( rft.IdLevel2 is None ):
indx=0
else:
indxPattern="(^0$)|(^([1-9][0-9]{,2})$)" # <decimal>: 33...
indxMatch=re.search(indxPattern,rft.IdLevel2)
if( indxMatch ):
indx=int(rft.IdLevel2) # convert base10 to integer
rft.printVerbose(4,"getPowerReading: Indx={}".format(indx))
else:
rft.printErr("Error: getPowerReading: invalid PowerControl index value: {}".format(rft.IdLevel2))
rft.printErr("Chassis getPowerReading [current] [-i<indx>] --<indx> is integer 0 - 99 (default is 0)")
if( (indx+1) > powerControlMembers ):
rft.printErr("Error: specified PowerControl index does not exist: indx={}, members={}".format(indx,powerControlMembers))
return(4,None,False,None)
#if here, we have a valid indx
if(prop is not None):
if( prop in powerControl[indx] ):
respDataVal=powerControl[indx][prop]
respData={prop: respDataVal}
rft.printVerbose(1," Get Current Power consumption (PowerConsumedWatts) of PowerControl[{}] resource".format(indx,skip1=True, printV12=cmdTop))
else:
rft.printErr("Error: Property {} not not returned in PowerControl[{}] resource".format(prop,indx))
return(4,r,j,d)
else:
respData=powerControl[indx] #return the full powerControl array
rft.printVerbose(1," Chassis PowerControl[{}] array:".format(indx,skip1=True, printV12=cmdTop))
return(rc,r,j,respData)
#setPowerLimit [-i<indx>] <limit> [<exception> [<correctionTime>]] -- set powerLimit control properties")
def setPowerLimit_single(self,sc,op,rft,cmdTop=False, prop=None):
rft.printVerbose(4,"{}:{}: in operation".format(rft.subcommand,sc.operation))
if cmdTop is True: prop=rft.prop
# check if there is a required 2nd arg <limit>
if( sc.argnum > 1 ):
limitPattern="(^null$)|(^0$)|(^([1-9][0-9]{,5})$)" # null | 0 | 8 | 33 |344 | 34333
limitMatch=re.search(limitPattern,sc.args[1]) # sc.args[1]=<limit>
if( limitMatch ):
if(sc.args[1] == "null"):
limit=None
else:
limit=int(sc.args[1]) # keep it a string
rft.printVerbose(4,"setPowerLimit: limit={}".format(limit))
powerLimitData={"LimitInWatts": limit }
else:
rft.printErr("Error: setPowerLimit: invalid <limit> value specified: {}".format(sc.args[1]))
rft.printErr("Chassis setPowerLimit [-i<indx>] <limit> [<exception> [<correctionTime>]] --limit=null | 0-99999")
return(8,None,False,None)
else:
rft.printErr("Error: setPowerLimit: no <limit> value specified: {}")
rft.printErr("Chassis setPowerLimit [-i<indx>] <limit> [<exception> [<correctionTime>]] --limit=null | 0-99999")
return(8,None,False,None)
# check if there is an optional 3rd arg <exception>
includeException=False
validExceptionVals=("NoAction", "HardPowerOff", "LogEventOnly", "Oem")
if (sc.argnum > 2 ):
exceptionVal=sc.args[2] # sc.args[2]=<exceptionEnum>
if( not exceptionVal in validExceptionVals ):
rft.printErr("Error: setPowerLimit: invalid <limit> value specified: {}".format(sc.args[2]))
rft.printErr("Chassis setPowerLimit [-i<indx>] <limit> [<exception> [<correctionTime>]] --limit=null | 0-99999")
return(8,None,False,None)
else:
rft.printVerbose(4,"setPowerLimit: exception={}".format(exceptionVal))
powerLimitData["LimitException"]=exceptionVal
includeException=True
# check if there is an optional 4th arg <correctionTime> in milliseconds
includeCorrectionTime=False
if (sc.argnum > 3 ):
correctionPattern="(^([1-9][0-9]{,6})$)" # 1-999999 ms
correctionMatch=re.search(correctionPattern,sc.args[3]) # sc.args[3]=<correctionInMs>
if( correctionMatch ):
correctionTime=int(sc.args[3]) # keep it a string
rft.printVerbose(4,"setPowerLimit: correctionInMs={}".format(correctionTime))
powerLimitData["CorrectionInMs"]=correctionTime
includeCorrectionTime=True
else:
rft.printErr("Error: setPowerLimit: invalid <correctionTime> value specified: {}".format(sc.args[3]))
rft.printErr("Chassis setPowerLimit [-i<indx>] <limit> [<exception> [<correctionTime>]] --correctionTime=1-999999 ms")
return(8,None,False,None)
# get the Chassis Power resource
rc,r,j,d=op.getPower(sc,op, rft)
if( rc != 0): return(rc,r,False,None)
# get the Power Control Object
if ("PowerControl" in d ):
powerControl=d["PowerControl"]
powerControlMembers=len(powerControl)
else:
rft.printErr("Error: Chassis resource does not have a PowerControl resource")
return(4,None,False,None)
if(powerControlMembers == 0 ):
rft.printErr("Error: Chassis PowerControl array is empty")
return(4,None,False,None)
# get the powerControl array index
if( rft.IdLevel2 is None ):
indx=0
else:
indxPattern="(^0$)|(^([1-9][0-9]*)$)" # <decimal>: 33...
indxMatch=re.search(indxPattern,rft.IdLevel2)
if( indxMatch ):
indx=int(rft.IdLevel2) # convert base10 to integer
rft.printVerbose(4,"setPowerLimit: Indx={}".format(indx))
else:
rft.printErr("Error: setPowerLimit: invalid PowerControl index: {}".format(rft.IdLevel2))
rft.printErr("Chassis setPowerLimit [current] [-i<indx>] --<indx> is integer 0 - 99 (default is 0)")
return(8,None,False,None)
if( (indx+1) > powerControlMembers ):
rft.printErr("Error: specified PowerControl index does not exist: indx={}, members={}".format(indx,powerControlMembers))
return(8,None,False,None)
# check that this PowerControl index member has the properties
if( not "LimitInWatts" in powerControl[indx]["PowerLimit"] ):
rft.printErr("Error: setPowerLimit: LimitInWatts property is not in rhost PowerControl[{}]".format(indx))
return(8,None,False,None)
if( ( includeException is True ) and ( not "LimitException" in powerControl[indx]["PowerLimit"] ) ):
rft.printErr("Error: setPowerLimit: LimitException property is not in rhost PowerControl[{}]".format(indx))
return(8,None,False,None)
if( ( includeCorrectionTime is True ) and ( not "CorrectionInMs" in powerControl[indx]["PowerLimit"] ) ):
rft.printErr("Error: setPowerLimit: CorrectionInMs property is not in rhost PowerControl[{}]".format(indx))
return(8,None,False,None)
# now build the final full patch data
#patchData={"PowerControl"[indx]: { "PowerLimit": powerLimitData } }
powerLimitRes={ "PowerLimit": powerLimitData }
patchData={ "PowerControl": [ {} ] }
empty={}
powerControlArray=list()
for i in range (0,powerControlMembers):
powerControlArray.append(empty)
powerControlArray[indx]=powerLimitRes
patchData["PowerControl"]=powerControlArray
rft.printVerbose(4,"setPowerLimit: patchData: {}".format(json.dumps(patchData)))
#call the generic patch command to send the patch. This takes care of etag support
rc,r,j,d=rft.patchResource(rft, r, patchData)
if(rc==0):
rft.printVerbose(1," SetPowerLimit [{}]:",indx, skip1=True, printV12=cmdTop)
powerLimit={"PowerLimit": d["PowerControl"][indx]["PowerLimit"]}
return(rc,r,j,powerLimit)
else: return(rc,r,False,None)
def setPowerLimit(self, sc, op, rft, cmdTop=False, prop=None):
return op.iterate_op(op.setPowerLimit_single, sc, op, rft, cmdTop=cmdTop, prop=prop)
def getLogService(self,sc,op,rft,cmdTop=False, prop=None):
rft.printVerbose(4,":{}:{}: in operation".format(rft.subcommand,sc.operation))
# get the Chassis resource
rc,r,j,d=op.get(sc,op, rft)
if( rc != 0): return(rc,r,False,None)
collName="LogServices"
# get the link to the LogServices collection
if ((collName in d) and ("@odata.id" in d[collName])):
logLink=d[collName]["@odata.id"]
else:
rft.printErr("Error: Chassis resource does not have a {} link".format(collName))
return(6,None,False,None)
if cmdTop is True: prop=rft.prop
# check if there is a list arg for the operation
if( sc.argnum > 1 and sc.args[1] == 'list' ):
#get the collection
rc,r,j,d=rft.rftSendRecvRequest(rft.AUTHENTICATED_API, 'GET', r.url, relPath=logLink)
#loop through the members and create the list sub-operation response
rc,r,j,d=rft.listCollection(rft, r, d, prop="Name")
if(rc==0):
rft.printVerbose(1," list {} Collection member info: Id, URI, Name".format(collName,skip1=True, printV12=cmdTop))
# else: check if no Log was specified. If not, return the collection
elif(rft.IdLevel2OptnCount==0):
rc,r,j,d=rft.rftSendRecvRequest(rft.AUTHENTICATED_API, 'GET', r.url, relPath=logLink, prop=prop)
if(rc==0):
rft.printVerbose(1," {} Collection ".format(collName,skip1=True, printV12=cmdTop))
# else: check if the -a (all) option is set. If not, return the proc specific by -i or -m
# search collection to find path using getPath2
elif( rft.allOptn is not True ):
# get the LogServices collection
rc,r,j,d=rft.rftSendRecvRequest(rft.AUTHENTICATED_API, 'GET', r.url, relPath=logLink, prop=prop)
collUrl=r.url
# now search for 2nd level resource and return
path2,rc,r,j,d=rft.getLevel2ResourceById(rft,r,d)
if(rc!=0):
return(rc,r,j,d)
# so rc=0
#if sysPath returned a response but we need to extract the property do it here
if( (r is not None) and (prop is not None) ):
rc,r,j,d=rft.getPropFromDict(rft,r,d,prop)
# otherwise, we need to do a GET to get the LogServices, if -P show property, else show full response
elif( r is None ):
rc,r,j,d=rft.rftSendRecvRequest(rft.AUTHENTICATED_API, 'GET', collUrl, relPath=path2, prop=prop)
if(rc==0):
rft.printVerbose(1," {} Collection Member ".format(collName,skip1=True, printV12=cmdTop))
# If '--Entries' specified, get "Entries" nav link and read it
if rc == 0 and rft.gotEntriesOptn:
if r is not None and j and isinstance(d, dict):
rft.printVerbose(1, 'getLogService: attempting to get Entries for Logs')
entries = d.get('Entries')
if entries is not None and isinstance(entries, dict):
entries_uri = entries.get('@odata.id')
if entries_uri is not None:
rc, r, j, d = rft.rftSendRecvRequest(rft.AUTHENTICATED_API, 'GET', r.url,
relPath=entries_uri, prop=prop)
else:
rft.printErr('getLogService: @odata.id not found in "Entries" property')
else:
rft.printErr('getLogService: "Entries" property not found in JSON payload')
else:
rft.printErr(
'Unable to fetch Entries property from previous response: response = {}, is_json = {}, type(json) = {}'
.format(r, j, type(d)))
# else, client specified the -a option requesting ALL of the LogServices members
# for logs, we will not support this. Its too much data.
else:
rft.printErr("Error: -a option not supported for LogServices")
return(6,None,False,None)
return(rc,r,j,d)
def clearLog(self,sc,op,rft,cmdTop=False, prop=None):
rft.printVerbose(4,"{}:{}: in operation".format(rft.subcommand,sc.operation))
return(8,None,False,None)
def getSensors(self,sc,op, rft, cmdTop=False, prop=None):
rft.printVerbose(4,"{}:{}: in operation".format(rft.subcommand,sc.operation))
sys.stdout.write("%-50s %-10s %-10s\n" % ("Sensor", "Reading", "UpperCritical"))
resName="Thermal"
# get the Chassis resource first
rc,r,j,d=op.get(sc, op, rft, cmdTop, resName)
if( rc != 0): return(rc,r,False,None)
# get the link to the Thermal resource under Chassis
if ((resName in d) and ("@odata.id" in d[resName])):
resLink=d[resName]["@odata.id"]
else:
rft.printErr("Error: Chassis resource does not have a {} link".format(resName))
return(6,None,False,None)
if cmdTop is True: prop=rft.prop
rc,r,j,d=rft.rftSendRecvRequest(rft.AUTHENTICATED_API, 'GET', r.url, relPath=resLink, prop=prop)
if(rc==0):
rft.printVerbose(1," {} Resource ".format(resName,skip1=True, printV12=cmdTop))
collection = ['Temperatures','Fans']
for collName in collection:
numOfLinks=len(d[collName])
for i in range (0,numOfLinks):
if collName== 'Fans':
sys.stdout.write("%-50s %-10s %-10s\n" % (d[collName][i]["MemberId"], d[collName][i].get("Reading","N/A"),"N/A"))
else:
sys.stdout.write("%-50s %-10s %-10s\n" % (d[collName][i]["MemberId"], d[collName][i].get("ReadingCelsius","N/A"), d[collName][i].get("UpperThresholdCritical","N/A)")))
resName="Sensors"
# get the Chassis resource first
rc,r,j,d=op.get(sc, op, rft, cmdTop, resName)
if( rc != 0): return(rc,r,False,None)
# get the link to the Thermal resource under Chassis
if ((resName in d) and ("@odata.id" in d[resName])):
resLink=d[resName]["@odata.id"]
else:
rft.printErr("Error: Chassis resource does not have a {} link".format(resName))
return(6,None,False,None)
if cmdTop is True: prop=rft.prop
rc,r,j,d=rft.rftSendRecvRequest(rft.AUTHENTICATED_API, 'GET', r.url, relPath=resLink, prop=prop)
if(rc==0):
rft.printVerbose(1," {} Resource ".format(resName,skip1=True, printV12=cmdTop))
numOfLinks=len(d["Members"])
for i in range (0,numOfLinks):
collName="Members"
rc1,r1,j1,d1=rft.rftSendRecvRequest(rft.AUTHENTICATED_API, 'GET', r.url, relPath=d[collName][i]["@odata.id"], prop=prop)
output=json.dumps(d1,indent=4)
sys.stdout.write("%-50s %-10s %-10s\n" % (d1["Id"], d1.get("Reading", "N/A"), d1.get("Thresholds", {}).get("UpperCritical",{}).get("Reading","N/A")))
return(rc,r,False,None)
def examples(self,sc,op,rft,cmdTop=False,prop=None):
rft.printVerbose(4,"{}:{}: in operation".format(rft.subcommand,sc.operation))
print(" {} -r<ip> Chassis # shows the Chassis collection".format(rft.program))
print(" {} -r<ip> Chassis list # lists Id, Uri, AssetTag for all Chassis".format(rft.program))
print(" {} -r<ip> Chassis -I <id> # gets the Chassis with Id=<d>".format(rft.program))
print(" {} -r<ip> Chassis -M AssetTag:12345 # gets the Chassis with AssetTag=12345".format(rft.program))
print(" {} -r<ip> Chassis -L <sysUrl> # gets the Chassis at URI=<systemUrl".format(rft.program))
print(" {} -r<ip> Chassis -F # get the First Chassis returned (for debug)".format(rft.program))
print(" {} -r<ip> Chassis -1 # get the first Chassis and verify that there is only one system".format(rft.program))
print(" {} -r<ip> Chassis -I <id> patch {{A: B,C: D,...}} # patch the json-formatted {{prop: value...}} data to the object".format(rft.program))
print(" {} -r<ip> Chassis -I <id> setAssetTag <assetTag> # set the system's asset tag ".format(rft.program))
print(" {} -r<ip> Chassis -I <id> setIndicatorLed <state> # set the indicator LED. <state>=redfish defined values: Off, Lit, Blinking".format(rft.program))
print(" {} -r<ip> Chassis -I<Id> Power # get the full chassis Power resource".format(rft.program))
print(" {} -r<ip> Chassis -I<Id> Thermal # get the full chassis Thermal resource".format(rft.program))
print(" {} -r<ip> Chassis -I<Id> getPowerReading[-i<indx> [consumed] # get chassis/Power powerControl[<indx>] resource".format(rft.program))
print(" # if optional \"consumed\" arg, then return only the PowerConsumedWatts prop")
print(" {} -r<ip> Chassis -L<Url> setPowerLimit [-i<indx>] <limit> [<exception> [<correctionTime>]] # set power limit".format(rft.program))
return(0,None,False,None)
'''
TODO:
1. clearlog not implemented
'''