2
0
mirror of https://opendev.org/x/pyghmi synced 2025-01-27 19:37:44 +00:00

Add TSM remote media support

For the SR635/SR655 implement the media management commands.

Change-Id: I9675729c3ca3ebe07f770fa1504eb347953dd715
This commit is contained in:
Jarrod Johnson 2019-11-22 08:19:30 -05:00
parent 9bff4096b1
commit 2adaf00bd2
3 changed files with 198 additions and 3 deletions

View File

@ -919,6 +919,9 @@ class OEMHandler(generic.OEMHandler):
def attach_remote_media(self, url, username, password):
if self.has_imm:
self.immhandler.attach_remote_media(url, username, password)
elif self.has_tsma:
return self.tsmahandler.attach_remote_media(
url, username, password, None)
elif self.has_megarac:
proto, host, path = util.urlsplit(url)
if proto == 'smb':
@ -1002,6 +1005,8 @@ class OEMHandler(generic.OEMHandler):
def detach_remote_media(self):
if self.has_imm:
self.immhandler.detach_remote_media()
elif self.has_tsma:
self.tsmahandler.detach_remote_media()
elif self.has_megarac:
self.ipmicmd.xraw_command(
netfn=0x32, command=0x9f, data=(8, 10, 0, 0))
@ -1015,6 +1020,8 @@ class OEMHandler(generic.OEMHandler):
def list_media(self):
if self.has_xcc or self.has_imm:
return self.immhandler.list_media()
if self.has_tsma:
return self.tsmahandler.list_media()
return super(OEMHandler, self).list_media()
def get_health(self, summary):

View File

