def test_preserve_dns_config_with_empty_state(setup_ipv4_ipv6_name_server): old_state = setup_ipv4_ipv6_name_server netapplier.apply({Interface.KEY: []}) current_state = netinfo.show() assert old_state[DNS.KEY][DNS.CONFIG] == current_state[DNS.KEY][DNS.CONFIG]
def test_add_bond_with_slaves_and_ipv4(eth1_up, eth2_up, setup_remove_bond99): desired_bond_state = { INTERFACES: [{ 'name': 'bond99', 'type': 'bond', 'state': 'up', 'ipv4': { 'enabled': True, 'address': [{ 'ip': '192.168.122.250', 'prefix-length': 24 }] }, 'link-aggregation': { 'mode': 'balance-rr', 'slaves': ['eth1', 'eth2'], 'options': { 'miimon': '140' } }, }] } netapplier.apply(desired_bond_state) assertlib.assert_state(desired_bond_state)
def test_rollback_for_bond(eth1_up, eth2_up): current_state = netinfo.show() desired_state = { INTERFACES: [{ 'name': 'bond99', 'type': 'bond', 'state': 'up', 'ipv4': { 'enabled': True, 'address': [{ 'ip': '192.168.122.250', 'prefix-length': 24 }] }, 'link-aggregation': { 'mode': 'balance-rr', 'slaves': ['eth1', 'eth2'], 'options': { 'miimon': '140' } }, }] } desired_state[INTERFACES][0]['invalid_key'] = 'foo' with pytest.raises(netapplier.DesiredStateIsNotCurrentError): netapplier.apply(desired_state) time.sleep(5) current_state_after_apply = netinfo.show() assert current_state == current_state_after_apply
def test_add_new_bond(netinfo_nm_mock, netapplier_nm_mock): netinfo_nm_mock.device.list_devices.return_value = [] netinfo_nm_mock.ipv4.get_route_running.return_value = [] netinfo_nm_mock.ipv4.get_route_config.return_value = [] netinfo_nm_mock.ipv6.get_route_running.return_value = [] netinfo_nm_mock.ipv6.get_route_config.return_value = [] desired_config = { INTERFACES: [{ Interface.NAME: "bond99", Interface.TYPE: BOND_TYPE, Interface.STATE: InterfaceState.UP, Bond.CONFIG_SUBTREE: { Bond.MODE: BondMode.ROUND_ROBIN, Bond.SLAVES: [], Bond.OPTIONS_SUBTREE: { "miimon": 200 }, }, Interface.IPV4: {}, Interface.IPV6: {}, }] } netapplier.apply(desired_config, verify_change=False) m_apply_changes = netapplier_nm_mock.applier.apply_changes m_apply_changes.assert_called_once_with(desired_config[INTERFACES])
def apply_partial_interface_state(self, interface_state): if isinstance(interface_state, list): interfaces = interface_state else: interfaces = [interface_state] new_partial_state = {"interfaces": interfaces} if self.params.get("debug"): self.result["previous_state"] = self.previous_state self.result["new_partial_state"] = new_partial_state self.result["debugfile"] = write_debug_state( self.module_name, new_partial_state) if self.module.check_mode: new_full_state = deepcopy(self.previous_state) new_full_state.update(new_partial_state) self.result["state"] = new_full_state # TODO: maybe compare only the state of the defined interfaces if self.previous_state != new_full_state: self.result["changed"] = True self.module.exit_json(**self.result) else: netapplier.apply(new_partial_state) current_state = netinfo.show() if current_state != self.previous_state: self.result["changed"] = True self.result["state"] = current_state self.module.exit_json(**self.result)
def test_edit_static_ipv6_address_and_prefix(setup_eth1_ipv6): eth1_setup = setup_eth1_ipv6[INTERFACES][0] desired_state = { INTERFACES: [ { 'name': 'eth1', 'type': 'ethernet', 'state': 'up', 'ipv6': { 'enabled': True, 'address': [ {'ip': IPV6_ADDRESS2, 'prefix-length': 24} ] } } ] } netapplier.apply(desired_state) eth1_desired_state = desired_state[INTERFACES][0] current_state = statelib.show_only(('eth1',)) eth1_current_state = current_state[INTERFACES][0] assert (eth1_desired_state['ipv6']['address'][0] in eth1_current_state['ipv6']['address']) assert (eth1_setup['ipv6']['address'][0] not in eth1_current_state['ipv6']['address'])
def test_iface_admin_state_change(netinfo_nm_mock, netapplier_nm_mock): current_config = { 'interfaces': [{ 'name': 'foo', 'type': 'unknown', 'state': 'up', 'ipv4': { 'enabled': False, }, }] } desired_config = copy.deepcopy(current_config) netinfo_nm_mock.device.list_devices.return_value = ['one-item'] netinfo_nm_mock.translator.Nm2Api.get_common_device_info.return_value = ( current_config['interfaces'][0]) netinfo_nm_mock.bond.is_bond_type_id.return_value = False netinfo_nm_mock.ovs.is_ovs_bridge_type_id.return_value = False netinfo_nm_mock.ovs.is_ovs_port_type_id.return_value = False netinfo_nm_mock.ipv4.get_info.return_value = ( current_config['interfaces'][0]['ipv4']) desired_config['interfaces'][0]['state'] = 'down' netapplier.apply(desired_config) netapplier_nm_mock.applier.set_ifaces_admin_state.assert_has_calls( [mock.call([]), mock.call(desired_config['interfaces'])])
def test_ipv6_dhcp_switch_on_to_off(dhcp_env): desired_state = statelib.show_only((DHCP_CLI_NIC, )) dhcp_cli_desired_state = desired_state[INTERFACES][0] dhcp_cli_desired_state['state'] = 'up' dhcp_cli_desired_state['ipv6']['dhcp'] = True dhcp_cli_desired_state['ipv6']['autoconf'] = True dhcp_cli_desired_state['ipv6']['auto-gateway'] = True dhcp_cli_desired_state['ipv6']['auto-dns'] = True dhcp_cli_desired_state['ipv6']['auto-routes'] = True netapplier.apply(desired_state) assertlib.assert_state(desired_state) time.sleep(5) # libnm does not wait on ipv6-ra or DHCPv6. assert _has_ipv6_auto_gateway() assert _has_ipv6_auto_extra_route() assert _has_ipv6_auto_nameserver() # disable dhcp and make sure dns, route, gone. desired_state = statelib.show_only((DHCP_CLI_NIC, )) dhcp_cli_desired_state = desired_state[INTERFACES][0] dhcp_cli_desired_state['state'] = 'up' dhcp_cli_desired_state['ipv6']['dhcp'] = False dhcp_cli_desired_state['ipv6']['autoconf'] = False netapplier.apply(desired_state) assertlib.assert_state(desired_state) assert not _has_ipv6_auto_gateway() assert not _has_ipv6_auto_extra_route() assert not _has_ipv6_auto_nameserver()
def test_add_new_bond( plugin_context_mock, show_with_plugins_mock, net_state_mock, ): show_with_plugins_mock.return_value = {} desired_config = { Interface.KEY: [{ Interface.NAME: "bond99", Interface.TYPE: BOND_TYPE, Interface.STATE: InterfaceState.UP, Bond.CONFIG_SUBTREE: { Bond.MODE: BondMode.ROUND_ROBIN, Bond.SLAVES: [], Bond.OPTIONS_SUBTREE: { "miimon": 200 }, }, Interface.IPV4: {}, Interface.IPV6: {}, }] } plugin = mock.MagicMock() plugin_context_mock.return_value.__enter__.return_value = [plugin] netapplier.apply(desired_config, verify_change=False) plugin.apply_changes.assert_called_once_with( net_state_mock(desired_config, {}), True)
def test_dhcp_for_bond_with_ip_address_and_slave(dhcp_env, setup_remove_dhcpcli, setup_remove_bond99): desired_state = { INTERFACES: [{ 'name': 'bond99', 'type': 'bond', 'state': 'up', 'ipv4': { 'enabled': True, 'dhcp': True }, 'link-aggregation': { 'mode': 'balance-rr', 'slaves': [DHCP_CLI_NIC], 'options': { 'miimon': '140' } } }] } netapplier.apply(desired_state) assertlib.assert_state(desired_state)
def test_ipv4_dhcp_switch_on_to_off(dhcp_env): desired_state = statelib.show_only((DHCP_CLI_NIC, )) dhcp_cli_desired_state = desired_state[INTERFACES][0] dhcp_cli_desired_state['state'] = 'up' dhcp_cli_desired_state['ipv4']['enabled'] = True dhcp_cli_desired_state['ipv4']['dhcp'] = True dhcp_cli_desired_state['ipv4']['auto-gateway'] = True dhcp_cli_desired_state['ipv4']['auto-dns'] = True dhcp_cli_desired_state['ipv4']['auto-routes'] = True dhcp_cli_desired_state['ipv6']['enabled'] = True netapplier.apply(desired_state) assertlib.assert_state(desired_state) time.sleep(5) # wait to get resolv.conf updated assert _has_ipv4_dhcp_nameserver() assert _has_ipv4_dhcp_gateway() assert _has_ipv4_classless_route() # disable dhcp and make sure dns, route, gone. desired_state = statelib.show_only((DHCP_CLI_NIC, )) dhcp_cli_desired_state = desired_state[INTERFACES][0] dhcp_cli_desired_state['state'] = 'up' dhcp_cli_desired_state['ipv4']['enabled'] = True dhcp_cli_desired_state['ipv4']['dhcp'] = False dhcp_cli_desired_state['ipv6']['enabled'] = True netapplier.apply(desired_state) assertlib.assert_state(desired_state) assert not _has_ipv4_dhcp_nameserver() assert not _has_ipv4_dhcp_gateway() assert not _has_ipv4_classless_route()
def test_ipv6_autoconf_only(dhcp_env): desired_state = statelib.show_only((DHCP_CLI_NIC, )) dhcp_cli_desired_state = desired_state[INTERFACES][0] dhcp_cli_desired_state['ipv6']['dhcp'] = False dhcp_cli_desired_state['ipv6']['autoconf'] = True netapplier.apply(desired_state)
def test_ipv6_dhcp_only(dhcp_env): desired_state = statelib.show_only((DHCP_CLI_NIC, )) dhcp_cli_desired_state = desired_state[INTERFACES][0] dhcp_cli_desired_state['state'] = 'up' dhcp_cli_desired_state['ipv6']['enabled'] = True dhcp_cli_desired_state['ipv6']['dhcp'] = True dhcp_cli_desired_state['ipv6']['autoconf'] = False dhcp_cli_desired_state['ipv6']['auto-routes'] = True dhcp_cli_desired_state['ipv6']['auto-dns'] = True dhcp_cli_desired_state['ipv6']['auto-gateway'] = True netapplier.apply(desired_state) assertlib.assert_state(desired_state) time.sleep(5) # libnm does not wait on ipv6-ra or DHCPv6. current_state = statelib.show_only((DHCP_CLI_NIC, )) dhcp_cli_current_state = current_state[INTERFACES][0] has_dhcp_ip_addr = False for addr in dhcp_cli_current_state['ipv6']['address']: if addr['prefix-length'] == 128 and DHCP_SRV_IP6_PREFIX in addr['ip']: has_dhcp_ip_addr = True break assert has_dhcp_ip_addr assert not _has_ipv6_auto_gateway() # DHCPv6 does not provide routes assert not _has_ipv6_auto_extra_route() # DHCPv6 does not provide routes assert _has_ipv6_auto_nameserver()
def test_add_new_bond(netinfo_nm_mock, netapplier_nm_mock): netinfo_nm_mock.device.list_devices.return_value = [] netinfo_nm_mock.ipv4.get_route_running.return_value = [] netinfo_nm_mock.ipv4.get_route_config.return_value = [] netinfo_nm_mock.ipv6.get_route_running.return_value = [] netinfo_nm_mock.ipv6.get_route_config.return_value = [] desired_config = { INTERFACES: [{ 'name': 'bond99', 'type': BOND_TYPE, 'state': 'up', 'link-aggregation': { 'mode': 'balance-rr', 'slaves': [], 'options': { 'miimon': 200 }, }, 'ipv4': {}, 'ipv6': {}, }] } netapplier.apply(desired_config, verify_change=False) m_prepare = netapplier_nm_mock.applier.prepare_edited_ifaces_configuration m_prepare.assert_called_once_with([]) m_prepare = netapplier_nm_mock.applier.prepare_new_ifaces_configuration m_prepare.assert_called_once_with(desired_config[INTERFACES])
def test_iface_admin_state_change( show_with_plugins_mock, plugin_context_mock, net_state_mock, ): current_config = { Interface.KEY: [{ Interface.NAME: "foo", Interface.TYPE: InterfaceType.DUMMY, Interface.STATE: InterfaceState.UP, Interface.IPV4: { InterfaceIPv4.ENABLED: False }, Interface.IPV6: { InterfaceIPv6.ENABLED: False }, }] } desired_config = copy.deepcopy(current_config) desired_config[Interface.KEY][0][Interface.STATE] = InterfaceState.DOWN show_with_plugins_mock.return_value = current_config plugin = mock.MagicMock() plugin_context_mock.return_value.__enter__.return_value = [plugin] netapplier.apply(desired_config, verify_change=False) plugin.apply_changes.assert_called_once_with( net_state_mock(desired_config, current_config), True)
def test_add_ifaces_with_same_static_ipv6_address_in_one_transaction(eth1_up, eth2_up): desired_state = { INTERFACES: [ { 'name': 'eth1', 'type': 'ethernet', 'state': 'up', 'ipv6': { 'enabled': True, 'address': [ {'ip': IPV6_ADDRESS1, 'prefix-length': 64} ] } }, { 'name': 'eth2', 'type': 'ethernet', 'state': 'up', 'ipv6': { 'enabled': True, 'address': [ {'ip': IPV6_ADDRESS1, 'prefix-length': 64} ] } } ] } netapplier.apply(desired_state) assertlib.assert_state(desired_state)
def test_add_new_bond(netinfo_nm_mock, netapplier_nm_mock): netinfo_nm_mock.device.list_devices.return_value = [] netinfo_nm_mock.ipv4.get_route_running.return_value = [] netinfo_nm_mock.ipv4.get_route_config.return_value = [] netinfo_nm_mock.ipv6.get_route_running.return_value = [] netinfo_nm_mock.ipv6.get_route_config.return_value = [] desired_config = { INTERFACES: [ { "name": "bond99", "type": BOND_TYPE, "state": "up", "link-aggregation": { "mode": "balance-rr", "slaves": [], "options": {"miimon": 200}, }, "ipv4": {}, "ipv6": {}, } ] } netapplier.apply(desired_config, verify_change=False) m_prepare = netapplier_nm_mock.applier.prepare_edited_ifaces_configuration m_prepare.assert_called_once_with([]) m_prepare = netapplier_nm_mock.applier.prepare_new_ifaces_configuration m_prepare.assert_called_once_with(desired_config[INTERFACES])
def test_add_new_bond(netinfo_nm_mock, netapplier_nm_mock): netinfo_nm_mock.device.list_devices.return_value = [] desired_config = { 'interfaces': [{ 'name': 'bond99', 'type': BOND_TYPE, 'state': 'up', 'link-aggregation': { 'mode': 'balance-rr', 'slaves': [], 'options': { 'miimon': 200, } } }] } netapplier.apply(desired_config) m_prepare = netapplier_nm_mock.applier.prepare_edited_ifaces_configuration m_prepare.assert_called_once_with([]) m_prepare = netapplier_nm_mock.applier.prepare_new_ifaces_configuration m_prepare.assert_called_once_with(desired_config['interfaces'])
def test_upper_limit_jambo_iface_mtu(): desired_state = statelib.show_only(('eth1',)) eth1_desired_state = desired_state[INTERFACES][0] eth1_desired_state['mtu'] = 9000 netapplier.apply(desired_state) assertlib.assert_state(desired_state)
def test_increase_more_than_jambo_iface_mtu(): desired_state = statelib.show_only(('eth1',)) eth1_desired_state = desired_state[INTERFACES][0] eth1_desired_state['mtu'] = 10000 netapplier.apply(desired_state) assertlib.assert_state(desired_state)
def test_decrease_to_ipv6_min_ethernet_frame_size_iface_mtu(): desired_state = statelib.show_only(('eth1',)) eth1_desired_state = desired_state[INTERFACES][0] eth1_desired_state['mtu'] = 1280 netapplier.apply(desired_state) assertlib.assert_state(desired_state)
def test_dns_edit_nameserver_with_static_gateway(dns_config): desired_state = { Interface.KEY: _get_test_iface_states(), Route.KEY: {Route.CONFIG: _gen_default_gateway_route()}, DNS.KEY: {DNS.CONFIG: dns_config}, } netapplier.apply(desired_state) current_state = netinfo.show() assert dns_config == current_state[DNS.KEY][DNS.CONFIG]
def dns_test_env(eth1_up, eth2_up): yield # Remove DNS config as it be saved in eth1 or eth2 which might trigger # failure when bring eth1/eth2 down. desired_state = { Interface.KEY: _get_test_iface_states(), DNS.KEY: {DNS.CONFIG: {DNS.SERVER: [], DNS.SEARCH: []}}, } netapplier.apply(desired_state)
def test_error_apply(): with pytest.raises(TypeError): # pylint: disable=too-many-function-args netapplier.apply({"interfaces": []}, True) # pylint: enable=too-many-function-args with pytest.raises(TypeError): # pylint: disable=too-many-function-args netapplier.apply({"interfaces": []}, True, True, 0)
def test_slave_ipaddr_learned_via_dhcp_added_as_static_to_linux_bridge( dhcp_env, setup_remove_dhcpcli): desired_state = { INTERFACES: [{ 'name': 'dhcpcli', 'type': 'ethernet', 'state': 'up', 'ipv4': { 'enabled': True, 'dhcp': True }, }] } netapplier.apply(desired_state) current_state = statelib.show_only(('dhcpcli', )) client_current_state = current_state[INTERFACES][0] dhcpcli_ip = client_current_state['ipv4']['address'] bridge_desired_state = { INTERFACES: [{ 'name': 'linux-br0', 'type': 'linux-bridge', 'state': 'up', 'ipv4': { 'enabled': True, 'dhcp': False, 'address': dhcpcli_ip }, 'bridge': { 'options': {}, 'port': [{ 'name': 'dhcpcli', 'stp-hairpin-mode': False, 'stp-path-cost': 100, 'stp-priority': 32 }] } }, { 'name': 'dhcpcli', 'type': 'ethernet', 'state': 'up', 'ipv4': { 'enabled': False, 'dhcp': False }, 'ipv6': { 'enabled': False, 'dhcp': False } }] } netapplier.apply(bridge_desired_state) assertlib.assert_state(bridge_desired_state)
def setup_remove_dhcpcli(): yield remove_bond = { INTERFACES: [{ 'name': 'dhcpcli', 'type': 'ethernet', 'state': 'absent' }] } netapplier.apply(remove_bond)
def setup_remove_bond99(): yield remove_bond = { INTERFACES: [{ 'name': 'bond99', 'type': 'bond', 'state': 'absent' }] } netapplier.apply(remove_bond)
def test_decrease_to_negative_iface_mtu(): desired_state = statelib.show_only(('eth1',)) origin_desired_state = copy.deepcopy(desired_state) eth1_desired_state = desired_state[INTERFACES][0] eth1_desired_state['mtu'] = -1 with pytest.raises(js.ValidationError) as err: netapplier.apply(desired_state) assert '-1' in err.value.args[0] assertlib.assert_state(origin_desired_state)
def test_remove_one_of_the_bond_slaves(eth1_up, eth2_up): with bond_interface(name='bond99', slaves=['eth1', 'eth2']) as bond_state: bond_state[INTERFACES][0]['link-aggregation']['slaves'] = ['eth2'] netapplier.apply(bond_state) current_state = statelib.show_only(('bond99', )) bond99_cur_state = current_state[INTERFACES][0] assert bond99_cur_state['link-aggregation']['slaves'] == ['eth2']
def apply_state(statedata, verify_change): use_yaml = False # JSON dictionaries start with a curly brace if statedata[0] == '{': state = json.loads(statedata) else: state = yaml.load(statedata) use_yaml = True netapplier.apply(state, verify_change) print('Desired state applied: ') print_state(state, use_yaml=use_yaml)
def setup(desired_state, verify_change): netapplier.apply(desired_state, verify_change)