Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,6 @@ python/build/
python/dist/
python/kubernetes_mcp_server.egg-info/
!python/kubernetes-mcp-server

.gevals-step*
gevals-kubevirt-vm-operations-out.json
1 change: 1 addition & 0 deletions internal/tools/update-readme/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
_ "github.com/containers/kubernetes-mcp-server/pkg/toolsets/config"
_ "github.com/containers/kubernetes-mcp-server/pkg/toolsets/core"
_ "github.com/containers/kubernetes-mcp-server/pkg/toolsets/helm"
_ "github.com/containers/kubernetes-mcp-server/pkg/toolsets/kubevirt"
)

type OpenShift struct{}
Expand Down
2 changes: 1 addition & 1 deletion pkg/kubernetes-mcp-server/cmd/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ func TestToolsets(t *testing.T) {
rootCmd := NewMCPServer(ioStreams)
rootCmd.SetArgs([]string{"--help"})
o, err := captureOutput(rootCmd.Execute) // --help doesn't use logger/klog, cobra prints directly to stdout
if !strings.Contains(o, "Comma-separated list of MCP toolsets to use (available toolsets: config, core, helm).") {
if !strings.Contains(o, "Comma-separated list of MCP toolsets to use (available toolsets: config, core, helm, kubevirt).") {
t.Fatalf("Expected all available toolsets, got %s %v", o, err)
}
})
Expand Down
9 changes: 9 additions & 0 deletions pkg/kubernetes/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package kubernetes

import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/rest"

"github.com/containers/kubernetes-mcp-server/pkg/helm"
"k8s.io/client-go/kubernetes/scheme"
Expand Down Expand Up @@ -30,6 +31,14 @@ func (k *Kubernetes) AccessControlClientset() *AccessControlClientset {
return k.manager.accessControlClientSet
}

// RESTConfig returns the Kubernetes REST configuration
func (k *Kubernetes) RESTConfig() *rest.Config {
if k.manager == nil {
return nil
}
return k.manager.cfg
}

var Scheme = scheme.Scheme
var ParameterCodec = runtime.NewParameterCodec(Scheme)

Expand Down
1 change: 1 addition & 0 deletions pkg/mcp/modules.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ package mcp
import _ "github.com/containers/kubernetes-mcp-server/pkg/toolsets/config"
import _ "github.com/containers/kubernetes-mcp-server/pkg/toolsets/core"
import _ "github.com/containers/kubernetes-mcp-server/pkg/toolsets/helm"
import _ "github.com/containers/kubernetes-mcp-server/pkg/toolsets/kubevirt"
34 changes: 34 additions & 0 deletions pkg/toolsets/kubevirt/toolset.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package kubevirt

import (
"slices"

"github.com/containers/kubernetes-mcp-server/pkg/api"
internalk8s "github.com/containers/kubernetes-mcp-server/pkg/kubernetes"
"github.com/containers/kubernetes-mcp-server/pkg/toolsets"
vm_create "github.com/containers/kubernetes-mcp-server/pkg/toolsets/kubevirt/vm/create"
vm_troubleshoot "github.com/containers/kubernetes-mcp-server/pkg/toolsets/kubevirt/vm/troubleshoot"
)

type Toolset struct{}

var _ api.Toolset = (*Toolset)(nil)

func (t *Toolset) GetName() string {
return "kubevirt"
}

func (t *Toolset) GetDescription() string {
return "KubeVirt virtual machine management tools"
}

func (t *Toolset) GetTools(o internalk8s.Openshift) []api.ServerTool {
return slices.Concat(
vm_create.Tools(),
vm_troubleshoot.Tools(),
)
}

func init() {
toolsets.Register(&Toolset{})
}
115 changes: 115 additions & 0 deletions pkg/toolsets/kubevirt/vm/create/plan.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# VirtualMachine Creation Plan

## ⚠️ IMPORTANT: Deprecated Field Warning

**DO NOT use the `running` field** - it is deprecated in KubeVirt. Always use `runStrategy` instead.

❌ **INCORRECT** (deprecated):
```yaml
spec:
running: true # DO NOT USE - deprecated field
```

✅ **CORRECT**:
```yaml
spec:
runStrategy: Always # Use runStrategy instead
```

## VirtualMachine YAML

Use the `resources_create_or_update` tool with the following YAML:

```yaml
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: {{.Name}}
namespace: {{.Namespace}}
spec:
runStrategy: Halted
{{- if .Instancetype}}
instancetype:
name: {{.Instancetype}}
kind: VirtualMachineClusterInstancetype
{{- end}}
{{- if .Preference}}
preference:
name: {{.Preference}}
kind: VirtualMachineClusterPreference
{{- end}}
{{- if .UseDataSource}}
dataVolumeTemplates:
- metadata:
name: {{.Name}}-rootdisk
spec:
sourceRef:
kind: DataSource
name: {{.DataSourceName}}
namespace: {{.DataSourceNamespace}}
storage:
resources:
requests:
storage: 30Gi
{{- end}}
template:
spec:
domain:
devices:
disks:
- name: {{.Name}}-rootdisk
{{- if not .Instancetype}}
memory:
guest: 2Gi
{{- end}}
volumes:
- name: {{.Name}}-rootdisk
{{- if .UseDataSource}}
dataVolume:
name: {{.Name}}-rootdisk
{{- else}}
containerDisk:
image: {{.ContainerDisk}}
{{- end}}
```

## Run Strategy Options

The VM is created with `runStrategy: Halted` (stopped state). You can modify the `runStrategy` field to control the VM's execution:

- **`Halted`** - VM is stopped and will not run
- **`Always`** - VM should always be running (restarts automatically)
- **`RerunOnFailure`** - Restart the VM only if it fails
- **`Manual`** - Manual start/stop control via `virtctl start/stop`
- **`Once`** - Run the VM once, then stop when it terminates

To start the VM after creation, change `runStrategy: Halted` to `runStrategy: Always` or use the Manual strategy and start it with virtctl.

## Verification

After creating the VirtualMachine, verify it was created successfully:

Use the `resources_get` tool:
- **apiVersion**: `kubevirt.io/v1`
- **kind**: `VirtualMachine`
- **namespace**: `{{.Namespace}}`
- **name**: `{{.Name}}`

Check the resource details for any warnings or errors in the status conditions.

## Troubleshooting

If the VirtualMachine fails to create or start:

1. **Check the VM resource details and events**:
- Use `resources_get` tool with apiVersion `kubevirt.io/v1`, kind `VirtualMachine`, namespace `{{.Namespace}}`, name `{{.Name}}`
- Look for error messages in the status conditions

2. **Verify instance type exists** (if specified):
- Use `resources_get` tool with apiVersion `instancetype.kubevirt.io/v1beta1`, kind `VirtualMachineClusterInstancetype`, name `{{.Instancetype}}`

3. **Verify preference exists** (if specified):
- Use `resources_get` tool with apiVersion `instancetype.kubevirt.io/v1beta1`, kind `VirtualMachineClusterPreference`, name `{{.Preference}}`

4. **Check KubeVirt installation**:
- Use `pods_list` tool with namespace `kubevirt`
Loading