vm-create
/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 resourcesresources_get(from openshift-virtualization) - Check VM existence and statusresources_list(from openshift-virtualization) - List StorageClassesnamespaces_list(from openshift-virtualization) - List available namespacesevents_list(from openshift-virtualization) - Diagnostic event gatheringvm_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:
- Check
openshift-virtualizationexists in.mcp.jsonβ If missing, report setup instructions - Verify
KUBECONFIGis 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-createcommand - 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_listwith 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>- REQUIREDname:<vm-name>- REQUIREDworkload:<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:
- Read scheduling-errors.md using Read tool
- 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:
- Apply patch:
resources_create_or_update(fetch, add tolerations, update) ORoc patch - Verify:
resources_getβ Check.spec.template.spec.tolerations - Restart VM:
vm_lifecycle(action="restart") to apply new spec - 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
openshift-virtualization- OpenShift MCP server with KubeVirt toolset (https://github.com/openshift/openshift-mcp-server)
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 namespacesevents_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
- scheduling-errors.md - ErrorUnschedulable (consulted Step 5a)
- storage-errors.md - ErrorDataVolumeNotReady
- network-errors.md - Network failures
- runtime-errors.md - CrashLoopBackOff
- Troubleshooting INDEX - Full error index
- OpenShift Virt Docs
- KubeVirt API
- OpenShift MCP
Critical: Human-in-the-Loop Requirements
IMPORTANT: This skill creates cluster resources consuming CPU, memory, storage. You MUST:
-
Before Creating
- Display complete configuration in table format
- Show resource impact
- Ask: "Confirm: yes/no/modify"
- Wait for explicit confirmation
-
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", ...})