SiamCafe.net Blog
Technology

oVirt Virtualization Developer Experience DX สร้าง Self-Service VM Platform

ovirt virtualization developer experience dx
oVirt Virtualization Developer Experience DX | SiamCafe Blog
2026-05-17· อ. บอม — SiamCafe.net· 1,221 คำ

Developer Experience ?????????????????? oVirt ?????????????????????

Developer Experience (DX) ????????????????????? ????????????????????????????????????????????????????????? developers ??????????????????????????????????????? platform ???????????? tool ?????????????????? oVirt virtualization platform DX ???????????????????????????????????? developers ?????????????????????????????????, ?????????????????? ???????????????????????? VMs ??????????????????????????????????????????????????? ???????????????????????????????????????????????? operations team ????????????????????????

oVirt DX ??????????????????????????????????????? API-first approach ?????????????????????????????????????????? REST API ?????????, SDK ???????????????????????? (Python, Java, Ruby), Infrastructure as Code ????????? Ansible, Terraform ?????????????????? VMs, Self-service portal developers ??????????????? VMs ??????????????????????????? quota, CI/CD integration ??????????????? test environments ???????????????????????????, Documentation ??????????????? API docs, examples, tutorials

??????????????? DX ????????????????????????????????? oVirt API documentation ??????????????????, SDK ?????? bugs ???????????? outdated, ??????????????? self-service developers ?????????????????? ops ????????????????????????, ??????????????? IaC ???????????? click ???????????? UI, ??????????????? templates ???????????? configure VM ????????????????????????????????????

????????????????????? Development Environment

Setup oVirt development environment

# === oVirt Developer Environment Setup ===

# 1. Install oVirt Python SDK
pip install ovirt-engine-sdk-python

# 2. Install oVirt Ansible Collection
ansible-galaxy collection install ovirt.ovirt

# 3. Install Terraform oVirt Provider
cat > versions.tf << 'EOF'
terraform {
  required_providers {
    ovirt = {
      source  = "ovirt/ovirt"
      version = "~> 2.0"
    }
  }
}
EOF

# 4. CLI Tool Setup
cat > ovirt-cli-config.yaml << 'EOF'
ovirt:
  url: "https://ovirt-engine.example.com/ovirt-engine/api"
  username: "admin@internal"
  password_env: "OVIRT_PASSWORD"
  ca_file: "/etc/pki/ovirt-engine/ca.pem"
  insecure: false
EOF

# 5. Development VM Template
cat > dev-template.yaml << 'EOF'
vm_template:
  name: "dev-template-ubuntu2204"
  specs:
    cpu: 4
    memory_gb: 8
    disk_gb: 50
    os: "Ubuntu 22.04 LTS"
  cloud_init:
    packages:
      - docker.io
      - docker-compose
      - git
      - curl
      - vim
      - htop
    users:
      - name: developer
        groups: docker,sudo
        ssh_authorized_keys:
          - "ssh-rsa AAAA... developer@company.com"
    runcmd:
      - systemctl enable docker
      - systemctl start docker
EOF

# 6. Quick VM Creation Script
cat > create-dev-vm.sh << 'BASH'
#!/bin/bash
# Quick create development VM
VM_NAME=""

python3 -c "
import ovirtsdk4 as sdk
import ovirtsdk4.types as types
import os

connection = sdk.Connection(
    url='https://ovirt-engine.example.com/ovirt-engine/api',
    username='admin@internal',
    password=os.environ['OVIRT_PASSWORD'],
    ca_file='/etc/pki/ovirt-engine/ca.pem',
)

vms_service = connection.system_service().vms_service()
vm = vms_service.add(
    types.Vm(
        name='$VM_NAME',
        template=types.Template(name='dev-template-ubuntu2204'),
        cluster=types.Cluster(name='Default'),
    ),
)
print(f'VM created: {vm.name} (ID: {vm.id})')
connection.close()
"

echo "VM $VM_NAME created"
BASH

chmod +x create-dev-vm.sh
echo "Development environment ready"

oVirt REST API ????????? SDK

????????? oVirt API ?????????????????? automation

