Example #1
0
def veth_pair(prefix='veth_', max_length=15):
    """
    Yield a pair of veth devices. This assumes root privileges (currently
    required by all tests anyway).

    Both sides of the pair have a pseudo-random suffix (e.g. veth_m6Lz7uMK9c).
    """
    left_side = random_iface_name(prefix, max_length)
    right_side = random_iface_name(prefix, max_length)
    try:
        linkAdd(left_side, linkType='veth', args=('peer', 'name', right_side))
        if nmstate.is_nmstate_backend():
            cmd.exec_sync(['nmcli', 'dev', 'set', left_side, 'managed', 'yes'])
            cmd.exec_sync(
                ['nmcli', 'dev', 'set', right_side, 'managed', 'yes'])
    except IPRoute2Error as e:
        pytest.skip('Failed to create a veth pair: %s', e)
    try:
        yield left_side, right_side
    finally:
        # the peer device is removed by the kernel
        linkDel(left_side)
        if nmstate.is_nmstate_backend():
            cmd.exec_sync(['nmcli', 'con', 'del', left_side])
            cmd.exec_sync(['nmcli', 'con', 'del', right_side])
Example #2
0
def _get(vdsmnets=None):
    """
    Generate a networking report for all devices.
    In case vdsmnets is provided, it is used in the report instead of
    retrieving data from the running config.
    :return: Dict of networking devices with all their details.
    """
    ipaddrs = getIpAddrs()
    routes = get_routes()

    devices_info = _devices_report(ipaddrs, routes)
    nets_info = _networks_report(vdsmnets, routes, ipaddrs, devices_info)

    add_qos_info_to_devices(nets_info, devices_info)

    flat_devs_info = _get_flat_devs_info(devices_info)
    devices = _get_dev_names(nets_info, flat_devs_info)
    extra_info = {}
    if nmstate.is_nmstate_backend():
        extra_info.update(_get_devices_info_from_nmstate(devices))
    else:
        extra_info.update(dhclient.dhcp_info(devices))

    _update_caps_info(nets_info, flat_devs_info, extra_info)

    networking_report = {'networks': nets_info}
    networking_report.update(devices_info)
    if nmstate.is_nmstate_backend():
        networking_report['nameservers'] = nmstate.show_nameservers()
    else:
        networking_report['nameservers'] = dns.get_host_nameservers()
    networking_report['supportsIPv6'] = ipv6_supported()

    return networking_report
Example #3
0
def stop_unprivileged_network_components():
    if nmstate.is_nmstate_backend():
        dhcp_monitor.Monitor.instance().stop()
    else:
        dhclient_monitor.stop()

    bond_monitor.stop()
Example #4
0
    def _assert_kernel_vs_running_config(self):
        """
        This is a special test, that checks setup integrity through
        non vdsm api data.
        The networking configuration relies on a semi-persistent running
        configuration files, describing the requested configuration.
        This configuration is checked against the actual caps report.
        """

        running_config = kernelconfig.normalize(self.running_config)
        running_config = running_config.as_unicode()

        netinfo = _normalize_caps(self.netinfo)
        kernel_config = kernelconfig.KernelConfig(netinfo)

        _extend_with_bridge_opts(kernel_config, running_config)
        kernel_config = kernel_config.as_unicode()
        _normalize_bonds((kernel_config, running_config))

        self._assert_inclusive_nameservers(kernel_config, running_config)
        # Do not use KernelConfig.__eq__ to get a better exception if something
        # breaks.
        assert running_config['networks'] == kernel_config['networks']
        if nmstate.is_nmstate_backend():
            self._assert_inclusive_bond_options(kernel_config, running_config)
        assert running_config['bonds'] == kernel_config['bonds']
Example #5
0
def init_unprivileged_network_components(cif, net_api):
    if nmstate.is_nmstate_backend():
        dhcp_monitor.initialize_monitor(cif, net_api)
    else:
        _init_sourceroute(net_api)
        _register_notifications(cif)
        dhclient_monitor.start()
