diff options
Diffstat (limited to 'deploy/reap.py')
-rw-r--r-- | deploy/reap.py | 414 |
1 files changed, 0 insertions, 414 deletions
diff --git a/deploy/reap.py b/deploy/reap.py deleted file mode 100644 index be729181f..000000000 --- a/deploy/reap.py +++ /dev/null @@ -1,414 +0,0 @@ -#!/usr/bin/python -############################################################################### -# Copyright (c) 2015, 2016 Ericsson AB and others. -# szilard.cserey@ericsson.com -# peter.barabas@ericsson.com -# 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 time -import os -import yaml -import glob -import shutil -import tempfile -import re -import netaddr -import templater - -from common import ( - N, - E, - R, - ArgParser, - exec_cmd, - parse, - err, - log, - delete, - commafy, -) - -DEA_1 = ''' -title: Deployment Environment Adapter (DEA) -# DEA API version supported -version: 1.1 -created: {date} -comment: {comment} -''' - -DHA_1 = ''' -title: Deployment Hardware Adapter (DHA) -# DHA API version supported -version: 1.1 -created: {date} -comment: {comment} - -# Adapter to use for this definition -# adapter: [ipmi|libvirt] -adapter: - -# Node list. -# Mandatory properties are id and role. -# All other properties are adapter specific. -# For Non-Fuel nodes controlled by: -# - ipmi adapter you need to provide: -# pxeMac -# ipmiIp -# ipmiUser -# ipmiPass -# and you *MAY* provide (optional, not added by reap.py): -# ipmiPort -# - libvirt adapter you need to provide: -# libvirtName: <whatever> -# libvirtTemplate: [libvirt/vms/controller.xml | libvirt/vms/compute.xml] -# -# For the Fuel Node you need to provide: -# libvirtName: <whatever> -# libvirtTemplate: libvirt/vms/fuel.xml -# isFuel: yes -# username: root -# password: r00tme -''' - -DHA_2 = ''' -# Adding the Fuel node as node id {node_id} -# which may not be correct - please adjust as needed. -''' - -DISKS = {'fuel': '100G', - 'controller': '100G', - 'compute': '100G'} - - -class Reap(object): - - def __init__(self, dea_file, dha_file, comment, base_dea, template): - self.dea_file = dea_file - self.dha_file = dha_file - self.comment = comment - self.base_dea = base_dea - self.template = template - self.temp_dir = None - self.env = None - self.env_id = None - self.last_node = None - - def get_env(self): - env_list = parse(exec_cmd('fuel env')) - if len(env_list) == 0: - err('No environment deployed') - elif len(env_list) > 1: - err('More than 1 environment deployed') - self.env = env_list[0] - self.env_id = self.env[E['id']] - - def download_config(self, config_type): - log('Download %s config for environment %s' - % (config_type, self.env_id)) - exec_cmd('fuel %s --env %s --download --dir %s' - % (config_type, self.env_id, self.temp_dir)) - - def download_node_config(self, nodeid): - log('Download node %s config for environment %s to %s' - % (nodeid, self.env_id,self.temp_dir)) - exec_cmd('fuel deployment --node-id %s --env %s --default --dir %s' - % (nodeid, self.env_id, self.temp_dir)) - - def write(self, file, text, newline=True): - mode = 'a' if os.path.isfile(file) else 'w' - with open(file, mode) as f: - f.write('%s%s' % (text, ('\n' if newline else ''))) - - def write_yaml(self, file, data, newline=True): - self.write(file, yaml.dump(data, default_flow_style=False).strip(), - newline) - - def get_node_by_id(self, node_list, node_id): - for node in node_list: - if node[N['id']] == node_id: - return node - - def reap_interface(self, node_id, interfaces): - interface, mac = self.get_interface(node_id) - if_name = None - if interfaces: - if_name = self.check_dict_exists(interfaces, interface) - if not if_name: - if_name = 'interfaces_%s' % str(len(interfaces) + 1) - interfaces[if_name] = interface - return if_name, mac - - def reap_transformation(self, node_id, roles, transformations): - main_role = 'controller' if 'controller' in roles else 'compute' - node_file = glob.glob('%s/deployment_%s/%s.yaml' - % (self.temp_dir, self.env_id, node_id)) - tr_name = None - with open(node_file[0]) as f: - node_config = yaml.load(f) - transformation = {'transformations': - node_config['network_scheme']['transformations']} - if transformations: - tr_name = self.check_dict_exists(transformations, transformation) - if not tr_name: - tr_name = 'transformations_%s' % str(len(transformations) + 1) - transformations[tr_name] = transformation - return tr_name - - def check_dict_exists(self, main_dict, dict): - for key, val in main_dict.iteritems(): - if cmp(dict, val) == 0: - return key - - def reap_nodes_interfaces_transformations(self): - node_list = parse(exec_cmd('fuel node')) - real_node_ids = [node[N['id']] for node in node_list] - real_node_ids = map(int, real_node_ids) - real_node_ids.sort() - min_node = min(real_node_ids) - interfaces = {} - transformations = {} - dea_nodes = [] - dha_nodes = [] - - for real_node_id in real_node_ids: - node_id = real_node_id - min_node + 1 - self.last_node = node_id - node = self.get_node_by_id(node_list, str(real_node_id)) - roles = commafy(node[N['roles']]) - if not roles: - err('Fuel Node %s has no role' % real_node_id) - dea_node = {'id': node_id, - 'role': roles} - dha_node = {'id': node_id} - if_name, mac = self.reap_interface(real_node_id, interfaces) - log('reap transformation for node %s' % real_node_id) - tr_name = self.reap_transformation(real_node_id, roles, - transformations) - dea_node.update( - {'interfaces': if_name, - 'transformations': tr_name}) - - dha_node.update( - {'pxeMac': mac if mac else None, - 'ipmiIp': None, - 'ipmiUser': None, - 'ipmiPass': None, - 'libvirtName': None, - 'libvirtTemplate': None}) - - dea_nodes.append(dea_node) - dha_nodes.append(dha_node) - - self.write_yaml(self.dha_file, {'nodes': dha_nodes}, False) - self.write_yaml(self.dea_file, {'nodes': dea_nodes}) - self.write_yaml(self.dea_file, interfaces) - self.write_yaml(self.dea_file, transformations) - self.reap_fuel_node_info() - self.write_yaml(self.dha_file, {'disks': DISKS}) - - def reap_fuel_node_info(self): - dha_nodes = [] - dha_node = { - 'id': self.last_node + 1, - 'libvirtName': None, - 'libvirtTemplate': None, - 'isFuel': True, - 'username': 'root', - 'password': 'r00tme'} - - dha_nodes.append(dha_node) - - self.write(self.dha_file, DHA_2.format(node_id=dha_node['id']), False) - self.write_yaml(self.dha_file, dha_nodes) - - def reap_environment_info(self): - network_file = ('%s/network_%s.yaml' - % (self.temp_dir, self.env_id)) - network = self.read_yaml(network_file) - - env = {'environment': - {'name': self.env[E['name']], - 'net_segment_type': - network['networking_parameters']['segmentation_type']}} - self.write_yaml(self.dea_file, env) - wanted_release = None - rel_list = parse(exec_cmd('fuel release')) - for rel in rel_list: - if rel[R['id']] == self.env[E['release_id']]: - wanted_release = rel[R['name']] - self.write_yaml(self.dea_file, {'wanted_release': wanted_release}) - - def reap_fuel_settings(self): - data = self.read_yaml('/etc/fuel/astute.yaml') - fuel = {} - del data['ADMIN_NETWORK']['mac'] - del data['ADMIN_NETWORK']['interface'] - for key in ['ADMIN_NETWORK', 'HOSTNAME', 'DNS_DOMAIN', 'DNS_SEARCH', - 'DNS_UPSTREAM', 'NTP1', 'NTP2', 'NTP3', 'FUEL_ACCESS']: - fuel[key] = data[key] - for key in fuel['ADMIN_NETWORK'].keys(): - if key not in ['ipaddress', 'netmask', - 'dhcp_pool_start', 'dhcp_pool_end', 'ssh_network']: - del fuel['ADMIN_NETWORK'][key] - - ## FIXME(armband): Factor in support for adding public/other interfaces. - ## TODO: Following block expects interface name(s) to be lowercase only - interfaces_list = exec_cmd('ip -o -4 a | grep -e "e[nt][hopsx].*"') - for interface in re.split('\n', interfaces_list): - # Sample output line from above cmd: - # 3: eth1 inet 10.0.2.10/24 scope global eth1 valid_lft forever ... - ifcfg = re.split(r'\s+', interface) - ifcfg_name = ifcfg[1] - ifcfg_ipaddr = ifcfg[3] - - # Filter out admin interface (device name is not known, match IP) - current_network = netaddr.IPNetwork(ifcfg_ipaddr) - if str(current_network.ip) == fuel['ADMIN_NETWORK']['ipaddress']: - continue - - # Read ifcfg-* network interface config file, write IFCFG_<IFNAME> - ifcfg_sec = 'IFCFG_%s' % ifcfg_name.upper() - fuel[ifcfg_sec] = {} - ifcfg_data = {} - ifcfg_f = ('/etc/sysconfig/network-scripts/ifcfg-%s' % ifcfg_name) - with open(ifcfg_f) as f: - for line in f: - if line.startswith('#'): - continue - (key, val) = line.split('=') - ifcfg_data[key.lower()] = val.rstrip() - - # Keep only needed info (e.g. filter-out type=Ethernet). - fuel[ifcfg_sec]['ipaddress'] = ifcfg_data['ipaddr'] - fuel[ifcfg_sec]['device'] = ifcfg_data['device'] - fuel[ifcfg_sec]['netmask'] = str(current_network.netmask) - fuel[ifcfg_sec]['gateway'] = ifcfg_data['gateway'] - - self.write_yaml(self.dea_file, {'fuel': fuel}) - - def reap_network_settings(self): - network_file = ('%s/network_%s.yaml' - % (self.temp_dir, self.env_id)) - data = self.read_yaml(network_file) - network = {} - network['networking_parameters'] = data['networking_parameters'] - network['networks'] = data['networks'] - for net in network['networks']: - del net['id'] - del net['group_id'] - self.write_yaml(self.dea_file, {'network': network}) - - def reap_settings(self): - settings_file = '%s/settings_%s.yaml' % (self.temp_dir, self.env_id) - settings = self.read_yaml(settings_file) - self.write_yaml(self.dea_file, {'settings': settings}) - - def get_interface(self, real_node_id): - exec_cmd('fuel node --node-id %s --network --download --dir %s' - % (real_node_id, self.temp_dir)) - interface_file = ('%s/node_%s/interfaces.yaml' - % (self.temp_dir, real_node_id)) - interfaces = self.read_yaml(interface_file) - interface_config = {} - pxe_mac = None - for interface in interfaces: - networks = [] - for network in interface['assigned_networks']: - networks.append(network['name']) - if network['name'] == 'fuelweb_admin': - pxe_mac = interface['mac'] - if networks: - interface_config[interface['name']] = networks - return interface_config, pxe_mac - - def read_yaml(self, yaml_file): - with open(yaml_file) as f: - data = yaml.load(f) - return data - - def intro(self): - delete(self.dea_file) - delete(self.dha_file) - - self.temp_dir = tempfile.mkdtemp() - date = time.strftime('%c') - self.write(self.dea_file, - DEA_1.format(date=date, comment=self.comment), False) - self.write(self.dha_file, - DHA_1.format(date=date, comment=self.comment)) - self.get_env() - - # Need to download deployment with explicit node ids - node_list = parse(exec_cmd('fuel node')) - real_node_ids = [node[N['id']] for node in node_list] - real_node_ids.sort() - self.download_node_config(','.join(real_node_ids)) - - self.download_config('settings') - self.download_config('network') - - def create_base_dea(self): - templater = templater.Templater(self.dea_file, - self.template, - self.base_dea) - templater.run() - - def finale(self): - log('DEA file is available at %s' % self.dea_file) - log('DHA file is available at %s (this is just a template)' - % self.dha_file) - if self.base_dea: - log('DEA base file is available at %s' % self.base_dea) - shutil.rmtree(self.temp_dir) - - def reap(self): - self.intro() - self.reap_environment_info() - self.reap_nodes_interfaces_transformations() - self.reap_fuel_settings() - self.reap_network_settings() - self.reap_settings() - if self.base_dea: - self.create_base_dea() - self.finale() - - -def parse_arguments(): - parser = ArgParser(prog='python %s' % __file__) - parser.add_argument('dea_file', nargs='?', action='store', - default='dea.yaml', - help='Deployment Environment Adapter: dea.yaml') - parser.add_argument('dha_file', nargs='?', action='store', - default='dha.yaml', - help='Deployment Hardware Adapter: dha.yaml') - parser.add_argument('comment', nargs='?', action='store', help='Comment') - parser.add_argument('-base_dea', - dest='base_dea', - help='Create specified base DEA file from "dea_file"') - parser.add_argument('-template', - dest='template', - nargs='?', - default='base_dea_template.yaml', - help='Base DEA is generated from this template') - args = parser.parse_args() - return (args.dea_file, - args.dha_file, - args.comment, - args.base_dea, - args.template) - - -def main(): - dea_file, dha_file, comment, base_dea, template = parse_arguments() - - r = Reap(dea_file, dha_file, comment, base_dea, template) - r.reap() - - -if __name__ == '__main__': - main() |