2
0
mirror of https://github.com/xcat2/confluent.git synced 2025-03-19 18:07:48 +00:00

Add remote media handling to API

This commit is contained in:
Jarrod Johnson 2017-12-08 15:03:27 -05:00
parent ae39a84a30
commit 09d20ea1ff
4 changed files with 94 additions and 17 deletions

View File

@ -250,6 +250,25 @@ def _init_core():
},
},
},
'media': {
'uploads': PluginCollection({
'pluginattrs': ['hardwaremanagement.method'],
'default': 'ipmi',
}),
'attach': PluginRoute({
'pluginattrs': ['hardwaremanagement.method'],
'default': 'ipmi',
}),
'detach': PluginRoute({
'pluginattrs': ['hardwaremanagement.method'],
'default': 'ipmi',
}),
'current': PluginRoute({
'pluginattrs': ['hardwaremanagement.method'],
'default': 'ipmi',
}),
},
'power': {
'state': PluginRoute({
'pluginattrs': ['hardwaremanagement.method'],

View File

@ -23,13 +23,17 @@ import confluent.messages as msg
import eventlet
updatesbytarget = {}
uploadsbytarget = {}
updatepool = eventlet.greenpool.GreenPool(256)
def execupdate(handler, filename, updateobj):
def execupdate(handler, filename, updateobj, type):
try:
completion = handler(filename, progress=updateobj.handle_progress,
bank=updateobj.bank)
if type == 'firmware':
completion = handler(filename, progress=updateobj.handle_progress,
bank=updateobj.bank)
else:
completion = handler(filename, progress=updateobj.handle_progress)
if completion is None:
completion = 'complete'
updateobj.handle_progress({'phase': completion, 'progress': 100.0})
@ -44,26 +48,30 @@ def execupdate(handler, filename, updateobj):
class Updater(object):
def __init__(self, node, handler, filename, tenant=None, name=None,
bank=None):
bank=None, type='firmware'):
self.bank = bank
self.node = node
self.phase = 'initializing'
self.detail = ''
self.percent = 0.0
#Change the below to a pool???
self.updateproc = updatepool.spawn(execupdate, handler, filename, self)
if (node, tenant) not in updatesbytarget:
updatesbytarget[(node, tenant)] = {}
self.updateproc = updatepool.spawn(execupdate, handler, filename,
self, type)
if type == 'firmware':
myparty = updatesbytarget
elif type == 'mediaupload':
myparty = uploadsbytarget
if (node, tenant) not in myparty:
myparty[(node, tenant)] = {}
if name is None:
name = 1
while '{0}'.format(name) in updatesbytarget[(node, tenant)]:
while '{0}'.format(name) in myparty[(node, tenant)]:
name += 1
self.name = '{0}'.format(name)
updatesbytarget[(node, tenant)][self.name] = self
myparty[(node, tenant)][self.name] = self
def handle_progress(self, progress):
self.phase = progress['phase']
self.percent = float(progress['progress'])
self.phase = progress.get('phase', 'unknown')
self.percent = float(progress.get('progress', 100.0))
self.detail = progress.get('detail', '')
def cancel(self):
@ -91,18 +99,25 @@ def remove_updates(nodes, tenant, element):
node, upid))
def list_updates(nodes, tenant, element):
def list_updates(nodes, tenant, element, type='firmware'):
showmode = False
if type == 'mediaupload':
myparty = uploadsbytarget
verb = 'upload'
else:
myparty = updatesbytarget
verb = 'update'
if len(element) > 4:
showmode = True
upid = element[-1]
for node in nodes:
if showmode:
try:
updater = updatesbytarget[(node, tenant)][upid]
updater = myparty[(node, tenant)][upid]
except KeyError:
raise exc.NotFoundException('No matching update process found')
raise exc.NotFoundException(
'No matching {0} process found'.format(verb))
yield msg.KeyValueData(updater.progress, name=node)
else:
for updateid in updatesbytarget.get((node, tenant), {}):
for updateid in myparty.get((node, tenant), {}):
yield msg.ChildCollection(updateid)

View File

@ -407,6 +407,10 @@ def get_input_message(path, operation, inputdata, nodes=None, multinode=False,
return InputNTPServer(path, nodes, inputdata)
elif 'inventory/firmware/updates/active' in '/'.join(path) and inputdata:
return InputFirmwareUpdate(path, nodes, inputdata)
elif '/'.join(path).startswith('media/detach'):
return DetachMedia(path, nodes, inputdata)
elif '/'.join(path).startswith('media/'):
return InputMedia(path, nodes, inputdata)
elif inputdata:
raise exc.InvalidArgumentException(
'No known input handler for request')
@ -414,10 +418,22 @@ def get_input_message(path, operation, inputdata, nodes=None, multinode=False,
class InputFirmwareUpdate(ConfluentMessage):
def __init__(self, path, nodes, inputdata):
self.filename = inputdata['filename']
self.filename = inputdata.get('filename', inputdata['url'])
self.bank = inputdata.get('bank', None)
self.nodes = nodes
class InputMedia(InputFirmwareUpdate):
# Use InputFirmwareUpdate
pass
class DetachMedia(ConfluentMessage):
def __init__(self, path, nodes, inputdata):
if inputdata['detach'] != 'all':
raise exc.InvalidArgumentException('Currently only supporting'
'{"detach": "all"}')
class Media(ConfluentMessage):
def __init__(self, node, media):
self.kvpairs = {node: {'name': media.name, 'url': media.url}}
class InputAlertData(ConfluentMessage):

View File

@ -450,6 +450,14 @@ class IpmiHandler(object):
self.handle_update()
elif self.element[0] == 'inventory':
self.handle_inventory()
elif self.element == ['media', 'attach']:
self.handle_attach_media()
elif self.element == ['media', 'detach']:
self.handle_detach_media()
elif self.element == ['media', 'uploads']:
self.handle_media_upload()
elif self.element == ['media', 'current']:
self.handle_list_media()
elif self.element == ['events', 'hardware', 'log']:
self.do_eventlog()
elif self.element == ['events', 'hardware', 'decode']:
@ -468,6 +476,22 @@ class IpmiHandler(object):
'nodes/{0}/inventory/firmware/updates/active/{1}'.format(
self.node, u.name)))
def handle_media_upload(self):
u = firmwaremanager.Updater(self.node, self.ipmicmd.upload_media,
self.inputdata.filename, self.tenant,
type='mediaupload')
self.output.put(msg.CreatedResource(
'nodes/{0}/media/uploads/{1}'.format(self.node, u.name)))
def handle_attach_media(self):
self.ipmicmd.attach_remote_media(self.inputdata.filename)
def handle_detach_media(self):
self.ipmicmd.detach_remote_media()
def handle_list_media(self):
for media in self.ipmicmd.list_media():
self.output.put(msg.Media(self.node, media))
def handle_configuration(self):
if self.element[1:3] == ['management_controller', 'alerts']:
@ -1022,6 +1046,9 @@ def retrieve(nodes, element, configmanager, inputdata):
if '/'.join(element).startswith('inventory/firmware/updates/active'):
return firmwaremanager.list_updates(nodes, configmanager.tenant,
element)
elif '/'.join(element).startswith('media/uploads'):
return firmwaremanager.list_updates(nodes, configmanager.tenent,
element, 'mediaupload')
else:
return perform_requests('read', nodes, element, configmanager, inputdata)