summaryrefslogtreecommitdiff
path: root/cxmanage/commands/fw.py
diff options
context:
space:
mode:
Diffstat (limited to 'cxmanage/commands/fw.py')
-rw-r--r--cxmanage/commands/fw.py164
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