def test_update_vpp_mapping(self):
        tmpdir = tempfile.mkdtemp()
        vpp_exec_path = os.path.join(tmpdir, 'vpp-exec')
        utils._VPP_EXEC_FILE = vpp_exec_path

        def test_get_dpdk_map():
            return [{
                'name': 'eth1',
                'pci_address': '0000:00:09.0',
                'mac_address': '01:02:03:04:05:06',
                'driver': 'vfio-pci'
            }]

        self.stub_out('os_net_config.utils._get_dpdk_map', test_get_dpdk_map)

        def test_execute(name, *args, **kwargs):
            return None, None

        self.stub_out('oslo_concurrency.processutils.execute', test_execute)

        def test_get_vpp_interface(pci_dev, tries, timeout):
            return {'name': 'GigabitEthernet0/9/0', 'index': '1'}

        self.stub_out('os_net_config.utils._get_vpp_interface',
                      test_get_vpp_interface)

        int1 = objects.VppInterface('eth1', options="vlan-strip-offload off")
        int1.pci_dev = '0000:00:09.0'
        int1.hwaddr = '01:02:03:04:05:06'
        int2 = objects.VppInterface('eth2')
        int2.pci_dev = '0000:00:09.1'
        int2.hwaddr = '01:02:03:04:05:07'
        interfaces = [int1, int2]

        utils.update_vpp_mapping(interfaces, [])

        contents = utils.get_file_data(utils._DPDK_MAPPING_FILE)

        dpdk_test = [{
            'name': 'eth1',
            'pci_address': '0000:00:09.0',
            'mac_address': '01:02:03:04:05:06',
            'driver': 'vfio-pci'
        }, {
            'name': 'eth2',
            'pci_address': '0000:00:09.1',
            'mac_address': '01:02:03:04:05:07',
            'driver': 'vfio-pci'
        }]
        dpdk_map = yaml.safe_load(contents) if contents else []
        self.assertEqual(2, len(dpdk_map))
        self.assertListEqual(dpdk_test, dpdk_map)
Example #2
0
    def test_update_vpp_mapping(self):
        def test_get_dpdk_map():
            return [{
                'name': 'eth1',
                'pci_address': '0000:00:09.0',
                'mac_address': '01:02:03:04:05:06',
                'driver': 'vfio-pci'
            }]

        self.stubs.Set(utils, '_get_dpdk_map', test_get_dpdk_map)

        def test_execute(name, dummy1, dummy2=None, dummy3=None):
            return None, None

        self.stubs.Set(processutils, 'execute', test_execute)

        def test_get_vpp_interface_name(pci_dev, tries, timeout):
            return 'GigabitEthernet0/9/0'

        self.stubs.Set(utils, '_get_vpp_interface_name',
                       test_get_vpp_interface_name)

        int1 = objects.VppInterface('eth1', options="vlan-strip-offload off")
        int1.pci_dev = '0000:00:09.0'
        int1.hwaddr = '01:02:03:04:05:06'
        int2 = objects.VppInterface('eth2')
        int2.pci_dev = '0000:00:09.1'
        int2.hwaddr = '01:02:03:04:05:07'
        interfaces = [int1, int2]

        utils.update_vpp_mapping(interfaces)

        contents = utils.get_file_data(utils._DPDK_MAPPING_FILE)

        dpdk_test = [{
            'name': 'eth1',
            'pci_address': '0000:00:09.0',
            'mac_address': '01:02:03:04:05:06',
            'driver': 'vfio-pci'
        }, {
            'name': 'eth2',
            'pci_address': '0000:00:09.1',
            'mac_address': '01:02:03:04:05:07',
            'driver': 'vfio-pci'
        }]
        dpdk_map = yaml.load(contents) if contents else []
        self.assertEqual(2, len(dpdk_map))
        self.assertListEqual(dpdk_test, dpdk_map)
