diff options
author | George Kraft <george.kraft@calxeda.com> | 2012-07-06 12:01:49 -0500 |
---|---|---|
committer | George Kraft <george.kraft@calxeda.com> | 2012-07-06 12:01:49 -0500 |
commit | d401e7f69b15c936fb68ba02d9d9327f95158fd3 (patch) | |
tree | 4e6553290f462bd376ff07b99743d958cf5c9c9d | |
parent | b88de195766cdb45d84fa863ba789b89e6f4bc40 (diff) | |
download | cxmanage-d401e7f69b15c936fb68ba02d9d9327f95158fd3.tar.gz |
cxmanage: Changes to "boot config" command
Remove the --retry argument, and add it as a boot arg instead. I.E.
cxmanage config boot disk,pxe,retry 192.168.100.250
Added a "boot config status" command to read the current boot order
cxmanage config boot status 192.168.100.250
-rw-r--r-- | cxmanage/controller.py | 23 | ||||
-rw-r--r-- | cxmanage/indicator.py | 2 | ||||
-rw-r--r-- | cxmanage/target.py | 60 | ||||
-rw-r--r-- | cxmanage/ubootenv.py | 69 | ||||
-rwxr-xr-x | scripts/cxmanage | 10 |
5 files changed, 116 insertions, 48 deletions
diff --git a/cxmanage/controller.py b/cxmanage/controller.py index b668d33..09bc9aa 100644 --- a/cxmanage/controller.py +++ b/cxmanage/controller.py @@ -431,10 +431,10 @@ class Controller: return len(errors) > 0 - def config_boot(self, boot_args, retry=False): + def config_boot(self, boot_args): """ Send config boot command to all targets """ results, errors = self._run_command("config_boot", - self.work_dir, self.tftp, boot_args, retry) + self.work_dir, self.tftp, boot_args) # Print successful addresses if self.verbosity >= 1 and len(results) > 0: @@ -448,6 +448,25 @@ class Controller: return len(errors) > 0 + def config_boot_status(self): + """ Get boot order from all targets """ + results, errors = self._run_command("config_boot_status", + self.work_dir, self.tftp) + + # Print results + if len(results) > 0: + print "Boot order" + for target in self.targets: + if target.address in results: + print "%s: %s" % (target.address.ljust(16), + ",".join(results[target.address])) + print + + # Print errors + self._print_errors(errors) + + return len(errors) > 0 + def ipmitool_command(self, ipmitool_args): """ Run an arbitrary ipmitool command on all targets """ results, errors = self._run_command("ipmitool_command", ipmitool_args) diff --git a/cxmanage/indicator.py b/cxmanage/indicator.py index f17f197..2b98dc2 100644 --- a/cxmanage/indicator.py +++ b/cxmanage/indicator.py @@ -1,3 +1,5 @@ +#Copyright 2012 Calxeda, Inc. All Rights Reserved. + import sys import threading import time diff --git a/cxmanage/target.py b/cxmanage/target.py index bb3d28b..cbe378a 100644 --- a/cxmanage/target.py +++ b/cxmanage/target.py @@ -9,7 +9,6 @@ import time from cxmanage import CxmanageError from cxmanage.image import Image -from cxmanage.simg import get_simg_header from cxmanage.ubootenv import UbootEnv from pyipmi import make_bmc, IpmiError @@ -227,34 +226,24 @@ class Target: except IpmiError: raise CxmanageError("Failed to reset configuration") - def config_boot(self, work_dir, tftp, boot_args, retry=False): + def config_boot(self, work_dir, tftp, boot_args): """ Configure boot order """ - # Get tftp address - tftp_address = "%s:%s" % (tftp.get_address(self.address), - tftp.get_port()) - - # Download uboot environment - filename = tempfile.mkstemp(prefix="%s/env_" % work_dir)[1] - basename = os.path.basename(filename) fwinfo = self.get_firmware_info() slot = self._get_slot(fwinfo, "UBOOTENV", "ACTIVE") - handle = self.bmc.retrieve_firmware(basename, - int(slot.slot), "UBOOTENV", tftp_address).tftp_handle_id - self._wait_for_transfer(handle) - tftp.get_file(basename, filename) - simg = open(filename).read() - header = get_simg_header(simg) - ubootenv = UbootEnv(simg[28:]) + # Download, modify, and reupload ubootenv + ubootenv = self._get_ubootenv(work_dir, tftp, slot) + ubootenv.set_boot_order(boot_args) + self._update_ubootenv(work_dir, tftp, slot, ubootenv) - # Modify uboot environment - ubootenv.set_boot_order(boot_args, retry) + def config_boot_status(self, work_dir, tftp): + """ Get boot order """ + fwinfo = self.get_firmware_info() + slot = self._get_slot(fwinfo, "UBOOTENV", "ACTIVE") - # Upload the new uboot environment - open(filename, "w").write(str(ubootenv)) - image = Image(filename, "UBOOTENV", version=header.version, - daddr=header.daddr, skip_crc32=header.crc32==0) - self._update_image(work_dir, tftp, image, slot) + # Download and read boot order + ubootenv = self._get_ubootenv(work_dir, tftp, slot) + return ubootenv.get_boot_order() def ipmitool_command(self, ipmitool_args): """ Execute an arbitrary ipmitool command """ @@ -359,3 +348,28 @@ class Target: break if result.status != "Complete": raise CxmanageError("Node reported transfer failure") + + def _get_ubootenv(self, work_dir, tftp, slot): + """ Download a uboot environment from the target """ + tftp_address = "%s:%s" % (tftp.get_address(self.address), + tftp.get_port()) + + # Download the image + filename = tempfile.mkstemp(prefix="%s/env_" % work_dir)[1] + basename = os.path.basename(filename) + handle = self.bmc.retrieve_firmware(basename, + int(slot.slot), "UBOOTENV", tftp_address).tftp_handle_id + self._wait_for_transfer(handle) + tftp.get_file(basename, filename) + + # Open the file + simg = open(filename).read() + return UbootEnv(simg[28:]) + + def _update_ubootenv(self, work_dir, tftp, slot, ubootenv): + """ Upload a uboot environment to the target """ + filename = tempfile.mkstemp(prefix="%s/env_" % work_dir)[1] + open(filename, "w").write(ubootenv.get_contents()) + image = Image(filename, "UBOOTENV", version=int(slot.version, 16), + daddr=int(slot.daddr, 16)) + self._update_image(work_dir, tftp, image, slot) diff --git a/cxmanage/ubootenv.py b/cxmanage/ubootenv.py index e9db686..af39303 100644 --- a/cxmanage/ubootenv.py +++ b/cxmanage/ubootenv.py @@ -1,21 +1,25 @@ +#Copyright 2012 Calxeda, Inc. All Rights Reserved. + import struct -from crc32 import get_crc32 +from cxmanage import CxmanageError +from cxmanage.crc32 import get_crc32 ENVIRONMENT_SIZE = 8192 class UbootEnv: """ A uboot environment consisting of variables and their assignments. """ - def __init__(self, contents): + def __init__(self, contents=None): """ Load a uboot environment from a binary string """ self.variables = {} - contents = contents.rstrip("%c%c" % (chr(0), chr(255)))[4:] - lines = contents.split(chr(0)) - for line in lines: - part = line.partition("=") - self.variables[part[0]] = part[2] + if contents != None: + contents = contents.rstrip("%c%c" % (chr(0), chr(255)))[4:] + lines = contents.split(chr(0)) + for line in lines: + part = line.partition("=") + self.variables[part[0]] = part[2] def get_variable(self, variable): """ Get a variable from the uboot environment """ @@ -28,7 +32,7 @@ class UbootEnv: """ Set a variable in the uboot environment """ self.variables[variable] = value - def set_boot_order(self, boot_args, retry=False): + def set_boot_order(self, boot_args): """ Set the boot order specified in the uboot environment. Here are the valid boot arguments: @@ -37,28 +41,55 @@ class UbootEnv: disk: boot from default sata drive disk#: boot from numbered sata drive """ - command = ["run bootcmd_setup"] + commands = ["run bootcmd_setup"] + retry = False for arg in boot_args: if arg == "pxe": - command.append("run bootcmd_pxe") + commands.append("run bootcmd_pxe") elif arg == "disk": - command.append("run bootcmd_sata") + commands.append("run bootcmd_sata") elif arg.startswith("disk"): - command.append("setenv bootdevice %i" % int(args[4:])) - command.append("run bootcmd_sata") + commands.append("setenv bootdevice %i && run bootcmd_sata" + % int(arg[4:])) + elif arg == "retry": + retry = True else: raise ValueError("Invalid boot argument %s" % arg) if retry: - # Set the "retry" variable - retry_command = ["sleep 1", command[-1], "run bootcmd_retry"] - self.set_variable("bootcmd_retry", "; ".join(retry_command)) + commands[-1] = "while true\ndo\n%s\nsleep 1\ndone" % commands[-1] + + self.set_variable("bootcmd0", "; ".join(commands)) + + def get_boot_order(self): + """ Get the boot order specified in the uboot environment. """ + + commands = self.get_variable("bootcmd0").split("; ") + boot_args = [] + + retry = False + for command in commands: + if command.startswith("while true"): + retry = True + command = command.split("\n")[2] + + if command == "run bootcmd_setup": + pass + elif command == "run bootcmd_pxe": + boot_args.append("pxe") + elif command == "run bootcmd_sata": + boot_args.append("disk") + elif command.startswith("setenv bootdevice"): + boot_args.append("disk%i" % int(command.split()[2])) + else: + raise CxmanageError("Unrecognized boot command: %s" % command) - command.append("run bootcmd_retry") + if retry: + boot_args.append("retry") - self.set_variable("bootcmd0", "; ".join(command)) + return boot_args - def __str__(self): + def get_contents(self): """ Return a raw string representation of the uboot environment """ contents = "" diff --git a/scripts/cxmanage b/scripts/cxmanage index c6ab827..9d2115f 100755 --- a/scripts/cxmanage +++ b/scripts/cxmanage @@ -157,9 +157,7 @@ def build_parser(): p['boot'] = p['config_subs'].add_parser('boot', help='set A9 boot order') - p['boot'].add_argument('boot_order', help='boot order to use') - p['boot'].add_argument('-r', '--retry', action="store_true", - help='set A9 to retry last boot device on failure') + p['boot'].add_argument('boot_args', help='boot order to use') p['boot'].set_defaults(func=config_boot_command) #ipmitool command @@ -333,8 +331,12 @@ def config_reset_command(controller, args): def config_boot_command(controller, args): """set A9 boot order""" - if controller.config_boot(args.boot_order.split(","), args.retry): + if args.boot_args == "status": + if controller.config_boot_status(): + return 1 + elif controller.config_boot(args.boot_args.split(",")): return 1 + return 0 |