Example #6
0
    def __call__(self, networks, bonds, options):
        self.setup_networks = networks
        self.setup_bonds = bonds

        status, msg = self.vdsm_proxy.setupNetworks(networks, bonds, options)
        if status != SUCCESS:
            self._update_configs()
            raise SetupNetworksError(status, msg)

        if nmstate.is_nmstate_backend():
            if self._is_dynamic():
                _wait_for_dhcp_response(10)
                self.vdsm_proxy.refreshNetworkCapabilities()
        else:
            if self._is_dynamic_ipv4():
                self._wait_for_dhcpv4_response(10)
                self.vdsm_proxy.refreshNetworkCapabilities()
        try:
            self._update_configs()
            self._assert_configs()
        except Exception:
            # Ignore cleanup failure, make sure to re-raise original exception.
            self._cleanup()
            raise

        return self
Example #7
0
    def __call__(self, networks, bonds, options):
        self.setup_networks = networks
        self.setup_bonds = bonds

        status, msg = self.vdsm_proxy.setupNetworks(networks, bonds, options)
        if status != SUCCESS:
            self._update_configs()
            raise SetupNetworksError(status, msg)

        if self._is_dynamic_ipv4():
            self._wait_for_dhcp_response(10)
            self.vdsm_proxy.refreshNetworkCapabilities()
        # FIXME This is just workaround, eventually we need to fix this by
        # adding proper support for IPv6 dhcp monitoring
        # (https://projects.engineering.redhat.com/browse/RHV-17589)
        if self._is_dynamic_ipv6() and nmstate.is_nmstate_backend():
            time.sleep(10)
            self.vdsm_proxy.refreshNetworkCapabilities()
        try:
            self._update_configs()
            self._assert_configs()
        except Exception:
            # Ignore cleanup failure, make sure to re-raise original exception.
            self._cleanup()
            raise

        return self
Example #8
0
    def test_mtu_default_value_of_base_nic_after_all_nets_are_removed(
            self, switch, bridged, bonded):
        if switch == 'legacy' and bonded and not nmstate.is_nmstate_backend():
            pytest.xfail('BZ#1633528')
        with dummy_devices(1) as (nic, ):
            NETWORK1_ATTRS = {
                'bridged': bridged,
                'vlan': VLAN1,
                'mtu': MTU_1600,
                'switch': switch,
            }
            NETBASE = {NETWORK1_NAME: NETWORK1_ATTRS}
            default_mtu = {'mtu': DEFAULT_MTU}
            if bonded:
                NETWORK1_ATTRS['bonding'] = BOND_NAME
                BONDBASE = {BOND_NAME: {'nics': [nic], 'switch': switch}}
            else:
                NETWORK1_ATTRS['nic'] = nic
                BONDBASE = {}

            with adapter.setupNetworks(NETBASE, BONDBASE, nftestlib.NOCHK):
                adapter.setupNetworks({NETWORK1_NAME: {
                    'remove': True
                }}, {}, nftestlib.NOCHK)

                adapter.assertLinkMtu(nic, default_mtu)
                if bonded:
                    adapter.assertLinkMtu(BOND_NAME, default_mtu)
