Skip to content

Instantly share code, notes, and snippets.

@ngschmidt
Last active December 25, 2023 20:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ngschmidt/88fe09a1c5733735a4232dd24c44f78e to your computer and use it in GitHub Desktop.
Save ngschmidt/88fe09a1c5733735a4232dd24c44f78e to your computer and use it in GitHub Desktop.
GitHub Actions vSphere + Netbox VM Deployment
---
- hosts: localhost
gather_facts: true
# Before executing ensure that the prerequisites are installed
# `ansible-galaxy collection install vmware.vmware_rest netbox.netbox`
# `python3 -m pip install aiohttp pynetbox`
# We start with a pre-check playbook, if it fails, we don't want to
# make changes
any_errors_fatal: true
vars_files:
- "parameters.yaml"
- "options.yaml"
tasks:
- name: "Debug"
ansible.builtin.debug:
msg: '{{ image_data[vm_data["template"]] }}'
- name: "Build the VM"
vmware.vmware_rest.vcenter_vmtemplate_libraryitems:
vcenter_hostname: '{{ lookup("env", "VHOSTNAME") }}'
vcenter_username: '{{ lookup("env", "VAPIUSER") }}'
vcenter_password: '{{ lookup("env", "VAPIPASS") }}'
vcenter_validate_certs: false
name: '{{ vm_data.name }}'
library: '{{ vm_data.library }}'
template_library_item: '{{ image_data[vm_data["template"]] }}'
placement:
cluster: '{{ vm_data.cluster }}'
folder: '{{ vm_data.folder }}'
disk_storage:
datastore: '{{ vm_data.datastore }}'
hardware_customization:
cpu_update:
num_cpus: '{{ vm_data.hardware.cpus }}'
memory_update:
memory: '{{ vm_data.hardware.memory }}'
session_timeout: 1200
state: deploy
register: vmware_vm
- name: "Report the VM!"
ansible.builtin.debug:
var: vmware_vm
- name: "Start the VM!"
vmware.vmware_rest.vcenter_vm_power:
vcenter_hostname: '{{ lookup("env", "VHOSTNAME") }}'
vcenter_username: '{{ lookup("env", "VAPIUSER") }}'
vcenter_password: '{{ lookup("env", "VAPIPASS") }}'
vcenter_validate_certs: false
vm: '{{ vmware_vm.value }}'
state: start
- name: "Wait for the VM to fully boot"
ansible.builtin.pause:
minutes: 2
- name: "Fetch VM networking information"
vmware.vmware_rest.vcenter_vm_guest_networking_interfaces_info:
vcenter_hostname: '{{ lookup("env", "VHOSTNAME") }}'
vcenter_username: '{{ lookup("env", "VAPIUSER") }}'
vcenter_password: '{{ lookup("env", "VAPIPASS") }}'
vcenter_validate_certs: false
vm: "{{ vmware_vm.value }}"
register: vmware_vm_networking_ifaces
- name: "Report the VM's Networking Interfaces Info!"
ansible.builtin.debug:
var: vmware_vm_networking_ifaces
- name: "Fetch VM networking information"
vmware.vmware_rest.vcenter_vm_guest_networking_info:
vcenter_hostname: '{{ lookup("env", "VHOSTNAME") }}'
vcenter_username: '{{ lookup("env", "VAPIUSER") }}'
vcenter_password: '{{ lookup("env", "VAPIPASS") }}'
vcenter_validate_certs: false
vm: "{{ vmware_vm.value }}"
register: vmware_vm_networking
- name: "Report the VM's Networking Info!"
ansible.builtin.debug:
var: vmware_vm_networking
- name: "Register the VM in Netbox!"
netbox.netbox.netbox_virtual_machine:
netbox_token: '{{ lookup("env", "NETBOX_TOKEN") }}'
netbox_url: '{{ lookup("env", "NETBOX_URL") }}'
validate_certs: false
data:
cluster: '{{ lookup("env", "NETBOX_CLUSTER") }}'
name: '{{ vm_data.name }}'
description: '{{ vmware_vm }}'
local_context_data: '{{ vm_data }}'
memory: '{{ vm_data.hardware.memory }}'
vcpus: '{{ vm_data.hardware.cpus }}'
- name: "Configure VM Interface in Netbox!"
netbox.netbox.netbox_vm_interface:
netbox_token: '{{ lookup("env", "NETBOX_TOKEN") }}'
netbox_url: '{{ lookup("env", "NETBOX_URL") }}'
validate_certs: false
data:
name: '{{ vm_data.name }}_intf_{{ item.mac_address | replace(":", "") | safe }}'
virtual_machine: '{{ vm_data.name }}'
vrf: 'Campus'
mac_address: '{{ item.mac_address }}'
with_items: '{{ vmware_vm_networking_ifaces.value }}'
- name: "Reserve IP"
netbox.netbox.netbox_ip_address:
netbox_token: '{{ lookup("env", "NETBOX_TOKEN") }}'
netbox_url: '{{ lookup("env", "NETBOX_URL") }}'
validate_certs: false
data:
address: '{{ item.ip.ip_addresses[0].ip_address }}/{{ item.ip.ip_addresses[0].prefix_length }}'
vrf: 'Campus'
assigned_object:
virtual_machine: '{{ vm_data.name }}'
state: present
with_items: '{{ vmware_vm_networking_ifaces.value }}'
register: ip_obj
- name: "Debug"
ansible.builtin.debug:
msg: "{{ ip_obj }}"
- name: "Finalize the VM in Netbox!"
netbox.netbox.netbox_virtual_machine:
netbox_token: '{{ lookup("env", "NETBOX_TOKEN") }}'
netbox_url: '{{ lookup("env", "NETBOX_URL") }}'
validate_certs: false
data:
cluster: 'eng-lab-c0'
name: '{{ vm_data.name }}'
primary_ip4:
address: '{{ vmware_vm_networking_ifaces.value[0].ip.ip_addresses[0].ip_address }}/{{ vmware_vm_networking_ifaces.value[0].ip.ip_addresses[0].prefix_length }}'
vrf: "Campus"
name: "On-Demand: Build VM"
on:
workflow_dispatch:
inputs:
machine_name:
description: "Machine Name"
required: true
default: "abcde"
template:
description: "VM Template UUID"
required: true
type: choice
options:
- alpine_latest
- ubuntu_latest
- debian_latest
default: "alpine_latest"
library:
description: "Content Library"
required: true
default: "9b15789e-af13-41fe-a931-a78d9fde840e"
hardware_cpus:
description: "VM vCPU Count"
required: true
default: "1"
hardware_memory:
description: "VM Memory Allocation (in MB)"
required: true
default: "512"
permissions:
contents: read
jobs:
build:
runs-on: self-hosted
steps:
- uses: actions/checkout@v3
- name: Create Variable YAML File
run: |
cat <<EOF > roles/vmware_rest/parameters.yaml
---
vm_data:
name: "${{ github.event.inputs.machine_name }}"
template: "${{ github.event.inputs.template }}"
cluster: "domain-c1008"
datastore: "datastore-73010"
folder: "group-v1100"
library: "${{ github.event.inputs.library }}"
hardware:
cpus: ${{ github.event.inputs.hardware_cpus }}
memory: ${{ github.event.inputs.hardware_memory }}
EOF
cat <<EOF > roles/vmware_rest/options.yaml
---
image_data:
alpine_latest: "e162b08e-a9a4-4a37-af61-d3f5397360af"
ubuntu_latest: "a609b303-931a-4c27-a2c5-06cf5a831695"
debian_latest: "78bfb9cd-c82a-4864-9755-a915974492db"
EOF
- name: Build VM
run: |
cd roles/vmware_rest/
cat parameters.yaml
cat options.yaml
export VAPIUSER="${{ secrets.VAPIUSER }}"
export VAPIPASS="${{ secrets.VAPIPASS }}"
export VHOSTNAME="vcenter.lab.engyak.net"
export NETBOX_TOKEN="${{ secrets.NETBOX_TOKEN }}"
export NETBOX_URL="https://netbox-url"
export NETBOX_CLUSTER="eng-lab-c0"
ansible-playbook build_vm.yml
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment