# In contrast to systemd-networkd-dhcpserver, this test configures
# the router with a static DHCP lease for the client's MAC address.
import ./make-test-python.nix ({ lib, ... }: {
  name = "systemd-networkd-dhcpserver-static-leases";
  meta = with lib.maintainers; {
    maintainers = [ veehaitch ];
  };
  nodes = {
    router = {
      virtualisation.vlans = [ 1 ];
      systemd.services.systemd-networkd.environment.SYSTEMD_LOG_LEVEL = "debug";
      networking = {
        useNetworkd = true;
        useDHCP = false;
        firewall.enable = false;
      };
      systemd.network = {
        networks = {
          # systemd-networkd will load the first network unit file
          # that matches, ordered lexiographically by filename.
          # /etc/systemd/network/{40-eth1,99-main}.network already
          # exists. This network unit must be loaded for the test,
          # however, hence why this network is named such.
          "01-eth1" = {
            name = "eth1";
            networkConfig = {
              DHCPServer = true;
              Address = "10.0.0.1/24";
            };
            dhcpServerStaticLeases = [{
              MACAddress = "02:de:ad:be:ef:01";
              Address = "10.0.0.10";
            }];
          };
        };
      };
    };

    client = {
      virtualisation.vlans = [ 1 ];
      systemd.services.systemd-networkd.environment.SYSTEMD_LOG_LEVEL = "debug";
      systemd.network = {
        enable = true;
        links."10-eth1" = {
          matchConfig.OriginalName = "eth1";
          linkConfig.MACAddress = "02:de:ad:be:ef:01";
        };
        networks."40-eth1" = {
          matchConfig.Name = "eth1";
          networkConfig = {
            DHCP = "ipv4";
            IPv6AcceptRA = false;
          };
          # This setting is important to have the router assign the
          # configured lease based on the client's MAC address. Also see:
          # https://github.com/systemd/systemd/issues/21368#issuecomment-982193546
          dhcpV4Config.ClientIdentifier = "mac";
          linkConfig.RequiredForOnline = "routable";
        };
      };
      networking = {
        useDHCP = false;
        firewall.enable = false;
        interfaces.eth1 = lib.mkForce {};
      };
    };
  };
  testScript = ''
    start_all()

    with subtest("check router network configuration"):
      router.wait_for_unit("systemd-networkd-wait-online.service")
      eth1_status = router.succeed("networkctl status eth1")
      assert "Network File: /etc/systemd/network/01-eth1.network" in eth1_status, \
        "The router interface eth1 is not using the expected network file"
      assert "10.0.0.1" in eth1_status, "Did not find expected router IPv4"

    with subtest("check client network configuration"):
      client.wait_for_unit("systemd-networkd-wait-online.service")
      eth1_status = client.succeed("networkctl status eth1")
      assert "Network File: /etc/systemd/network/40-eth1.network" in eth1_status, \
        "The client interface eth1 is not using the expected network file"
      assert "10.0.0.10" in eth1_status, "Did not find expected client IPv4"

    with subtest("router and client can reach each other"):
      client.wait_until_succeeds("ping -c 5 10.0.0.1")
      router.wait_until_succeeds("ping -c 5 10.0.0.10")
  '';
})
