From 4b269fba0ca273dfa3acf44c9f5490f01e0c3d87 Mon Sep 17 00:00:00 2001 From: Trevor Bramwell Date: Fri, 22 Sep 2017 12:23:36 -0700 Subject: Rename pharos-dashboard and pharos-validator As subdirectories of the pharos-tools repo, there is little need to keep the pharos prefix. Change-Id: Ica3d79411f409df638647300036c0664183c2725 Signed-off-by: Trevor Bramwell --- validator/src/validation_tool/src/config.py | 176 ++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 validator/src/validation_tool/src/config.py (limited to 'validator/src/validation_tool/src/config.py') diff --git a/validator/src/validation_tool/src/config.py b/validator/src/validation_tool/src/config.py new file mode 100644 index 0000000..443467e --- /dev/null +++ b/validator/src/validation_tool/src/config.py @@ -0,0 +1,176 @@ +############################################################################## +# 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()) -- cgit 1.2.3-korg