From b5c5f62789726655117d27e03744b99d7bcdd369 Mon Sep 17 00:00:00 2001 From: Markus Hilger Date: Mon, 13 Jul 2026 00:59:38 +0200 Subject: [PATCH] Fix OEM asynchronous operation dispatch --- .../aiohmi/ipmi/oem/lenovo/handler.py | 13 ++++--- .../aiohmi/ipmi/oem/lenovo/imm.py | 34 +++++++++---------- .../aiohmi/ipmi/oem/lenovo/nextscale.py | 18 +++++----- confluent_server/aiohmi/redfish/command.py | 14 ++++---- .../aiohmi/redfish/oem/dell/idrac.py | 10 +++--- .../aiohmi/redfish/oem/lenovo/tsma.py | 2 +- .../aiohmi/redfish/oem/lenovo/xcc.py | 24 ++++++------- .../aiohmi/redfish/oem/lenovo/xcc3.py | 12 +++---- 8 files changed, 62 insertions(+), 65 deletions(-) diff --git a/confluent_server/aiohmi/ipmi/oem/lenovo/handler.py b/confluent_server/aiohmi/ipmi/oem/lenovo/handler.py index 65186e69..40fc0380 100755 --- a/confluent_server/aiohmi/ipmi/oem/lenovo/handler.py +++ b/confluent_server/aiohmi/ipmi/oem/lenovo/handler.py @@ -493,8 +493,7 @@ class OEMHandler(generic.OEMHandler): if await self.has_tsm() or await self.has_ami() or await self.has_asrock(): # Thinkserver with TSM if not self.oem_inventory_info: - async for desc in self._collect_tsm_inventory(): - yield desc + await self._collect_tsm_inventory() for compname in self.oem_inventory_info: yield compname elif await self.has_imm(): @@ -767,7 +766,7 @@ class OEMHandler(generic.OEMHandler): except (AttributeError, KeyError, IndexError): pass if await self.has_xcc() and name and name.startswith('PSU '): - self.immhandler.augment_psu_info(fru, name) + await self.immhandler.augment_psu_info(fru, name) if (await self.has_xcc() and 'memory_type' in fru and fru['memory_type'] == 'Unknown'): await self.immhandler.fetch_dimm(name, fru) @@ -1028,14 +1027,14 @@ class OEMHandler(generic.OEMHandler): async def add_extra_net_configuration(self, netdata, channel=None): if await self.has_tsm(): - ipv6_addr = await self.ipmicmd.raw_command( + ipv6_addr = (await self.ipmicmd.raw_command( netfn=0x0c, command=0x02, - data=(0x01, 0xc5, 0x00, 0x00))["data"][1:] + data=(0x01, 0xc5, 0x00, 0x00)))['data'][1:] if not ipv6_addr: return - rspdata = await self.ipmicmd.raw_command( + rspdata = (await self.ipmicmd.raw_command( netfn=0xc, command=0x02, - data=(0x1, 0xc6, 0, 0))['data'] + data=(0x1, 0xc6, 0, 0)))['data'] ipv6_prefix_ba = bytearray(rspdata) ipv6_prefix = ipv6_prefix_ba[1] diff --git a/confluent_server/aiohmi/ipmi/oem/lenovo/imm.py b/confluent_server/aiohmi/ipmi/oem/lenovo/imm.py index 9451cce8..5fd5848a 100644 --- a/confluent_server/aiohmi/ipmi/oem/lenovo/imm.py +++ b/confluent_server/aiohmi/ipmi/oem/lenovo/imm.py @@ -839,7 +839,7 @@ class IMMClient(object): hwmap[aname] = bdata self.datacache['lenovo_cached_hwmap'] = (hwmap, util._monotonic_time()) - self.weblogout() + await self.weblogout() return hwmap async def get_firmware_inventory(self, bmcver, components, category): @@ -1434,7 +1434,7 @@ class XCCClient(IMMClient): if controller != disk.id[0]: raise pygexc.UnsupportedFunctionality( 'Cannot span arrays across controllers') - raidmap = self._raid_number_map(controller) + raidmap = await self._raid_number_map(controller) if not raidmap: raise pygexc.InvalidParameterValue( 'There are no available drives for a new array') @@ -1487,21 +1487,21 @@ class XCCClient(IMMClient): # TODO(): adding new volume to existing array would be here pass - def _make_jbod(self, disk, realcfg): + async def _make_jbod(self, disk, realcfg): currstatus = self._get_status(disk, realcfg) if currstatus.lower() == 'jbod': return - self._make_available(disk, realcfg) - self._set_drive_state(disk, 16) + await self._make_available(disk, realcfg) + await self._set_drive_state(disk, 16) - def _make_global_hotspare(self, disk, realcfg): + async def _make_global_hotspare(self, disk, realcfg): currstatus = self._get_status(disk, realcfg) if currstatus.lower() == 'global hot spare': return - self._make_available(disk, realcfg) - self._set_drive_state(disk, 1) + await self._make_available(disk, realcfg) + await self._set_drive_state(disk, 1) - def _make_available(self, disk, realcfg): + async def _make_available(self, disk, realcfg): # 8 if jbod, 4 if hotspare.., leave alone if already... currstatus = self._get_status(disk, realcfg) newstate = None @@ -1511,7 +1511,7 @@ class XCCClient(IMMClient): newstate = 4 elif currstatus.lower() == 'jbod': newstate = 8 - self._set_drive_state(disk, newstate) + await self._set_drive_state(disk, newstate) def _get_status(self, disk, realcfg): for cfgdisk in realcfg.disks: @@ -1536,7 +1536,7 @@ class XCCClient(IMMClient): wc = await self.wc() rsp = await wc.grab_json_response( '/api/function', {'raidlink_ClearRaidConf': '1'}) - self.weblogout() + await self.weblogout() if rsp['return'] != 0: raise Exception('Unexpected return to clear config: ' + repr(rsp)) @@ -1560,10 +1560,10 @@ class XCCClient(IMMClient): if rsp.get('return', -1) != 0: raise Exception( 'Unexpected return to volume deletion: ' + repr(rsp)) - self._wait_storage_async() + await self._wait_storage_async() for disk in cfgspec.disks: await self._make_available(disk, realcfg) - self.weblogout() + await self.weblogout() async def apply_storage_configuration(self, cfgspec): realcfg = await self.get_storage_configuration(False) @@ -2168,7 +2168,7 @@ class XCCClient(IMMClient): retry = 3 while not complete and retry > 0: try: - pgress, status = self.grab_redfish_response_with_status( + pgress, status = await self.grab_redfish_response_with_status( monitorurl) except socket.timeout: pgress = None @@ -2205,10 +2205,10 @@ class XCCClient(IMMClient): return 'complete' return 'pending' finally: - self.grab_redfish_response_with_status( + await self.grab_redfish_response_with_status( '/redfish/v1/UpdateService', {'HttpPushUriTargetsBusy': False}, method='PATCH') - self.grab_redfish_response_with_status( + await self.grab_redfish_response_with_status( '/redfish/v1/UpdateService', {'HttpPushUriTargets': []}, method='PATCH') @@ -2410,7 +2410,7 @@ class XCCClient(IMMClient): errmsg = repr(rsp) if rsp else wc.lastjsonerror raise Exception( 'Unexpected result from PCI select: ' + errmsg) - self.set_property('/v2/ibmc/uefi/force-inventory', 1) + await self.set_property('/v2/ibmc/uefi/force-inventory', 1) else: await self._refresh_token() rsp = await wc.grab_json_response( diff --git a/confluent_server/aiohmi/ipmi/oem/lenovo/nextscale.py b/confluent_server/aiohmi/ipmi/oem/lenovo/nextscale.py index 1c15d507..53fe238e 100644 --- a/confluent_server/aiohmi/ipmi/oem/lenovo/nextscale.py +++ b/confluent_server/aiohmi/ipmi/oem/lenovo/nextscale.py @@ -671,14 +671,14 @@ class SMMClient(object): for bayn in range(1, numbays + 1): if fnmatch.fnmatch('bay{0}_user_cap'.format(bayn), key.lower()): - self.set_bay_cap(bayn, changeset[key]['value']) + await self.set_bay_cap(bayn, changeset[key]['value']) if fnmatch.fnmatch( 'bay{0}_user_cap_active'.format(bayn), key.lower()): - self.set_bay_cap_active(bayn, changeset[key]['value']) + await self.set_bay_cap_active(bayn, changeset[key]['value']) if fnmatch.fnmatch('chassis_user_cap', key.lower()): - self.set_bay_cap(numbays + 1, changeset[key]['value']) + await self.set_bay_cap(numbays + 1, changeset[key]['value']) if fnmatch.fnmatch('chassis_user_cap_active', key.lower()): - self.set_bay_cap_active(numbays + 1, changeset[key]['value']) + await self.set_bay_cap_active(numbays + 1, changeset[key]['value']) if fnmatch.fnmatch('fanspeed', key.lower()): for mode in self.fanmodes: byteval = mode @@ -816,10 +816,10 @@ class SMMClient(object): async def process_fru(self, fru): smmv1 = self.smm_variant & 0xf0 == 0 # TODO(jjohnson2): can also get EIOM, SMM, and riser data if warranted - snum = bytes(await self.ipmicmd.raw_command( - netfn=0x32, command=0xb0, data=(5, 1))['data'][:]) - mnum = bytes(await self.ipmicmd.raw_command( - netfn=0x32, command=0xb0, data=(5, 0))['data'][:]) + snum = bytes((await self.ipmicmd.raw_command( + netfn=0x32, command=0xb0, data=(5, 1)))['data'][:]) + mnum = bytes((await self.ipmicmd.raw_command( + netfn=0x32, command=0xb0, data=(5, 0)))['data'][:]) if not smmv1: snum = snum[2:] mnum = mnum[2:] @@ -1115,5 +1115,5 @@ class SMMClient(object): async def wc(self): if (not self._wc or self._wc.broken or self._wc.vintage < util._monotonic_time() + 30): - self._wc = await self.get_webclient() + self._wc = self.get_webclient() return self._wc diff --git a/confluent_server/aiohmi/redfish/command.py b/confluent_server/aiohmi/redfish/command.py index e602393f..dd0cdfa4 100644 --- a/confluent_server/aiohmi/redfish/command.py +++ b/confluent_server/aiohmi/redfish/command.py @@ -1035,7 +1035,7 @@ class Command(object): 'Address': static_gateway, }] if patch: - nicurl = self._get_bmc_nic_url(name) + nicurl = await self._get_bmc_nic_url(name) await self._do_web_request(nicurl, patch, 'PATCH') async def set_net_configuration(self, ipv4_address=None, ipv4_configuration=None, @@ -1458,22 +1458,22 @@ class Command(object): del self.wc.stdheaders['Authorization'] return for vmurl in vmurls: - vminfo = self._do_web_request(vmurl, cache=False) + vminfo = await self._do_web_request(vmurl, cache=False) if vminfo.get('ConnectedVia', None) != 'NotConnected': continue inserturl = vminfo.get( 'Actions', {}).get( '#VirtualMedia.InsertMedia', {}).get('target', None) if inserturl: - self._do_web_request(inserturl, {'Image': url}) + await self._do_web_request(inserturl, {'Image': url}) else: try: - self._do_web_request(vmurl, - {'Image': url, 'Inserted': True}, - 'PATCH') + await self._do_web_request(vmurl, + {'Image': url, 'Inserted': True}, + 'PATCH') except exc.RedfishError as re: if re.msgid.endswith(u'PropertyUnknown'): - self._do_web_request(vmurl, {'Image': url}, 'PATCH') + await self._do_web_request(vmurl, {'Image': url}, 'PATCH') else: raise break diff --git a/confluent_server/aiohmi/redfish/oem/dell/idrac.py b/confluent_server/aiohmi/redfish/oem/dell/idrac.py index e52eacdf..9863dae7 100644 --- a/confluent_server/aiohmi/redfish/oem/dell/idrac.py +++ b/confluent_server/aiohmi/redfish/oem/dell/idrac.py @@ -17,8 +17,8 @@ import aiohmi.redfish.oem.generic as generic class OEMHandler(generic.OEMHandler): - def set_bootdev(self, bootdev, persist=False, uefiboot=None, - fishclient=None): + async def set_bootdev(self, bootdev, persist=False, uefiboot=None, + fishclient=None): # gleaned from web console, under configuration, system settings, # hardware, first boot device. iDrac presumes that the standard # explicitly refers only to physical devices. I think the intent @@ -26,8 +26,8 @@ class OEMHandler(generic.OEMHandler): # the 'physical' standard to the vFDD/VCD-DVD seen in the idrac # web gui if bootdev not in ('floppy', 'cd'): - return super(OEMHandler, self).set_bootdev(bootdev, persist, - uefiboot, fishclient) + return await super(OEMHandler, self).set_bootdev(bootdev, persist, + uefiboot, fishclient) payload = {'Attributes': {}} if persist: payload['Attributes']['ServerBoot.1.BootOnce'] = 'Disabled' @@ -37,7 +37,7 @@ class OEMHandler(generic.OEMHandler): payload['Attributes']['ServerBoot.1.FirstBootDevice'] = 'vFDD' elif bootdev == 'cd': payload['Attributes']['ServerBoot.1.FirstBootDevice'] = 'VCD-DVD' - fishclient._do_web_request( + await fishclient._do_web_request( '/redfish/v1/Managers/iDRAC.Embedded.1/Attributes', payload, method='PATCH') return {'bootdev': bootdev} diff --git a/confluent_server/aiohmi/redfish/oem/lenovo/tsma.py b/confluent_server/aiohmi/redfish/oem/lenovo/tsma.py index 49d0fe8c..0136bc13 100644 --- a/confluent_server/aiohmi/redfish/oem/lenovo/tsma.py +++ b/confluent_server/aiohmi/redfish/oem/lenovo/tsma.py @@ -186,7 +186,7 @@ class TsmHandler(generic.OEMHandler): if 'dns_domain'.startswith(key.lower()): dnschgs['domain_name'] = currval if 'password_complexity'.startswith(key.lower()): - self._set_pass_complexity(currval, wc) + await self._set_pass_complexity(currval, wc) if 'password_login_failures'.startswith(key.lower()): await self._set_pass_lockout(currval, wc) if dnschgs: diff --git a/confluent_server/aiohmi/redfish/oem/lenovo/xcc.py b/confluent_server/aiohmi/redfish/oem/lenovo/xcc.py index 09fd1a11..8dad831f 100644 --- a/confluent_server/aiohmi/redfish/oem/lenovo/xcc.py +++ b/confluent_server/aiohmi/redfish/oem/lenovo/xcc.py @@ -184,7 +184,7 @@ class OEMHandler(generic.OEMHandler): try: self.fwo = await self.fwc.get_fw_options(fetchimm=fetchimm) except config.Unsupported: - return super(OEMHandler, self).get_system_configuration( + return await super(OEMHandler, self).get_system_configuration( hideadvanced, fishclient) except Exception: raise Exception('%s failed to retrieve UEFI configuration' @@ -831,7 +831,7 @@ class OEMHandler(generic.OEMHandler): wc.set_header('X-XSRF-TOKEN', cookie.value) wc.vintage = util._monotonic_time() - def _make_available(self, disk, realcfg): + async def _make_available(self, disk, realcfg): # 8 if jbod, 4 if hotspare.., leave alone if already... currstatus = self._get_status(disk, realcfg) newstate = None @@ -841,21 +841,21 @@ class OEMHandler(generic.OEMHandler): newstate = 4 elif currstatus.lower() == 'jbod': newstate = 8 - self._set_drive_state(disk, newstate) + await self._set_drive_state(disk, newstate) - def _make_jbod(self, disk, realcfg): + async def _make_jbod(self, disk, realcfg): currstatus = self._get_status(disk, realcfg) if currstatus.lower() == 'jbod': return - self._make_available(disk, realcfg) - self._set_drive_state(disk, 16) + await self._make_available(disk, realcfg) + await self._set_drive_state(disk, 16) - def _make_global_hotspare(self, disk, realcfg): + async def _make_global_hotspare(self, disk, realcfg): currstatus = self._get_status(disk, realcfg) if currstatus.lower() == 'global hot spare': return - self._make_available(disk, realcfg) - self._set_drive_state(disk, 1) + await self._make_available(disk, realcfg) + await self._set_drive_state(disk, 1) def _get_status(self, disk, realcfg): for cfgdisk in realcfg.disks: @@ -978,7 +978,7 @@ class OEMHandler(generic.OEMHandler): pass async def _create_array(self, pool): - params = self._parse_array_spec(pool) + params = await self._parse_array_spec(pool) cid = params['controller'].split(',')[0] cslotno = params['controller'].split(',')[1] url = '/api/function/raid_conf?params=raidlink_GetDefaultVolProp' @@ -1443,7 +1443,7 @@ class OEMHandler(generic.OEMHandler): async def update_firmware_backend(self, filename, data=None, progress=None, bank=None): - self._refresh_token() + await self._refresh_token() wc = await self.wc() rsv = await wc.grab_json_response('/api/providers/fwupdate', json.dumps( {'UPD_WebReserve': 1})) @@ -1470,7 +1470,7 @@ class OEMHandler(generic.OEMHandler): raise Exception('File is larger than supported') raise Exception('Unexpected result:' + repr(rsp)) uploadstate = rsp['state'] - self._refresh_token() + await self._refresh_token() while uploadstate != 'done': rsp = await wc.grab_json_response( '/upload/progress?X-Progress-ID={0}'.format(xid)) diff --git a/confluent_server/aiohmi/redfish/oem/lenovo/xcc3.py b/confluent_server/aiohmi/redfish/oem/lenovo/xcc3.py index a109931c..342b5e92 100644 --- a/confluent_server/aiohmi/redfish/oem/lenovo/xcc3.py +++ b/confluent_server/aiohmi/redfish/oem/lenovo/xcc3.py @@ -432,7 +432,7 @@ class OEMHandler(generic.OEMHandler): await self._make_available(disk, realcfg) self._urlcache.clear() - def _parse_array_spec(self, arrayspec): + async def _parse_array_spec(self, arrayspec): controller = None if arrayspec.disks: for disk in list(arrayspec.disks) + list(arrayspec.hotspares): @@ -441,7 +441,7 @@ class OEMHandler(generic.OEMHandler): if controller != disk.id[0]: raise pygexc.UnsupportedFunctionality( 'Cannot span arrays across controllers') - raidmap = self._raid_number_map(controller) + raidmap = await self._raid_number_map(controller) if not raidmap: raise pygexc.InvalidParameterValue( 'No RAID Type supported on this controller') @@ -511,7 +511,7 @@ class OEMHandler(generic.OEMHandler): return themap async def _create_array(self, pool): - params = self._parse_array_spec(pool) + params = await self._parse_array_spec(pool) cid = params['controller'].split(',')[0] c_capabilities, code = await self.webclient.grab_json_response_with_status( f'/redfish/v1/Systems/1/Storage/{cid}/Volumes/Capabilities') @@ -906,7 +906,7 @@ class OEMHandler(generic.OEMHandler): cache=False) rawsettings = rawsettings.get('Attributes', {}) pendingsettings = {} - ret = self._set_redfish_settings( + ret = await self._set_redfish_settings( changeset, fishclient, currsettings, rawsettings, pendingsettings, self.lenovobmcattrdeps, reginfo, '/redfish/v1/Managers/1/Oem/Lenovo/BMCSettings') @@ -1039,7 +1039,7 @@ class OEMHandler(generic.OEMHandler): if usbsettings: await self.apply_usb_configuration(usbsettings) if bmchangeset: - self._set_xcc3_settings(bmchangeset, self) + await self._set_xcc3_settings(bmchangeset, self) async def apply_usb_configuration(self, usbsettings): bmcattribs = {} @@ -1220,5 +1220,3 @@ class OEMHandler(generic.OEMHandler): 'Name': 'HPM-FPGA Pending', 'build': pendinghpm} raise pygexc.BypassGenericBehavior() - -