From f4d388ea508ba00771e43a219ac64e0d430b73bd Mon Sep 17 00:00:00 2001 From: Tim Rozet Date: Sun, 25 Jun 2017 21:25:36 -0400 Subject: Migrates Apex to Python Removes all bash libraries and converts almost all of the code to a mixture of Python and Ansible. utils.sh and clean.sh still exist. clean.sh will be migrated fully to clean.py in another patch. The Apex Python package is now built into the opnfv-apex-common RPM. To install locally do 'pip3 install .'. To deploy: opnfv-deploy -d -n --image-dir /root/apex/.build -v --debug Non-python files (THT yaml, settings files, ansible playbooks) are all installed into /usr/share/opnfv-apex/. The RPM will copy settings files into /etc/opnfv-apex/. JIRA: APEX-317 Change-Id: I3232f0329bcd13bce5a28da6a8c9c84d0b048024 Signed-off-by: Tim Rozet --- apex/network/jumphost.py | 172 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 apex/network/jumphost.py (limited to 'apex/network/jumphost.py') diff --git a/apex/network/jumphost.py b/apex/network/jumphost.py new file mode 100644 index 00000000..81562c7a --- /dev/null +++ b/apex/network/jumphost.py @@ -0,0 +1,172 @@ +############################################################################## +# Copyright (c) 2017 Tim Rozet (trozet@redhat.com) 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 os +import re +import shutil +import subprocess + +from apex.common.exceptions import ApexDeployException +from apex.network import ip_utils + +NET_MAP = { + 'admin': 'br-admin', + 'tenant': 'br-tenant', + 'external': 'br-external', + 'storage': 'br-storage', + 'api': 'br-api' +} + + +def configure_bridges(ns): + """ + Configures IP on jumphost bridges + :param ns: network_settings + :return: None + """ + bridge_networks = ['admin'] + if 'external' in ns.enabled_network_list: + bridge_networks.append('external') + for network in bridge_networks: + if network == 'external': + net_config = ns['networks'][network][0] + else: + net_config = ns['networks'][network] + cidr = net_config['cidr'] + interface = ip_utils.get_interface(NET_MAP[network], cidr.version) + + if interface: + logging.info("Bridge {} already configured with IP: {}".format( + NET_MAP[network], interface.ip)) + else: + logging.info("Will configure IP for {}".format(NET_MAP[network])) + ovs_ip = net_config['overcloud_ip_range'][1] + if cidr.version == 6: + ipv6_br_path = "/proc/sys/net/ipv6/conf/{}/disable_" \ + "ipv6".format(NET_MAP[network]) + try: + subprocess.check_call('echo', 0, '>', ipv6_br_path) + except subprocess.CalledProcessError: + logging.error("Unable to enable ipv6 on " + "bridge {}".format(NET_MAP[network])) + raise + try: + ip_prefix = "{}/{}".format(ovs_ip, cidr.prefixlen) + subprocess.check_call(['ip', 'addr', 'add', ip_prefix, 'dev', + NET_MAP[network]]) + subprocess.check_call(['ip', 'link', 'set', 'up', NET_MAP[ + network]]) + logging.info("IP configured: {} on bridge {}".format(ovs_ip, + NET_MAP[network])) + except subprocess.CalledProcessError: + logging.error("Unable to configure IP address on " + "bridge {}".format(NET_MAP[network])) + + +def attach_interface_to_ovs(bridge, interface, network): + """ + Attaches jumphost interface to OVS for baremetal deployments + :param bridge: bridge to attach to + :param interface: interface to attach to bridge + :param network: Apex network type for these interfaces + :return: None + """ + + net_cfg_path = '/etc/sysconfig/network-scripts' + if_file = os.path.join(net_cfg_path, "ifcfg-{}".format(interface)) + ovs_file = os.path.join(net_cfg_path, "ifcfg-{}".format(bridge)) + + logging.info("Attaching interface: {} to bridge: {} on network {}".format( + bridge, interface, network + )) + + try: + output = subprocess.check_output(['ovs-vsctl', 'list-ports', bridge], + stderr=subprocess.STDOUT) + if bridge in output: + logging.debug("Interface already attached to bridge") + return + except subprocess.CalledProcessError as e: + logging.error("Unable to dump ports for bridge: {}".format(bridge)) + logging.error("Error output: {}".format(e.output)) + raise + + if not os.path.isfile(if_file): + logging.error("Interface ifcfg not found: {}".format(if_file)) + raise FileNotFoundError("Interface file missing: {}".format(if_file)) + + ifcfg_params = { + 'IPADDR': '', + 'NETMASK': '', + 'GATEWAY': '', + 'METRIC': '', + 'DNS1': '', + 'DNS2': '', + 'PREFIX': '' + } + with open(if_file, 'r') as fh: + interface_output = fh.read() + + for param in ifcfg_params.keys(): + match = re.search("{}=(.*)\n".format(param), interface_output) + if match: + ifcfg_params[param] = match.group(1) + + if not ifcfg_params['IPADDR']: + logging.error("IPADDR missing in {}".format(if_file)) + raise ApexDeployException("IPADDR missing in {}".format(if_file)) + if not (ifcfg_params['NETMASK'] or ifcfg_params['PREFIX']): + logging.error("NETMASK/PREFIX missing in {}".format(if_file)) + raise ApexDeployException("NETMASK/PREFIX missing in {}".format( + if_file)) + if network == 'external' and not ifcfg_params['GATEWAY']: + logging.error("GATEWAY is required to be in {} for external " + "network".format(if_file)) + raise ApexDeployException("GATEWAY is required to be in {} for " + "external network".format(if_file)) + + shutil.move(if_file, "{}.orig".format(if_file)) + if_content = """DEVICE={} +DEVICETYPE=ovs +TYPE=OVSPort +PEERDNS=no +BOOTPROTO=static +NM_CONTROLLED=no +ONBOOT=yes +OVS_BRIDGE={} +PROMISC=yes""".format(interface, bridge) + + bridge_content = """DEVICE={} +DEVICETYPE=ovs +BOOTPROTO=static +ONBOOT=yes +TYPE=OVSBridge +PROMISC=yes""".format(bridge) + peer_dns = 'no' + for param, value in ifcfg_params.items(): + if value: + bridge_content += "\n{}={}".format(param, value) + if param == 'DNS1' or param == 'DNS2': + peer_dns = 'yes' + bridge_content += "\n{}={}".format('PEERDNS', peer_dns) + + logging.debug("New interface file content:\n{}".format(if_content)) + logging.debug("New bridge file content:\n{}".format(bridge_content)) + with open(if_file, 'w') as fh: + fh.write(if_content) + with open(ovs_file, 'w') as fh: + fh.write(bridge_content) + logging.info("New network ifcfg files written") + logging.info("Restarting Linux networking") + try: + subprocess.check_call(['systemctl', 'restart', 'network']) + except subprocess.CalledProcessError: + logging.error("Failed to restart Linux networking") + raise -- cgit 1.2.3-korg