Example #9
0
    def test_move_net_between_bond_and_nic_with_non_default_mtu(
            self, switch, bridged, bonded, vlan):
        if switch == 'legacy' and not nmstate.is_nmstate_backend():
            pytest.skip('Not supported with ifcfg BZ#1790761')
        with dummy_devices(2) as (nic1, nic2):
            net_attrs = {'bridged': bridged, 'mtu': MTU_2000, 'switch': switch}
            BONDBASE = {BOND_NAME: {'nics': [nic1], 'switch': switch}}
            default_mtu = {'mtu': DEFAULT_MTU}
            if bonded:
                net_attrs['bonding'] = BOND_NAME
            else:
                net_attrs['nic'] = nic2

            if vlan:
                net_attrs['vlan'] = VLAN1

            with adapter.setupNetworks({NETWORK_NAME: net_attrs}, BONDBASE,
                                       nftestlib.NOCHK):
                if bonded:
                    net_attrs.pop('bonding')
                    net_attrs['nic'] = nic2
                else:
                    net_attrs.pop('nic')
                    net_attrs['bonding'] = BOND_NAME
                adapter.setupNetworks({NETWORK_NAME: net_attrs}, {},
                                      nftestlib.NOCHK)
                adapter.assertNetwork(NETWORK_NAME, net_attrs)
                adapter.assertLinkMtu(BOND_NAME,
                                      default_mtu if bonded else net_attrs)
                adapter.assertLinkMtu(nic1,
                                      default_mtu if bonded else net_attrs)
                adapter.assertLinkMtu(nic2,
                                      net_attrs if bonded else default_mtu)
Example #10
0
def setup(networks, bondings, options, net_info, in_rollback):
    if nmstate.is_nmstate_backend():
        _setup_nmstate(networks, bondings, options, in_rollback)
    else:
        _setup(networks, bondings, options, in_rollback, net_info)

    if options.get('commitOnSuccess'):
        persist()
Example #11
0
def init_unpriviliged_dhclient_monitor_ctx(event_sink, net_api):
    if nmstate.is_nmstate_backend():
        ctx = dhcp_monitor.initialize_monitor_ctx(event_sink, net_api)
    else:
        _init_sourceroute(net_api)
        _register_notifications(event_sink)
        ctx = dhclient_monitor_ctx()
    with ctx:
        yield
Example #12
0
def _canonicalize_nameservers(data):
    if 'nameservers' not in data:
        # Nameservers are relevant only for the default route network (usually
        # the management network)
        if data['defaultRoute'] and data['bootproto'] != 'dhcp':
            data['nameservers'] = dns.get_host_nameservers()
            # FIXME https://bugzilla.redhat.com/1816043
            if nmstate.is_nmstate_backend():
                data['nameservers'] = data['nameservers'][:2]
        else:
            data['nameservers'] = []
Example #13
0
 def create(self):
     try:
         linkAdd(self.devName, linkType='dummy')
         if nmstate.is_nmstate_backend():
             cmd.exec_sync(
                 ['nmcli', 'dev', 'set', self.devName, 'managed', 'yes'])
     except IPRoute2Error as e:
         pytest.skip('Failed to create a dummy interface %s: %s' %
                     (self.devName, e))
     else:
         return self.devName
Example #14
0
 def remove(self):
     """
     Remove the dummy interface. This assumes root privileges.
     """
     try:
         linkDel(self.devName)
     except IPRoute2Error as e:
         pytest.skip("Unable to delete the dummy interface %s: %s" %
                     (self.devName, e))
     finally:
         if nmstate.is_nmstate_backend():
             cmd.exec_sync(['nmcli', 'con', 'del', self.devName])
Example #15
0
def create_tap():
    devname = '_tap99'
    rc, _, err = exec_sync(['ip', 'tuntap', 'add', devname, 'mode', 'tap'])
    if rc != 0:
        pytest.fail('Unable to create tap device. err: {}'.format(err))
    try:
        iface(devname).up()
        yield devname
    finally:
        exec_sync(['ip', 'tuntap', 'del', devname, 'mode', 'tap'])
        if nmstate.is_nmstate_backend():
            exec_sync(['nmcli', 'con', 'del', devname])
