1{ pkgs, makeTest }:
2
3with pkgs.lib;
4
5{
6 makeEc2Test =
7 {
8 name,
9 image,
10 userData,
11 script,
12 hostname ? "ec2-instance",
13 sshPublicKey ? null,
14 meta ? { },
15 }:
16 let
17 metaData = pkgs.stdenv.mkDerivation {
18 name = "metadata";
19 buildCommand = ''
20 mkdir -p $out/1.0/meta-data
21 ln -s ${pkgs.writeText "userData" userData} $out/1.0/user-data
22 echo "${hostname}" > $out/1.0/meta-data/hostname
23 echo "(unknown)" > $out/1.0/meta-data/ami-manifest-path
24 ''
25 + optionalString (sshPublicKey != null) ''
26 mkdir -p $out/1.0/meta-data/public-keys/0
27 ln -s ${pkgs.writeText "sshPublicKey" sshPublicKey} $out/1.0/meta-data/public-keys/0/openssh-key
28 '';
29 };
30 indentLines = str: concatLines (map (s: " " + s) (splitString "\n" str));
31 in
32 makeTest {
33 name = "ec2-" + name;
34 nodes = { };
35 testScript = ''
36 import os
37 import subprocess
38 import tempfile
39
40 image_dir = os.path.join(
41 os.environ.get("TMPDIR", tempfile.gettempdir()), "tmp", "vm-state-machine"
42 )
43 os.makedirs(image_dir, mode=0o700, exist_ok=True)
44 disk_image = os.path.join(image_dir, "machine.qcow2")
45 subprocess.check_call(
46 [
47 "qemu-img",
48 "create",
49 "-f",
50 "qcow2",
51 "-F",
52 "qcow2",
53 "-o",
54 "backing_file=${image}",
55 disk_image,
56 ]
57 )
58 subprocess.check_call(["qemu-img", "resize", disk_image, "10G"])
59
60 # Note: we use net=169.0.0.0/8 rather than
61 # net=169.254.0.0/16 to prevent dhcpcd from getting horribly
62 # confused. (It would get a DHCP lease in the 169.254.*
63 # range, which it would then configure and promptly delete
64 # again when it deletes link-local addresses.) Ideally we'd
65 # turn off the DHCP server, but qemu does not have an option
66 # to do that.
67 start_command = (
68 "qemu-kvm -m 1024"
69 + " -device virtio-net-pci,netdev=vlan0"
70 + " -netdev 'user,id=vlan0,net=169.0.0.0/8,guestfwd=tcp:169.254.169.254:80-cmd:${pkgs.micro-httpd}/bin/micro_httpd ${metaData}'"
71 + f" -drive file={disk_image},if=virtio,werror=report"
72 + " $QEMU_OPTS"
73 )
74
75 machine = create_machine(start_command)
76 try:
77 ''
78 + indentLines script
79 + ''
80 finally:
81 machine.shutdown()
82 '';
83
84 inherit meta;
85 };
86}