#!/usr/bin/env python3
# ovirt_api.py ??? oVirt REST API & SDK Examples
import json
import logging
from typing import Dict, List

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("ovirt")

class OVirtManager:
    """oVirt VM Management via SDK"""
    
    def __init__(self):
        self.vms = {}
    
    def list_vms(self):
        """List all VMs with status"""
        # Simulate SDK call
        return [
            {"name": "dev-john-001", "status": "up", "cpu": 4, "memory_gb": 8, "ip": "10.0.1.10"},
            {"name": "dev-jane-002", "status": "up", "cpu": 2, "memory_gb": 4, "ip": "10.0.1.11"},
            {"name": "test-ci-003", "status": "down", "cpu": 8, "memory_gb": 16, "ip": None},
            {"name": "staging-app", "status": "up", "cpu": 4, "memory_gb": 8, "ip": "10.0.1.20"},
        ]
    
    def create_vm(self, name, template, cpu=4, memory_gb=8):
        """Create VM from template"""
        vm = {
            "name": name,
            "template": template,
            "cpu": cpu,
            "memory_gb": memory_gb,
            "status": "creating",
            "cloud_init": True,
        }
        self.vms[name] = vm
        return vm
    
    def snapshot_vm(self, vm_name, snapshot_name):
        """Create VM snapshot"""
        return {
            "vm": vm_name,
            "snapshot": snapshot_name,
            "status": "ok",
            "size_gb": 2.5,
        }
    
    def clone_vm(self, source_vm, new_name):
        """Clone VM"""
        return {
            "source": source_vm,
            "clone": new_name,
            "status": "cloning",
        }
    
    def api_examples(self):
        """REST API curl examples"""
        return {
            "list_vms": {
                "method": "GET",
                "url": "/ovirt-engine/api/vms",
                "curl": 'curl -k -u admin@internal:pass https://engine/ovirt-engine/api/vms -H "Accept: application/json"',
            },
            "create_vm": {
                "method": "POST",
                "url": "/ovirt-engine/api/vms",
                "body": {
                    "name": "dev-vm-01",
                    "template": {"name": "dev-template"},
                    "cluster": {"name": "Default"},
                    "memory": 8589934592,
                },
            },
            "start_vm": {
                "method": "POST",
                "url": "/ovirt-engine/api/vms/{vm_id}/start",
                "curl": 'curl -k -X POST -u admin@internal:pass https://engine/ovirt-engine/api/vms/{id}/start -H "Content-Type: application/xml" -d ""',
            },
            "stop_vm": {
                "method": "POST",
                "url": "/ovirt-engine/api/vms/{vm_id}/stop",
            },
            "create_snapshot": {
                "method": "POST",
                "url": "/ovirt-engine/api/vms/{vm_id}/snapshots",
                "body": {"description": "Before deployment"},
            },
        }

manager = OVirtManager()

# List VMs
vms = manager.list_vms()
print("oVirt VMs:")
for vm in vms:
    status_icon = "UP" if vm["status"] == "up" else "DOWN"
    print(f"  [{status_icon}] {vm['name']}: {vm['cpu']}vCPU, {vm['memory_gb']}GB, IP={vm.get('ip', 'N/A')}")

# API examples
apis = manager.api_examples()
print("\nREST API Endpoints:")
for name, info in apis.items():
    print(f"  {info['method']} {info['url']}")

Infrastructure as Code ?????????????????? oVirt

?????????????????? oVirt ???????????? Ansible ????????? Terraform

# === Infrastructure as Code for oVirt ===

