summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Kraft <george.kraft@calxeda.com>2012-07-06 12:01:49 -0500
committerGeorge Kraft <george.kraft@calxeda.com>2012-07-06 12:01:49 -0500
commitd401e7f69b15c936fb68ba02d9d9327f95158fd3 (patch)
tree4e6553290f462bd376ff07b99743d958cf5c9c9d
parentb88de195766cdb45d84fa863ba789b89e6f4bc40 (diff)
downloadcxmanage-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.py23
-rw-r--r--cxmanage/indicator.py2
-rw-r--r--cxmanage/target.py60
-rw-r--r--cxmanage/ubootenv.py69
-rwxr-xr-xscripts/cxmanage10
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