diff --git a/confluent_client/bin/nodeapply b/confluent_client/bin/nodeapply index 7547895f..6d619f57 100755 --- a/confluent_client/bin/nodeapply +++ b/confluent_client/bin/nodeapply @@ -37,6 +37,7 @@ import confluent.sortutil as sortutil devnull = None def run_automation(noderange, category, c): + exitcode = 0 automationbynode = {} for res in c.update('/noderange/{0}/deployment/remote_config/run'.format(noderange), { 'category': category, @@ -64,7 +65,8 @@ def run_automation(noderange, category, c): if res.get('complete', False): del automationbynode[node] sys.stdout.write('{0}: Automation complete\n'.format(node)) - + return exitcode + def run(): global devnull @@ -104,10 +106,13 @@ def run(): pipedesc = {} pendingexecs = deque() exitcode = 0 + # Kept apart from exitcode: a failed automation run must not trip the + # early exit below, which would abandon ssh children already spawned. + autoexitcode = 0 c.stop_if_noderange_over(args[0], options.maxnodes) if options.automation: - run_automation(args[0], options.automation, c) + autoexitcode = run_automation(args[0], options.automation, c) nodemap = {} cmdparms = [] @@ -124,7 +129,7 @@ def run(): cmdstorun.append(['run_remote', script]) if not cmdstorun: if options.automation: - sys.exit(0) + sys.exit(autoexitcode) argparser.print_help() sys.exit(1) for res in c.read('/noderange/{0}/nodes/'.format(args[0])): @@ -145,7 +150,7 @@ def run(): else: pendingexecs.append((sshnode, cmdv)) if not all or exitcode: - sys.exit(exitcode) + sys.exit(exitcode | autoexitcode) rdy = poller.poll(10) while all: pernodeout = {} @@ -193,7 +198,7 @@ def run(): sys.stdout.flush() if all: rdy = poller.poll(10) - sys.exit(exitcode) + sys.exit(exitcode | autoexitcode) def run_cmdv(node, cmdv, all, poller, pipedesc): diff --git a/confluent_client/bin/nodeconsole b/confluent_client/bin/nodeconsole index fe6decc9..800da71c 100755 --- a/confluent_client/bin/nodeconsole +++ b/confluent_client/bin/nodeconsole @@ -790,6 +790,7 @@ numrows = 0 cwidth = 0 cheight = 0 imagedatabynode = {} +firstnodename = None def redraw(): for node in imagedatabynode: @@ -818,6 +819,7 @@ async def do_screenshot(): global streaming global resized global numrows + global firstnodename sess = client.Command() if streaming: asyncio.create_task(watch_input()) diff --git a/confluent_client/bin/nodedeploy b/confluent_client/bin/nodedeploy index 47b607eb..e47f8d35 100755 --- a/confluent_client/bin/nodedeploy +++ b/confluent_client/bin/nodedeploy @@ -133,11 +133,6 @@ def main(args): curr = nodeinfo[attr].get('value', '') if curr and node not in profilebynode: profilebynode[node] = curr - for lockinfo in c.read('/noderange/{0}/deployment/lock'.format(args.noderange)): - for node in lockinfo.get('databynode', {}): - lockstate = lockinfo['databynode'][node]['lock']['value'] - if lockstate == 'locked': - lockednodes.append(node) if args.profile and profilebynode: sys.stderr.write('The -r/--redeploy option cannot be used with a profile, it redeploys the current or pending profile\n') return 1 diff --git a/confluent_client/samples/nodeattrib_from_switch.py b/confluent_client/samples/nodeattrib_from_switch.py index eff3e394..ba133846 100644 --- a/confluent_client/samples/nodeattrib_from_switch.py +++ b/confluent_client/samples/nodeattrib_from_switch.py @@ -13,6 +13,7 @@ import confluent.client as cl import socket import struct +import sys c = cl.Command() macs = [] interface = sys.argv[1] diff --git a/confluent_server/confluent/asynchttp.py b/confluent_server/confluent/asynchttp.py index 29c937d5..76458f8d 100644 --- a/confluent_server/confluent/asynchttp.py +++ b/confluent_server/confluent/asynchttp.py @@ -119,12 +119,12 @@ def handle_async(querydict, wshandler=None): # This may be one of two things, a request for a new async stream # or a request for next data from async stream # httpapi otherwise handles requests an injecting them to queue - if 'asyncid' not in querydict or not querydict['asyncid']: + if wshandler and ('asyncid' not in querydict or not querydict['asyncid']): # This is a new request, create a new multiplexer - currsess = AsyncSession(wshandler) - if wshandler: - yield currsess - return + yield AsyncSession(wshandler) + return + # Without a websocket handler there is nobody to hand a session to, so do + # not register one that would never be reaped. raise Exception("Long polling asynchttp is discontinued") diff --git a/confluent_server/confluent/discovery/handlers/xcc3.py b/confluent_server/confluent/discovery/handlers/xcc3.py index 0a1c7590..e2d57095 100644 --- a/confluent_server/confluent/discovery/handlers/xcc3.py +++ b/confluent_server/confluent/discovery/handlers/xcc3.py @@ -12,11 +12,27 @@ # See the License for the specific language governing permissions and # limitations under the License. +import codecs import confluent.discovery.handlers.redfishbmc as redfishbmc +import confluent.util as util import socket +import struct import aiohmi.util.webclient as webclient +# Duplicated from the xcc handler rather than imported: xcc imports this +# module, so importing it back would be circular. smm carries its own copy of +# this for the same reason. +def fixuuid(baduuid): + # SMM dumps it out in hex + uuidprefix = (baduuid[:8], baduuid[9:13], baduuid[14:18]) + a = codecs.encode(struct.pack('= (3,): - if isinstance(username, str): username = username.encode(encoding) - if isinstance(service, str): service = service.encode(encoding) - else: - if isinstance(username, unicode): - username = username.encode(encoding) - if isinstance(password, unicode): - password = password.encode(encoding) - if isinstance(service, unicode): - service = service.encode(encoding) + if isinstance(username, str): username = username.encode(encoding) + if isinstance(service, str): service = service.encode(encoding) if b'\x00' in username or b'\x00' in service: self.code = 4 # PAM_SYSTEM_ERR in Linux-PAM @@ -242,11 +234,7 @@ if __name__ == "__main__": readline.redisplay() readline.set_pre_input_hook(hook) - if sys.version_info >= (3,): - getinput = input - else: - getinput = raw_input - result = getinput(prompt) + result = input(prompt) readline.set_pre_input_hook() return result diff --git a/confluent_server/confluent/plugins/hardwaremanagement/cooltera.py b/confluent_server/confluent/plugins/hardwaremanagement/cooltera.py index 528d79c6..b5238577 100644 --- a/confluent_server/confluent/plugins/hardwaremanagement/cooltera.py +++ b/confluent_server/confluent/plugins/hardwaremanagement/cooltera.py @@ -151,12 +151,9 @@ _sensors_by_node = {} async def read_sensors(element, node, configmanager): category, name = element[-2:] if len(element) == 3: - # just get names + # the request is for the names under a category, so that is the last + # element rather than the one before it category = name - name = 'all' - for sensor in sensors: - yield msg.ChildCollection(simplify_name(sensors[sensor][0])) - return if category in ('leds, fans'): return sn = _sensors_by_node.get(node, None) @@ -166,6 +163,12 @@ async def read_sensors(element, node, configmanager): statinfo = xml2stateinfo(statdata) _sensors_by_node[node] = (statinfo, time.time() + 1) sn = _sensors_by_node.get(node, None) + if len(element) == 3: + # the names are only known after reading the device, as the sensor + # set depends on the model + for sensor in sn[0] if sn else (): + yield msg.ChildCollection(simplify_name(sensor['name'])) + return if sn: yield msg.SensorReadings(sn[0], name=node) diff --git a/confluent_server/confluent/plugins/hardwaremanagement/deltapdu.py b/confluent_server/confluent/plugins/hardwaremanagement/deltapdu.py index e3da3786..02df6406 100644 --- a/confluent_server/confluent/plugins/hardwaremanagement/deltapdu.py +++ b/confluent_server/confluent/plugins/hardwaremanagement/deltapdu.py @@ -195,7 +195,8 @@ async def retrieve(nodes, element, configmanager, inputdata): async def update(nodes, element, configmanager, inputdata): if 'outlets' not in element: - yield msg.ConfluentResourceUnavailable(node, 'Not implemented') + for node in nodes: + yield msg.ConfluentResourceUnavailable(node, 'Not implemented') return timeout = 4 for node in nodes: diff --git a/confluent_server/confluent/plugins/hardwaremanagement/eatonpdu.py b/confluent_server/confluent/plugins/hardwaremanagement/eatonpdu.py index f26bd0bd..f6c0a3ac 100644 --- a/confluent_server/confluent/plugins/hardwaremanagement/eatonpdu.py +++ b/confluent_server/confluent/plugins/hardwaremanagement/eatonpdu.py @@ -327,7 +327,8 @@ async def retrieve(nodes, element, configmanager, inputdata): async def update(nodes, element, configmanager, inputdata): if 'outlets' not in element: - yield msg.ConfluentResourceUnavailable(node, 'Not implemented') + for node in nodes: + yield msg.ConfluentResourceUnavailable(node, 'Not implemented') return for node in nodes: gc = PDUClient(node, configmanager) diff --git a/confluent_server/confluent/plugins/hardwaremanagement/geist.py b/confluent_server/confluent/plugins/hardwaremanagement/geist.py index 9a3e0a8e..cb7bea1e 100644 --- a/confluent_server/confluent/plugins/hardwaremanagement/geist.py +++ b/confluent_server/confluent/plugins/hardwaremanagement/geist.py @@ -336,7 +336,8 @@ async def retrieve(nodes, element, configmanager, inputdata): async def update(nodes, element, configmanager, inputdata): if 'outlets' not in element: - yield msg.ConfluentResourceUnavailable(node, 'Not implemented') + for node in nodes: + yield msg.ConfluentResourceUnavailable(node, 'Not implemented') return for node in nodes: gc = GeistClient(node, configmanager) diff --git a/confluent_server/confluentdbgcli.py b/confluent_server/confluentdbgcli.py index 6c804cc3..eb7d5f45 100644 --- a/confluent_server/confluentdbgcli.py +++ b/confluent_server/confluentdbgcli.py @@ -20,7 +20,7 @@ import readline import socket connection = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) -self.connection.connect('/var/run/confluent/dbg.sock') +connection.connect('/var/run/confluent/dbg.sock') readline.parse_and_bind("tab: complete") readline.parse_and_bind("set bell-style none") diff --git a/misc/filterpasswd b/misc/filterpasswd index 1d2785bd..11adc3a8 100644 --- a/misc/filterpasswd +++ b/misc/filterpasswd @@ -1,3 +1,5 @@ +import sys + uidmin = 1000 uidmax = 60000 gidmin = 1000