mirror of
https://opendev.org/x/pyghmi
synced 2026-01-10 18:22:32 +00:00
Fix SMM3 update process
First, break up the generic update into distinct pieces. For SMMv3, first supersede getting the upload url, as multipart is advertised, but doesn't work, but simpleupdate (deprecated) works. Then after upload, switch to hard coded logic specific to SMMv3 to determine how to start the update and where to monitor results. Then hand back over to generic to finish out monitoring. Change-Id: I33b2e67603400b920aca4aa11047c11978c3c6f6
This commit is contained in:
@@ -21,6 +21,7 @@ import re
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
from dateutil import tz
|
||||
import socket
|
||||
import time
|
||||
|
||||
import pyghmi.constants as const
|
||||
@@ -1065,22 +1066,7 @@ class OEMHandler(object):
|
||||
|
||||
def update_firmware(self, filename, data=None, progress=None, bank=None, otherfields=()):
|
||||
# disable cache to make sure we trigger the token renewal logic if needed
|
||||
usd = self._do_web_request('/redfish/v1/UpdateService', cache=False)
|
||||
upurl = usd.get('MultipartHttpPushUri', None)
|
||||
ismultipart = True
|
||||
if not upurl:
|
||||
ismultipart = False
|
||||
if usd.get('HttpPushUriTargetsBusy', False):
|
||||
raise exc.TemporaryError('Cannot run multtiple updates to '
|
||||
'same target concurrently')
|
||||
try:
|
||||
upurl = usd['HttpPushUri']
|
||||
except KeyError:
|
||||
raise exc.UnsupportedFunctionality('Redfish firmware update only supported for implementations with push update support')
|
||||
if 'HttpPushUriTargetsBusy' in usd:
|
||||
self._do_web_request(
|
||||
'/redfish/v1/UpdateService',
|
||||
{'HttpPushUriTargetsBusy': True}, method='PATCH')
|
||||
usd, upurl, ismultipart = self.retrieve_firmware_upload_url()
|
||||
try:
|
||||
uploadthread = webclient.FileUploader(
|
||||
self.webclient, upurl, filename, data, formwrap=ismultipart,
|
||||
@@ -1105,8 +1091,19 @@ class OEMHandler(object):
|
||||
except Exception:
|
||||
raise Exception(uploadthread.rsp)
|
||||
raise Exception(errmsg)
|
||||
return self.continue_update(uploadthread, progress)
|
||||
finally:
|
||||
if 'HttpPushUriTargetsBusy' in usd:
|
||||
self._do_web_request(
|
||||
'/redfish/v1/UpdateService',
|
||||
{'HttpPushUriTargetsBusy': False}, method='PATCH')
|
||||
|
||||
def continue_update(self, uploadthread, progress):
|
||||
rsp = json.loads(uploadthread.rsp)
|
||||
monitorurl = rsp['@odata.id']
|
||||
return self.monitor_update_progress(monitorurl, progress)
|
||||
|
||||
def monitor_update_progress(self, monitorurl, progress):
|
||||
complete = False
|
||||
phase = "apply"
|
||||
statetype = 'TaskState'
|
||||
@@ -1151,11 +1148,26 @@ class OEMHandler(object):
|
||||
if not retry:
|
||||
raise Exception('Falied to monitor update progress due to excessive timeouts')
|
||||
return 'pending'
|
||||
finally:
|
||||
|
||||
|
||||
def retrieve_firmware_upload_url(self):
|
||||
usd = self._do_web_request('/redfish/v1/UpdateService', cache=False)
|
||||
upurl = usd.get('MultipartHttpPushUri', None)
|
||||
ismultipart = True
|
||||
if not upurl:
|
||||
ismultipart = False
|
||||
if usd.get('HttpPushUriTargetsBusy', False):
|
||||
raise exc.TemporaryError('Cannot run multtiple updates to '
|
||||
'same target concurrently')
|
||||
try:
|
||||
upurl = usd['HttpPushUri']
|
||||
except KeyError:
|
||||
raise exc.UnsupportedFunctionality('Redfish firmware update only supported for implementations with push update support')
|
||||
if 'HttpPushUriTargetsBusy' in usd:
|
||||
self._do_web_request(
|
||||
'/redfish/v1/UpdateService',
|
||||
{'HttpPushUriTargetsBusy': False}, method='PATCH')
|
||||
self._do_web_request('/redfish/v1/UpdateService',
|
||||
{'HttpPushUriTargetsBusy': True}, method='PATCH')
|
||||
|
||||
return usd,upurl,ismultipart
|
||||
|
||||
|
||||
def _do_bulk_requests(self, urls, cache=True):
|
||||
|
||||
@@ -19,6 +19,7 @@ import pyghmi.constants as pygconst
|
||||
import pyghmi.util.webclient as webclient
|
||||
import pyghmi.exceptions as exc
|
||||
import time
|
||||
import socket
|
||||
|
||||
healthlookup = {
|
||||
'ok': pygconst.Health.Ok,
|
||||
@@ -78,6 +79,37 @@ class OEMHandler(generic.OEMHandler):
|
||||
def get_system_configuration(self, hideadvanced=True, fishclient=None):
|
||||
return {}
|
||||
|
||||
def retrieve_firmware_upload_url(self):
|
||||
# SMMv3 needs to do the non-multipart upload
|
||||
usd = self._do_web_request('/redfish/v1/UpdateService', cache=False)
|
||||
if usd.get('HttpPushUriTargetsBusy', False):
|
||||
raise exc.TemporaryError('Cannot run multtiple updates to '
|
||||
'same target concurrently')
|
||||
try:
|
||||
upurl = usd['HttpPushUri']
|
||||
except KeyError:
|
||||
raise exc.UnsupportedFunctionality('Redfish firmware update only supported for implementations with push update support')
|
||||
if 'HttpPushUriTargetsBusy' in usd:
|
||||
self._do_web_request(
|
||||
'/redfish/v1/UpdateService',
|
||||
{'HttpPushUriTargetsBusy': True}, method='PATCH')
|
||||
return usd,upurl,False
|
||||
|
||||
def continue_update(self, uploadthread, progress):
|
||||
# SMMv3 does not provide a response, must hardcode the continuation
|
||||
# /redfish/v1/UpdateService/FirmwareInventory/fwuimage
|
||||
rsp = self._do_web_request('/redfish/v1/UpdateService/FirmwareInventory/fwuimage')
|
||||
for ri in rsp.get('RelatedItem', []):
|
||||
targ = ri.get('@odata.id', None)
|
||||
parms = {'Oem': {'Lenovo': {'SecureRollBack': False}}}
|
||||
rsp = self._do_web_request('/redfish/v1/UpdateService', parms, method='PATCH')
|
||||
targspec = {'target': targ}
|
||||
rsp = self._do_web_request('/redfish/v1/UpdateService/Actions/UpdateService.StartUpdate', targspec)
|
||||
monitorurl = rsp.get('@odata.id', None)
|
||||
return self.monitor_update_progress(monitorurl, progress)
|
||||
|
||||
|
||||
|
||||
def get_diagnostic_data(self, savefile, progress=None, autosuffix=False):
|
||||
tsk = self._do_web_request(
|
||||
'/redfish/v1/Managers/bmc/LogServices/Dump/Actions/LogService.CollectDiagnosticData',
|
||||
|
||||
Reference in New Issue
Block a user