vm-create

SKILL.md

/vm-create Skill

Create virtual machines in OpenShift Virtualization using the vm_create tool from the openshift-virtualization MCP server.

Prerequisites

Required MCP Server: openshift-virtualization (OpenShift MCP Server)

Required MCP Tools:

  • vm_create (from openshift-virtualization) - Create VirtualMachine resources
  • resources_get (from openshift-virtualization) - Check VM existence and status
  • resources_list (from openshift-virtualization) - List StorageClasses
  • namespaces_list (from openshift-virtualization) - List available namespaces
  • events_list (from openshift-virtualization) - Diagnostic event gathering
  • vm_lifecycle (from openshift-virtualization) - VM restart for workarounds

Required Environment Variables:

  • KUBECONFIG - Path to Kubernetes configuration file with cluster access

Required Cluster Setup:

  • OpenShift cluster (>= 4.19)
  • OpenShift Virtualization operator installed
  • ServiceAccount with RBAC permissions to create VirtualMachine resources
  • Namespace with appropriate permissions

Prerequisite Verification

Before executing, verify MCP server availability:

  1. Check openshift-virtualization exists in .mcp.json β†’ If missing, report setup instructions
  2. Verify KUBECONFIG is set (check presence only, never expose value) β†’ If missing, report to user

Human Notification Protocol (when prerequisites fail):

❌ Cannot execute vm-create: MCP server 'openshift-virtualization' not available
πŸ“‹ Setup: Add to .mcp.json, set KUBECONFIG env var, restart Claude Code
πŸ”— Docs: https://github.com/openshift/openshift-mcp-server

⚠️ SECURITY: Never display actual KUBECONFIG path or credential values.

When to Use This Skill

Trigger this skill when:

  • User explicitly invokes /vm-create command
  • User requests creating a new virtual machine
  • Deploying VMs with specific OS (Fedora, Ubuntu, RHEL, CentOS, Debian)
  • Setting up VMs with custom sizing (small, medium, large)
  • Provisioning VMs with specific storage requirements

User phrases:

  • "Create a Fedora VM in namespace vms"
  • "Deploy a medium Ubuntu VM with 100Gi disk"
  • "Set up a RHEL VM called database-01"
  • "/vm-create" (explicit command)

Do NOT use when:

  • Start/stop existing VMs β†’ Use /vm-lifecycle-manager
  • List VMs β†’ Use /vm-inventory
  • Delete VMs β†’ Use /vm-delete

Workflow

Step 1: Gather VM Requirements

Determine missing parameters:

Required: VM Name (validate: lowercase, alphanumeric+hyphens, start letter, max 63 chars, unique), Namespace Optional (use defaults): OS (fedora), Size (medium), Storage (30Gi), Performance (u1), Autostart (false)

Gather cluster info:

  • Detect current namespace: kubectl config view --minify -o jsonpath='{..namespace}' || echo "default"
  • List namespaces: namespaces_list (from openshift-virtualization)
  • List StorageClasses: resources_list with apiVersion="storage.k8s.io/v1", kind="StorageClass"
  • Identify default SC: annotation storageclass.kubernetes.io/is-default-class="true"
  • Analyze SC: .volumeBindingMode (Immediate/WaitForFirstConsumer), provisioner (rbd/cephfs=RWX hint)

If parameters missing, use AskUserQuestion tool with questions for: VM Name (custom input with validation), Namespace (current + list), OS (fedora/ubuntu/rhel/centos-stream/debian/opensuse), Performance (u1/c1/m1/o1), Size (small/medium/large/xlarge), Storage (30Gi/50Gi/100Gi/custom), StorageClass (dynamic list with hints), Autostart (yes/no). See Example Usage for complete JSON structure.

Process responses - map labels to values:

  • OS: "Fedora"β†’"fedora", "Ubuntu"β†’"ubuntu", "RHEL"β†’"rhel", "CentOS Stream"β†’"centos-stream", "Debian"β†’"debian", "OpenSUSE"β†’"opensuse"
  • Performance: "General Purpose (u1)"β†’"u1", "Compute (c1)"β†’"c1", "Memory (m1)"β†’"m1", "Overcommitted (o1)"β†’"o1"
  • Size: "Small"β†’"small", "Medium"β†’"medium", "Large"β†’"large", "XLarge"β†’"xlarge"
  • Autostart: "No"β†’false, "Yes"β†’true

Step 2: Check VM Existence

