From 19306d660031133dd0dbb84393c1bde58ac2dd2b Mon Sep 17 00:00:00 2001 From: Andrew McLeod Date: Tue, 24 Sep 2019 16:25:53 +0200 Subject: [PATCH 1/9] WIP - add plumb_dataport_method --- zaza/openstack/configure/network.py | 11 ++++++ zaza/openstack/utilities/openstack.py | 55 +++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/zaza/openstack/configure/network.py b/zaza/openstack/configure/network.py index 68965d9..542c595 100755 --- a/zaza/openstack/configure/network.py +++ b/zaza/openstack/configure/network.py @@ -219,6 +219,17 @@ def setup_gateway_ext_port(network_config, keystone_session=None): dvr_mode=network_config.get("dvr_enabled", False), net_id=net_id) + current_release = openstack_utils.get_os_release() + bionic_queens = openstack_utils.get_os_release('bionic_queens') + if current_release >= bionic_queens: + logging.warn("Adding second interface for dataport to guest netplan, \ + for bionic-queens and later") + openstack_utils.plumb_guest_nic( + nova_client, + neutron_client, + dvr_mode=network_config.get("dvr_enabled", False), + net_id=net_id) + def run_from_cli(**kwargs): """Run network configurations from CLI. diff --git a/zaza/openstack/utilities/openstack.py b/zaza/openstack/utilities/openstack.py index 9b2e617..87c54ef 100644 --- a/zaza/openstack/utilities/openstack.py +++ b/zaza/openstack/utilities/openstack.py @@ -55,6 +55,7 @@ import sys import tempfile import tenacity import urllib +import textwrap from zaza import model from zaza.openstack.utilities import ( @@ -483,6 +484,60 @@ def get_admin_net(neutron_client): return net +def plumb_guest_nic(novaclient, neutronclient, + dvr_mode=None, net_id=None): + + """Add port associated with net_id to netplan + + :type net_id: string + """ + + if dvr_mode: + uuids = get_ovs_uuids() + else: + uuids = get_gateway_uuids() + + for uuid in uuids: + server = novaclient.servers.get(uuid) + ext_port_name = "{}_ext-port".format(server.name) + for port in neutronclient.list_ports(device_id=server.id)['ports']: + if port['name'] == ext_port_name: + logging.info('Adding second port to netplan in guest:\ + {}'.format(port['name'])) + mac_address = port['mac_address'] + if dvr_mode: + application_name = 'neutron-openvswitch' + else: + application_name = 'neutron-gateway' + unit_name = juju_utils.get_unit_name_from_ip_address( + server.ip, application_name) + interface = model.async_run_on_unit( + unit_name, "ip addr|grep\ + {}".format( + mac_address)).split("\n")[0].split(" ")[2] + body_value = textwrap.dedent("""\ + network: + ethernets: + {}: + dhcp4: false + dhcp6: true + optional: true + match: + macaddress: {} + set-name: {} + \n + version: 2 + """.format(interface, mac_address, interface)) + netplan_file = open("60-dataport.yaml", "w") + netplan_file.write(body_value) + netplan_file.close() + model.async_scp_to_unit(unit_name, './60-dataport.yaml', + '/etc/netplan/', user="root") + subprocess.call("rm 60-dataport.yaml") + model.async_run_on_unit(unit_name, "netplan apply", + user="root") + + def configure_gateway_ext_port(novaclient, neutronclient, dvr_mode=None, net_id=None): """Configure the neturong-gateway external port. From ab89054847f40b6fcbe5e919a732373bc6187db0 Mon Sep 17 00:00:00 2001 From: Andrew McLeod Date: Wed, 25 Sep 2019 16:08:20 +0200 Subject: [PATCH 2/9] enable guest interface plumbing for bionic-queens and later --- zaza/openstack/configure/network.py | 24 +++--- zaza/openstack/utilities/openstack.py | 102 ++++++++++++++------------ 2 files changed, 67 insertions(+), 59 deletions(-) diff --git a/zaza/openstack/configure/network.py b/zaza/openstack/configure/network.py index 542c595..50405c0 100755 --- a/zaza/openstack/configure/network.py +++ b/zaza/openstack/configure/network.py @@ -212,23 +212,23 @@ def setup_gateway_ext_port(network_config, keystone_session=None): else: net_id = None + # If we're using netplan, we need to add the new interface to the guest + current_release = openstack_utils.get_os_release() + bionic_queens = openstack_utils.get_os_release('bionic_queens') + if current_release >= bionic_queens: + logging.warn("Adding second interface for dataport to guest netplan " + "for bionic-queens and later") + plumb_guest_nic = True + else: + plumb_guest_nic = False + logging.info("Configuring network for OpenStack undercloud/provider") openstack_utils.configure_gateway_ext_port( nova_client, neutron_client, dvr_mode=network_config.get("dvr_enabled", False), - net_id=net_id) - - current_release = openstack_utils.get_os_release() - bionic_queens = openstack_utils.get_os_release('bionic_queens') - if current_release >= bionic_queens: - logging.warn("Adding second interface for dataport to guest netplan, \ - for bionic-queens and later") - openstack_utils.plumb_guest_nic( - nova_client, - neutron_client, - dvr_mode=network_config.get("dvr_enabled", False), - net_id=net_id) + net_id=net_id, + plumb_guest_nic=plumb_guest_nic) def run_from_cli(**kwargs): diff --git a/zaza/openstack/utilities/openstack.py b/zaza/openstack/utilities/openstack.py index 87c54ef..729f524 100644 --- a/zaza/openstack/utilities/openstack.py +++ b/zaza/openstack/utilities/openstack.py @@ -484,62 +484,67 @@ def get_admin_net(neutron_client): return net -def plumb_guest_nic(novaclient, neutronclient, - dvr_mode=None, net_id=None): +def _plumb_guest_nic(server_name, mac_address, dvr_mode=None): + """In guest server_name, add port with mac_address to netplan - """Add port associated with net_id to netplan - - :type net_id: string + :param server_name: Hostname of instance + :type server_name: string + :param mac_address: mac address of nic to be added to netplan + :type mac_address: string """ if dvr_mode: - uuids = get_ovs_uuids() + application_name = 'neutron-openvswitch' else: - uuids = get_gateway_uuids() + application_name = 'neutron-gateway' - for uuid in uuids: - server = novaclient.servers.get(uuid) - ext_port_name = "{}_ext-port".format(server.name) - for port in neutronclient.list_ports(device_id=server.id)['ports']: - if port['name'] == ext_port_name: - logging.info('Adding second port to netplan in guest:\ - {}'.format(port['name'])) - mac_address = port['mac_address'] - if dvr_mode: - application_name = 'neutron-openvswitch' - else: - application_name = 'neutron-gateway' - unit_name = juju_utils.get_unit_name_from_ip_address( - server.ip, application_name) - interface = model.async_run_on_unit( - unit_name, "ip addr|grep\ - {}".format( - mac_address)).split("\n")[0].split(" ")[2] - body_value = textwrap.dedent("""\ - network: - ethernets: - {}: - dhcp4: false - dhcp6: true - optional: true - match: - macaddress: {} - set-name: {} - \n - version: 2 - """.format(interface, mac_address, interface)) - netplan_file = open("60-dataport.yaml", "w") - netplan_file.write(body_value) - netplan_file.close() - model.async_scp_to_unit(unit_name, './60-dataport.yaml', - '/etc/netplan/', user="root") - subprocess.call("rm 60-dataport.yaml") - model.async_run_on_unit(unit_name, "netplan apply", - user="root") + unit_name = juju_utils.get_unit_name_from_host_name( + server_name, application_name) + + run_cmd_nic = "ip addr|grep {} -B1".format(mac_address) + interface = model.run_on_unit(unit_name, run_cmd_nic) + interface = interface['Stdout'].split(' ')[1].replace(':', '') + + run_cmd_netplan = """sudo egrep -iR '{}|{}' /etc/netplan/ + """.format(mac_address, interface) + + netplancfg = model.run_on_unit(unit_name, run_cmd_netplan) + + if (mac_address in str(netplancfg)) or (interface in str(netplancfg)): + logging.warn("mac address {} or nic {} already exists in " + "/etc/netplan".format(mac_address, interface)) + return + body_value = textwrap.dedent("""\ + network: + ethernets: + {0}: + dhcp4: false + dhcp6: true + optional: true + match: + macaddress: {1} + set-name: {0} + version: 2 + """.format(interface, mac_address)) + logging.debug("plumb guest interfae debug info:") + logging.debug("body_value: {}\nunit_name: {}\ninterface: {}\nmac_address:" + "{}\nserver_name: {}".format(body_value, unit_name, + interface, mac_address, + server_name)) + netplan_file = open("60-dataport.yaml", "w") + netplan_file.write(body_value) + netplan_file.close() + model.scp_to_unit(unit_name, './60-dataport.yaml', + '/home/ubuntu/', user="ubuntu") + run_cmd_mv = "sudo mv /home/ubuntu/60-dataport.yaml /etc/netplan" + model.run_on_unit(unit_name, run_cmd_mv) + subprocess.call(["rm", "60-dataport.yaml"]) + model.run_on_unit(unit_name, "sudo netplan apply") def configure_gateway_ext_port(novaclient, neutronclient, - dvr_mode=None, net_id=None): + dvr_mode=None, net_id=None, + plumb_guest_nic=False): """Configure the neturong-gateway external port. :param novaclient: Authenticated novaclient @@ -586,6 +591,9 @@ def configure_gateway_ext_port(novaclient, neutronclient, port = neutronclient.create_port(body=body_value) server.interface_attach(port_id=port['port']['id'], net_id=None, fixed_ip=None) + if plumb_guest_nic: + _plumb_guest_nic(server.name, mac_address=port['mac_address'], + dvr_mode=dvr_mode) ext_br_macs = [] for port in neutronclient.list_ports(network_id=net_id)['ports']: if 'ext-port' in port['name']: From 889053a3dfff0005ba3970de02dfdbefd39ab9af Mon Sep 17 00:00:00 2001 From: Andrew McLeod Date: Wed, 25 Sep 2019 16:14:37 +0200 Subject: [PATCH 3/9] fix docstring --- zaza/openstack/utilities/openstack.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/zaza/openstack/utilities/openstack.py b/zaza/openstack/utilities/openstack.py index 729f524..464d49c 100644 --- a/zaza/openstack/utilities/openstack.py +++ b/zaza/openstack/utilities/openstack.py @@ -485,14 +485,13 @@ def get_admin_net(neutron_client): def _plumb_guest_nic(server_name, mac_address, dvr_mode=None): - """In guest server_name, add port with mac_address to netplan + """In guest server_name, add port with mac_address to netplan. :param server_name: Hostname of instance :type server_name: string :param mac_address: mac address of nic to be added to netplan :type mac_address: string """ - if dvr_mode: application_name = 'neutron-openvswitch' else: From 36e9e45f0b6c35a20dbe10d32dcef2a8950c4cdb Mon Sep 17 00:00:00 2001 From: Andrew McLeod Date: Wed, 25 Sep 2019 16:17:08 +0200 Subject: [PATCH 4/9] add dvr_mode to docstring --- zaza/openstack/utilities/openstack.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zaza/openstack/utilities/openstack.py b/zaza/openstack/utilities/openstack.py index 464d49c..3eae559 100644 --- a/zaza/openstack/utilities/openstack.py +++ b/zaza/openstack/utilities/openstack.py @@ -491,6 +491,8 @@ def _plumb_guest_nic(server_name, mac_address, dvr_mode=None): :type server_name: string :param mac_address: mac address of nic to be added to netplan :type mac_address: string + :param dvr_mode: Using DVR mode or not + :type dvr_mode: boolean """ if dvr_mode: application_name = 'neutron-openvswitch' From 48a410151efcff47cbfa1b0be137528d922783d6 Mon Sep 17 00:00:00 2001 From: Andrew McLeod Date: Wed, 25 Sep 2019 16:19:12 +0200 Subject: [PATCH 5/9] fix typo --- zaza/openstack/utilities/openstack.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zaza/openstack/utilities/openstack.py b/zaza/openstack/utilities/openstack.py index 3eae559..dd0fd42 100644 --- a/zaza/openstack/utilities/openstack.py +++ b/zaza/openstack/utilities/openstack.py @@ -527,7 +527,7 @@ def _plumb_guest_nic(server_name, mac_address, dvr_mode=None): set-name: {0} version: 2 """.format(interface, mac_address)) - logging.debug("plumb guest interfae debug info:") + logging.debug("plumb guest interface debug info:") logging.debug("body_value: {}\nunit_name: {}\ninterface: {}\nmac_address:" "{}\nserver_name: {}".format(body_value, unit_name, interface, mac_address, From 028602f3659ed97b23971c14c6c03d7f4ba148dc Mon Sep 17 00:00:00 2001 From: Andrew McLeod Date: Thu, 26 Sep 2019 13:47:19 +0200 Subject: [PATCH 6/9] change terminology from plumb --- zaza/openstack/configure/network.py | 6 +++--- zaza/openstack/utilities/openstack.py | 13 +++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/zaza/openstack/configure/network.py b/zaza/openstack/configure/network.py index 50405c0..55bcdf3 100755 --- a/zaza/openstack/configure/network.py +++ b/zaza/openstack/configure/network.py @@ -218,9 +218,9 @@ def setup_gateway_ext_port(network_config, keystone_session=None): if current_release >= bionic_queens: logging.warn("Adding second interface for dataport to guest netplan " "for bionic-queens and later") - plumb_guest_nic = True + add_dataport_to_netplan = True else: - plumb_guest_nic = False + add_dataport_to_netplan = False logging.info("Configuring network for OpenStack undercloud/provider") openstack_utils.configure_gateway_ext_port( @@ -228,7 +228,7 @@ def setup_gateway_ext_port(network_config, keystone_session=None): neutron_client, dvr_mode=network_config.get("dvr_enabled", False), net_id=net_id, - plumb_guest_nic=plumb_guest_nic) + add_dataport_to_netplan=add_dataport_to_netplan) def run_from_cli(**kwargs): diff --git a/zaza/openstack/utilities/openstack.py b/zaza/openstack/utilities/openstack.py index dd0fd42..94e86a8 100644 --- a/zaza/openstack/utilities/openstack.py +++ b/zaza/openstack/utilities/openstack.py @@ -484,8 +484,8 @@ def get_admin_net(neutron_client): return net -def _plumb_guest_nic(server_name, mac_address, dvr_mode=None): - """In guest server_name, add port with mac_address to netplan. +def add_interface_to_netplan(server_name, mac_address, dvr_mode=None): + """In guest server_name, add nic with mac_address to netplan. :param server_name: Hostname of instance :type server_name: string @@ -545,7 +545,7 @@ def _plumb_guest_nic(server_name, mac_address, dvr_mode=None): def configure_gateway_ext_port(novaclient, neutronclient, dvr_mode=None, net_id=None, - plumb_guest_nic=False): + add_dataport_to_netplan=False): """Configure the neturong-gateway external port. :param novaclient: Authenticated novaclient @@ -592,9 +592,10 @@ def configure_gateway_ext_port(novaclient, neutronclient, port = neutronclient.create_port(body=body_value) server.interface_attach(port_id=port['port']['id'], net_id=None, fixed_ip=None) - if plumb_guest_nic: - _plumb_guest_nic(server.name, mac_address=port['mac_address'], - dvr_mode=dvr_mode) + if add_dataport_to_netplan: + add_interface_to_netplan(server.name, + mac_address=port['mac_address'], + dvr_mode=dvr_mode) ext_br_macs = [] for port in neutronclient.list_ports(network_id=net_id)['ports']: if 'ext-port' in port['name']: From 6f903b73a6ea6d71d0deb4556de65b69901b9f6d Mon Sep 17 00:00:00 2001 From: Andrew McLeod Date: Thu, 26 Sep 2019 13:59:59 +0200 Subject: [PATCH 7/9] fix interface and mac address matching --- zaza/openstack/utilities/openstack.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zaza/openstack/utilities/openstack.py b/zaza/openstack/utilities/openstack.py index 94e86a8..e966716 100644 --- a/zaza/openstack/utilities/openstack.py +++ b/zaza/openstack/utilities/openstack.py @@ -502,11 +502,11 @@ def add_interface_to_netplan(server_name, mac_address, dvr_mode=None): unit_name = juju_utils.get_unit_name_from_host_name( server_name, application_name) - run_cmd_nic = "ip addr|grep {} -B1".format(mac_address) + run_cmd_nic = "ip -f link -br -o addr|grep {}".format(mac_address) interface = model.run_on_unit(unit_name, run_cmd_nic) - interface = interface['Stdout'].split(' ')[1].replace(':', '') + interface = interface['Stdout'].split(' ')[0] - run_cmd_netplan = """sudo egrep -iR '{}|{}' /etc/netplan/ + run_cmd_netplan = """sudo egrep -iR '{}|{}$' /etc/netplan/ """.format(mac_address, interface) netplancfg = model.run_on_unit(unit_name, run_cmd_netplan) From 1af831399a8f84f432318602aa7eac2e965c1e98 Mon Sep 17 00:00:00 2001 From: Andrew McLeod Date: Thu, 26 Sep 2019 14:16:19 +0200 Subject: [PATCH 8/9] add context manager for netplan_file --- zaza/openstack/utilities/openstack.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/zaza/openstack/utilities/openstack.py b/zaza/openstack/utilities/openstack.py index e966716..4acdc00 100644 --- a/zaza/openstack/utilities/openstack.py +++ b/zaza/openstack/utilities/openstack.py @@ -532,15 +532,14 @@ def add_interface_to_netplan(server_name, mac_address, dvr_mode=None): "{}\nserver_name: {}".format(body_value, unit_name, interface, mac_address, server_name)) - netplan_file = open("60-dataport.yaml", "w") - netplan_file.write(body_value) - netplan_file.close() - model.scp_to_unit(unit_name, './60-dataport.yaml', - '/home/ubuntu/', user="ubuntu") - run_cmd_mv = "sudo mv /home/ubuntu/60-dataport.yaml /etc/netplan" - model.run_on_unit(unit_name, run_cmd_mv) - subprocess.call(["rm", "60-dataport.yaml"]) - model.run_on_unit(unit_name, "sudo netplan apply") + with tempfile.NamedTemporaryFile(mode="w") as netplan_file: + netplan_file.write(body_value) + netplan_file.flush() + model.scp_to_unit(unit_name, netplan_file.name, + '/home/ubuntu/60-dataport.yaml', user="ubuntu") + run_cmd_mv = "sudo mv /home/ubuntu/60-dataport.yaml /etc/netplan/" + model.run_on_unit(unit_name, run_cmd_mv) + model.run_on_unit(unit_name, "sudo netplan apply") def configure_gateway_ext_port(novaclient, neutronclient, From 5ad18dfc2fddbecbbbcb9d2d7d07943b0c50ab0a Mon Sep 17 00:00:00 2001 From: Andrew McLeod Date: Thu, 26 Sep 2019 14:19:37 +0200 Subject: [PATCH 9/9] fix context mgr --- zaza/openstack/utilities/openstack.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zaza/openstack/utilities/openstack.py b/zaza/openstack/utilities/openstack.py index 4acdc00..3956063 100644 --- a/zaza/openstack/utilities/openstack.py +++ b/zaza/openstack/utilities/openstack.py @@ -537,9 +537,9 @@ def add_interface_to_netplan(server_name, mac_address, dvr_mode=None): netplan_file.flush() model.scp_to_unit(unit_name, netplan_file.name, '/home/ubuntu/60-dataport.yaml', user="ubuntu") - run_cmd_mv = "sudo mv /home/ubuntu/60-dataport.yaml /etc/netplan/" - model.run_on_unit(unit_name, run_cmd_mv) - model.run_on_unit(unit_name, "sudo netplan apply") + run_cmd_mv = "sudo mv /home/ubuntu/60-dataport.yaml /etc/netplan/" + model.run_on_unit(unit_name, run_cmd_mv) + model.run_on_unit(unit_name, "sudo netplan apply") def configure_gateway_ext_port(novaclient, neutronclient,