Example #16
0
    def test_restore_missing_dynamic_ipv4_network(self, adapter, switch,
                                                  bridged):
        if switch == 'ovs':
            # With OVS, the restoration creates the network without an IP.
            pytest.xfail('Inconsistent behaviour with OVS')
        elif bridged and not nmstate.is_nmstate_backend():
            pytest.xfail('https://bugzilla.redhat.com/1790392')

        with veth_pair() as (server, client):
            linkSet(server, ['up'])
            linkSet(client, ['up'])
            SETUP_NET = {
                NETWORK_NAME: {
                    'nic': client,
                    'bridged': bridged,
                    'bootproto': 'dhcp',
                    'switch': switch,
                }
            }
            REMOVE_NET = {NETWORK_NAME: {'remove': True}}

            with adapter.reset_persistent_config():
                with adapter.setupNetworks(SETUP_NET, {}, NOCHK):
                    adapter.setSafeNetworkConfig()
                    adapter.setupNetworks(REMOVE_NET, {}, NOCHK)

                    adapter.assertNoNetworkExists(NETWORK_NAME)

                    adapter.restore_nets()

                    if nmstate.is_nmstate_backend():
                        # nmstate successfully restores a network without
                        # a dhcp server in place.
                        adapter.assertNetworkExists(NETWORK_NAME)
                    else:
                        # Attempt to restore network without dhcp server.
                        # As expected, restoration occurs with
                        # blockingdhcp=True and therefore it should fail the
                        # setup.
                        adapter.assertNoNetworkExists(NETWORK_NAME)
Example #17
0
def validate(networks, bondings, net_info):
    legacy_nets, ovs_nets, legacy_bonds, ovs_bonds = _split_switch_type(
        networks, bondings, net_info)

    use_legacy_switch = legacy_nets or legacy_bonds
    use_ovs_switch = ovs_nets or ovs_bonds

    if (not nmstate.is_nmstate_backend() and use_legacy_switch
            and use_ovs_switch):
        raise ne.ConfigNetworkError(
            ne.ERR_BAD_PARAMS,
            'Mixing of legacy and OVS networks is not supported inside one '
            'setupNetworks() call.',
        )

    validator.validate_network_setup(networks, bondings, net_info)
    if use_legacy_switch:
        legacy_switch.validate_network_setup(legacy_nets)
Example #18
0
    def test_base_iface_mtu_is_preserved_when_not_all_nets_on_top_are_deleted(
            self, switch, bridged, bonded):
        if switch == 'legacy' and bonded and not nmstate.is_nmstate_backend():
            pytest.xfail('BZ#1633528')

        common_net_mtu = MTU_1600
        with dummy_devices(1) as (nic, ):
            vlaned_network = {
                'bridged': bridged,
                'vlan': VLAN1,
                'mtu': common_net_mtu,
                'switch': switch,
            }
            non_vlaned_network = {
                'bridged': bridged,
                'mtu': common_net_mtu,
                'switch': switch,
            }
            all_networks = {
                NETWORK1_NAME: vlaned_network,
                NETWORK2_NAME: non_vlaned_network,
            }

            mtu_to_keep = {'mtu': common_net_mtu}
            if bonded:
                vlaned_network['bonding'] = BOND_NAME
                non_vlaned_network['bonding'] = BOND_NAME
                bonds = {BOND_NAME: {'nics': [nic], 'switch': switch}}
            else:
                vlaned_network['nic'] = nic
                non_vlaned_network['nic'] = nic
                bonds = {}

            with adapter.setupNetworks(all_networks, bonds, nftestlib.NOCHK):
                adapter.setupNetworks({NETWORK1_NAME: {
                    'remove': True
                }}, {}, nftestlib.NOCHK)

                adapter.assertLinkMtu(nic, mtu_to_keep)
                if bonded:
                    adapter.assertLinkMtu(BOND_NAME, mtu_to_keep)
Example #19
0
    def test_move_net_from_one_iface_to_another_with_non_default_mtu(
            self, switch, bridged, bonded, vlan):
        if switch == 'legacy' and bonded and not nmstate.is_nmstate_backend():
            pytest.skip('Not supported with ifcfg BZ#1790761')
        with dummy_devices(2) as (nic1, nic2):
            net_attrs = {'bridged': bridged, 'mtu': MTU_2000, 'switch': switch}
            default_mtu = {'mtu': DEFAULT_MTU}
            if bonded:
                net_attrs['bonding'] = BOND_NAME
                BONDBASE = {
                    BOND_NAME: {
                        'nics': [nic1],
                        'switch': switch
                    },
                    BOND_NAME2: {
                        'nics': [nic2],
                        'switch': switch
                    },
                }
            else:
                net_attrs['nic'] = nic1
                BONDBASE = {}

            if vlan:
                net_attrs['vlan'] = VLAN1

            with adapter.setupNetworks({NETWORK_NAME: net_attrs}, BONDBASE,
                                       nftestlib.NOCHK):
                if bonded:
                    net_attrs['bonding'] = BOND_NAME2
                else:
                    net_attrs['nic'] = nic2
                adapter.setupNetworks({NETWORK_NAME: net_attrs}, {},
                                      nftestlib.NOCHK)
                adapter.assertNetwork(NETWORK_NAME, net_attrs)
                if bonded:
                    adapter.assertLinkMtu(BOND_NAME, default_mtu)
                    adapter.assertLinkMtu(BOND_NAME2, net_attrs)
                adapter.assertLinkMtu(nic1, default_mtu)
                adapter.assertLinkMtu(nic2, net_attrs)
Example #20
0
class TestBondBasic(object):
    def test_add_bond_with_two_nics(self, switch):
        with dummy_devices(2) as (nic1, nic2):
            BONDCREATE = {BOND_NAME: {'nics': [nic1, nic2], 'switch': switch}}

            with adapter.setupNetworks({}, BONDCREATE, NOCHK):
                adapter.assertBond(BOND_NAME, BONDCREATE[BOND_NAME])

    def test_add_bond_with_two_nics_and_options(self, switch):
        with dummy_devices(2) as (nic1, nic2):
            BONDCREATE = {
                BOND_NAME: {
                    'nics': [nic1, nic2],
                    'options': 'mode=3 miimon=150',
                    'switch': switch,
                }
            }

            with adapter.setupNetworks({}, BONDCREATE, NOCHK):
                adapter.assertBond(BOND_NAME, BONDCREATE[BOND_NAME])

    def test_remove_bond(self, switch):
        with dummy_devices(2) as (nic1, nic2):
            BONDCREATE = {BOND_NAME: {'nics': [nic1, nic2], 'switch': switch}}
            BONDREMOVE = {BOND_NAME: {'remove': True}}

            with adapter.setupNetworks({}, BONDCREATE, NOCHK):
                adapter.setupNetworks({}, BONDREMOVE, NOCHK)
                adapter.assertNoBond(BOND_NAME)

    @pytest.mark.xfail(
        condition=nmstate.is_nmstate_backend(),
        reason='Links stability not supported by nmstate/NM',
        raises=nftestlib.UnexpectedLinkStateChangeError,
        strict=True,
    )
    def test_change_bond_slaves(self, switch):
        with dummy_devices(3) as (nic1, nic2, nic3):
            BONDCREATE = {BOND_NAME: {'nics': [nic1, nic2], 'switch': switch}}
            BONDEDIT = {BOND_NAME: {'nics': [nic1, nic3], 'switch': switch}}

            with adapter.setupNetworks({}, BONDCREATE, NOCHK):
                with nftestlib.monitor_stable_link_state(BOND_NAME):
                    adapter.setupNetworks({}, BONDEDIT, NOCHK)
                    adapter.assertBond(BOND_NAME, BONDEDIT[BOND_NAME])

    def test_swap_slaves_between_bonds(self, switch):
        BOND1 = BOND_NAME + '1'
        BOND2 = BOND_NAME + '2'

        with dummy_devices(4) as (nic1, nic2, nic3, nic4):
            BONDCREATE = {
                BOND1: {'nics': [nic1, nic2], 'switch': switch},
                BOND2: {'nics': [nic3, nic4], 'switch': switch},
            }
            BONDEDIT = {
                BOND1: {'nics': [nic1, nic3], 'switch': switch},
                BOND2: {'nics': [nic2, nic4], 'switch': switch},
            }
            with adapter.setupNetworks({}, BONDCREATE, NOCHK):
                adapter.setupNetworks({}, BONDEDIT, NOCHK)
                adapter.assertBond(BOND1, BONDEDIT[BOND1])
                adapter.assertBond(BOND2, BONDEDIT[BOND2])

    def test_resize_bond(self, switch):
        with dummy_devices(4) as (nic1, nic2, nic3, nic4):
            bond = {BOND_NAME: {'nics': [nic1, nic2], 'switch': switch}}
            with adapter.setupNetworks({}, bond, NOCHK):
                bond[BOND_NAME]['nics'] += [nic3, nic4]
                adapter.setupNetworks({}, bond, NOCHK)
                adapter.assertBond(BOND_NAME, bond[BOND_NAME])

                bond[BOND_NAME]['nics'].remove(nic4)
                adapter.setupNetworks({}, bond, NOCHK)
                adapter.assertBond(BOND_NAME, bond[BOND_NAME])

    def test_add_bond_with_bad_name_fails(self, switch):
        INVALID_BOND_NAMES = ('bond', 'bond bad', 'jamesbond007')

        with dummy_devices(2) as (nic1, nic2):
            for bond_name in INVALID_BOND_NAMES:
                BONDCREATE = {
                    bond_name: {'nics': [nic1, nic2], 'switch': switch}
                }
                with pytest.raises(SetupNetworksError) as cm:
                    with adapter.setupNetworks({}, BONDCREATE, NOCHK):
                        pass
                assert cm.value.status == ne.ERR_BAD_BONDING

    def test_add_bond_with_no_nics_fails(self, switch):
        BONDCREATE = {BOND_NAME: {'nics': [], 'switch': switch}}

        with pytest.raises(SetupNetworksError) as err:
            with adapter.setupNetworks({}, BONDCREATE, NOCHK):
                pass
        assert err.value.status == ne.ERR_BAD_PARAMS

    def test_add_bond_with_enforced_mac_address(self, switch):
        if switch == 'ovs':
            pytest.xfail(
                'Bond mac enforcement is currently not implemented for ovs'
            )
        HWADDRESS = 'ce:0c:46:59:c9:d1'
        with dummy_devices(2) as (nic1, nic2):
            BONDCREATE = {
                BOND_NAME: {
                    'nics': [nic1, nic2],
                    'hwaddr': HWADDRESS,
                    'switch': switch,
                }
            }

            with adapter.setupNetworks({}, BONDCREATE, NOCHK):
                adapter.assertBond(BOND_NAME, BONDCREATE[BOND_NAME])

    def test_bond_slaves_order_does_not_affect_the_mac_address(self, switch):
        with dummy_devices(2) as (nic1, nic2):
            bond1 = {BOND_NAME: {'nics': [nic1, nic2], 'switch': switch}}
            bond2 = {BOND_NAME: {'nics': [nic2, nic1], 'switch': switch}}

            with adapter.setupNetworks({}, bond1, NOCHK):
                bond1_hwaddr = adapter.netinfo.bondings[BOND_NAME]['hwaddr']
            with adapter.setupNetworks({}, bond2, NOCHK):
                bond2_hwaddr = adapter.netinfo.bondings[BOND_NAME]['hwaddr']

            assert bond1_hwaddr == bond2_hwaddr
Example #21
0
 def delDevice(self):
     self._down()
     linkDel(self.devName)
     if nmstate.is_nmstate_backend():
         cmd.exec_sync(['nmcli', 'con', 'del', self.devName])
Example #22
0
def dhcp_client_run(iface, family=4):
    dhcp_client = (dhcp_nm_client
                   if nmstate.is_nmstate_backend() else dhclient_run)
    with dhcp_client(iface, family):
        yield
Example #23
0
def is_nmstate_backend():
    return nmstate.is_nmstate_backend()
Example #24
0
 def _notify(**kwargs):
     if not nmstate.is_nmstate_backend():
         # Delay the notification in order to allow the ifup job to finish
         time.sleep(5)
     cif.notify('|net|host_conn|no_id')