Ansible Collection Integration
The PiVirt Ansible Collection (pilab.pivirt) provides automated playbooks and modules for orchestrating virtual machine lifecycles, storage pools, network bridges, and multi-node clusters.
Installation
Section titled “Installation”Install Collection
Section titled “Install Collection”# Install from Ansible Galaxyansible-galaxy collection install pilab.pivirt
# Install from sourcegit clone https://github.com/pilab-cloud/ansible-collection-pivirtcd ansible-collection-pivirtansible-galaxy collection buildansible-galaxy collection install pilab-pivirt-1.0.0.tar.gzRequirements
Section titled “Requirements”collections: - name: pilab.pivirt version: ">=1.0.0"ansible-galaxy install -r requirements.ymlConfiguration
Section titled “Configuration”Inventory
Section titled “Inventory”all: children: pivirt: hosts: agent.pilab.hu: ansible_connection: local pivirt_endpoint: "https://agent.pilab.hu:8443" pivirt_ca_file: "~/.config/pvcli/ca.crt" pivirt_cert_file: "~/.config/pvcli/client.crt" pivirt_key_file: "~/.config/pvcli/client.key" pivirt_namespace: "production"Connection Plugin
Section titled “Connection Plugin”# ansible.cfg[defaults]collections_paths = ~/.ansible/collections:/usr/share/ansible/collections
[pivirt]endpoint = https://agent.pilab.hu:8443ca_file = ~/.config/pvcli/ca.crtcert_file = ~/.config/pvcli/client.crtkey_file = ~/.config/pvcli/client.keynamespace = productionModules
Section titled “Modules”Virtual Machine
Section titled “Virtual Machine”Create VM
Section titled “Create VM”- name: Create web server VM pilab.pivirt.vm: name: web-01 namespace: production state: present cpu: cores: 2 model: host-passthrough memory: size: 4Gi disks: - name: root size: 20Gi pool: default bus: virtio boot_order: 1 nics: - name: eth0 network: virbr0 model: virtio cloud_init: user_data: "{{ lookup('file', 'cloud-init.yaml') }}" labels: app: web env: productionStart/Stop VM
Section titled “Start/Stop VM”- name: Start VM pilab.pivirt.vm: name: web-01 namespace: production state: running
- name: Stop VM pilab.pivirt.vm: name: web-01 namespace: production state: stopped
- name: Restart VM pilab.pivirt.vm: name: web-01 namespace: production state: restartedDelete VM
Section titled “Delete VM”- name: Delete VM pilab.pivirt.vm: name: web-01 namespace: production state: absent cascade: true # Also delete disksGet VM Info
Section titled “Get VM Info”- name: Get VM info pilab.pivirt.vm_info: name: web-01 namespace: production register: vm_info
- name: Display VM IP debug: msg: "VM IP: {{ vm_info.vm.ip_address }}"Storage
Section titled “Storage”Create Volume
Section titled “Create Volume”- name: Create storage volume pilab.pivirt.storage_volume: name: data-01 pool: default size: 100Gi format: qcow2 state: presentCreate Snapshot
Section titled “Create Snapshot”- name: Create volume snapshot pilab.pivirt.storage_snapshot: volume: data-01 name: backup-01 state: presentResize Volume
Section titled “Resize Volume”- name: Resize volume pilab.pivirt.storage_volume: name: data-01 size: 200GiNetwork
Section titled “Network”Create Network
Section titled “Create Network”- name: Create VXLAN network pilab.pivirt.network: name: vxlan-net type: vxlan vxlan: vni: 1000 local_ip: 10.0.1.10 remote_ips: - 10.0.1.11 - 10.0.1.12 cidr: 10.10.0.0/16 state: presentAttach VM to Network
Section titled “Attach VM to Network”- name: Attach VM to network pilab.pivirt.network_attach: vm: web-01 network: vxlan-net ip: 10.10.1.10Cluster
Section titled “Cluster”Add Node
Section titled “Add Node”- name: Add worker node pilab.pivirt.cluster_node: cluster: production name: worker-04 role: worker ip: 10.0.1.24 state: presentDrain Node
Section titled “Drain Node”- name: Drain node for maintenance pilab.pivirt.cluster_node: cluster: production name: worker-01 drain: truePlaybooks
Section titled “Playbooks”Deploy Web Application Stack
Section titled “Deploy Web Application Stack”---- name: Deploy web application stack hosts: pivirt gather_facts: false
vars: namespace: production web_count: 3
tasks: - name: Create network pilab.pivirt.network: name: app-network type: bridge bridge: name: app-br interface: eth1 cidr: 10.10.0.0/24 state: present
- name: Create web servers pilab.pivirt.vm: name: "web-{{ item }}" namespace: "{{ namespace }}" state: running cpu: cores: 2 memory: size: 4Gi disks: - name: root size: 20Gi pool: default bus: virtio nics: - name: eth0 network: app-network model: virtio cloud_init: user_data: "{{ lookup('template', 'web-cloud-init.yaml.j2') }}" labels: app: web env: production loop: "{{ range(1, web_count + 1) | list }}" register: web_vms
- name: Create database server pilab.pivirt.vm: name: db-01 namespace: "{{ namespace }}" state: running cpu: cores: 4 memory: size: 8Gi disks: - name: root size: 20Gi pool: default bus: virtio - name: data size: 100Gi pool: fast-pool bus: virtio nics: - name: eth0 network: app-network model: virtio cloud_init: user_data: "{{ lookup('file', 'db-cloud-init.yaml') }}" labels: app: database env: production register: db_vm
- name: Create network policy pilab.pivirt.network_policy: name: web-to-db namespace: "{{ namespace }}" pod_selector: match_labels: app: database ingress: - from: - pod_selector: match_labels: app: web ports: - protocol: TCP port: 5432 state: present
- name: Display web server IPs debug: msg: "Web server {{ item.item }}: {{ item.vm.ip_address }}" loop: "{{ web_vms.results }}"
- name: Display database IP debug: msg: "Database server: {{ db_vm.vm.ip_address }}"Cloud-Init Templates
Section titled “Cloud-Init Templates”# web-cloud-init.yaml.j2#cloud-confighostname: web-{{ item }}fqdn: web-{{ item }}.pilab.hu
users: - name: pivirt groups: [sudo, docker] sudo: ALL=(ALL) NOPASSWD:ALL shell: /bin/bash ssh_authorized_keys: - {{ ssh_public_key }}
packages: - nginx - docker.io
runcmd: - systemctl enable --now nginx - systemctl enable --now docker
write_files: - path: /var/www/html/index.html content: | <!DOCTYPE html> <html> <head><title>Welcome</title></head> <body> <h2>Welcome to web-{{ item }}</h2> </body> </html>
final_message: "Web server ready"#cloud-confighostname: db-01fqdn: db-01.pilab.hu
users: - name: pivirt groups: [sudo, docker] sudo: ALL=(ALL) NOPASSWD:ALL shell: /bin/bash ssh_authorized_keys: - {{ ssh_public_key }}
packages: - postgresql - docker.io
runcmd: - systemctl enable --now postgresql - systemctl enable --now docker
final_message: "Database server ready"Backup Playbook
Section titled “Backup Playbook”---- name: Backup VMs hosts: pivirt gather_facts: false
vars: namespace: production retention_days: 7
tasks: - name: Get all VMs pilab.pivirt.vm_info: namespace: "{{ namespace }}" register: all_vms
- name: Create snapshots pilab.pivirt.vm_snapshot: vm: "{{ item.name }}" name: "backup-{{ ansible_date_time.date }}" state: present loop: "{{ all_vms.vms }}" when: item.status == 'running'
- name: Delete old snapshots pilab.pivirt.vm_snapshot: vm: "{{ item.0.name }}" name: "{{ item.1.name }}" state: absent loop: "{{ all_vms.vms | product(old_snapshots) | list }}" vars: old_snapshots: "{{ item.0.snapshots | selectattr('created_at', 'lt', retention_date) | list }}" retention_date: "{{ (ansible_date_time.epoch | int - (retention_days * 86400)) | to_datetime }}" when: old_snapshots | length > 0Web Server Role
Section titled “Web Server Role”---- name: Create web server VM pilab.pivirt.vm: name: "{{ vm_name }}" namespace: "{{ namespace }}" state: running cpu: cores: "{{ cpu_cores | default(2) }}" memory: size: "{{ memory_size | default('4Gi') }}" disks: - name: root size: "{{ disk_size | default('20Gi') }}" pool: "{{ storage_pool | default('default') }}" bus: virtio nics: - name: eth0 network: "{{ network_name }}" model: virtio cloud_init: user_data: "{{ lookup('template', 'cloud-init.yaml.j2') }}" labels: app: "{{ app_name }}" env: "{{ environment }}" register: vm_result
- name: Wait for VM to be ready pause: seconds: 30 when: vm_result.changed
- name: Get VM info pilab.pivirt.vm_info: name: "{{ vm_name }}" namespace: "{{ namespace }}" register: vm_infoBest Practices
Section titled “Best Practices”1. Use Variables
Section titled “1. Use Variables”---pivirt_endpoint: "https://agent.pilab.hu:8443"pivirt_namespace: "production"ssh_public_key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"2. Use Tags
Section titled “2. Use Tags”- name: Create web servers pilab.pivirt.vm: # ... tags: - web - create3. Use Handlers
Section titled “3. Use Handlers”- name: Update VM configuration pilab.pivirt.vm: name: web-01 # ... notify: Restart VM
handlers: - name: Restart VM pilab.pivirt.vm: name: web-01 state: restarted