MCP Tool: resources_get (from openshift-virtualization) Parameters: apiVersion="kubevirt.io/v1", kind="VirtualMachine", namespace=<namespace>, name=<vm-name>

If VM exists:

⚠️ VM `<name>` already exists in namespace `<namespace>`
Status: <status>
Options: 1) Different name, 2) Delete existing, 3) Cancel

STOP and wait for user decision.

If not exists: Proceed to Step 3.

Step 3: Present Configuration for Confirmation

Display configuration table:

## Virtual Machine Configuration

| Parameter | Value | Notes |
|-----------|-------|-------|
| VM Name | `<name>` | validated |
| Namespace | `<namespace>` | from user/context |
| OS | `<os>` | from selection |
| Performance | `<perf>` | default: u1 |
| Size | `<size>` | default: medium |
| Storage | `<storage>` | default: 30Gi |
| StorageClass | `<sc>` | default: cluster default |
| Autostart | `<yes/no>` | default: no |

This will create a VirtualMachine consuming cluster resources.
Confirm: yes/no/modify

WAIT for explicit user confirmation before proceeding.

Step 4: Create Virtual Machine

MCP Tool: vm_create (from openshift-virtualization)

Parameters:

  • namespace: <namespace> - REQUIRED
  • name: <vm-name> - REQUIRED
  • workload: <os> - OPTIONAL (default: fedora)
  • size: <size> - OPTIONAL (small/medium/large/xlarge)
  • storage: <storage> - OPTIONAL (default: 30Gi)
  • performance: <perf> - OPTIONAL (u1/c1/m1/o1)
  • autostart: <bool> - OPTIONAL (default: false)

Example: vm_create({"namespace": "vms", "name": "web-server", "workload": "fedora", "size": "medium", "storage": "50Gi", "autostart": false})

Error Handling:

  • Namespace not found β†’ Report, list available
  • RBAC denied β†’ Report permissions error
  • Storage fails β†’ Check StorageClass exists
  • Scheduling fails β†’ See Step 5

Step 5: Verify Status and Diagnose Issues

Wait 5-10 seconds, then check status:

MCP Tool: resources_get (apiVersion="kubevirt.io/v1", kind="VirtualMachine", name=<name>, namespace=<namespace>) Extract: .status.printableStatus

Status interpretation:

  • Stopped/Halted β†’ Success (VM created, not started)
  • Running β†’ Success (if autostart=true)
  • Provisioning β†’ Wait 5s, check again
  • ErrorUnschedulable β†’ Execute diagnostic workflow (Step 5a)
  • ErrorDataVolumeNotReady β†’ Storage issue (see Common Issues)

5a. Diagnostic Workflow (ErrorUnschedulable)

CRITICAL: Document Consultation FIRST:

  1. Read scheduling-errors.md using Read tool
  2. Output: "I detected ErrorUnschedulable. I consulted [scheduling-errors.md] to understand diagnosis strategies."

Gather diagnostics:

  • List events: events_list (namespace=<namespace>) β†’ Filter for VM/VMI
  • Get VM: resources_get β†’ Check .status.conditions
  • List nodes: resources_list (apiVersion="v1", kind="Node") β†’ Extract .spec.taints

Parse root cause:

  • "taints" in events β†’ Taints/tolerations issue
  • "Insufficient cpu/memory" β†’ Resource constraints
  • "no nodes available" β†’ No suitable nodes

Present diagnosis:

## ⚠️ VM Scheduling Issue Detected

**Status**: ErrorUnschedulable | **Root Cause**: <identified-cause> | **Details**: <specifics>

### Recommended Solution
<workaround-description>
**Command**: `oc patch vm <name> -n <namespace> ...`
**Impact**: <what-changes>
**Options**: 1) Apply workaround, 2) Manual, 3) Cancel, 4) Ignore
⚠️ MCP limitation: vm_create doesn't support tolerations

Wait for user decision.

If user confirms:

  1. Apply patch: resources_create_or_update (fetch, add tolerations, update) OR oc patch
  2. Verify: resources_get β†’ Check .spec.template.spec.tolerations
  3. Restart VM: vm_lifecycle (action="restart") to apply new spec
  4. Wait 15-20s, check status β†’ Stopped β†’ Provisioning β†’ Running

Report: ## βœ“ Workaround Applied | **Action**: Added tolerations, restarted | **Status**: <current>

Step 6: Report Creation Status

On success:

## βœ“ Virtual Machine Created Successfully

**VM**: `<name>` (namespace: `<namespace>`)
**OS**: <os> | **Size**: <size> (<perf>) | **Storage**: <storage> | **Status**: <status>
**Provisioning**: ~2-5 min (Provisioning β†’ Stopped)

### Next Steps
Start: "Start VM <name>" | View: "Show VM <name>"

### Accessing the VM
1. Serial: `virtctl console <name> -n <ns>`
2. VNC: OpenShift Console β†’ Virtualization β†’ VMs β†’ <name> β†’ Console
3. SSH: Get IP from VMI, `ssh <user>@<ip>`
4. Port Forward: `virtctl port-forward vmi/<name> -n <ns> 8080:80`

### Default Credentials
- Fedora: fedora | Ubuntu: ubuntu | RHEL: cloud-user | CentOS: centos | Debian: debian
- All require SSH key or console password set: `virtctl console <name>`, `sudo passwd <user>`

On failure:

## ❌ Failed to Create Virtual Machine

**Error**: <error-message>

**Common Causes**:
- Namespace not exists β†’ `oc create namespace <name>`
- RBAC denied β†’ Check ServiceAccount permissions
- Resource constraints β†’ Try smaller size
- Invalid parameters β†’ Verify OS, size, storage format
- Operator not installed β†’ Verify CSVs

Troubleshooting: See Common Issues

Common Issues

Issue 1: Namespace Not Found

Error: "Namespace 'xyz' not found" Solution: List with namespaces_list, create with resources_create_or_update or oc create namespace <name>

Issue 2: Insufficient Permissions

Error: "Forbidden: User cannot create VirtualMachines" Solution: Verify KUBECONFIG RBAC, requires create VirtualMachine permissions, contact admin

Issue 3: Resource Constraints (ErrorUnschedulable)

Error: "0/N nodes: Insufficient cpu/memory" Solution: Check nodes_top, try smaller size (medium→small, o1 overcommitted), scale cluster

Issue 4: Node Taints (ErrorUnschedulable)

Error: "0/N nodes: taints pod didn't tolerate" Solution: Apply tolerations workaround (Step 5a), restart VM

Issue 5: Storage Provisioning (ErrorDataVolumeNotReady)

Error: "PVC pending" or "StorageClass not found" Solution: Verify SC (resources_list), check default annotation, verify provisioner, check quotas

Issue 6: DataVolume Import Failure

Error: "DataVolume import failed" or "image pull error" Solution: Verify internet access, check DV status, ensure valid OS, verify registry auth

Issue 7: Operator Not Installed

Error: "VirtualMachine CRD not found" Solution: Verify operator: resources_list (apiVersion="operators.coreos.com/v1alpha1", kind="CSV", namespace="openshift-cnv")

Dependencies

Required MCP Servers

Required MCP Tools

  • vm_create - Create VMs (namespace, name, workload, size, storage, performance, autostart)
  • resources_get - Get resources (apiVersion, kind, namespace, name)
  • resources_list - List resources (apiVersion, kind, namespace optional)
  • namespaces_list - List namespaces
  • events_list - List events (namespace)
  • vm_lifecycle - VM lifecycle (namespace, name, action: start/stop/restart)
  • resources_create_or_update - Update resources (JSON)

Related Skills

  • vm-lifecycle-manager - Start VMs | vm-inventory - List VMs | vm-delete - Delete VMs | vm-clone - Clone VMs | vm-snapshot-create - Snapshot VMs

Reference Documentation

Critical: Human-in-the-Loop Requirements

IMPORTANT: This skill creates cluster resources consuming CPU, memory, storage. You MUST:

  1. Before Creating

    • Display complete configuration in table format
    • Show resource impact
    • Ask: "Confirm: yes/no/modify"
    • Wait for explicit confirmation
  2. Never Auto-Execute

    • NEVER create VMs without displaying configuration
    • NEVER assume approval
    • NEVER create multiple VMs without individual confirmations

Why: Resource consumption, cost impact, namespace quotas

Rationale: Prevents unintended resource consumption; maintains user control.

Security Considerations

  • RBAC: Requires create VirtualMachines (kubevirt.io/v1) in namespace
  • Namespace Isolation: VMs in specified namespace only
  • Storage Quotas: Respects ResourceQuotas
  • Image Security: Uses official images from trusted registries
  • KUBECONFIG: Never exposed (presence only)
  • Audit: All ops logged via K8s audit

Example Usage

Example 1: Complete Interactive Workflow

User: "Create a VM"
Agent: [No params, detects namespace: production, queries SCs]
       [AskUserQuestion with all 8 questions - see JSON below]
[User selects: my-app-server, production, fedora, u1, medium, 30Gi, default SC, no]
Agent: [Validates βœ“, checks existence βœ“, shows configuration table]
User: "yes"
Agent: [vm_create(...)]
## βœ“ Virtual Machine Created Successfully
[Details, next steps, access instructions]

AskUserQuestion JSON (8 questions: VM Name, Namespace, OS, Performance, Size, Storage, StorageClass, Autostart):

{"questions": [
  {"question": "VM name?", "header": "VM Name", "multiSelect": false, "options": [{"label": "Enter custom name", "description": "Lowercase, alphanumeric+hyphens, start letter, max 63"}]},
  {"question": "Namespace?", "header": "Namespace", "multiSelect": false, "options": [{"label": "<current> (Current)", "description": "From kubeconfig"}, {"label": "Other", "description": "<list>"}]},
  {"question": "OS?", "header": "OS", "multiSelect": false, "options": [{"label": "Fedora (Recommended)", "description": "General purpose"}, {"label": "Ubuntu", "description": "Web services"}, {"label": "RHEL", "description": "Enterprise"}, {"label": "CentOS Stream", "description": "Upstream RHEL"}, {"label": "Debian", "description": "Stable minimal"}, {"label": "OpenSUSE", "description": "Community"}]},
  {"question": "Performance?", "header": "Performance", "multiSelect": false, "options": [{"label": "General (u1) (Recommended)", "description": "Balanced - most workloads"}, {"label": "Compute (c1)", "description": "CPU-intensive"}, {"label": "Memory (m1)", "description": "Memory-intensive"}, {"label": "Overcommitted (o1)", "description": "Dev/test"}]},
  {"question": "Size?", "header": "Size", "multiSelect": false, "options": [{"label": "Small", "description": "1 vCPU, 2Gi"}, {"label": "Medium (Recommended)", "description": "2-4 vCPU, 4-8Gi"}, {"label": "Large", "description": "4-8 vCPU, 8-16Gi"}, {"label": "XLarge", "description": "8+ vCPU, 16+ Gi"}]},
  {"question": "Storage?", "header": "Storage", "multiSelect": false, "options": [{"label": "30Gi (Recommended)", "description": "Most workloads"}, {"label": "50Gi", "description": "Moderate needs"}, {"label": "100Gi", "description": "Large requirements"}, {"label": "Custom", "description": "Specify (e.g., 75Gi)"}]},
  {"question": "StorageClass?", "header": "SC", "multiSelect": false, "options": [{"label": "<default> (Default)", "description": "<perf-hint>, <migration-hint>"}, {"label": "<sc-1>", "description": "<hints>"}]},
  {"question": "Autostart?", "header": "Autostart", "multiSelect": false, "options": [{"label": "No (Recommended)", "description": "Start manually"}, {"label": "Yes", "description": "Auto-start"}]}
]}

Example 2: Partial Parameters

User: "Create Ubuntu VM web-01 in apps"
Agent: [Detects: web-01, apps, ubuntu; Asks: Performance, Size, Storage, SC, Autostart]
[User: u1, large, 100Gi, local-storage, yes]
Agent: [Validates, shows config]
User: "yes"
Agent: [Creates with autostart=true]
## βœ“ Virtual Machine Created and Starting

Example 3: User Modifies Config

User: "Deploy memory-optimized RHEL VM db-server in production"
Agent: [Detects: db-server, production, rhel, m1; Asks: Size, Storage, SC, Autostart]
[User: large, 100Gi, ceph-rbd, no]
Agent: [Shows config]
User: "Actually, compute-optimized and autostart"
Agent: [Updates: c1, yes; Shows updated]
User: "yes"
Agent: [Creates]

Advanced Features

Custom Images: vm_create({"workload": "quay.io/containerdisks/fedora:latest", ...}) Secondary Networks: vm_create({"networks": ["vlan-network"], ...}) or {"networks": [{"name": "eth1", "networkName": "vlan"}], ...} Explicit Instance Type: vm_create({"instancetype": "u1.large", ...})

Weekly Installs
1
GitHub Stars
4
First Seen
4 days ago
Installed on
claude-code1