From 685f5c6803ecd1ad0932169deec442ce3a19ecd9 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Fri, 2 Feb 2018 16:20:13 -0500 Subject: [PATCH] Add system configuration This gives access to system configuration where available --- confluent_server/confluent/core.py | 8 +++++- confluent_server/confluent/messages.py | 28 ++++++++++++++++++- .../plugins/hardwaremanagement/ipmi.py | 11 ++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/confluent_server/confluent/core.py b/confluent_server/confluent/core.py index 58cfaa4a..88db962d 100644 --- a/confluent_server/confluent/core.py +++ b/confluent_server/confluent/core.py @@ -172,7 +172,13 @@ def _init_core(): 'default': 'ipmi', }), }, - } + }, + 'system': { + 'all': PluginRoute({ + 'pluginattrs': ['hardwaremanagement.method'], + 'default': 'ipmi', + }), + }, }, '_console': { 'session': PluginRoute({ diff --git a/confluent_server/confluent/messages.py b/confluent_server/confluent/messages.py index 81b3de9a..2f75c4e0 100644 --- a/confluent_server/confluent/messages.py +++ b/confluent_server/confluent/messages.py @@ -410,6 +410,9 @@ 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 (path[:3] == ['configuration', 'system', 'all'] and + operation != 'retrieve'): + return InputConfigChangeSet(path, inputdata, nodes, configmanager) elif 'inventory/firmware/updates/active' in '/'.join(path) and inputdata: return InputFirmwareUpdate(path, nodes, inputdata) elif '/'.join(path).startswith('media/detach'): @@ -484,6 +487,27 @@ class InputExpression(ConfluentMessage): nodeattr = deepcopy(self.nodeattribs[node]) return nodeattr +class InputConfigChangeSet(InputExpression): + # For now, this is identical to InputExpression, later it may + # internalize formula expansion, but not now.. + def __init__(self, path, inputdata, nodes=None, configmanager=None): + self.cfm = configmanager + super(InputConfigChangeSet, self).__init__(path, inputdata, nodes) + + def get_attributes(self, node): + attrs = super(InputConfigChangeSet, self).get_attributes(node) + endattrs = {} + for attr in attrs: + origval = attrs[attr] + if isinstance(origval, str) or isinstance(origval, unicode): + origval = {'expression': origval} + if 'expression' not in origval: + endattrs[attr] = attrs[attr] + else: + endattrs[attr] = list(self.cfm.expand_attrib_expression( + [node], attrs[attr]))[0][1] + return endattrs + class InputAttributes(ConfluentMessage): # This is particularly designed for attributes, where a simple string @@ -491,7 +515,7 @@ class InputAttributes(ConfluentMessage): # preserve the client provided expression for posterity, rather than # immediate consumption. # for things like node configuration or similar, a different class is - # appropriate since it nedes to immediately expand an expression. + # appropriate since it needs to immediately expand an expression. # with that class, the 'InputExpression' and calling code in attributes.py # might be deprecated in favor of the generic expression expander # and a small function in attributes.py to reflect the expansion back @@ -1249,6 +1273,8 @@ class Attributes(ConfluentMessage): name: nkv } +class ConfigSet(Attributes): + pass class ListAttributes(ConfluentMessage): def __init__(self, name=None, kv=None, desc=''): diff --git a/confluent_server/confluent/plugins/hardwaremanagement/ipmi.py b/confluent_server/confluent/plugins/hardwaremanagement/ipmi.py index 34bc58be..0a073982 100644 --- a/confluent_server/confluent/plugins/hardwaremanagement/ipmi.py +++ b/confluent_server/confluent/plugins/hardwaremanagement/ipmi.py @@ -359,6 +359,7 @@ def perform_request(operator, node, element, results.put(msg.ConfluentNodeError(node, str(e))) except Exception as e: results.put(e) + raise finally: results.put('Done') @@ -513,6 +514,8 @@ class IpmiHandler(object): return self.handle_domain_name() elif self.element[1:3] == ['management_controller', 'ntp']: return self.handle_ntp() + elif self.element[1:3] == ['system', 'all']: + return self.handle_sysconfig() raise Exception('Not implemented') def decode_alert(self): @@ -973,6 +976,14 @@ class IpmiHandler(object): self.ipmicmd.set_domain_name(dn) return + def handle_sysconfig(self): + if 'read' == self.op: + self.output.put(msg.ConfigSet( + self.node, self.ipmicmd.get_system_configuration())) + elif 'update' == self.op: + self.ipmicmd.set_system_configuration( + self.inputdata.get_attributes(self.node)) + def handle_ntp(self): if self.element[3] == 'enabled': if 'read' == self.op: