...
This commit is contained in:
19
pkg2/heroscript/cmd/vmhandler/.gitignore
vendored
Normal file
19
pkg2/heroscript/cmd/vmhandler/.gitignore
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
vmhandler
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
|
||||
# Go workspace file
|
||||
go.work
|
134
pkg2/heroscript/cmd/vmhandler/README.md
Normal file
134
pkg2/heroscript/cmd/vmhandler/README.md
Normal file
@@ -0,0 +1,134 @@
|
||||
# VM Handler Example
|
||||
|
||||
This example demonstrates how to use the HandlerFactory with a VM handler to process heroscript commands.
|
||||
|
||||
## Overview
|
||||
|
||||
The VM handler example shows how to:
|
||||
|
||||
1. Create a handler that processes VM-related actions
|
||||
2. Register the handler with the HandlerFactory
|
||||
3. Start a telnet server that uses the HandlerFactory to process commands
|
||||
4. Connect to the telnet server and send heroscript commands
|
||||
|
||||
## Running the Example
|
||||
|
||||
To run the example:
|
||||
|
||||
```bash
|
||||
cd ~/code/github/freeflowuniverse/herocode/heroagent/pkg/handlerfactory/cmd/vmhandler
|
||||
go run . tutorial
|
||||
#to run just the server do
|
||||
go run .
|
||||
#you can then go to other terminal and play with telnet / nc
|
||||
```
|
||||
|
||||
This will start a telnet server on:
|
||||
- Unix socket: `/tmp/vmhandler.sock`
|
||||
- TCP: `localhost:8024`
|
||||
|
||||
## Connecting to the Server
|
||||
|
||||
### Using Unix Socket
|
||||
|
||||
```bash
|
||||
nc -U /tmp/vmhandler.sock
|
||||
```
|
||||
|
||||
### Using TCP
|
||||
|
||||
```bash
|
||||
telnet localhost 8024
|
||||
```
|
||||
|
||||
## Authentication
|
||||
|
||||
When you connect, you'll need to authenticate with the secret:
|
||||
|
||||
```
|
||||
!!auth secret:1234
|
||||
```
|
||||
|
||||
## Available Commands
|
||||
|
||||
Once authenticated, you can use the following commands:
|
||||
|
||||
```
|
||||
!!vm.define name:'test_vm' cpu:4 memory:'8GB' storage:'100GB'
|
||||
!!vm.start name:'test_vm'
|
||||
!!vm.stop name:'test_vm'
|
||||
!!vm.disk_add name:'test_vm' size:'50GB' type:'SSD'
|
||||
!!vm.list
|
||||
!!vm.status name:'test_vm'
|
||||
!!vm.delete name:'test_vm' force:true
|
||||
```
|
||||
|
||||
## Example Session
|
||||
|
||||
Here's an example session:
|
||||
|
||||
```
|
||||
$ telnet localhost 8024
|
||||
Connected to localhost.
|
||||
Escape character is '^]'.
|
||||
** Welcome: you are not authenticated, provide secret.
|
||||
!!auth secret:1234
|
||||
|
||||
** Welcome: you are authenticated.
|
||||
!!vm.define name:'test_vm' cpu:4 memory:'8GB' storage:'100GB'
|
||||
VM 'test_vm' defined successfully with 4 CPU, 8GB memory, and 100GB storage
|
||||
|
||||
!!vm.start name:'test_vm'
|
||||
VM 'test_vm' started successfully
|
||||
|
||||
!!vm.disk_add name:'test_vm' size:'50GB' type:'SSD'
|
||||
Added 50GB SSD disk to VM 'test_vm'
|
||||
|
||||
!!vm.status name:'test_vm'
|
||||
VM 'test_vm' status:
|
||||
- Status: running
|
||||
- CPU: 4
|
||||
- Memory: 8GB
|
||||
- Storage: 100GB
|
||||
- Attached disks:
|
||||
1. 50GB SSD
|
||||
|
||||
!!vm.list
|
||||
Defined VMs:
|
||||
- test_vm (running): 4 CPU, 8GB memory, 100GB storage
|
||||
Attached disks:
|
||||
1. 50GB SSD
|
||||
|
||||
!!vm.stop name:'test_vm'
|
||||
VM 'test_vm' stopped successfully
|
||||
|
||||
!!vm.delete name:'test_vm'
|
||||
VM 'test_vm' deleted successfully
|
||||
|
||||
!!quit
|
||||
Goodbye!
|
||||
Connection closed by foreign host.
|
||||
```
|
||||
|
||||
## Other Commands
|
||||
|
||||
- `!!help`, `h`, or `?` - Show help
|
||||
- `!!interactive` or `!!i` - Toggle interactive mode (with colors)
|
||||
- `!!quit`, `!!exit`, or `q` - Disconnect from server
|
||||
|
||||
## How It Works
|
||||
|
||||
1. The `main.go` file creates a HandlerFactory and registers the VM handler
|
||||
2. It starts a telnet server that uses the HandlerFactory to process commands
|
||||
3. When a client connects and sends a heroscript command, the server:
|
||||
- Parses the command to determine the actor and action
|
||||
- Calls the appropriate method on the VM handler
|
||||
- Returns the result to the client
|
||||
|
||||
## Extending the Example
|
||||
|
||||
You can extend this example by:
|
||||
|
||||
1. Adding more methods to the VM handler
|
||||
2. Creating new handlers for different actors
|
||||
3. Registering multiple handlers with the HandlerFactory
|
276
pkg2/heroscript/cmd/vmhandler/tutorial.go
Normal file
276
pkg2/heroscript/cmd/vmhandler/tutorial.go
Normal file
@@ -0,0 +1,276 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/handlerfactory"
|
||||
)
|
||||
|
||||
// runTutorial runs an interactive tutorial demonstrating the VM handler
|
||||
func runTutorial() {
|
||||
fmt.Println("=== VM Handler Tutorial ===")
|
||||
fmt.Println("This tutorial will demonstrate how to use the VM handler with heroscript commands.")
|
||||
fmt.Println("Press Enter to continue through each step...")
|
||||
waitForEnter()
|
||||
|
||||
// Create a new handler factory
|
||||
fmt.Println("\nStep 1: Create a new HandlerFactory")
|
||||
fmt.Println("factory := handlerfactory.NewHandlerFactory()")
|
||||
factory := handlerfactory.NewHandlerFactory()
|
||||
waitForEnter()
|
||||
|
||||
// Create a VM handler
|
||||
fmt.Println("\nStep 2: Create a VM handler")
|
||||
fmt.Println("vmHandler := NewVMHandler()")
|
||||
vmHandler := NewVMHandler()
|
||||
waitForEnter()
|
||||
|
||||
// Register the VM handler with the factory
|
||||
fmt.Println("\nStep 3: Register the VM handler with the factory")
|
||||
fmt.Println("factory.RegisterHandler(vmHandler)")
|
||||
err := factory.RegisterHandler(vmHandler)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("Handler registered successfully!")
|
||||
waitForEnter()
|
||||
|
||||
// Show available actions
|
||||
fmt.Println("\nStep 4: List available actions for the VM handler")
|
||||
actions := factory.GetSupportedActions()
|
||||
fmt.Println("Supported actions for 'vm' actor:")
|
||||
for _, action := range actions["vm"] {
|
||||
fmt.Printf("- %s\n", action)
|
||||
}
|
||||
waitForEnter()
|
||||
|
||||
// Process heroscript commands
|
||||
fmt.Println("\nStep 5: Process heroscript commands")
|
||||
|
||||
// Define a VM
|
||||
defineScript := `!!vm.define name:'tutorial_vm' cpu:2 memory:'4GB' storage:'50GB'
|
||||
description: 'A tutorial VM for demonstration purposes'`
|
||||
fmt.Println("\nCommand:")
|
||||
fmt.Println(defineScript)
|
||||
fmt.Println("\nProcessing...")
|
||||
time.Sleep(1 * time.Second)
|
||||
result, err := factory.ProcessHeroscript(defineScript)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
} else {
|
||||
fmt.Printf("Result: %s\n", result)
|
||||
}
|
||||
waitForEnter()
|
||||
|
||||
// Start the VM
|
||||
startScript := `!!vm.start name:'tutorial_vm'`
|
||||
fmt.Println("\nCommand:")
|
||||
fmt.Println(startScript)
|
||||
fmt.Println("\nProcessing...")
|
||||
time.Sleep(1 * time.Second)
|
||||
result, err = factory.ProcessHeroscript(startScript)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
} else {
|
||||
fmt.Printf("Result: %s\n", result)
|
||||
}
|
||||
waitForEnter()
|
||||
|
||||
// Add a disk
|
||||
diskAddScript := `!!vm.disk_add name:'tutorial_vm' size:'20GB' type:'SSD'`
|
||||
fmt.Println("\nCommand:")
|
||||
fmt.Println(diskAddScript)
|
||||
fmt.Println("\nProcessing...")
|
||||
time.Sleep(1 * time.Second)
|
||||
result, err = factory.ProcessHeroscript(diskAddScript)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
} else {
|
||||
fmt.Printf("Result: %s\n", result)
|
||||
}
|
||||
waitForEnter()
|
||||
|
||||
// Check VM status
|
||||
statusScript := `!!vm.status name:'tutorial_vm'`
|
||||
fmt.Println("\nCommand:")
|
||||
fmt.Println(statusScript)
|
||||
fmt.Println("\nProcessing...")
|
||||
time.Sleep(1 * time.Second)
|
||||
result, err = factory.ProcessHeroscript(statusScript)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
} else {
|
||||
fmt.Printf("Result: %s\n", result)
|
||||
}
|
||||
waitForEnter()
|
||||
|
||||
// List all VMs
|
||||
listScript := `!!vm.list`
|
||||
fmt.Println("\nCommand:")
|
||||
fmt.Println(listScript)
|
||||
fmt.Println("\nProcessing...")
|
||||
time.Sleep(1 * time.Second)
|
||||
result, err = factory.ProcessHeroscript(listScript)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
} else {
|
||||
fmt.Printf("Result: %s\n", result)
|
||||
}
|
||||
waitForEnter()
|
||||
|
||||
// Stop the VM
|
||||
stopScript := `!!vm.stop name:'tutorial_vm'`
|
||||
fmt.Println("\nCommand:")
|
||||
fmt.Println(stopScript)
|
||||
fmt.Println("\nProcessing...")
|
||||
time.Sleep(1 * time.Second)
|
||||
result, err = factory.ProcessHeroscript(stopScript)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
} else {
|
||||
fmt.Printf("Result: %s\n", result)
|
||||
}
|
||||
waitForEnter()
|
||||
|
||||
// Delete the VM
|
||||
deleteScript := `!!vm.delete name:'tutorial_vm'`
|
||||
fmt.Println("\nCommand:")
|
||||
fmt.Println(deleteScript)
|
||||
fmt.Println("\nProcessing...")
|
||||
time.Sleep(1 * time.Second)
|
||||
result, err = factory.ProcessHeroscript(deleteScript)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
} else {
|
||||
fmt.Printf("Result: %s\n", result)
|
||||
}
|
||||
waitForEnter()
|
||||
|
||||
// Try an invalid command
|
||||
invalidScript := `!!vm.invalid name:'tutorial_vm'`
|
||||
fmt.Println("\nInvalid Command:")
|
||||
fmt.Println(invalidScript)
|
||||
fmt.Println("\nProcessing...")
|
||||
time.Sleep(1 * time.Second)
|
||||
result, err = factory.ProcessHeroscript(invalidScript)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
} else {
|
||||
fmt.Printf("Result: %s\n", result)
|
||||
}
|
||||
waitForEnter()
|
||||
|
||||
// Conclusion
|
||||
fmt.Println("\nTutorial Complete!")
|
||||
fmt.Println("You've seen how to:")
|
||||
fmt.Println("1. Create a HandlerFactory")
|
||||
fmt.Println("2. Register a VM handler")
|
||||
fmt.Println("3. Process various heroscript commands")
|
||||
fmt.Println("\nTo run the full telnet server example, execute:")
|
||||
fmt.Println("go run main.go vm_handler.go")
|
||||
fmt.Println("\nPress Enter to exit the tutorial...")
|
||||
waitForEnter()
|
||||
}
|
||||
|
||||
// waitForEnter waits for the user to press Enter
|
||||
func waitForEnter() {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
reader.ReadString('\n')
|
||||
}
|
||||
|
||||
// VMTutorial contains the tutorial text for the VM handler
|
||||
const VMTutorial = `
|
||||
VM Handler Tutorial
|
||||
==================
|
||||
|
||||
The VM handler provides a set of commands to manage virtual machines through heroscript commands.
|
||||
|
||||
Available VM commands:
|
||||
!!vm.define name:test_vm cpu:4 memory:8GB storage:100GB
|
||||
!!vm.start name:test_vm
|
||||
!!vm.stop name:test_vm
|
||||
!!vm.disk_add name:test_vm size:50GB type:SSD
|
||||
!!vm.list
|
||||
!!vm.status name:test_vm
|
||||
!!vm.delete name:test_vm force:true
|
||||
|
||||
Authentication secret: 1234
|
||||
|
||||
Command Details:
|
||||
--------------
|
||||
1. define - Create a new VM with specified resources
|
||||
Parameters:
|
||||
- name: (required) Name of the VM
|
||||
- cpu: (optional) Number of CPUs, default: 1
|
||||
- memory: (optional) Memory size, default: 1GB
|
||||
- storage: (optional) Storage size, default: 10GB
|
||||
- description: (optional) Description of the VM
|
||||
|
||||
2. start - Start a VM
|
||||
Parameters:
|
||||
- name: (required) Name of the VM to start
|
||||
|
||||
3. stop - Stop a running VM
|
||||
Parameters:
|
||||
- name: (required) Name of the VM to stop
|
||||
|
||||
4. disk_add - Add a disk to a VM
|
||||
Parameters:
|
||||
- name: (required) Name of the VM
|
||||
- size: (optional) Size of the disk, default: 10GB
|
||||
- type: (optional) Type of disk (SSD, HDD), default: HDD
|
||||
|
||||
5. list - List all VMs
|
||||
|
||||
6. status - Show status of a VM
|
||||
Parameters:
|
||||
- name: (required) Name of the VM
|
||||
|
||||
7. delete - Delete a VM
|
||||
Parameters:
|
||||
- name: (required) Name of the VM
|
||||
- force: (optional) Force deletion even if VM is running, default: false
|
||||
|
||||
8. help - Show this help message
|
||||
|
||||
Examples:
|
||||
--------
|
||||
1. Create a new VM:
|
||||
!!vm.define name:webserver cpu:2 memory:4GB storage:50GB description:'Web server VM'
|
||||
|
||||
2. Start the VM:
|
||||
!!vm.start name:webserver
|
||||
|
||||
3. Add an SSD disk:
|
||||
!!vm.disk_add name:webserver size:100GB type:SSD
|
||||
|
||||
4. Check VM status:
|
||||
!!vm.status name:webserver
|
||||
|
||||
5. List all VMs:
|
||||
!!vm.list
|
||||
|
||||
6. Stop the VM:
|
||||
!!vm.stop name:webserver
|
||||
|
||||
7. Delete the VM:
|
||||
!!vm.delete name:webserver force:true
|
||||
`
|
||||
|
||||
// addTutorialCommand adds the tutorial command to the main function
|
||||
func addTutorialCommand() {
|
||||
// Check command line arguments
|
||||
if len(os.Args) > 1 && os.Args[1] == "tutorial" {
|
||||
runTutorial()
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
// GetVMTutorial returns the VM handler tutorial text
|
||||
func GetVMTutorial() string {
|
||||
return VMTutorial
|
||||
}
|
285
pkg2/heroscript/cmd/vmhandler/vm_handler.go
Normal file
285
pkg2/heroscript/cmd/vmhandler/vm_handler.go
Normal file
@@ -0,0 +1,285 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/handlerfactory"
|
||||
)
|
||||
|
||||
// VMHandler handles VM-related actions
|
||||
type VMHandler struct {
|
||||
handlerfactory.BaseHandler
|
||||
vms map[string]*VM
|
||||
}
|
||||
|
||||
// VM represents a virtual machine
|
||||
type VM struct {
|
||||
Name string
|
||||
CPU int
|
||||
Memory string
|
||||
Storage string
|
||||
Description string
|
||||
Running bool
|
||||
Disks []Disk
|
||||
}
|
||||
|
||||
// Disk represents a disk attached to a VM
|
||||
type Disk struct {
|
||||
Size string
|
||||
Type string
|
||||
}
|
||||
|
||||
// NewVMHandler creates a new VM handler
|
||||
func NewVMHandler() *VMHandler {
|
||||
return &VMHandler{
|
||||
BaseHandler: handlerfactory.BaseHandler{
|
||||
ActorName: "vm",
|
||||
},
|
||||
vms: make(map[string]*VM),
|
||||
}
|
||||
}
|
||||
|
||||
// Define handles the vm.define action
|
||||
func (h *VMHandler) Define(script string) string {
|
||||
params, err := h.ParseParams(script)
|
||||
if err != nil {
|
||||
return fmt.Sprintf("Error parsing parameters: %v", err)
|
||||
}
|
||||
|
||||
name := params.Get("name")
|
||||
if name == "" {
|
||||
return "Error: VM name is required"
|
||||
}
|
||||
|
||||
// Check if VM already exists
|
||||
if _, exists := h.vms[name]; exists {
|
||||
return fmt.Sprintf("Error: VM '%s' already exists", name)
|
||||
}
|
||||
|
||||
// Create new VM
|
||||
cpu := params.GetIntDefault("cpu", 1)
|
||||
memory := params.Get("memory")
|
||||
if memory == "" {
|
||||
memory = "1GB"
|
||||
}
|
||||
storage := params.Get("storage")
|
||||
if storage == "" {
|
||||
storage = "10GB"
|
||||
}
|
||||
description := params.Get("description")
|
||||
|
||||
vm := &VM{
|
||||
Name: name,
|
||||
CPU: cpu,
|
||||
Memory: memory,
|
||||
Storage: storage,
|
||||
Description: description,
|
||||
Running: false,
|
||||
Disks: []Disk{},
|
||||
}
|
||||
|
||||
// Add VM to map
|
||||
h.vms[name] = vm
|
||||
|
||||
return fmt.Sprintf("VM '%s' defined successfully with %d CPU, %s memory, and %s storage",
|
||||
name, cpu, memory, storage)
|
||||
}
|
||||
|
||||
// Start handles the vm.start action
|
||||
func (h *VMHandler) Start(script string) string {
|
||||
params, err := h.ParseParams(script)
|
||||
if err != nil {
|
||||
return fmt.Sprintf("Error parsing parameters: %v", err)
|
||||
}
|
||||
|
||||
name := params.Get("name")
|
||||
if name == "" {
|
||||
return "Error: VM name is required"
|
||||
}
|
||||
|
||||
// Find VM
|
||||
vm, exists := h.vms[name]
|
||||
if !exists {
|
||||
return fmt.Sprintf("Error: VM '%s' not found", name)
|
||||
}
|
||||
|
||||
// Start VM
|
||||
if vm.Running {
|
||||
return fmt.Sprintf("VM '%s' is already running", name)
|
||||
}
|
||||
|
||||
vm.Running = true
|
||||
return fmt.Sprintf("VM '%s' started successfully", name)
|
||||
}
|
||||
|
||||
// Stop handles the vm.stop action
|
||||
func (h *VMHandler) Stop(script string) string {
|
||||
params, err := h.ParseParams(script)
|
||||
if err != nil {
|
||||
return fmt.Sprintf("Error parsing parameters: %v", err)
|
||||
}
|
||||
|
||||
name := params.Get("name")
|
||||
if name == "" {
|
||||
return "Error: VM name is required"
|
||||
}
|
||||
|
||||
// Find VM
|
||||
vm, exists := h.vms[name]
|
||||
if !exists {
|
||||
return fmt.Sprintf("Error: VM '%s' not found", name)
|
||||
}
|
||||
|
||||
// Stop VM
|
||||
if !vm.Running {
|
||||
return fmt.Sprintf("VM '%s' is already stopped", name)
|
||||
}
|
||||
|
||||
vm.Running = false
|
||||
return fmt.Sprintf("VM '%s' stopped successfully", name)
|
||||
}
|
||||
|
||||
// DiskAdd handles the vm.disk_add action
|
||||
func (h *VMHandler) DiskAdd(script string) string {
|
||||
params, err := h.ParseParams(script)
|
||||
if err != nil {
|
||||
return fmt.Sprintf("Error parsing parameters: %v", err)
|
||||
}
|
||||
|
||||
name := params.Get("name")
|
||||
if name == "" {
|
||||
return "Error: VM name is required"
|
||||
}
|
||||
|
||||
// Find VM
|
||||
vm, exists := h.vms[name]
|
||||
if !exists {
|
||||
return fmt.Sprintf("Error: VM '%s' not found", name)
|
||||
}
|
||||
|
||||
// Add disk
|
||||
size := params.Get("size")
|
||||
if size == "" {
|
||||
size = "10GB"
|
||||
}
|
||||
diskType := params.Get("type")
|
||||
if diskType == "" {
|
||||
diskType = "HDD"
|
||||
}
|
||||
|
||||
disk := Disk{
|
||||
Size: size,
|
||||
Type: diskType,
|
||||
}
|
||||
|
||||
vm.Disks = append(vm.Disks, disk)
|
||||
return fmt.Sprintf("Added %s %s disk to VM '%s'", size, diskType, name)
|
||||
}
|
||||
|
||||
// Delete handles the vm.delete action
|
||||
func (h *VMHandler) Delete(script string) string {
|
||||
params, err := h.ParseParams(script)
|
||||
if err != nil {
|
||||
return fmt.Sprintf("Error parsing parameters: %v", err)
|
||||
}
|
||||
|
||||
name := params.Get("name")
|
||||
if name == "" {
|
||||
return "Error: VM name is required"
|
||||
}
|
||||
|
||||
// Find VM
|
||||
vm, exists := h.vms[name]
|
||||
if !exists {
|
||||
return fmt.Sprintf("Error: VM '%s' not found", name)
|
||||
}
|
||||
|
||||
// Check if VM is running and force flag is not set
|
||||
if vm.Running && !params.GetBool("force") {
|
||||
return fmt.Sprintf("Error: VM '%s' is running. Use force:true to delete anyway", name)
|
||||
}
|
||||
|
||||
// Delete VM
|
||||
delete(h.vms, name)
|
||||
return fmt.Sprintf("VM '%s' deleted successfully", name)
|
||||
}
|
||||
|
||||
// List handles the vm.list action
|
||||
func (h *VMHandler) List(script string) string {
|
||||
if len(h.vms) == 0 {
|
||||
return "No VMs defined"
|
||||
}
|
||||
|
||||
var result strings.Builder
|
||||
result.WriteString("Defined VMs:\n")
|
||||
|
||||
for _, vm := range h.vms {
|
||||
status := "stopped"
|
||||
if vm.Running {
|
||||
status = "running"
|
||||
}
|
||||
|
||||
result.WriteString(fmt.Sprintf("- %s (%s): %d CPU, %s memory, %s storage\n",
|
||||
vm.Name, status, vm.CPU, vm.Memory, vm.Storage))
|
||||
|
||||
if len(vm.Disks) > 0 {
|
||||
result.WriteString(" Attached disks:\n")
|
||||
for i, disk := range vm.Disks {
|
||||
result.WriteString(fmt.Sprintf(" %d. %s %s\n", i+1, disk.Size, disk.Type))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result.String()
|
||||
}
|
||||
|
||||
// Help handles the vm.help action
|
||||
func (h *VMHandler) Help(script string) string {
|
||||
return GetVMTutorial()
|
||||
}
|
||||
|
||||
// Status handles the vm.status action
|
||||
func (h *VMHandler) Status(script string) string {
|
||||
params, err := h.ParseParams(script)
|
||||
if err != nil {
|
||||
return fmt.Sprintf("Error parsing parameters: %v", err)
|
||||
}
|
||||
|
||||
name := params.Get("name")
|
||||
if name == "" {
|
||||
return "Error: VM name is required"
|
||||
}
|
||||
|
||||
// Find VM
|
||||
vm, exists := h.vms[name]
|
||||
if !exists {
|
||||
return fmt.Sprintf("Error: VM '%s' not found", name)
|
||||
}
|
||||
|
||||
// Return VM status
|
||||
status := "stopped"
|
||||
if vm.Running {
|
||||
status = "running"
|
||||
}
|
||||
|
||||
var result strings.Builder
|
||||
result.WriteString(fmt.Sprintf("VM '%s' status:\n", name))
|
||||
result.WriteString(fmt.Sprintf("- Status: %s\n", status))
|
||||
result.WriteString(fmt.Sprintf("- CPU: %d\n", vm.CPU))
|
||||
result.WriteString(fmt.Sprintf("- Memory: %s\n", vm.Memory))
|
||||
result.WriteString(fmt.Sprintf("- Storage: %s\n", vm.Storage))
|
||||
|
||||
if vm.Description != "" {
|
||||
result.WriteString(fmt.Sprintf("- Description: %s\n", vm.Description))
|
||||
}
|
||||
|
||||
if len(vm.Disks) > 0 {
|
||||
result.WriteString("- Attached disks:\n")
|
||||
for i, disk := range vm.Disks {
|
||||
result.WriteString(fmt.Sprintf(" %d. %s %s\n", i+1, disk.Size, disk.Type))
|
||||
}
|
||||
}
|
||||
|
||||
return result.String()
|
||||
}
|
75
pkg2/heroscript/cmd/vmhandler/vm_handler_server.go
Normal file
75
pkg2/heroscript/cmd/vmhandler/vm_handler_server.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/handlerfactory"
|
||||
)
|
||||
|
||||
// The tutorial functions are defined in tutorial.go
|
||||
|
||||
func main() {
|
||||
// Check if tutorial mode is requested
|
||||
addTutorialCommand()
|
||||
|
||||
fmt.Println("Starting VM Handler Example")
|
||||
|
||||
// Create a new handler factory
|
||||
factory := handlerfactory.NewHandlerFactory()
|
||||
|
||||
// Create and register the VM handler
|
||||
vmHandler := NewVMHandler()
|
||||
err := factory.RegisterHandler(vmHandler)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to register VM handler: %v", err)
|
||||
}
|
||||
|
||||
// Create a telnet server with the handler factory
|
||||
server := handlerfactory.NewTelnetServer(factory, "1234")
|
||||
|
||||
// Create socket directory if it doesn't exist
|
||||
socketDir := "/tmp"
|
||||
err = os.MkdirAll(socketDir, 0755)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create socket directory: %v", err)
|
||||
}
|
||||
|
||||
// Start the telnet server on a Unix socket
|
||||
socketPath := filepath.Join(socketDir, "vmhandler.sock")
|
||||
err = server.Start(socketPath)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to start telnet server: %v", err)
|
||||
}
|
||||
fmt.Printf("Telnet server started on socket: %s\n", socketPath)
|
||||
fmt.Printf("Connect with: nc -U %s\n", socketPath)
|
||||
|
||||
// Also start on TCP port for easier access
|
||||
err = server.StartTCP("localhost:8024")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to start TCP telnet server: %v", err)
|
||||
}
|
||||
fmt.Println("Telnet server started on TCP: localhost:8024")
|
||||
fmt.Println("Connect with: telnet localhost 8024")
|
||||
|
||||
// Print available commands
|
||||
fmt.Println("\nVM Handler started. Type '!!vm.help' to see available commands.")
|
||||
fmt.Println("Authentication secret: 1234")
|
||||
|
||||
// Wait for interrupt signal
|
||||
sigChan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-sigChan
|
||||
|
||||
// Stop the server
|
||||
fmt.Println("Stopping server...")
|
||||
err = server.Stop()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to stop telnet server: %v", err)
|
||||
}
|
||||
fmt.Println("Telnet server stopped")
|
||||
}
|
Reference in New Issue
Block a user