Skip to content
Snippets Groups Projects
Commit 4d4735e6 authored by Florent Gluck's avatar Florent Gluck
Browse files

Added new tool: vmcred2pdf (cmdVM/vmEdit.go) which creates a PDF with the...

Added new tool: vmcred2pdf (cmdVM/vmEdit.go) which creates a PDF with the credentials required to attach to running VMs.
Updated README.md accordingly.
parent c3980da7
No related branches found
No related tags found
No related merge requests found
......@@ -35,28 +35,29 @@ List of supported Commands:
login Login and obtain an access token.
whoami Display the current user's details.
passwd Update the current user's password.
user_list List users (regex matching).
user_add Add a user.
user_del Delete one or more users.
user_setcaps Set a user's capabilities.
userlist List users (regex matching).
useradd Add a user.
userdel Delete one or more users.
usersetcaps Set a user's capabilities.
vmlist List VMs that can be listed (regex matching).
vmlist_start List VMs that can be started (regex matching).
vmlist_attach List VMs that can be attached to (regex matching).
vmlist_stop List VMs that can be stopped (regex matching).
vmlist_edit List VMs that can be edited (regex matching).
vmlist_editaccess List VMs that can have their VM access edited (regex matching).
vmlist_del List VMs that can be deleted (regex matching).
vm_start Start one or more VMs (regex matching).
vm_stop Stop one or more VMs (regex matching).
vm_attach Attach to a VM in order to use its desktop environment.
vm_create Create one or more VMs (regex matching).
vm_edit Edit one or more VMs' properties: name, cpus, ram or nic (regex matching).
vm_del Delete one or more VMs (regex matching).
vm_setaccess Set a user's VM access in one or more VMs (regex matching).
vm_delaccess Delete a user's VM access in one or more VMs (regex matching).
tpl_list List available templates (regex matching).
tpl_create Create a template.
tpl_del Delete one or more templates.
vmliststart List VMs that can be started (regex matching).
vmlistattach List VMs that can be attached to (regex matching).
vmliststop List VMs that can be stopped (regex matching).
vmlistedit List VMs that can be edited (regex matching).
vmlisteditaccess List VMs that can have their VM access edited (regex matching).
vmlistdel List VMs that can be deleted (regex matching).
vmcred2pdf Create a PDF with the credentials required to attach to running VMs (regex matching).
vmstart Start one or more VMs (regex matching).
vmstop Stop one or more VMs (regex matching).
vmattach Attach to a VM in order to use its desktop environment.
vmcreate Create one or more VMs (regex matching).
vmedit Edit one or more VMs' properties: name, cpus, ram or nic (regex matching).
vmdel Delete one or more VMs (regex matching).
vmsetaccess Set a user's VM access in one or more VMs (regex matching).
vmdelaccess Delete a user's VM access in one or more VMs (regex matching).
tpllist List available templates (regex matching).
tplcreate Create a template.
tpldel Delete one or more templates.
```
### Compiling nexus-client
......@@ -96,9 +97,9 @@ List all available commands:
nexus-client
```
Display the help for the `vm_create` command:
Display the help for the `vmcreate` command:
```
nexus-client vm_create
nexus-client vmcreate
```
Authentify user `janedoe@nexus.org` and obtain an access token:
......@@ -113,17 +114,17 @@ nexus-client whoami
List all users:
```
nexus-client user_list .
nexus-client userlist .
```
List users matching the "jane" pattern:
```
nexus-client user_list jane
nexus-client userlist jane
```
Add new user `lukesky@force.org` with a list of capabilities:
```
nexus-client user_add lukesky@force.org Luke Skywalker pipomolo USER_CREATE USER_DESTROY USER_LIST USER_SET_CAPS VM_CREATE
nexus-client useradd lukesky@force.org Luke Skywalker pipomolo USER_CREATE USER_DESTROY USER_LIST USER_SET_CAPS VM_CREATE
```
List all listable VMs:
......@@ -143,52 +144,52 @@ nexus-client vmlist ubuntu 6713ce26-941e-4d95-8e92-6b71d44bf75a
List all VMs that can be started:
```
nexus-client vmlist_start .
nexus-client vmliststart .
```
Start VM `6713ce26-941e-4d95-8e92-6b71d44bf75a`:
```
nexus-client vm_start 6713ce26-941e-4d95-8e92-6b71d44bf75a
nexus-client vmstart 6713ce26-941e-4d95-8e92-6b71d44bf75a
```
Start VMs matching the "exam ISC_433 PCO" pattern:
```
nexus-client vm_start "exam ISC_433 PCO"
nexus-client vmstart "exam ISC_433 PCO"
```
List all VMs that can be attached to:
```
nexus-client vmlist_attach .
nexus-client vmlistattach .
```
Attach to VM `6713ce26-941e-4d95-8e92-6b71d44bf75a`:
```
nexus-client vm_attach 6713ce26-941e-4d95-8e92-6b71d44bf75a
nexus-client vmattach 6713ce26-941e-4d95-8e92-6b71d44bf75a
```
List all VMs that can be stopped:
```
nexus-client vmlist_stop .
nexus-client vmliststop .
```
Stop VMs matching the "exam ISC_433 PCO" pattern:
```
nexus-client vm_stop "exam ISC_433 PCO"
nexus-client vmstop "exam ISC_433 PCO"
```
Stop VM `6713ce26-941e-4d95-8e92-6b71d44bf75a`:
```
nexus-client vm_stop 6713ce26-941e-4d95-8e92-6b71d44bf75a
nexus-client vmstop 6713ce26-941e-4d95-8e92-6b71d44bf75a
```
Create a VM named "Doom", based on the `fbccb584-9ea6-40f7-926d-dabf3970525e` (Doom) template, with 4 CPUs, 4GB RAM, and a network interface with NAT translation:
```
nexus-client vm_create Doom 4 4096 user fbccb584-9ea6-40f7-926d-dabf3970525e
nexus-client vmcreate Doom 4 4096 user fbccb584-9ea6-40f7-926d-dabf3970525e
```
Create 50 VMs with the base name "ISC_433 Exam" based on the `6713ce26-941e-4d95-8e92-6b71d44bf75a` template, with 2 CPUs, 2GB RAM, and no network interface:
```
nexus-client vm_create "ISC_433 Exam" 2 2048 none 6713ce26-941e-4d95-8e92-6b71d44bf75a 50
nexus-client vmcreate "ISC_433 Exam" 2 2048 none 6713ce26-941e-4d95-8e92-6b71d44bf75a 50
```
It takes about 30 seconds and 11MB of disk space to create these 50 VMs.
They will have the following names:
......@@ -201,77 +202,82 @@ ISC_433 Exam [50]
List all VMs that can be edited:
```
nexus-client vmlist_edit .
nexus-client vmlistedit .
```
Edit VM `6713ce26-941e-4d95-8e92-6b71d44bf75a` by changing its name to "Tagada VM", changing it to 1 CPU and no network interface (`none`):
```
nexus-client vm_edit 6713ce26-941e-4d95-8e92-6b71d44bf75a name="Tagada VM" cpus=1 nic=none
nexus-client vmedit 6713ce26-941e-4d95-8e92-6b71d44bf75a name="Tagada VM" cpus=1 nic=none
```
Edit VMs matching the "PCO lab2" pattern by changing their CPU to 1 core and a network interface with NAT translation (`user`):
```
nexus-client vm_edit "PCO lab2" cpus=1 nic=user
nexus-client vmedit "PCO lab2" cpus=1 nic=user
```
List all VMs that can be deleted:
```
nexus-client vmlist_del .
nexus-client vmlistdel .
```
Delete VM `6713ce26-941e-4d95-8e92-6b71d44bf75a`:
```
nexus-client vm_del 6713ce26-941e-4d95-8e92-6b71d44bf75a
nexus-client vmdel 6713ce26-941e-4d95-8e92-6b71d44bf75a
```
Delete VMs matching the "exam ISC_433 PCO" pattern:
```
nexus-client vm_del "exam ISC_433 PCO"
nexus-client vmdel "exam ISC_433 PCO"
```
List all VMs that can have their access edited:
```
nexus-client vmlist_editaccess .
nexus-client vmlisteditaccess .
```
Set the VM access for VM `89649fe3-4940-4b77-929e-50903789cd87` with: `VM_LIST` and `VM_DESTROY` for user `student@nexus.org`:
```
nexus-client vm_setaccess 89649fe3-4940-4b77-929e-50903789cd87 student@nexus.org VM_LIST VM_DESTROY
nexus-client vmsetaccess 89649fe3-4940-4b77-929e-50903789cd87 student@nexus.org VM_LIST VM_DESTROY
```
Set VM access for VMs matching the "alpine" pattern with: `VM_START` and `VM_STOP` for user `student@nexus.org`:
```
nexus-client vm_setaccess alpine student@nexus.org VM_START VM_STOP
nexus-client vmsetaccess alpine student@nexus.org VM_START VM_STOP
```
Remove VM access for `student@nexus.org` from VM `89649fe3-4940-4b77-929e-50903789cd87`:
```
nexus-client vm_delaccess 89649fe3-4940-4b77-929e-50903789cd87 student@nexus.org
nexus-client vmdelaccess 89649fe3-4940-4b77-929e-50903789cd87 student@nexus.org
```
Remove VM access for `student@nexus.org` from VMs matching the "lab2" pattern:
```
nexus-client vm_delaccess lab2 student@nexus.org
nexus-client vmdelaccess lab2 student@nexus.org
```
Generate `exam_vms.pdf` with the credentials required to connect to all running VMs matching "exam prog sys":
```
nexus-client vmcred2pdf "exam prog sys" output.pdf
```
List all available templates:
```
nexus-client tpl_list .
nexus-client tpllist .
```
List templates matching the "ubuntu" pattern:
```
nexus-client tpl_list ubuntu
nexus-client tpllist ubuntu
```
Create a new `public` template, named "Xubuntu 22.04 + golang toolchain" based on VM `89649fe3-4940-4b77-929e-50903789cd87` (`public` templates are accessible to everyone while `private` templates are only accessible to their creators):
```
nexus-client tpl_list 89649fe3-4940-4b77-929e-50903789cd87 "Xubuntu 22.04 + golang toolchain" public
nexus-client tpllist 89649fe3-4940-4b77-929e-50903789cd87 "Xubuntu 22.04 + golang toolchain" public
```
Delete template `8ae56a30-3195-4aea-960d-abb45c47f99e`:
```
nexus-client tpl_del 8ae56a30-3195-4aea-960d-abb45c47f99e
nexus-client tpldel 8ae56a30-3195-4aea-960d-abb45c47f99e
```
## nexus-client-exam
......
package cmdVM
import (
"strconv"
u "nexus-client/utils"
"github.com/go-pdf/fpdf"
)
type Cred2pdf struct {
Name string
}
func (cmd *Cred2pdf)GetName() string {
return cmd.Name
}
func (cmd *Cred2pdf)GetDesc() string {
return "Create a PDF with the credentials required to attach to running VMs (regex matching)."
}
func (cmd *Cred2pdf)PrintUsage() {
u.PrintlnErr(cmd.GetDesc())
u.PrintlnErr("Usage: ",cmd.GetName()," [ID ...] [regex ...] pdfile")
u.PrintlnErr("Only VMs that can be attached to and matching the specified IDs or regexes will be listed.")
const usage string = `Any number of IDs or regexes can be specified.
The regex only matches the VM's name and is case-insensitive.
Regex examples:
"" -> matches any VMs
"." -> matches any VMs
"bla" -> matches any VMs containing "bla" in their name`
u.PrintlnErr(usage)
}
func (cmd *Cred2pdf)Run(args []string) int {
argc := len(args)
if argc < 2 {
cmd.PrintUsage()
return 1
}
pdfFile := args[argc-1]
vms, err := getFilteredVMs("/vms/attach", args[:argc-1])
if err != nil {
u.PrintlnErr("Error: "+err.Error())
return 1
}
const leftMargin = 4.
const topMargin = 4.
const rightMargin = 0.
columnWidth := [...]float64 {80.,13.,40.,20.,69.}
const rowHeight = 15.
const fontSize = 10.
const cellBorder = "1" // full cell border; use "" for no border
const nextPos = 0 // 0 means to move right
const align = "L"
const bkgd = false // transparent background; use true for filled
const link = 0 // no link
const url = "" // no url
pdf := fpdf.New("p", "mm", "A4", "") // "p" means portrait orienation
pdf.SetMargins(leftMargin, topMargin, rightMargin)
pdf.AddPage()
for _, vm := range vms {
pdf.SetX(leftMargin)
pdf.SetFont("Arial", "b", fontSize) // "b" means bold; use "" for normal
pdf.CellFormat(columnWidth[0], rowHeight, vm.Name, cellBorder, nextPos, align, bkgd, link, url)
pdf.SetFont("Courier", "b", fontSize) // "b" means bold; use "" for normal
pdf.CellFormat(columnWidth[1], rowHeight, strconv.Itoa(vm.Run.Port), cellBorder, nextPos, align, bkgd, link, url)
pdf.SetFont("Courier", "b", fontSize+1) // "b" means bold; use "" for normal
pdf.CellFormat(columnWidth[2], rowHeight, vm.Run.Pwd, cellBorder, nextPos, align, bkgd, link, url)
pdf.CellFormat(columnWidth[4], rowHeight, "", cellBorder, nextPos, align, bkgd, link, url)
pdf.Ln(-1) // line break; -1 means move by the height of the last printed cell
}
if err = pdf.OutputFileAndClose(pdfFile); err != nil {
u.PrintlnErr("Error: "+err.Error())
return 1
}
return 0
}
......@@ -97,14 +97,22 @@ func (cmd *Edit)parseArgs(args []string) (*vmEditParameters, []string, error) {
var patterns []string
atLeastOneArg := false
getStringVal := func(s string, prefix string) string {
if strings.HasPrefix(s, prefix) {
parts := strings.Split(s, prefix)
return parts[1]
}
return ""
}
for _, arg := range args {
s := cmd.getStringVal(arg, "name=")
s := getStringVal(arg, "name=")
if s != "" {
vmParams.Name = s
atLeastOneArg = true
continue
}
s = cmd.getStringVal(arg, "cpus=")
s = getStringVal(arg, "cpus=")
if s != "" {
cpus, err := strconv.Atoi(s)
if err != nil {
......@@ -114,7 +122,7 @@ func (cmd *Edit)parseArgs(args []string) (*vmEditParameters, []string, error) {
atLeastOneArg = true
continue
}
s = cmd.getStringVal(arg, "ram=")
s = getStringVal(arg, "ram=")
if s != "" {
ram, err := strconv.Atoi(s)
if err != nil {
......@@ -124,7 +132,7 @@ func (cmd *Edit)parseArgs(args []string) (*vmEditParameters, []string, error) {
atLeastOneArg = true
continue
}
s = cmd.getStringVal(arg, "nic=")
s = getStringVal(arg, "nic=")
if s != "" {
vmParams.Nic = s
atLeastOneArg = true
......@@ -140,11 +148,3 @@ func (cmd *Edit)parseArgs(args []string) (*vmEditParameters, []string, error) {
return nil, nil, nil
}
}
func (cmd *Edit)getStringVal(s string, prefix string) string {
if strings.HasPrefix(s, prefix) {
parts := strings.Split(s, prefix)
return parts[1]
}
return ""
}
......@@ -23,6 +23,10 @@ require (
)
require (
github.com/go-pdf/fpdf v0.6.0 // indirect
github.com/phpdave11/gofpdi v1.0.13 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/signintech/gopdf v0.14.0 // indirect
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
......
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-pdf/fpdf v0.6.0 h1:MlgtGIfsdMEEQJr2le6b/HNr1ZlQwxyWr77r2aj2U/8=
github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M=
github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY=
github.com/phpdave11/gofpdi v1.0.11 h1:wsBNx+3S0wy1dEp6fzv281S74ogZGgIdYWV2PugWgho=
github.com/phpdave11/gofpdi v1.0.11/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/phpdave11/gofpdi v1.0.13 h1:o61duiW8M9sMlkVXWlvP92sZJtGKENvW3VExs6dZukQ=
github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w=
github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk=
github.com/signintech/gopdf v0.14.0 h1:/nE8Le+mR1ZLM8JlRinykoSx34ed6rHv1W85l1Sjm9U=
github.com/signintech/gopdf v0.14.0/go.mod h1:a+E8HlIuBwghPyoo7UaoB5UaL7zklDzmYVIAHoW/Rlw=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM=
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
......@@ -15,5 +38,6 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
......@@ -25,31 +25,33 @@ var cmdList = []cmd.Command {
&cmdUser.Whoami{"whoami"},
&cmdUser.UpdatePwd{"passwd"},
&cmdUser.List{"user_list"},
&cmdUser.Add{"user_add"},
&cmdUser.Del{"user_del"},
&cmdUser.SetCaps{"user_setcaps"},
&cmdUser.List{"userlist"},
&cmdUser.Add{"useradd"},
&cmdUser.Del{"userdel"},
&cmdUser.SetCaps{"usersetcaps"},
&cmdVM.List{"vmlist"},
&cmdVM.ListStart{"vmlist_start"},
&cmdVM.ListAttach{"vmlist_attach"},
&cmdVM.ListStop{"vmlist_stop"},
&cmdVM.ListEdit{"vmlist_edit"},
&cmdVM.ListEditAccess{"vmlist_editaccess"},
&cmdVM.ListDel{"vmlist_del"},
&cmdVM.Start{"vm_start"},
&cmdVM.Stop{"vm_stop"},
&cmdVM.Attach{"vm_attach"},
&cmdVM.Create{"vm_create"},
&cmdVM.Edit{"vm_edit"},
&cmdVM.Del{"vm_del"},
&cmdVM.SetAccess{"vm_setaccess"},
&cmdVM.DelAccess{"vm_delaccess"},
&cmdTemplate.List{"tpl_list"},
&cmdTemplate.Create{"tpl_create"},
&cmdTemplate.Del{"tpl_del"},
&cmdVM.ListStart{"vmliststart"},
&cmdVM.ListAttach{"vmlistattach"},
&cmdVM.ListStop{"vmliststop"},
&cmdVM.ListEdit{"vmlistedit"},
&cmdVM.ListEditAccess{"vmlisteditaccess"},
&cmdVM.ListDel{"vmlistdel"},
&cmdVM.Cred2pdf{"vmcred2pdf"},
&cmdVM.Start{"vmstart"},
&cmdVM.Stop{"vmstop"},
&cmdVM.Attach{"vmattach"},
&cmdVM.Create{"vmcreate"},
&cmdVM.Edit{"vmedit"},
&cmdVM.Del{"vmdel"},
&cmdVM.SetAccess{"vmsetaccess"},
&cmdVM.DelAccess{"vmdelaccess"},
&cmdTemplate.List{"tpllist"},
&cmdTemplate.Create{"tplcreate"},
&cmdTemplate.Del{"tpldel"},
}
func main() {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment