diff --git a/confluent_client/bin/confetty b/confluent_client/bin/confetty index fe65742f..4b34490f 100755 --- a/confluent_client/bin/confetty +++ b/confluent_client/bin/confetty @@ -542,7 +542,7 @@ def get_session_node(shellargs): return None -def conserver_command(filehandle, command): +def conserver_command(filehandle, localcommand): # x - conserver has that as 'show baud', I am inclined to replace that with # 'request exclusive' # b - conserver has that as 'broadcast message', I'm tempted to use that @@ -557,33 +557,121 @@ def conserver_command(filehandle, command): # d - down a console... never used this... # L - toggle logging # w - who is on console - while not command: - ready, _, _ = select.select((filehandle,), (), (), 1) - if ready: - command += filehandle.read() - if command[0] == '.': + + cmdlen = 1 + localcommand = get_command_bytes(filehandle, localcommand, cmdlen) + + if localcommand[0] == '.': print("disconnect]\r") quitconfetty(fullexit=consoleonly) - elif command[0] == 'o': + elif localcommand[0] == 'o': tlvdata.send(session.connection, {'operation': 'reopen', 'path': currconsole}) print('reopen]\r') - elif command[0] == 'b': + elif localcommand[0] == 'b': tlvdata.send(session.connection, {'operation': 'break', 'path': currconsole}) print("break sent]\r") - elif command[0] == '?': + elif localcommand[0] == 'p': # print + cmdlen += 1 + localcommand = get_command_bytes(filehandle, localcommand, cmdlen) + + if localcommand[1] == 'o': # off + print("powering off...") + session.simple_noderange_command(consolename, '/power/state', 'off') + print("complete]\r") + elif localcommand[1] == 's': # shutdown + print("shutting down...") + session.simple_noderange_command(consolename, '/power/state', 'shutdown') + print("complete]\r") + elif localcommand[1] == 'b': # boot + cmdlen += 1 + localcommand = get_command_bytes(filehandle, localcommand, cmdlen) + + if localcommand[2] == 's': # boot to setup + print("booting to setup...") + + bootmode = 'uefi' + bootdev = 'setup' + + rc = session.simple_noderange_command(consolename, '/boot/nextdevice', bootdev, bootmode=bootmode) + + if rc: + print("Error]\r") + else: + rc = session.simple_noderange_command(consolename, '/power/state', 'boot') + if rc: + print("Error]\r") + else: + print("complete]\r") + + elif localcommand[2] == 'n': # boot to network + print("booting to network...") + + bootmode = 'uefi' + bootdev = 'network' + + rc = session.simple_noderange_command(consolename, '/boot/nextdevice', bootdev, bootmode=bootmode) + + if rc: + print("Error]\r") + else: + rc = session.simple_noderange_command(consolename, '/power/state', 'boot') + + if rc: + print("Error]\r") + else: + print("complete]\r") + + elif localcommand[2] == '\x0d': # boot to default + print("booting to default...") + + bootmode = 'uefi' + bootdev = 'default' + + rc = session.simple_noderange_command(consolename, '/boot/nextdevice', bootdev, bootmode=bootmode) + + if rc: + print("Error]\r") + else: + rc = session.simple_noderange_command(consolename, '/power/state', 'boot') + + if rc: + print("Error]\r") + else: + print("complete]\r") + + else: + print("Unknown boot state.]\r") + + else: + print("Unknown power state.]\r") + + elif localcommand[0] == '?': print("help]\r") - print(". disconnect\r") - print("b break\r") - print("o reopen\r") + print(". disconnect\r") + print("b break\r") + print("o reopen\r") + print("po power off\r") + print("ps shutdown\r") + print("pbs boot to setup\r") + print("pbn boot to network\r") + print("pb boot to default\r") print(" abort command\r") - elif command[0] == '\x0d': + elif localcommand[0] == '\x0d': print("ignored]\r") else: # not a command at all.. print("unknown -- use '?']\r") +def get_command_bytes(filehandle, localcommand, cmdlen): + while len(localcommand) < cmdlen: + ready, _, _ = select.select((filehandle,), (), (), 1) + if ready: + localcommand += filehandle.read() + return localcommand + + def check_escape_seq(currinput, filehandle): while conserversequence.startswith(currinput): if currinput.startswith(conserversequence): # We have full sequence diff --git a/confluent_client/bin/nodeboot b/confluent_client/bin/nodeboot new file mode 100755 index 00000000..9aa940a6 --- /dev/null +++ b/confluent_client/bin/nodeboot @@ -0,0 +1,66 @@ +#!/usr/bin/env python +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2015 Lenovo +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import optparse +import os +import sys + +path = os.path.dirname(os.path.realpath(__file__)) +path = os.path.realpath(os.path.join(path, '..', 'lib', 'python')) +if path.startswith('/opt'): + sys.path.append(path) + +import confluent.client as client + +argparser = optparse.OptionParser() +argparser.add_option('-b', '--bios', dest='biosmode', + action='store_true', default=False, + help='Request BIOS style boot (rather than UEFI)') +argparser.add_option('-p', '--persist', dest='persist', action='store_true', + default=False, + help='Request the boot device be persistent rather than ' + 'one time') + +(options, args) = argparser.parse_args() + +try: + noderange = args[0] +except IndexError: + sys.stderr.write( + 'Usage: {0} [default|cd|network|setup|hd]\n'.format( + sys.argv[0])) + sys.exit(1) +bootdev = None +if len(sys.argv) > 2: + bootdev = sys.argv[2] + if bootdev in ('net', 'pxe'): + bootdev = 'network' +session = client.Command() +exitcode = 0 +if options.biosmode: + bootmode = 'bios' +else: + bootmode = 'uefi' + +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 diff --git a/confluent_client/setup.py.tmpl b/confluent_client/setup.py.tmpl index 3fe14bc6..f8768bd5 100644 --- a/confluent_client/setup.py.tmpl +++ b/confluent_client/setup.py.tmpl @@ -1,4 +1,7 @@ from setuptools import setup +import os + +scriptlist = ['bin/{0}'.format(d) for d in os.listdir('bin/')] setup( name='confluent_client', @@ -7,9 +10,6 @@ setup( author_email='jjohnson2@lenovo.com', url='http://xcat.sf.net/', packages=['confluent'], - scripts=['bin/confetty', 'bin/nodeconsole', 'bin/nodeeventlog', - 'bin/nodefirmware', 'bin/nodehealth', 'bin/nodeidentify', - 'bin/nodeinventory', 'bin/nodelist', 'bin/nodepower', - 'bin/nodesensors', 'bin/nodesetboot', 'bin/noderun'], + scripts=scriptlist, data_files=[('/etc/profile.d', ['confluent_env.sh'])], ) diff --git a/confluent_server/confluent/config/configmanager.py b/confluent_server/confluent/config/configmanager.py index 8ce69753..e00d79e1 100644 --- a/confluent_server/confluent/config/configmanager.py +++ b/confluent_server/confluent/config/configmanager.py @@ -65,6 +65,7 @@ import anydbm as dbm import ast import base64 import confluent.config.attributes as allattributes +import confluent.config.conf as conf import confluent.log import confluent.util import confluent.exceptions as exc @@ -1357,7 +1358,7 @@ class ConfigManager(object): changeset) -def _restore_keys(jsond, password, newpassword): +def _restore_keys(jsond, password, newpassword=None): # the jsond from the restored file, password (if any) used to protect # the file, and newpassword to use, (also check the service.cfg file) global _masterkey @@ -1365,8 +1366,20 @@ def _restore_keys(jsond, password, newpassword): keydata = json.loads(jsond) cryptkey = _parse_key(keydata['cryptkey'], password) integritykey = _parse_key(keydata['integritykey'], password) + conf.init_config() + cfg = conf.get_config() + if cfg.has_option('security', 'externalcfgkey'): + keyfilename = cfg.get('security', 'externalcfgkey') + with open(keyfilename, 'r') as keyfile: + newpassword = keyfile.read() + set_global('master_privacy_key', _format_key(cryptkey, + password=newpassword)) + set_global('master_integrity_key', _format_key(integritykey, + password=newpassword)) _masterkey = cryptkey _masterintegritykey = integritykey + ConfigManager.wait_for_sync() + # At this point, we should have the key situation all sorted def _dump_keys(password):