mirror of
https://opendev.org/x/pyghmi
synced 2025-01-27 19:37:44 +00:00
More work to make it get further on session establishment
This commit is contained in:
parent
9269810e7c
commit
df43c5336b
@ -32,3 +32,31 @@ rmcp_codes = {
|
||||
0x12: 'Illegal or unrecognized parameter',
|
||||
}
|
||||
|
||||
ipmi_completion_codes = {
|
||||
0x0: "Success",
|
||||
0xc0: "Node Busy",
|
||||
0xc1: "Invalid command",
|
||||
0xc2: "Invalid command for given LUN",
|
||||
0xc3: "Timeout while processing command",
|
||||
0xc4: "Out of storage space on BMC",
|
||||
0xc5: "Reservation canceled or invalid reservation ID",
|
||||
0xc6: "Request data truncated",
|
||||
0xc7: "Request data length invalid",
|
||||
0xc8: "Request data field length limit exceeded",
|
||||
0xc9: "Parameter out of range",
|
||||
0xca: "Cannot return number of requested data bytes",
|
||||
0xcb: "Requested sensor, data, or record not present",
|
||||
0xcc: "Invalid data field in request",
|
||||
0xcd: "Command illegal for specified sensor or record type",
|
||||
0xce: "Command response could not be provided",
|
||||
0xcf: "Cannot execute duplicated request",
|
||||
0xd0: "SDR repository in update mode",
|
||||
0xd1: "Device in firmware update mode",
|
||||
0xd2: "BMC initialization in progress",
|
||||
0xd3: "Internal destination unavailable",
|
||||
0xd4: "Insufficient privilege level or firmware firewall",
|
||||
0xd5: "Command not supported in present state",
|
||||
0xd6: "Cannot execute command because subfunction disabled or unavailable",
|
||||
0xff: "Unspecified",
|
||||
}
|
||||
|
||||
|
56
ipmibase.py
56
ipmibase.py
@ -7,11 +7,16 @@ from collections import deque
|
||||
from time import time
|
||||
from hashlib import md5
|
||||
from struct import pack, unpack
|
||||
from ipmi_constants import payload_types
|
||||
from ipmi_constants import payload_types, ipmi_completion_codes
|
||||
from random import random
|
||||
|
||||
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 get_ipmi_errstr():
|
||||
if code in ipmi_completion_codes:
|
||||
return ipmi_completion_codes[code]
|
||||
else:
|
||||
return "Unknown code "+code+" encountered"
|
||||
class IPMISession:
|
||||
poller=select.poll()
|
||||
bmc_handlers={}
|
||||
@ -40,15 +45,30 @@ class IPMISession:
|
||||
#but does not increase buffers for applications that do less creative things
|
||||
#TODO: 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
|
||||
def __init__(self,bmc,userid,password,port=623):
|
||||
'''
|
||||
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,onlogon=None):
|
||||
self.bmc=bmc
|
||||
self.userid=userid
|
||||
self.password=password
|
||||
self.port=port
|
||||
if (onlogon is None):
|
||||
self.async=False
|
||||
self.onlogon=self._sync_login
|
||||
else:
|
||||
self.async=True
|
||||
self.onlogon=onlogon
|
||||
if not hasattr(IPMISession,'socket'):
|
||||
self._createsocket()
|
||||
self.login()
|
||||
def _initsession(self):
|
||||
self.ipmicallback=None
|
||||
self.ipmicallbackargs=None
|
||||
self.sessioncontext=0
|
||||
self.sequencenumber=0
|
||||
self.sessionid=0
|
||||
@ -143,13 +163,31 @@ class IPMISession:
|
||||
print hashdata
|
||||
return hashdata
|
||||
|
||||
def _got_channel_auth_cap(self):
|
||||
pass
|
||||
|
||||
def _got_channel_auth_cap(self,response):
|
||||
if (response['error']):
|
||||
if self.onlogonargs is not None:
|
||||
args = (response,self.onlogonargs)
|
||||
else:
|
||||
args = (response,)
|
||||
self.onlogon(*args)
|
||||
return
|
||||
code = response['code']
|
||||
if code == 0xcc and self.ipmi15only is not None: #tried ipmi 2.0 against a 1.5 which should work, but some bmcs thought 'reserved' meant 'must be zero'
|
||||
self.ipmi15only=1
|
||||
return self._get_channel_auth_cap()
|
||||
if code != 0:
|
||||
response['error']=get_ipmi_errstr(code)+" while trying to get channel authentication capabilities"
|
||||
if self.onlogonargs is not None:
|
||||
args = (response,self.onlogonargs)
|
||||
else:
|
||||
args = (response,)
|
||||
self.onlogon(*args)
|
||||
return
|
||||
|
||||
|
||||
|
||||
def _get_channel_auth_cap(self):
|
||||
self.callback=self._got_channel_auth_cap
|
||||
self.ipmicallback=self._got_channel_auth_cap
|
||||
if (self.ipmi15only):
|
||||
self._send_ipmi_net_payload(netfn=0x6,command=0x38,data=[0x0e,0x04])
|
||||
else:
|
||||
@ -245,7 +283,11 @@ class IPMISession:
|
||||
del payload[0:2]
|
||||
response['data']=payload
|
||||
self.timeout=initialtimeout+(0.5*random())
|
||||
print repr(response)
|
||||
if self.ipmicallbackargs is not None:
|
||||
args=(response,self.ipmicallbackargs)
|
||||
else:
|
||||
args=(response,)
|
||||
self.ipmicallback(*args)
|
||||
|
||||
def _timedout(self):
|
||||
#TODO: retransmit and error handling on lost packets
|
||||
|
Loading…
x
Reference in New Issue
Block a user