2
0
mirror of https://github.com/xcat2/confluent.git synced 2024-11-29 13:00:03 +00:00

Phase 1 of firmware update support

Provide ability to launch firmware updates.
Next will be ability to enumerate, monitor, and
delete.
This commit is contained in:
Jarrod Johnson 2017-07-25 17:01:32 -04:00
parent 0bf21238aa
commit a40f015076
4 changed files with 97 additions and 2 deletions

View File

@ -233,6 +233,14 @@ def _init_core():
'pluginattrs': ['hardwaremanagement.method'],
'default': 'ipmi',
}),
'updates': {
'active': {
PluginCollection({
'pluginattrs': ['hardwaremanagement.method'],
'default': 'ipmi',
}),
},
},
},
},
'power': {

View File

@ -0,0 +1,62 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2017 Lenovo
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# provide managing firmware update process and firmware repository if/when
# the time comes
import confluent.messages as msg
import eventlet
updatesbytarget = {}
def execupdate(handler, filename, updateobj):
try:
handler(filename, progress=updateobj.handle_progress)
updateobj.handle_progress({'phase': 'complete', 'progress': 100.0})
except Exception as e:
updateobj.handle_progress({'phase': 'error', 'progress': 0.0,
'detail': repr(e)})
class Updater(object):
def __init__(self, node, handler, filename, tenant=None, name=None):
self.node = node
self.phase = 'initializing'
self.percent = 0.0
self.updateproc = eventlet.spawn(execupdate, handler, filename, self)
if (node, tenant) not in updatesbytarget:
updatesbytarget[(node, tenant)] = {}
if name is None:
name = 1
while name in updatesbytarget[(node, tenant)]:
name += 1
updatesbytarget[(node, tenant)][name] = self
def handle_progress(self, progress):
self.phase = progress['phase']
self.percent = float(progress['progress'])
self.detail = progress.get('detail', '')
@property
def progress(self):
return {'phase': self.phase, 'progress': self.percent,
'detail': self.detail}
def list_updates(nodes, tenant=None):
for node in nodes:
for updateid in updatesbytarget.get((node, None), {}):
yield msg.ChildCollection(updateid)

View File

@ -389,8 +389,17 @@ def get_input_message(path, operation, inputdata, nodes=None, multinode=False):
elif (path[:4] == ['configuration', 'management_controller', 'ntp',
'servers'] and operation != 'retrieve' and len(path) == 5):
return InputNTPServer(path, nodes, inputdata)
elif 'inventory/firmware/updates/active' in '/'.join(path) and inputdata:
return InputFirmwareUpdate(path, nodes, inputdata)
elif inputdata:
raise exc.InvalidArgumentException()
raise exc.InvalidArgumentException(
'No known input handler for request')
class InputFirmwareUpdate(ConfluentMessage):
def __init__(self, path, nodes, inputdata):
self.filename = inputdata['filename']
self.nodes = nodes
class InputAlertData(ConfluentMessage):

View File

@ -15,6 +15,7 @@
import atexit
import confluent.exceptions as exc
import confluent.firmwaremanager as firmwaremanager
import confluent.interface.console as conapi
import confluent.messages as msg
import confluent.util as util
@ -350,6 +351,7 @@ class IpmiHandler(object):
connparams = get_conn_params(node, self.cfg)
self.ipmicmd = None
self.inputdata = inputdata
self.tenant = cfg.tenant
tenant = cfg.tenant
if ((node, tenant) not in persistent_ipmicmds or
not persistent_ipmicmds[(node, tenant)].ipmi_session.logged):
@ -417,6 +419,8 @@ class IpmiHandler(object):
self.handle_sensors()
elif self.element[0] == 'configuration':
self.handle_configuration()
elif self.element[:3] == ['inventory', 'firmware', 'updates']:
self.handle_update()
elif self.element[0] == 'inventory':
self.handle_inventory()
elif self.element == ['events', 'hardware', 'log']:
@ -428,6 +432,11 @@ class IpmiHandler(object):
else:
raise Exception('Not Implemented')
def handle_update(self):
firmwaremanager.Updater(self.node, self.ipmicmd.update_firmware,
self.inputdata.filename, self.tenant)
def handle_configuration(self):
if self.element[1:3] == ['management_controller', 'alerts']:
return self.handle_alerts()
@ -961,9 +970,16 @@ def update(nodes, element, configmanager, inputdata):
return create(nodes, element, configmanager, inputdata)
def list_active_updates(nodes, configmanager):
raise Exception('Not Implemented')
def retrieve(nodes, element, configmanager, inputdata):
initthread()
return perform_requests('read', nodes, element, configmanager, inputdata)
if '/'.join(element).startswith('inventory/firmware/updates/active'):
return firmwaremanager.list_updates(nodes, configmanager.tenant)
else:
return perform_requests('read', nodes, element, configmanager, inputdata)
def delete(nodes, element, configmanager, inputdata):
initthread()