summaryrefslogtreecommitdiff
path: root/create-vm
diff options
context:
space:
mode:
Diffstat (limited to 'create-vm')
-rwxr-xr-xcreate-vm148
1 files changed, 148 insertions, 0 deletions
diff --git a/create-vm b/create-vm
new file mode 100755
index 0000000..00242fc
--- /dev/null
+++ b/create-vm
@@ -0,0 +1,148 @@
+#!/usr/bin/env python3
+
+import os
+import shutil
+import socket
+import subprocess
+import sys
+import tempfile
+import time
+import yaml
+
+
+def cloud_init_iso(iso, hostname, pubkey):
+ tmp = tempfile.mkdtemp()
+
+ with open(os.path.join(tmp, "meta-data"), "w") as f:
+ f.write(
+ f"""\
+# Amazon EC2 style metadata
+local-hostname: {hostname}
+"""
+ )
+
+ with open(os.path.join(tmp, "user-data"), "w") as f:
+ f.write(
+ f"""\
+#cloud-config
+ssh_authorized_keys:
+- {pubkey}
+"""
+ )
+
+ subprocess.check_call(
+ [
+ "genisoimage",
+ "-quiet",
+ "-volid",
+ "cidata",
+ "-joliet",
+ "-rock",
+ "-output",
+ iso,
+ tmp,
+ ]
+ )
+ shutil.rmtree(tmp)
+
+
+def create_vm(vm, image, iso, memory=1024, cpus=1):
+ subprocess.check_call(
+ [
+ "virt-install",
+ "--name",
+ vm,
+ "--memory",
+ str(memory),
+ "--vcpus",
+ str(cpus),
+ f"--disk=path={image},cache=none",
+ f"--disk=path={iso},readonly=on",
+ "--network=network=default",
+ "--connect",
+ "qemu:///system",
+ "--cpu=host-passthrough",
+ "--os-variant=debian9",
+ "--import",
+ "--graphics=spice",
+ "--noautoconsole",
+ "--quiet",
+ ]
+ )
+
+
+def wait_for_ssh(hostname):
+ ssh_port = 22
+ while True:
+ time.sleep(5)
+ try:
+ conn = socket.create_connection((hostname, ssh_port), timeout=1)
+ except Exception:
+ continue
+ conn.close()
+ break
+
+
+def provision(vm, pubkey):
+ ssh_opts = [
+ "ControlMaster=auto",
+ "ControlPersist=60s",
+ "StrictHostKeyChecking=accept-new",
+ "UserKnownHostsFile=/dev/null",
+ ]
+
+ env = dict(os.environ)
+ env["ANSIBLE_SSH_ARGS"] = " ".join(f"-o{opt}" for opt in ssh_opts)
+
+ vars_file = {"user_pub": pubkey}
+
+ fd, filename = tempfile.mkstemp()
+ os.write(fd, yaml.safe_dump(vars_file).encode("UTF-8"))
+ os.close(fd)
+
+ argv = [
+ "ansible-playbook",
+ "-i",
+ "hosts",
+ "manager.yml",
+ f"-eansible_ssh_host={vm}",
+ f"-e@{filename}",
+ ]
+ subprocess.check_output(argv, env=env)
+
+ os.remove(filename)
+
+
+def main():
+ config = yaml.safe_load(open(sys.argv[1]))
+
+ base = config["base_image"]
+ vm = config["name"]
+ img = config["image_file"]
+ size = config["image_size"]
+ pubkey = config["public_key"]
+ memory = config.get("memory", 1024)
+ cpus = config.get("cpus", 1)
+
+ memory = int(memory)
+ cpus = int(cpus)
+ pubkey = open(pubkey).read().rstrip()
+ iso = f"{vm}.iso"
+
+ cloud_init_iso(iso, vm, pubkey)
+
+ if os.path.exists(img):
+ os.remove(img)
+ shutil.copy(base, img)
+
+ subprocess.check_call(["qemu-img", "resize", "-q", img, size])
+
+ create_vm(vm, img, iso, memory=memory, cpus=cpus)
+ wait_for_ssh(vm)
+ os.remove(iso)
+
+
+# provision(vm, pubkey)
+
+
+main()