# 1. Ansible Playbook ??? Create Development VMs
cat > ansible/create-dev-env.yml << 'EOF'
---
- name: Create Development Environment
  hosts: localhost
  gather_facts: false
  vars:
    ovirt_url: "https://ovirt-engine.example.com/ovirt-engine/api"
    ovirt_username: "admin@internal"
    ovirt_password: "{{ lookup('env', 'OVIRT_PASSWORD') }}"
    ovirt_ca_file: "/etc/pki/ovirt-engine/ca.pem"
    
    dev_vms:
      - name: "dev-web-01"
        template: "ubuntu2204-template"
        cpu: 4
        memory: 8GiB
        disk: 50GiB
      - name: "dev-db-01"
        template: "ubuntu2204-template"
        cpu: 2
        memory: 4GiB
        disk: 100GiB
      - name: "dev-redis-01"
        template: "ubuntu2204-template"
        cpu: 2
        memory: 4GiB
        disk: 20GiB

  tasks:
    - name: Login to oVirt
      ovirt.ovirt.ovirt_auth:
        url: "{{ ovirt_url }}"
        username: "{{ ovirt_username }}"
        password: "{{ ovirt_password }}"
        ca_file: "{{ ovirt_ca_file }}"

    - name: Create VMs
      ovirt.ovirt.ovirt_vm:
        auth: "{{ ovirt_auth }}"
        name: "{{ item.name }}"
        template: "{{ item.template }}"
        cluster: "Default"
        memory: "{{ item.memory }}"
        cpu_cores: "{{ item.cpu }}"
        state: running
        cloud_init:
          host_name: "{{ item.name }}.dev.local"
          authorized_ssh_keys: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
      loop: "{{ dev_vms }}"

    - name: Wait for VMs to be ready
      ovirt.ovirt.ovirt_vm_info:
        auth: "{{ ovirt_auth }}"
        pattern: "name=dev-*"
      register: vm_info
      until: vm_info.ovirt_vms | selectattr('status', 'equalto', 'up') | list | length == dev_vms | length
      retries: 30
      delay: 10

    - name: Logout
      ovirt.ovirt.ovirt_auth:
        state: absent
        ovirt_auth: "{{ ovirt_auth }}"
EOF

# 2. Terraform ??? oVirt Provider
cat > terraform/main.tf << 'EOF'
provider "ovirt" {
  url      = "https://ovirt-engine.example.com/ovirt-engine/api"
  username = "admin@internal"
  password = var.ovirt_password
  tls_ca_files = ["/etc/pki/ovirt-engine/ca.pem"]
}

variable "ovirt_password" {
  sensitive = true
}

variable "dev_count" {
  default = 3
}

resource "ovirt_vm" "dev" {
  count       = var.dev_count
  name        = "dev-vm-"
  cluster_id  = data.ovirt_cluster.default.id
  template_id = data.ovirt_template.ubuntu.id

  cpu {
    cores   = 4
    sockets = 1
  }

  memory = 8 * 1024 * 1024 * 1024  # 8GB

  initialization {
    host_name     = "dev-vm-.dev.local"
    custom_script = file("cloud-init.yaml")
  }
}

data "ovirt_cluster" "default" {
  name = "Default"
}

data "ovirt_template" "ubuntu" {
  name = "ubuntu2204-template"
}

output "vm_ips" {
  value = ovirt_vm.dev[*].name
}
EOF

echo "IaC configured"

CI/CD Integration

????????? oVirt ????????? CI/CD pipeline

# === CI/CD with oVirt ===

# 1. GitHub Actions ??? Create Test Environment
cat > .github/workflows/test-env.yml << 'EOF'
name: Create Test Environment

on:
  pull_request:
    types: [opened, synchronize]

jobs:
  create-test-env:
    runs-on: self-hosted
    steps:
      - uses: actions/checkout@v4

      - name: Create Test VM
        env:
          OVIRT_PASSWORD: }
        run: |
          pip install ovirt-engine-sdk-python
          python3 scripts/create-test-vm.py \
            --name "test-pr-}" \
            --template "ubuntu2204-template" \
            --cpu 4 --memory 8

      - name: Wait for VM Ready
        run: |
          python3 scripts/wait-vm-ready.py \
            --name "test-pr-}" \
            --timeout 300

      - name: Deploy Application
        run: |
          VM_IP=$(python3 scripts/get-vm-ip.py --name "test-pr-}")
          ssh -o StrictHostKeyChecking=no developer@$VM_IP "
            cd /opt/app
            docker compose pull
            docker compose up -d
          "

      - name: Run Integration Tests
        run: |
          VM_IP=$(python3 scripts/get-vm-ip.py --name "test-pr-}")
          npm run test:integration -- --base-url http://$VM_IP:8080

      - name: Cleanup Test VM
        if: always()
        run: |
          python3 scripts/delete-vm.py \
            --name "test-pr-}"
