2
0
mirror of https://opendev.org/x/pyghmi synced 2025-01-28 11:57:34 +00:00

PEP8 compliance

Change instances in code where flake8 complained

Change-Id: I0b125fcff39024f9d4bf3c4c26a863efd0fa5cba
This commit is contained in:
Jarrod Johnson 2013-07-16 13:37:09 -04:00
parent 51cf01f6c9
commit 0e8ca33842
5 changed files with 153 additions and 142 deletions

View File

@ -81,17 +81,17 @@ class Command(object):
# 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)
userid=userid,
password=password,
kg=kg)
def get_bootdev(self, callback=None, callback_args=None):
"""Get current boot device override information.
Provides the current requested boot device. Be aware that not all IPMI
devices support this. Even in BMCs that claim to, occasionally the BIOS
or UEFI fail to honor it. This is usually only applicable to the next
reboot.
devices support this. Even in BMCs that claim to, occasionally the
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
@ -114,13 +114,16 @@ class Command(object):
return self.lastresponse
return True
def set_power(self, powerstate, wait=False, callback=None, callback_args=None):
def set_power(self, powerstate, wait=False, callback=None,
callback_args=None):
"""Request power state change
:param powerstate:
* on -- Request system turn on
* off -- Request system turn off without waiting for OS to shutdown
* shutdown -- Have system request OS proper shutdown
* off -- Request system turn off without waiting
for OS to shutdown
* shutdown -- Have system request OS proper
shutdown
* reset -- Request system reset without waiting for
OS
* boot -- If system is off, then 'on', else 'reset'
@ -141,11 +144,11 @@ class Command(object):
self.wait_for_power = wait
self.ipmi_session.raw_command(netfn=0,
command=1,
callback=self._set_power_with_chassis_info
callback=self._set_power_with_chassisinfo
)
return self._waitifsync()
def _set_power_with_chassis_info(self, response):
def _set_power_with_chassisinfo(self, response):
if 'error' in response:
_raiseorcall(
self.commandcallback, response, self.commandcallbackargs)
@ -177,8 +180,8 @@ class Command(object):
self.requestpending = False
if self.commandcallback:
session.call_with_optional_args(self.commandcallback,
self.lastresponse,
self.commandcallbackargs)
self.lastresponse,
self.commandcallbackargs)
def _power_wait(self, response):
if 'error' in response:
@ -191,8 +194,8 @@ class Command(object):
self.lastresponse = {'powerstate': self.powerstate}
if self.commandcallback:
session.call_with_optional_args(self.commandcallback,
self.lastresponse,
self.commandcallbackargs)
self.lastresponse,
self.commandcallbackargs)
return
self.ipmi_session.raw_command(netfn=0,
command=1,
@ -211,9 +214,11 @@ class Command(object):
*hd -- Boot from hard drive
*optical -- boot from CD or DVD drive
*setup -- Boot into setup utility
*default -- remove any IPMI directed boot device request
:param persist: If true, ask that system firmware use this device beyond
next boot. Be aware many systems do not honor this
*default -- remove any IPMI directed boot device
request
:param persist: If true, ask that system firmware use this device
beyond next boot. Be aware many systems do not honor
this
:param uefiboot: If true, request UEFI boot explicitly. Strictly
speaking, the spec sugests that if not set, the system
should BIOS boot and offers no "don't care" option.
@ -321,8 +326,8 @@ class Command(object):
self.lastresponse = {'bootdev': bootnum}
if self.commandcallback:
session.call_with_optional_args(self.commandcallback,
self.lastresponse,
self.commandcallbackargs)
self.lastresponse,
self.commandcallbackargs)
def get_power(self, callback=None, callback_args=None):
"""Get current power state of the managed system
@ -352,5 +357,5 @@ class Command(object):
self.lastresponse = {'powerstate': self.powerstate}
if self.commandcallback:
session.call_with_optional_args(self.commandcallback,
self.lastresponse,
self.commandcallbackargs)
self.lastresponse,
self.commandcallbackargs)

View File

@ -19,9 +19,11 @@
import fcntl
import os
import struct
import types
from ipmi.private import session
from ipmi.private import constants
from ipmi.private import session
class Console(object):
"""IPMI SOL class.
@ -42,13 +44,13 @@ class Console(object):
def __init__(self, bmc, userid, password,
iohandler=None,
force=False, kg=None):
if type(iohandler) == tuple: #two file handles
if type(iohandler) == tuple: # two file handles
self.console_in = iohandler[0]
self.console_out = iohandler[1]
elif type(iohandler) == file: # one full duplex file handle
elif type(iohandler) == file: # one full duplex file handle
self.console_out = iohandler
self.console_in = iohandler
elif type(iohander) == types.FunctionType:
elif isinstance(iohandler, types.FunctionType):
self.console_out = None
self.console_in = None
self.out_handler = iohandler
@ -63,15 +65,14 @@ class Console(object):
self.ackedcount = 0
self.ackedseq = 0
self.retriedpayload = 0
self.pendingoutput=""
self.awaitingack=False
self.pendingoutput = ""
self.awaitingack = False
self.force_session = force
self.ipmi_session = session.Session(bmc=bmc,
userid=userid,
password=password,
kg=kg,
onlogon=self._got_session
)
userid=userid,
password=password,
kg=kg,
onlogon=self._got_session)
def _got_session(self, response):
"""Private function to navigate SOL payload activation
@ -104,15 +105,15 @@ class Console(object):
0x82: 'Maximum SOL session count reached',
0x83: 'Cannot activate payload with encryption',
0x84: 'Cannot activate payload without encryption',
}
}
if response['code']:
if response['code'] in constants.ipmi_completion_codes:
self._print_data(
constants.ipmi_completion_codes[response['code']])
constants.ipmi_completion_codes[response['code']])
return
elif response['code'] == 0x80:
if self.force_session and not self.retriedpayload:
self.retriedpayload=1
self.retriedpayload = 1
self.ipmi_session.raw_command(netfn=0x6, command=0x49,
data=(1, 1, 0, 0, 0, 0),
callback=self._got_session)
@ -125,8 +126,8 @@ class Console(object):
return
else:
self._print_data(
'SOL encountered Unrecognized error code %d\n' %
response['code'])
'SOL encountered Unrecognized error code %d\n' %
response['code'])
return
#data[0:3] is reserved except for the test mode, which we don't use
data = response['data']
@ -138,12 +139,12 @@ class Console(object):
raise Exception("TODO(jbjohnso): support atypical SOL port number")
#ignore data[10:11] for now, the vlan detail, shouldn't matter to this
#code anyway...
self.ipmi_session.sol_handler=self._got_sol_payload
self.ipmi_session.sol_handler = self._got_sol_payload
if self.console_in is not None:
self.ipmi_session.register_handle_callback(self.console_in,
self._got_cons_input)
def _got_cons_input(self,handle):
def _got_cons_input(self, handle):
"""Callback for handle events detected by ipmi session
"""
self.pendingoutput += handle.read()
@ -156,19 +157,19 @@ class Console(object):
if self.myseq == 0:
self.myseq = 1
payload = struct.pack("BBBB",
self.myseq,
self.ackedseq,
self.ackedseq,
self.sendbreak)
self.myseq,
self.ackedseq,
self.ackedseq,
self.sendbreak)
payload += self.pendingoutput
self.lasttextsize = len(self.pendingoutput)
self.pendingoutput = ""
self.awaitingack = True
payload = struct.unpack("%dB" % len(payload), payload)
self.lastpayload=payload
self.lastpayload = payload
self.ipmi_session.send_payload(payload, payload_type=1)
def _print_data(self,data):
def _print_data(self, data):
"""Convey received data back to caller in the format of their choice.
Caller may elect to provide this class filehandle(s) or else give a
@ -178,7 +179,7 @@ class Console(object):
if self.console_out is not None:
self.console_out.write(data)
self.console_out.flush()
elif self.out_handler: #callback style..
elif self.out_handler: # callback style..
self.out_handler(data)
def _got_sol_payload(self, payload):
@ -197,41 +198,41 @@ class Console(object):
#no reason would be treated the same, new payload with partial data
remdata = ""
remdatalen = 0
if newseq != 0: #this packet at least has some data to send to us..
if newseq != 0: # this packet at least has some data to send to us..
if len(payload) > 4:
remdatalen = len(payload[4:]) #store remote data len before dupe
remdatalen = len(payload[4:]) # store remote len before dupe
#retry logic, we must ack *this* many even if it is
#a retry packet with new partial data
remdata = struct.pack("%dB" % remdatalen, *payload[4:])
if newseq == self.remseq: #it is a retry, but could have new data..
if newseq == self.remseq: # it is a retry, but could have new data
if remdatalen > self.lastsize:
remdata = remdata[4 + self.lastsize:]
else: # no new data...
else: # no new data...
remdata = ""
else: #TODO(jbjohnso) what if remote sequence number is wrong??
else: # TODO(jbjohnso) what if remote sequence number is wrong??
self.remseq = newseq
self.lastsize=remdatalen
self.lastsize = remdatalen
self._print_data(remdata)
ackpayload = (0, self.remseq, remdatalen, 0)
#Why not put pending data into the ack? because it's rare
#and might be hard to decide what to do in the context of
#retry situation
self.ipmi_session.send_payload(ackpayload,
payload_type=1, retry=False)
if self.myseq != 0 and ackseq == self.myseq: #the bmc has something to
#say about our last xmit
self.awaitingack=False
if nacked > 0: #the BMC was in some way unhappy
payload_type=1, retry=False)
if self.myseq != 0 and ackseq == self.myseq: # the bmc has something
# to say about last xmit
self.awaitingack = False
if nacked > 0: # the BMC was in some way unhappy
if poweredoff:
self._print_data("Remote system is powered down\n")
if deactivated:
self._print_data("Remote IPMI console disconnected\n")
else: #retry all or part of packet, but in a new form
#also add pending output for efficiency and ease
else: # retry all or part of packet, but in a new form
# also add pending output for efficiency and ease
newtext = self.lastpayload[4 + ackcount:]
self.pendingoutput = newtext + self.pendingoutput
self._sendpendingoutput()
elif self.awaitingack: #session has marked us as happy, but we are not
elif self.awaitingack: # session marked us as happy, but we are not
#this does mean that we will occasionally retry a packet
#sooner than retry suggests, but that's no big deal
self.ipmi_session.send_payload(payload=self.lastpayload,
@ -247,7 +248,7 @@ class Console(object):
"""
#wait_for_rsp promises to return a false value when no sessions are
#alive anymore
#TODO(jbjohnso): wait_for_rsp is not returning a true value from our own
#TODO(jbjohnso): wait_for_rsp is not returning a true value for our own
#session
while (1):
session.Session.wait_for_rsp(timeout=600)

View File

@ -305,16 +305,16 @@ class Session:
else:
self.ipmicallback = callback
self._send_ipmi_net_payload(netfn, command, data, retry=retry)
if retry: #in retry case, let the retry timers auto-indicate wait time
timeout=None
else: #if not retry, give it a second before surrending
timeout=1
if retry: # in retry case, let the retry timers indicate wait time
timeout = None
else: # if not retry, give it a second before surrending
timeout = 1
#In the synchronous case, wrap the event loop in this call
#The event loop is shared amongst python-ipmi session instances
#within a process. In this way, synchronous usage of the interface
#plays well with asynchronous use. In fact, this produces the behavior
#of only the constructor *really* needing a callback. From then on,
#synchronous usage of the class acts in a greenthread manner governed by
#synchronous usage of the class acts in a greenthread style governed by
#order of data on the network
if callback is None:
while self.lastresponse is None:
@ -332,10 +332,10 @@ class Session:
#we already have a packet outgoing, make this
# a pending payload
# this way a simplistic BMC won't get confused
# and we also avoid having to do a more complicated
# and we also avoid having to do more complicated
# retry mechanism where each payload is
# retried separately
self.pendingpayloads.append((payload,payload_type,retry))
self.pendingpayloads.append((payload, payload_type, retry))
return
if payload_type is None:
payload_type = self.last_payload_type
@ -389,8 +389,8 @@ class Session:
payloadtocrypt = _aespad(payload)
crypter = AES.new(self.aeskey, AES.MODE_CBC, iv)
crypted = crypter.encrypt(struct.pack("%dB" %
len(payloadtocrypt),
*payloadtocrypt))
len(payloadtocrypt),
*payloadtocrypt))
crypted = list(struct.unpack("%dB" % len(crypted), crypted))
message += crypted
else: # no confidetiality algorithm
@ -411,21 +411,21 @@ class Session:
integdata = message[4:]
authcode = HMAC.new(self.k1,
struct.pack("%dB" % len(integdata),
*integdata),
*integdata),
SHA).digest()[:12] # SHA1-96
# per RFC2404 truncates to 96 bits
# per RFC2404 truncates to 96 bits
message += struct.unpack("12B", authcode)
self.netpacket = struct.pack("!%dB" % len(message), *message)
#advance idle timer since we don't need keepalive while slinging packets
#advance idle timer since we don't need keepalive while sending packets
#out naturally
if self in Session.keepalive_sessions:
Session.keepalive_sessions[self]['timeout'] = time.time() + 25 + \
(random.random() * 4.9)
(random.random() * 4.9)
self._xmit_packet(retry)
def _ipmi15authcode(self, payload, checkremotecode=False):
if self.authtype == 0: # Only for things prior to auth in ipmi 1.5, not
# like 2.0 cipher suite 0
if self.authtype == 0: # Only for things before auth in ipmi 1.5, not
# like 2.0 cipher suite 0
return ()
password = self.password
padneeded = 16 - len(password)
@ -435,14 +435,14 @@ class Session:
passdata = struct.unpack("16B", password)
if checkremotecode:
seqbytes = struct.unpack("!4B",
struct.pack("<I", self.remsequencenumber))
struct.pack("<I", self.remsequencenumber))
else:
seqbytes = struct.unpack("!4B",
struct.pack("<I", self.sequencenumber))
struct.pack("<I", self.sequencenumber))
sessdata = struct.unpack("!4B", struct.pack("<I", self.sessionid))
bodydata = passdata + sessdata + tuple(payload) + seqbytes + passdata
dgst = hashlib.md5(
struct.pack("%dB" % len(bodydata), *bodydata)).digest()
struct.pack("%dB" % len(bodydata), *bodydata)).digest()
hashdata = struct.unpack("!%dB" % len(dgst), dgst)
return hashdata
@ -468,10 +468,11 @@ class Session:
self.ipmiversion = 2.0
if self.ipmiversion == 1.5:
if not (data[1] & 0b100):
call_with_optional_args(self.onlogon,
{'error':
"MD5 is required but not enabled/available on target BMC"},
self.onlogonargs)
call_with_optional_args(
self.onlogon,
{'error':
"MD5 required but not enabled/available on target BMC"},
self.onlogonargs)
return
self._get_session_challenge()
elif self.ipmiversion == 2.0:
@ -509,7 +510,8 @@ class Session:
return
data = response['data']
self.sessionid = struct.unpack("<I", struct.pack("4B", *data[1:5]))[0]
self.sequencenumber = struct.unpack("<I", struct.pack("4B", *data[5:9]))[0]
self.sequencenumber = struct.unpack("<I",
struct.pack("4B", *data[5:9]))[0]
self._req_priv_level()
def _req_priv_level(self):
@ -531,7 +533,7 @@ class Session:
Session.keepalive_sessions[self] = {}
Session.keepalive_sessions[self]['ipmisession'] = self
Session.keepalive_sessions[self]['timeout'] = time.time() + 25 + \
(random.random() * 4.9)
(random.random() * 4.9)
call_with_optional_args(
self.onlogon, {'success': True}, self.onlogonargs)
@ -547,7 +549,7 @@ class Session:
def _open_rmcpplus_request(self):
self.authtype = 6
self.localsid += 1 # have unique local session ids to ignore aborted
self.localsid += 1 # have unique local session ids to ignore aborted
# login attempts from the past
self.rmcptag += 1
data = [
@ -563,8 +565,9 @@ class Session:
#2,0,0,8,0,0,0,0, #no privacy confalgo
]
self.sessioncontext = 'OPENSESSION'
self.send_payload(payload=data,
payload_type=constants.payload_types['rmcpplusopenreq'])
self.send_payload(
payload=data,
payload_type=constants.payload_types['rmcpplusopenreq'])
def _get_channel_auth_cap(self):
self.ipmicallback = self._got_channel_auth_cap
@ -606,7 +609,7 @@ class Session:
# each session with active outbound payload has callback to
# handle retry/timout error
# each session that is 'alive' wants to send a keepalive ever so often.
# We want to make sure the most strict request is honored, and block for
# We want to make sure the most strict request is honored and block for
# no more time than that, so that whatever part(ies) need to service in
# a deadline, will be honored
if timeout != 0:
@ -614,18 +617,20 @@ class Session:
if parms['timeout'] <= curtime:
timeout = 0 # exit after one guaranteed pass
break
if timeout is not None and timeout < parms['timeout'] - curtime:
continue # timeout is smaller than the current session needs
if (timeout is not None and
timeout < parms['timeout'] - curtime):
continue # timeout smaller than the current session needs
timeout = parms['timeout'] - curtime # set new timeout value
for session, parms in cls.keepalive_sessions.iteritems():
if parms['timeout'] <= curtime:
timeout = 0
break
if timeout is not None and timeout < parms['timeout'] - curtime:
if (timeout is not None and
timeout < parms['timeout'] - curtime):
continue
timeout = parms['timeout'] - curtime
# If the loop above found no sessions wanting *and* the caller had no
# timeout in mind, exit function. In this case there is no way a session
# timeout, exit function. In this case there is no way a session
# could be waiting so we can always return 0
if timeout is None:
return 0
@ -643,7 +648,7 @@ class Session:
(data, sockaddr) = pktqueue.popleft()
cls._route_ipmiresponse(sockaddr, data)
while cls.ipmipoller.poll(0): # seems ridiculous, but
# between every single callback, check for packets again
# between every callback, check for packets again
rdata = cls.socket.recvfrom(3000)
pktqueue.append(rdata)
for handlepair in cls.poller.poll(0):
@ -655,20 +660,20 @@ class Session:
for session, parms in cls.keepalive_sessions.iteritems():
if parms['timeout'] < curtime:
cls.keepalive_sessions[session]['timeout'] = 25 + \
(random.random() * 4.9)
(random.random() * 4.9)
session._keepalive()
for session, parms in cls.waiting_sessions.iteritems():
if parms['timeout'] < curtime: # timeout has expired, time to
# give up # on it and trigger timeout
# response # in the respective
# session
if parms['timeout'] < curtime: # timeout has expired, time to
# give up on it and trigger timeout
# response in the respective
# session
sessionstodel.append(
session) # defer deletion until after loop
# to avoid confusing the for loop
for session in sessionstodel:
cls.pending -= 1
session.lastpayload = None
cls.waiting_sessions.pop(session,None)
cls.waiting_sessions.pop(session, None)
session._timedout()
return len(cls.waiting_sessions)
@ -686,10 +691,10 @@ class Session:
this class method will register that.
:param handle: filehandle too watch for input
:param callback: function to call when input detected on the handle.
:param callback: function to call when input detected on the handle.
will receive the handle as an argument
"""
cls._external_handlers[handle.fileno()]=(callback,handle)
cls._external_handlers[handle.fileno()] = (callback, handle)
cls.poller.register(handle, select.POLLIN)
@classmethod
@ -729,7 +734,7 @@ class Session:
# copying pieces of the packet over and over
rsp = list(struct.unpack("!%dB" % len(data), data))
authcode = False
if data[4] == '\x02': # we have an authcode in this ipmi 1.5 packet
if data[4] == '\x02': # we have authcode in this ipmi 1.5 packet
authcode = data[13:29]
del rsp[13:29]
# this is why we needed a mutable representation
@ -738,7 +743,7 @@ class Session:
expectedauthcode = self._ipmi15authcode(payload,
checkremotecode=True)
expectedauthcode = struct.pack("%dB" % len(expectedauthcode),
*expectedauthcode)
*expectedauthcode)
if expectedauthcode != authcode:
return
self._parse_ipmi_payload(payload)
@ -760,7 +765,7 @@ class Session:
elif ptype == 0x15:
return self._got_rakp4(data[16:])
elif ptype == 0 or ptype == 1: # good old ipmi payload or sol
# If I'm endorsing a shared secret scheme, then at the very least it
# If endorsing a shared secret scheme, then at the very least it
# needs to do mutual assurance
if not (data[5] & 0b01000000): # This would be the line that might
# trip up some insecure BMC
@ -789,22 +794,22 @@ class Session:
iv = rawdata[16:32]
decrypter = AES.new(self.aeskey, AES.MODE_CBC, iv)
decrypted = decrypter.decrypt(
struct.pack("%dB" % len(payload[16:]),
*payload[16:]))
struct.pack("%dB" % len(payload[16:]),
*payload[16:]))
payload = struct.unpack("%dB" % len(decrypted), decrypted)
padsize = payload[-1] + 1
payload = list(payload[:-padsize])
if ptype == 0:
self._parse_ipmi_payload(payload)
elif ptype == 1: #There should be no other option
#note that we assume the SOL payload is good enough to avoid
elif ptype == 1: # There should be no other option
# note that we assume the SOL payload is good enough to avoid
# retry SOL logic is sufficiently different, we just
# defer that call to the sol handler, it can re submit if it
# is unhappy
if self.last_payload_type == 1: #but only if SOL was last sent
if self.last_payload_type == 1: # but only if SOL was last tx
self.lastpayload = None
self.last_payload_type = None
Session.waiting_sessions.pop(self,None)
Session.waiting_sessions.pop(self, None)
if self.sol_handler:
self.sol_handler(payload)
@ -829,8 +834,8 @@ class Session:
localsid = struct.unpack("<I", struct.pack("4B", *data[4:8]))[0]
if self.localsid != localsid:
return -9
self.pendingsessionid = struct.unpack("<I",
struct.pack("4B", *data[8:12]))[0]
self.pendingsessionid = struct.unpack(
"<I", struct.pack("4B", *data[8:12]))[0]
# TODO(jbjohnso): currently, we take it for granted that the responder
# accepted our integrity/auth/confidentiality proposal
self.lastpayload = None
@ -841,11 +846,12 @@ class Session:
self.randombytes = os.urandom(16)
userlen = len(self.userid)
payload = [self.rmcptag, 0, 0, 0] + \
list(struct.unpack("4B", struct.pack("<I", self.pendingsessionid))) +\
list(struct.unpack("16B", self.randombytes)) +\
[self.privlevel, 0, 0] +\
[userlen] +\
list(struct.unpack("%dB" % userlen, self.userid))
list(struct.unpack("4B",
struct.pack("<I", self.pendingsessionid))) +\
list(struct.unpack("16B", self.randombytes)) +\
[self.privlevel, 0, 0] +\
[userlen] +\
list(struct.unpack("%dB" % userlen, self.userid))
self.sessioncontext = "EXPECTINGRAKP2"
self.send_payload(
payload=payload, payload_type=constants.payload_types['rakp1'])
@ -948,10 +954,11 @@ 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)
call_with_optional_args(
self.onlogon,
{'error':
"Invalid RAKP4 integrity code (wrong Kg?)"},
self.onlogonargs)
return
self.sessionid = self.pendingsessionid
self.integrityalgo = 'sha1'
@ -970,28 +977,28 @@ class Session:
# TODO(jbjohnso): if implementing other channels, add checksum checks
# here
if (payload[4] != self.seqlun or
payload[1] >> 2 != self.expectednetfn or
payload[5] != self.expectedcmd):
return -1 # this payload is not a match for our outstanding packet
payload[1] >> 2 != self.expectednetfn or
payload[5] != self.expectedcmd):
return -1 # payload is not a match for our last packet
if hasattr(self, 'hasretried') and self.hasretried:
self.hasretried = 0
self.tabooseq[
(self.expectednetfn, self.expectedcmd, self.seqlun)] = 16
# try to skip it for at most 16 cycles of overflow
# We want to now remember that we do not have an expected packet
self.expectednetfn = 0x1ff # bigger than one byte means
#it can never match the one byte value by mistake
self.expectednetfn = 0x1ff # bigger than one byte means it can never
# match the one byte value by mistake
self.expectedcmd = 0x1ff
self.seqlun += 4 # prepare seqlun for next transmit
self.seqlun &= 0xff # when overflowing, wrap around
Session.waiting_sessions.pop(self,None)
Session.waiting_sessions.pop(self, None)
self.lastpayload = None # render retry mechanism utterly incapable of
#doing anything, though it shouldn't matter
# doing anything, though it shouldn't matter
self.last_payload_type = None
response = {}
response['netfn'] = payload[1] >> 2
del payload[0:5]
# remove header of rsaddr/netfn/lun/checksum/rq/seq/lun
# ^^ remove header of rsaddr/netfn/lun/checksum/rq/seq/lun
del payload[-1] # remove the trailing checksum
response['command'] = payload[0]
response['code'] = payload[1]
@ -1003,7 +1010,7 @@ class Session:
self.pendingpayloads.popleft()
self.send_payload(payload=nextpayload,
payload_type=nextpayloadtype,
retry=nextretry)
retry=retry)
call_with_optional_args(self.ipmicallback,
response,
self.ipmicallbackargs)
@ -1036,7 +1043,7 @@ class Session:
self._relog()
else: # in IPMI case, the only recourse is to act as if the packet is
# idempotent. SOL has more sophisticated retry handling
# the biggest risks are reset sp, which is often fruitless to retry
# the biggest risks are reset sp which is often fruitless to retry
# and chassis reset, which sometimes will shoot itself
# systematically in the head in a shared port case making replies
# impossible
@ -1059,7 +1066,7 @@ class Session:
Session.waiting_sessions[self] = {}
Session.waiting_sessions[self]['ipmisession'] = self
Session.waiting_sessions[self]['timeout'] = self.timeout + \
time.time()
time.time()
Session.pending += 1
if self.sockaddr:
Session.socket.sendto(self.netpacket, self.sockaddr)
@ -1070,7 +1077,7 @@ class Session:
0,
socket.SOCK_DGRAM):
sockaddr = res[4]
if (res[0] == socket.AF_INET): #convert the sockaddr AF_INET6
if (res[0] == socket.AF_INET): # convert the sockaddr AF_INET6
newhost = '::ffff:' + sockaddr[0]
sockaddr = (newhost, sockaddr[1], 0, 0)
Session.bmc_handlers[sockaddr] = self
@ -1088,7 +1095,7 @@ class Session:
self.raw_command(command=0x3c,
netfn=6,
data=struct.unpack("4B",
struct.pack("I", self.sessionid)),
struct.pack("I", self.sessionid)),
retry=False,
callback=callback,
callback_args=callback_args)

View File

@ -38,12 +38,12 @@ if len(sys.argv) >= 5:
args = sys.argv[4:]
ipmicmd = Command(bmc=bmc, userid=userid, password=password)
if command == 'power':
if args[0]:
if args:
print ipmicmd.set_power(args[0], wait=True)
else:
print ipmicmd.get_power()
elif command == 'bootdev':
if args[0]:
if args:
print ipmicmd.set_bootdev(args[0])
else:
print ipmicmd.get_bootdev()

View File

@ -20,16 +20,14 @@ limitations under the License.
"""
import os
import sys
import fcntl
import tty
import termios
import tty
from ipmi import console
tcattr = termios.tcgetattr(sys.stdin)
newtcattr = tcattr
#TODO: allow ctrl-c and crtl-z to go to remote console, add our own exit handler
#TODO(jbjohnso): add our exit handler
newtcattr[-1][termios.VINTR] = 0
newtcattr[-1][termios.VSUSP] = 0
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, newtcattr)