Skip to content

Commit

Permalink
Add update playbook (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
teddyphreak authored May 4, 2024
1 parent b15d78b commit 1e3851d
Show file tree
Hide file tree
Showing 21 changed files with 996 additions and 37 deletions.
75 changes: 75 additions & 0 deletions .github/workflows/libvirt.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
name: libvirt

on:
pull_request:
branches:
- master
paths:
- 'playbooks/prepare.yml'
- 'molecule/update/*.yml'
- 'playbooks/update.yml'
- '.github/workflows/libvirt.yml'

jobs:
version:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Check if galaxy.yml has been modified
run: |
# Get a list of all modified files in this PR
FILES_CHANGED=$(git diff --name-only HEAD^ HEAD)
echo "Files changed: $FILES_CHANGED"
# Check if galaxy.yml is in the list of changed files
if [[ $FILES_CHANGED != *"galaxy.yml"* ]]; then
echo "Error: galaxy.yml has not been modified."
exit 1
fi
libvirt:
name: libvirt
runs-on: libvirt
needs: version
strategy:
matrix:
scenario:
- update
image:
- https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img
steps:
- name: Check out the codebase
uses: actions/checkout@v4

- name: Set up python 3
uses: actions/setup-python@v5
with:
python-version: '3.x'

- name: Update ubuntu repositories
run: sudo apt-get update

- name: Install make
run: sudo apt-get install -y make

- name: Install dependencies
run: make install

- name: Debug test environment
run: make debug

- name: Install role requirements
run: make requirements

- name: Run molecule tests.
run: make test
env:
PY_COLORS: '1'
ANSIBLE_FORCE_COLOR: '1'
MOLECULE_KVM_IMAGE: ${{ matrix.image }}
MOLECULE_SCENARIO: ${{ matrix.scenario }}
18 changes: 4 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,12 @@

An [ansible collection](https://galaxy.ansible.com/ui/repo/published/pokerops/consul/) to install and manage [Consul](https://www.consul.io/) clusters

## ToDo

* Add CI harness
* Add role dependencies
* Add install playbook
* Add install CI tests
* Add update playbook
* Add update CI tests
* Publish collection

## Collection hostgroups

| Hostgroup | Default | Description |
|:-------------|--------:|:---------------|
| consul_group | consul' | Consul cluster |
| | | |
| Hostgroup | Default | Description |
|:-------------------------|---------------------:|:---------------------------------|
| consul_group | 'consul' | Consul cluster members |
| consul_update_skip_group | 'consul_update_skip' | Consul cluster update skip hosts |

## Collection variables

Expand Down
2 changes: 1 addition & 1 deletion galaxy.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
namespace: pokerops
name: consul
version: 0.0.2
version: 0.0.3
readme: README.md
authors:
- Ted Cook <[email protected]>
Expand Down
1 change: 0 additions & 1 deletion molecule/binary/molecule.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ provisioner:
hosts:
all:
vars:
consul_config_hostnames: false
consul_install_from_repo: false
verifier:
name: ansible
Expand Down
275 changes: 275 additions & 0 deletions molecule/common/create.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,275 @@
---
- name: Configure KVM host
hosts: localhost
become: true
vars_files:
- vars.yml
tasks:
- name: Install package requirements
ansible.builtin.package:
name:
- qemu-kvm
- qemu-efi
- libvirt-clients
- libvirt-daemon-system
- libvirt-daemon-system-systemd
- python3-libvirt
become: true

- name: Query libvirt pools
community.libvirt.virt_pool:
command: list_pools
register: _pools

- name: Create libvirt path
ansible.builtin.file:
path: "{{ _libvirt_path }}"
state: directory
owner: root
group: root
mode: 0755
become: true

- name: Define libvirt pool
community.libvirt.virt_pool:
command: define
name: "{{ _libvirt_pool }}"
xml: "{{ lookup('ansible.builtin.template', 'pool.j2.xml') }}"
vars:
_pool: "{{ _libvirt_pool }}"
_path: "{{ _libvirt_path }}"

- name: Activate libvirt pool
community.libvirt.virt_pool:
state: active
name: "{{ _libvirt_pool }}"

- name: Add libvirt network
community.libvirt.virt_net:
command: define
name: "{{ _libvirt_network }}"
xml: "{{ lookup('ansible.builtin.template', 'network.j2.xml') }}"
vars:
_network: "{{ _libvirt_network }}"
_address: "{{ _libvirt_address }}"
_dhcp: "{{ _libvirt_dhcp }}"
_net_address: "{{ _address | ansible.utils.ipaddr('1') | ansible.utils.ipaddr('address') }}"
_net_mask: "{{ _address | ansible.utils.ipaddr('netmask') }}"
_net_dhcp_start: "{{ _dhcp | ansible.utils.ipaddr('2') | ansible.utils.ipaddr('address') }}"
_net_dhcp_end: "{{ _dhcp | ansible.utils.ipaddr('-2') | ansible.utils.ipaddr('address') }}"
when: _libvirt_network != "default"

- name: Start libvirt network
community.libvirt.virt_net:
command: create
name: "{{ _libvirt_network }}"
when: _libvirt_network != "default"

- name: List cached images
ansible.builtin.find:
paths: "{{ _libvirt_path }}"
recurse: false
register: _cache_query

- name: Inspect cached images
ansible.builtin.set_fact:
_uncached_images: "{{ (_uncached_images | default([])) + [item] }}"
vars:
_cached_images: "{{ _cache_query.files | map(attribute='path') }}"
_basename: "{{ item | urlsplit('path') | basename }}"
_path: "{{ _libvirt_path }}/{{ _basename }}"
loop: "{{ molecule_yml.platforms | map(attribute='image') | unique }}"
when: _path not in _cached_images

- name: Cache platform images
ansible.builtin.get_url:
url: "{{ item }}"
dest: "{{ _path }}"
owner: root
group: root
mode: 0600
vars:
_basename: "{{ item | urlsplit('path') | basename }}"
_path: "{{ _libvirt_path }}/{{ _basename }}"
loop: "{{ _uncached_images | default([]) }}"


- name: Create KVM guests
hosts: all
gather_facts: false
become: true
vars_files:
- vars.yml
tasks:
- name: Create KVM guest
delegate_to: localhost
block:
- name: Create SSH key
community.crypto.openssh_keypair:
path: "{{ lookup('ansible.builtin.env', 'MOLECULE_EPHEMERAL_DIRECTORY') }}/id_rsa"
run_once: true
register: _pubkey
become: false

- name: Query active KVM guests
ansible.builtin.command: virsh list --name
run_once: true
register: guest_query

- name: Manage KVM guests
when: inventory_hostname not in guest_query.stdout_lines
block:
- name: Create KVM guest disks
ansible.builtin.copy:
remote_src: true
src: "{{ _libvirt_path }}/{{ _platform.image | urlsplit('path') | basename }}"
dest: "{{ _disk }}"
owner: libvirt-qemu
group: kvm
mode: 0666
force: true
vars:
_platforms: "{{ molecule_yml.platforms }}"
_platform: "{{ _platforms | selectattr('name', 'equalto', inventory_hostname) | first }}"
_disk: "{{ _libvirt_path }}/{{ _platform.name }}.img"

- name: Resize KVM guest disks
ansible.builtin.command:
cmd: qemu-img resize {{ _disk }} {{ _platform.size | default('20G') }}
vars:
_platforms: "{{ molecule_yml.platforms }}"
_platform: "{{ _platforms | selectattr('name', 'equalto', inventory_hostname) | first }}"
_disk: "{{ _libvirt_path }}/{{ _platform.name }}.img"

- name: Create cloud-init tempdir
ansible.builtin.tempfile:
state: directory
prefix: libvirt
register: libvirt_tmpdir
run_once: true

- name: Create KVM guest
block:
- name: Create instance tempdir
ansible.builtin.file:
dest: "{{ libvirt_tmpdir.path }}/{{ inventory_hostname }}"
state: directory

- name: Create cloud-init meta data
ansible.builtin.template:
src: "meta-data.yml.j2"
dest: "{{ libvirt_tmpdir.path }}/{{ inventory_hostname }}/meta-data"

- name: Create cloud-init user data
ansible.builtin.template:
src: "user-data.yml.j2"
dest: "{{ libvirt_tmpdir.path }}/{{ inventory_hostname }}/user-data"
vars:
guest_user: "{{ _libvirt_user }}"
guest_key: "{{ _pubkey.public_key }}"

- name: Create cloud-init iso
ansible.builtin.command:
cmd: |
xorriso -as mkisofs
-volid cidata -joliet -rock
-o {{ _libvirt_path }}/{{ inventory_hostname }}.iso .
chdir: "{{ libvirt_tmpdir.path }}/{{ inventory_hostname }}"

- name: Create KVM guest
community.libvirt.virt:
xml: "{{ lookup('ansible.builtin.template', 'vm.j2.xml') }}"
command: define
vars:
_platforms: "{{ molecule_yml.platforms }}"
_platform: "{{ _platforms | selectattr('name', 'equalto', inventory_hostname) | first }}"
guest_hostname: "{{ inventory_hostname }}"
guest_disk_format: qcow2
guest_disk_path: "{{ _libvirt_path }}/{{ inventory_hostname }}.img"
guest_iso_path: "{{ _libvirt_path }}/{{ inventory_hostname }}.iso"
guest_network: "{{ _libvirt_network }}"
guest_mac: "{{ '52:54:00' | random_mac(seed=guest_hostname) }}"
guest_mem: "{{ (_platform.mem | default(2)) * 1048576 }}"
guest_cpu: "{{ _platform.cpu | default(2) }}"
loop_control:
label: "{{ inventory_hostname }} - {{ _libvirt_path }}/{{ inventory_hostname }}.img"

always:
- name: Destroy cloud-init tempdir
ansible.builtin.file:
dest: "{{ libvirt_tmpdir.path }}"
state: absent
run_once: true

- name: Start KVM guest
community.libvirt.virt:
name: "{{ inventory_hostname }}"
state: running


- name: Build instance config file
hosts: localhost
vars_files:
- vars.yml
tasks:
- name: Create SSH key
community.crypto.openssh_keypair:
path: "{{ lookup('ansible.builtin.env', 'MOLECULE_EPHEMERAL_DIRECTORY') }}/id_rsa"
run_once: true
register: _pubkey

- name: Retrieve platform ip information
become: true
block:
- name: Wait for DHCP lease assignment
ansible.builtin.shell:
cmd: "virsh net-dhcp-leases --network {{ _libvirt_network }} | grep {{ item }}"
executable: /bin/bash
loop: "{{ molecule_yml.platforms | map(attribute='name') }}"
register: dhcp_query
retries: 6
delay: 30
until: dhcp_query is succeeded

- name: Query DHCP leases
ansible.builtin.shell: >
virsh net-dhcp-leases --network {{ _libvirt_network }} | grep {{ item }} | awk '{print $5}'
loop: "{{ molecule_yml.platforms | map(attribute='name') }}"
register: dhcp_query

- name: Populate instance config dict
ansible.builtin.set_fact:
instance_conf_dict: {
'instance': "{{ item }}",
'address': "{{ _libvirt_address | ansible.utils.ipaddr('address') }}",
'user': "{{ _libvirt_user }}",
'port': "22",
'identity_file': "{{ _pubkey.filename }}"
}
vars:
_libvirt_addresses: "{{ dhcp_query.results | nephelaiio.plugins.list_to_dict('item') }}"
_libvirt_address: "{{ _libvirt_addresses[item].stdout }}"
loop: "{{ molecule_yml.platforms | map(attribute='name') }}"
register: instance_config_dict

- name: Convert instance config dict to a list
ansible.builtin.set_fact:
_instance_conf: "{{ _instance_results | map(attribute='ansible_facts.instance_conf_dict') | list }}"
vars:
_instance_results: "{{ instance_config_dict.results }}"

- name: Dump instance config
ansible.builtin.copy:
content: "{{ _instance_conf | ansible.builtin.to_nice_yaml(indent=2) }}"
dest: "{{ molecule_instance_config }}"
mode: 0640

- name: Configure host file entries
ansible.builtin.lineinfile:
path: /etc/hosts
regexp: ".*{{ item.instance }}.*"
line: "{{ item.address }} {{ item.instance }}"
loop_control:
label: "{{ item.instance }}"
loop: "{{ _instance_conf }}"
become: true
Loading

0 comments on commit 1e3851d

Please sign in to comment.