2
0
mirror of https://opendev.org/x/pyghmi synced 2025-09-17 23:38:21 +00:00

Implement upload_media for Lenovo

Implement the Lenovo OEM mechanism
for media upload under redfish command object.

Change-Id: I47f7b8ba5751741a1c6fb322366b18a9120f7db3
This commit is contained in:
Jarrod Johnson
2019-06-10 14:06:36 -04:00
parent 963d8b40c1
commit a9d8882773
4 changed files with 75 additions and 2 deletions

View File

@@ -1982,7 +1982,7 @@ class Command(object):
:param filename: The filename to use, the basename of the parameter
will be given to the bmc.
:param filename: Optional callback for progress updates
:param progress: Optional callback for progress updates
"""
self.oem_init()
return self._oem.upload_media(filename, progress)

View File

@@ -1198,6 +1198,19 @@ class Command(object):
"""
return self.oem.apply_storage_configuration(cfgspec)
def upload_media(self, filename, progress=None):
"""Upload a file to be hosted on the target BMC
This will upload the specified data to
the BMC so that it will make it available to the system as an emulated
USB device.
:param filename: The filename to use, the basename of the parameter
will be given to the bmc.
:param progress: Optional callback for progress updates
"""
return self.oem.upload_media(filename, progress)
if __name__ == '__main__':
import os
import sys

View File

@@ -52,6 +52,10 @@ class OEMHandler(object):
raise exc.UnsupportedFunctionality(
'Remote storage configuration not supported on this platform')
def upload_media(self, filename, progress=None):
raise exc.UnsupportedFunctionality(
'Remote media upload not supported on this platform')
def _do_web_request(self, url, payload=None, method=None, cache=True):
res = None
if cache and payload is None and method is None:

View File

@@ -22,6 +22,8 @@ import time
import pyghmi.ipmi.private.util as util
import pyghmi.exceptions as pygexc
import pyghmi.storage as storage
import pyghmi.util.webclient as webclient
import random
class OEMHandler(generic.OEMHandler):
@@ -79,7 +81,7 @@ class OEMHandler(generic.OEMHandler):
except ValueError:
pass
yield ('{0} {1}'.format(aname, fname), bdata)
def _get_disk_firmware_single(self, diskent, prefix=''):
bdata = {}
if not prefix and diskent.get('location', '').startswith('M.2'):
@@ -178,6 +180,15 @@ class OEMHandler(generic.OEMHandler):
'Unexpected return to set disk state: {0}'.format(
rsp.get('return', -1)))
def _refresh_token(self):
self._refresh_token_wc(self.wc)
def _refresh_token_wc(self, wc):
wc.grab_json_response('/api/providers/identity')
if '_csrf_token' in wc.cookies:
wc.set_header('X-XSRF-TOKEN', self.wc.cookies['_csrf_token'])
wc.vintage = util._monotonic_time()
def _make_available(self, disk, realcfg):
# 8 if jbod, 4 if hotspare.., leave alone if already...
currstatus = self._get_status(disk, realcfg)
@@ -414,3 +425,48 @@ class OEMHandler(generic.OEMHandler):
if '_csrf_token' in wc.cookies:
wc.set_header('X-XSRF-TOKEN', wc.cookies['_csrf_token'])
return wc
def upload_media(self, filename, progress=None):
xid = random.randint(0, 1000000000)
self._refresh_token()
uploadthread = webclient.FileUploader(
self.wc, '/upload?X-Progress-ID={0}'.format(xid), filename, None)
uploadthread.start()
while uploadthread.isAlive():
uploadthread.join(3)
rsp = self.wc.grab_json_response(
'/upload/progress?X-Progress-ID={0}'.format(xid))
if progress and rsp['state'] == 'uploading':
progress({'phase': 'upload',
'progress': 100.0 * rsp['received'] / rsp['size']})
self._refresh_token()
rsp = json.loads(uploadthread.rsp)
if progress:
progress({'phase': 'upload',
'progress': 100.0})
thepath = rsp['items'][0]['path']
thename = rsp['items'][0]['name']
writeable = 1 if filename.lower().endswith('.img') else 0
addfile = {"Url": thepath, "Protocol": 6, "Write": writeable,
"Credential": ":", "Option": "", "Domain": "",
"WebUploadName": thename}
rsp = self.wc.grab_json_response('/api/providers/rp_rdoc_addfile',
addfile)
self._refresh_token()
if rsp.get('return', -1) != 0:
errmsg = repr(rsp) if rsp else self.wc.lastjsonerror
raise Exception('Unrecognized return: ' + errmsg)
rsp = self.wc.grab_json_response('/api/providers/rp_rdoc_getfiles')
if 'items' not in rsp or len(rsp['items']) == 0:
raise Exception(
'Image upload was not accepted, it may be too large')
self._refresh_token()
rsp = self.wc.grab_json_response('/api/providers/rp_rdoc_mountall',
{})
self._refresh_token()
if rsp.get('return', -1) != 0:
errmsg = repr(rsp) if rsp else self.wc.lastjsonerror
raise Exception('Unrecognized return: ' + errmsg)
if progress:
progress({'phase': 'complete'})
#self.weblogout()