Example #3
0
    def test_update_vpp_mapping(self):
        tmpdir = tempfile.mkdtemp()
        vpp_exec_path = os.path.join(tmpdir, 'vpp-exec')
        utils._VPP_EXEC_FILE = vpp_exec_path

        def test_get_dpdk_map():
            return [{'name': 'eth1', 'pci_address': '0000:00:09.0',
                     'mac_address': '01:02:03:04:05:06',
                     'driver': 'vfio-pci'}]

        self.stub_out('os_net_config.utils._get_dpdk_map', test_get_dpdk_map)

        def test_execute(name, *args, **kwargs):
            return None, None
        self.stub_out('oslo_concurrency.processutils.execute', test_execute)

        def test_get_vpp_interface(pci_dev, tries, timeout):
            return {'name': 'GigabitEthernet0/9/0', 'index': '1'}

        self.stub_out('os_net_config.utils._get_vpp_interface',
                      test_get_vpp_interface)

        int1 = objects.VppInterface('eth1', options="vlan-strip-offload off")
        int1.pci_dev = '0000:00:09.0'
        int1.hwaddr = '01:02:03:04:05:06'
        int2 = objects.VppInterface('eth2')
        int2.pci_dev = '0000:00:09.1'
        int2.hwaddr = '01:02:03:04:05:07'
        interfaces = [int1, int2]

        utils.update_vpp_mapping(interfaces, [])

        contents = utils.get_file_data(utils._DPDK_MAPPING_FILE)

        dpdk_test = [{'name': 'eth1', 'pci_address': '0000:00:09.0',
                      'mac_address': '01:02:03:04:05:06',
                      'driver': 'vfio-pci'},
                     {'name': 'eth2', 'pci_address': '0000:00:09.1',
                      'mac_address': '01:02:03:04:05:07',
                      'driver': 'vfio-pci'}]
        dpdk_map = yaml.safe_load(contents) if contents else []
        self.assertEqual(2, len(dpdk_map))
        self.assertListEqual(dpdk_test, dpdk_map)