EOF

# 2. Jenkins Pipeline
cat > Jenkinsfile << 'EOF'
pipeline {
    agent any
    
    environment {
        OVIRT_PASSWORD = credentials('ovirt-password')
    }
    
    stages {
        stage('Create Test VM') {
            steps {
                sh """
                    ansible-playbook ansible/create-test-env.yml \
                        -e "vm_name=test-" \
                        -e "ovirt_password="
                """
            }
        }
        
        stage('Deploy & Test') {
            steps {
                sh """
                    VM_IP=\$(python3 scripts/get-vm-ip.py --name test-)
                    ./deploy.sh \$VM_IP
                    ./run-tests.sh \$VM_IP
                """
            }
        }
    }
    
    post {
        always {
            sh """
                ansible-playbook ansible/destroy-test-env.yml \
                    -e "vm_name=test-"
            """
        }
    }
}
EOF

echo "CI/CD integration configured"

Self-Service Portal ?????????????????? Developers

??????????????? developer portal

#!/usr/bin/env python3
# self_service.py ??? Developer Self-Service Portal
import json
import logging
from typing import Dict, List

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("portal")

class DeveloperPortal:
    def __init__(self):
        self.quotas = {}
        self.vms = {}
    
    def set_quota(self, team, quota):
        self.quotas[team] = quota
    
    def check_quota(self, team, requested_cpu, requested_memory_gb):
        quota = self.quotas.get(team, {"max_cpu": 16, "max_memory_gb": 32, "max_vms": 5})
        current_usage = self.get_team_usage(team)
        
        return {
            "allowed": (
                current_usage["cpu"] + requested_cpu <= quota["max_cpu"] and
                current_usage["memory_gb"] + requested_memory_gb <= quota["max_memory_gb"] and
                current_usage["vm_count"] + 1 <= quota["max_vms"]
            ),
            "current": current_usage,
            "quota": quota,
            "requested": {"cpu": requested_cpu, "memory_gb": requested_memory_gb},
        }
    
    def get_team_usage(self, team):
        team_vms = [v for v in self.vms.values() if v.get("team") == team]
        return {
            "cpu": sum(v["cpu"] for v in team_vms),
            "memory_gb": sum(v["memory_gb"] for v in team_vms),
            "vm_count": len(team_vms),
        }
    
    def request_vm(self, user, team, specs):
        """Self-service VM request"""
        # Check quota
        quota_check = self.check_quota(team, specs["cpu"], specs["memory_gb"])
        if not quota_check["allowed"]:
            return {"status": "DENIED", "reason": "Quota exceeded", "quota": quota_check}
        
        # Auto-approve within quota
        vm_name = f"dev-{user}-{len(self.vms) + 1:03d}"
        self.vms[vm_name] = {
            "name": vm_name,
            "user": user,
            "team": team,
            "cpu": specs["cpu"],
            "memory_gb": specs["memory_gb"],
            "status": "provisioning",
            "auto_delete_hours": specs.get("ttl_hours", 72),
        }
        
        return {"status": "APPROVED", "vm": self.vms[vm_name]}
    
    def catalog(self):
        return {
            "templates": [
                {"name": "dev-small", "cpu": 2, "memory_gb": 4, "disk_gb": 30, "description": "Development (light)"},
                {"name": "dev-medium", "cpu": 4, "memory_gb": 8, "disk_gb": 50, "description": "Development (standard)"},
                {"name": "dev-large", "cpu": 8, "memory_gb": 16, "disk_gb": 100, "description": "Development (heavy)"},
                {"name": "test-ci", "cpu": 4, "memory_gb": 8, "disk_gb": 50, "description": "CI/CD test runner"},
                {"name": "staging", "cpu": 4, "memory_gb": 8, "disk_gb": 100, "description": "Staging environment"},
            ],
        }

portal = DeveloperPortal()
portal.set_quota("backend", {"max_cpu": 32, "max_memory_gb": 64, "max_vms": 10})

# Request VM
result = portal.request_vm("john", "backend", {"cpu": 4, "memory_gb": 8, "ttl_hours": 48})
print(f"VM Request: {result['status']}")
if result["status"] == "APPROVED":
    print(f"  VM: {result['vm']['name']}, TTL: {result['vm']['auto_delete_hours']}h")

# Show catalog
catalog = portal.catalog()
print("\nVM Catalog:")
for t in catalog["templates"]:
    print(f"  {t['name']}: {t['cpu']}vCPU, {t['memory_gb']}GB ??? {t['description']}")

FAQ ??????????????????????????????????????????

Q: oVirt SDK ???????????????????????????????????????????

A: oVirt ?????? official SDKs ?????????????????? Python (ovirt-engine-sdk-python) ???????????? SDK ???????????? maintained ????????????????????????, Java (ovirt-engine-sdk-java) ?????????????????? Java applications, Ruby (ovirt-engine-sdk-ruby) ?????????????????? Ruby/Rails ???????????????????????????????????? REST API ???????????????????????????????????????????????????????????????????????????????????????????????? HTTP requests ????????? (Go, Node.js, PHP) Python SDK ????????????????????????????????????????????????????????? documentation ?????? community ???????????? examples ????????? ?????????????????????????????? Ansible ???????????????

Q: oVirt ????????? OpenStack ??????????????????????????????????????????????????? private cloud?

A: oVirt ???????????? virtualization platform ???????????? VM management ????????????????????????????????????????????? OpenStack ????????? (Engine + Host) ????????????????????????????????? SMB ?????????????????????????????? VM management ?????????????????????????????? cloud features ????????? OpenStack ???????????? full cloud platform ?????? compute, storage, networking, identity management ?????????????????????????????????????????? ????????????????????????????????? 2-3 ???????????????????????? ????????????????????????????????? large enterprise ?????????????????????????????? IaaS ??????????????? oVirt ??????????????? ????????????????????? VM management ??????????????? ????????????????????? (1-2 ??????) ?????????????????????????????? multi-tenancy ????????????????????? ??????????????? OpenStack ??????????????? ????????????????????? full IaaS, multi-tenant, self-service portal ????????? ?????? dedicated team ????????????

Q: Developer self-service ???????????????????????????????

A: ?????????????????????????????????????????? controls ?????? Quota management ??????????????? resources ????????? team/user (CPU, memory, VMs, storage), RBAC ????????? oVirt roles ??????????????? permissions (UserRole ????????????????????????/?????????????????? VMs ???????????????????????????), Network isolation ????????? network ?????????????????? dev VMs ??????????????????????????????????????? production, Auto-expiry ???????????? TTL ?????????????????? VMs ?????????????????????????????????????????????????????????????????????, Audit logging log ????????? action ?????????????????? compliance, Template-only creation ????????????????????????????????? approved templates ???????????????????????? ????????????????????????????????????????????? VMs ?????????????????? secure

Q: Terraform oVirt Provider ????????????????

A: Terraform oVirt Provider (ovirt/ovirt) ??????????????????????????????????????????????????? basic VM management (create, start, stop, delete, snapshot) ?????????????????? resources ???????????? VMs, disks, NICs, templates ???????????????????????? ????????????????????????????????? oVirt features ????????????????????? (????????? advanced features ????????????????????? REST API), community-maintained ????????? update ????????????????????? official providers ?????????????????? production ???????????????????????? Ansible ovirt.ovirt collection ????????? (official maintained ????????? Red Hat, features ?????????????????????) ????????? Terraform ??????????????? ?????????????????? Terraform ???????????????????????? ????????????????????? state management, ????????? Ansible ??????????????? ????????????????????? features ????????? ?????? day-2 operations (configure VMs ???????????????????????????)

📖 บทความที่เกี่ยวข้อง

Ansible Collection Developer Experience DXอ่านบทความ → oVirt Virtualization Community Buildingอ่านบทความ → oVirt Virtualization DNS Managementอ่านบทความ → PagerDuty Incident Developer Experience DXอ่านบทความ → Go Fiber Developer Experience DXอ่านบทความ →

📚 ดูบทความทั้งหมด →