2
0
mirror of https://github.com/xcat2/confluent.git synced 2025-08-26 21:20:30 +00:00

Add IPMI enablement to generic Redfish handler

If attributes indicate desire for IPMI, try to accomodate.
This commit is contained in:
Jarrod Johnson
2024-08-05 11:07:50 -04:00
parent cfb31a0d8d
commit 30c4d6b863
3 changed files with 76 additions and 29 deletions

View File

@@ -57,8 +57,28 @@ class NodeHandler(generic.NodeHandler):
self.csrftok = None
self.channel = None
self.atdefault = True
self._srvroot = None
self._mgrinfo = None
super(NodeHandler, self).__init__(info, configmanager)
def srvroot(self, wc):
if not self._srvroot:
srvroot, status = wc.grab_json_response_with_status('/redfish/v1/')
if status == 200:
self._srvroot = srvroot
return self._srvroot
def mgrinfo(self, wc):
if not self._mgrinfo:
mgrs = self.srvroot(wc)['Managers']['@odata.id']
rsp = wc.grab_json_response(mgrs)
if len(rsp['Members']) != 1:
raise Exception("Can not handle multiple Managers")
mgrurl = rsp['Members'][0]['@odata.id']
self._mgrinfo = wc.grab_json_response(mgrurl)
return self._mgrinfo
def get_firmware_default_account_info(self):
raise Exception('This must be subclassed')
@@ -75,6 +95,30 @@ class NodeHandler(generic.NodeHandler):
fprint = util.get_fingerprint(self.https_cert)
return util.cert_matches(fprint, certificate)
def enable_ipmi(self, wc):
npu = self.mgrinfo(wc).get(
'NetworkProtocol', {}).get('@odata.id', None)
if not npu:
raise Exception('Cannot enable IPMI, no NetworkProtocol on BMC')
npi = wc.grab_json_response(npu)
if not npi.get('IPMI', {}).get('ProtocolEnabled'):
wc.set_header('If-Match', '*')
wc.grab_json_response_with_status(
npu, {'IPMI': {'ProtocolEnabled': True}}, method='PATCH')
acctinfo = wc.grab_json_response_with_status(
self.target_account_url(wc))
acctinfo = acctinfo[0]
actypes = acctinfo['AccountTypes']
candidates = acctinfo['AccountTypes@Redfish.AllowableValues']
if 'IPMI' not in actypes and 'IPMI' in candidates:
actypes.append('IPMI')
acctupd = {
'AccountTypes': actypes,
'Password': self.currpass,
}
rsp = wc.grab_json_response_with_status(
self.target_account_url(wc), acctupd, method='PATCH')
def _get_wc(self):
defuser, defpass = self.get_firmware_default_account_info()
wc = webclient.SecureHTTPConnection(self.ipaddr, 443, verifycallback=self.validate_cert)
@@ -144,13 +188,33 @@ class NodeHandler(generic.NodeHandler):
self.currpass = self.targpass
return wc
def target_account_url(self, wc):
asrv = self.srvroot(wc).get('AccountService', {}).get('@odata.id')
rsp, status = wc.grab_json_response_with_status(asrv)
accts = rsp.get('Accounts', {}).get('@odata.id')
rsp, status = wc.grab_json_response_with_status(accts)
accts = rsp.get('Members', [])
for accturl in accts:
accturl = accturl.get('@odata.id', '')
if accturl:
rsp, status = wc.grab_json_response_with_status(accturl)
if rsp.get('UserName', None) == self.curruser:
targaccturl = accturl
break
else:
raise Exception("Unable to identify Account URL to modify on this BMC")
return targaccturl
def config(self, nodename):
mgrs = None
self.nodename = nodename
creds = self.configmanager.get_node_attributes(
nodename, ['secret.hardwaremanagementuser',
'secret.hardwaremanagementpassword',
'hardwaremanagement.manager', 'hardwaremanagement.method', 'console.method'],
True)
'hardwaremanagement.manager',
'hardwaremanagement.method',
'console.method'],
True)
cd = creds.get(nodename, {})
defuser, defpass = self.get_firmware_default_account_info()
user, passwd, _ = self.get_node_credentials(
@@ -160,7 +224,6 @@ class NodeHandler(generic.NodeHandler):
self.targuser = user
self.targpass = passwd
wc = self._get_wc()
srvroot, status = wc.grab_json_response_with_status('/redfish/v1/')
curruserinfo = {}
authupdate = {}
wc.set_header('Content-Type', 'application/json')
@@ -169,21 +232,7 @@ class NodeHandler(generic.NodeHandler):
if passwd != self.currpass:
authupdate['Password'] = passwd
if authupdate:
targaccturl = None
asrv = srvroot.get('AccountService', {}).get('@odata.id')
rsp, status = wc.grab_json_response_with_status(asrv)
accts = rsp.get('Accounts', {}).get('@odata.id')
rsp, status = wc.grab_json_response_with_status(accts)
accts = rsp.get('Members', [])
for accturl in accts:
accturl = accturl.get('@odata.id', '')
if accturl:
rsp, status = wc.grab_json_response_with_status(accturl)
if rsp.get('UserName', None) == self.curruser:
targaccturl = accturl
break
else:
raise Exception("Unable to identify Account URL to modify on this BMC")
targaccturl = self.target_account_url(wc)
rsp, status = wc.grab_json_response_with_status(targaccturl, authupdate, method='PATCH')
if status >= 300:
raise Exception("Failed attempting to update credentials on BMC")
@@ -193,7 +242,11 @@ class NodeHandler(generic.NodeHandler):
while tries and status >= 300:
tries -= 1
eventlet.sleep(1.0)
_, status = wc.grab_json_response_with_status('/redfish/v1/Managers')
_, status = wc.grab_json_response_with_status(
'/redfish/v1/Managers')
if (cd.get('hardwaremanagement.method', {}).get('value', 'ipmi') != 'redfish'
or cd.get('console.method', {}).get('value', None) == 'ipmi'):
self.enable_ipmi(wc)
if ('hardwaremanagement.manager' in cd and
cd['hardwaremanagement.manager']['value'] and
not cd['hardwaremanagement.manager']['value'].startswith(
@@ -204,14 +257,8 @@ class NodeHandler(generic.NodeHandler):
newip = newipinfo[-1][0]
if ':' in newip:
raise exc.NotImplementedException('IPv6 remote config TODO')
mgrs = srvroot['Managers']['@odata.id']
rsp = wc.grab_json_response(mgrs)
if len(rsp['Members']) != 1:
raise Exception("Can not handle multiple Managers")
mgrurl = rsp['Members'][0]['@odata.id']
mginfo = wc.grab_json_response(mgrurl)
hifurls = get_host_interface_urls(wc, mginfo)
mgtnicinfo = mginfo['EthernetInterfaces']['@odata.id']
hifurls = get_host_interface_urls(wc, self.mgrinfo(wc))
mgtnicinfo = self.mgrinfo(wc)['EthernetInterfaces']['@odata.id']
mgtnicinfo = wc.grab_json_response(mgtnicinfo)
mgtnics = [x['@odata.id'] for x in mgtnicinfo.get('Members', [])]
actualnics = []
@@ -240,7 +287,6 @@ class NodeHandler(generic.NodeHandler):
rsp, status = wc.grab_json_response_with_status(actualnics[0], {
'DHCPv4': {'DHCPEnabled': False},
'IPv4StaticAddresses': [newconfig]}, method='PATCH')
elif self.ipaddr.startswith('fe80::'):
self.configmanager.set_node_attributes(
{nodename: {'hardwaremanagement.manager': self.ipaddr}})

View File

@@ -639,7 +639,7 @@ def remote_nodecfg(nodename, cfm):
ipaddr = ipaddr.split('/', 1)[0]
ipaddr = getaddrinfo(ipaddr, 0)[0][-1]
if not ipaddr:
raise Excecption('Cannot remote configure a system without known '
raise Exception('Cannot remote configure a system without known '
'address')
info = {'addresses': [ipaddr]}
nh = NodeHandler(info, cfm)

View File

@@ -24,6 +24,7 @@ getaddrinfo = eventlet.support.greendns.getaddrinfo
class NodeHandler(redfishbmc.NodeHandler):
devname = 'XCC'
def get_firmware_default_account_info(self):
return ('USERID', 'PASSW0RD')