def test_translate_add_network_with_default_route(bridged): networks = { TESTNET1: _create_network_config( 'nic', IFACE0, bridged=bridged, static_ip_configuration=_create_static_ip_configuration( IPv4_ADDRESS1, IPv4_NETMASK1, IPv6_ADDRESS1, IPv6_PREFIX1 ), default_route=True, gateway=IPv4_GATEWAY1 ) } state = nmstate.generate_state(networks=networks, bondings={}) eth0_state = _create_ethernet_iface_state(IFACE0) ip0_state = _create_ipv4_state(IPv4_ADDRESS1, IPv4_PREFIX1) ip0_state.update(_create_ipv6_state(IPv6_ADDRESS1, IPv6_PREFIX1)) expected_state = {nmstate.Interface.KEY: [eth0_state]} if bridged: _disable_iface_ip(eth0_state) bridge1_state = _create_bridge_iface_state( TESTNET1, IFACE0, options=_generate_bridge_options( stp_enabled=False) ) bridge1_state.update(ip0_state) expected_state[nmstate.Interface.KEY].append(bridge1_state) if_with_default_route = TESTNET1 else: eth0_state.update(ip0_state) if_with_default_route = IFACE0 expected_state[nmstate.Route.KEY] = _get_routes_config( IPv4_GATEWAY1, if_with_default_route ) assert state == expected_state
def test_translate_remove_nets(rconfig_mock, bridged): rconfig_mock.return_value.networks = { TESTNET1: { 'nic': IFACE0, 'bridged': bridged, 'switch': 'legacy', 'defaultRoute': False}, TESTNET2: { 'nic': IFACE1, 'bridged': bridged, 'switch': 'legacy', 'defaultRoute': False} } networks = { TESTNET1: {'remove': True}, TESTNET2: {'remove': True} } state = nmstate.generate_state(networks=networks, bondings={}) eth0_state = _create_ethernet_iface_state(IFACE0) eth1_state = _create_ethernet_iface_state(IFACE1) _disable_iface_ip(eth0_state, eth1_state) expected_state = {nmstate.Interface.KEY: [eth0_state, eth1_state]} if bridged: expected_state[nmstate.Interface.KEY].extend([ { 'name': TESTNET1, 'state': 'absent' }, { 'name': TESTNET2, 'state': 'absent' } ]) _sort_by_name(expected_state[nmstate.Interface.KEY]) assert expected_state == state
def test_translate_remove_vlan_net(rconfig_mock, bridged): rconfig_mock.return_value.networks = { TESTNET1: { 'nic': IFACE0, 'bridged': bridged, 'vlan': VLAN101, 'switch': 'legacy', 'defaultRoute': False } } networks = { TESTNET1: {'remove': True} } state = nmstate.generate_state(networks=networks, bondings={}) expected_state = { nmstate.Interface.KEY: [ { 'name': IFACE0 + '.' + str(VLAN101), 'state': 'absent', } ] } if bridged: expected_state[nmstate.Interface.KEY].append({ 'name': TESTNET1, 'state': 'absent' }) _sort_by_name(expected_state[nmstate.Interface.KEY]) assert expected_state == state
def test_bridgeless_and_vlan_networks_on_the_same_nic(): networks = { TESTNET1: create_network_config( 'nic', IFACE0, bridged=False, static_ip_configuration=create_static_ip_configuration( IPv4_ADDRESS1, IPv4_NETMASK1, None, None ), ), TESTNET2: create_network_config( 'nic', IFACE0, bridged=False, vlan=VLAN101 ), } state = nmstate.generate_state(networks=networks, bondings={}) bridgeless_state = create_ethernet_iface_state(IFACE0) vlan0_state = create_vlan_iface_state(IFACE0, VLAN101) ipv4_state = create_ipv4_state(IPv4_ADDRESS1, IPv4_PREFIX1) ipv4_disabled_state = create_ipv4_state() ipv6_disabled_state = create_ipv6_state() bridgeless_state.update(ipv4_state) bridgeless_state.update(ipv6_disabled_state) vlan0_state.update(ipv4_disabled_state) vlan0_state.update(ipv6_disabled_state) expected_state = {nmstate.Interface.KEY: [bridgeless_state, vlan0_state]} assert expected_state == state
def test_translate_remove_net_on_bond(self, rconfig_mock, bridged): rconfig_mock.return_value.networks = { TESTNET1: {'bonding': TESTBOND0, 'bridged': bridged, 'switch': 'legacy', 'defaultRoute': False} } networks = { TESTNET1: {'remove': True} } state = nmstate.generate_state(networks=networks, bondings={}) expected_state = { nmstate.Interface.KEY: [ { 'name': TESTBOND0, 'state': 'up', 'ipv4': {'enabled': False}, 'ipv6': {'enabled': False} } ] } if bridged: expected_state[nmstate.Interface.KEY].append({ 'name': TESTNET1, 'state': 'absent' }) _sort_by_name(expected_state[nmstate.Interface.KEY]) assert expected_state == state
def _setup_nmstate(networks, bondings, options, in_rollback): """ Setup the networks using nmstate as the backend provider. nmstate handles the rollback by itself in case of an error during the transaction or in case the resulted state does not include the desired one. In order to support the connectivity check, the "regular" rollback is used (the Transaction context). """ logging.info('Processing setup through nmstate') desired_state = nmstate.generate_state(networks, bondings) logging.info('Desired state: %s', desired_state) nmstate.setup(desired_state, verify_change=not in_rollback) with Transaction(in_rollback=in_rollback) as config: config.networks = { name: attrs for name, attrs in six.viewitems(networks) if not attrs.get('remove') } config.bonds = { name: attrs for name, attrs in six.viewitems(bondings) if not attrs.get('remove') } connectivity.check(options)
def test_move_vlan_to_another_iface(rconfig_mock): rconfig_mock.networks = { TESTNET1: create_network_config( 'nic', IFACE0, bridged=False, vlan=VLAN101 ) } networks = { TESTNET1: create_network_config( 'nic', IFACE1, bridged=False, vlan=VLAN101 ) } state = nmstate.generate_state(networks=networks, bondings={}) eth1_vlan_state = create_vlan_iface_state(IFACE1, VLAN101) disable_iface_ip(eth1_vlan_state) eth1_state = create_ethernet_iface_state(IFACE1) disable_iface_ip(eth1_state) remove_vlan_eth0_state = { nmstate.Interface.NAME: 'eth0.101', nmstate.Interface.STATE: nmstate.InterfaceState.ABSENT, } expected_state = { nmstate.Interface.KEY: [ eth1_vlan_state, remove_vlan_eth0_state, eth1_state, ] } sort_by_name(expected_state[nmstate.Interface.KEY]) assert expected_state == state
def test_remove_net_without_ip(bridged, rconfig_mock, current_state_mock): rconfig_mock.networks = { TESTNET1: {'nic': IFACE0, 'bridged': bridged, 'switch': 'ovs'}, TESTNET2: {'nic': IFACE0, 'bridged': bridged, 'switch': 'ovs'}, } current_ifaces_states = current_state_mock[nmstate.Interface.KEY] current_ifaces_states.append( { 'name': OVS_BRIDGE[5], nmstate.Interface.TYPE: nmstate.InterfaceType.OVS_BRIDGE, 'state': 'up', nmstate.OvsBridgeSchema.CONFIG_SUBTREE: { nmstate.OvsBridgeSchema.PORT_SUBTREE: [ {nmstate.OvsBridgeSchema.Port.NAME: TESTNET1}, {nmstate.OvsBridgeSchema.Port.NAME: TESTNET2}, {nmstate.OvsBridgeSchema.Port.NAME: IFACE0}, ] }, } ) networks = {TESTNET2: {'remove': True}} state = nmstate.generate_state(networks=networks, bondings={}) nb_state = {'name': TESTNET2, 'state': 'absent'} expected_state = {nmstate.Interface.KEY: [nb_state]} sort_by_name(expected_state[nmstate.Interface.KEY]) assert expected_state == state
def test_add_nets_over_single_sb_without_ip(bridged, vlanned): vlan1 = VLAN101 if vlanned else None vlan2 = VLAN102 if vlanned else None networks = { TESTNET1: create_network_config( 'nic', IFACE0, bridged, switch='ovs', vlan=vlan1 ), TESTNET2: create_network_config( 'nic', IFACE0, bridged, switch='ovs', vlan=vlan2 ), } state = nmstate.generate_state(networks=networks, bondings={}) eth0_state = create_ethernet_iface_state(IFACE0, mtu=None) bridge_ports = [ create_ovs_port_state(IFACE0), create_ovs_port_state(TESTNET1, vlan=vlan1), create_ovs_port_state(TESTNET2, vlan=vlan2), ] sort_by_name(bridge_ports) bridge_state = create_ovs_bridge_state(OVS_BRIDGE[0], bridge_ports) nb1_state = create_ovs_northbound_state(TESTNET1) nb2_state = create_ovs_northbound_state(TESTNET2) expected_state = { nmstate.Interface.KEY: [eth0_state, bridge_state, nb1_state, nb2_state] } sort_by_name(expected_state[nmstate.Interface.KEY]) assert expected_state == state
def test_translate_remove_vlan_net(rconfig_mock, bridged): rconfig_mock.networks = { TESTNET1: { 'nic': IFACE0, 'bridged': bridged, 'vlan': VLAN101, 'switch': 'legacy', 'defaultRoute': False, } } networks = {TESTNET1: {'remove': True}} state = nmstate.generate_state(networks=networks, bondings={}) expected_state = { nmstate.Interface.KEY: [ { nmstate.Interface.NAME: IFACE0 + '.' + str(VLAN101), nmstate.Interface.STATE: nmstate.InterfaceState.ABSENT, } ] } if bridged: expected_state[nmstate.Interface.KEY].append( { nmstate.Interface.NAME: TESTNET1, nmstate.Interface.STATE: nmstate.InterfaceState.ABSENT, } ) sort_by_name(expected_state[nmstate.Interface.KEY]) assert expected_state == state
def test_translate_remove_network_with_default_route(rconfig_mock, bridged): rconfig_mock.return_value.networks = { TESTNET1: { 'nic': IFACE0, 'bridged': bridged, 'switch': 'legacy', 'defaultRoute': True, 'gateway': IPv4_GATEWAY1 } } networks = {TESTNET1: {'remove': True}} state = nmstate.generate_state(networks=networks, bondings={}) eth0_state = _create_ethernet_iface_state(IFACE0) _disable_iface_ip(eth0_state) expected_state = {nmstate.Interface.KEY: [eth0_state]} if bridged: expected_state[nmstate.Interface.KEY].append( {'name': TESTNET1, 'state': 'absent'} ) assert expected_state == state
def test_translate_remove_bridgeless_vlan_net_on_bond(rconfig_mock): rconfig_mock.return_value.networks = { 'testnet1': { 'bonding': 'testbond0', 'bridged': False, 'vlan': 101, 'switch': 'legacy' } } networks = { 'testnet1': {'remove': True} } state = nmstate.generate_state(networks=networks, bondings={}) expected_state = { nmstate.INTERFACES: [ { 'name': 'testbond0.101', 'type': 'vlan', 'state': 'absent', } ] } _sort_by_name(expected_state[nmstate.INTERFACES]) assert expected_state == state
def _setup_nmstate(networks, bondings, options, in_rollback): """ Setup the networks using nmstate as the backend provider. nmstate handles the rollback by itself in case of an error during the transaction or in case the resulted state does not include the desired one. In order to support the connectivity check, the "regular" rollback is used (the Transaction context). """ logging.info('Processing setup through nmstate') desired_state = nmstate.generate_state(networks, bondings) logging.info('Desired state: %s', desired_state) _setup_dynamic_src_routing(networks) nmstate.setup(desired_state, verify_change=not in_rollback) net_info = NetInfo(netinfo_get()) with Transaction(in_rollback=in_rollback, persistent=False) as config: _setup_qos(networks, net_info, config.networks) for net_name, net_attrs in six.viewitems(networks): if net_attrs.get('remove'): config.removeNetwork(net_name) for net_name, net_attrs in six.viewitems(networks): if not net_attrs.get('remove'): config.setNetwork(net_name, net_attrs) for bond_name, bond_attrs in six.viewitems(bondings): if bond_attrs.get('remove'): config.removeBonding(bond_name) for bond_name, bond_attrs in six.viewitems(bondings): if not bond_attrs.get('remove'): config.setBonding(bond_name, bond_attrs) _setup_static_src_routing(networks) config.save() link_setup.setup_custom_bridge_opts(networks) connectivity.check(options)
def test_add_network_with_lower_mtu(self, current_state_mock): mtu = DEFAULT_MTU - 500 current_ifaces_states = current_state_mock[nmstate.Interface.KEY] current_ifaces_states += self._create_bond_with_slaves_ifaces_states( DEFAULT_MTU, include_type=True ) current_ifaces_states += self._create_vlan_with_bridge_ifaces_states( VLAN101, TESTNET1, DEFAULT_MTU ) networks = { TESTNET2: create_network_config( 'bonding', TESTBOND0, bridged=True, vlan=VLAN102, mtu=mtu ) } state = nmstate.generate_state(networks=networks, bondings={}) expected_ifaces_states = self._create_vlan_with_bridge_ifaces_states( VLAN102, TESTNET2, mtu ) expected_bond_state = { nmstate.Interface.NAME: TESTBOND0, nmstate.Interface.STATE: nmstate.InterfaceState.UP, nmstate.Interface.MTU: DEFAULT_MTU, } expected_ifaces_states.append(expected_bond_state) sort_by_name(expected_ifaces_states) assert {nmstate.Interface.KEY: expected_ifaces_states} == state
def test_translate_remove_vlan_net_on_bond(rconfig_mock, bridged): rconfig_mock.return_value.networks = { 'testnet1': { 'bonding': 'testbond0', 'bridged': bridged, 'vlan': VLAN101, 'switch': 'legacy', 'defaultRoute': False } } networks = { 'testnet1': {'remove': True} } state = nmstate.generate_state(networks=networks, bondings={}) expected_state = { nmstate.Interface.KEY: [ { 'name': 'testbond0.' + str(VLAN101), 'state': 'absent', } ] } if bridged: expected_state[nmstate.Interface.KEY].extend([ { 'name': 'testnet1', 'state': 'absent' } ]) _sort_by_name(expected_state[nmstate.Interface.KEY]) assert expected_state == state
def test_translate_remove_bridgeless_nets(rconfig_mock): rconfig_mock.return_value.networks = { 'testnet1': {'nic': 'eth0', 'bridged': False, 'switch': 'legacy'}, 'testnet2': {'nic': 'eth1', 'bridged': False, 'switch': 'legacy'} } networks = { 'testnet1': {'remove': True}, 'testnet2': {'remove': True} } state = nmstate.generate_state(networks=networks, bondings={}) expected_state = { nmstate.INTERFACES: [ { 'name': 'eth0', 'type': 'ethernet', 'state': 'up', 'ipv4': {'enabled': False}, 'ipv6': {'enabled': False} }, { 'name': 'eth1', 'type': 'ethernet', 'state': 'up', 'ipv4': {'enabled': False}, 'ipv6': {'enabled': False} } ] } _sort_by_name(expected_state[nmstate.INTERFACES]) assert expected_state == state
def test_dynamic_ip(self, families): dhcpv4 = IPv4_FAMILY in families dhcpv6 = IPv6_FAMILY in families networks = { TESTNET1: create_network_config( 'nic', IFACE0, bridged=True, switch='ovs', dynamic_ip_configuration=create_dynamic_ip_configuration( dhcpv4, dhcpv6, ipv6autoconf=dhcpv6), ) } state = nmstate.generate_state(networks=networks, bondings={}) eth0_state = create_ethernet_iface_state(IFACE0) disable_iface_ip(eth0_state) bridge_ports = [ create_ovs_port_state(IFACE0), create_ovs_port_state(TESTNET1), ] sort_by_name(bridge_ports) bridge_state = create_ovs_bridge_state(OVS_BRIDGE[0], bridge_ports) nb_state = create_ovs_northbound_state(TESTNET1) nb_state.update(create_ipv4_state(dynamic=dhcpv4, auto_dns=False)) nb_state.update(create_ipv6_state(dynamic=dhcpv6, auto_dns=False)) expected_state = { nmstate.Interface.KEY: [eth0_state, bridge_state, nb_state] } sort_by_name(expected_state[nmstate.Interface.KEY]) assert expected_state == state
def test_dns_replace_network_with_default_route(self, rconfig_mock): rconfig_networks = { TESTNET1: create_network_config( 'nic', IFACE0, bridged=True, default_route=True, gateway=IPv4_GATEWAY1, nameservers=DNS_SERVERS1, ) } rconfig_mock.return_value.networks = rconfig_networks networks = { TESTNET2: create_network_config( 'nic', IFACE1, bridged=True, default_route=True, gateway=IPv4_GATEWAY1, nameservers=DNS_SERVERS2, ) } state = nmstate.generate_state(networks=networks, bondings={}) expected_state = { nmstate.DNS.CONFIG: {nmstate.DNS.SERVER: DNS_SERVERS2} } assert expected_state == state[nmstate.DNS.KEY]
def test_single_network_with_specific_mtu(self, current_state_mock): mtu = 2000 current_ifaces_states = current_state_mock[nmstate.Interface.KEY] current_ifaces_states += self._create_bond_slaves_states( DEFAULT_MTU, include_type=True ) networks = { TESTNET1: create_network_config( 'bonding', TESTBOND0, bridged=True, vlan=VLAN101, mtu=mtu ) } bondings = create_bonding_config(slaves=[IFACE0, IFACE1]) state = nmstate.generate_state(networks=networks, bondings=bondings) expected_slaves_states = self._create_bond_slaves_states(mtu) expected_bond_state = self._create_bond_state(mtu) expected_vlan_state = self._create_vlan_state(VLAN101, mtu) expected_bridge_state = self._create_bridge_state( TESTNET1, expected_vlan_state[nmstate.Interface.NAME], mtu ) expected_state = { nmstate.Interface.KEY: expected_slaves_states + [expected_bond_state, expected_vlan_state, expected_bridge_state] } sort_by_name(expected_state[nmstate.Interface.KEY]) assert expected_state == state
def test_translate_bridgeless_nets_without_ip(): networks = { 'testnet1': { 'nic': 'eth0', 'bridged': False, 'switch': 'legacy' }, 'testnet2': { 'nic': 'eth1', 'bridged': False, 'switch': 'legacy' } } state = nmstate.generate_state(networks=networks, bondings={}) expected_state = { nmstate.INTERFACES: [{ 'name': 'eth0', 'type': 'ethernet', 'state': 'up', }, { 'name': 'eth1', 'type': 'ethernet', 'state': 'up', }] } _sort_by_name(expected_state[nmstate.INTERFACES]) assert expected_state == state
def test_remove_net(self, bridged, rconfig_mock, current_state_mock): rconfig_mock.networks = { TESTNET1: {'nic': IFACE0, 'bridged': bridged, 'switch': 'ovs'}, TESTNET2: {'nic': IFACE0, 'bridged': bridged, 'switch': 'ovs'}, } current_ifaces_states = current_state_mock[nmstate.Interface.KEY] current_ifaces_states.append( { nmstate.Interface.NAME: OVS_BRIDGE[5], nmstate.Interface.TYPE: nmstate.InterfaceType.OVS_BRIDGE, nmstate.Interface.STATE: nmstate.InterfaceState.UP, nmstate.OvsBridgeSchema.CONFIG_SUBTREE: { nmstate.OvsBridgeSchema.PORT_SUBTREE: [ {nmstate.OvsBridgeSchema.Port.NAME: TESTNET1}, {nmstate.OvsBridgeSchema.Port.NAME: TESTNET2}, {nmstate.OvsBridgeSchema.Port.NAME: IFACE0}, ] }, } ) networks = {TESTNET2: {'remove': True}} state = nmstate.generate_state(networks=networks, bondings={}) nb_state = { nmstate.Interface.NAME: TESTNET2, nmstate.Interface.STATE: nmstate.InterfaceState.ABSENT, } bridge_mappings_state = create_ovs_bridge_mappings_state( {OVS_BRIDGE[5]: [TESTNET1]} ) expected_state = {nmstate.Interface.KEY: [nb_state]} expected_state.update(bridge_mappings_state) sort_by_name(expected_state[nmstate.Interface.KEY]) assert expected_state == state
def test_translate_bond_with_two_slaves_and_options(): bondings = { 'testbond0': { 'nics': ['eth0', 'eth1'], 'options': 'mode=4 miimon=150', 'switch': 'legacy' } } state = nmstate.generate_state(networks={}, bondings=bondings) expected_state = { nmstate.INTERFACES: [{ 'name': 'testbond0', 'type': 'bond', 'state': 'up', 'link-aggregation': { 'mode': '802.3ad', 'slaves': ['eth0', 'eth1'], 'options': { 'miimon': '150' } } }] } assert expected_state == state
def test_translate_bridgeless_net_with_dynamic_ip(): networks = { 'testnet1': { 'bonding': 'testbond0', 'bridged': False, 'bootproto': 'dhcp', 'dhcpv6': True, 'ipv6autoconf': True, 'switch': 'legacy' } } bondings = {'testbond0': {'nics': ['eth0', 'eth1'], 'switch': 'legacy'}} state = nmstate.generate_state(networks=networks, bondings=bondings) expected_state = { nmstate.INTERFACES: [{ 'name': 'testbond0', 'type': 'bond', 'state': 'up', 'link-aggregation': { 'mode': 'balance-rr', 'slaves': ['eth0', 'eth1'] }, 'ipv4': { 'enabled': True, 'dhcp': True }, 'ipv6': { 'enabled': True, 'dhcp': True, 'autoconf': True } }] } assert expected_state == state
def test_translate_remove_bridgeless_net_on_bond(rconfig_mock): rconfig_mock.return_value.networks = { 'testnet1': { 'bonding': 'testbond0', 'bridged': False, 'switch': 'legacy' } } networks = {'testnet1': {'remove': True}} state = nmstate.generate_state(networks=networks, bondings={}) expected_state = { nmstate.INTERFACES: [{ 'name': 'testbond0', 'type': 'bond', 'state': 'up', 'ipv4': { 'enabled': False }, 'ipv6': { 'enabled': False } }] } _sort_by_name(expected_state[nmstate.INTERFACES]) assert expected_state == state
def test_translate_nets_without_ip(bridged): networks = { 'testnet1': _create_network_config('nic', IFACE0, bridged), 'testnet2': _create_network_config('nic', IFACE1, bridged) } state = nmstate.generate_state(networks=networks, bondings={}) eth0_state = _create_ethernet_iface_state(IFACE0) eth1_state = _create_ethernet_iface_state(IFACE1) _disable_iface_ip(eth0_state, eth1_state) expected_state = { nmstate.Interface.KEY: [ eth0_state, eth1_state ] } if bridged: bridge1_state = _create_bridge_iface_state( 'testnet1', IFACE0, options=_generate_bridge_options( stp_enabled=False) ) bridge2_state = _create_bridge_iface_state( 'testnet2', IFACE1, options=_generate_bridge_options( stp_enabled=False) ) _disable_iface_ip(bridge1_state, bridge2_state) expected_state[nmstate.Interface.KEY].extend([ bridge1_state, bridge2_state ]) _sort_by_name(expected_state[nmstate.Interface.KEY]) assert expected_state == state
def test_translate_bond_with_two_slaves_and_options(): bondings = { 'testbond0': { 'nics': ['eth0', 'eth1'], 'options': 'mode=4 miimon=150', 'switch': 'legacy' } } state = nmstate.generate_state(networks={}, bondings=bondings) expected_state = { nmstate.INTERFACES: [ { 'name': 'testbond0', 'type': 'bond', 'state': 'up', 'link-aggregation': { 'mode': '802.3ad', 'slaves': ['eth0', 'eth1'], 'options': { 'miimon': '150' } } } ] } assert expected_state == state
def test_add_single_net(self, bridged, vlan): networks = { TESTNET1: create_network_config('nic', IFACE0, bridged, switch='ovs', vlan=vlan) } state = nmstate.generate_state(networks=networks, bondings={}) eth0_state = create_ethernet_iface_state(IFACE0) bridge_ports = [ create_ovs_port_state(IFACE0), create_ovs_port_state(TESTNET1, vlan=vlan), ] sort_by_name(bridge_ports) bridge_state = create_ovs_bridge_state(OVS_BRIDGE[0], bridge_ports) nb_state = create_ovs_northbound_state(TESTNET1) disable_iface_ip(eth0_state, nb_state) expected_state = { nmstate.Interface.KEY: [eth0_state, bridge_state, nb_state] } sort_by_name(expected_state[nmstate.Interface.KEY]) assert expected_state == state
def test_mtu_reset_on_network_dettach( self, rconfig_mock, bridged, current_state_mock ): mtu = DEFAULT_MTU * 4 current_ifaces_states = current_state_mock[nmstate.Interface.KEY] current_ifaces_states.append( create_ethernet_iface_state(IFACE0, include_type=True, mtu=mtu) ) if bridged: current_ifaces_states.append( self._create_bridge_state(TESTNET1, IFACE0, mtu) ) rconfig_mock.return_value.bonds = {} rconfig_mock.return_value.networks = { TESTNET1: create_network_config( 'nic', IFACE0, bridged=bridged, mtu=mtu ) } remove_network = {TESTNET1: {'remove': True}} state = nmstate.generate_state(networks=remove_network, bondings={}) expected_iface_state = create_ethernet_iface_state(IFACE0) disable_iface_ip(expected_iface_state) expected_iface_states = [expected_iface_state] if bridged: expected_iface_states.append( { nmstate.Interface.NAME: TESTNET1, nmstate.Interface.STATE: nmstate.InterfaceState.ABSENT, } ) assert {nmstate.Interface.KEY: expected_iface_states} == state
def test_dns_remove_network_with_default_route( self, rconfig_mock, current_state_mock ): current_ifaces_states = current_state_mock[nmstate.Interface.KEY] current_ifaces_states.append( { nmstate.Interface.NAME: IFACE0, nmstate.Interface.TYPE: nmstate.InterfaceType.ETHERNET, nmstate.Interface.STATE: nmstate.InterfaceState.UP, nmstate.Interface.MTU: DEFAULT_MTU, nmstate.Interface.IPV4: {nmstate.InterfaceIP.ENABLED: False}, nmstate.Interface.IPV6: {nmstate.InterfaceIP.ENABLED: False}, } ) rconfig_networks = { TESTNET1: create_network_config( 'nic', IFACE0, bridged=True, default_route=True, gateway=IPv4_GATEWAY1, nameservers=DNS_SERVERS1, ) } rconfig_mock.return_value.networks = rconfig_networks networks = {TESTNET1: {'remove': True}} state = nmstate.generate_state(networks=networks, bondings={}) expected_state = {nmstate.DNS.CONFIG: {nmstate.DNS.SERVER: []}} assert expected_state == state[nmstate.DNS.KEY]
def test_translate_add_network_with_default_route_on_vlan_interface(): networks = { TESTNET1: create_network_config( 'nic', IFACE0, bridged=False, static_ip_configuration=create_static_ip_configuration( IPv4_ADDRESS1, IPv4_NETMASK1, IPv6_ADDRESS1, IPv6_PREFIX1 ), default_route=True, gateway=IPv4_GATEWAY1, vlan=VLAN101, ) } state = nmstate.generate_state(networks=networks, bondings={}) vlan101_state = create_vlan_iface_state(IFACE0, VLAN101) ip0_state = create_ipv4_state(IPv4_ADDRESS1, IPv4_PREFIX1) ip0_state.update(create_ipv6_state(IPv6_ADDRESS1, IPv6_PREFIX1)) vlan101_state.update(ip0_state) vlan_base_state = create_ethernet_iface_state(IFACE0) vlan_base_state.update(create_ipv4_state()) vlan_base_state.update(create_ipv6_state()) expected_state = {nmstate.Interface.KEY: [vlan_base_state, vlan101_state]} expected_state[nmstate.Route.KEY] = { nmstate.Route.CONFIG: get_routes_config( IPv4_GATEWAY1, vlan101_state['name'] ) } assert expected_state == state
def test_translate_nets_without_ip(bridged): networks = { TESTNET1: create_network_config('nic', IFACE0, bridged), TESTNET2: create_network_config('nic', IFACE1, bridged), } state = nmstate.generate_state(networks=networks, bondings={}) eth0_state = create_ethernet_iface_state(IFACE0) eth1_state = create_ethernet_iface_state(IFACE1) disable_iface_ip(eth0_state, eth1_state) expected_state = {nmstate.Interface.KEY: [eth0_state, eth1_state]} if bridged: bridge1_state = create_bridge_iface_state( TESTNET1, IFACE0, options=generate_bridge_options(stp_enabled=False), ) bridge2_state = create_bridge_iface_state( TESTNET2, IFACE1, options=generate_bridge_options(stp_enabled=False), ) disable_iface_ip(bridge1_state, bridge2_state) expected_state[nmstate.Interface.KEY].extend( [bridge1_state, bridge2_state] ) sort_by_name(expected_state[nmstate.Interface.KEY]) assert expected_state == state
def test_translate_net_with_dynamic_ip(self, bridged): networks = { TESTNET1: create_network_config( 'bonding', TESTBOND0, bridged, dynamic_ip_configuration=create_dynamic_ip_configuration( dhcpv4=True, dhcpv6=True, ipv6autoconf=True ), ) } bondings = {TESTBOND0: {'nics': [IFACE0, IFACE1], 'switch': 'legacy'}} state = nmstate.generate_state(networks=networks, bondings=bondings) bond0_state = create_bond_iface_state( TESTBOND0, 'balance-rr', [IFACE0, IFACE1] ) ip_state = create_ipv4_state(dynamic=True) ip_state.update(create_ipv6_state(dynamic=True)) expected_state = {nmstate.Interface.KEY: [bond0_state]} if bridged: disable_iface_ip(bond0_state) bridge1_state = create_bridge_iface_state( TESTNET1, TESTBOND0, options=generate_bridge_options(stp_enabled=False), ) bridge1_state.update(ip_state) expected_state[nmstate.Interface.KEY].extend([bridge1_state]) else: bond0_state.update(ip_state) assert expected_state == state
def test_translate_net_with_ip_on_bond(self, bridged): networks = { TESTNET1: create_network_config( 'bonding', TESTBOND0, bridged, static_ip_configuration=create_static_ip_configuration( IPv4_ADDRESS1, IPv4_NETMASK1, IPv6_ADDRESS1, IPv6_PREFIX1 ), ) } bondings = {TESTBOND0: {'nics': [IFACE0, IFACE1], 'switch': 'legacy'}} state = nmstate.generate_state(networks=networks, bondings=bondings) bond0_state = create_bond_iface_state( TESTBOND0, 'balance-rr', [IFACE0, IFACE1] ) ip_state = create_ipv4_state(IPv4_ADDRESS1, IPv4_PREFIX1) ip_state.update(create_ipv6_state(IPv6_ADDRESS1, IPv6_PREFIX1)) expected_state = {nmstate.Interface.KEY: [bond0_state]} if bridged: disable_iface_ip(bond0_state) bridge1_state = create_bridge_iface_state( TESTNET1, TESTBOND0, options=generate_bridge_options(stp_enabled=False), ) bridge1_state.update(ip_state) expected_state[nmstate.Interface.KEY].extend([bridge1_state]) else: bond0_state.update(ip_state) assert expected_state == state
def test_translate_bridgeless_net_with_ip_on_vlan_on_bond(): networks = { 'testnet1': { 'bonding': 'testbond0', 'bridged': False, 'vlan': 101, 'ipaddr': IPv4_ADDRESS1, 'netmask': IPv4_NETMASK1, 'ipv6addr': IPv6_ADDRESS1 + '/' + IPv6_PREFIX1, 'switch': 'legacy' } } bondings = { 'testbond0': { 'nics': ['eth0', 'eth1'], 'switch': 'legacy' } } state = nmstate.generate_state(networks=networks, bondings=bondings) expected_state = { nmstate.INTERFACES: [ { 'name': 'testbond0', 'type': 'bond', 'state': 'up', 'link-aggregation': { 'mode': 'balance-rr', 'slaves': ['eth0', 'eth1'] } }, { 'name': 'testbond0.101', 'type': 'vlan', 'state': 'up', 'vlan': { 'id': 101, 'base-iface': 'testbond0' }, 'ipv4': { 'enabled': True, 'address': [ {'ip': IPv4_ADDRESS1, 'prefix-length': IPv4_PREFIX1} ] }, 'ipv6': { 'enabled': True, 'address': [ {'ip': IPv6_ADDRESS1, 'prefix-length': IPv6_PREFIX1} ] } } ] } assert expected_state == state
def test_translate_remove_bonds(): bondings = { 'testbond0': {'remove': True} } state = nmstate.generate_state(networks={}, bondings=bondings) expected_state = { nmstate.INTERFACES: [ { 'name': 'testbond0', 'type': 'bond', 'state': 'absent', } ] } assert expected_state == state
def test_translate_bridgeless_net_with_dynamic_ip(): networks = { 'testnet1': { 'bonding': 'testbond0', 'bridged': False, 'bootproto': 'dhcp', 'dhcpv6': True, 'ipv6autoconf': True, 'switch': 'legacy' } } bondings = { 'testbond0': { 'nics': ['eth0', 'eth1'], 'switch': 'legacy' } } state = nmstate.generate_state(networks=networks, bondings=bondings) expected_state = { nmstate.INTERFACES: [ { 'name': 'testbond0', 'type': 'bond', 'state': 'up', 'link-aggregation': { 'mode': 'balance-rr', 'slaves': ['eth0', 'eth1'] }, 'ipv4': { 'enabled': True, 'dhcp': True }, 'ipv6': { 'enabled': True, 'dhcp': True, 'autoconf': True } } ] } assert expected_state == state
def _setup_nmstate(networks, bondings, options, in_rollback): """ Setup the networks using nmstate as the backend provider. nmstate handles the rollback by itself in case of an error during the transaction or in case the resulted state does not include the desired one. In order to support the connectivity check, the "regular" rollback is used (the Transaction context). """ logging.info('Processing setup through nmstate') desired_state = nmstate.generate_state(networks, bondings) nmstate.setup(desired_state, verify_change=not in_rollback) with Transaction(in_rollback=in_rollback) as config: config.networks = { name: attrs for name, attrs in six.viewitems(networks) if not attrs.get('remove') } config.bonds = { name: attrs for name, attrs in six.viewitems(bondings) if not attrs.get('remove') } connectivity.check(options)
def test_translate_bond_with_two_slaves(): bondings = { 'testbond0': { 'nics': ['eth0', 'eth1'], 'switch': 'legacy' } } state = nmstate.generate_state(networks={}, bondings=bondings) expected_state = { nmstate.INTERFACES: [ { 'name': 'testbond0', 'type': 'bond', 'state': 'up', 'link-aggregation': { 'mode': 'balance-rr', 'slaves': ['eth0', 'eth1'] } } ] } assert expected_state == state
def test_translate_bridgeless_nets_without_ip(): networks = { 'testnet1': {'nic': 'eth0', 'bridged': False, 'switch': 'legacy'}, 'testnet2': {'nic': 'eth1', 'bridged': False, 'switch': 'legacy'} } state = nmstate.generate_state(networks=networks, bondings={}) expected_state = { nmstate.INTERFACES: [ { 'name': 'eth0', 'type': 'ethernet', 'state': 'up', }, { 'name': 'eth1', 'type': 'ethernet', 'state': 'up', } ] } _sort_by_name(expected_state[nmstate.INTERFACES]) assert expected_state == state
def test_translate_empty_networks_and_bonds(): state = nmstate.generate_state(networks={}, bondings={}) assert {nmstate.INTERFACES: []} == state
def test_translate_bridgeless_nets_with_ip(): networks = { 'testnet1': { 'nic': 'eth0', 'bridged': False, 'ipaddr': IPv4_ADDRESS1, 'netmask': IPv4_NETMASK1, 'ipv6addr': IPv6_ADDRESS1 + '/' + IPv6_PREFIX1, 'switch': 'legacy' }, 'testnet2': { 'nic': 'eth1', 'bridged': False, 'ipaddr': IPv4_ADDRESS2, 'netmask': IPv4_NETMASK2, 'ipv6addr': IPv6_ADDRESS2 + '/' + IPv6_PREFIX2, 'switch': 'legacy' } } state = nmstate.generate_state(networks=networks, bondings={}) expected_state = { nmstate.INTERFACES: [ { 'name': 'eth0', 'type': 'ethernet', 'state': 'up', 'ipv4': { 'enabled': True, 'address': [ {'ip': IPv4_ADDRESS1, 'prefix-length': IPv4_PREFIX1} ] }, 'ipv6': { 'enabled': True, 'address': [ {'ip': IPv6_ADDRESS1, 'prefix-length': IPv6_PREFIX1} ] } }, { 'name': 'eth1', 'type': 'ethernet', 'state': 'up', 'ipv4': { 'enabled': True, 'address': [ {'ip': IPv4_ADDRESS2, 'prefix-length': IPv4_PREFIX2} ] }, 'ipv6': { 'enabled': True, 'address': [ {'ip': IPv6_ADDRESS2, 'prefix-length': IPv6_PREFIX2} ] } } ] } _sort_by_name(expected_state[nmstate.INTERFACES]) assert expected_state == state