From 349dcfe06e23cde7cf0836c812422fe91d16edef Mon Sep 17 00:00:00 2001 From: George Kraft Date: Wed, 22 Aug 2012 14:11:57 -0500 Subject: When using --all-nodes, obtain IP addresses in parallel. Getting IP addresses from the fabric can be slow since it has to wait for a TFTP transfer. It's generally not noticable with just a single host, but for multiple fabrics, it can take a while. Getting addresses in parallel should speed things up a bit. --- cxmanage/controller.py | 76 ++++++++++++++++++++++++++++------------ cxmanage_test/controller_test.py | 4 +-- scripts/cxmanage | 32 +++++++++-------- 3 files changed, 73 insertions(+), 39 deletions(-) diff --git a/cxmanage/controller.py b/cxmanage/controller.py index b47ab0b..c0c054e 100644 --- a/cxmanage/controller.py +++ b/cxmanage/controller.py @@ -175,20 +175,32 @@ class Controller: ########################### Targets-specific methods ######################### - - def add_target(self, address, username, password, all_nodes=False): - """ Add the target to the list of targets for the group. """ - # Do nothing if the target is already present + def add_target(self, address, username, password): + """ Add a target to the controller """ for target in self.targets: if target.address == address: return target = self.target_class(address, username, password, self.verbosity) - if all_nodes: - for entry in target.get_ipinfo(self.tftp): - self.add_target(entry[1], username, password) - else: - self.targets.append(target) + self.targets.append(target) + + def add_fabrics(self, addresses, username, password): + """ Add all targets reported by each fabric """ + targets = [self.target_class(x, username, password, self.verbosity) + for x in addresses] + + if self.verbosity >= 1: + print "Getting IP addresses..." + results, errors = self._run_command(targets, "get_ipinfo", self.tftp) + + for target in targets: + if target.address in results: + for ipinfo in results[target.address]: + self.add_target(ipinfo[1], username, password) + + self._print_errors(targets, errors) + + return len(errors) > 0 def get_addresses_in_range(self, start, end): """ Return a list of addresses in the given IP range """ @@ -229,6 +241,8 @@ class Controller: def power_status(self): """ Retrieve power status from all targets in group """ + if self.verbosity >= 1: + print "Getting power status..." results, errors = self._run_command(self.targets, "get_power") # Print results @@ -244,7 +258,7 @@ class Controller: print # Print errors - self._print_errors(errors) + self._print_errors(self.targets, errors) return len(errors) > 0 @@ -260,6 +274,8 @@ class Controller: def power_policy_status(self): """ Get power policy status for all targets """ + if self.verbosity >= 1: + print "Getting power policy status..." results, errors = self._run_command(self.targets, "get_power_policy") # Print results @@ -272,7 +288,7 @@ class Controller: print # Print errors - self._print_errors(errors) + self._print_errors(self.targets, errors) return len(errors) > 0 @@ -299,6 +315,8 @@ class Controller: def firmware_info(self): """ Print firmware info for all targets """ + if self.verbosity >= 1: + print "Getting firmware info..." results, errors = self._run_command(self.targets, "get_firmware_info") for target in self.targets: @@ -316,12 +334,14 @@ class Controller: print "In Use : %s" % partition.in_use print - self._print_errors(errors) + self._print_errors(self.targets, errors) return len(errors) > 0 def get_sensors(self, name=""): """ Get sensor readings from all targets """ + if self.verbosity >= 1: + print "Getting sensor readings..." results, errors = self._run_command(self.targets, "get_sensors", name) if len(results) > 0: @@ -372,12 +392,14 @@ class Controller: print - self._print_errors(errors) + self._print_errors(self.targets, errors) return len(errors) > 0 def get_ipinfo(self): """ Get IP info from all targets """ + if self.verbosity >= 1: + print "Getting IP info..." results, errors = self._run_command(self.targets, "get_ipinfo", self.tftp) @@ -391,12 +413,14 @@ class Controller: print "Node %i: %s" % entry print - self._print_errors(errors) + self._print_errors(self.targets, errors) return len(errors) > 0 def get_macaddrs(self): """ Get mac addresses from all targets """ + if self.verbosity >= 1: + print "Getting MAC addresses..." results, errors = self._run_command(self.targets, "get_macaddrs", self.tftp) @@ -411,7 +435,7 @@ class Controller: if target != self.targets[-1] or len(errors) > 0: print - self._print_errors(errors) + self._print_errors(self.targets, errors) return len(errors) > 0 @@ -445,6 +469,8 @@ class Controller: def config_boot_status(self): """ Get boot order from all targets """ + if self.verbosity >= 1: + print "Getting boot orders..." results, errors = self._run_command(self.targets, "get_boot_order", self.tftp) @@ -458,12 +484,14 @@ class Controller: print # Print errors - self._print_errors(errors) + self._print_errors(self.targets, errors) return len(errors) > 0 def info_basic(self): """ Get basic SoC info from all targets """ + if self.verbosity >= 1: + print "Getting SoC info..." results, errors = self._run_command(self.targets, "info_basic") # Print results @@ -480,12 +508,14 @@ class Controller: print # Print errors - self._print_errors(errors) + self._print_errors(self.targets, errors) return len(errors) > 0 def info_ubootenv(self): """ Print u-boot environment for all targets """ + if self.verbosity >= 1: + print "Getting u-boot environments..." results, errors = self._run_command(self.targets, "get_ubootenv", self.tftp) @@ -500,7 +530,7 @@ class Controller: print # Print errors - self._print_errors(errors) + self._print_errors(self.targets, errors) return len(errors) > 0 @@ -514,6 +544,8 @@ class Controller: def ipmitool_command(self, ipmitool_args): """ Run an arbitrary ipmitool command on all targets """ + if self.verbosity >= 1: + print "Running IPMItool command..." results, errors = self._run_command(self.targets, "ipmitool_command", ipmitool_args) @@ -526,7 +558,7 @@ class Controller: print # Print errors - self._print_errors(errors) + self._print_errors(self.targets, errors) return len(errors) > 0 @@ -546,7 +578,7 @@ class Controller: return False else: # Print errors - self._print_errors(errors) + self._print_errors(targets, errors) # Decide whether or not to retry if retries == None: @@ -624,11 +656,11 @@ class Controller: return results, errors - def _print_errors(self, errors): + def _print_errors(self, targets, errors): """ Print errors if they occured """ if len(errors) > 0: print "Command failed on these hosts" - for target in self.targets: + for target in targets: if target.address in errors: print "%s: %s" % (target.address.ljust(16), errors[target.address]) diff --git a/cxmanage_test/controller_test.py b/cxmanage_test/controller_test.py index 2a9296b..5235cdc 100644 --- a/cxmanage_test/controller_test.py +++ b/cxmanage_test/controller_test.py @@ -65,7 +65,7 @@ class ControllerTest(unittest.TestCase): """ Test adding targets with ipinfo """ # Add targets self.assertEqual(len(self.controller.targets), 0) - self.controller.add_target(ADDRESSES[0], "admin", "admin", True) + self.controller.add_fabrics([ADDRESSES[0]], "admin", "admin") # Examine targets self.assertEqual(len(ADDRESSES), len(self.controller.targets)) @@ -99,7 +99,7 @@ class ControllerCommandTest(unittest.TestCase): # Set up the controller and add targets self.controller = Controller(max_threads=32, image_class=DummyImage, target_class=DummyTarget) - self.controller.add_target(ADDRESSES[0], "admin", "admin", True) + self.controller.add_fabrics([ADDRESSES[0]], "admin", "admin") def test_power(self): """ Test power command """ diff --git a/scripts/cxmanage b/scripts/cxmanage index 409d922..b4fac67 100755 --- a/scripts/cxmanage +++ b/scripts/cxmanage @@ -38,7 +38,6 @@ import os import pkgutil import sys -from cxmanage import CxmanageError from cxmanage.controller import Controller # Load plugins @@ -300,11 +299,19 @@ def set_tftp(controller, args): controller.set_internal_tftp_server() -def add_targets(controller, args, hosts=None): - """add targets to controller addresses""" - if hosts == None: - hosts = args.hostname.split(',') +def add_targets(controller, args): + hosts = parse_hosts(controller, args.hostname.split(',')) + if args.all_nodes: + if controller.add_fabrics(hosts, args.user, args.password): + print "ERROR: Failed to get IP addresses. Aborting.\n" + sys.exit(1) + else: + for host in hosts: + controller.add_target(host, args.user, args.password) +def parse_hosts(controller, hosts): + """add targets to controller addresses""" + results = [] for entry in hosts: # Check if it's a hostfile if entry.startswith('hostfile='): @@ -314,7 +321,7 @@ def add_targets(controller, args, hosts=None): elements = line.partition('#')[0].split() for element in elements: hostfile_entries.extend(element.split(',')) - add_targets(controller, args, hostfile_entries) + hosts.extend(parse_hosts(controller, hostfile_entries)) except IOError: print 'ERROR: %s is not a valid hostfile entry' % entry sys.exit(1) @@ -322,17 +329,12 @@ def add_targets(controller, args, hosts=None): # Not a hostfile, is it an IP range? try: start, end = entry.split('-') - addresses = controller.get_addresses_in_range(start, end) - add_targets(controller, args, addresses) + hosts.extend(controller.get_addresses_in_range(start, end)) except ValueError: # Not a hostfile or IP range, add it as a regular host - try: - controller.add_target(entry, args.user, - args.password, args.all_nodes) - except CxmanageError: - print ("ERROR: Failed to retrieve IP info from %s\n" - % entry) - sys.exit(1) + results.append(entry) + + return results def power_command(controller, args): -- cgit v1.2.1