diff --git a/confluent_client/bin/nodeconfig b/confluent_client/bin/nodeconfig index e6f46e35..3ac1a66e 100755 --- a/confluent_client/bin/nodeconfig +++ b/confluent_client/bin/nodeconfig @@ -60,6 +60,10 @@ argparser.add_option('-a', '--advanced', dest='advanced', help='Include advanced settings, which are normally not ' 'intended to be used without direction from the ' 'relevant server vendor.') +argparser.add_option('-r', '--restoredefault', default=False, + action='store_true', + help='Restore the BIOS/UEFI configuration of the node ' + 'to factory default') (options, args) = argparser.parse_args() cfgpaths = { @@ -170,6 +174,11 @@ for param in args[1:]: queryparms[path][attrib] = param session = client.Command() rcode = 0 +if options.restoredefault: + for fr in session.update('/noderange/{0}/configuration/system/clear', + {'clear': True}): + rcode |= client.printerror(fr) + sys.exit(rcode) if setmode: if options.exclude: sys.stderr.write('Cannot use exclude and assign at the same time\n') diff --git a/confluent_client/doc/man/nodeconfig.ronn b/confluent_client/doc/man/nodeconfig.ronn index edabdfcb..aacd33b9 100644 --- a/confluent_client/doc/man/nodeconfig.ronn +++ b/confluent_client/doc/man/nodeconfig.ronn @@ -30,6 +30,11 @@ given as a node expression, as documented in the man page for nodeattribexpressi Provide detailed data as available. This can include help text and valid values for a setting. +* `-r`, `--restoredefault`: + Request that the specified nodes be restored to default BIOS/UEFI + configuration. This excludes BMC configuration which is not supported + to be cleared at this time. + ## EXAMPLES * Showing the current IP configuration of noderange BMC/IMM/XCC: diff --git a/confluent_server/confluent/core.py b/confluent_server/confluent/core.py index 0130c233..bb0fb72b 100644 --- a/confluent_server/confluent/core.py +++ b/confluent_server/confluent/core.py @@ -205,6 +205,10 @@ def _init_core(): 'pluginattrs': ['hardwaremanagement.method'], 'default': 'ipmi', }), + 'clear': PluginRoute({ + 'pluginattrs': ['hardwaremanagement.method'], + 'default': 'ipmi', + }) }, }, '_console': { diff --git a/confluent_server/confluent/messages.py b/confluent_server/confluent/messages.py index 84f82411..94aae1e9 100644 --- a/confluent_server/confluent/messages.py +++ b/confluent_server/confluent/messages.py @@ -416,6 +416,9 @@ def get_input_message(path, operation, inputdata, nodes=None, multinode=False, elif (path[:3] == ['configuration', 'system', 'all'] and operation != 'retrieve'): return InputConfigChangeSet(path, inputdata, nodes, configmanager) + elif (path[:3] == ['configuration', 'system', 'clear'] and + operation != 'retrieve'): + return InputConfigClear(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'): @@ -492,6 +495,13 @@ class InputExpression(ConfluentMessage): nodeattr = deepcopy(self.nodeattribs[node]) return nodeattr +class InputConfigClear(ConfluentMessage): + def __init__(self, path, inputdata, nodes=None): + if not inputdata: + raise exc.InvalidArgumentException('no request data provided') + if 'clear' not in inputdata or not inputdata['clear']: + raise exc.InvalidArgumentException('Input must be {"clear":true}') + class InputConfigChangeSet(InputExpression): # For now, this is identical to InputExpression, later it may # internalize formula expansion, but not now.. diff --git a/confluent_server/confluent/plugins/hardwaremanagement/ipmi.py b/confluent_server/confluent/plugins/hardwaremanagement/ipmi.py index a7cf3c13..05c77050 100644 --- a/confluent_server/confluent/plugins/hardwaremanagement/ipmi.py +++ b/confluent_server/confluent/plugins/hardwaremanagement/ipmi.py @@ -548,6 +548,8 @@ class IpmiHandler(object): return self.handle_sysconfig() elif self.element[1:3] == ['system', 'advanced']: return self.handle_sysconfig(True) + elif self.element[1:3] == ['system', 'clear']: + return self.handle_sysconfigclear() raise Exception('Not implemented') def decode_alert(self): @@ -1040,6 +1042,12 @@ class IpmiHandler(object): self.ipmicmd.set_domain_name(dn) return + def handle_sysconfigclear(self): + if 'read' == self.op: + raise exc.InvalidArgumentException( + 'Cannot read the "clear" resource') + self.ipmicmd.clear_system_configuration() + def handle_sysconfig(self, advanced=False): if 'read' == self.op: self.output.put(msg.ConfigSet(