diff options
Diffstat (limited to 'tools/pharos-validator/src/validation_tool/src')
13 files changed, 0 insertions, 1042 deletions
diff --git a/tools/pharos-validator/src/validation_tool/src/__init__.py b/tools/pharos-validator/src/validation_tool/src/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/tools/pharos-validator/src/validation_tool/src/__init__.py +++ /dev/null diff --git a/tools/pharos-validator/src/validation_tool/src/config.py b/tools/pharos-validator/src/validation_tool/src/config.py deleted file mode 100644 index 443467ee..00000000 --- a/tools/pharos-validator/src/validation_tool/src/config.py +++ /dev/null @@ -1,176 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Todd Gaunt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - -import logging -import sys -import os -import yaml -import struct -import socket - -from pharosvalidator import util -from collections import namedtuple - -class Topology(): - """ - Topology: Class to store any number of Network classes - and metadata about them - """ - def __init__(self, yaml_config): - # Dictionary of available networks - self.logger = logging.getLogger(__name__) - self.networks = {} - self.external_networks = [] - - # Fill the above dictionaries - self.parse_yaml(yaml_config) - - def parse_yaml(self, yaml_config): - """ - parse_yaml: parses the yaml configuration file this program uses - for all the network and node information - """ - config = safe_yaml_read(yaml_config) - for network in config["networks"]: - self.logger.info("Reading network section {}".format(network)) - if network == "admin": - self.networks[network] = Network(config["networks"][network]) - #TODO - elif network == "external": - for external_network in config["networks"][network]: - self.external_networks.append(Network(external_network)) - -class Network(): - """ - Network: Class to store all information on a given network - """ - def __init__(self, network): - try: - self.logger = logging.getLogger(__name__) - - # Some generic settings - self.enabled = network["enabled"] - self.vlan = network["vlan"] - - # VM settings - self.installer_nic_type = network["installer_vm"]["nic_type"] - self.installer_members = network["installer_vm"]["members"] - self.installer_ip = network["installer_vm"]["ip"] - - # Tuple containing the minimum and maximum - self.usable_ip_range = self.parse_ip_range(network["usable_ip_range"]) - self.gateway = network["gateway"] - self.cidr = network["cidr"] - self.dhcp_range = network["dhcp_range"] - self.dns_domain = network["dns-domain"] - self.dns_search = network["dns-search"] - - subnet, netmask = self.split_cidr(network["cidr"]) - self.subnet = subnet - self.netmask = netmask - - # List of all dns servers - self.dns_upstream = network["dns-upstream"] - - self.nic_mapping = {} - except KeyError as e: - self.logger.error("Field {} not available in network configuration file".format(e)) - - def split_cidr(self, cidr): - """ - split_cidr: Split up cidr notation subnets into a subnet string and a - netmask string - - input: cidr notation of a subnet - - output: Subnet string; Netmask string - """ - split = cidr.split('/') - host_bits = int(split[1]) - netmask = self.cidr_to_netmask(host_bits) - subnet = split[0] - - return subnet, netmask - - def parse_ip_range(self, ip_range_string): - """ - parse_ip_range: Create a named tuple object that contains the lowest - ip address and the highest ip address from a configuration file - - input: String formatted like so "min, max" where min/max are ip addresses - - output: Named tuple object containing a minimum and maximum field - """ - rp = ip_range_string.split(",") - ip_range = namedtuple("ip_range", ['minimum', 'maximum'])(minimum=min(rp), maximum=max(rp)) - return ip_range - - def cidr_to_netmask(self, cidr): - bits = 0xffffffff ^ (1 << 32 - cidr) - 1 - netmask = socket.inet_ntoa(struct.pack('>I', bits)) - self.logger.debug("Netmask generated from cidr '{}': '{}'".format(cidr, netmask)) - return netmask - -class Inventory(): - """ - Inventory: Class to hold configuration file data - """ - def __init__(self, yaml_config): - # Create the class logger - self.logger = logging.getLogger(__name__) - - self.nodes = [] - - # Fill the above list - self.parse_yaml(yaml_config) - - def parse_yaml(self, yaml_config): - config = safe_yaml_read(yaml_config) - nodes = [] - for node in config["nodes"]: - self.nodes.append(Node(node)) - - def nodecount(self): - return len(self.nodes) - -class Node(): - """ - Node: Class to hold - """ - def __init__(self, node): - self.logger = logging.getLogger(__name__) - try: - self.name = node["name"] - self.tags = node["tags"] - self.arch = node["arch"] - self.mac_address = node["mac_address"] # ipmi mac address - self.cpus = node["cpus"] - self.memory = node["memory"] - self.disk = node["disk"] - except KeyError as e: - self.logger.error("Field {} not available in inventory file".format(e)) - - # Power sub section - if node["power"]["type"] == "ipmi": - try: - self.ipmi_addr = node["power"]["address"] - self.ipmi_user = node["power"]["user"] - self.ipmi_pass = node["power"]["pass"] - except KeyError as e: - self.logger.error("Field {} not available in inventory file".format(e)) - else: - pass - -def safe_yaml_read(yamlfile): - logger = logging.getLogger(__name__) - if os.path.isfile(yamlfile) == False: - logger.critical("Could not open find {}".format(yamlfile)) - quit(1) - with open(yamlfile, 'r') as fd: - return yaml.load(fd.read()) diff --git a/tools/pharos-validator/src/validation_tool/src/const.py b/tools/pharos-validator/src/validation_tool/src/const.py deleted file mode 100644 index a204a964..00000000 --- a/tools/pharos-validator/src/validation_tool/src/const.py +++ /dev/null @@ -1,48 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Todd Gaunt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - -## Various constant strings used throughout program -HARDWARE_TEST="pharos-validator-node" - -## Pharos hardware specification -# memory -MIN_MEMSIZE = 32000000 # In Kb - -# cpu -MIN_CPUFREQ = 1800.000 # In Mhz -MIN_CORECOUNT = 4 - -# storage -MIN_DISKCOUNT = 3 -MIN_SSDCOUNT = 1 -MIN_HDDSIZE = 1000 # In Gb -MIN_SSDSIZE = 100 # In Gb -# Smallest possible disk size -MIN_DISKSIZE = min(MIN_HDDSIZE, MIN_SSDSIZE) - -# Virtual deployments -# Requirements are per node -APEX_REQ = {"cores": 2, \ - "ram": 8000000, \ - "disk": 40} - -# Requirements are per node -COMPASS_REQ = {"cores": 4, \ - "ram": 4000000, \ - "disk": 100} - -# Requirements are per node -JOID_REQ = {"cores": 4, \ - "ram": 4000000, \ - "disk": 100} - -# Requirements are per node -FUEL_REQ = {"cores": 4, \ - "ram": 4000000, \ - "disk": 100} diff --git a/tools/pharos-validator/src/validation_tool/src/dhcp.py b/tools/pharos-validator/src/validation_tool/src/dhcp.py deleted file mode 100644 index 26c42f84..00000000 --- a/tools/pharos-validator/src/validation_tool/src/dhcp.py +++ /dev/null @@ -1,102 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Todd Gaunt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - -import yaml -import netifaces -import subprocess -import copy -import re -import os -import logging - -from pharosvalidator.specification import * -from pharosvalidator import util - -init_cmd = ["systemctl", "start", "dhcpd.service"] - -def gen_dhcpd_file(dhcpdfile, nodes, network): - """Generates and associates incremental ip addresses to - MAC addresses according to restrictions placed by network - configuration file. Writes all of this out in dhcpd.conf format""" - logger = logging.getLogger(__name__) - logger.info("Generating dhcpfile...") - - header = "default-lease-time 86400;\n\ - max-lease-time 604800;\n\ - max-lease-time 604800;\n\ - \n\ - allow booting;\n\ - authoritative;\n\ - \n" - - # Skip this network if it is disabled - if network.enabled == False: - logger.info("Admin network is disabled, please change the configuration to \"enabled\" if you would like this test to run") - quit() - - # Not explicitly in the cofiguration file - broadcastaddr = "0.0.0.0" - next_server = "0.0.0.0" - - ip_range = util.gen_ip_range(network.cidr, [network.installer_ip], network.usable_ip_range.minimum, \ - network.usable_ip_range.maximum) - - tab = ' ' - subnetconf = "subnet {} netmask {} {{\n".format(network.subnet, network.netmask)\ - + tab+"range {} {};\n".format(network.usable_ip_range.minimum, network.usable_ip_range.maximum)\ - + tab+"option broadcast-address {};\n".format(broadcastaddr)\ - + tab+'filename "pxelinux.0";\n'\ - + tab+"next-server {};\n".format(next_server) - - # For now no static addresses are assigned - """ - static_addrs = [] - for node in nodes: - # Skip the node if it doesn't have a name or mac address specified - if not node.name or not node.mac_address: - continue - - if node.ipmi_addr in ip_range: - ip_range.remove(node.ipmi_addr) - - static_line = "host {node} {{ hardware ethernet {ipmi_mac}; fixed-address {ip_addr}; }}\n".format\ - (node=node.name, ipmi_mac=node.mac_address, ip_addr=ip_range[0]) - ip_range = ip_range[1::] # Remove the assigned ip address - static_addrs.append(static_line) - - # Now add all statically assigned ip addresses - for addr in static_addrs: - subnetconf += tab+addr - """ - - subnetconf += "}\n" # Just the closing bracket - - # The final text to be written out to a file - dhcpdtext = header + subnetconf - - with open(dhcpdfile, "w+") as fd: - logger.info("Writing out dhcpd file to {}".format(dhcpdfile)) - fd.write(dhcpdtext) - - return dhcpdtext - -def start_server(): - logger = logging.getLogger(__name__) - global init_cmd - cmd = init_cmd - with open(os.devnull, 'w') as fn: - status = subprocess.Popen(cmd, stdout=fn, stderr=fn).wait() - if int(status) != 0: - logger.error("Could not bring up dhcpd server") - else: - logger.info("Dhcp server brought up") - return status - -if __name__ == "__main__": - split("inventory.yaml", "eth0") diff --git a/tools/pharos-validator/src/validation_tool/src/ipmi.py b/tools/pharos-validator/src/validation_tool/src/ipmi.py deleted file mode 100644 index 44be207a..00000000 --- a/tools/pharos-validator/src/validation_tool/src/ipmi.py +++ /dev/null @@ -1,63 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Todd Gaunt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - -import os -import subprocess -import logging - -def power_nodes(nodes, action): - """ Attempts to power on all nodes specified in a list, then returns a list - of the names of all failures. The list will be empty if no failures.""" - failed_nodes = [] - logger = logging.getLogger(__name__) - if not nodes: - logger.info("No nodes, is empty list") - for node in nodes: - # -I flag must be 'lanplus', 'lan' by itself doesn't work with - # the most recent idrac/ipmi version - if action == "on": - pass - elif action == "off": - pass - else: - logger.error("Invalid ipmi command") - - cmd = ["ipmitool", \ - "-I", "lanplus", \ - "-H ", "'"+node.ipmi_addr+"'", \ - "-U ", "'"+node.ipmi_user+"'", \ - "-P ", "'"+node.ipmi_pass+"'", \ - "power", action] - - logger.debug("Running: \"{}\"".format(' '.join(cmd))) - try: - with open(os.devnull, 'w') as fn: - status = subprocess.check_call(" ".join(cmd), \ - stdout=fn, stderr=fn, shell=True) - except subprocess.CalledProcessError as e: - status = e.returncode - logger.error("{} could not be accessed at {} (exit code {})".format(\ - node.name, node.ipmi_addr, status)) - failed_nodes.append(node.name) - if int(status) == 0: - logger.info("{} successfully powered {}".format(node.name, action)) - - return failed_nodes - -def status(node, ipaddr, username, passwd): - # -I flag must be 'lanplus', 'lan' by itself doesn't work with - # the most recent idrac/ipmi version - chkcmd = ["ipmitool", \ - "-I", "lanplus", \ - "-H", ipaddr, \ - "-U", username, \ - "-P", passwd, \ - "chassis", "status"] - print(chkcmd) - subprocess.Popen(chkcmd) diff --git a/tools/pharos-validator/src/validation_tool/src/jenkins.py b/tools/pharos-validator/src/validation_tool/src/jenkins.py deleted file mode 100644 index 443a6157..00000000 --- a/tools/pharos-validator/src/validation_tool/src/jenkins.py +++ /dev/null @@ -1,8 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Todd Gaunt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## diff --git a/tools/pharos-validator/src/validation_tool/src/node.py b/tools/pharos-validator/src/validation_tool/src/node.py deleted file mode 100644 index 280abb7f..00000000 --- a/tools/pharos-validator/src/validation_tool/src/node.py +++ /dev/null @@ -1,85 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Todd Gaunt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - -import logging -import socket -import yaml -import os - -import pharosvalidator.test.probe as probe -import pharosvalidator.test.evaluate as evaluate -from pharosvalidator.util import send_msg - -def hardware_test(): - """ - hardware_test: Run hardware probing/testing functions - - input: None - - output: String in YAML format of the tests that were run - """ - logger = logging.getLogger(__name__) - logger.info("Beginning hardware test") - - # Run test scripts - results = [] - results.append(testinterpreter("CPU test", evaluate.cpu, probe.cpu())) - results.append(testinterpreter("Memory test", evaluate.memory, probe.memory())) - results.append(testinterpreter("Storage test", evaluate.storage, probe.storage())) - - # Start generating the yaml file - yamltext = "" - for result in results: - yamltext += yaml.dump(result, default_flow_style=False) - return yamltext - -def network_test(networkfile): - logger = logging.getLogger(__name__) - logger.info("Beginning network test") - logger.info("Ending network test") - pass - -def send_result(host, port, result): - """ - send_result: Send the final test result to the central test server - - input: Host address of target; Port of target; String to send to server - - output: None - """ - logger = logging.getLogger(__name__) - logger.info("Sending test result") - - # Format the results properly - linecount = 0 - for c in result: - if c == "\n": - linecount += 1 - - result = str(linecount) + "\n" + result - - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.connect((host, int(port))) - send_msg(sock, result) - -def testinterpreter(name, test, dataset): - """High level function for test functions within this module to print out - their results in an ordered function while also writing out logs, - expects a list of testresults objects""" - - # Start the yaml file contents - data = {name:[]} - - # test the dataset - results = test(dataset) - - for result in results: - data[name].append(result) - - return data diff --git a/tools/pharos-validator/src/validation_tool/src/receiver.py b/tools/pharos-validator/src/validation_tool/src/receiver.py deleted file mode 100644 index 07d968e7..00000000 --- a/tools/pharos-validator/src/validation_tool/src/receiver.py +++ /dev/null @@ -1,46 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Todd Gaunt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - -import socket -import threading -import logging - -from pharosvalidator.util import read_msg - -def start(nodecount, port, q): - """Start a server to retrieve the files from the nodes. Server will run - indefinetely until the parent process ends""" - logging.basicConfig(level=0) - logger = logging.getLogger(__name__) - - address = "" # Empty means act as a server on all available interfaces - - logger.info("Bringing up receiver server...") - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.bind((address, port)) - sock.listen(nodecount) # Max connections is the amount of nodes - - while True: - # Receive a descriptor for the client socket, cl stands for client - (clsock, claddress) = sock.accept() - logger.info("Received client connection...") - client_thread = threading.Thread(target=_server_accept_thread, \ - args=(clsock, claddress, q), daemon=True) - # Start a new thread to read the new client socket connection - client_thread.start() - - socket.close() - logger.info("Bringing down receiver server...") - -def _server_accept_thread(clsock, claddress, q): - """Read from the socket into the queue, then close the connection""" - logger = logging.getLogger(__name__) - q.put(read_msg(clsock)) - logger.info("Retreived message from socket") - clsock.close() diff --git a/tools/pharos-validator/src/validation_tool/src/server.py b/tools/pharos-validator/src/validation_tool/src/server.py deleted file mode 100644 index 91c9a4f2..00000000 --- a/tools/pharos-validator/src/validation_tool/src/server.py +++ /dev/null @@ -1,111 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Todd Gaunt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - -import logging -import os -import subprocess -import time - -# Constant definitions -from pharosvalidator.const import * - -def ssh_thread(remoteaddr, returnaddr, port, passes): - """ - ssh_thread: the main loop of a thread the server spawns to connect to a node - over ssh. - - input: remoteaddr, returnaddr, and port to forward to run_remote_test; - passes to specify how many attempts should be made - """ - for i in range(passes): - status = run_remote_test(remoteaddr, returnaddr, port) - time.sleep(1) - -def run_remote_test(remoteaddr, returnaddr, port): - """ - run_remote_tests: ssh to a give remote address, and run a test program - on the remote machine specifying the address and port of where the results - should be sent (usually back to the machine this program was run on) - - input: ip address of the ssh target; Adress of the test results target; - Port of the test results target - - output: 0 if the test ran over ssh perfectly, non-zero if the test faild - """ - #TODO add way to keep attempting to ssh until service is up and running aka ping part 2 - logger = logging.getLogger(__name__) - - cmd = ["ssh", "root@"+remoteaddr, HARDWARE_TEST, \ - "-p", port, "-H", returnaddr, "hardware"] - - logger.debug("Running: {}".format(" ".join(cmd))) - try: - with open(os.devnull, 'w') as fn: - status = subprocess.check_call(" ".join(cmd), stdout=fn, stderr=fn, shell=True) - except subprocess.CalledProcessError as e: - status = e.returncode - logger.error("ssh attempt to '{}' failed".format(remoteaddr)) - - return status - -def ping_network(ip_range_list, ipcnt, passes): - """ - ping_network: Ping a range of ips until the amount of successful pings - reaches a number n - - input: List of ip addresses to be pinged; Counter for threshold - of successful pings; Number of iterations to pass - - output: List of ip addresses that were found to be up - """ - logger = logging.getLogger("pharosvalidator") - assert isinstance(ip_range_list, list) - ips_found = 0 - alive_ips = [] - for t in range(passes): - for addr in list(ip_range_list): - cmd = [ \ - "ping", \ - "-c", "1", \ - "-w", "1", \ - addr] - logger.debug("Running: \"{}\"".format(' '.join(cmd))) - try: - with open(os.devnull, 'w') as fn: - status = subprocess.check_call(" ".join(cmd), \ - stdout=fn, stderr=fn, shell=True) - except subprocess.CalledProcessError as e: - status = e.returncode - logger.error("Ping at '{}' failed".format(addr)) - # If the ip address was pinged successfully, then remove it from future attempts - if status == 0: - ips_found += 1 - logger.info("{} is up, {} total nodes up".format(addr, ips_found)) - - # Remove the ip that was successfully pinged from being tested again - ip_range_list.remove(addr) - - # Add the successfully pinged node to a list of successful pings - alive_ips.append(addr) - - if ips_found >= ipcnt: - break - - if ips_found >= ipcnt: - break - - return alive_ips - -def bring_up_admin_ip(ipaddr): - """ - Assign the machine this test is running on an address according to the - configuration file - """ - cmd = [""] - subprocess.Popen(cmd) diff --git a/tools/pharos-validator/src/validation_tool/src/test/__init__.py b/tools/pharos-validator/src/validation_tool/src/test/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/tools/pharos-validator/src/validation_tool/src/test/__init__.py +++ /dev/null diff --git a/tools/pharos-validator/src/validation_tool/src/test/evaluate.py b/tools/pharos-validator/src/validation_tool/src/test/evaluate.py deleted file mode 100644 index 81a837d6..00000000 --- a/tools/pharos-validator/src/validation_tool/src/test/evaluate.py +++ /dev/null @@ -1,159 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Todd Gaunt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - -import logging - -from pharosvalidator.util import approxsize - -# Constant macros -from pharosvalidator.const import * - -def cpu(cpudata): - """Compares system cpu against the pharos specification""" - results = [] - - # Architecture evaluation, a value of 63 or greater indicates at least a 64-bit OS - if cpudata["bitsize"] >= 63: - val = True - else: - val = False - result = {"architecture": { - "pass": val, - "description": str(cpudata["architecture"])}} - results.append(result) - - # Core evaluation - if cpudata["cores"] < MIN_CORECOUNT: - val = False - else: - val = True - desc = "Have {0}, Need at least {1}".format(cpudata["cores"], MIN_CORECOUNT) - result = {"corecount": { - "pass": val, - "description": desc}} - results.append(result) - - # Speed evaluation - i = 0 - for cpufreq in cpudata["frequency"]: - # Cpufrequency was not read if this is the result - if cpufreq == -1: - desc = "(Cpu freuency could not be read)" - else: - if approxsize(cpufreq, MIN_CPUFREQ, 5) or cpufreq > MIN_CPUFREQ: - val = True - else: - val = False - desc = "Have {:.2f}Mhz, Need at least ~= {:.2f}Mhz".format( \ - cpufreq, MIN_CPUFREQ) - result = {"cpu"+str(i): { - "pass": val, - "description": desc}} - results.append(result) - i += 1 - - return results - -def memory(memdata): - """Compares system meminfo object against the pharos specification""" - logger = logging.getLogger(__name__) - - results = [] - - logger.debug("required memory: {}, detected memory: {}".format(\ - MIN_MEMSIZE, memdata["size"])) - # Capacity evaluation - if approxsize(memdata["size"], MIN_MEMSIZE, 5) or memdata["size"] > MIN_MEMSIZE: - val = True - else: - val = False - - desc = "Have {:.2f}G, Need at least ~= {:.2f}G".format( \ - memdata["size"], MIN_MEMSIZE/1000000) - - result = {"memory capacity": { - "pass": val, - "description": desc}} - results.append(result) - - return results - -def storage(diskdata): - """Compares system storage against the Pharos specification""" - def sizecmp(a, b, unit): - if approxsize(a, b, 10) or a > b: - val = True - else: - val = False - desc = "capacity is {:.2f}{}, Need at least ~= {:.2f}{}".format(a, \ - unit, b, unit) - return (val,desc) - - results = [] - # Disk size evaluation (also counts the disks) - diskcount = {"ssd":0, "non-ssd":0} - for disk in diskdata["names"]: - if diskdata["rotational"][disk]: - disktype = "non-ssd" - diskcount["non-ssd"] += 1 - else: - disktype = "ssd" - diskcount["ssd"] += 1 - val, desc = sizecmp(diskdata["sizes"][disk], MIN_SSDSIZE, 'G') - data = diskdata["sizes"][disk] - result = {disk: { - "pass": val, - "description": "Disk type: disktype; " + desc}} - results.append(result) - - # Disk number evaluation - if sum(diskcount.values()) >= 3 and diskcount["ssd"] >= 1: - val = True - else: - val = False - desc = "Have {0} drives, Need at least {1} drives and {3} ssds".format( \ - sum(diskcount.values()), MIN_DISKCOUNT, \ - diskcount["ssd"], MIN_SSDCOUNT) - - data = diskcount - result = {"diskcount": { - "pass": val, - "description": desc}} - results.append(result) - return results - -""" -def netinterfaces(netfaces): - results = [] - for netface in netfaces: - if netface.status <= 0: - val = False - state = "down" - else: - val = True - state = "up" - try: - MACaddr = netface.MAC[0]["addr"] - except IndexError: - MACaddr = "no MAC" - if len(netface.addrs) > 0: - addrs = "" - for addr in netface.addrs: - if len(addrs) > 0: - addrs += ", " - addrs += addr['addr'] - addrs = "addresses: " + addrs - else: - addrs = "no address" - desc = "({0} is {1} with {2})".format(netface.name, state, addrs) - data = MACaddr - results.append(gen_yamltext(netface.name, val, desc, data)) - return results - """ - diff --git a/tools/pharos-validator/src/validation_tool/src/test/probe.py b/tools/pharos-validator/src/validation_tool/src/test/probe.py deleted file mode 100644 index daeccbc0..00000000 --- a/tools/pharos-validator/src/validation_tool/src/test/probe.py +++ /dev/null @@ -1,137 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Todd Gaunt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - -import os -import re -import sys -import platform -import subprocess -import netifaces -import logging - -from pharosvalidator.util import cd # Contains the pharos specification values - -# Static vars -mempath="/proc/meminfo" -cpuinfopath="/proc/cpuinfo" -cpupath="/sys/devices/system/cpu/" -diskpath="/sys/block/" - -def readproc(path): - """Reads and parses /proc from [path] argument files - and returns a hashmap of values""" - logger = logging.getLogger(__name__) - # Fail if path does not exist - try: - hashmap = {} - with open(path) as fd: - logger.debug("Reading {}".format(path)) - for line in fd: - data = line.split(":") - if len(data) == 2: - # Strip trailing characters from hashmap names and entries - # for less junk - hashmap[data[0].strip()] = data[1].strip() - return hashmap - except IOError: - logger.error("Path to file does not exist: {}".format(path)) - quit(1) - -def cpu(): - logger = logging.getLogger(__name__) - cpudata = {} - cpuinfo = readproc(cpuinfopath) - cpudata["bitsize"] = sys.maxsize.bit_length() - cpudata["architecture"] = platform.architecture()[0] - cpudata["cores"] = int(cpuinfo["cpu cores"]) - cpudata["frequency"] = [] - for i in range(cpudata["cores"]): - freqpath = "{0}/cpu{1}/cpufreq/cpuinfo_max_freq".format(cpupath, \ - str(i)) - try: - with open(freqpath) as fd: - logger.debug("Opening {}".format(freqpath)) - cpufreq = (float(fd.read(-1)))/1000 - except IOError: - # Less accurate way of getting cpu information as - # this frequency may change during operation, - # if dynamic frequency scaling is enabled, - # however it is better than nothing. - logger.error("Path to file does not exist: {}".format(freqpath)) - logger.error("Reading cpu frequency from {} instead".format(freqpath)) - cpufreq = float(cpuinfo["cpu MHz"]) - - if cpufreq < 0: - cpudata["frequency"].append(0) - else: - cpudata["frequency"].append(cpufreq) - - return cpudata - -def memory(): - logger = logging.getLogger(__name__) - meminfo=readproc(mempath) - # Create the memory object to store memory information - memdata = {} - memdata["size"] = (int(meminfo["MemTotal"].split(' ')[0]))/1000000 - return memdata - -def storage(): - """Gather's disk information""" - logger = logging.getLogger(__name__) - diskdata = {"names":[],"rotational":{},"sizes":{}} - for disk in os.listdir(diskpath): - #sdX is the naming schema for IDE/SATA interfaces in Linux - if re.match(r"sd\w",disk): - logger.debug("Found disk {}".format(disk)) - diskdata["names"].append(disk) - sizepath = "{0}/{1}/size".format(diskpath, disk) - try: - with open(sizepath) as fd: - size = int(fd.read(-1)) - except IOError: - size = -1 - # If the read was successful - if size != -1: - # Converts the value to Gb - diskdata["sizes"][disk] = (size * 512)/1000000000 - - rotationalpath = "{0}/{1}/queue/rotational".format(diskpath, disk) - try: - with open(rotationalpath) as fd: - rotational = int(fd.read(-1)) - except IOError: - rotational = -1 - if rotational == 0: - diskdata["rotational"][disk] = False - else: - diskdata["rotational"][disk] = True - - return diskdata - -def netinterfaces(nodeinfo): - """Uses netifaces to probe the system for network interface information""" - netfaces = [] - for interface in netifaces.interfaces(): - netface = netdata() - netface.name = interface - tmp = netifaces.ifaddresses(interface) - # If the interface is up and has at least one ip address - if netifaces.AF_INET in tmp: - netface.status = 1 # 1 stands for "up" - netface.addrs = tmp[netifaces.AF_INET] - # If the interface is down - else: - netface.status = 0 # 0 stands for "down" - # The file /proc/net/arp may also be used to read MAC addresses - if netifaces.AF_LINK in tmp: - netface.MAC = tmp[netifaces.AF_LINK] - netfaces.append(netface) - - return netfaces diff --git a/tools/pharos-validator/src/validation_tool/src/util.py b/tools/pharos-validator/src/validation_tool/src/util.py deleted file mode 100644 index 67a75a56..00000000 --- a/tools/pharos-validator/src/validation_tool/src/util.py +++ /dev/null @@ -1,107 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Todd Gaunt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - -import ipaddress -import logging -import os - -class cd: - """Context manager for changing the current working directory""" - def __init__(self, new_path): - self.new_path = os.path.expanduser(new_path) - - def __enter__(self): - self.saved_path = os.getcwd() - os.chdir(self.new_path) - - def __exit__(self, etype, value, traceback): - os.chdir(self.saved_path) - -def approxsize(x, y, deviation): - """Approximately compares 'x' to 'y' with in % of 'deviation'""" - logger = logging.getLogger(__name__) - - dev = (y * .01 * deviation) - - if x >= round(y - dev, 0) and x <= round(y + dev, 0): - logger.debug("{} is approximately {}".format(x, y)) - return True - else: - logger.debug("{} is not approximately {}".format(x, y)) - return False - -def read_line(sock): - """Reads from a socket until a \n character or 512 bytes have been read, - whichever comes first""" - c = "" - recvline = "" - reads = 0 - while (c != "\n" and reads < 512): - # Decode bytes to str, sockets output bytes which aren't pretty - c = sock.recv(1).decode("utf-8") - #print("char: '" + c + "'") # Debugging code - recvline += c - reads += 1 - return recvline - -def read_msg(sock): - """Reads a message prefixed with a number and a newline char, eg. "20\n" - then reads x lines, where x is equal to the number in the first line.""" - # Read the socket once initially for the line count - buf = read_line(sock) - buf = buf[:-1] # Cut off the '\n' character - length = int(buf) - - lines = [] - for i in range(length): - lines.append(read_line(sock)) - return "".join(lines) - -def send_msg(sock, msg): - """Sends a message to a socket""" - # Encode python str to bytes beforehand, sockets only deal in bytes - msg = bytes(msg, "utf-8") - totalsent = 0 - while totalsent < len(msg): - sent = sock.send(msg[totalsent:]) - if sent == 0: - return -1 - totalsent = totalsent + sent - return totalsent - -def get_addr(interface): - """Get the address of the machine that this program is running on""" - return netifaces.ifaddresses(interface)[netifaces.AF_INET][0]["addr"] - -def gen_ip_range(cidr, excluded, minimum, maximum ): - """Takes a network cidr number, and then a min max value, and creates a list - of ip addresses avalable on [a,b]. Also removes "excluded" addresses - from the range""" - logger = logging.getLogger(__name__) - # Generate a list of available ip addresses for the dhcp server - ip_range = list(map(lambda x: x.exploded, ipaddress.ip_network(cidr).hosts())) - - for addr in excluded: - # Remove the value from the list, if it isn't in the list then whatever - try: - ip_range.remove(addr) - except ValueError: - logger.debug("{} not in ip_range, cannot remove".format(addr)) - - # Remove all values before the minimum usable value - for i in range(len(ip_range)): - if ip_range[i] == minimum: - ip_range = ip_range[i::] - break - # Remove all values after the maximum usable value - for i in range(len(ip_range)): - if ip_range[i] == maximum: - ip_range = ip_range[0:i+1] - break - return ip_range |