2
0
mirror of https://opendev.org/x/pyghmi synced 2025-04-19 03:27:22 +00:00

Add IMMv2 remote media upload

IMMv2 media upload was required, so this implements it.

Change-Id: Idf4ea58c0b01186b2ae646ff428ff952ab72c0ef
This commit is contained in:
Jarrod Johnson 2018-06-18 15:48:41 -04:00
parent dfe960d5a3
commit dc8d2f3bf6
3 changed files with 76 additions and 7 deletions

View File

@ -933,12 +933,12 @@ class OEMHandler(generic.OEMHandler):
self.ipmicmd.xraw_command(netfn=0x32, command=0x9f, data=(8, 11))
def upload_media(self, filename, progress):
if self.has_xcc:
if self.has_xcc or self.has_imm:
return self.immhandler.upload_media(filename, progress)
return super(OEMHandler, self).upload_media(filename, progress)
def list_media(self):
if self.has_xcc:
if self.has_xcc or self.has_imm:
return self.immhandler.list_media()
return super(OEMHandler, self).list_media()

View File

@ -80,15 +80,17 @@ def fixup_str(propstr):
class FileUploader(threading.Thread):
def __init__(self, webclient, url, filename, data):
def __init__(self, webclient, url, filename, data=None, otherfields=None):
self.wc = webclient
self.url = url
self.filename = filename
self.data = data
self.otherfields = otherfields
super(FileUploader, self).__init__()
def run(self):
self.rsp = self.wc.upload(self.url, self.filename, self.data)
self.rsp = self.wc.upload(self.url, self.filename, self.data,
otherfields=self.otherfields)
class IMMClient(object):
@ -284,6 +286,13 @@ class IMMClient(object):
if 'token2_name' in rspdata and 'token2_value' in rspdata:
wc.set_header(rspdata['token2_name'],
rspdata['token2_value'])
if 'token3_name' in rspdata and 'token3_value' in rspdata:
self.uploadtoken = {rspdata['token3_name']:
rspdata['token3_value']}
else:
self.uploadtoken = {}
wc.set_header('Referer', self.adp_referer)
wc.set_header('Host', self.imm)
return wc
@property
@ -315,6 +324,46 @@ class IMMClient(object):
except KeyError:
return None
def upload_media(self, filename, progress=None):
xid = random.randint(0, 1000000000)
alloc = self.wc.grab_json_response(
'/data/set',
'RP_VmAllocateLoc({0},{1},1)'.format(self.username, filename))
if alloc['return'] != 'Success':
raise Exception('Unexpected reply to allocation: ' + repr(alloc))
slotid = alloc['slotId']
uploadfields = self.uploadtoken
uploadfields['filePath'] = alloc['filePath']
uploadfields['uploadType'] = 'iframe'
uploadfields['available'] = alloc['available']
uploadfields['checksum'] = xid
ut = FileUploader(self.wc, '/designs/imm/upload/rp_image_upload.esp',
filename, otherfields=uploadfields)
ut.start()
while ut.isAlive():
ut.join(3)
if progress:
progress({'phase': 'upload',
'progress': 100 * self.wc.get_upload_progress()})
status = self.wc.grab_json_response(
'/designs/imm/upload/rp_image_upload_status.esp',
'filePath={0}'.format(alloc['filePath']))
if not status['rpImgUploadResult'].endswith('Success'):
raise Exception(
'Upload status returned unexpected data: ' + repr(alloc))
ups = self.wc.grab_json_response(
'/data/set',
'RP_VmUpdateSize({1}, {0})'.format(status['originalFileSize'],
slotid))
if ups['return'] != 'Success':
raise Exception('Unexpected return to update size: ' + repr(ups))
ups = self.wc.grab_json_response('/data/set',
'RP_VmMount({0})'.format(slotid))
if ups['return'] != 'Success':
raise Exception('Unexpected return to mount: ' + repr(ups))
if progress:
progress({'phase': 'complete'})
def attach_remote_media(self, url, user, password):
url = url.replace(':', '\:')
params = urllib.urlencode({
@ -330,6 +379,16 @@ class IMMClient(object):
raise Exception(result['reason'])
self.weblogout()
def list_media(self):
rt = self.wc.grab_json_response(
'/designs/imm/dataproviders/imm_rp_images.php',
referer=self.adp_referer)
for item in rt['items']:
if 'images' in item:
for uload in item['images']:
if uload['status'] != 0:
yield media.Media(uload['filename'])
def detach_remote_media(self):
mnt = self.wc.grab_json_response(
'/designs/imm/dataproviders/imm_rp_images.php',
@ -339,6 +398,11 @@ class IMMClient(object):
if 'urls' in item:
for url in item['urls']:
removeurls.append(url['url'])
if 'images' in item:
for uload in item['images']:
self.wc.grab_json_response(
'/data/set', 'RP_RemoveFile({0}, 0)'.format(
uload['slotId']))
for url in removeurls:
url = url.replace(':', '\:')
params = urllib.urlencode({

View File

@ -148,13 +148,15 @@ class SecureHTTPConnection(httplib.HTTPConnection, object):
"""
if data is None:
data = open(filename, 'rb')
form = StringIO.StringIO(get_upload_form(filename, data, formname,
otherfields))
self._upbuffer = StringIO.StringIO(get_upload_form(filename, data,
formname,
otherfields))
ulheaders = self.stdheaders.copy()
ulheaders['Content-Type'] = 'multipart/form-data; boundary=' + BND
ulheaders['Content-Length'] = len(uploadforms[filename])
self.ulsize = len(uploadforms[filename])
webclient = self.dupe()
webclient.request('POST', url, form, ulheaders)
webclient.request('POST', url, self._upbuffer, ulheaders)
rsp = webclient.getresponse()
# peer updates in progress should already have pointers,
# subsequent transactions will cause memory to needlessly double,
@ -168,6 +170,9 @@ class SecureHTTPConnection(httplib.HTTPConnection, object):
rsp.read())
return rsp.read()
def get_upload_progress(self):
return float(self._upbuffer.tell()) / float(self.ulsize)
def request(self, method, url, body=None, headers=None, referer=None):
if headers is None:
headers = self.stdheaders.copy()