def test_server_tag_global_option(): cfg = setup_server_for_config_backend_cmds(server_tag="abc") _set_server_tag("xyz") _set_server_tag("abc") cfg.add_subnet(server_tags="abc") cfg.add_option(server_tags=["all"], code=22, csv_format=True, data="2001::1", name="sip-server-addr", space="dhcp6") abc = _get_server_config() # server should have just one option now, from "all" assert len(abc["arguments"]["Dhcp6"]["option-data"]) == 1 assert abc["arguments"]["Dhcp6"]["option-data"][0]["data"] == "2001::1" get_address(req_opts=[22], exp_option={"code": 22, "data": "2001::1"}) cfg.add_option(server_tags=["abc"], code=22, csv_format=True, data="2001::2", name="sip-server-addr", space="dhcp6") abc = _get_server_config() # now, despite the fact that two tags are for server "abc" ("abc" and "all") option "all" should be overwritten assert len(abc["arguments"]["Dhcp6"]["option-data"]) == 1 assert abc["arguments"]["Dhcp6"]["option-data"][0]["data"] == "2001::2" get_address(req_opts=[22], exp_option={"code": 22, "data": "2001::2"}) cfg.add_option(server_tags=["xyz"], code=22, csv_format=True, data="2001::3", name="sip-server-addr", space="dhcp6") abc = _get_server_config() # after adding "xyz" option, there should not be any change in running kea assert len(abc["arguments"]["Dhcp6"]["option-data"]) == 1 assert abc["arguments"]["Dhcp6"]["option-data"][0]["data"] == "2001::2" get_address(req_opts=[22], exp_option={"code": 22, "data": "2001::2"}) srv_control.start_srv('DHCP', 'stopped') cfg_xyz = setup_server_for_config_backend_cmds(server_tag="xyz") cfg_xyz.add_subnet(server_tags="xyz") abc = _get_server_config() # new kea is started with tag "xyz" assert len(abc["arguments"]["Dhcp6"]["option-data"]) == 1 assert abc["arguments"]["Dhcp6"]["option-data"][0]["data"] == "2001::3" get_address(req_opts=[22], exp_option={"code": 22, "data": "2001::3"}) # delete option with tag "xyz", kea should download tag "all" cfg_xyz.del_option(server_tags=["xyz"], code=22) xyz = _get_server_config() assert len(xyz["arguments"]["Dhcp6"]["option-data"]) == 1 assert xyz["arguments"]["Dhcp6"]["option-data"][0]["data"] == "2001::1" get_address(req_opts=[22], exp_option={"code": 22, "data": "2001::1"})
def test_server_tag_global_parameter(): cfg = setup_server_for_config_backend_cmds(server_tag="abc") _set_server_tag("xyz") _set_server_tag("abc") cfg.add_subnet(server_tags=["abc"], subnet="2001:db8:1::/64", id=1, pools=[{'pool': "2001:db8:1::1-2001:db8:1::100"}]) cfg.set_global_parameter(server_tags=["all"], valid_lifetime=7700) get_address(mac_addr='00:00:00:00:00:03', exp_ia_na_iaaddr_validlft=7700) # this update should not change anything cfg.set_global_parameter(server_tags=["xyz"], valid_lifetime=5001) xyz = _get_server_config() assert xyz["arguments"]["Dhcp6"]["valid-lifetime"] == 7700 get_address(mac_addr='00:00:00:00:00:04', exp_ia_na_iaaddr_validlft=7700) # this should overwrite "all" cfg.set_global_parameter(server_tags=["abc"], valid_lifetime=5002) xyz = _get_server_config() assert xyz["arguments"]["Dhcp6"]["valid-lifetime"] == 5002 get_address(mac_addr='00:00:00:00:00:05', exp_ia_na_iaaddr_validlft=5002) srv_control.start_srv('DHCP', 'stopped') cfg = setup_server_for_config_backend_cmds(server_tag="xyz") cfg.add_subnet(server_tags=["xyz"], subnet="2001:db8:1::/64", id=1, pools=[{'pool': "2001:db8:1::1-2001:db8:1::100"}]) # now server "xyz" has two parameters configured, should use "xyz" xyz = _get_server_config() assert xyz["arguments"]["Dhcp6"]["valid-lifetime"] == 5001 get_address(mac_addr='00:00:00:00:00:06', exp_ia_na_iaaddr_validlft=5001)
def test_server_tag_network(): cfg = setup_server_for_config_backend_cmds(server_tag="abc") _set_server_tag("xyz") _set_server_tag("abc") cfg.add_network(server_tags=["abc"], name="flor1") cfg.add_subnet(shared_network_name="flor1", server_tags=["abc"], subnet="2001:db8:1::/64", id=1, pools=[{'pool': "2001:db8:1::1-2001:db8:1::1"}]) xyz = _get_server_config() assert len(xyz["arguments"]["Dhcp6"]["shared-networks"][0]["subnet6"]) == 1 assert xyz["arguments"]["Dhcp6"]["shared-networks"][0]["subnet6"][0]["subnet"] == "2001:db8:1::/64" get_address(mac_addr='00:00:00:00:00:03', exp_addr='2001:db8:1::1') cfg.add_network(server_tags=["xyz"], name="flor2") cfg.add_subnet(shared_network_name="flor2", server_tags=["xyz"], subnet="2001:db8:2::/64", id=2, pools=[{'pool': "2001:db8:2::5-2001:db8:2::5"}]) # we still want just one network with one subnet xyz = _get_server_config() assert len(xyz["arguments"]["Dhcp6"]["shared-networks"]) == 1 assert len(xyz["arguments"]["Dhcp6"]["shared-networks"][0]["subnet6"]) == 1 assert xyz["arguments"]["Dhcp6"]["shared-networks"][0]["subnet6"][0]["subnet"] == "2001:db8:1::/64" get_rejected(mac_addr='00:00:00:00:00:10') srv_control.start_srv('DHCP', 'stopped') setup_server_for_config_backend_cmds(server_tag="xyz") get_address(mac_addr='00:00:00:00:00:04', exp_addr='2001:db8:2::5') # we still want just one network with one subnet but different subnet, from xyz xyz = _get_server_config() assert len(xyz["arguments"]["Dhcp6"]["shared-networks"]) == 1 assert len(xyz["arguments"]["Dhcp6"]["shared-networks"][0]["subnet6"]) == 1 assert xyz["arguments"]["Dhcp6"]["shared-networks"][0]["subnet6"][0]["subnet"] == "2001:db8:2::/64" cfg.add_subnet(shared_network_name="flor2", server_tags=["all"], subnet="2001:db8:3::/64", id=3, pools=[{'pool': "2001:db8:3::5-2001:db8:3::5"}]) # model was incomplete on previous step so I can't use del_subnet method because it's again # forcing checking cmd = dict(command="remote-subnet6-del-by-prefix", arguments={"remote": {"type": "mysql"}, "subnets": [{"subnet": "2001:db8:2::/64"}]}) srv_msg.send_ctrl_cmd(cmd, exp_result=0) xyz = _get_server_config(reload_kea=True) assert len(xyz["arguments"]["Dhcp6"]["shared-networks"][0]["subnet6"]) == 1 assert xyz["arguments"]["Dhcp6"]["shared-networks"][0]["subnet6"][0]["subnet"] == "2001:db8:3::/64" # this time we expect address from "all" get_address(mac_addr='00:00:00:00:00:05', exp_addr='2001:db8:3::5')
def run_around_tests(): setup_server_for_config_backend_cmds( config_control={"config-fetch-wait-time": 1}, force_reload=False) cmd = dict(command="remote-server6-set", arguments={ "remote": { "type": "mysql" }, "servers": [{ "server-tag": "abc" }] }) srv_msg.send_ctrl_cmd(cmd, exp_result=0)
def test_echo_client_id(initial_echo_client_id): # Set initial value of echo-client-id in config file and then change it # using cb-cmds. Observe if client-id is included in responses according to settings. # Different initial settings for echo-client-id: default (=True), True and False. cfg = setup_server_for_config_backend_cmds( echo_client_id=initial_echo_client_id) cfg.add_subnet() # Request address and check if client-id is returned according to initial setting. get_address(client_id='00010203040506', exp_client_id='00010203040506' if initial_echo_client_id in [None, True] else 'missing') # Change setting to NOT return client-id. It should be missing in responses. cfg.set_global_parameter(echo_client_id=False) get_address(client_id='10010203040506', exp_client_id='missing') # Change again setting to return client-id. It should be missing in responses. cfg.set_global_parameter(echo_client_id=True) get_address(client_id='20010203040506', exp_client_id='20010203040506') # Change setting to NOT return client-id. It should be missing in responses. cfg.set_global_parameter(echo_client_id=False) get_address(client_id='30010203040506', exp_client_id='missing')
def test_interface_id_in_subnet(): cfg = setup_server_for_config_backend_cmds() # relay_addr='7::1' always set to avoid matching thie relay agent # to defined subnet # create a subnet with specific relay agent interface-id subnet_cfg, _ = cfg.add_subnet(interface_id='vlan-a') # client 1 behind interface-id 'vlan-a' should get a lease get_address(mac_addr='00:00:00:00:00:01', interface_id='vlan-a', relay_addr='7::1') # client 2 behind interface-id 'vlan-b' should NOT get any lease get_rejected(mac_addr='00:00:00:00:00:02', interface_id='vlan-b', relay_addr='7::1') # change interface-id in subnet from 'vlan-a' to 'vlan-b' subnet_cfg.update(interface_id='vlan-b') # client 3 now should get a lease over interface-id 'vlan-b' get_address(mac_addr='00:00:00:00:00:03', interface_id='vlan-b', relay_addr='7::1') # but client 4 now behind interface-id 'vlan-a' should NOT get any lease get_rejected(mac_addr='00:00:00:00:00:04', interface_id='vlan-a', relay_addr='7::1')
def test_interface_id_in_network(): cfg = setup_server_for_config_backend_cmds() # relay_addr='7::1' always set to avoid matching thie relay agent # to defined subnet # create a network with specific relay agent interface-id network_cfg, _ = cfg.add_network(interface_id='vlan-a') subnet_cfg, _ = cfg.add_subnet(network=network_cfg, interface='') # client 1 behind interface-id 'vlan-a' should get a lease get_address(mac_addr='00:00:00:00:00:01', interface_id='vlan-a', relay_addr='7::1') # client 2 behind interface-id 'vlan-b' should NOT get any lease get_rejected(mac_addr='00:00:00:00:00:02', interface_id='vlan-b', relay_addr='7::1') # change interface-id in network from 'vlan-a' to 'vlan-b' network_cfg.update(interface_id='vlan-b') # client 3 now should get a lease over interface-id 'vlan-b' get_address(mac_addr='00:00:00:00:00:03', interface_id='vlan-b', relay_addr='7::1') # but client 4 now behind interface-id 'vlan-a' should NOT get any lease get_rejected(mac_addr='00:00:00:00:00:04', interface_id='vlan-a', relay_addr='7::1') # set interface-id in subnet from 'vlan-c' ie. override the one in network subnet_cfg.update(interface_id='vlan-c') # client 5 now should get a lease over interface-id 'vlan-c' get_address(mac_addr='00:00:00:00:00:05', interface_id='vlan-b', relay_addr='7::1') # but client 6 now behind interface-id 'vlan-b' (that is set in network) # should NOT get any lease get_rejected(mac_addr='00:00:00:00:00:06', interface_id='vlan-b', relay_addr='7::1')
def test_calculate_timers_init_v4(initial_calculate_tee_times, initial_t1_percent, initial_t2_percent, initial_valid_lifetime): # check initial values of different timers in config file cfg = setup_server_for_config_backend_cmds( calculate_tee_times=initial_calculate_tee_times, t1_percent=initial_t1_percent, t2_percent=initial_t2_percent, valid_lifetime=initial_valid_lifetime) # define one, default subnet cfg.add_subnet() calculate_tee_times = initial_calculate_tee_times if initial_calculate_tee_times is not None else False valid_lifetime = initial_valid_lifetime if initial_valid_lifetime is not None else get_cfg_default( 'valid-lifetime') if calculate_tee_times: t1_percent = initial_t1_percent if initial_t1_percent is not None else get_cfg_default( 't1-percent') t2_percent = initial_t2_percent if initial_t2_percent is not None else get_cfg_default( 't2-percent') renew_timer = int(t1_percent * valid_lifetime) rebind_timer = int(t2_percent * valid_lifetime) else: renew_timer = None rebind_timer = None # check getting address from this subnet get_address(exp_renew_timer=renew_timer, exp_rebind_timer=rebind_timer, exp_lease_time=valid_lifetime)
def test_subnet_and_rebind_timer(dhcp_version): # pylint: disable=unused-argument # change rebind timer on different levels (global and subnet) # and check if these changes are properly reflected in received ACKs cfg = setup_server_for_config_backend_cmds() # define one, default subnet cfg.add_subnet() # check getting address from this subnet get_address() # change global renew_timer to 1sec and now check # if received lease has renew_timer accordingly set cfg.set_global_parameter(rebind_timer=1) get_address(exp_rebind_timer=1) # change rebind_timer on subnet level to 1000sec # and now check if received lease has rebind_timer accordingly set cfg.update_subnet(rebind_timer=1000) get_address(exp_rebind_timer=1000) # change again rebind_timer on subnet level to 1sec # and now check if received lease has rebind_timer accordingly set cfg.update_subnet(rebind_timer=1) get_address(exp_rebind_timer=1) # change again rebind_timer on global level to 500sec # and now check if it is ignored ans it still should be taken # from subnet level cfg.set_global_parameter(rebind_timer=500) get_address(exp_rebind_timer=1)
def test_subnet_and_timers_renew_less(dhcp_version): # pylint: disable=unused-argument # change both renew and rebind timers on different levels (global and subnet) # and check if these changes are properly reflected in received ACKs # in this case renew is always less than rebind time so both should # be present in responses cfg = setup_server_for_config_backend_cmds() # define one, default subnet cfg.add_subnet() # check getting address from this subnet get_address() # set renew and rebind timers on global level # and check if they are present in ACK packet cfg.set_global_parameter(renew_timer=100, rebind_timer=1000) get_address(exp_renew_timer=100, exp_rebind_timer=1000) # set renew and rebind timers on subnet level # and check if they are present in ACK packet cfg.update_subnet(renew_timer=200, rebind_timer=2000) get_address(exp_renew_timer=200, exp_rebind_timer=2000) # change renew and rebind timers on subnet level # and check if they are present in ACK packet cfg.update_subnet(renew_timer=300, rebind_timer=3000) get_address(exp_renew_timer=300, exp_rebind_timer=3000) # change renew and rebind timers on global level # and check if they are not reflected in ACK packet, # they still should be taken from subnet cfg.set_global_parameter(renew_timer=400, rebind_timer=4000) get_address(exp_renew_timer=300, exp_rebind_timer=3000)
def test_interface_id_in_network(): cfg = setup_server_for_config_backend_cmds() # create a network with specific relay agent interface-id network_cfg, _ = cfg.add_network(interface_id='vlan-a') subnet_cfg, _ = cfg.add_subnet(network=network_cfg) # client 1 behind interface-id 'vlan-a' should get a lease get_address(mac_addr='00:00:00:00:00:01', interface_id='vlan-a') # client 2 behind interface-id 'vlan-b' should NOT get any lease get_rejected(mac_addr='00:00:00:00:00:02', interface_id='vlan-b') # change interface-id in network from 'vlan-a' to 'vlan-b' network_cfg.update(interface_id='vlan-b') # client 3 now should get a lease over interface-id 'vlan-b' get_address(mac_addr='00:00:00:00:00:03', interface_id='vlan-b') # but client 4 now behind interface-id 'vlan-a' should NOT get any lease get_rejected(mac_addr='00:00:00:00:00:04', interface_id='vlan-a') # set interface-id in subnet from 'vlan-c' ie. override the one in network subnet_cfg.update(interface_id='vlan-c') # client 5 now should get a lease over interface-id 'vlan-c' get_address(mac_addr='00:00:00:00:00:05', interface_id='vlan-b') # but client 6 now behind interface-id 'vlan-b' (that is set in network) # should NOT get any lease get_rejected(mac_addr='00:00:00:00:00:06', interface_id='vlan-b')
def test_class_in_subnet(dhcp_version): # prepare initial config with 1 class 'modem' for 1 client with specificed MAC address init_cfg = {'client-classes': [{'name': 'modem'}]} if dhcp_version == 'v4': init_cfg['client-classes'][0]['test'] = "hexstring(pkt4.mac, ':') == '00:00:00:00:00:01'" else: init_cfg['client-classes'][0]['test'] = "hexstring(option[1].hex, ':') == '00:03:00:01:00:00:00:00:00:01'" cfg = setup_server_for_config_backend_cmds(**init_cfg) # add 1 subnet that permits only client from 'modem' class subnet_cfg, _ = cfg.add_subnet(client_class='modem') # client from 'modem' class with specific MAC address should get lease get_address(mac_addr="00:00:00:00:00:01", exp_addr='192.168.50.1' if dhcp_version == 'v4' else '2001:db8:1::1') # client with another MAC address should be rejected get_rejected(mac_addr='00:00:00:00:00:02') # change class name in subnet and now the first client should not be given a lease # as class names do not match subnet_cfg.update(client_class='not-modem') get_rejected(mac_addr='00:00:00:00:00:01') # change class name in subnet to '' ie. reset it, ie. make the subnet open to any client # and now unclassified should get a lease subnet_cfg.update(client_class='') get_address(mac_addr="00:00:00:00:00:03", exp_addr='192.168.50.2' if dhcp_version == 'v4' else '2001:db8:1::2')
def test_relay_in_subnet(dhcp_version): relay_addr_1 = "10.0.0.1" if dhcp_version == 'v4' else '10:0:0::1' relay_addr_2 = "10.0.0.2" if dhcp_version == 'v4' else '10:0:0::2' exp_addr_1 = '192.168.50.1' if dhcp_version == 'v4' else '2001:db8:1::1' exp_addr_2 = '192.168.50.2' if dhcp_version == 'v4' else '2001:db8:1::2' exp_addr_3 = '192.168.50.3' if dhcp_version == 'v4' else '2001:db8:1::3' cfg = setup_server_for_config_backend_cmds() # create a subnet with specific IP address for relay agent subnet_cfg, _ = cfg.add_subnet(relay={"ip-addresses": [relay_addr_1]}) # client 1 behind relay agent 1 should get a lease get_address(mac_addr='00:00:00:00:00:01', relay_addr=relay_addr_1, exp_addr=exp_addr_1) # client 2 behing unknown relay agent 2 should NOT get any lease get_rejected(mac_addr='00:00:00:00:00:02', relay_addr=relay_addr_2) # add another relay agent 2 subnet_cfg.update(relay={"ip-addresses": [relay_addr_1, relay_addr_2]}) # client 2 now should get a lease get_address(mac_addr='00:00:00:00:00:02', relay_addr=relay_addr_2, exp_addr=exp_addr_2) # another client 3 behind relay agent 1 still should be able to get a lease get_address(mac_addr='00:00:00:00:00:03', relay_addr=relay_addr_1, exp_addr=exp_addr_3)
def test_auto_reload_1second(dhcp_version): # prepare initial config with fetch wait time set to 1 second cfg = setup_server_for_config_backend_cmds( config_control={"config-fetch-wait-time": 1}, force_reload=False) dhcp_key = 'Dhcp%s' % dhcp_version[1] subnet_key = 'subnet%s' % dhcp_version[1] # check config that there is no subnets and fetch time is 1 new_cfg = get_config() assert len(new_cfg[dhcp_key][subnet_key]) == 0 assert new_cfg[dhcp_key]['config-control']['config-fetch-wait-time'] == 1 # add subnet and wait 2 seconds that config is reloaded automatically cfg.add_subnet() time.sleep(2) # now check if there is a subnet in config new_cfg = get_config() assert len(new_cfg[dhcp_key][subnet_key]) == 1 assert new_cfg[dhcp_key][subnet_key][0]['subnet'] == list( cfg.subnets.keys())[0] # there is subnet so getting address should succeed get_address()
def test_subnet_and_timers_renew_less(dhcp_version): # pylint: disable=unused-argument # change both renew and rebind timers on different levels (global and subnet) # and check if these changes are properly reflected in received ACKs # in this case renew is always less than rebind time so both should # be present in responses cfg = setup_server_for_config_backend_cmds() # define one, default subnet cfg.add_subnet() # check getting address from this subnet get_address() # set renew and rebind timers on global level # and check if they are present in ACK packet cfg.set_global_parameter(renew_timer=100, rebind_timer=1000) get_address(exp_renew_timer=100, exp_rebind_timer=1000) # set renew and rebind timers on subnet level # and check if they are present in ACK packet cfg.update_subnet(renew_timer=200, rebind_timer=2000) get_address(exp_renew_timer=200, exp_rebind_timer=2000) # change renew and rebind timers on subnet level # and check if they are present in ACK packet cfg.update_subnet(renew_timer=300, rebind_timer=3000) get_address(exp_renew_timer=300, exp_rebind_timer=3000) # change renew and rebind timers on global level # and check if they are not reflected in ACK packet, # they still should be taken from subnet cfg.set_global_parameter(renew_timer=400, rebind_timer=4000) get_address(exp_renew_timer=300, exp_rebind_timer=3000)
def test_subnet_and_timers_equal(dhcp_version): # change both renew and rebind timers on different levels (global and subnet) # and check if these changes are properly reflected in received ACKs # in this case renew is always equal to rebind time, # ie. renew should be ignored and not present in responses cfg = setup_server_for_config_backend_cmds() # define one, default subnet cfg.add_subnet() # check getting address from this subnet get_address() # set renew and rebind timers on global level # and as renew equals rebind check if only rebind is present in ACK packet cfg.set_global_parameter(renew_timer=1, rebind_timer=1) get_address(exp_renew_timer='missing' if dhcp_version == 'v4' else 0, exp_rebind_timer=1) # set renew and rebind timers on subnet level # and as renew equals rebind check if only rebind is present in ACK packet cfg.update_subnet(renew_timer=1000, rebind_timer=1000) get_address(exp_renew_timer='missing' if dhcp_version == 'v4' else 0, exp_rebind_timer=1000) # change renew and rebind timers on subnet level # and as renew equals rebind check if only rebind is present in ACK packet cfg.update_subnet(renew_timer=2, rebind_timer=2) get_address(exp_renew_timer='missing' if dhcp_version == 'v4' else 0, exp_rebind_timer=2) # change renew and rebind timers on global level # and check if they are not reflected in ACK packet, # they still should be taken from subnet cfg.set_global_parameter(renew_timer=5, rebind_timer=5) get_address(exp_renew_timer='missing' if dhcp_version == 'v4' else 0, exp_rebind_timer=2)
def test_calculate_timers_init_v6(initial_calculate_tee_times, initial_t1_percent, initial_t2_percent, initial_preferred_lifetime, initial_valid_lifetime): # check initial values of different timers in config file cfg = setup_server_for_config_backend_cmds(calculate_tee_times=initial_calculate_tee_times, t1_percent=initial_t1_percent, t2_percent=initial_t2_percent, preferred_lifetime=initial_preferred_lifetime, valid_lifetime=initial_valid_lifetime) # define one, default subnet cfg.add_subnet() calculate_tee_times = initial_calculate_tee_times if initial_calculate_tee_times is not None else False if initial_preferred_lifetime is not None: preferred_lifetime = initial_preferred_lifetime else: preferred_lifetime = get_cfg_default('preferred-lifetime') valid_lifetime = initial_valid_lifetime if initial_valid_lifetime is not None else get_cfg_default('valid-lifetime') if calculate_tee_times: t1_percent = initial_t1_percent if initial_t1_percent is not None else get_cfg_default('t1-percent') t2_percent = initial_t2_percent if initial_t2_percent is not None else get_cfg_default('t2-percent') renew_timer = int(t1_percent * preferred_lifetime) rebind_timer = int(t2_percent * preferred_lifetime) else: renew_timer = None rebind_timer = None # check getting address from this subnet get_address(exp_renew_timer=renew_timer, exp_rebind_timer=rebind_timer, exp_ia_na_iaaddr_preflft=preferred_lifetime, exp_lease_time=valid_lifetime)
def test_subnet_and_rebind_timer(dhcp_version): # pylint: disable=unused-argument # change rebind timer on different levels (global and subnet) # and check if these changes are properly reflected in received ACKs cfg = setup_server_for_config_backend_cmds() # define one, default subnet cfg.add_subnet() # check getting address from this subnet get_address() # change global renew_timer to 1sec and now check # if received lease has renew_timer accordingly set cfg.set_global_parameter(rebind_timer=1) get_address(exp_rebind_timer=1) # change rebind_timer on subnet level to 1000sec # and now check if received lease has rebind_timer accordingly set cfg.update_subnet(rebind_timer=1000) get_address(exp_rebind_timer=1000) # change again rebind_timer on subnet level to 1sec # and now check if received lease has rebind_timer accordingly set cfg.update_subnet(rebind_timer=1) get_address(exp_rebind_timer=1) # change again rebind_timer on global level to 500sec # and now check if it is ignored ans it still should be taken # from subnet level cfg.set_global_parameter(rebind_timer=500) get_address(exp_rebind_timer=1)
def test_relay_in_subnet(dhcp_version): relay_addr_1 = "10.0.0.1" if dhcp_version == 'v4' else '10:0:0::1' relay_addr_2 = "10.0.0.2" if dhcp_version == 'v4' else '10:0:0::2' exp_addr_1 = '192.168.50.1' if dhcp_version == 'v4' else '2001:db8:1::1' exp_addr_2 = '192.168.50.2' if dhcp_version == 'v4' else '2001:db8:1::2' exp_addr_3 = '192.168.50.3' if dhcp_version == 'v4' else '2001:db8:1::3' cfg = setup_server_for_config_backend_cmds() # create a subnet with specific IP address for relay agent subnet_cfg, _ = cfg.add_subnet(relay={"ip-addresses": [relay_addr_1]}) # client 1 behind relay agent 1 should get a lease get_address(mac_addr='00:00:00:00:00:01', relay_addr=relay_addr_1, exp_addr=exp_addr_1) # client 2 behing unknown relay agent 2 should NOT get any lease get_rejected(mac_addr='00:00:00:00:00:02', relay_addr=relay_addr_2) # add another relay agent 2 subnet_cfg.update(relay={"ip-addresses": [relay_addr_1, relay_addr_2]}) # client 2 now should get a lease get_address(mac_addr='00:00:00:00:00:02', relay_addr=relay_addr_2, exp_addr=exp_addr_2) # another client 3 behind relay agent 1 still should be able to get a lease get_address(mac_addr='00:00:00:00:00:03', relay_addr=relay_addr_1, exp_addr=exp_addr_3)
def test_server_tag_kea_without_tag(): # create first configuration, kea has no assigned tag, so it should get config just from "all" cfg = setup_server_for_config_backend_cmds(server_tag="") _set_server_tag("abc") cfg.add_subnet(server_tags=["abc"], subnet="2001:db8:1::/64", id=1, pools=[{'pool': "2001:db8:1::1-2001:db8:1::100"}]) get_rejected() xyz = _get_server_config() # check that we don't have anything configured except default value assert len(xyz["arguments"]["Dhcp6"]["subnet6"]) == 0 assert len(xyz["arguments"]["Dhcp6"]["shared-networks"]) == 0 assert xyz["arguments"]["Dhcp6"]["valid-lifetime"] == 7200 assert len(xyz["arguments"]["Dhcp6"]["option-data"]) == 0 # set network, subnet, option and parameter for "all" cfg.add_network(server_tags=["all"], name="flor1") cfg.add_subnet(server_tags=["all"], shared_network_name="flor1", subnet="2001:db8:2::/64", id=2, pools=[{'pool': "2001:db8:2::1-2001:db8:2::100"}]) cfg.set_global_parameter(server_tags=["all"], valid_lifetime=7700) cfg.add_option(server_tags=["all"], code=22, csv_format=True, data="2001::1", name="sip-server-addr", space="dhcp6") xyz = _get_server_config() assert len(xyz["arguments"]["Dhcp6"]["subnet6"]) == 0 assert len(xyz["arguments"]["Dhcp6"]["shared-networks"]) == 1 assert len(xyz["arguments"]["Dhcp6"]["shared-networks"][0]["subnet6"]) == 1 assert xyz["arguments"]["Dhcp6"]["valid-lifetime"] == 7700 assert len(xyz["arguments"]["Dhcp6"]["option-data"]) == 1 get_address(mac_addr='00:00:00:00:00:06', exp_ia_na_iaaddr_validlft=7700, req_opts=[22], exp_option={"code": 22, "data": "2001::1"})
def test_reservation_mode_in_globals(dhcp_version): if dhcp_version == 'v4': init_cfg = dict(subnet4=[{ 'subnet': '2.2.2.0/24', 'pools': [{ 'pool': '2.2.2.1/32' }], 'interface': '$(SERVER_IFACE)', 'reservations': [{ "hw-address": "00:00:00:00:00:01", "ip-address": '2.2.2.2' }] }], reservations=[{ "hw-address": "00:00:00:00:00:01", "ip-address": '1.1.1.1' }]) else: init_cfg = dict(subnet6=[{ 'subnet': '2001:db8:1::/64', 'pools': [{ 'pool': '2001:db8:1::1/128' }], 'interface': '$(SERVER_IFACE)', 'reservations': [{ "duid": "00:03:00:01:00:00:00:00:00:01", "ip-addresses": ['2001:db8:1::2'] }] }], reservations=[{ "duid": "00:03:00:01:00:00:00:00:00:01", "ip-addresses": ['2001:db8:1::3'] }]) init_cfg['check-config'] = True cfg, _ = setup_server_for_config_backend_cmds(**init_cfg) # by default reservation-mode is 'all' so the address should be returned from subnet reservation get_address( mac_addr="00:00:00:00:00:01", exp_addr='2.2.2.2' if dhcp_version == 'v4' else '2001:db8:1::2') # change reservation-mode to 'global' and now address should be returned from global reservations cfg.set_global_parameter(reservation_mode='global') get_address( mac_addr="00:00:00:00:00:01", exp_addr='1.1.1.1' if dhcp_version == 'v4' else '2001:db8:1::3') # now change reservation-mode to 'disabled' and then the address should be returned from subnet pool # (not from reservations) cfg.set_global_parameter(reservation_mode='disabled') get_address( mac_addr="00:00:00:00:00:01", exp_addr='2.2.2.1' if dhcp_version == 'v4' else '2001:db8:1::1')
def test_subnet_change_params(): cfg = setup_server_for_config_backend_cmds() # create one subnet with defaults cfg.add_subnet() get_address(exp_next_server='0.0.0.0', exp_server_hostname='', exp_boot_file_name='') # set global params and check if they are in returned lease cfg.set_global_parameter(next_server='2.2.2.2', server_hostname='bbb.example.com', boot_file_name='/boot/bbb') get_address(exp_next_server='2.2.2.2', exp_server_hostname='bbb.example.com', exp_boot_file_name='/boot/bbb') # delete subnet and create new one with explicit params # and check if they are in returned lease cfg.del_subnet() cfg.add_subnet(next_server='3.3.3.3', server_hostname='ccc.example.com', boot_file_name='/boot/ccc') get_address(exp_next_server='3.3.3.3', exp_server_hostname='ccc.example.com', exp_boot_file_name='/boot/ccc') # update subnet and check if new params are in returned lease cfg.update_subnet(next_server='4.4.4.4', server_hostname='ddd.example.com', boot_file_name='/boot/ddd') get_address(exp_next_server='4.4.4.4', exp_server_hostname='ddd.example.com', exp_boot_file_name='/boot/ddd')
def test_subnet_change_params(): cfg = setup_server_for_config_backend_cmds() # create one subnet with defaults cfg.add_subnet() get_address(exp_next_server='0.0.0.0', exp_server_hostname='', exp_boot_file_name='') # set global params and check if they are in returned lease cfg.set_global_parameter(next_server='2.2.2.2', server_hostname='bbb.example.com', boot_file_name='/boot/bbb') get_address(exp_next_server='2.2.2.2', exp_server_hostname='bbb.example.com', exp_boot_file_name='/boot/bbb') # delete subnet and create new one with explicit params # and check if they are in returned lease cfg.del_subnet() cfg.add_subnet(next_server='3.3.3.3', server_hostname='ccc.example.com', boot_file_name='/boot/ccc') get_address(exp_next_server='3.3.3.3', exp_server_hostname='ccc.example.com', exp_boot_file_name='/boot/ccc') # update subnet and check if new params are in returned lease cfg.update_subnet(next_server='4.4.4.4', server_hostname='ddd.example.com', boot_file_name='/boot/ddd') get_address(exp_next_server='4.4.4.4', exp_server_hostname='ddd.example.com', exp_boot_file_name='/boot/ddd')
def test_options_inherit(): cfg = setup_server_for_config_backend_cmds() # just with global option and empty subnet cfg.add_subnet() cfg.add_option(code=23, csv_format=True, data="2001::31", name="dns-servers", space="dhcp6") get_address(req_opts=23, exp_option={"code": 23, "data": "2001::31"}) # del subnet, set network with option and with subnet without option cfg.del_subnet() network_cfg, _ = cfg.add_network( option_data={ "code": 23, "csv-format": True, "data": "2001::32", "name": "dns-servers", "space": "dhcp6" }) cfg.add_subnet(network=network_cfg) get_address(req_opts=23, exp_option={"code": 23, "data": "2001::32"}) # delete subnet without option, set with new subnet with option - options on higher level are # still configured cfg.del_subnet() cfg.add_subnet(network=network_cfg, option_data={ "code": 23, "csv-format": True, "data": "2001::33", "name": "dns-servers", "space": "dhcp6" }) get_address(req_opts=23, exp_option={"code": 23, "data": "2001::33"}) # delete subnet, and set new one, with option on subnet level and option at pool level cfg.del_subnet() cfg.add_subnet(network=network_cfg, option_data={ "code": 23, "csv-format": True, "data": "2001::33", "name": "dns-servers", "space": "dhcp6" }, pool_option_data={ "code": 23, "csv-format": True, "data": "2001::34", "name": "dns-servers", "space": "dhcp6" }) get_address(req_opts=23, exp_option={"code": 23, "data": "2001::34"})
def test_server_tag_global_parameter4(): cfg = setup_server_for_config_backend_cmds(server_tag="abc") _set_server_tag("xyz") _set_server_tag("abc") cfg.add_subnet(server_tags=["abc"], subnet="192.168.50.0/24", id=1, pools=[{ 'pool': "192.168.50.1-192.168.50.100" }]) cfg.set_global_parameter(server_tags=["all"], boot_file_name="/dev/null_all") get_address(exp_boot_file_name="/dev/null_all") xyz = _get_server_config() assert xyz["arguments"]["Dhcp4"]["boot-file-name"] == "/dev/null_all" cfg.set_global_parameter(server_tags=["xyz"], boot_file_name="/dev/null_xyz") get_address(exp_boot_file_name="/dev/null_all") xyz = _get_server_config() assert xyz["arguments"]["Dhcp4"]["boot-file-name"] == "/dev/null_all" # now despite the fact that there still is "all" tag in db, we should have "abc" cfg.set_global_parameter(server_tags=["abc"], boot_file_name="/dev/null_abc") get_address(exp_boot_file_name="/dev/null_abc") xyz = _get_server_config() assert xyz["arguments"]["Dhcp4"]["boot-file-name"] == "/dev/null_abc" srv_control.start_srv('DHCP', 'stopped') cfg = setup_server_for_config_backend_cmds(server_tag="xyz") cfg.add_subnet(server_tags=["xyz"], subnet="192.168.52.0/24", id=3, pools=[{ 'pool': "192.168.52.1-192.168.52.100" }]) # new servers should start with "xyz" xyz = _get_server_config() assert xyz["arguments"]["Dhcp4"]["boot-file-name"] == "/dev/null_xyz" get_address(exp_boot_file_name="/dev/null_xyz")
def test_class_in_network(dhcp_version): # prepare initial config with 3 class: modem, user, other # each class is assigned to 1 client with specificed MAC address if dhcp_version == 'v4': init_cfg = {'client-classes': [{ 'name': 'modem', 'test': "hexstring(pkt4.mac, ':') == '00:00:00:00:00:01'" }, { 'name': 'user', 'test': "hexstring(pkt4.mac, ':') == '00:00:00:00:00:02'" }, { 'name': 'other', 'test': "hexstring(pkt4.mac, ':') == '00:00:00:00:00:03'" }]} else: init_cfg = {'client-classes': [{ 'name': 'modem', 'test': "hexstring(option[1].hex, ':') == '00:03:00:01:00:00:00:00:00:01'" }, { 'name': 'user', 'test': "hexstring(option[1].hex, ':') == '00:03:00:01:00:00:00:00:00:02'" }, { 'name': 'other', 'test': "hexstring(option[1].hex, ':') == '00:03:00:01:00:00:00:00:00:03'" }]} cfg = setup_server_for_config_backend_cmds(**init_cfg) # add 2 subnets # subnet 1 is for a modem class cfg.add_subnet(client_class='modem') # subnet 2 is assigned to shared netwrok which is assigned to user class network_cfg, _ = cfg.add_network(name='user-nets', client_class='user') pool = '2.2.2.1-2.2.2.10' if dhcp_version == 'v4' else '2:2:2::1-2:2:2::10' cfg.add_subnet(shared_network_name='user-nets', subnet='2.2.2.0/24' if dhcp_version == 'v4' else '2:2:2::/64', pools=[{'pool': pool}]) # client 1 from 'modem' class should get lease from subnet 1 get_address(mac_addr="00:00:00:00:00:01", exp_addr='192.168.50.1' if dhcp_version == 'v4' else '2001:db8:1::1') # client 2 from 'user' class should get lease from subnet 2 get_address(mac_addr="00:00:00:00:00:02", exp_addr='2.2.2.1' if dhcp_version == 'v4' else '2:2:2::1') # client 3 from 'other' class should be rejected get_rejected(mac_addr='00:00:00:00:00:03') # change class name in network to 'other' and now client 3 should be given a lease network_cfg.update(client_class='other') get_address(mac_addr="00:00:00:00:00:03", exp_addr='2.2.2.2' if dhcp_version == 'v4' else '2:2:2::2') # change class name in network to '' ie. reset it, ie. make the network open to any client # and now unclassified client 4 should be given a lease from subnet 2 network_cfg.update(client_class='') get_address(mac_addr="00:00:00:00:00:04", exp_addr='2.2.2.3' if dhcp_version == 'v4' else '2:2:2::3')
def test_shared_networks_and_timers_renew_less(dhcp_version): # pylint: disable=unused-argument # change both renew and rebind timers on different levels (global, shared network and subnet) # and check if these changes are properly reflected in received ACKs # in this case renew is always less than rebind time so both should be present in responses cfg = setup_server_for_config_backend_cmds() # define a shared network with one subnet network_cfg, _ = cfg.add_network() subnet_cfg, _ = cfg.add_subnet(network=network_cfg) # check getting address from this subnet get_address() # set renew and rebind timers on global level # and check if they are present in ACK packet cfg.set_global_parameter(renew_timer=10, rebind_timer=100) get_address(exp_renew_timer=10, exp_rebind_timer=100) # set renew and rebind timers on network level # and check if they are present in ACK packet network_cfg.update(renew_timer=20, rebind_timer=200) get_address(exp_renew_timer=20, exp_rebind_timer=200) # change renew and rebind timers on global level # and check if they are not reflected in ACK packet, # they still should be taken from subnet cfg.set_global_parameter(renew_timer=30, rebind_timer=300) get_address(exp_renew_timer=20, exp_rebind_timer=200) # change renew and rebind timers on network level # and check if they are present in ACK packet network_cfg.update(renew_timer=40, rebind_timer=400) get_address(exp_renew_timer=40, exp_rebind_timer=400) # set renew and rebind timers on subnet level # and check if they are present in ACK packet subnet_cfg.update(renew_timer=50, rebind_timer=500) get_address(exp_renew_timer=50, exp_rebind_timer=500) # change renew and rebind timers on subnet level # and check if they are present in ACK packet subnet_cfg.update(renew_timer=60, rebind_timer=600) get_address(exp_renew_timer=60, exp_rebind_timer=600) # change renew and rebind timers on global level # and check if they are not reflected in ACK packet, # they still should be taken from subnet network_cfg.update(renew_timer=70, rebind_timer=700) get_address(exp_renew_timer=60, exp_rebind_timer=600) # change renew and rebind timers on global level # and check if they are not reflected in ACK packet, # they still should be taken from subnet cfg.set_global_parameter(renew_timer=80, rebind_timer=800) get_address(exp_renew_timer=60, exp_rebind_timer=600)
def test_shared_networks_and_timers_renew_less(dhcp_version): # pylint: disable=unused-argument # change both renew and rebind timers on different levels (global, shared network and subnet) # and check if these changes are properly reflected in received ACKs # in this case renew is always less than rebind time so both should be present in responses cfg = setup_server_for_config_backend_cmds() # define a shared network with one subnet network_cfg, _ = cfg.add_network() subnet_cfg, _ = cfg.add_subnet(network=network_cfg) # check getting address from this subnet get_address() # set renew and rebind timers on global level # and check if they are present in ACK packet cfg.set_global_parameter(renew_timer=10, rebind_timer=100) get_address(exp_renew_timer=10, exp_rebind_timer=100) # set renew and rebind timers on network level # and check if they are present in ACK packet network_cfg.update(renew_timer=20, rebind_timer=200) get_address(exp_renew_timer=20, exp_rebind_timer=200) # change renew and rebind timers on global level # and check if they are not reflected in ACK packet, # they still should be taken from subnet cfg.set_global_parameter(renew_timer=30, rebind_timer=300) get_address(exp_renew_timer=20, exp_rebind_timer=200) # change renew and rebind timers on network level # and check if they are present in ACK packet network_cfg.update(renew_timer=40, rebind_timer=400) get_address(exp_renew_timer=40, exp_rebind_timer=400) # set renew and rebind timers on subnet level # and check if they are present in ACK packet subnet_cfg.update(renew_timer=50, rebind_timer=500) get_address(exp_renew_timer=50, exp_rebind_timer=500) # change renew and rebind timers on subnet level # and check if they are present in ACK packet subnet_cfg.update(renew_timer=60, rebind_timer=600) get_address(exp_renew_timer=60, exp_rebind_timer=600) # change renew and rebind timers on global level # and check if they are not reflected in ACK packet, # they still should be taken from subnet network_cfg.update(renew_timer=70, rebind_timer=700) get_address(exp_renew_timer=60, exp_rebind_timer=600) # change renew and rebind timers on global level # and check if they are not reflected in ACK packet, # they still should be taken from subnet cfg.set_global_parameter(renew_timer=80, rebind_timer=800) get_address(exp_renew_timer=60, exp_rebind_timer=600)
def test_subnet_and_valid_lifetime(dhcp_version): # change valid-lifetime on different levels (global and subnet) # and check if behavior is as expected ie leases after lifetime # are available for other clients cfg = setup_server_for_config_backend_cmds() # define one, default subnet with 1 IP address cfg.add_subnet(pool="192.168.50.2/32" if dhcp_version == 'v4' else '2001:db8:1::2/128') # check getting address from this subnet by client 1 get_address(mac_addr='00:00:00:00:00:01', exp_addr='192.168.50.2' if dhcp_version == 'v4' else '2001:db8:1::2') # after 2 seconds check if another client 2 can get address - as default lifetime is big # it should fail because there is no more IP addresses (there is only 1 taken) time.sleep(2) get_rejected(mac_addr='00:00:00:00:00:02') # change lease lifetime on global level to be small ie. 1sec # and 1) extend address pool by 1 IP for new client 3 as previous IP address is taken for long time # and 2) check getting address by this new client 3 cfg.set_global_parameter(valid_lifetime=1) cfg.update_subnet(pool="192.168.50.2/31" if dhcp_version == 'v4' else '2001:db8:1::2/127') get_address(mac_addr='00:00:00:00:00:03', exp_lease_time=1, exp_addr='192.168.50.3' if dhcp_version == 'v4' else '2001:db8:1::3') # as lease time is 1 sec after 2secs this just taken IP address should # be available for other clients ie. client 4 time.sleep(2) get_address(mac_addr='00:00:00:00:00:04', exp_addr='192.168.50.3' if dhcp_version == 'v4' else '2001:db8:1::3') # wait for lease expiration for next test steps time.sleep(2) # change lease lifetime on subnet level to be big ie. 1000sec # and check getting address by client 5 cfg.update_subnet(valid_lifetime=1000) get_address(mac_addr='00:00:00:00:00:05', exp_lease_time=1000, exp_addr='192.168.50.3' if dhcp_version == 'v4' else '2001:db8:1::3') # after 2 seconds check if another client 6 can get address - as new lifetime is big # it should fail because there is no more IP addresses (there is only 2 taken) time.sleep(2) get_rejected(mac_addr='00:00:00:00:00:06') # change lease lifetime on subnet level to be small ie. 1sec # and check getting address by client 7 but first extent pool by one address # as previous IP addresses are taken for long time cfg.update_subnet(valid_lifetime=1, pool="192.168.50.2-192.168.50.4" if dhcp_version == 'v4' else '2001:db8:1::2-2001:db8:1::4') get_address(mac_addr='00:00:00:00:00:07', exp_lease_time=1, exp_addr='192.168.50.4' if dhcp_version == 'v4' else '2001:db8:1::4') # as lease time is 1 sec after 2secs this just taken IP address should # be available for other clients ie. client 8 time.sleep(2) get_address(mac_addr='00:00:00:00:00:08', exp_addr='192.168.50.4' if dhcp_version == 'v4' else '2001:db8:1::4')
def test_dhcp4o6_port(initial_dhcp4o6_port, dhcp_version): # pylint: disable=unused-argument cfg, config = setup_server_for_config_backend_cmds(dhcp4o6_port=initial_dhcp4o6_port, check_config=True) dhcp_key = 'Dhcp%s' % dhcp_version[1] if initial_dhcp4o6_port is None: assert config[dhcp_key]['dhcp4o6-port'] == 0 else: assert config[dhcp_key]['dhcp4o6-port'] == 1234 cfg.set_global_parameter(dhcp4o6_port=4321)
def test_options_pool(): cfg = setup_server_for_config_backend_cmds() cfg.add_subnet( pool_option_data={ "code": 22, "csv-format": True, "data": "2001::3", "name": "sip-server-addr", "space": "dhcp6" }) get_address(req_opts=22, exp_option={"code": 22, "data": "2001::3"})
def test_reservation_mode_override_init(initial_reservation_mode, dhcp_version): # pylint: disable=unused-argument # set initial reservation-mode cfg, _ = setup_server_for_config_backend_cmds( reservation_mode=initial_reservation_mode, check_config=True) # change reservation-mode to disabled or global and check it if initial_reservation_mode == 'disabled': exp_reservation_mode = 'global' else: exp_reservation_mode = 'disabled' cfg.set_global_parameter(reservation_mode=exp_reservation_mode)
def test_dhcp4o6_port(initial_dhcp4o6_port, dhcp_version): # pylint: disable=unused-argument cfg, config = setup_server_for_config_backend_cmds( dhcp4o6_port=initial_dhcp4o6_port, check_config=True) dhcp_key = 'Dhcp%s' % dhcp_version[1] if initial_dhcp4o6_port is None: assert config[dhcp_key]['dhcp4o6-port'] == 0 else: assert config[dhcp_key]['dhcp4o6-port'] == 1234 cfg.set_global_parameter(dhcp4o6_port=4321)
def test_server_tag_kea_without_tag(): # create first configuration, kea has no assigned tag, so it should get config just from "all" cfg = setup_server_for_config_backend_cmds(server_tag="") _set_server_tag("abc") cfg.add_subnet(server_tags=["abc"], subnet="192.168.52.0/24", id=1, pools=[{ 'pool': "192.168.52.1-192.168.52.100" }]) get_rejected() xyz = _get_server_config() # check that we don't have anything configured except default value assert len(xyz["arguments"]["Dhcp4"]["subnet4"]) == 0 assert len(xyz["arguments"]["Dhcp4"]["shared-networks"]) == 0 assert xyz["arguments"]["Dhcp4"]["boot-file-name"] == "" assert len(xyz["arguments"]["Dhcp4"]["option-data"]) == 0 # set network, subnet, option and parameter for "all" cfg.add_network(server_tags=["all"], name="flor1") cfg.add_subnet(server_tags=["all"], shared_network_name="flor1", subnet="192.168.50.0/24", id=2, pools=[{ 'pool': "192.168.50.1-192.168.50.100" }]) cfg.set_global_parameter(server_tags=["all"], valid_lifetime=7700) cfg.set_global_parameter(server_tags=["all"], boot_file_name="/dev/null_all") cfg.add_option(server_tags=["all"], code=3, csv_format=True, data="10.0.0.1", name="routers", space="dhcp4") xyz = _get_server_config() assert len(xyz["arguments"]["Dhcp4"]["subnet4"]) == 0 assert len(xyz["arguments"]["Dhcp4"]["shared-networks"]) == 1 assert len(xyz["arguments"]["Dhcp4"]["shared-networks"][0]["subnet4"]) == 1 assert xyz["arguments"]["Dhcp4"]["boot-file-name"] == "/dev/null_all" assert len(xyz["arguments"]["Dhcp4"]["option-data"]) == 1 get_address(mac_addr='00:00:00:00:00:06', exp_boot_file_name="/dev/null_all", req_opts=[3], exp_option={ "code": 3, "data": "10.0.0.1" })
def test_options_network(): cfg = setup_server_for_config_backend_cmds() network_cfg, _ = cfg.add_network( option_data={ "code": 23, "csv-format": True, "data": "2001::3", "name": "dns-servers", "space": "dhcp6" }) cfg.add_subnet(network=network_cfg) get_address(req_opts=[23, 27], exp_option={"code": 23, "data": "2001::3"})
def test_rapid_commit_in_subnet(): cfg = setup_server_for_config_backend_cmds() # create a subnet and check getting address regular way subnet_cfg, _ = cfg.add_subnet() get_address(mac_addr='00:00:00:00:00:01', exp_addr='2001:db8:1::1') # disable rapid commit on subnet level and get address regular way subnet_cfg.update(rapid_commit=True) get_address(mac_addr='00:00:00:00:00:02', rapid_commit=True, exp_addr='2001:db8:1::2') # enable rapid commit on subnet level and get get address using rapid method subnet_cfg.update(rapid_commit=False) get_address(mac_addr='00:00:00:00:00:03', exp_addr='2001:db8:1::3')
def test_options_global(): cfg = setup_server_for_config_backend_cmds() cfg.add_subnet() cfg.add_option(code=23, csv_format=True, data="2001::3", name="dns-servers", space="dhcp6") get_address(req_opts=[23, 27], exp_option={"code": 23, "data": "2001::3"}) cfg.del_option(code=23) get_address(req_opts=[23, 27], no_exp_option={"code": 23})
def test_match_client_id_override_init(initial_match_client_id): cfg, _ = setup_server_for_config_backend_cmds( match_client_id=initial_match_client_id, check_config=True) cfg.add_subnet() # check initial situation if initial_match_client_id in [None, True]: _check_matching_client_id_when_true() else: _check_matching_client_id_when_false() # client id is used on global level cfg.set_global_parameter(match_client_id=True) _check_matching_client_id_when_true()
def test_match_client_id_override_init(initial_match_client_id): cfg, _ = setup_server_for_config_backend_cmds(match_client_id=initial_match_client_id, check_config=True) cfg.add_subnet() # check initial situation if initial_match_client_id in [None, True]: _check_matching_client_id_when_true() else: _check_matching_client_id_when_false() # client id is used on global level cfg.set_global_parameter(match_client_id=True) _check_matching_client_id_when_true()
def test_pd_pool(): cfg = setup_server_for_config_backend_cmds() # add subnet with prefix delegation subnet_cfg, _ = cfg.add_subnet(subnet='3000::/64', pools=[{ 'pool': '3000::2/128' }], pd_pools=[{ "prefix": '2001:db8:1::', "prefix-len": 90, "delegated-len": 96, }]) # and get a PD get_address(mac_addr='00:00:00:00:00:01', req_ia='IA-PD', exp_ia_pd_iaprefix_prefix='2001:db8:1::', exp_ia_pd_iaprefix_plen=96) # change PD params (prefix itself, its len and delgated len) subnet_cfg.update(pd_pools=[{ "prefix": '2001:db8:2::', "prefix-len": 80, "delegated-len": 104, }]) # get again a PD get_address(mac_addr='00:00:00:00:00:02', req_ia='IA-PD', exp_ia_pd_iaprefix_prefix='2001:db8:2::', exp_ia_pd_iaprefix_plen=104) # TODO: exclude support on 1.6 final # add exlusion to PD subnet_cfg.update(pd_pools=[{ "prefix": '2001:db8:2::', "prefix-len": 80, "delegated-len": 104, "excluded-prefix": "2001:db8:2::", "excluded-prefix-len": 108, }]) # TODO: make proper check for exclusion get_address(mac_addr='00:00:00:00:00:03', req_ia='IA-PD', exp_ia_pd_iaprefix_prefix='2001:db8:2::', exp_ia_pd_iaprefix_plen=104)
def test_network_override_init(initial_next_server, initial_server_hostname, initial_boot_file_name): cfg = setup_server_for_config_backend_cmds(next_server=initial_next_server, server_hostname=initial_server_hostname, boot_file_name=initial_boot_file_name) cfg.add_subnet() get_address(exp_next_server=initial_next_server if initial_next_server else '0.0.0.0', exp_server_hostname=initial_server_hostname if initial_server_hostname else '', exp_boot_file_name=initial_boot_file_name if initial_boot_file_name else '') cfg.set_global_parameter(next_server='2.2.2.2', server_hostname='bbb.example.com', boot_file_name='/boot/bbb') get_address(exp_next_server='2.2.2.2', exp_server_hostname='bbb.example.com', exp_boot_file_name='/boot/bbb')
def test_relay_in_network(dhcp_version): relay_addr_1 = "10.0.0.1" if dhcp_version == 'v4' else '10:0:0::1' relay_addr_2 = "10.0.0.2" if dhcp_version == 'v4' else '10:0:0::2' relay_addr_3 = "10.0.0.3" if dhcp_version == 'v4' else '10:0:0::3' exp_addr_1 = '192.168.50.1' if dhcp_version == 'v4' else '2001:db8:1::1' exp_addr_2 = '192.168.50.2' if dhcp_version == 'v4' else '2001:db8:1::2' exp_addr_3 = '192.168.50.3' if dhcp_version == 'v4' else '2001:db8:1::3' exp_addr_4 = '192.168.50.4' if dhcp_version == 'v4' else '2001:db8:1::4' cfg = setup_server_for_config_backend_cmds() # create a network with specific IP address for relay agent network_cfg, _ = cfg.add_network(relay={"ip-addresses": [relay_addr_1]}) subnet_cfg, _ = cfg.add_subnet(network=network_cfg) # client 1 behind relay agent 1 should get a lease get_address(mac_addr='00:00:00:00:00:01', relay_addr=relay_addr_1, exp_addr=exp_addr_1) # client 2 behing unknown relay agent 2 should NOT get any lease get_rejected(mac_addr='00:00:00:00:00:02', relay_addr=relay_addr_2) # add another relay agent 2 network_cfg.update(relay={"ip-addresses": [relay_addr_1, relay_addr_2]}) # client 2 now should get a lease get_address(mac_addr='00:00:00:00:00:02', relay_addr=relay_addr_2, exp_addr=exp_addr_2) # another client 3 behind relay agent 1 still should be able to get a lease get_address(mac_addr='00:00:00:00:00:03', relay_addr=relay_addr_1, exp_addr=exp_addr_3) # and now override relay on subnet level to relay agent 3 subnet_cfg.update(relay={"ip-addresses": [relay_addr_3]}) # client 4 now should get a lease get_address(mac_addr='00:00:00:00:00:04', relay_addr=relay_addr_3, exp_addr=exp_addr_4) # another client 5 behind relay agent 1 now should NOT be able to get any lease get_rejected(mac_addr='00:00:00:00:00:03', relay_addr=relay_addr_1)
def test_reservation_mode_in_globals(dhcp_version): if dhcp_version == 'v4': init_cfg = dict( subnet4=[{ 'subnet': '2.2.2.0/24', 'pools': [{'pool': '2.2.2.1/32'}], 'interface': '$(SERVER_IFACE)', 'reservations': [{ "hw-address": "00:00:00:00:00:01", "ip-address": '2.2.2.2' }] }], reservations=[{"hw-address": "00:00:00:00:00:01", "ip-address": '1.1.1.1'}]) else: init_cfg = dict( subnet6=[{ 'subnet': '2001:db8:1::/64', 'pools': [{'pool': '2001:db8:1::1/128'}], 'interface': '$(SERVER_IFACE)', 'reservations': [{ "duid": "00:03:00:01:00:00:00:00:00:01", "ip-addresses": ['2001:db8:1::2'] }] }], reservations=[{"duid": "00:03:00:01:00:00:00:00:00:01", "ip-addresses": ['2001:db8:1::1']}]) init_cfg['check-config'] = True cfg, _ = setup_server_for_config_backend_cmds(**init_cfg) # by default reservation-mode is 'all' so the address should be returned from subnet reservation get_address(mac_addr="00:00:00:00:00:01", exp_addr='2.2.2.2' if dhcp_version == 'v4' else '2001:db8:1::2') # change reservation-mode to 'global' and now address should be returned from global reservations cfg.set_global_parameter(reservation_mode='global') get_address(mac_addr="00:00:00:00:00:01", exp_addr='1.1.1.1' if dhcp_version == 'v4' else '2001:db8:1::1') # BUG #585: this is failing because global fields are inherited by predefined subnets during config file parsing # and then later there are not longer inherited when are updated by CB API # now change reservation-mode to 'disabled' and then the address should be returned from subnet pool cfg.set_global_parameter(reservation_mode='disabled') get_address(mac_addr="00:00:00:00:00:01", exp_addr='2.2.2.1' if dhcp_version == 'v4' else '2001:db8:1::??') # TODO: ipv6 addr
def test_interface_id_in_subnet(): cfg = setup_server_for_config_backend_cmds() # create a subnet with specific relay agent interface-id subnet_cfg, _ = cfg.add_subnet(interface_id='vlan-a') # client 1 behind interface-id 'vlan-a' should get a lease get_address(mac_addr='00:00:00:00:00:01', interface_id='vlan-a') # client 2 behind interface-id 'vlan-b' should NOT get any lease get_rejected(mac_addr='00:00:00:00:00:02', interface_id='vlan-b') # change interface-id in subnet from 'vlan-a' to 'vlan-b' subnet_cfg.update(interface_id='vlan-b') # client 3 now should get a lease over interface-id 'vlan-b' get_address(mac_addr='00:00:00:00:00:03', interface_id='vlan-b') # but client 4 now behind interface-id 'vlan-a' should NOT get any lease get_rejected(mac_addr='00:00:00:00:00:04', interface_id='vlan-a')
def test_reservation_mode_override_init(initial_reservation_mode, dhcp_version): # set initial reservation-mode cfg, received_cfg = setup_server_for_config_backend_cmds(reservation_mode=initial_reservation_mode, check_config=True) if initial_reservation_mode is None: exp_reservation_mode = 'all' else: exp_reservation_mode = initial_reservation_mode dhcp_key = 'Dhcp%s' % dhcp_version[1] # check if initial reservation-mode is set assert received_cfg[dhcp_key]['reservation-mode'] == exp_reservation_mode # change reservation-mode to disabled or global and check it if initial_reservation_mode == 'disabled': exp_reservation_mode = 'global' else: exp_reservation_mode = 'disabled' received_cfg = cfg.set_global_parameter(reservation_mode=exp_reservation_mode) assert received_cfg[dhcp_key]['reservation-mode'] == exp_reservation_mode
def test_subnet_and_match_client_id(): cfg, _ = setup_server_for_config_backend_cmds(check_config=True) cfg.add_subnet() _check_matching_client_id_when_true() # client id is used on global level cfg.set_global_parameter(match_client_id=True) _check_matching_client_id_when_true() # client id is ignored on global level cfg.set_global_parameter(match_client_id=False) _check_matching_client_id_when_false() # client id is used on subnet level cfg.update_subnet(match_client_id=True) _check_matching_client_id_when_true() # client id is ignored on subnet level cfg.update_subnet(match_client_id=False) _check_matching_client_id_when_false()
def test_subnet_and_calculate_timers(dhcp_version): # change renew timer on different levels (global and subnet) # and check if these changes are properly reflected in received ACKs cfg = setup_server_for_config_backend_cmds() # define one, default subnet cfg.add_subnet() if dhcp_version == 'v4': base_lifetime = get_cfg_default('valid-lifetime') else: base_lifetime = get_cfg_default('preferred-lifetime') # change global renew_timer to 1sec and now check # if received lease has renew_timer accordingly set cfg.set_global_parameter(calculate_tee_times=True) t1_percent = get_cfg_default('t1-percent') t2_percent = get_cfg_default('t2-percent') get_address(exp_renew_timer=int(t1_percent * base_lifetime), exp_rebind_timer=int(t2_percent * base_lifetime)) # change t1 and t2 and check new renew/rebind-timers t1_percent = 0.1 t2_percent = 0.9 cfg.set_global_parameter(t1_percent=t1_percent, t2_percent=t2_percent) get_address(exp_renew_timer=int(t1_percent * base_lifetime), exp_rebind_timer=int(t2_percent * base_lifetime)) # change again but only t1 and check new renew/rebind-timers t1_percent = 0.3 cfg.set_global_parameter(t1_percent=t1_percent) get_address(exp_renew_timer=int(t1_percent * base_lifetime), exp_rebind_timer=int(t2_percent * base_lifetime)) # switch off calculate_tee_times and check if renew/rebind-timers # are not present in responses anymore cfg.set_global_parameter(calculate_tee_times=False) get_address(exp_renew_timer=None, exp_rebind_timer=None)
def test_auto_reload_100seconds(dhcp_version): # prepare initial config with fetch wait time set to 100 seconds cfg = setup_server_for_config_backend_cmds(config_control={"config-fetch-wait-time": 100}, force_reload=False) dhcp_key = 'Dhcp%s' % dhcp_version[1] subnet_key = 'subnet%s' % dhcp_version[1] # check config that there is no subnets and fetch time is 100 new_cfg = get_config() assert len(new_cfg[dhcp_key][subnet_key]) == 0 assert new_cfg[dhcp_key]['config-control']['config-fetch-wait-time'] == 100 # add subnet and wait 2 seconds that config is NOT reloaded automatically as it is done every 100 seconds cfg.add_subnet() time.sleep(2) # now check if there is NO subnets in config new_cfg = get_config() assert len(new_cfg[dhcp_key][subnet_key]) == 0 # there is NO subnet so getting address should fail get_rejected()
def test_network_and_match_client_id(): cfg, _ = setup_server_for_config_backend_cmds(check_config=True) network_cfg, _ = cfg.add_network() subnet_cfg, _ = cfg.add_subnet(network=network_cfg) _check_matching_client_id_when_true() # client id is ignored on global level cfg.set_global_parameter(match_client_id=False) _check_matching_client_id_when_false() # client id is used on network level network_cfg.update(match_client_id=True) _check_matching_client_id_when_true() # client id is ignored on network level network_cfg.update(match_client_id=False) _check_matching_client_id_when_false() # client id is used on subnet level subnet_cfg.update(match_client_id=True) _check_matching_client_id_when_true() # client id is ignored on subnet level subnet_cfg.update(match_client_id=False) _check_matching_client_id_when_false() # client id is still ignored on subnet level but used on network level network_cfg.update(match_client_id=True) _check_matching_client_id_when_false() # client id is used on subnet level subnet_cfg.update(match_client_id=True) _check_matching_client_id_when_true() # match-client-id is reset on subnet level # and should be used due to network leve setting subnet_cfg.update(match_client_id=None) _check_matching_client_id_when_true()
def test_subnet_and_timers_mix(dhcp_version): # change both renew and rebind timers on different levels (global and subnet) # and check if these changes are properly reflected in received ACKs # in this case they are in different relations to each other cfg = setup_server_for_config_backend_cmds() # define one, default subnet cfg.add_subnet() # check getting address from this subnet get_address() # change renew and rebind timers that they are either greater # less or equal to each other, do it on global level cfg.set_global_parameter(renew_timer=1500, rebind_timer=1000) get_address(exp_renew_timer='missing' if dhcp_version == 'v4' else 0, exp_rebind_timer=1000) cfg.set_global_parameter(renew_timer=1500, rebind_timer=1500) get_address(exp_renew_timer='missing' if dhcp_version == 'v4' else 0, exp_rebind_timer=1500) cfg.set_global_parameter(renew_timer=1000, rebind_timer=1500) get_address(exp_renew_timer=1000, exp_rebind_timer=1500) cfg.set_global_parameter(renew_timer=1000, rebind_timer=1000) get_address(exp_renew_timer='missing' if dhcp_version == 'v4' else 0, exp_rebind_timer=1000) # now change on subnet level in all directions cfg.update_subnet(renew_timer=1500, rebind_timer=1000) get_address(exp_renew_timer='missing' if dhcp_version == 'v4' else 0, exp_rebind_timer=1000) cfg.update_subnet(renew_timer=1500, rebind_timer=1500) get_address(exp_renew_timer='missing' if dhcp_version == 'v4' else 0, exp_rebind_timer=1500) cfg.update_subnet(renew_timer=1000, rebind_timer=1500) get_address(exp_renew_timer=1000, exp_rebind_timer=1500) cfg.update_subnet(renew_timer=1000, rebind_timer=1000) get_address(exp_renew_timer='missing' if dhcp_version == 'v4' else 0, exp_rebind_timer=1000)
def test_relay_in_network(dhcp_version): relay_addr_1 = "10.0.0.1" if dhcp_version == 'v4' else '10:0:0::1' relay_addr_2 = "10.0.0.2" if dhcp_version == 'v4' else '10:0:0::2' relay_addr_3 = "10.0.0.3" if dhcp_version == 'v4' else '10:0:0::3' exp_addr_1 = '192.168.50.1' if dhcp_version == 'v4' else '2001:db8:1::1' exp_addr_2 = '192.168.50.2' if dhcp_version == 'v4' else '2001:db8:1::2' exp_addr_3 = '192.168.50.3' if dhcp_version == 'v4' else '2001:db8:1::3' exp_addr_4 = '192.168.50.4' if dhcp_version == 'v4' else '2001:db8:1::4' cfg = setup_server_for_config_backend_cmds() # create a network with specific IP address for relay agent network_cfg, _ = cfg.add_network(relay={"ip-addresses": [relay_addr_1]}) subnet_cfg, _ = cfg.add_subnet(network=network_cfg) # client 1 behind relay agent 1 should get a lease get_address(mac_addr='00:00:00:00:00:01', relay_addr=relay_addr_1, exp_addr=exp_addr_1) # client 2 behing unknown relay agent 2 should NOT get any lease get_rejected(mac_addr='00:00:00:00:00:02', relay_addr=relay_addr_2) # add another relay agent 2 network_cfg.update(relay={"ip-addresses": [relay_addr_1, relay_addr_2]}) # client 2 now should get a lease get_address(mac_addr='00:00:00:00:00:02', relay_addr=relay_addr_2, exp_addr=exp_addr_2) # another client 3 behind relay agent 1 still should be able to get a lease get_address(mac_addr='00:00:00:00:00:03', relay_addr=relay_addr_1, exp_addr=exp_addr_3) # and now override relay on subnet level to relay agent 3 subnet_cfg.update(relay={"ip-addresses": [relay_addr_3]}) # client 4 now should get a lease get_address(mac_addr='00:00:00:00:00:04', relay_addr=relay_addr_3, exp_addr=exp_addr_4) # another client 5 behind relay agent 1 now should NOT be able to get any lease get_rejected(mac_addr='00:00:00:00:00:03', relay_addr=relay_addr_1)
def test_auto_reload_1second(dhcp_version): # prepare initial config with fetch wait time set to 1 second cfg = setup_server_for_config_backend_cmds(config_control={"config-fetch-wait-time": 1}, force_reload=False) dhcp_key = 'Dhcp%s' % dhcp_version[1] subnet_key = 'subnet%s' % dhcp_version[1] # check config that there is no subnets and fetch time is 1 new_cfg = get_config() assert len(new_cfg[dhcp_key][subnet_key]) == 0 assert new_cfg[dhcp_key]['config-control']['config-fetch-wait-time'] == 1 # add subnet and wait 2 seconds that config is reloaded automatically cfg.add_subnet() time.sleep(2) # now check if there is a subnet in config new_cfg = get_config() assert len(new_cfg[dhcp_key][subnet_key]) == 1 assert new_cfg[dhcp_key][subnet_key][0]['subnet'] == cfg.subnets.keys()[0] # there is subnet so getting address should succeed get_address()
def test_echo_client_id(initial_echo_client_id): # Set initial value of echo-client-id in config file and then change it # using cb-cmds. Observe if client-id is included in responses according to settings. # Different initial settings for echo-client-id: default (=True), True and False. cfg = setup_server_for_config_backend_cmds(echo_client_id=initial_echo_client_id) cfg.add_subnet() # Request address and check if client-id is returned according to initial setting. get_address(client_id='00010203040506', exp_client_id='00010203040506' if initial_echo_client_id in [None, True] else 'missing') # Change setting to NOT return client-id. It should be missing in responses. cfg.set_global_parameter(echo_client_id=False) get_address(client_id='10010203040506', exp_client_id='missing') # Change again setting to return client-id. It should be missing in responses. cfg.set_global_parameter(echo_client_id=True) get_address(client_id='20010203040506', exp_client_id='20010203040506') # Change setting to NOT return client-id. It should be missing in responses. cfg.set_global_parameter(echo_client_id=False) get_address(client_id='30010203040506', exp_client_id='missing')
def test_subnet_and_renew_timer(dhcp_version): # change renew timer on different levels (global and subnet) # and check if these changes are properly reflected in received ACKs cfg = setup_server_for_config_backend_cmds() dhcp_key = 'Dhcp%s' % dhcp_version[1] subnet_key = 'subnet%s' % dhcp_version[1] # define one, default subnet _, config = cfg.add_subnet() assert 'renew-timer' not in config[dhcp_key][subnet_key][0] # check getting address from this subnet get_address() # change global renew_timer to 1sec and now check # if received lease has renew_timer accordingly set cfg.set_global_parameter(renew_timer=1) get_address(exp_renew_timer=1) # change renew_timer on subnet level to 1000sec # and now check if received lease has renew_timer accordingly set cfg.update_subnet(renew_timer=1000) get_address(exp_renew_timer=1000) # change again renew_timer on subnet level to 1sec # and now check if received lease has renew_timer accordingly set cfg.update_subnet(renew_timer=1) get_address(exp_renew_timer=1) # change again renew_timer on global level to 500sec # and now check if it is ignored ans it still should be taken # from subnet level cfg.set_global_parameter(renew_timer=500) get_address(exp_renew_timer=1)
def test_decline_and_probation_period(initial_decline_probation_period, dhcp_version): # Set initial value of decline-probation-period in config file and then change it # using cb-cmds. Observe if the setting is honored in case of sending DECLINE messages. # Different initial settings for decline-probation-period: default (=24h), 1 second and 1000 seconds. cfg = setup_server_for_config_backend_cmds(decline_probation_period=initial_decline_probation_period) # Prepare subnet with only 1 IP address in a pool. This way when the second DISCOVER is send # no response should be expected from server. cfg.add_subnet(pool='192.168.50.1/32' if dhcp_version == 'v4' else '2001:db8:1::1/128') # Get address and decline it. if dhcp_version == 'v4': addr = get_address4(exp_yiaddr='192.168.50.1') send_decline4(addr) else: get_address6(exp_ia_na_iaaddr_addr='2001:db8:1::1') send_decline6() # Wait a moment. time.sleep(2) # If initial decline-probation-period was 1 second then it should # be possible to acquire the same IP again, ie. after 1 second it should have been # returned to pool from probation space. if initial_decline_probation_period == 1: get_address(exp_addr='192.168.50.1' if dhcp_version == 'v4' else '2001:db8:1::1') else: # If initial value was other than 1 second then server should still keep # the IP in probation and no response should be sent by server. get_rejected() # Delete subnet. This will delete IP in probation. Ie. start from scratch. cfg.del_subnet() # Change decline-probation-period from initial to 1000 seconds. cfg.set_global_parameter(decline_probation_period=1000) # Create new subnet with different pool but still with 1 IP address. cfg.add_subnet(pool='192.168.50.2/32' if dhcp_version == 'v4' else '2001:db8:1::2/128') # Now after decline and sleeping 2 seconds the declined address still should # be in probation and server should not send any response for discover. if dhcp_version == 'v4': addr = get_address4(exp_yiaddr='192.168.50.2') send_decline4(addr) else: get_address6(exp_ia_na_iaaddr_addr='2001:db8:1::2') send_decline6() time.sleep(2) get_rejected() # Start from scratch again. New pool with 1 IP address. # Probation period is changed now to 1 second. cfg.del_subnet() cfg.set_global_parameter(decline_probation_period=1) cfg.add_subnet(pool='192.168.50.3/32' if dhcp_version == 'v4' else '2001:db8:1::3/128') # This time after decline and sleeping the address should be available # for the following request. if dhcp_version == 'v4': addr1 = get_address4(exp_yiaddr='192.168.50.3') send_decline4(addr1) time.sleep(2) addr2 = get_address4() assert addr2 == addr1 else: get_address6(exp_ia_na_iaaddr_addr='2001:db8:1::3') send_decline6() time.sleep(2) get_address6(exp_ia_na_iaaddr_addr='2001:db8:1::3')
def test_network_change_params(): cfg = setup_server_for_config_backend_cmds() # add 1 subnet, no shared networks yet, and check received lease cfg.add_subnet() get_address(exp_next_server='0.0.0.0', # TODO: why 0.0.0.0? why not '' exp_server_hostname='', exp_boot_file_name='') # change global params and check received lease cfg.set_global_parameter(next_server='2.2.2.2', server_hostname='bbb.example.com', boot_file_name='/boot/bbb') get_address(exp_next_server='2.2.2.2', exp_server_hostname='bbb.example.com', exp_boot_file_name='/boot/bbb') # delete subnet and add 1 network with 1 subnet # and check received lease if it takes params from network now cfg.del_subnet() network_cfg, _ = cfg.add_network(next_server='3.3.3.3', server_hostname='ccc.example.com', boot_file_name='/boot/ccc') subnet2_cfg, _ = cfg.add_subnet(network=network_cfg) get_address(exp_next_server='3.3.3.3', exp_server_hostname='ccc.example.com', exp_boot_file_name='/boot/ccc') # change params in network's subnet # and check received lease if it takes params from subnet now subnet2_cfg.update(next_server='4.4.4.4', server_hostname='ddd.example.com', boot_file_name='/boot/ddd') get_address(exp_next_server='4.4.4.4', exp_server_hostname='ddd.example.com', exp_boot_file_name='/boot/ddd') # reset params in subnet # and check received lease if it takes params from network scope subnet2_cfg.update(next_server='', server_hostname='', boot_file_name='') get_address(exp_next_server='3.3.3.3', exp_server_hostname='ccc.example.com', exp_boot_file_name='/boot/ccc') # reset params in network # and check received lease if it takes params from global scope network_cfg.update(next_server='', server_hostname='', boot_file_name='') get_address(exp_next_server='2.2.2.2', exp_server_hostname='bbb.example.com', exp_boot_file_name='/boot/bbb') # reset params in global scope # and check received lease if it takes default params ie. empty cfg.set_global_parameter(next_server='0.0.0.0', server_hostname='', boot_file_name='') get_address(exp_next_server='0.0.0.0', # TODO: why 0.0.0.0? why not '' exp_server_hostname='', exp_boot_file_name='')