From a922de2ed69ec7b6d9ee6911e15da8a260c6b32e Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Tue, 18 Jul 2017 14:17:39 -0400 Subject: [PATCH 1/4] Have nodeboot continue on non-failed nodes If even one of a noderange failed to complete the set boot device step, none would progress. Change the behavior so that exit code still happens and processing does stop on timed out nodes, but go ahead and reboot those that were fine. --- confluent_client/bin/nodeboot | 12 ++++++------ confluent_client/confluent/client.py | 10 ++++++---- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/confluent_client/bin/nodeboot b/confluent_client/bin/nodeboot index ee1f4eba..6edd7bf9 100755 --- a/confluent_client/bin/nodeboot +++ b/confluent_client/bin/nodeboot @@ -61,11 +61,11 @@ if options.biosmode: else: bootmode = 'uefi' +errnodes = set([]) rc = session.simple_noderange_command(noderange, '/boot/nextdevice', bootdev, bootmode=bootmode, - persistent=options.persist) - -if rc: - sys.exit(rc) -else: - sys.exit(session.simple_noderange_command(noderange, '/power/state', 'boot')) \ No newline at end of file + persistent=options.persist, + errnodes=errnodes) +noderange = noderange + ',-(' + ','.join(errnodes) + ')' +rc |= session.simple_noderange_command(noderange, '/power/state', 'boot') +sys.exit(rc) diff --git a/confluent_client/confluent/client.py b/confluent_client/confluent/client.py index 1936ab89..f9283dd0 100644 --- a/confluent_client/confluent/client.py +++ b/confluent_client/confluent/client.py @@ -77,7 +77,7 @@ class Command(object): def add_precede_key(self, keyname): self._prevkeyname = keyname - def handle_results(self, ikey, rc, res): + def handle_results(self, ikey, rc, res, errnodes=None): if 'error' in res: sys.stderr.write('Error: {0}\n'.format(res['error'])) if 'errorcode' in res: @@ -89,6 +89,8 @@ class Command(object): res = res['databynode'] for node in res: if 'error' in res[node]: + if errnodes is not None: + errnodes.add(node) sys.stderr.write('{0}: Error: {1}\n'.format( node, res[node]['error'])) if 'errorcode' in res[node]: @@ -110,7 +112,7 @@ class Command(object): return rc def simple_noderange_command(self, noderange, resource, input=None, - key=None, **kwargs): + key=None, errnodes=None, **kwargs): try: rc = 0 if resource[0] == '/': @@ -123,12 +125,12 @@ class Command(object): if input is None: for res in self.read('/noderange/{0}/{1}'.format( noderange, resource)): - rc = self.handle_results(ikey, rc, res) + rc = self.handle_results(ikey, rc, res, errnodes) else: kwargs[ikey] = input for res in self.update('/noderange/{0}/{1}'.format( noderange, resource), kwargs): - rc = self.handle_results(ikey, rc, res) + rc = self.handle_results(ikey, rc, res, errnodes) return rc except KeyboardInterrupt: print('') From 2795dfe7b9c36d7a5a6b9348be0fce32bb915065 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Tue, 18 Jul 2017 15:37:37 -0400 Subject: [PATCH 2/4] Only mod noderange if bad nodes detected This was triggering a defect in noderange. The defect should be fixed, but in the meantime, avoid tripping over it and looking weird anyway. --- confluent_client/bin/nodeboot | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/confluent_client/bin/nodeboot b/confluent_client/bin/nodeboot index 6edd7bf9..f8aa1adf 100755 --- a/confluent_client/bin/nodeboot +++ b/confluent_client/bin/nodeboot @@ -66,6 +66,7 @@ rc = session.simple_noderange_command(noderange, '/boot/nextdevice', bootdev, bootmode=bootmode, persistent=options.persist, errnodes=errnodes) -noderange = noderange + ',-(' + ','.join(errnodes) + ')' +if errnodes: + noderange = noderange + ',-(' + ','.join(errnodes) + ')' rc |= session.simple_noderange_command(noderange, '/power/state', 'boot') sys.exit(rc) From 60756d9b4127aeb2a78e871972f0f675e6e601ed Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Thu, 20 Jul 2017 10:12:53 -0400 Subject: [PATCH 3/4] Fix handling of numeric enclosure.bay enclosure.bay is integer rather than string now. Fix the filter to use format, which is more robust in numeric versus string anyway. Also, consistently make the underlying data integer rather than sometimes string. --- confluent_server/confluent/discovery/core.py | 2 +- confluent_server/confluent/discovery/handlers/xcc.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/confluent_server/confluent/discovery/core.py b/confluent_server/confluent/discovery/core.py index b2c6ff4f..e8fd1fa9 100644 --- a/confluent_server/confluent/discovery/core.py +++ b/confluent_server/confluent/discovery/core.py @@ -608,7 +608,7 @@ def eval_node(cfg, handler, info, nodename, manual=False): # search for nodes fitting our description using filters # lead with the most specific to have a small second pass nl = cfg.filter_node_attributes( - 'enclosure.bay=' + info['enclosure.bay'], nl) + 'enclosure.bay={0}'.format(info['enclosure.bay']), nl) nl = list(nl) if len(nl) != 1: info['discofailure'] = 'ambigconfig' diff --git a/confluent_server/confluent/discovery/handlers/xcc.py b/confluent_server/confluent/discovery/handlers/xcc.py index 1337f33a..de80b9f2 100644 --- a/confluent_server/confluent/discovery/handlers/xcc.py +++ b/confluent_server/confluent/discovery/handlers/xcc.py @@ -58,7 +58,7 @@ class NodeHandler(bmchandler.NodeHandler): '/v2/cmm/sp/7') if not bayid: return - self.info['enclosure.bay'] = bayid + self.info['enclosure.bay'] = int(bayid) smmid = ipmicmd._oem.immhandler.get_property( '/v2/ibmc/smm/chassis/uuid') if not smmid: From ba9ea1acd8f83104dca195a94f010ec226029fe7 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Thu, 20 Jul 2017 10:20:22 -0400 Subject: [PATCH 4/4] Treat empty string same as undefined If an administrator clears the cert fingerprint, they will likely set it to ''. In such a case, go down the 'no fingerprint' path rather than reject it. --- confluent_server/confluent/util.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/confluent_server/confluent/util.py b/confluent_server/confluent/util.py index 5e2d6e1e..3e41bd86 100644 --- a/confluent_server/confluent/util.py +++ b/confluent_server/confluent/util.py @@ -121,8 +121,9 @@ class TLSCertVerifier(object): fingerprint = get_fingerprint(certificate) storedprint = self.cfm.get_node_attributes(self.node, (self.fieldname,) ) - if self.fieldname not in storedprint[self.node]: # no stored value, check - # policy for next action + if (self.fieldname not in storedprint[self.node] or + storedprint[self.node][self.fieldname]['value'] == ''): + # no stored value, check policy for next action newpolicy = self.cfm.get_node_attributes(self.node, ('pubkeys.addpolicy',)) if ('pubkeys.addpolicy' in newpolicy[self.node] and