From f88e0bca4cba293ba17c1163e3ee338cf56f6e7e Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Mon, 19 Mar 2018 08:45:13 -0400 Subject: [PATCH 1/7] Fix nodeshell hang on incomplete lines readline would hang because the filehandle was really not ready. --- confluent_client/bin/nodeshell | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/confluent_client/bin/nodeshell b/confluent_client/bin/nodeshell index 6db57f6a..d090e0ba 100755 --- a/confluent_client/bin/nodeshell +++ b/confluent_client/bin/nodeshell @@ -86,7 +86,7 @@ def run(): desc = pipedesc[r] node = desc['node'] data = True - while data and select.select([r], [], [], 0): + while data and select.select([r], [], [], 0)[0]: data = r.readline() if data: if desc['type'] == 'stdout': From 6671b9aad3c7fe4c0fde8891e0b63d11275696f2 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Fri, 23 Mar 2018 08:27:27 -0400 Subject: [PATCH 2/7] Provide cleaner behavior on timeouts If a timeout occurred outside of a keeplaive, provide a more consistent message about the situation. --- confluent_server/confluent/discovery/protocols/ssdp.py | 2 -- confluent_server/confluent/plugins/hardwaremanagement/ipmi.py | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/confluent_server/confluent/discovery/protocols/ssdp.py b/confluent_server/confluent/discovery/protocols/ssdp.py index de543697..2b03f28a 100644 --- a/confluent_server/confluent/discovery/protocols/ssdp.py +++ b/confluent_server/confluent/discovery/protocols/ssdp.py @@ -191,7 +191,6 @@ def _parse_ssdp(peer, rsp, peerdata): _, code, _ = headlines[0].split(' ', 2) except ValueError: return - myurl = None if code == '200': if nid in peerdata: peerdatum = peerdata[nid] @@ -208,7 +207,6 @@ def _parse_ssdp(peer, rsp, peerdata): header = header.strip() value = value.strip() if header == 'AL' or header == 'LOCATION': - myurl = value if 'urls' not in peerdatum: peerdatum['urls'] = [value] elif value not in peerdatum['urls']: diff --git a/confluent_server/confluent/plugins/hardwaremanagement/ipmi.py b/confluent_server/confluent/plugins/hardwaremanagement/ipmi.py index eff94678..e3daa375 100644 --- a/confluent_server/confluent/plugins/hardwaremanagement/ipmi.py +++ b/confluent_server/confluent/plugins/hardwaremanagement/ipmi.py @@ -344,7 +344,7 @@ def perform_request(operator, node, element, cfg, results).handle_request() except pygexc.IpmiException as ipmiexc: excmsg = str(ipmiexc) - if excmsg == 'Session no longer connected': + if excmsg in ('Session no longer connected', 'timeout'): results.put(msg.ConfluentTargetTimeout(node)) else: results.put(msg.ConfluentNodeError(node, excmsg)) From f97c39cea4845a59c3ff7ccc007eeb7f1ef80f1f Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Tue, 27 Mar 2018 15:51:14 -0400 Subject: [PATCH 3/7] Add hostname to api The hostname of the BMC is added to the api. --- confluent_server/confluent/core.py | 4 +++ confluent_server/confluent/messages.py | 35 ++++++++++++++++++- .../plugins/hardwaremanagement/ipmi.py | 12 +++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/confluent_server/confluent/core.py b/confluent_server/confluent/core.py index 88db962d..2cd5e11f 100644 --- a/confluent_server/confluent/core.py +++ b/confluent_server/confluent/core.py @@ -154,6 +154,10 @@ def _init_core(): 'pluginattrs': ['hardwaremanagement.method'], 'default': 'ipmi', }), + 'hostname': PluginRoute({ + 'pluginattrs': ['hardwaremanagement.method'], + 'default': 'ipmi', + }), 'identifier': PluginRoute({ 'pluginattrs': ['hardwaremanagement.method'], 'default': 'ipmi', diff --git a/confluent_server/confluent/messages.py b/confluent_server/confluent/messages.py index 13331f11..e9694b17 100644 --- a/confluent_server/confluent/messages.py +++ b/confluent_server/confluent/messages.py @@ -394,9 +394,12 @@ def get_input_message(path, operation, inputdata, nodes=None, multinode=False, elif (path[:3] == ['configuration', 'management_controller', 'reset'] and operation != 'retrieve'): return InputBMCReset(path, nodes, inputdata) - elif (path[:3] == ['configuration', 'management_controller', 'identifier'] + elif (path[:2] == ['configuration', 'management_controller', 'identifier'] and operation != 'retrieve'): return InputMCI(path, nodes, inputdata) + elif (path[:2] == ['configuration', 'management_controller', 'hostname'] + and operation != 'retrieve'): + return InputHostname(path, nodes, inputdata, configmanager) elif (path[:4] == ['configuration', 'management_controller', 'net_interfaces', 'management'] and operation != 'retrieve'): return InputNetworkConfiguration(path, nodes, inputdata, @@ -719,6 +722,25 @@ class InputBMCReset(ConfluentInputMessage): return self.inputbynode[node] + +class InputHostname(ConfluentInputMessage): + def __init__(self, path, nodes, inputdata, configmanager): + self.inputbynode = {} + self.stripped = False + if not inputdata or 'hostname' not in inputdata: + raise exc.InvalidArgumentException('missing hostname attribute') + if nodes is None: + raise exc.InvalidArgumentException( + 'This only supports per-node input') + for expanded in configmanager.expand_attrib_expression( + nodes, inputdata['hostname']): + node, value = expanded + self.inputbynode[node] = value + + def hostname(self, node): + return self.inputbynode[node] + + class InputMCI(ConfluentInputMessage): def __init__(self, path, nodes, inputdata): self.inputbynode = {} @@ -1298,6 +1320,17 @@ class MCI(ConfluentMessage): self.kvpairs = {name: kv} +class Hostname(ConfluentMessage): + def __init__(self, name=None, hostname=None): + self.notnode = name is None + self.desc = 'BMC hostname' + + kv = {'hostname': {'value': hostname}} + if self.notnode: + self.kvpairs = kv + else: + self.kvpairs = {name: kv} + class DomainName(ConfluentMessage): def __init__(self, name=None, dn=None): self.notnode = name is None diff --git a/confluent_server/confluent/plugins/hardwaremanagement/ipmi.py b/confluent_server/confluent/plugins/hardwaremanagement/ipmi.py index eff94678..b42c01d9 100644 --- a/confluent_server/confluent/plugins/hardwaremanagement/ipmi.py +++ b/confluent_server/confluent/plugins/hardwaremanagement/ipmi.py @@ -518,6 +518,8 @@ class IpmiHandler(object): return self.handle_reset() elif self.element[1:3] == ['management_controller', 'identifier']: return self.handle_identifier() + elif self.element[1:3] == ['management_controller', 'hostname']: + return self.handle_hostname() elif self.element[1:3] == ['management_controller', 'domain_name']: return self.handle_domain_name() elif self.element[1:3] == ['management_controller', 'ntp']: @@ -986,6 +988,16 @@ class IpmiHandler(object): self.ipmicmd.set_mci(mci) return + def handle_hostname(self): + if 'read' == self.op: + hostname = self.ipmicmd.get_hostname() + self.output.put(msg.Hostname(self.node, hostname)) + return + elif 'update' == self.op: + hostname = self.inputdata.hostname(self.node) + self.ipmicmd.set_hostname(hostname) + return + def handle_domain_name(self): if 'read' == self.op: dn = self.ipmicmd.get_domain_name() From 3dd86c71fd0a283eae3767c219be6c2b4c943c13 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Tue, 27 Mar 2018 16:32:37 -0400 Subject: [PATCH 4/7] Add bmc.hostname to nodeconfig --- confluent_client/bin/nodeconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/confluent_client/bin/nodeconfig b/confluent_client/bin/nodeconfig index 6055e315..78f46680 100755 --- a/confluent_client/bin/nodeconfig +++ b/confluent_client/bin/nodeconfig @@ -67,6 +67,8 @@ cfgpaths = { 'bmc.ipv4_gateway': ( 'configuration/management_controller/net_interfaces/management', 'ipv4_gateway'), + 'bmc.hostname': ( + 'configuration/management_controller/hostname', 'hostname'), } autodeps = { From bd40f2f4a6f452a0bee7f5f916cf7d414384c411 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Tue, 27 Mar 2018 17:11:35 -0400 Subject: [PATCH 5/7] Fix mistake in indexing of url --- confluent_server/confluent/messages.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/confluent_server/confluent/messages.py b/confluent_server/confluent/messages.py index e9694b17..fb40ad79 100644 --- a/confluent_server/confluent/messages.py +++ b/confluent_server/confluent/messages.py @@ -394,10 +394,10 @@ def get_input_message(path, operation, inputdata, nodes=None, multinode=False, elif (path[:3] == ['configuration', 'management_controller', 'reset'] and operation != 'retrieve'): return InputBMCReset(path, nodes, inputdata) - elif (path[:2] == ['configuration', 'management_controller', 'identifier'] + elif (path[:3] == ['configuration', 'management_controller', 'identifier'] and operation != 'retrieve'): return InputMCI(path, nodes, inputdata) - elif (path[:2] == ['configuration', 'management_controller', 'hostname'] + elif (path[:3] == ['configuration', 'management_controller', 'hostname'] and operation != 'retrieve'): return InputHostname(path, nodes, inputdata, configmanager) elif (path[:4] == ['configuration', 'management_controller', From 5ca52ff03ba38784e010b98a2ff47407c4cec3b1 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Mon, 9 Apr 2018 10:48:06 -0400 Subject: [PATCH 6/7] Handle interruptions to select such as resize Resize can cause an interrupted operation on stdin, handle that. --- confluent_client/bin/confetty | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/confluent_client/bin/confetty b/confluent_client/bin/confetty index 02690e68..86ef1aea 100755 --- a/confluent_client/bin/confetty +++ b/confluent_client/bin/confetty @@ -763,7 +763,10 @@ def conserver_command(filehandle, localcommand): def get_command_bytes(filehandle, localcommand, cmdlen): while len(localcommand) < cmdlen: - ready, _, _ = select.select((filehandle,), (), (), 1) + try: + ready, _, _ = select.select((filehandle,), (), (), 1) + except select.error: + ready = () if ready: localcommand += filehandle.read() return localcommand @@ -776,7 +779,10 @@ def check_escape_seq(currinput, filehandle): sys.stdout.flush() return conserver_command( filehandle, currinput[len(conserversequence):]) - ready, _, _ = select.select((filehandle,), (), (), 3) + try: + ready, _, _ = select.select((filehandle,), (), (), 3) + except select.error: + ready = () if not ready: # 3 seconds of no typing break currinput += filehandle.read() @@ -866,8 +872,11 @@ def check_power_state(): while inconsole or not doexit: if inconsole: - rdylist, _, _ = select.select( - (sys.stdin, session.connection), (), (), 10) + try: + rdylist, _, _ = select.select( + (sys.stdin, session.connection), (), (), 10) + except select.error: + rdylist = () for fh in rdylist: if fh == session.connection: # this only should get called in the From 76a4a913519476d775d7796fde6f7cc746922fc0 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Tue, 10 Apr 2018 15:11:20 -0400 Subject: [PATCH 7/7] Fix pyparsing rpm name Accept another likely formulation of an rpm name for the package. --- confluent_server/confluent_server.spec.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/confluent_server/confluent_server.spec.tmpl b/confluent_server/confluent_server.spec.tmpl index 55e307cc..e93922d7 100644 --- a/confluent_server/confluent_server.spec.tmpl +++ b/confluent_server/confluent_server.spec.tmpl @@ -12,7 +12,7 @@ Group: Development/Libraries BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot Prefix: %{_prefix} BuildArch: noarch -Requires: python-pyghmi >= 1.0.34, python-eventlet, python-greenlet, python-crypto >= 2.6.1, confluent_client, pyparsing, python-paramiko, python-dns, python-netifaces, python2-pyasn1 >= 0.2.3, python-pysnmp >= 4.3.4, python-pyte, python-lxml, python-eficompressor +Requires: python-pyghmi >= 1.0.34, python-eventlet, python-greenlet, python-crypto >= 2.6.1, confluent_client, python-pyparsing, python-paramiko, python-dns, python-netifaces, python2-pyasn1 >= 0.2.3, python-pysnmp >= 4.3.4, python-pyte, python-lxml, python-eficompressor Vendor: Jarrod Johnson Url: http://xcat.sf.net/