summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2021-08-20 19:32:08 +0300
committerLars Wirzenius <liw@liw.fi>2021-08-20 19:32:08 +0300
commitcb437c9e3a1f7b25e1306e504656286c24186e4c (patch)
treec8314be1f48e51b0f145450c3a91a8b79390499e
parentd6789ab0b7175173ea73723fc2a686097569bf6f (diff)
downloadansibleness-cb437c9e3a1f7b25e1306e504656286c24186e4c.tar.gz
drop old crap
Sponsored-by: author
-rw-r--r--README48
-rwxr-xr-xcreate-vm173
-rw-r--r--heat/pieni.heat109
-rwxr-xr-xnew-create-vm167
-rwxr-xr-xnew-remove-vm26
-rw-r--r--new.yaml7
-rwxr-xr-xremove-vm55
7 files changed, 0 insertions, 585 deletions
diff --git a/README b/README
deleted file mode 100644
index e1ce7a4..0000000
--- a/README
+++ /dev/null
@@ -1,48 +0,0 @@
-Managing my virtual machines
-============================
-
-I have a laptop with 16 GiB RAM, which is enough to run a few virtual
-machines. I make use of this to run VMs as, for example, workers for
-my CI setup, such that I have two or three versions of Debian
-(oldstable, stable, unstable) and two CPU architectures (i386, amd64).
-This lets me test the software I develop on a large fraction of the
-environments in which my users run it on.
-
-I have a few other VMs as well. Managing all of these would be tricky,
-but I've gathered some tools for this:
-
-* The actual virtualisation is KVM, managed by libvirt. This is less
- invasive than running OpenStack of similar cloud services on my
- laptop.
-
-* I use Ansible for configuration management. It's easy to use, and
- doesn't require Ruby or running an agent on each machine.
-
-* I create each VM from a base image. The base images are created by
- vmdebootstrap, a tool I wrote and that Neil Williams now maintains.
- The base images have a minimal install, with a user `ansible` that
- is allowed passwordless sudo, and an `authorized_keys` file that
- allows my Ansible to log into them and do things.
-
-The creation of a new VM is a somewhat intricate process:
-
-* Create a new LV of the same size as the base images.
-
-* Unpack the correct base image onto the LV. The base images are
- stored compressed in an archive location.
-
-* Create the VM, with `virt-install`. This chooses a random MAC
- address for the new VM, and also starts it.
-
-* Find the new VM's MAC address in the
- `/var/lib/libvirt/dnsmasq/default.leases` file, and pick out the IP
- address given to it.
-
-* Add to `/etc/hosts` a line that gives the VM's IP address a name
- that's the new VM's hostname.
-
-All of the above is automated into a script.
-
-After this, the new VM can be managed by Ansible. Ansible gets run
-manually after the VM creation script, and after I've added the new VM
-to my Ansible config.
diff --git a/create-vm b/create-vm
deleted file mode 100755
index ecb760a..0000000
--- a/create-vm
+++ /dev/null
@@ -1,173 +0,0 @@
-#!/bin/sh
-#
-# Create a new VM for liw.
-
-
-set -eu
-
-
-verbose()
-{
- echo "INFO: $@"
-}
-
-
-die()
-{
- echo "$@" 1>&2
- exit 1
-}
-
-
-get_ip()
-{
- python -c '
-import sys, json
-leases = json.load(open(sys.argv[1]))
-for lease in leases:
- if lease["mac-address"] == sys.argv[2]:
- print lease["ip-address"]
-' "$1" "$2" || true
-}
-
-
-xz_uncompressed_size()
-{
- xz --robot --verbose --list "$1" | awk '/^file/ { print $5 }'
-}
-
-raw_uncompressed_size()
-{
- stat -c %s "$1"
-}
-
-
-# Check parameters.
-
-if [ "$#" -lt 2 ]
-then
- die "Usage: $0 NAME BASE [virt-install-options]"
-fi
-verbose "Command line args OK"
-
-
-# Config variables.
-. "$HOME/.config/ansibleness/vm.conf"
-verbose "Loaded config file"
-
-# Command line parameters: name of VM and base image (no .img.xz suffix).
-name="$1"
-case "$2" in
- */*) basepath="$2" ;;
- *) basepath="$imagedir/base-$2.img.xz" ;;
-esac
-verbose "basepath=$basepath"
-
-shift 2
-
-# Does the base image exist?
-if [ ! -e "$basepath" ]
-then
- echo "$basepath does not exist" 1>&2
- exit 1
-fi
-verbose "$basepath exists"
-
-# Is base image compressed?
-case "$basepath" in
- *.xz) xz=true ;;
- *) xz=false ;;
-esac
-
-
-# How large is the (uncompressed) image? In bytes.
-if $xz
-then
- size="$(xz_uncompressed_size "$basepath")"
-else
- size="$(raw_uncompressed_size "$basepath")"
-fi
-verbose "Image is $size bytes"
-
-# Create new LV.
-verbose "Creating LV /dev/$vg/$name"
-sudo lvcreate --name "$name" --size "${size}b" \
- --zero y --wipesignatures n --activate y "$vg"
-lvpath="/dev/$vg/$name"
-verbose "lvpath=$lvpath"
-#sudo lvchange -ay "$lvpath"
-
-# Copy uncompressed image to LV.
-if $xz
-then
- verbose "Uncompressing and copying image to LV"
- unxz < "$basepath" |
- pv --size "$size" |
- sudo ionice -c3 tee "$lvpath" > /dev/null
-else
- verbose "Copying uncompressed imagew to LV"
- pv "$basepath" |
- sudo ionice -c3 tee "$lvpath" > /dev/null
-fi
-
-# Edit /etc/hostname
-verbose "Set hostname on new system to $name"
-mnt="$(mktemp -d)"
-for part in $(sudo kpartx -asv "$lvpath" | awk '/^add map / { print $3 }')
-do
- sudo mount "/dev/mapper/$part" "$mnt"
- if [ -e "$mnt/etc/hostname" ]
- then
- echo "$name" | sudo tee "$mnt/etc/hostname"
- fi
- sudo umount "$mnt"
-done
-sudo kpartx -dsv "$lvpath"
-
-# Create VM.
-verbose "Creating VM"
-virt-install --connect qemu:///system \
- --quiet \
- --name="$name" \
- --memory=1024 \
- --cpu=host-passthrough \
- --import \
- --os-variant=debian9 \
- --disk="path=$lvpath,cache=none" \
- --network="$vmnetwork" \
- --graphics=spice \
- --noautoconsole \
- "$@"
-
-# If we're using the virtual network "default", wait for the VM to get
-# a DHCP response and add it to /etc/hosts. We don't do it for other
-# types of network (e.g., bridge=br0), since we ... can't.
-
-if [ "$vmnetwork" = "network=default" ]
-then
- verbose "Waiting for VM to boot and get IP"
-
- # Get the MAC address.
- mac="$(virsh -c qemu:///system dumpxml "$name" |
- sed -n "/<mac address=/s/^.*'\(.*\)'.*/\1/p")"
- verbose "MAC: $mac"
-
- # Get IP address related to the MAC address. Append that to /etc/hosts.
- leases=/var/lib/libvirt/dnsmasq/virbr0.status
-
- ip=""
- while [ "$ip" = "" ]
- do
- sleep 1
- if [ -s "$leases" ]
- then
- ip="$(get_ip "$leases" "$mac")"
- fi
- done
- echo "$ip $name" | sudo tee -a /etc/hosts > /dev/null
-
- # Done.
- echo "Virtual machine $name ($ip) has been created and started."
-else
- echo "Virtual machine $name has been created and started, and may be ready soon."
-fi
diff --git a/heat/pieni.heat b/heat/pieni.heat
deleted file mode 100644
index 0ab8aa5..0000000
--- a/heat/pieni.heat
+++ /dev/null
@@ -1,109 +0,0 @@
----
-heat_template_version: 2015-04-30
-
-description: >-
- pieni.net.
-
-parameters:
-
- key_name:
- type: string
- label: Key name
- description: Name of key-pair to be used for compute instance
-
- instance_flavor:
- type: string
- label: Instance Type
- description: Type of instance (flavor) to be used
- default: nbl-n1-medium
-
- image_id:
- type: string
- label: Image ID
- description: "stretch"
- default: 64e1068f-09f0-4eb3-aca1-05946de594c3
-
- floating_network:
- type: string
- label: Public network UUID
- description: UUID of the public network
- default: Public-Helsinki-1
-
- availability_zone:
- type: string
- label: Availability zone
- description: Name of the Availability zone
- default: helsinki-1
-
- public_network:
- type: string
- description: The network for the VM in helsinki-1
- default: Network-Public-Helsinki-1
-
-resources:
-
- sg:
- type: OS::Neutron::SecurityGroup
- properties:
- description: some stuff
- rules:
- # Allow ssh in.
- - direction: ingress
- ethertype: IPv4
- port_range_min: 22
- port_range_max: 22
- protocol: tcp
- # Allow smtp in.
- - direction: ingress
- ethertype: IPv4
- port_range_min: 25
- port_range_max: 25
- protocol: tcp
- # Allow https in.
- - direction: ingress
- ethertype: IPv4
- port_range_min: 80
- port_range_max: 80
- protocol: tcp
- # Allow imaps in.
- - direction: ingress
- ethertype: IPv4
- port_range_min: 993
- port_range_max: 993
- protocol: tcp
- # Allow smtp submission in.
- - direction: ingress
- ethertype: IPv4
- port_range_min: 587
- port_range_max: 587
- protocol: tcp
- # Allow git in.
- - direction: ingress
- ethertype: IPv4
- port_range_min: 9418
- port_range_max: 9418
- protocol: tcp
-
- public_port:
- type: OS::Neutron::Port
- properties:
- network: { get_param: public_network }
- security_groups: [{ get_resource: sg }]
-
- public_ip:
- type: OS::Neutron::FloatingIP
- depends_on: public_port
- properties:
- floating_network: { get_param: floating_network }
- port_id: { get_resource: public_port }
-
- pieni:
- type: OS::Nova::Server
- depends_on: public_port
- properties:
- availability_zone : { get_param: availability_zone }
- key_name: { get_param: key_name }
- image: { get_param: image_id }
- flavor: { get_param: instance_flavor }
- networks:
- - port: { get_resource: public_port }
diff --git a/new-create-vm b/new-create-vm
deleted file mode 100755
index 6350247..0000000
--- a/new-create-vm
+++ /dev/null
@@ -1,167 +0,0 @@
-#!/usr/bin/env python3
-
-import os
-import shutil
-import socket
-import subprocess
-import sys
-import tempfile
-import time
-import yaml
-
-
-def msg(s):
- print(f"{s}")
-
-
-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, network, 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",
- f"--network={network}",
- "--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]))
- vm = sys.argv[2]
-
- msg(f"creating VM {vm}")
-
- config = config[vm]
- base = os.path.expanduser(config["base_image"])
- img = os.path.expanduser(config["image_file"])
- size = config["image_size"]
- pubkey = os.path.expanduser(config["public_key"])
- memory = config.get("memory", 1024)
- cpus = config.get("cpus", 1)
- network = config.get("network", "network=default")
-
- memory = int(memory)
- cpus = int(cpus)
- pubkey = open(pubkey).read().rstrip()
- iso = f"{vm}.iso"
-
- msg(f"creating cloud-init config {iso}")
- cloud_init_iso(iso, vm, pubkey)
-
- if os.path.exists(img):
- msg(f"removing existing image {img}")
- os.remove(img)
- msg(f"creating new image {img} as a copy of {base}")
- shutil.copy(base, img)
-
- msg(f"resizing to {size}")
- subprocess.check_call(["qemu-img", "resize", "-q", img, size])
-
- msg(f"creating VM")
- create_vm(vm, img, iso, network, memory=memory, cpus=cpus)
-
- msg(f"waiting for SSH to be available")
- wait_for_ssh(vm)
-
- msg(f"removing cloud-init config")
- subprocess.check_output(
- ["virsh", "detach-disk", "--persistent", "--live", vm, "vdb"]
- )
- os.remove(iso)
-
- msg("OK")
-
-
-main()
diff --git a/new-remove-vm b/new-remove-vm
deleted file mode 100755
index 67a078d..0000000
--- a/new-remove-vm
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/bin/bash
-
-set -eu -o pipefail
-
-running()
-{
- virsh domstate "$1" | grep -q -Fx running
-}
-
-shutoff()
-{
- virsh domstate "$1" | grep -q -Fx "shut off"
-}
-
-for vm in "$@"
-do
- if running "$vm"
- then
- virsh shutdown "$vm" > /dev/null
- while ! shutoff "$vm"
- do
- sleep 1
- done
- fi
- virsh undefine "$vm" > /dev/null
-done
diff --git a/new.yaml b/new.yaml
deleted file mode 100644
index b2d6d06..0000000
--- a/new.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-testvm:
- base_image: ~/tmp/debian-10-openstack-amd64.qcow2
- image_file: ~/tmp/vms/testvm.qcow2
- image_size: 10G
- memory: 1024
- cpus: 2
- public_key: ~/.ssh/liw-openpgp.pub
diff --git a/remove-vm b/remove-vm
deleted file mode 100755
index e60bc93..0000000
--- a/remove-vm
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/bin/sh
-#
-# Remove a VM for liw.
-
-set -eu
-
-run_virsh()
-{
- virsh -c qemu:///system "$@"
-}
-
-vm_exists()
-{
- run_virsh list --all | grep -F "$name" > /dev/null
-}
-
-remove_vm()
-{
- local name="$1"
-
- # Shut down and remove the VM, if it exists.
- if vm_exists "$name"
- then
- run_virsh destroy "$name" || true
- run_virsh undefine --nvram "$name"
- fi
-
-
- # Remove the LV, if it exists.
- lvpath="/dev/$vg/$name"
- if [ -e "$lvpath" ]
- then
- if ! sudo lvremove --force "$lvpath"
- then
- # In case the LV was kpartx'd, undo that
- sudo kpartx -dsv "$lvpath"
- sudo lvremove --force "$lvpath"
- fi
- fi
-
- # Remove the host from /etc/hosts, if there.
- awk -v "name=$name" '$2 != name' /etc/hosts | sudo sponge /etc/hosts
-
- # Done.
- echo "Virtual machine $name is gone."
-}
-
-
-# Read config variables.
-. "$HOME/.config/ansibleness/vm.conf"
-
-for name in "$@"
-do
- remove_vm "$name"
-done