Terraform Provider Integration
The PiVirt Terraform Provider (pilab-cloud/pivirt) allows infrastructure engineers to provision and manage virtual machines, storage pools, networks, and cloud clusters declaratively as code.
Installation
Section titled “Installation”Install Provider
Section titled “Install Provider”terraform { required_providers { pivirt = { source = "pilab-cloud/pivirt" version = "~> 1.0" } }}
provider "pivirt" { endpoint = "https://agent.pilab.hu:8443" ca_file = "~/.config/pvcli/ca.crt" cert_file = "~/.config/pvcli/client.crt" key_file = "~/.config/pvcli/client.key"}Install from Source
Section titled “Install from Source”git clone https://github.com/pilab-cloud/terraform-provider-pivirtcd terraform-provider-pivirtgo build -o terraform-provider-pivirtmkdir -p ~/.terraform.d/plugins/registry.terraform.io/pilab-cloud/pivirt/1.0.0/linux_amd64mv terraform-provider-pivirt ~/.terraform.d/plugins/registry.terraform.io/pilab-cloud/pivirt/1.0.0/linux_amd64/Provider Configuration
Section titled “Provider Configuration”Basic Configuration
Section titled “Basic Configuration”provider "pivirt" { endpoint = "https://agent.pilab.hu:8443" ca_file = "~/.config/pvcli/ca.crt" cert_file = "~/.config/pvcli/client.crt" key_file = "~/.config/pvcli/client.key"
# Optional settings namespace = "production" timeout = "30m"}Authentication
Section titled “Authentication”# Using environment variablesexport PIVIRT_ENDPOINT="https://agent.pilab.hu:8443"export PIVIRT_CA_FILE="~/.config/pvcli/ca.crt"export PIVIRT_CERT_FILE="~/.config/pvcli/client.crt"export PIVIRT_KEY_FILE="~/.config/pvcli/client.key"
# Or using tokenexport PIVIRT_TOKEN="your-jwt-token"Resources
Section titled “Resources”Virtual Machine
Section titled “Virtual Machine”resource "pivirt_virtual_machine" "web" { name = "web-01" namespace = "production"
cpu { cores = 2 model = "host-passthrough" }
memory { size = "4Gi" }
disk { name = "root" size = "20Gi" pool = "default" bus = "virtio" boot_order = 1 }
nic { name = "eth0" network = "virbr0" model = "virtio" }
os { type = "linux" boot_order = ["disk", "network"] }
cloud_init { user_data = file("${path.module}/cloud-init.yaml") }
labels = { app = "web" env = "production" }}Storage Volume
Section titled “Storage Volume”resource "pivirt_storage_volume" "data" { name = "data-01" pool = "default" size = "100Gi" format = "qcow2"
labels = { app = "database" }}Storage Snapshot
Section titled “Storage Snapshot”resource "pivirt_storage_snapshot" "backup" { volume_id = pivirt_storage_volume.data.id name = "backup-01"}Network
Section titled “Network”resource "pivirt_network" "vxlan" { 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"}Network Policy
Section titled “Network Policy”resource "pivirt_network_policy" "web_isolation" { name = "web-isolation" namespace = "production"
pod_selector { match_labels = { app = "web" } }
ingress { from { namespace_selector { match_labels = { name = "monitoring" } } }
ports { protocol = "TCP" port = 80 } }}Data Sources
Section titled “Data Sources”List VMs
Section titled “List VMs”data "pivirt_virtual_machines" "running" { namespace = "production"
filter { name = "status" values = ["running"] }}
output "running_vms" { value = data.pivirt_virtual_machines.running.vms}Get VM Details
Section titled “Get VM Details”data "pivirt_virtual_machine" "web" { name = "web-01" namespace = "production"}
output "web_vm_ip" { value = data.pivirt_virtual_machine.web.ip_address}List Storage Pools
Section titled “List Storage Pools”data "pivirt_storage_pools" "all" {}
output "storage_pools" { value = data.pivirt_storage_pools.all.pools}Complete Example
Section titled “Complete Example”Web Application Stack
Section titled “Web Application Stack”terraform { required_providers { pivirt = { source = "pilab-cloud/pivirt" version = "~> 1.0" } }}
provider "pivirt" { endpoint = var.pivirt_endpoint ca_file = var.pivirt_ca_file cert_file = var.pivirt_cert_file key_file = var.pivirt_key_file}
variable "pivirt_endpoint" { type = string default = "https://agent.pilab.hu:8443"}
variable "pivirt_ca_file" { type = string default = "~/.config/pvcli/ca.crt"}
variable "pivirt_cert_file" { type = string default = "~/.config/pvcli/client.crt"}
variable "pivirt_key_file" { type = string default = "~/.config/pvcli/client.key"}
# Networkresource "pivirt_network" "app_network" { name = "app-network" type = "bridge"
bridge { name = "app-br" interface = "eth1" }
cidr = "10.10.0.0/24"}
# Web serversresource "pivirt_virtual_machine" "web" { count = 3
name = "web-${count.index + 1}" namespace = "production"
cpu { cores = 2 }
memory { size = "4Gi" }
disk { name = "root" size = "20Gi" pool = "default" bus = "virtio" }
nic { name = "eth0" network = pivirt_network.app_network.name model = "virtio" }
cloud_init { user_data = templatefile("${path.module}/web-cloud-init.yaml", { hostname = "web-${count.index + 1}" }) }
labels = { app = "web" env = "production" }}
# Database serverresource "pivirt_virtual_machine" "db" { name = "db-01" namespace = "production"
cpu { cores = 4 }
memory { size = "8Gi" }
disk { name = "root" size = "20Gi" pool = "default" bus = "virtio" }
disk { name = "data" size = "100Gi" pool = "fast-pool" bus = "virtio" }
nic { name = "eth0" network = pivirt_network.app_network.name model = "virtio" }
cloud_init { user_data = file("${path.module}/db-cloud-init.yaml") }
labels = { app = "database" env = "production" }}
# Network policyresource "pivirt_network_policy" "web_to_db" { name = "web-to-db" namespace = "production"
pod_selector { match_labels = { app = "database" } }
ingress { from { pod_selector { match_labels = { app = "web" } } }
ports { protocol = "TCP" port = 5432 } }}
# Outputsoutput "web_ips" { value = pivirt_virtual_machine.web[*].ip_address}
output "db_ip" { value = pivirt_virtual_machine.db.ip_address}Cloud-Init Templates
Section titled “Cloud-Init Templates”#cloud-confighostname: ${hostname}fqdn: ${hostname}.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 ${hostname}</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
write_files: - path: /etc/postgresql/16/main/postgresql.conf content: | listen_addresses = '*' max_connections = 100
final_message: "Database server ready"Initialize
Section titled “Initialize”terraform initterraform planterraform applyDestroy
Section titled “Destroy”terraform destroyBest Practices
Section titled “Best Practices”1. Use Variables
Section titled “1. Use Variables”variable "vm_count" { type = number default = 3}
variable "vm_size" { type = object({ cpu = number memory = string disk = string }) default = { cpu = 2 memory = "4Gi" disk = "20Gi" }}2. Use Modules
Section titled “2. Use Modules”module "web_servers" { source = "./modules/web-server"
count = 3 namespace = "production" network = pivirt_network.app_network.name cloud_init = file("${path.module}/web-cloud-init.yaml")}3. Use State Management
Section titled “3. Use State Management”terraform { backend "s3" { bucket = "terraform-state" key = "pivirt/production/terraform.tfstate" region = "eu-central-1" }}