diff options
Diffstat (limited to 'cxmanage/commands/fw.py')
-rw-r--r-- | cxmanage/commands/fw.py | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/cxmanage/commands/fw.py b/cxmanage/commands/fw.py new file mode 100644 index 0000000..87f810b --- /dev/null +++ b/cxmanage/commands/fw.py @@ -0,0 +1,164 @@ +# Copyright (c) 2012, Calxeda Inc. +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Calxeda Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +# DAMAGE. + +from pkg_resources import parse_version + +from cxmanage import get_tftp, get_nodes, get_node_strings, run_command, \ + prompt_yes + +from cxmanage_api.image import Image +from cxmanage_api.firmware_package import FirmwarePackage + + +def fwupdate_command(args): + """update firmware on a cluster or host""" + def do_update(): + """ Do a single firmware check+update. Returns True on failure. """ + if not args.force: + if not args.quiet: + print "Checking hosts..." + + results, errors = run_command(args, nodes, "_check_firmware", + package, args.partition, args.priority) + if errors: + print "ERROR: Firmware update aborted." + return True + + if not args.quiet: + print "Updating firmware..." + + results, errors = run_command(args, nodes, "update_firmware", package, + args.partition, args.priority) + if errors: + print "ERROR: Firmware update failed." + return True + + return False + + def do_reset(): + """ Reset and wait. Returns True on failure. """ + if not args.quiet: + print "Checking ECME versions..." + + results, errors = run_command(args, nodes, "get_versions") + if errors: + print "ERROR: MC reset aborted. Backup partitions not updated." + return True + + for result in results.values(): + version = result.ecme_version.lstrip("v") + if parse_version(version) < parse_version("1.2.0"): + print "ERROR: MC reset is unsafe on ECME version v%s" % version + print "Please power cycle the system and start a new fwupdate." + return True + + if not args.quiet: + print "Resetting nodes..." + + results, errors = run_command(args, nodes, "mc_reset", True) + if errors: + print "ERROR: MC reset failed. Backup partitions not updated." + return True + + return False + + if args.image_type == "PACKAGE": + package = FirmwarePackage(args.filename) + else: + try: + simg = None + if args.force_simg: + simg = False + elif args.skip_simg: + simg = True + + image = Image(args.filename, args.image_type, simg, args.daddr, + args.skip_crc32, args.fw_version) + package = FirmwarePackage() + package.images.append(image) + except ValueError as e: + print "ERROR: %s" % e + return True + + if not args.all_nodes: + if args.force: + print 'WARNING: Updating firmware without --all-nodes is dangerous.' + else: + if not prompt_yes( + 'WARNING: Updating firmware without --all-nodes is dangerous. Continue?'): + return 1 + + tftp = get_tftp(args) + nodes = get_nodes(args, tftp, verify_prompt=True) + + errors = do_update() + + if args.full and not errors: + errors = do_reset() + if not errors: + errors = do_update() + + if not args.quiet and not errors: + print "Command completed successfully.\n" + + return errors + + +def fwinfo_command(args): + """print firmware info""" + tftp = get_tftp(args) + nodes = get_nodes(args, tftp) + + if not args.quiet: + print "Getting firmware info..." + + results, errors = run_command(args, nodes, "get_firmware_info") + + node_strings = get_node_strings(args, results, justify=False) + for node in nodes: + if node in results: + print "[ Firmware info for %s ]" % node_strings[node] + + for partition in results[node]: + print "Partition : %s" % partition.partition + print "Type : %s" % partition.type + print "Offset : %s" % partition.offset + print "Size : %s" % partition.size + print "Priority : %s" % partition.priority + print "Daddr : %s" % partition.daddr + print "Flags : %s" % partition.flags + print "Version : %s" % partition.version + print "In Use : %s" % partition.in_use + print + + if not args.quiet and errors: + print "Some errors occured during the command.\n" + + return len(errors) > 0 |