diff --git a/README.md b/README.md index 21d015ef1c4c6781faea5d74f29ee51e2d6a6ef8..2301add3d1deaae32afa8ada3f529c7b733150cc 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/src/client_cli/cmdVM/vmCred2pdf.go b/src/client_cli/cmdVM/vmCred2pdf.go new file mode 100644 index 0000000000000000000000000000000000000000..53f90f4b33bf85b1de4716212f1f449ddb9ab08b --- /dev/null +++ b/src/client_cli/cmdVM/vmCred2pdf.go @@ -0,0 +1,84 @@ +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 +} diff --git a/src/client_cli/cmdVM/vmEdit.go b/src/client_cli/cmdVM/vmEdit.go index c00d85e92cf1ca54aa7c9897d20d72d676f82b45..dfea71eeeee0a62e83083c59721142a0866af463 100644 --- a/src/client_cli/cmdVM/vmEdit.go +++ b/src/client_cli/cmdVM/vmEdit.go @@ -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 "" -} diff --git a/src/client_cli/go.mod b/src/client_cli/go.mod index 299ccd655a57f65ce055c36a3dce3639aa7e4a95..6fa84034a6e39f3d9a5f7e8f9a7fb80a4fdb3437 100644 --- a/src/client_cli/go.mod +++ b/src/client_cli/go.mod @@ -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 diff --git a/src/client_cli/go.sum b/src/client_cli/go.sum index 3e54ad76934bb38ce18ad819a2caf2aad9bc24f9..1eae60b1375f41b90e28cd35930847a57942f624 100644 --- a/src/client_cli/go.sum +++ b/src/client_cli/go.sum @@ -1,11 +1,34 @@ +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= diff --git a/src/client_cli/nexus-client.go b/src/client_cli/nexus-client.go index a1e11c65a47633185c40f6998c514da48c7f33c0..0863288f76a2d0502a7a0ac68c68aaf754f4aba3 100644 --- a/src/client_cli/nexus-client.go +++ b/src/client_cli/nexus-client.go @@ -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() {