summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSheldon Sandbekkhaug <sheldon.sandbekkhaug@calxeda.com>2013-06-24 15:48:19 -0500
committerSheldon Sandbekkhaug <sheldon.sandbekkhaug@calxeda.com>2013-06-24 15:48:19 -0500
commit5015e71b3e19a051ecdf65421561c6fe0ff2f28e (patch)
treeabb18f377dc3619c1832f4708086da7a6c902644
parent5b3e94d50784235616ca2383592bea71d50a6239 (diff)
downloadcxmanage-5015e71b3e19a051ecdf65421561c6fe0ff2f28e.tar.gz
(CXMAN-194) Create a command to get all data
coredump.py/tspackage.py Changed coredump.py to tspackage.py ("troubleshoot package") Removed code to check for server IP Removed requirement to power on nodes Uses python's tempfile module instead of trying to manually find unused temporary filenames No longer calls ipmitool directly, only functions in node.py are used Removed function to get SDR (already had another function to get sensor information) Uses node.ip_address instead of custom function to get ip_addresses of nodes Removed function to delete files. Now uses python's shutil.rmtree() Archives files using python's tarfile module instead of using subprocess.call Archived filenames now contain the date and time they were created. Various minor changes scripts/cxmanage Reflects name change (coredump to tspackage) Removed unneeded arguments for tspackage node.py Added a function to get the SEL cxmanage/__init__.py Moved the components dictionary from cxmanage/commands/info.py to here, so other files can access it info.py Now references the components dictionary from __init__.py
-rw-r--r--cxmanage/__init__.py16
-rw-r--r--cxmanage/commands/coredump.py507
-rw-r--r--cxmanage/commands/info.py14
-rw-r--r--cxmanage/commands/tspackage.py376
-rw-r--r--cxmanage_api/node.py3
-rwxr-xr-xscripts/cxmanage21
6 files changed, 402 insertions, 535 deletions
diff --git a/cxmanage/__init__.py b/cxmanage/__init__.py
index 50b760a..cb9b81e 100644
--- a/cxmanage/__init__.py
+++ b/cxmanage/__init__.py
@@ -322,3 +322,19 @@ def _print_command_status(tasks, counter):
dots = "".join(["." for x in range(counter % 4)]).ljust(3)
sys.stdout.write(message % (successes, errors, nodes_left, dots))
sys.stdout.flush()
+
+
+def get_components():
+ """ Return the components list needed for ipinfo. """
+ components = [
+ ("ecme_version", "ECME version"),
+ ("cdb_version", "CDB version"),
+ ("stage2_version", "Stage2boot version"),
+ ("bootlog_version", "Bootlog version"),
+ ("a9boot_version", "A9boot version"),
+ ("uboot_version", "Uboot version"),
+ ("ubootenv_version", "Ubootenv version"),
+ ("dtb_version", "DTB version")
+ ]
+
+ return components
diff --git a/cxmanage/commands/coredump.py b/cxmanage/commands/coredump.py
deleted file mode 100644
index b18b9bc..0000000
--- a/cxmanage/commands/coredump.py
+++ /dev/null
@@ -1,507 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright 2013 Calxeda, Inc. All Rights Reserved.
-
-
-import os
-import subprocess
-
-from subprocess import call
-
-from cxmanage import get_tftp, get_nodes, run_command
-
-
-def coredump_command(args):
- """Get information pertaining to each node. This includes:
- IP addresses (ECME and server)
- Version info (like cxmanage info)
- MAC addresses
- Sensor readings
- Sensor data records
- Firmware info
- Boot order
- SELs (System Event Logs),
- Depth charts
- Routing Tables
-
- All nodes in the fabric should be powered on before running this command.
-
- This data will be written to a set of files. Each node will get its own
- file. All of these files will be archived and saved to the user's current
- directory.
-
- Internally, this command is called from:
- ~/virtual_testenv/workspace/cx_manage_util/scripts/cxmanage
- """
-
- tftp = get_tftp(args)
- nodes = get_nodes(args, tftp)
-
- temp_dir = "coredump"
-
- try:
- os.mkdir(temp_dir)
- except:
- """ Create a new directory with a unique name. The number
- associated with the directory (e.g. the "5" in "coredump5/")
- should match the number of the tar file (e.g. "coredump5.tar").
-
- """
- temp_dir, _ = get_unused_directory_and_file_names(".", "coredump.tar")
-
- os.mkdir(temp_dir)
-
- os.chdir(temp_dir)
-
- quiet = args.quiet
-
- write_ip_addresses(args, nodes)
-
- if not quiet:
- print("Getting boot order...")
- write_boot_order(args, nodes)
-
- if not quiet:
- print("Getting version information...")
- write_version_info(args, nodes)
-
- if not quiet:
- print("Getting MAC addresses...")
- write_mac_addrs(args, nodes)
-
- if not quiet:
- print("Getting sensor information...")
- write_sensor_info(args, nodes)
- print("Done!")
-
- if not quiet:
- print("Getting sensor data records...")
- write_sdr(args, nodes)
- print("Done!")
-
- if not quiet:
- print("Getting firmware information...")
- write_fwinfo(args, nodes)
-
- if not quiet:
- print("Getting system event logs...")
- write_sel(args, nodes)
- print("Done!")
-
- if not quiet:
- print("Getting depth charts...")
- write_depth_chart(args, nodes)
-
- if not quiet:
- print("Getting routing tables...")
- write_routing_table(args, nodes)
-
- # Archive the files
- os.chdir("..")
- archive(temp_dir)
-
- # The original files are already archived.
- delete_files(temp_dir)
-
- return 0
-
-
-def write_ip_addresses(args, nodes):
- """ Write the ECME and server IP addresses for each node
- to their respective files.
-
- """
- ip_discover_results, ip_discover_errors = run_command(
- args,
- nodes,
- 'get_server_ip')
-
- if (len(ip_discover_errors) > 0 and (not args.quiet)):
- print("WARNING: Error discovering server IP addresses on "
- "the following nodes:")
- for error in ip_discover_errors:
- print(node_ip(error))
-
- for node in nodes:
- write_to_file(
- node,
- ["Node " + str(node.node_id)],
- False
- )
-
- if node in ip_discover_results:
- write_to_file(
- node,
- ["[ ECME : Server ]",
- node_ip(node) + " : " + ip_discover_results[node]]
- )
- else:
- write_to_file(
- node,
- ["[ ECME : Server ]",
- node_ip(node) + " : (Unknown)"]
- )
-
-
-def write_version_info(args, nodes):
- """ Write the version info (like cxmanage info) for each node
- to their respective files.
-
- """
- info_results, info_errors = run_command(args, nodes, "get_versions")
-
- # This will be used when writing version info to file
- components = [
- ("ecme_version", "ECME version"),
- ("cdb_version", "CDB version"),
- ("stage2_version", "Stage2boot version"),
- ("bootlog_version", "Bootlog version"),
- ("a9boot_version", "A9boot version"),
- ("uboot_version", "Uboot version"),
- ("ubootenv_version", "Ubootenv version"),
- ("dtb_version", "DTB version")
- ]
-
- for node in nodes:
- lines = [] # The lines of text to write to file
- # \n is used here to give a blank line before this section
- lines.append(
- "\n[ Version Info for Node " +
- str(node.node_id) + " ]"
- )
-
- if node in info_results:
- info_result = info_results[node]
- lines.append(
- "Hardware version : %s" %
- info_result.hardware_version
- )
- lines.append(
- "Firmware version : %s" %
- info_result.firmware_version
- )
- for var, description in components:
- if hasattr(info_result, var):
- version = getattr(info_result, var)
- lines.append("%s: %s" % (description.ljust(19), version))
- else:
- lines.append("No version information could be found.")
-
- write_to_file(node, lines)
-
-
-def write_mac_addrs(args, nodes):
- """ Write the MAC addresses for each node to their respective files. """
- mac_addr_results, mac_addr_errors = run_command(
- args,
- nodes,
- "get_fabric_macaddrs"
- )
-
- for node in nodes:
- lines = [] # Lines of text to write to file
- # \n is used here to give a blank line before this section
- lines.append("\n[ MAC Addresses for Node " + str(node.node_id) + " ]")
-
- if node in mac_addr_results:
- for port in mac_addr_results[node][node.node_id]:
- for mac_address in mac_addr_results[node][node.node_id][port]:
- lines.append("Node %i, Port %i: %s" %
- (node.node_id, port, mac_address)
- )
- else:
- lines.append("\nWARNING: No MAC addresses found!")
- write_to_file(node, lines)
-
-
-def write_sensor_info(args, nodes):
- """ Write sensor information for each node to their respective files. """
- for node in nodes:
- lines = [] # Lines of text to write to file
- # \n is used here to give a blank line before this section
- lines.append("\n[ Sensors for Node " + str(node.node_id) + " ]")
-
- try:
- sensor_command = "ipmitool sensor -I lanplus -H " + \
- node_ip(node) + " -U admin -P admin list -v"
- sensor_call = subprocess.Popen(
- sensor_command.split(),
- stdout=subprocess.PIPE
- )
- sensor_info = sensor_call.communicate()[0]
- lines.append(sensor_info)
- except Exception as e:
- lines.append("Could not get sensor info! " + str(e))
- if not args.quiet:
- print("Failed to get sensor information for " + node_ip(node))
- write_to_file(node, lines)
-
-
-def write_sdr(args, nodes):
- """ Write the sensor data record for each node to their
- respective files.
-
- """
- for node in nodes:
- lines = [] # Lines of text to write to file
- # \n is used here to give a blank line before this section
- lines.append(
- "\n[ Sensor Data Record for Node " + str(
- node.node_id) + " ]")
-
- try:
- sdr_command = "ipmitool sdr -I lanplus -H " + \
- node_ip(node) + " -U admin -P admin info"
- sdr_call = subprocess.Popen(
- sdr_command.split(),
- stdout=subprocess.PIPE
- )
- sdr = sdr_call.communicate()[0]
- lines.append(sdr)
- except Exception as e:
- lines.append("Could not get SDR! " + str(e))
- if not args.quiet:
- print("Failed to get sensor data record for " + node_ip(node))
- write_to_file(node, lines)
-
-
-def write_fwinfo(args, nodes):
- """ Write information about each node's firware partitions
- to its respective file.
-
- """
- results, errors = run_command(args, nodes, "get_firmware_info")
-
- for node in nodes:
- lines = [] # Lines of text to write to file
- # \n is used here to give a blank line before this section
- lines.append("\n[ Firmware Info for Node " + str(node.node_id) + " ]")
-
- if node in results:
- for partition in results[node]:
- lines.append("\nPartition : %s" % partition.partition)
- lines.append("Type : %s" % partition.type)
- lines.append("Offset : %s" % partition.offset)
- lines.append("Size : %s" % partition.size)
- lines.append("Priority : %s" % partition.priority)
- lines.append("Daddr : %s" % partition.daddr)
- lines.append("Flags : %s" % partition.flags)
- lines.append("Version : %s" % partition.version)
- lines.append("In Use : %s" % partition.in_use)
- else:
- lines.append("Could not get firmware info!")
- write_to_file(node, lines)
-
-
-def write_boot_order(args, nodes):
- """ Write the boot order of each node to their respective files. """
- results, boot_order_errors = run_command(args, nodes, "get_boot_order")
-
- for node in nodes:
- lines = [] # Lines of text to write to file
- # \n is used here to give a blank line before this section
- lines.append("\n[ Boot Order for Node " + str(node.node_id) + " ]")
-
- if node in results:
- lines.append(", ".join(results[node]))
- else:
- lines.append("Could not get boot order!")
-
- write_to_file(node, lines)
-
-
-def write_sel(args, nodes):
- """ Write the SEL for each node to their respective files. """
- for node in nodes:
- lines = [] # Lines of text to write to file
- # \n is used here to give a blank line before this section
- lines.append(
- "\n[ System Event Log for Node " + str(
- node.node_id) + " ]")
-
- try:
- sel_command = "ipmitool sel -I lanplus -H " + node_ip(node) + \
- " -U admin -P admin list"
- sel_call = subprocess.Popen(
- sel_command.split(),
- stdout=subprocess.PIPE
- )
- sel = sel_call.communicate()[0]
- lines.append(sel)
- except Exception as e:
- lines.append("Could not get SEL! " + str(e))
- if not args.quiet:
- print("Failed to get system event log for " + node_ip(node))
-
- write_to_file(node, lines)
-
-
-def write_depth_chart(args, nodes):
- """ Write the depth chart for each node to their respective files. """
- depth_results, depth_errors = run_command(args, nodes, "get_depth_chart")
-
- for node in nodes:
- lines = [] # Lines of text to write to file
- # \n is used here to give a blank line before this section
- lines.append("\n[ Depth Chart for Node " + str(node.node_id) + " ]")
-
- if node in depth_results:
- depth_chart = depth_results[node]
- for key in depth_chart:
- subchart = depth_chart[key]
- lines.append("To node " + str(key))
- for subkey in subchart:
- lines.append(" " + str(subkey) +
- " : " + str(subchart[subkey])
- )
- else:
- lines.append("Could not get depth chart!")
-
- write_to_file(node, lines)
-
-
-def write_routing_table(args, nodes):
- """ Write the routing table for each node to their respective files. """
- routing_results, routing_errors = run_command(
- args, nodes, "get_routing_table")
-
- for node in nodes:
- lines = [] # Lines of text to write to file
- # \n is used here to give a blank line before this section
- lines.append("\n[ Routing Table for Node " + str(node.node_id) + " ]")
-
- if node in routing_results:
- table = routing_results[node]
- for node_to in table:
- lines.append(str(node_to) + " : " + str(table[node_to]))
- else:
- lines.append("Could not get routing table!")
-
- write_to_file(node, lines)
-
-
-def write_to_file(node, toWrite, add_newlines=True):
- """ Append toWrite to an info file for every node in nodes.
-
- :param node: Node object to write about
- :type node: Nobe object
- :param toWrite: Text to write to the files
- :type toWrite: List of strings
- :
-param add_newlines: Whether to add newline characters before
- every item in toWrite. True by default. True will add newline
- characters.
- :type add_newlines: bool
-
- """
-
- with open("node" + str(node.node_id) + ".txt", 'a') as file:
- for line in toWrite:
- if add_newlines:
- file.write("\n" + line)
- else:
- file.write(line)
-
-
-def node_ip(node):
- """ Return a string containing the given node's ECME IP address.
- :returns: A string containing the node's ECME IP address.
- :rtype: string
- :param node: The node to get an IP address from.
- :type node: Node object
-
- """
- return str(node)[6:]
-
-
-def delete_files(directory):
- """ Remove all files inside directory, and directory itself. """
- command = "rm -r " + directory
- call(command.split())
-
-
-def archive(directory_to_archive):
- """ Creates a .tar containing everything in the directory_to_archive.
- The .tar is saved to the current directory under the same name as
- the directory, but with .tar appended.
-
- :param directory_to_archive: A path to the directory to be archived.
- :type directory_to_archive: string
-
- """
-
- make_tar_command = "tar -cf " + directory_to_archive + ".tar " + \
- directory_to_archive
-
- call(make_tar_command.split())
- print("Finished! One archive created:\n" + directory_to_archive + ".tar")
-
-
-def get_unused_directory_and_file_names(directory, name):
- """ Given a directory and filename, determine an unused directory name
- and an unused file name that share the same name before any extensions.
-
- Returns: A list containing two strings: an unused directory name, and
- an unused file name.
-
- :param directory: A path to the directory to look in.
- :type directory: string
- :param name: The original name of a file, possibly including an extension
- :type name: string
-
- """
- dir_name, _, _ = name.partition(".")
-
- dir_number = 0
- file_number = 0
-
- while True:
- # Try to get an unused dir starting from file_number
- new_dir, dir_number = get_unused_name(directory, dir_name, file_number)
-
- # Try to get an unused name starting from dir_number
- new_file, file_number = get_unused_name(directory, name, dir_number)
-
- # dir_number and file_number always indicate unused names
- if dir_number == file_number:
- return [new_dir, new_file]
-
-
-def get_unused_name(directory, name, number=0):
- """ Get a new filename. This new filename cannot be the same as any
- existing file in directory, and should be based off of name. name should
- contain one or zero periods, and should not start with a period.
- The return type is a list containing the new filename (string), and the
- number attached to it (int).
-
- :param directory: A path to directory
- :type directory: string
- :param name: The original name of a file, possibly with an extension
- :type name: string
- :param number: The number to start searching from
- :type number: int
-
- """
- name, dot, extension = name.partition('.')
-
- # Create a new string, similar to "name0.extension"
- destination = name + str(number) + dot + extension
- exit = False
-
- # Increment the number in name#.ext until we find an unused filename
- while exit == False:
- command = 'ls'
-
- a_call = subprocess.Popen(
- command.split(),
- stdout=subprocess.PIPE
- )
- call_result = a_call.communicate()[0]
-
- if destination in call_result:
- number = number + 1
- destination = name + str(number) + dot + extension
- else:
- exit = True
-
- return [destination, number]
diff --git a/cxmanage/commands/info.py b/cxmanage/commands/info.py
index d002906..f552fae 100644
--- a/cxmanage/commands/info.py
+++ b/cxmanage/commands/info.py
@@ -28,7 +28,8 @@
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
-from cxmanage import get_tftp, get_nodes, get_node_strings, run_command
+from cxmanage import get_components, get_tftp, get_nodes, get_node_strings
+from cxmanage import run_command
def info_command(args):
@@ -41,16 +42,7 @@ def info_command(args):
def info_basic_command(args):
"""Print basic info"""
- components = [
- ("ecme_version", "ECME version"),
- ("cdb_version", "CDB version"),
- ("stage2_version", "Stage2boot version"),
- ("bootlog_version", "Bootlog version"),
- ("a9boot_version", "A9boot version"),
- ("uboot_version", "Uboot version"),
- ("ubootenv_version", "Ubootenv version"),
- ("dtb_version", "DTB version")
- ]
+ components = get_components()
tftp = get_tftp(args)
nodes = get_nodes(args, tftp)
diff --git a/cxmanage/commands/tspackage.py b/cxmanage/commands/tspackage.py
new file mode 100644
index 0000000..da18800
--- /dev/null
+++ b/cxmanage/commands/tspackage.py
@@ -0,0 +1,376 @@
+#!/usr/bin/env python
+
+# Copyright 2013 Calxeda, Inc. All Rights Reserved.
+
+
+import os
+import time
+import shutil
+import tarfile
+import tempfile
+
+from cxmanage import get_tftp, get_nodes, run_command, get_components
+
+
+def tspackage_command(args):
+ """ Get information pertaining to each node. This includes:
+ Version info (like cxmanage info)
+ MAC addresses
+ Sensor readings
+ Sensor data records
+ Firmware info
+ Boot order
+ SELs (System Event Logs),
+ Depth charts
+ Routing Tables
+
+ This data will be written to a set of files. Each node will get its own
+ file. All of these files will be archived and saved to the user's current
+ directory.
+
+ Internally, this command is called from:
+ ~/virtual_testenv/workspace/cx_manage_util/scripts/cxmanage
+
+ """
+
+ tftp = get_tftp(args)
+ nodes = get_nodes(args, tftp)
+
+ # Make a temporary directory to store the node information files
+ original_dir = os.getcwd()
+ temp_dir = tempfile.mkdtemp()
+ os.chdir(temp_dir)
+ tspackage_dir = "tspackage.%s" % time.strftime("%Y%m%d%H%M%S")
+ os.mkdir(tspackage_dir)
+ os.chdir(tspackage_dir)
+
+ quiet = args.quiet
+
+ if not quiet:
+ print("Getting version information...")
+ write_version_info(args, nodes)
+
+ if not quiet:
+ print("Getting boot order...")
+ write_boot_order(args, nodes)
+
+ if not quiet:
+ print("Getting MAC addresses...")
+ write_mac_addrs(args, nodes)
+
+ if not quiet:
+ print("Getting sensor information...")
+ write_sensor_info(args, nodes)
+
+ if not quiet:
+ print("Getting firmware information...")
+ write_fwinfo(args, nodes)
+
+ if not quiet:
+ print("Getting system event logs...")
+ write_sel(args, nodes)
+
+ if not quiet:
+ print("Getting depth charts...")
+ write_depth_chart(args, nodes)
+
+ if not quiet:
+ print("Getting routing tables...")
+ write_routing_table(args, nodes)
+
+ # Archive the files
+ archive(os.getcwd(), original_dir)
+
+ # The original files are already archived, so we can delete them.
+ shutil.rmtree(temp_dir)
+
+ return 0
+
+
+def write_version_info(args, nodes):
+ """ Write the version info (like cxmanage info) for each node
+ to their respective files.
+
+ """
+ info_results, _ = run_command(args, nodes, "get_versions")
+
+ # This will be used when writing version info to file
+ components = get_components()
+
+ for node in nodes:
+ lines = [] # The lines of text to write to file
+
+ # Since this is the first line of the file, we don't need a \n
+ write_to_file(
+ node,
+ "[ Version Info for Node " + str(node.node_id) + " ]",
+ False
+ )
+
+ lines.append("ECME IP Address : %s" % node.ip_address)
+
+ if node in info_results:
+ info_result = info_results[node]
+ lines.append(
+ "Hardware version : %s" %
+ info_result.hardware_version
+ )
+ lines.append(
+ "Firmware version : %s" %
+ info_result.firmware_version
+ )
+ for var, description in components:
+ if hasattr(info_result, var):
+ version = getattr(info_result, var)
+ lines.append("%s: %s" % (description.ljust(19), version))
+ else:
+ lines.append("No version information could be found.")
+
+ write_to_file(node, lines)
+
+
+def write_mac_addrs(args, nodes):
+ """ Write the MAC addresses for each node to their respective files. """
+ mac_addr_results, _ = run_command(
+ args,
+ nodes,
+ "get_fabric_macaddrs"
+ )
+
+ for node in nodes:
+ lines = [] # Lines of text to write to file
+ # \n is used here to give a blank line before this section
+ lines.append("\n[ MAC Addresses for Node " + str(node.node_id) + " ]")
+
+ if node in mac_addr_results:
+ for port in mac_addr_results[node][node.node_id]:
+ for mac_address in mac_addr_results[node][node.node_id][port]:
+ lines.append(
+ "Node %i, Port %i: %s" %
+ (node.node_id, port, mac_address)
+ )
+ else:
+ lines.append("\nWARNING: No MAC addresses found!")
+ write_to_file(node, lines)
+
+
+def write_sensor_info(args, nodes):
+ """ Write sensor information for each node to their respective files. """
+
+ args.sensor_name = ""
+
+ results, _ = run_command(args, nodes, "get_sensors",
+ args.sensor_name)
+
+ sensors = {}
+ for node in nodes:
+ lines = [] # Lines of text to write to file
+ # \n is used here to give a blank line before this section
+ lines.append("\n[ Sensors for Node " + str(node.node_id) + " ]")
+
+ if node in results:
+ for sensor_name, sensor in results[node].iteritems():
+ if not sensor_name in sensors:
+ sensors[sensor_name] = []
+
+ reading = sensor.sensor_reading.replace("(+/- 0) ", "")
+ try:
+ value = float(reading.split()[0])
+ suffix = reading.lstrip("%f " % value)
+ sensors[sensor_name].append((node, value, suffix))
+ except ValueError:
+ sensors[sensor_name].append((node, reading, ""))
+ else:
+ print("Could not get sensor info!")
+ lines.append("Could not get sensor info!")
+
+ for sensor_name, readings in sensors.iteritems():
+ for reading_node, reading, suffix in readings:
+ if reading_node.ip_address == node.ip_address:
+ lines.append(
+ "%s: %.2f %s" %
+ (sensor_name, reading, suffix)
+ )
+
+ write_to_file(node, lines)
+
+
+def write_fwinfo(args, nodes):
+ """ Write information about each node's firware partitions
+ to its respective file.
+
+ """
+ results, _ = run_command(args, nodes, "get_firmware_info")
+
+ for node in nodes:
+ lines = [] # Lines of text to write to file
+ # \n is used here to give a blank line before this section
+ lines.append("\n[ Firmware Info for Node " + str(node.node_id) + " ]")
+
+ if node in results:
+ first_partition = True # The first partiton doesn't need \n
+
+ for partition in results[node]:
+ if first_partition:
+ lines.append("Partition : %s" % partition.partition)
+ first_partition = False
+ else:
+ lines.append("\nPartition : %s" % partition.partition)
+ lines.append("Type : %s" % partition.type)
+ lines.append("Offset : %s" % partition.offset)
+ lines.append("Size : %s" % partition.size)
+ lines.append("Priority : %s" % partition.priority)
+ lines.append("Daddr : %s" % partition.daddr)
+ lines.append("Flags : %s" % partition.flags)
+ lines.append("Version : %s" % partition.version)
+ lines.append("In Use : %s" % partition.in_use)
+ else:
+ lines.append("Could not get firmware info!")
+ write_to_file(node, lines)
+
+
+def write_boot_order(args, nodes):
+ """ Write the boot order of each node to their respective files. """
+ results, _ = run_command(args, nodes, "get_boot_order")
+
+ for node in nodes:
+ lines = [] # Lines of text to write to file
+ # \n is used here to give a blank line before this section
+ lines.append("\n[ Boot Order for Node " + str(node.node_id) + " ]")
+
+ if node in results:
+ lines.append(", ".join(results[node]))
+ else:
+ lines.append("Could not get boot order!")
+
+ write_to_file(node, lines)
+
+
+def write_sel(args, nodes):
+ """ Write the SEL for each node to their respective files. """
+ results, _ = run_command(args, nodes, "get_sel")
+
+ for node in nodes:
+ lines = [] # Lines of text to write to file
+ # \n is used here to give a blank line before this section
+ lines.append(
+ "\n[ System Event Log for Node " + str(node.node_id) + " ]"
+ )
+
+ try:
+ if node in results:
+ for event in results[node]:
+ lines.append(event)
+
+ except Exception as error:
+ lines.append("Could not get SEL! " + str(error))
+ if not args.quiet:
+ print("Failed to get system event log for " + node.ip_address)
+
+ write_to_file(node, lines)
+
+
+def write_depth_chart(args, nodes):
+ """ Write the depth chart for each node to their respective files. """
+ depth_results, _ = run_command(args, nodes, "get_depth_chart")
+
+ for node in nodes:
+ lines = [] # Lines of text to write to file
+ # \n is used here to give a blank line before this section
+ lines.append("\n[ Depth Chart for Node " + str(node.node_id) + " ]")
+
+ if node in depth_results:
+ depth_chart = depth_results[node]
+ for key in depth_chart:
+ subchart = depth_chart[key]
+ lines.append("To node " + str(key))
+
+ # The 'shortest' entry is one tuple, but
+ # the 'others' are a list.
+ for subkey in subchart:
+ if str(subkey) == "shortest":
+ lines.append(
+ " " + str(subkey) +
+ " : " + str(subchart[subkey])
+ )
+ else:
+ for entry in subchart[subkey]:
+ lines.append(
+ " " + str(subkey) +
+ " : " + str(entry)
+ )
+
+ else:
+ lines.append("Could not get depth chart!")
+
+ write_to_file(node, lines)
+
+
+def write_routing_table(args, nodes):
+ """ Write the routing table for each node to their respective files. """
+ routing_results, _ = run_command(
+ args, nodes, "get_routing_table")
+
+ for node in nodes:
+ lines = [] # Lines of text to write to file
+ # \n is used here to give a blank line before this section
+ lines.append("\n[ Routing Table for Node " + str(node.node_id) + " ]")
+
+ if node in routing_results:
+ table = routing_results[node]
+ for node_to in table:
+ lines.append(str(node_to) + " : " + str(table[node_to]))
+ else:
+ lines.append("Could not get routing table!")
+
+ write_to_file(node, lines)
+
+
+def write_to_file(node, to_write, add_newlines=True):
+ """ Append to_write to an info file for every node in nodes.
+
+ :param node: Node object to write about
+ :type node: Node object
+ :param to_write: Text to write to the files
+ :type to_write: List of strings
+ :param add_newlines: Whether to add newline characters before
+ every item in to_write. True by default. True will add newline
+ characters.
+ :type add_newlines: bool
+
+ """
+
+ with open("node" + str(node.node_id) + ".txt", 'a') as node_file:
+ if add_newlines:
+ # join() doesn't add a newline before the first item
+ to_write[0] = "\n" + to_write[0]
+ node_file.write("\n".join(to_write))
+ else:
+ node_file.write("".join(to_write))
+
+
+def archive(directory_to_archive, destination):
+ """ Creates a .tar containing everything in the directory_to_archive.
+ The .tar is saved to destination with the same name as the original
+ directory_to_archive, but with .tar appended.
+
+ :param directory_to_archive: A path to the directory to be archived.
+ :type directory_to_archive: string
+
+ :param destination: A path to the location the .tar should be saved
+ :type destination: string
+
+ """
+
+ os.chdir(os.path.dirname(directory_to_archive))
+
+ tar_name = os.path.basename(directory_to_archive) + ".tar"
+ tar_name = os.path.join(destination, tar_name)
+
+ with tarfile.open(tar_name, "w") as tar:
+ tar.add(os.path.basename(directory_to_archive))
+
+ print(
+ "Finished! One archive created:\n" +
+ os.path.join(destination, tar_name)
+ )
diff --git a/cxmanage_api/node.py b/cxmanage_api/node.py
index efd38ba..df3db65 100644
--- a/cxmanage_api/node.py
+++ b/cxmanage_api/node.py
@@ -314,6 +314,9 @@ class Node(object):
else:
raise Exception("Reset timed out")
+ def get_sel(self):
+ return self.bmc.sel_list()
+
def get_sensors(self, search=""):
"""Get a list of sensor objects that match search criteria.
diff --git a/scripts/cxmanage b/scripts/cxmanage
index 5f38fec..2e0af98 100755
--- a/scripts/cxmanage
+++ b/scripts/cxmanage
@@ -46,7 +46,7 @@ from cxmanage.commands.config import config_reset_command, config_boot_command
from cxmanage.commands.info import info_command
from cxmanage.commands.ipmitool import ipmitool_command
from cxmanage.commands.ipdiscover import ipdiscover_command
-from cxmanage.commands.coredump import coredump_command
+from cxmanage.commands.tspackage import tspackage_command
PYIPMI_VERSION = '0.7.1'
@@ -285,22 +285,9 @@ def build_parser():
parser.add_argument('hostname',
help='nodes to operate on (see examples below)')
- # Coredump command
- coredump = subparsers.add_parser('coredump', help='Get all data from each node')
- coredump.add_argument('sensor_name', help='Sensor name to read',
- nargs='?', default='')
- coredump.add_argument('-A', '--aggressive', action='store_true',
- help='discover IPs aggressively')
- coredump.add_argument('-U', '--server-user', type=str, default='user1',
- metavar='USER', help='Server-side Linux username')
- coredump.add_argument('-P', '--server-password', type=str,
- default='1Password', metavar='PASSWORD',
- help='Server-side Linux password')
- coredump.add_argument('-6', '--ipv6', action='store_true',
- help='Discover IPv6 addresses')
- coredump.add_argument('-I', '--interface', type=str, default=None,
- help='Network interface to check')
- coredump.set_defaults(func=coredump_command)
+ # tspackage command
+ tspackage = subparsers.add_parser('tspackage', help='Get all data from each node')
+ tspackage.set_defaults(func=tspackage_command)
return parser