X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=deploy%2Freap.py;h=eb02fe25d5eed22e7585cb11f1d3b0446897af98;hb=71f990b9dbc92d34c6e25d7175db988d14b56c06;hp=b7080cdaead330ee58f4d958cf76334a651d9392;hpb=24a95306d2564b272b5320e9149d9aea70b4061c;p=fuel.git diff --git a/deploy/reap.py b/deploy/reap.py index b7080cdae..eb02fe25d 100644 --- a/deploy/reap.py +++ b/deploy/reap.py @@ -1,6 +1,8 @@ +#!/usr/bin/python ############################################################################### -# Copyright (c) 2015 Ericsson AB and others. +# 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 @@ -13,6 +15,9 @@ import os import yaml import glob import shutil +import tempfile +import re +import netaddr from common import ( N, @@ -55,6 +60,8 @@ adapter: # ipmiIp # ipmiUser # ipmiPass +# and you *MAY* provide (optional, not added by reap.py): +# ipmiPort # - libvirt adapter you need to provide: # libvirtName: # libvirtTemplate: [libvirt/vms/controller.xml | libvirt/vms/compute.xml] @@ -72,17 +79,21 @@ DHA_2 = ''' # which may not be correct - please adjust as needed. ''' -DISKS = {'fuel': '30G', - 'controller': '30G', - 'compute': '30G'} +TEMPLATER = 'templater.py' + +DISKS = {'fuel': '100G', + 'controller': '100G', + 'compute': '100G'} class Reap(object): - def __init__(self, dea_file, dha_file, comment): + 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 @@ -90,8 +101,10 @@ class Reap(object): def get_env(self): env_list = parse(exec_cmd('fuel env')) - if len(env_list) > 1: - err('Not exactly one environment') + 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']] @@ -101,6 +114,12 @@ class Reap(object): 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: @@ -127,9 +146,8 @@ class Reap(object): 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_%s.yaml' - % (self.temp_dir, self.env_id, - main_role, node_id)) + 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) @@ -152,7 +170,6 @@ class Reap(object): real_node_ids = [node[N['id']] for node in node_list] real_node_ids.sort() min_node = real_node_ids[0] - interfaces = {} transformations = {} dea_nodes = [] @@ -169,6 +186,7 @@ class Reap(object): '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( @@ -212,9 +230,9 @@ class Reap(object): 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']], - 'mode': self.env[E['mode']], 'net_segment_type': network['networking_parameters']['segmentation_type']}} self.write_yaml(self.dea_file, env) @@ -235,8 +253,42 @@ class Reap(object): fuel[key] = data[key] for key in fuel['ADMIN_NETWORK'].keys(): if key not in ['ipaddress', 'netmask', - 'dhcp_pool_start', 'dhcp_pool_end']: + '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_ + 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): @@ -282,21 +334,34 @@ class Reap(object): def intro(self): delete(self.dea_file) delete(self.dha_file) - self.temp_dir = exec_cmd('mktemp -d') + + 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() - self.download_config('deployment') + + # 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): + exec_cmd('python %s %s %s %s' + % (TEMPLATER, self.dea_file, self.template, self.base_dea)) + 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): @@ -306,16 +371,11 @@ class Reap(object): self.reap_fuel_settings() self.reap_network_settings() self.reap_settings() + if self.base_dea: + self.create_base_dea() self.finale() -def usage(): - print ''' - Usage: - python reap.py - ''' - - def parse_arguments(): parser = ArgParser(prog='python %s' % __file__) parser.add_argument('dea_file', nargs='?', action='store', @@ -325,14 +385,26 @@ def parse_arguments(): 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) + return (args.dea_file, + args.dha_file, + args.comment, + args.base_dea, + args.template) def main(): - dea_file, dha_file, comment = parse_arguments() + dea_file, dha_file, comment, base_dea, template = parse_arguments() - r = Reap(dea_file, dha_file, comment) + r = Reap(dea_file, dha_file, comment, base_dea, template) r.reap()