@ -16,6 +16,7 @@
import pyghmi.redfish.oem.generic as generic
import pyghmi.exceptions as exc
import pyghmi.media as media
import pyghmi.util.webclient as webclient
import struct
import time
@ -35,7 +36,7 @@ def read_hpm(filename):
with open(filename, 'rb') as hpmfile:
hpmfile.seek(0x20)
skip = struct.unpack('>H', hpmfile.read(2))[0]
hpmfile.seek(skip + 1, 1)
hpmfile.seek(skip + 1, 1)
sectype, compid = struct.unpack('BB', hpmfile.read(2))
while sectype == 2:
currsec = HpmSection()
@ -53,7 +54,7 @@ def read_hpm(filename):
if hashpresent != 1:
hashpresent = 0
currsec.hash_size = hashpresent * (256 * blocks + hdrsize)
hpmfile.seek(5, 1)
hpmfile.seek(5, 1)
currsec.data = hpmfile.read(currlen)
hpminfo.append(currsec)
sectype, compid = struct.unpack('BB', hpmfile.read(2))
@ -154,7 +155,7 @@ class TsmHandler(generic.OEMHandler):
wc.set_header('X-CSRFTOKEN', self.csrftok)
self._wc = wc
return wc
def update_firmware(self, filename, data=None, progress=None, bank=None):
wc = self.wc
wc.set_header('Content-Type', 'application/json')
@ -348,3 +349,188 @@ class TsmHandler(generic.OEMHandler):
rsp = wc.grab_json_response_with_status('/api/maintenance/reset', method='POST', headers=hdrs)
self._wc = None
return 'complete'
def _detach_all_media(self, wc, slots):
for slot in slots: # Stop all active redirections to reconfigure
if slot['redirection_status'] != 0:
wc.grab_json_response(
'/api/settings/media/remote/stop-media',
{'image_name': slot['image_name'],
'image_type': slot['media_type'],
'image_index': slot['media_index']})
def detach_remote_media(self):
wc = self.wc
slots = wc.grab_json_response('/api/settings/media/remote/configurations')
self._detach_all_media(wc, slots)
def _allocate_slot(self, slots, filetype, wc, server, path):
currhdds = []
currisos = []
for slot in slots:
if slot['image_name']:
if slot['media_type'] == 1:
currisos.append(slot['image_name'])
elif slot['media_type'] == 4:
currhdds.append(slot['image_name'])
else:
raise exc.UnsupportedFunctionality(
'Unrecognized mounted image: ' + repr(slot))
hddslots = len(currhdds)
cdslots = len(currisos)
if filetype == 1:
cdslots += 1
elif filetype == 4:
hddslots += 1
else:
raise exc.UnsupportedFunctionality('Unknown slot type requested')
gensettings = wc.grab_json_response('/api/settings/media/general')
samesettings = gensettings['same_settings'] == 1
if samesettings:
hds = gensettings['cd_remote_server_address']
hdp = gensettings['cd_remote_source_path'].replace('\\/', '/')
else:
hds = gensettings['hd_remote_server_address']
hdp = gensettings['hd_remote_source_path'].replace('\\/', '/')
if filetype == 1 and (currisos or (samesettings and currhdds)):
if gensettings['cd_remote_server_address'] != server:
raise exc.UnsupportedFunctionality(
'Cannot mount ISO images from multiple '
'servers at a time')
if gensettings['cd_remote_source_path'].replace('\\/', '/') != path:
raise exc.UnsupportedFunctionality(
'Cannot mount ISO images from different '
'directories at a time')
if filetype == 4 and currhdds:
if hds != server:
raise exc.UnsupportedFunctionality(
'Cannot mount IMG images from multiple servers at a time')
if hdp != path:
raise exc.UnsupportedFunctionality(
'Cannot mount IMG images from muliple directories at a '
'time')
self._detach_all_media(wc, slots)
if filetype == 1 or (samesettings and currhdds):
gensettings['cd_remote_server_address'] = server
gensettings['cd_remote_source_path'] = path #.replace('/', '\\/')
gensettings['cd_remote_share_type'] = 'nfs'
gensettings['mount_cd'] = 1
elif filetype == 4:
gensettings['same_settings'] = 0
gensettings['hd_remote_server_address'] = server
gensettings['hd_remote_source_path'] = path #.replace('/', '\\/')
gensettings['hd_remote_share_type'] = 'nfs'
gensettings['mount_hd'] = 1
gensettings['remote_media_support'] = 1
gensettings['cd_remote_password'] = ''
gensettings['hd_remote_password'] = ''
rsp = wc.grab_json_response_with_status('/api/settings/media/general',
gensettings, method='PUT')
# need to calibrate instances correctly
currinfo, status = wc.grab_json_response_with_status('/api/settings/media/instance')
currinfo['num_cd'] = cdslots
currinfo['num_hd'] = hddslots
if currinfo['kvm_num_cd'] > cdslots:
currinfo['kvm_num_cd'] = cdslots
if currinfo['kvm_num_hd'] > hddslots:
currinfo['kvm_num_hd'] = hddslots
rsp = wc.grab_json_response_with_status(
'/api/settings/media/instance', currinfo, method='PUT')
images = wc.grab_json_response('/api/settings/media/remote/images')
tries = 20
while tries and not images:
tries -= 1
time.sleep(1)
images = wc.grab_json_response('/api/settings/media/remote/images')
for iso in currisos:
self._exec_mount(iso, images, wc)
for iso in currhdds:
self._exec_mount(iso, images, wc)
def _exec_mount(self, name, images, wc):
for img in images:
if img['image_name'] == name:
break
else:
raise exc.InvalidParameterValue(
'Unable to locate image {0}'.format(name))
wc.grab_json_response(
'/api/settings/media/remote/start-media',
{'image_name': name, 'image_type': img['image_type'],
'image_index': img['image_index']})
def upload_media(self, filename, progress=None):
raise exc.UnsupportedFunctionality(
'Remote media upload not supported on this system')
def list_media(self):
wc = self.wc
rsp = wc.grab_json_response('/api/settings/media/general')
cds = rsp['cd_remote_server_address']
cdpath = rsp['cd_remote_source_path']
cdproto = rsp['cd_remote_share_type']
if rsp['same_settings'] == 1:
hds = cds
hdpath = cdpath
hdproto = cdproto
else:
hds = rsp['hd_remote_server_address']
hdpath = rsp['cd_remote_source_path']
hdproto = rsp['cd_remote_share_type']
slots = wc.grab_json_response('/api/settings/media/remote/configurations')
for slot in slots:
if slot['redirection_status'] == 1:
url = None
if slot['media_type'] == 1:
url = '{0}://{1}{2}/{3}'.format(
cdproto, cds, cdpath, slot['image_name'])
elif slot['media_type'] == 4:
url = '{0}://{1}{2}/{3}'.format(
hdproto, hds, hdpath, slot['image_name'])
if url:
yield media.Media(url)
def attach_remote_media(self, url, user, password, vmurls):
if not url.startswith('nfs://'):
raise exc.UnsupportedFunctionality(
'Only nfs:// urls are supported by this system')
path = url.replace('nfs://', '')
server, path = path.split('/', 1)
path, filename = path.rsplit('/', 1)
path = '/' + path
filetype = filename.rsplit('.')[-1]
if filetype == 'iso':
filetype = 1
elif filetype == 'img':
filetype = 4
else:
raise exc.UnsupportedFunctionality(
'Only iso and img files supported')
wc = self.wc
mountslots = wc.grab_json_response(
'/api/settings/media/remote/configurations')
images = wc.grab_json_response('/api/settings/media/remote/images')
currtypeenabled = False
for slot in mountslots:
if slot['image_name'] == filename:
return # Already mounted...
for img in images:
if img['image_name'] == filename:
break
if img['image_type'] == filetype:
currtypeenabled = True
else:
if currtypeenabled:
raise exc.UnsupportedFunctionality(
'This system cannot mount images from different locations at the same time')
img = None
myslot = None
for slot in mountslots:
if slot['media_type'] != filetype:
continue
if slot['redirection_status'] == 0:
break
else:
self._allocate_slot(mountslots, filetype, wc, server, path)
images = wc.grab_json_response('/api/settings/media/remote/images')
self._exec_mount(filename, images, wc)

View File

@ -289,6 +289,8 @@ class SecureHTTPConnection(httplib.HTTPConnection, object):
del headers['Content-Type']
if method == 'POST' and body and 'Content-Type' not in headers:
headers['Content-Type'] = 'application/x-www-form-urlencoded'
if body and 'Content-Length' not in headers:
headers['Content-Length'] = len(body)
if self.cookies:
cookies = []
for ckey in self.cookies: