Remove callback arguments from most functions.
After some contemplation, I realized that given the underlying behavior of 'wait_for_rsp', that synchronous and asynchronous calls play well with each other. The pattern of considering an 'onlogon' function as running in a sort of greenthread works well and leads to much more comprehensible code for the average person. While removing those arguments, the module contents were reorganized to serve as an example of how more straightforward code written in this fashion may be. Change-Id: I9c83660e4d3c68ad8ae0c016a3377b2a0e7ee6ec
This commit is contained in:
parent
86a2d39db7
commit
b985624a4b
263
ipmi/command.py
263
ipmi/command.py
@ -49,14 +49,6 @@ power_states = {
|
||||
}
|
||||
|
||||
|
||||
def _raiseorcall(callback, response, args=None):
|
||||
if callback is None:
|
||||
if 'error' in response:
|
||||
raise Exception(response['error'])
|
||||
else:
|
||||
session.call_with_optional_args(callback, args)
|
||||
|
||||
|
||||
class Command(object):
|
||||
"""Send IPMI commands to BMCs.
|
||||
|
||||
@ -74,18 +66,37 @@ class Command(object):
|
||||
:param bmc: hostname or ip address of the BMC
|
||||
:param userid: username to use to connect
|
||||
:param password: password to connect to the BMC
|
||||
:param onlogon: function to run when logon completes in an asynchronous
|
||||
fashion. This will result in a greenthread behavior.
|
||||
:param kg: Optional parameter to use if BMC has a particular Kg configured
|
||||
"""
|
||||
|
||||
def __init__(self, bmc, userid, password, kg=None):
|
||||
def __init__(self, bmc, userid, password, onlogon=None, kg=None):
|
||||
# TODO(jbjohnso): accept tuples and lists of each parameter for mass
|
||||
# operations without pushing the async complexities up the stack
|
||||
self.ipmi_session = session.Session(bmc=bmc,
|
||||
userid=userid,
|
||||
password=password,
|
||||
kg=kg)
|
||||
self.onlogon = onlogon
|
||||
self.bmc = bmc
|
||||
if onlogon is not None:
|
||||
self.ipmi_session = session.Session(bmc=bmc,
|
||||
userid=userid,
|
||||
password=password,
|
||||
onlogon=self.logged,
|
||||
kg=kg)
|
||||
else:
|
||||
self.ipmi_session = session.Session(bmc=bmc,
|
||||
userid=userid,
|
||||
password=password,
|
||||
kg=kg)
|
||||
|
||||
def get_bootdev(self, callback=None, callback_args=None):
|
||||
def logged(self, response):
|
||||
self.onlogon(response, self)
|
||||
|
||||
@classmethod
|
||||
def eventloop(cls):
|
||||
while (session.Session.wait_for_rsp()):
|
||||
pass
|
||||
|
||||
def get_bootdev(self):
|
||||
"""Get current boot device override information.
|
||||
|
||||
Provides the current requested boot device. Be aware that not all IPMI
|
||||
@ -93,29 +104,32 @@ class Command(object):
|
||||
BIOS or UEFI fail to honor it. This is usually only applicable to the
|
||||
next reboot.
|
||||
|
||||
:param callback: optional callback
|
||||
:param callback_args: optional arguments to callback
|
||||
:returns: dict or True -- If callback is not provided, the response
|
||||
will be provided in the return
|
||||
:returns: dict --The response will be provided in the return as a dict
|
||||
"""
|
||||
self.commandcallback = callback
|
||||
self.commandcallbackargs = callback_args
|
||||
self.ipmi_session.raw_command(netfn=0,
|
||||
command=9,
|
||||
data=(5, 0, 0),
|
||||
callback=self._got_bootdev)
|
||||
return self._waitifsync()
|
||||
response = self.ipmi_session.raw_command(netfn=0,
|
||||
command=9,
|
||||
data=(5, 0, 0))
|
||||
# interpret response per 'get system boot options'
|
||||
if 'error' in response:
|
||||
return response
|
||||
# this should only be invoked for get system boot option complying to
|
||||
# ipmi spec and targeting the 'boot flags' parameter
|
||||
assert (response['command'] == 9 and
|
||||
response['netfn'] == 1 and
|
||||
response['data'][0] == 1 and
|
||||
(response['data'][1] & 0b1111111) == 5)
|
||||
if (response['data'][1] & 0b10000000 or
|
||||
not response['data'][2] & 0b10000000):
|
||||
return {'bootdev': 'default'}
|
||||
else: # will consult data2 of the boot flags parameter for the data
|
||||
bootnum = (response['data'][3] & 0b111100) >> 2
|
||||
bootdev = boot_devices[bootnum]
|
||||
if (bootdev):
|
||||
return {'bootdev': bootdev}
|
||||
else:
|
||||
return {'bootdev': bootnum}
|
||||
|
||||
def _waitifsync(self):
|
||||
self.requestpending = True
|
||||
if self.commandcallback is None:
|
||||
while self.requestpending:
|
||||
session.Session.wait_for_rsp()
|
||||
return self.lastresponse
|
||||
return True
|
||||
|
||||
def set_power(self, powerstate, wait=False, callback=None,
|
||||
callback_args=None):
|
||||
def set_power(self, powerstate, wait=False):
|
||||
"""Request power state change
|
||||
|
||||
:param powerstate:
|
||||
@ -127,79 +141,39 @@ class Command(object):
|
||||
* reset -- Request system reset without waiting for
|
||||
OS
|
||||
* boot -- If system is off, then 'on', else 'reset'
|
||||
:param wait: If True, do not return or callback until system actually
|
||||
completes requested state change
|
||||
:param callback: optional callback
|
||||
:param callback_args: optional arguments to callback
|
||||
:returns: dict or True -- If callback is not provided, the response
|
||||
:param wait: If True, do not return until system actually completes
|
||||
requested state change
|
||||
:returns: dict -- A dict describing the response retrieved
|
||||
"""
|
||||
self.commandcallback = callback
|
||||
self.commandcallbackargs = callback_args
|
||||
if powerstate not in power_states:
|
||||
_raiseorcall(self.commandcallback,
|
||||
{'error':
|
||||
"Unknown power state %s requested" % powerstate},
|
||||
self.commandcallbackargs)
|
||||
raise Exception("Unknown power state %s requested" % powerstate)
|
||||
self.newpowerstate = powerstate
|
||||
self.wait_for_power = wait
|
||||
self.ipmi_session.raw_command(netfn=0,
|
||||
command=1,
|
||||
callback=self._set_power_with_chassisinfo
|
||||
)
|
||||
return self._waitifsync()
|
||||
|
||||
def _set_power_with_chassisinfo(self, response):
|
||||
response = self.ipmi_session.raw_command(netfn=0, command=1)
|
||||
if 'error' in response:
|
||||
_raiseorcall(
|
||||
self.commandcallback, response, self.commandcallbackargs)
|
||||
return
|
||||
return response
|
||||
self.powerstate = 'on' if (response['data'][0] & 1) else 'off'
|
||||
if self.newpowerstate == 'boot':
|
||||
self.newpowerstate = 'on' if self.powerstate == 'off' else 'reset'
|
||||
self.ipmi_session.raw_command(netfn=0,
|
||||
command=2,
|
||||
data=[power_states[self.newpowerstate]],
|
||||
callback=self._power_set)
|
||||
|
||||
def _power_set(self, response):
|
||||
response = self.ipmi_session.raw_command(
|
||||
netfn=0, command=2, data=[power_states[self.newpowerstate]])
|
||||
if 'error' in response:
|
||||
_raiseorcall(
|
||||
self.commandcallback, response, self.commandcallbackargs)
|
||||
return
|
||||
return response
|
||||
self.lastresponse = {'pendingpowerstate': self.newpowerstate}
|
||||
if (self.wait_for_power and
|
||||
if (wait and
|
||||
self.newpowerstate in ('on', 'off', 'shutdown', 'softoff')):
|
||||
if self.newpowerstate in ('softoff', 'shutdown'):
|
||||
self.waitpowerstate = 'off'
|
||||
else:
|
||||
self.waitpowerstate = self.newpowerstate
|
||||
self.ipmi_session.raw_command(netfn=0,
|
||||
command=1,
|
||||
callback=self._power_wait)
|
||||
currpowerstate = None
|
||||
while currpowerstate != self.waitpowerstate:
|
||||
response = self.ipmi_session.raw_command(netfn=0, command=1)
|
||||
if 'error' in response:
|
||||
return response
|
||||
currpowerstate = 'on' if (response['data'][0] & 1) else 'off'
|
||||
return {'powerstate': currpowerstate}
|
||||
else:
|
||||
self.requestpending = False
|
||||
if self.commandcallback:
|
||||
session.call_with_optional_args(self.commandcallback,
|
||||
self.lastresponse,
|
||||
self.commandcallbackargs)
|
||||
|
||||
def _power_wait(self, response):
|
||||
if 'error' in response:
|
||||
_raiseorcall(
|
||||
self.commandcallback, response, self.commandcallbackargs)
|
||||
return
|
||||
self.powerstate = 'on' if (response['data'][0] & 1) else 'off'
|
||||
if self.powerstate == self.waitpowerstate:
|
||||
self.requestpending = False
|
||||
self.lastresponse = {'powerstate': self.powerstate}
|
||||
if self.commandcallback:
|
||||
session.call_with_optional_args(self.commandcallback,
|
||||
self.lastresponse,
|
||||
self.commandcallbackargs)
|
||||
return
|
||||
self.ipmi_session.raw_command(netfn=0,
|
||||
command=1,
|
||||
callback=self._power_wait)
|
||||
return self.lastresponse
|
||||
|
||||
def set_bootdev(self,
|
||||
bootdev,
|
||||
@ -232,10 +206,7 @@ class Command(object):
|
||||
self.commandcallback = callback
|
||||
self.commandcallbackargs = callback_args
|
||||
if bootdev not in boot_devices:
|
||||
_raiseorcall(self.commandcallback,
|
||||
{'error': "Unknown bootdevice %s requested" %
|
||||
bootdev},
|
||||
self.commandcallbackargs)
|
||||
return {'error': "Unknown bootdevice %s requested" % bootdev}
|
||||
self.bootdev = boot_devices[bootdev]
|
||||
self.persistboot = persist
|
||||
self.uefiboot = uefiboot
|
||||
@ -243,21 +214,11 @@ class Command(object):
|
||||
# then move on to set chassis capabilities
|
||||
self.requestpending = True
|
||||
# Set System Boot Options is netfn=0, command=8, data
|
||||
self.ipmi_session.raw_command(netfn=0,
|
||||
command=8, data=(3, 8),
|
||||
callback=self._bootdev_timer_disabled)
|
||||
if callback is None:
|
||||
while self.requestpending:
|
||||
session.Session.wait_for_rsp()
|
||||
return self.lastresponse
|
||||
|
||||
def _bootdev_timer_disabled(self, response):
|
||||
self.requestpending = False
|
||||
response = self.ipmi_session.raw_command(netfn=0, command=8,
|
||||
data=(3, 8))
|
||||
self.lastresponse = response
|
||||
if 'error' in response:
|
||||
_raiseorcall(
|
||||
self.commandcallback, response, self.commandcallbackargs)
|
||||
return
|
||||
return response
|
||||
bootflags = 0x80
|
||||
if self.uefiboot:
|
||||
bootflags = bootflags | 1 << 5
|
||||
@ -266,18 +227,12 @@ class Command(object):
|
||||
if self.bootdev == 0:
|
||||
bootflags = 0
|
||||
data = (5, bootflags, self.bootdev, 0, 0, 0)
|
||||
self.ipmi_session.raw_command(netfn=0,
|
||||
command=8,
|
||||
data=data,
|
||||
callback=self.commandcallback,
|
||||
callback_args=self.commandcallbackargs)
|
||||
response = self.ipmi_session.raw_command(netfn=0, command=8, data=data)
|
||||
if 'error' in response:
|
||||
return response
|
||||
return {'bootdev': bootdev}
|
||||
|
||||
def raw_command(self,
|
||||
netfn,
|
||||
command,
|
||||
data=(),
|
||||
callback=None,
|
||||
callback_args=None):
|
||||
def raw_command(self, netfn, command, data=()):
|
||||
"""Send raw ipmi command to BMC
|
||||
|
||||
This allows arbitrary IPMI bytes to be issued. This is commonly used
|
||||
@ -288,74 +243,22 @@ class Command(object):
|
||||
:param netfn: Net function number
|
||||
:param command: Command value
|
||||
:param data: Command data as a tuple or list
|
||||
:param callback: optional callback
|
||||
:param callback_args: optional arguments to callback
|
||||
:returns: dict or True -- If callback is not provided, the response
|
||||
:returns: dict -- The response from IPMI device
|
||||
"""
|
||||
response = self.ipmi_session.raw_command(netfn=0,
|
||||
command=1,
|
||||
callback=callback,
|
||||
callback_args=callback_args)
|
||||
if response: # this means there was no callback
|
||||
if 'error' in response:
|
||||
raise Exception(response['error'])
|
||||
return response
|
||||
return self.ipmi_session.raw_command(netfn=netfn, command=command)
|
||||
|
||||
def _got_bootdev(self, response):
|
||||
# interpret response per 'get system boot options'
|
||||
self.requestpending = False
|
||||
if 'error' in response:
|
||||
_raiseorcall(
|
||||
self.commandcallback, response, self.commandcallbackargs)
|
||||
return
|
||||
# this should only be invoked for get system boot option complying to
|
||||
# ipmi spec and targeting the 'boot flags' parameter
|
||||
assert (response['command'] == 9 and
|
||||
response['netfn'] == 1 and
|
||||
response['data'][0] == 1 and
|
||||
(response['data'][1] & 0b1111111) == 5)
|
||||
if (response['data'][1] & 0b10000000 or
|
||||
not response['data'][2] & 0b10000000):
|
||||
self.lastresponse = {'bootdev': 'default'}
|
||||
else: # will consult data2 of the boot flags parameter for the data
|
||||
bootnum = (response['data'][3] & 0b111100) >> 2
|
||||
bootdev = boot_devices[bootnum]
|
||||
if (bootdev):
|
||||
self.lastresponse = {'bootdev': bootdev}
|
||||
else:
|
||||
self.lastresponse = {'bootdev': bootnum}
|
||||
if self.commandcallback:
|
||||
session.call_with_optional_args(self.commandcallback,
|
||||
self.lastresponse,
|
||||
self.commandcallbackargs)
|
||||
|
||||
def get_power(self, callback=None, callback_args=None):
|
||||
def get_power(self):
|
||||
"""Get current power state of the managed system
|
||||
|
||||
The response, if successful, should contain 'powerstate' key and
|
||||
either 'on' or 'off' to indicate current state.
|
||||
|
||||
:param callback: optional callback
|
||||
:param callback_args: optional arguments to callback
|
||||
:returns: dict or True -- If callback is not provided, the response
|
||||
:returns: dict -- {'powerstate': value}
|
||||
"""
|
||||
self.commandcallback = callback
|
||||
self.commandcallbackargs = callback_args
|
||||
self.ipmi_session.raw_command(netfn=0,
|
||||
command=1,
|
||||
callback=self._got_power)
|
||||
return self._waitifsync()
|
||||
|
||||
def _got_power(self, response):
|
||||
self.requestpending = False
|
||||
response = self.ipmi_session.raw_command(netfn=0, command=1)
|
||||
if 'error' in response:
|
||||
_raiseorcall(
|
||||
self.commandcallback, response, self.commandcallbackargs)
|
||||
raise Exception(response['error'])
|
||||
return
|
||||
assert(response['command'] == 1 and response['netfn'] == 1)
|
||||
self.powerstate = 'on' if (response['data'][0] & 1) else 'off'
|
||||
self.lastresponse = {'powerstate': self.powerstate}
|
||||
if self.commandcallback:
|
||||
session.call_with_optional_args(self.commandcallback,
|
||||
self.lastresponse,
|
||||
self.commandcallbackargs)
|
||||
return {'powerstate': self.powerstate}
|
||||
|
@ -194,8 +194,7 @@ class Session:
|
||||
password,
|
||||
port=623,
|
||||
kg=None,
|
||||
onlogon=None,
|
||||
onlogonargs=None):
|
||||
onlogon=None):
|
||||
self.lastpayload = None
|
||||
self.bmc = bmc
|
||||
self.userid = userid
|
||||
@ -207,7 +206,6 @@ class Session:
|
||||
else:
|
||||
self.kg = password
|
||||
self.port = port
|
||||
self.onlogonargs = onlogonargs
|
||||
if (onlogon is None):
|
||||
self.async = False
|
||||
self.onlogon = self._sync_login
|
||||
@ -464,7 +462,7 @@ class Session:
|
||||
|
||||
def _got_channel_auth_cap(self, response):
|
||||
if 'error' in response:
|
||||
call_with_optional_args(self.onlogon, response, self.onlogonargs)
|
||||
self.onlogon(response)
|
||||
return
|
||||
if response['code'] == 0xcc and self.ipmi15only is not None:
|
||||
# tried ipmi 2.0 against a 1.5 which should work, but some bmcs
|
||||
@ -474,9 +472,7 @@ class Session:
|
||||
mysuffix = " while trying to get channel authentication capabalities"
|
||||
errstr = get_ipmi_error(response, suffix=mysuffix)
|
||||
if errstr:
|
||||
call_with_optional_args(self.onlogon,
|
||||
{'error': errstr},
|
||||
self.onlogonargs)
|
||||
self.onlogon({'error': errstr})
|
||||
return
|
||||
data = response['data']
|
||||
self.currentchannel = data[0]
|
||||
@ -484,11 +480,9 @@ class Session:
|
||||
self.ipmiversion = 2.0
|
||||
if self.ipmiversion == 1.5:
|
||||
if not (data[1] & 0b100):
|
||||
call_with_optional_args(
|
||||
self.onlogon,
|
||||
self.onlogon(
|
||||
{'error':
|
||||
"MD5 required but not enabled/available on target BMC"},
|
||||
self.onlogonargs)
|
||||
"MD5 required but not enabled/available on target BMC"})
|
||||
return
|
||||
self._get_session_challenge()
|
||||
elif self.ipmiversion == 2.0:
|
||||
@ -498,9 +492,7 @@ class Session:
|
||||
errstr = get_ipmi_error(response,
|
||||
suffix=" while getting session challenge")
|
||||
if errstr:
|
||||
call_with_optional_args(self.onlogon,
|
||||
{'error': errstr},
|
||||
self.onlogonargs)
|
||||
self.onlogon({'error': errstr})
|
||||
return
|
||||
data = response['data']
|
||||
self.sessionid = struct.unpack("<I", struct.pack("4B", *data[0:4]))[0]
|
||||
@ -520,9 +512,7 @@ class Session:
|
||||
def _activated_session(self, response):
|
||||
errstr = get_ipmi_error(response)
|
||||
if errstr:
|
||||
call_with_optional_args(self.onlogon,
|
||||
{'error': errstr},
|
||||
self.onlogonargs)
|
||||
self.onlogon({'error': errstr})
|
||||
return
|
||||
data = response['data']
|
||||
self.sessionid = struct.unpack("<I", struct.pack("4B", *data[1:5]))[0]
|
||||
@ -541,17 +531,14 @@ class Session:
|
||||
self.privlevel, self.userid)
|
||||
errstr = get_ipmi_error(response, suffix=mysuffix)
|
||||
if errstr:
|
||||
call_with_optional_args(self.onlogon,
|
||||
{'error': errstr},
|
||||
self.onlogonargs)
|
||||
self.onlogon({'error': errstr})
|
||||
return
|
||||
self.logged = 1
|
||||
Session.keepalive_sessions[self] = {}
|
||||
Session.keepalive_sessions[self]['ipmisession'] = self
|
||||
Session.keepalive_sessions[self]['timeout'] = _monotonic_time() + \
|
||||
25 + (random.random() * 4.9)
|
||||
call_with_optional_args(
|
||||
self.onlogon, {'success': True}, self.onlogonargs)
|
||||
self.onlogon({'success': True})
|
||||
|
||||
def _get_session_challenge(self):
|
||||
reqdata = [2]
|
||||
@ -841,9 +828,7 @@ class Session:
|
||||
errstr = constants.rmcp_codes[data[1]]
|
||||
else:
|
||||
errstr = "Unrecognized RMCP code %d" % data[1]
|
||||
call_with_optional_args(self.onlogon,
|
||||
{'error': errstr},
|
||||
self.onlogonargs)
|
||||
self.onlogon({'error': errstr})
|
||||
return -9
|
||||
self.allowedpriv = data[2]
|
||||
# TODO(jbjohnso): enable lower priv access (e.g. operator/user)
|
||||
@ -887,9 +872,7 @@ class Session:
|
||||
errstr = constants.rmcp_codes[data[1]]
|
||||
else:
|
||||
errstr = "Unrecognized RMCP code %d" % data[1]
|
||||
call_with_optional_args(self.onlogon,
|
||||
{'error': errstr + " in RAKP2"},
|
||||
self.onlogonargs)
|
||||
self.onlogon({'error': errstr + " in RAKP2"})
|
||||
return -9
|
||||
localsid = struct.unpack("<I", struct.pack("4B", *data[4:8]))[0]
|
||||
if localsid != self.localsid:
|
||||
@ -905,9 +888,7 @@ class Session:
|
||||
givenhash = struct.pack("%dB" % len(data[40:]), *data[40:])
|
||||
if givenhash != expectedhash:
|
||||
self.sessioncontext = "FAILED"
|
||||
call_with_optional_args(self.onlogon,
|
||||
{'error': "Incorrect password provided"},
|
||||
self.onlogonargs)
|
||||
self.onlogon({'error': "Incorrect password provided"})
|
||||
return -9
|
||||
# We have now validated that the BMC and client agree on password, time
|
||||
# to store the keys
|
||||
@ -957,9 +938,7 @@ class Session:
|
||||
errstr = constants.rmcp_codes[data[1]]
|
||||
else:
|
||||
errstr = "Unrecognized RMCP code %d" % data[1]
|
||||
call_with_optional_args(self.onlogon,
|
||||
{'error': errstr + " reported in RAKP4"},
|
||||
self.onlogonargs)
|
||||
self.onlogon({'error': errstr + " reported in RAKP4"})
|
||||
return -9
|
||||
localsid = struct.unpack("<I", struct.pack("4B", *data[4:8]))[0]
|
||||
if localsid != self.localsid: # ignore if wrong session id indicated
|
||||
@ -970,11 +949,7 @@ class Session:
|
||||
expectedauthcode = HMAC.new(self.sik, hmacdata, SHA).digest()[:12]
|
||||
authcode = struct.pack("%dB" % len(data[8:]), *data[8:])
|
||||
if authcode != expectedauthcode:
|
||||
call_with_optional_args(
|
||||
self.onlogon,
|
||||
{'error':
|
||||
"Invalid RAKP4 integrity code (wrong Kg?)"},
|
||||
self.onlogonargs)
|
||||
self.onlogon({'error': "Invalid RAKP4 integrity code (wrong Kg?)"})
|
||||
return
|
||||
self.sessionid = self.pendingsessionid
|
||||
self.integrityalgo = 'sha1'
|
||||
|
48
ipmictl.py
48
ipmictl.py
@ -21,6 +21,7 @@ it isn't conceived as a general utility to actually use, just help developers
|
||||
understand how the ipmi_command class workes.
|
||||
"""
|
||||
import os
|
||||
import string
|
||||
import sys
|
||||
|
||||
from ipmi import command
|
||||
@ -32,23 +33,36 @@ if (len(sys.argv) < 3):
|
||||
sys.exit(1)
|
||||
bmc = sys.argv[1]
|
||||
userid = sys.argv[2]
|
||||
cmmand = sys.argv[3]
|
||||
args = None
|
||||
if len(sys.argv) >= 5:
|
||||
args = sys.argv[4:]
|
||||
ipmicmd = command.Command(bmc=bmc, userid=userid, password=password)
|
||||
if cmmand == 'power':
|
||||
if args:
|
||||
print ipmicmd.set_power(args[0], wait=True)
|
||||
else:
|
||||
print ipmicmd.get_power()
|
||||
elif cmmand == 'bootdev':
|
||||
if args:
|
||||
print ipmicmd.set_bootdev(args[0])
|
||||
else:
|
||||
print ipmicmd.get_bootdev()
|
||||
elif cmmand == 'raw':
|
||||
netfn = args[0]
|
||||
cmmand = args[1]
|
||||
data = args[2:]
|
||||
print ipmicmd.raw_command(netfn=netfn, command=cmmand, data=data)
|
||||
|
||||
ipmicmd = None
|
||||
|
||||
|
||||
def docommand(result, ipmisession):
|
||||
cmmand = sys.argv[3]
|
||||
print "Logged into %s" % ipmisession.bmc
|
||||
if 'error' in result:
|
||||
print result['error']
|
||||
return
|
||||
if cmmand == 'power':
|
||||
if args:
|
||||
print ipmisession.set_power(args[0], wait=True)
|
||||
else:
|
||||
value = ipmisession.get_power()
|
||||
print "%s: %s" % (ipmisession.bmc, value['powerstate'])
|
||||
elif cmmand == 'bootdev':
|
||||
if args:
|
||||
print ipmisession.set_bootdev(args[0])
|
||||
else:
|
||||
print ipmisession.get_bootdev()
|
||||
elif cmmand == 'raw':
|
||||
print ipmisession.raw_command(netfn=args[0],
|
||||
command=args[1], data=args[2:])
|
||||
|
||||
bmcs = string.split(bmc, ",")
|
||||
for bmc in bmcs:
|
||||
ipmicmd = command.Command(bmc=bmc, userid=userid, password=password,
|
||||
onlogon=docommand)
|
||||
ipmicmd.eventloop()
|
||||
|
Loading…
Reference in New Issue
Block a user