1 ##############################################################################
2 # Copyright (c) 2017 Tim Rozet (trozet@redhat.com) 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 ##############################################################################
16 from apex.common.exceptions import ApexDeployException
17 from apex.network import ip_utils
21 'tenant': 'br-tenant',
22 'external': 'br-external',
23 'storage': 'br-storage',
28 def configure_bridges(ns):
30 Configures IP on jumphost bridges
31 :param ns: network_settings
34 bridge_networks = ['admin']
35 if 'external' in ns.enabled_network_list:
36 bridge_networks.append('external')
37 for network in bridge_networks:
38 if network == 'external':
39 net_config = ns['networks'][network][0]
41 net_config = ns['networks'][network]
42 cidr = net_config['cidr']
43 interface = ip_utils.get_interface(NET_MAP[network], cidr.version)
46 logging.info("Bridge {} already configured with IP: {}".format(
47 NET_MAP[network], interface.ip))
49 logging.info("Will configure IP for {}".format(NET_MAP[network]))
50 ovs_ip = net_config['overcloud_ip_range'][1]
52 ipv6_br_path = "/proc/sys/net/ipv6/conf/{}/disable_" \
53 "ipv6".format(NET_MAP[network])
55 subprocess.check_call('echo', 0, '>', ipv6_br_path)
56 except subprocess.CalledProcessError:
57 logging.error("Unable to enable ipv6 on "
58 "bridge {}".format(NET_MAP[network]))
61 ip_prefix = "{}/{}".format(ovs_ip, cidr.prefixlen)
62 subprocess.check_call(['ip', 'addr', 'add', ip_prefix, 'dev',
64 subprocess.check_call(['ip', 'link', 'set', 'up', NET_MAP[
66 logging.info("IP configured: {} on bridge {}".format(ovs_ip,
68 except subprocess.CalledProcessError:
69 logging.error("Unable to configure IP address on "
70 "bridge {}".format(NET_MAP[network]))
73 def attach_interface_to_ovs(bridge, interface, network):
75 Attaches jumphost interface to OVS for baremetal deployments
76 :param bridge: bridge to attach to
77 :param interface: interface to attach to bridge
78 :param network: Apex network type for these interfaces
82 net_cfg_path = '/etc/sysconfig/network-scripts'
83 if_file = os.path.join(net_cfg_path, "ifcfg-{}".format(interface))
84 ovs_file = os.path.join(net_cfg_path, "ifcfg-{}".format(bridge))
86 logging.info("Attaching interface: {} to bridge: {} on network {}".format(
87 bridge, interface, network
91 output = subprocess.check_output(['ovs-vsctl', 'show'],
92 stderr=subprocess.STDOUT)
93 if bridge not in output.decode('utf-8'):
94 logging.debug("Bridge {} not found. Creating...".format(bridge))
95 subprocess.check_call(['ovs-vsctl', 'add-br', bridge])
97 logging.debug("Bridge {} found".format(bridge))
98 except subprocess.CalledProcessError:
99 logging.error("Unable to validate/create OVS bridge {}".format(bridge))
102 output = subprocess.check_output(['ovs-vsctl', 'list-ports', bridge],
103 stderr=subprocess.STDOUT)
104 if interface in output.decode('utf-8'):
105 logging.debug("Interface already attached to bridge")
107 except subprocess.CalledProcessError as e:
108 logging.error("Unable to dump ports for bridge: {}".format(bridge))
109 logging.error("Error output: {}".format(e.output))
112 if not os.path.isfile(if_file):
113 logging.error("Interface ifcfg not found: {}".format(if_file))
114 raise FileNotFoundError("Interface file missing: {}".format(if_file))
125 with open(if_file, 'r') as fh:
126 interface_output = fh.read()
128 for param in ifcfg_params.keys():
129 match = re.search("{}=(.*)\n".format(param), interface_output)
131 ifcfg_params[param] = match.group(1)
133 if not ifcfg_params['IPADDR']:
134 logging.error("IPADDR missing in {}".format(if_file))
135 raise ApexDeployException("IPADDR missing in {}".format(if_file))
136 if not (ifcfg_params['NETMASK'] or ifcfg_params['PREFIX']):
137 logging.error("NETMASK/PREFIX missing in {}".format(if_file))
138 raise ApexDeployException("NETMASK/PREFIX missing in {}".format(
140 if network == 'external' and not ifcfg_params['GATEWAY']:
141 logging.error("GATEWAY is required to be in {} for external "
142 "network".format(if_file))
143 raise ApexDeployException("GATEWAY is required to be in {} for "
144 "external network".format(if_file))
146 shutil.move(if_file, "{}.orig".format(if_file))
147 if_content = """DEVICE={}
155 PROMISC=yes""".format(interface, bridge)
157 bridge_content = """DEVICE={}
162 PROMISC=yes""".format(bridge)
164 for param, value in ifcfg_params.items():
166 bridge_content += "\n{}={}".format(param, value)
167 if param == 'DNS1' or param == 'DNS2':
169 bridge_content += "\n{}={}".format('PEERDNS', peer_dns)
171 logging.debug("New interface file content:\n{}".format(if_content))
172 logging.debug("New bridge file content:\n{}".format(bridge_content))
173 with open(if_file, 'w') as fh:
175 with open(ovs_file, 'w') as fh:
176 fh.write(bridge_content)
177 logging.info("New network ifcfg files written")
178 logging.info("Restarting Linux networking")
180 subprocess.check_call(['systemctl', 'restart', 'network'])
181 except subprocess.CalledProcessError:
182 logging.error("Failed to restart Linux networking")