+#!/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
import yaml
import glob
import shutil
+import tempfile
+import re
+import netaddr
+import templater
from common import (
N,
# 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]
# which may not be correct - please adjust as needed.
'''
-DISKS = {'fuel': '30G',
- 'controller': '30G',
- 'compute': '30G'}
+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
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']]
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:
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)
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 = []
'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(
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)
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_<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):
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):
+ 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.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 <dea_file> <dha_file> <comment>
- '''
-
-
def parse_arguments():
parser = ArgParser(prog='python %s' % __file__)
parser.add_argument('dea_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)
+ 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()