Example #4
0
    def apply(self, cleanup=False, activate=True):
        """Apply the network configuration.

        :param cleanup: A boolean which indicates whether any undefined
            (existing but not present in the object model) interface
            should be disabled and deleted.
        :param activate: A boolean which indicates if the config should
            be activated by stopping/starting interfaces
            NOTE: if cleanup is specified we will deactivate interfaces even
            if activate is false
        :returns: a dict of the format: filename/data which contains info
            for each file that was changed (or would be changed if in --noop
            mode).
        Note the noop mode is set via the constructor noop boolean
        """
        logger.info('applying network configs...')
        restart_interfaces = []
        restart_vlans = []
        restart_bridges = []
        restart_linux_bonds = []
        restart_linux_teams = []
        restart_vpp = False
        update_files = {}
        all_file_names = []
        ivs_uplinks = []  # ivs physical uplinks
        ivs_interfaces = []  # ivs internal ports
        nfvswitch_interfaces = []       # nfvswitch physical interfaces
        nfvswitch_internal_ifaces = []  # nfvswitch internal/management ports
        stop_dhclient_interfaces = []
        ovs_needs_restart = False
        vpp_interfaces = self.vpp_interface_data.values()

        for interface_name, iface_data in self.interface_data.items():
            route_data = self.route_data.get(interface_name, '')
            route6_data = self.route6_data.get(interface_name, '')
            interface_path = self.root_dir + ifcfg_config_path(interface_name)
            route_path = self.root_dir + route_config_path(interface_name)
            route6_path = self.root_dir + route6_config_path(interface_name)
            all_file_names.append(interface_path)
            all_file_names.append(route_path)
            all_file_names.append(route6_path)
            if "IVS_BRIDGE" in iface_data:
                ivs_uplinks.append(interface_name)
            if "NFVSWITCH_BRIDGE" in iface_data:
                nfvswitch_interfaces.append(interface_name)
            all_file_names.append(route6_path)
            if (utils.diff(interface_path, iface_data) or
                    utils.diff(route_path, route_data) or
                    utils.diff(route6_path, route6_data)):
                restart_interfaces.append(interface_name)
                restart_interfaces.extend(self.child_members(interface_name))
                update_files[interface_path] = iface_data
                update_files[route_path] = route_data
                update_files[route6_path] = route6_data
                if "BOOTPROTO=dhcp" not in iface_data:
                    stop_dhclient_interfaces.append(interface_name)
                # Openvswitch needs to be restarted when OVSDPDKPort or
                # OVSDPDKBond is added
                if "OVSDPDK" in iface_data:
                    ovs_needs_restart = True

            else:
                logger.info('No changes required for interface: %s' %
                            interface_name)

        for interface_name, iface_data in self.ivsinterface_data.items():
            route_data = self.route_data.get(interface_name, '')
            route6_data = self.route6_data.get(interface_name, '')
            interface_path = self.root_dir + ifcfg_config_path(interface_name)
            route_path = self.root_dir + route_config_path(interface_name)
            route6_path = self.root_dir + route6_config_path(interface_name)
            all_file_names.append(interface_path)
            all_file_names.append(route_path)
            all_file_names.append(route6_path)
            ivs_interfaces.append(interface_name)
            if (utils.diff(interface_path, iface_data) or
                    utils.diff(route_path, route_data)):
                restart_interfaces.append(interface_name)
                restart_interfaces.extend(self.child_members(interface_name))
                update_files[interface_path] = iface_data
                update_files[route_path] = route_data
                update_files[route6_path] = route6_data
            else:
                logger.info('No changes required for ivs interface: %s' %
                            interface_name)

        for iface_name, iface_data in self.nfvswitch_intiface_data.items():
            route_data = self.route_data.get(iface_name, '')
            route6_data = self.route6_data.get(iface_name, '')
            iface_path = self.root_dir + ifcfg_config_path(iface_name)
            route_path = self.root_dir + route_config_path(iface_name)
            route6_path = self.root_dir + route6_config_path(iface_name)
            all_file_names.append(iface_path)
            all_file_names.append(route_path)
            all_file_names.append(route6_path)
            nfvswitch_internal_ifaces.append(iface_name)
            if (utils.diff(iface_path, iface_data) or
                    utils.diff(route_path, route_data)):
                restart_interfaces.append(iface_name)
                restart_interfaces.extend(self.child_members(iface_name))
                update_files[iface_path] = iface_data
                update_files[route_path] = route_data
                update_files[route6_path] = route6_data
            else:
                logger.info('No changes required for nfvswitch interface: %s' %
                            iface_name)

        for vlan_name, vlan_data in self.vlan_data.items():
            route_data = self.route_data.get(vlan_name, '')
            route6_data = self.route6_data.get(vlan_name, '')
            vlan_path = self.root_dir + ifcfg_config_path(vlan_name)
            vlan_route_path = self.root_dir + route_config_path(vlan_name)
            vlan_route6_path = self.root_dir + route6_config_path(vlan_name)
            all_file_names.append(vlan_path)
            all_file_names.append(vlan_route_path)
            all_file_names.append(vlan_route6_path)
            if (utils.diff(vlan_path, vlan_data) or
                    utils.diff(vlan_route_path, route_data)):
                restart_vlans.append(vlan_name)
                restart_vlans.extend(self.child_members(vlan_name))
                update_files[vlan_path] = vlan_data
                update_files[vlan_route_path] = route_data
                update_files[vlan_route6_path] = route6_data
            else:
                logger.info('No changes required for vlan interface: %s' %
                            vlan_name)

        for bridge_name, bridge_data in self.bridge_data.items():
            route_data = self.route_data.get(bridge_name, '')
            route6_data = self.route6_data.get(bridge_name, '')
            bridge_path = self.root_dir + bridge_config_path(bridge_name)
            br_route_path = self.root_dir + route_config_path(bridge_name)
            br_route6_path = self.root_dir + route6_config_path(bridge_name)
            all_file_names.append(bridge_path)
            all_file_names.append(br_route_path)
            all_file_names.append(br_route6_path)
            if (utils.diff(bridge_path, bridge_data) or
                    utils.diff(br_route_path, route_data) or
                    utils.diff(br_route6_path, route6_data)):
                restart_bridges.append(bridge_name)
                # Avoid duplicate interface being added to the restart list
                children = self.child_members(bridge_name)
                for child in children:
                    if child not in restart_interfaces:
                        restart_interfaces.append(child)
                update_files[bridge_path] = bridge_data
                update_files[br_route_path] = route_data
                update_files[br_route6_path] = route6_data
            else:
                logger.info('No changes required for bridge: %s' % bridge_name)

        for bridge_name, bridge_data in self.linuxbridge_data.items():
            route_data = self.route_data.get(bridge_name, '')
            route6_data = self.route6_data.get(bridge_name, '')
            bridge_path = self.root_dir + bridge_config_path(bridge_name)
            br_route_path = self.root_dir + route_config_path(bridge_name)
            br_route6_path = self.root_dir + route6_config_path(bridge_name)
            all_file_names.append(bridge_path)
            all_file_names.append(br_route_path)
            all_file_names.append(br_route6_path)
            if (utils.diff(bridge_path, bridge_data) or
                    utils.diff(br_route_path, route_data) or
                    utils.diff(br_route6_path, route6_data)):
                restart_bridges.append(bridge_name)
                restart_interfaces.extend(self.child_members(bridge_name))
                update_files[bridge_path] = bridge_data
                update_files[br_route_path] = route_data
                update_files[br_route6_path] = route6_data
            else:
                logger.info('No changes required for bridge: %s' % bridge_name)

        for team_name, team_data in self.linuxteam_data.items():
            route_data = self.route_data.get(team_name, '')
            route6_data = self.route6_data.get(team_name, '')
            team_path = self.root_dir + bridge_config_path(team_name)
            team_route_path = self.root_dir + route_config_path(team_name)
            team_route6_path = self.root_dir + route6_config_path(team_name)
            all_file_names.append(team_path)
            all_file_names.append(team_route_path)
            all_file_names.append(team_route6_path)
            if (utils.diff(team_path, team_data) or
                    utils.diff(team_route_path, route_data) or
                    utils.diff(team_route6_path, route6_data)):
                restart_linux_teams.append(team_name)
                restart_interfaces.extend(self.child_members(team_name))
                update_files[team_path] = team_data
                update_files[team_route_path] = route_data
                update_files[team_route6_path] = route6_data
            else:
                logger.info('No changes required for linux team: %s' %
                            team_name)

        for bond_name, bond_data in self.linuxbond_data.items():
            route_data = self.route_data.get(bond_name, '')
            route6_data = self.route6_data.get(bond_name, '')
            bond_path = self.root_dir + bridge_config_path(bond_name)
            bond_route_path = self.root_dir + route_config_path(bond_name)
            bond_route6_path = self.root_dir + route6_config_path(bond_name)
            all_file_names.append(bond_path)
            all_file_names.append(bond_route_path)
            all_file_names.append(bond_route6_path)
            if (utils.diff(bond_path, bond_data) or
                    utils.diff(bond_route_path, route_data) or
                    utils.diff(bond_route6_path, route6_data)):
                restart_linux_bonds.append(bond_name)
                restart_interfaces.extend(self.child_members(bond_name))
                update_files[bond_path] = bond_data
                update_files[bond_route_path] = route_data
                update_files[bond_route6_path] = route6_data
            else:
                logger.info('No changes required for linux bond: %s' %
                            bond_name)

        # Infiniband interfaces are handled similarly to Ethernet interfaces
        for interface_name, iface_data in self.ib_interface_data.items():
            route_data = self.route_data.get(interface_name, '')
            route6_data = self.route6_data.get(interface_name, '')
            interface_path = self.root_dir + ifcfg_config_path(interface_name)
            route_path = self.root_dir + route_config_path(interface_name)
            route6_path = self.root_dir + route6_config_path(interface_name)
            all_file_names.append(interface_path)
            all_file_names.append(route_path)
            all_file_names.append(route6_path)
            # TODO(dsneddon) determine if InfiniBand can be used with IVS
            if "IVS_BRIDGE" in iface_data:
                ivs_uplinks.append(interface_name)
            all_file_names.append(route6_path)
            if (utils.diff(interface_path, iface_data) or
                    utils.diff(route_path, route_data) or
                    utils.diff(route6_path, route6_data)):
                restart_interfaces.append(interface_name)
                restart_interfaces.extend(self.child_members(interface_name))
                update_files[interface_path] = iface_data
                update_files[route_path] = route_data
                update_files[route6_path] = route6_data
            else:
                logger.info('No changes required for InfiniBand iface: %s' %
                            interface_name)

        if self.vpp_interface_data:
            vpp_path = self.root_dir + vpp_config_path()
            vpp_config = utils.generate_vpp_config(vpp_path, vpp_interfaces)
            if utils.diff(vpp_path, vpp_config):
                restart_vpp = True
                update_files[vpp_path] = vpp_config
            else:
                logger.info('No changes required for VPP')

        if cleanup:
            for ifcfg_file in glob.iglob(cleanup_pattern()):
                if ifcfg_file not in all_file_names:
                    interface_name = ifcfg_file[len(cleanup_pattern()) - 1:]
                    if interface_name != 'lo':
                        logger.info('cleaning up interface: %s'
                                    % interface_name)
                        self.ifdown(interface_name)
                        self.remove_config(ifcfg_file)

        if activate:
            for vlan in restart_vlans:
                self.ifdown(vlan)

            for interface in restart_interfaces:
                self.ifdown(interface)

            for linux_bond in restart_linux_bonds:
                self.ifdown(linux_bond)

            for linux_team in restart_linux_teams:
                self.ifdown(linux_team)

            for bridge in restart_bridges:
                self.ifdown(bridge, iftype='bridge')

            for vpp_interface in vpp_interfaces:
                self.ifdown(vpp_interface.name)

            for oldname, newname in self.renamed_interfaces.items():
                self.ifrename(oldname, newname)

        # DPDK initialization is done before running os-net-config, to make
        # the DPDK ports available when enabled. DPDK Hotplug support is
        # supported only in OvS 2.7 version. Until then, OvS needs to be
        # restarted after adding a DPDK port. This change will be removed on
        # migration to OvS 2.7 where DPDK Hotplug support is available.
        if ovs_needs_restart:
            msg = "Restart openvswitch"
            self.execute(msg, '/usr/bin/systemctl',
                         'restart', 'openvswitch')

        for location, data in update_files.items():
            self.write_config(location, data)

        if ivs_uplinks or ivs_interfaces:
            location = ivs_config_path()
            data = self.generate_ivs_config(ivs_uplinks, ivs_interfaces)
            self.write_config(location, data)

        if nfvswitch_interfaces or nfvswitch_internal_ifaces:
            location = nfvswitch_config_path()
            data = self.generate_nfvswitch_config(nfvswitch_interfaces,
                                                  nfvswitch_internal_ifaces)
            self.write_config(location, data)

        if activate:
            for linux_team in restart_linux_teams:
                self.ifup(linux_team)

            for bridge in restart_bridges:
                self.ifup(bridge, iftype='bridge')

            # If dhclient is running and dhcp not set, stop dhclient
            for interface in stop_dhclient_interfaces:
                logger.debug("Calling stop_dhclient_interfaces() for %s" %
                             interface)
                if not self.noop:
                    stop_dhclient_process(interface)

            for interface in restart_interfaces:
                self.ifup(interface)

            for linux_bond in restart_linux_bonds:
                self.ifup(linux_bond)

            for bond in self.bond_primary_ifaces:
                self.ovs_appctl('bond/set-active-slave', bond,
                                self.bond_primary_ifaces[bond])

            if ivs_uplinks or ivs_interfaces:
                logger.info("Attach to ivs with "
                            "uplinks: %s, "
                            "interfaces: %s" %
                            (ivs_uplinks, ivs_interfaces))
                for ivs_uplink in ivs_uplinks:
                    self.ifup(ivs_uplink)
                for ivs_interface in ivs_interfaces:
                    self.ifup(ivs_interface)
                msg = "Restart ivs"
                self.execute(msg, '/usr/bin/systemctl',
                             'restart', 'ivs')

            if nfvswitch_interfaces or nfvswitch_internal_ifaces:
                logger.info("Attach to nfvswitch with "
                            "interfaces: %s, "
                            "internal interfaces: %s" %
                            (nfvswitch_interfaces, nfvswitch_internal_ifaces))
                for nfvswitch_interface in nfvswitch_interfaces:
                    self.ifup(nfvswitch_interface)
                for nfvswitch_internal in nfvswitch_internal_ifaces:
                    self.ifup(nfvswitch_internal)
                msg = "Restart nfvswitch"
                self.execute(msg, '/usr/bin/systemctl',
                             'restart', 'nfvswitch')

            for vlan in restart_vlans:
                self.ifup(vlan)

            if not self.noop:
                if restart_vpp:
                    logger.info('Restarting VPP')
                    utils.restart_vpp(vpp_interfaces)

                if self.vpp_interface_data:
                    logger.info('Updating VPP mapping')
                    utils.update_vpp_mapping(vpp_interfaces)

            if self.errors:
                message = 'Failure(s) occurred when applying configuration'
                logger.error(message)
                for e in self.errors:
                    logger.error('stdout: %s, stderr: %s', e.stdout, e.stderr)
                raise os_net_config.ConfigurationError(message)

        return update_files