2
0
mirror of https://opendev.org/x/pyghmi synced 2025-01-27 19:37:44 +00:00

Stylistic reworks

This commit is contained in:
Jarrod Johnson 2013-06-25 11:23:24 -04:00
parent d8c7f9d903
commit ab1b981547

View File

@ -31,13 +31,17 @@ from Crypto.Hash import HMAC, SHA
from ipmi_constants import payload_types, ipmi_completion_codes, command_completion_codes, payload_types, rmcp_codes
initialtimeout = 0.5 #minimum timeout for first packet to retry in any given session. This will be randomized to stagger out retries in case of congestion
initialtimeout = 0.5 #minimum timeout for first packet to retry in any given
#session. This will be randomized to stagger out retries
#in case of congestion
def _aespad(data): # ipmi demands a certain pad scheme, per table 13-20 AES-CBC encrypted payload fields
def _aespad(data): # ipmi demands a certain pad scheme, per table 13-20 AES-CBC
# encrypted payload fields
newdata=list(data)
currlen=len(data)+1 #need to count the pad length field as well
neededpad=currlen%16
if neededpad: #if it happens to be zero, hurray, but otherwise invert the sense of the padding
if neededpad: #if it happens to be zero, hurray, but otherwise invert the
#sense of the padding
neededpad = 16-neededpad
padval=1
while padval <= neededpad:
@ -77,9 +81,8 @@ class ipmi_session:
bmc_handlers={}
waiting_sessions={}
peeraddr_to_nodes={}
'''
Upon exit of python, make sure we play nice with BMCs by assuring closed sessions for all that we tracked
'''
#Upon exit of python, make sure we play nice with BMCs by assuring closed
#sessions for all that we tracked
@classmethod
def _cleanup(cls):
for session in cls.bmc_handlers.itervalues():
@ -101,21 +104,33 @@ class ipmi_session:
curmax=cls.socket.getsockopt(socket.SOL_SOCKET,socket.SO_RCVBUF)
cls.poller.register(cls.socket,select.POLLIN)
curmax = curmax/2
#we throttle such that we never have no more outstanding packets than our receive buffer should be able to handle
#we throttle such that we never have no more outstanding packets than
#our receive buffer should be able to handle
cls.pending=0
cls.maxpending=curmax/1000 #pessimistically assume 1 kilobyte messages, way larger than almost all ipmi datagrams
#for faster performance, sysadmins may want to examine and tune /proc/sys/net/core/rmem_max up. This allows the module to request more,
#but does not increase buffers for applications that do less creative things
#TODO(jbjohnso): perhaps spread sessions across a socket pool when rmem_max is small, still get ~65/socket, but avoid long queues that might happen with
#low rmem_max and putting thousands of nodes in line
cls.maxpending=curmax/1000 #pessimistically assume 1 kilobyte messages, #way larger than almost all ipmi datagrams
#for faster performance, sysadmins may want to examine and tune
#/proc/sys/net/core/rmem_max up. This allows the module to request
#more, but does not increase buffers for applications that do less
#creative things
#TODO(jbjohnso): perhaps spread sessions across a socket pool when
#rmem_max is small, still get ~65/socket, but avoid long queues that
#might happen with low rmem_max and putting thousands of nodes in line
'''
This function handles the synchronous caller case in liue of a client provided callback
This function handles the synchronous caller case in liue of a client
provided callback
'''
def _sync_login(self,response):
if 'error' in response:
raise Exception(response['error'])
def __init__(self,bmc,userid,password,port=623,kg=None,onlogon=None,onlogonargs=None):
def __init__(self,
bmc,
userid,
password,
port=623,
kg=None,
onlogon=None,
onlogonargs=None):
self.bmc=bmc
self.userid=userid
self.password=password
@ -140,8 +155,11 @@ class ipmi_session:
while not self.logged:
ipmi_session.wait_for_rsp()
def _initsession(self):
self.localsid=2017673555 #this number can be whatever we want. I picked 'xCAT' minus 1 so that a hexdump of packet would show xCAT
self.privlevel=4 #for the moment, assume admin access TODO(jbjohnso): make flexible
self.localsid=2017673555 #this number can be whatever we want. I picked
#'xCAT' minus 1 so that a hexdump of packet
# would show xCAT
self.privlevel=4 #for the moment, assume admin access
#TODO(jbjohnso): make flexible
self.confalgo=0
self.aeskey=None
self.integrityalgo=0
@ -156,12 +174,19 @@ class ipmi_session:
self.ipmiversion=1.5
self.timeout=initialtimeout+(0.5*random())
self.seqlun=0
self.rqaddr=0x81 #per IPMI table 5-4, software ids in the ipmi spec may be 0x81 through 0x8d. We'll stick with 0x81 for now, do not forsee a reason to adjust
self.rqaddr=0x81 #per IPMI table 5-4, software ids in the ipmi spec may
#be 0x81 through 0x8d. We'll stick with 0x81 for now,
#do not forsee a reason to adjust
self.logged=0
self.sockaddr=None #when we confirm a working sockaddr, put it here to skip getaddrinfo
self.tabooseq={} #this tracks netfn,command,seqlun combinations that were retried so that
#we don't loop around and reuse the same request data and cause potential ambiguity in return
self.ipmi15only=0 #default to supporting ipmi 2.0. Strictly by spec, this should gracefully be backwards compat, but some 1.5 implementations checked reserved bits
self.sockaddr=None #when we confirm a working sockaddr, put it here to
#skip getaddrinfo
self.tabooseq={} #this tracks netfn,command,seqlun combinations that
#were retried so that we don't loop around and reuse
#the same request data and cause potential ambiguity
#in return
self.ipmi15only=0 #default to supporting ipmi 2.0. Strictly by spec,
#this should gracefully be backwards compat, but some
#1.5 implementations checked reserved bits
def _checksum(self,*data): #Two's complement over the data
csum=sum(data)
csum=csum^0xff
@ -174,15 +199,21 @@ class ipmi_session:
'''
def _make_ipmi_payload(self,netfn,command,data=()):
self.expectedcmd=command
self.expectednetfn=netfn+1 #in ipmi, the response netfn is always one higher than the request payload, we assume we are always the
#requestor for now
seqincrement=7 #IPMI spec forbids gaps bigger then 7 in seq number. Risk the taboo rather than violate the rules
while (netfn,command,self.seqlun) in self.tabooseq and self.tabooseq[(netfn,command,self.seqlun)] and seqincrement:
self.tabooseq[(self.expectednetfn,command,self.seqlun)]-=1 #Allow taboo to eventually expire after a few rounds
self.expectednetfn=netfn+1 #in ipmi, the response netfn is always one
#higher than the request payload, we assume
#we are always the requestor for now
seqincrement=7 #IPMI spec forbids gaps bigger then 7 in seq number.
#Risk the taboo rather than violate the rules
while (netfn,command,self.seqlun) in self.tabooseq and
self.tabooseq[(netfn,command,self.seqlun)] and seqincrement:
self.tabooseq[(self.expectednetfn,command,self.seqlun)]-=1
#Allow taboo to eventually expire after a few rounds
self.seqlun += 4 #the last two bits are lun, so add 4 to add 1
self.seqlun &= 0xff #we only have one byte, wrap when exceeded
seqincrement-=1
header=[0x20,netfn<<2] #figure 13-4, first two bytes are rsaddr and netfn, rsaddr is always 0x20 since we are addressing BMC
header=[0x20,netfn<<2] #figure 13-4, first two bytes are rsaddr and
#netfn, rsaddr is always 0x20 since we are
#addressing BMC
reqbody=[self.rqaddr,self.seqlun,command]+list(data)
headsum=self._checksum(*header)
bodysum=self._checksum(*reqbody)
@ -194,7 +225,12 @@ class ipmi_session:
if errorstr:
response['error']=errorstr
self.lastresponse=response
def raw_command(self,netfn,command,data=[],callback=None,callback_args=None):
def raw_command(self,
netfn,
command,
data=[],
callback=None,
callback_args=None):
self.ipmicallbackargs=callback_args
if callback is None:
self.lastresponse=None