From ec854a9c27bb33896a9a3cf1b6389c8615de6c90 Mon Sep 17 00:00:00 2001 From: moeny-matt Date: Thu, 21 Nov 2024 15:35:42 -0500 Subject: [PATCH] Add bolt scripting to create VMs --- .gitignore | 1 + README.md | 17 +++- bolt_vm_automation/.gitignore | 7 ++ bolt_vm_automation/bolt-project.yaml | 2 + bolt_vm_automation/inventory.yaml | 32 ++++++++ bolt_vm_automation/plans/create_vm.yaml | 95 ++++++++++++++++++++++ bolt_vm_automation/tasks/create_vm.json | 40 +++++++++ bolt_vm_automation/tasks/create_vm.sh | 31 +++++++ bolt_vm_automation/tasks/install_docker.sh | 39 +++++++++ bolt_vm_automation/tasks/system_setup.json | 40 +++++++++ bolt_vm_automation/tasks/system_setup.sh | 51 ++++++++++++ user-data.yaml | 2 +- 12 files changed, 355 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 bolt_vm_automation/.gitignore create mode 100644 bolt_vm_automation/bolt-project.yaml create mode 100644 bolt_vm_automation/inventory.yaml create mode 100644 bolt_vm_automation/plans/create_vm.yaml create mode 100644 bolt_vm_automation/tasks/create_vm.json create mode 100644 bolt_vm_automation/tasks/create_vm.sh create mode 100644 bolt_vm_automation/tasks/install_docker.sh create mode 100644 bolt_vm_automation/tasks/system_setup.json create mode 100644 bolt_vm_automation/tasks/system_setup.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..496ee2c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store \ No newline at end of file diff --git a/README.md b/README.md index d669f6a..5368c0f 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ Note that the following steps are derived from this [guide](https://www.pugetsys [Autoinstall configuration reference manual](https://canonical-subiquity.readthedocs-hosted.com/en/latest/reference/autoinstall-reference.html) +## Generating the autoinstall ISO + 1. Install necessary packages ```bash @@ -111,4 +113,17 @@ sudo apt install yamllint yamllint server/user-data ``` -Once the `xorriso` command is run successfully, the `ubuntu-22.04-autoinstall.iso` will be created in the `iso-build` directory. \ No newline at end of file +Once the `xorriso` command is run successfully, the `ubuntu-22.04-autoinstall.iso` will be created in the `iso-build` directory. + +## Creating the VM using Bolt + +Update the parameters provided to the below plan run command as needed. + +```bash +cd bolt_vm_automation +bolt plan run bolt_vm_automation::create_vm \ + target=roscoe \ + vm_name=moeny-bank01 \ + ip_with_cidr=100.40.223.189/24 \ + hostname=moeny-bank01 +``` \ No newline at end of file diff --git a/bolt_vm_automation/.gitignore b/bolt_vm_automation/.gitignore new file mode 100644 index 0000000..16d0241 --- /dev/null +++ b/bolt_vm_automation/.gitignore @@ -0,0 +1,7 @@ +.modules/ +.resource_types/ +bolt-debug.log +.plan_cache.json +.plugin_cache.json +.task_cache.json +.rerun.json diff --git a/bolt_vm_automation/bolt-project.yaml b/bolt_vm_automation/bolt-project.yaml new file mode 100644 index 0000000..7c36176 --- /dev/null +++ b/bolt_vm_automation/bolt-project.yaml @@ -0,0 +1,2 @@ +--- +name: bolt_vm_automation diff --git a/bolt_vm_automation/inventory.yaml b/bolt_vm_automation/inventory.yaml new file mode 100644 index 0000000..44423a9 --- /dev/null +++ b/bolt_vm_automation/inventory.yaml @@ -0,0 +1,32 @@ +groups: + - name: remote-host + targets: + - name: roscoe + config: + transport: ssh + ssh: + host: 100.40.223.136 + user: root + host-key-check: false + - name: siderack + config: + transport: ssh + ssh: + host: 100.40.223.138 + user: root + host-key-check: false + + - name: new-vm + targets: + - name: vm-template-staging + config: + transport: ssh + ssh: + host: 100.40.223.190 + user: moeny + private-key: ~/.ssh/DMMF-20211104 + host-key-check: false + +config: + ssh: + native-ssh: true diff --git a/bolt_vm_automation/plans/create_vm.yaml b/bolt_vm_automation/plans/create_vm.yaml new file mode 100644 index 0000000..abb733d --- /dev/null +++ b/bolt_vm_automation/plans/create_vm.yaml @@ -0,0 +1,95 @@ +--- +parameters: + target: + type: String + description: "Target host to create the VM on" + default: "roscoe" + iso_path: + type: String + description: "Path to the ISO file" + default: "/mnt/nfs/kvm-isos/iso-build/ubuntu-22.04-autoinstall.iso" + vm_name: + type: String + description: "Name of the VM" + default: "vm-template-staging" + ram: + type: Integer + description: "Amount of RAM in MB" + default: 2048 + vcpus: + type: Integer + description: "Number of virtual CPUs" + default: 4 + disk_size: + type: Integer + description: "Size of the disk in GB" + default: 100 + disk_path: + type: String + description: "Base path for disk images" + default: "/mnt/nfs/kvm-images" + network: + type: String + description: "Network to connect the VM to" + default: "wan-verizon" + ip_with_cidr: + type: String + description: "Public IP of the VM" + default: "100.40.223.190/24" + hostname: + type: String + description: "Hostname of the VM" + default: "vm-template-staging" + dhcp: + type: Boolean + description: "Enable DHCP on the VM" + default: false + gateway: + type: String + description: "Gateway for the VM" + default: "100.40.223.1" + nameserver1: + type: String + description: "Primary nameserver for the VM" + default: "8.8.8.8" + nameserver2: + type: String + description: "Secondary nameserver for the VM" + default: "8.8.4.4" + nameserver3: + type: String + description: "Tertiary nameserver for the VM" + default: "1.1.1.1" + +steps: + - name: create_vm + task: bolt_vm_automation::create_vm + targets: $target + parameters: + iso_path: $iso_path + vm_name: $vm_name + ram: $ram + vcpus: $vcpus + disk_size: $disk_size + disk_path: "${disk_path}/${vm_name}.qcow2" + network: $network + + - name: install_docker + description: Install Docker on the VM + task: bolt_vm_automation::install_docker + targets: vm-template-staging + + - name: system_setup + task: bolt_vm_automation::system_setup + targets: vm-template-staging + parameters: + ip_with_cidr: $ip_with_cidr + hostname: $hostname + dhcp: $dhcp + gateway: $gateway + nameserver1: $nameserver1 + nameserver2: $nameserver2 + nameserver3: $nameserver3 + +return: + message: "VM ${vm_name} created and updated successfully!" diff --git a/bolt_vm_automation/tasks/create_vm.json b/bolt_vm_automation/tasks/create_vm.json new file mode 100644 index 0000000..02fcc99 --- /dev/null +++ b/bolt_vm_automation/tasks/create_vm.json @@ -0,0 +1,40 @@ +{ + "description": "Creates a new VM using virt-install", + "parameters": { + "iso_path": { + "type": "String", + "description": "Path to the autoinstall ISO", + "default": "/mnt/nfs/kvm-isos/iso-build/ubuntu-22.04-autoinstall.iso" + }, + "vm_name": { + "type": "String", + "description": "Name of the VM", + "default": "vm-template-staging" + }, + "ram": { + "type": "Integer", + "description": "Amount of RAM in MB", + "default": 2048 + }, + "vcpus": { + "type": "Integer", + "description": "Number of virtual CPUs", + "default": 4 + }, + "disk_size": { + "type": "Integer", + "description": "Size of the VM disk in GB", + "default": 100 + }, + "disk_path": { + "type": "String", + "description": "Base path for disk images", + "default": "/mnt/nfs/kvm-images/vm-template-staging.qcow2" + }, + "network": { + "type": "String", + "description": "Network to connect the VM to", + "default": "wan-verizon" + } + } +} \ No newline at end of file diff --git a/bolt_vm_automation/tasks/create_vm.sh b/bolt_vm_automation/tasks/create_vm.sh new file mode 100644 index 0000000..9b3cca3 --- /dev/null +++ b/bolt_vm_automation/tasks/create_vm.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# Input Variables +ISO_PATH=$PT_iso_path +VM_NAME=$PT_vm_name +RAM=$PT_ram +VCPUS=$PT_vcpus +DISK_SIZE=$PT_disk_size +DISK_PATH=$PT_disk_path +NETWORK=$PT_network + +# Create VM disk if not already exists +if [ ! -f "$DISK_PATH" ]; then + qemu-img create -f qcow2 "$DISK_PATH" "$DISK_SIZE"G > /dev/null 2>&1 +fi + +# Create VM +virt-install \ + --name "$VM_NAME" \ + --ram "$RAM" \ + --vcpus "$VCPUS" \ + --os-variant ubuntu22.04 \ + --disk path="$DISK_PATH",format=qcow2 \ + --cdrom "$ISO_PATH" \ + --network network="$NETWORK" \ + --graphics vnc \ + --noautoconsole \ + --autostart \ + --wait -1 + +sleep 45 \ No newline at end of file diff --git a/bolt_vm_automation/tasks/install_docker.sh b/bolt_vm_automation/tasks/install_docker.sh new file mode 100644 index 0000000..4d29a76 --- /dev/null +++ b/bolt_vm_automation/tasks/install_docker.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +# Update package list and install prerequisites +sudo apt-get update +sudo apt-get install -y \ + ca-certificates \ + curl \ + gnupg + +# Add Docker's official GPG key +sudo install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg +sudo chmod a+r /etc/apt/keyrings/docker.gpg + +# Add the repository to Apt sources +echo \ + "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ + "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \ + sudo tee /etc/apt/sources.list.d/docker.list > /dev/null + +# Update package list again and install Docker +sudo apt-get update +sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin + +# Add current user to docker group +sudo usermod -aG docker "$USER" + +# Start and enable Docker service +sudo systemctl start docker +sudo systemctl enable docker + +# Verify installation +if docker --version > /dev/null 2>&1; then + echo "Docker installed successfully" + exit 0 +else + echo "Docker installation failed" + exit 1 +fi diff --git a/bolt_vm_automation/tasks/system_setup.json b/bolt_vm_automation/tasks/system_setup.json new file mode 100644 index 0000000..d8f0ade --- /dev/null +++ b/bolt_vm_automation/tasks/system_setup.json @@ -0,0 +1,40 @@ +{ + "description": "Configures system network settings using netplan", + "parameters": { + "ip_with_cidr": { + "type": "String", + "description": "IP address for the VM", + "default": "100.40.223.190/24" + }, + "hostname": { + "type": "String", + "description": "Hostname for the VM", + "default": "vm-template-staging" + }, + "dhcp": { + "type": "Boolean", + "description": "Whether to use DHCP for network configuration", + "default": false + }, + "gateway": { + "type": "String", + "description": "Gateway IP address", + "default": "100.40.223.1" + }, + "nameserver1": { + "type": "String", + "description": "Primary DNS nameserver", + "default": "8.8.8.8" + }, + "nameserver2": { + "type": "String", + "description": "Secondary DNS nameserver", + "default": "8.8.4.4" + }, + "nameserver3": { + "type": "String", + "description": "Tertiary DNS nameserver", + "default": "1.1.1.1" + } + } +} diff --git a/bolt_vm_automation/tasks/system_setup.sh b/bolt_vm_automation/tasks/system_setup.sh new file mode 100644 index 0000000..32baad3 --- /dev/null +++ b/bolt_vm_automation/tasks/system_setup.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# Using Bolt's environment variables +IP="${PT_ip_with_cidr}" +HOSTNAME="${PT_hostname}" +DHCP="${PT_dhcp}" +GATEWAY="${PT_gateway}" +NAMESERVER1="${PT_nameserver1}" +NAMESERVER2="${PT_nameserver2}" +NAMESERVER3="${PT_nameserver3}" + +# Check if all required parameters are provided +if [ -z "$IP" ] || [ -z "$HOSTNAME" ] || [ -z "$DHCP" ] || [ -z "$GATEWAY" ] || [ -z "$NAMESERVER1" ] || [ -z "$NAMESERVER2" ] || [ -z "$NAMESERVER3" ]; then + echo "Missing required parameters. All parameters must be provided." + exit 1 +fi + +# Create the new netplan configuration +sudo tee /etc/netplan/50-cloud-init.yaml << EOL +network: + version: 2 + ethernets: + enp1s0: + dhcp4: ${DHCP} +EOL + +# If DHCP is false, add static IP configuration +if [ "$DHCP" = "false" ]; then + sudo tee -a /etc/netplan/50-cloud-init.yaml << EOL + addresses: + - ${IP} + routes: + - to: default + via: ${GATEWAY} + nameservers: + addresses: [${NAMESERVER1}, ${NAMESERVER2}, ${NAMESERVER3}] +EOL +fi + +# Set the hostname +sudo hostnamectl set-hostname "${HOSTNAME}" +echo "${HOSTNAME}" | sudo tee /etc/hostname > /dev/null + +# Update /etc/hosts +sudo sed -i "s/127.0.1.1.*/127.0.1.1\t${HOSTNAME}/" /etc/hosts + +echo "System configuration completed successfully" + +# Apply network configuration in the background and exit before it takes effect +nohup bash -c "(sleep 2 && sudo netplan apply) &" > /dev/null 2>&1 +exit 0 \ No newline at end of file diff --git a/user-data.yaml b/user-data.yaml index 2d8de00..d55d18b 100644 --- a/user-data.yaml +++ b/user-data.yaml @@ -43,4 +43,4 @@ autoinstall: shutdown: reboot late-commands: - - curtin in-target --target=/target apt-get update \ No newline at end of file + - ["curtin", "in-target", "--target=/target", "--", "/bin/bash", "-c", "echo '%sudo ALL=(ALL) NOPASSWD: ALL' | tee -a /etc/sudoers.d/nopasswd_sudo_group"] \ No newline at end of file