1 ##############################################################################
2 # Copyright (c) 2015 Todd Gaunt and others.
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
17 from pharosvalidator import util
18 from collections import namedtuple
22 Topology: Class to store any number of Network classes
23 and metadata about them
25 def __init__(self, yaml_config):
26 # Dictionary of available networks
27 self.logger = logging.getLogger(__name__)
29 self.external_networks = []
31 # Fill the above dictionaries
32 self.parse_yaml(yaml_config)
34 def parse_yaml(self, yaml_config):
36 parse_yaml: parses the yaml configuration file this program uses
37 for all the network and node information
39 config = safe_yaml_read(yaml_config)
40 for network in config["networks"]:
41 self.logger.info("Reading network section {}".format(network))
42 if network == "admin":
43 self.networks[network] = Network(config["networks"][network])
45 elif network == "external":
46 for external_network in config["networks"][network]:
47 self.external_networks.append(Network(external_network))
51 Network: Class to store all information on a given network
53 def __init__(self, network):
55 self.logger = logging.getLogger(__name__)
57 # Some generic settings
58 self.enabled = network["enabled"]
59 self.vlan = network["vlan"]
62 self.installer_nic_type = network["installer_vm"]["nic_type"]
63 self.installer_members = network["installer_vm"]["members"]
64 self.installer_ip = network["installer_vm"]["ip"]
66 # Tuple containing the minimum and maximum
67 self.usable_ip_range = self.parse_ip_range(network["usable_ip_range"])
68 self.gateway = network["gateway"]
69 self.cidr = network["cidr"]
70 self.dhcp_range = network["dhcp_range"]
71 self.dns_domain = network["dns-domain"]
72 self.dns_search = network["dns-search"]
74 subnet, netmask = self.split_cidr(network["cidr"])
76 self.netmask = netmask
78 # List of all dns servers
79 self.dns_upstream = network["dns-upstream"]
83 self.logger.error("Field {} not available in network configuration file".format(e))
85 def split_cidr(self, cidr):
87 split_cidr: Split up cidr notation subnets into a subnet string and a
90 input: cidr notation of a subnet
92 output: Subnet string; Netmask string
94 split = cidr.split('/')
95 host_bits = int(split[1])
96 netmask = self.cidr_to_netmask(host_bits)
99 return subnet, netmask
101 def parse_ip_range(self, ip_range_string):
103 parse_ip_range: Create a named tuple object that contains the lowest
104 ip address and the highest ip address from a configuration file
106 input: String formatted like so "min, max" where min/max are ip addresses
108 output: Named tuple object containing a minimum and maximum field
110 rp = ip_range_string.split(",")
111 ip_range = namedtuple("ip_range", ['minimum', 'maximum'])(minimum=min(rp), maximum=max(rp))
114 def cidr_to_netmask(self, cidr):
115 bits = 0xffffffff ^ (1 << 32 - cidr) - 1
116 netmask = socket.inet_ntoa(struct.pack('>I', bits))
117 self.logger.debug("Netmask generated from cidr '{}': '{}'".format(cidr, netmask))
122 Inventory: Class to hold configuration file data
124 def __init__(self, yaml_config):
125 # Create the class logger
126 self.logger = logging.getLogger(__name__)
130 # Fill the above list
131 self.parse_yaml(yaml_config)
133 def parse_yaml(self, yaml_config):
134 config = safe_yaml_read(yaml_config)
136 for node in config["nodes"]:
137 self.nodes.append(Node(node))
140 return len(self.nodes)
146 def __init__(self, node):
147 self.logger = logging.getLogger(__name__)
149 self.name = node["name"]
150 self.tags = node["tags"]
151 self.arch = node["arch"]
152 self.mac_address = node["mac_address"] # ipmi mac address
153 self.cpus = node["cpus"]
154 self.memory = node["memory"]
155 self.disk = node["disk"]
156 except KeyError as e:
157 self.logger.error("Field {} not available in inventory file".format(e))
160 if node["power"]["type"] == "ipmi":
162 self.ipmi_addr = node["power"]["address"]
163 self.ipmi_user = node["power"]["user"]
164 self.ipmi_pass = node["power"]["pass"]
165 except KeyError as e:
166 self.logger.error("Field {} not available in inventory file".format(e))
170 def safe_yaml_read(yamlfile):
171 logger = logging.getLogger(__name__)
172 if os.path.isfile(yamlfile) == False:
173 logger.critical("Could not open find {}".format(yamlfile))
175 with open(yamlfile, 'r') as fd:
176 return yaml.load(fd.read())