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

Ongoing work on usb redirection

parent 64a181ed
No related branches found
No related tags found
No related merge requests found
......@@ -3,6 +3,7 @@ package cmdTemplate
import (
u "nexus-client/utils"
g "nexus-client/globals"
"github.com/google/uuid"
"github.com/go-resty/resty/v2"
)
......@@ -27,7 +28,7 @@ func (cmd *Create)PrintUsage() {
u.PrintlnErr("―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――")
u.PrintlnErr("USAGE: "+cmd.GetName()+" ID name access")
u.PrintlnErr("―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――")
u.PrintlnErr("ID ID of the VM used to create the template.")
u.PrintlnErr("vmID ID of the VM used to create the template.")
u.PrintlnErr("name Name of the template to create.")
u.PrintlnErr("access Access type, either \"public\" or \"private\"")
}
......@@ -39,11 +40,14 @@ func (cmd *Create)Run(args []string) int {
return 1
}
id := args[0]
vmID, err := uuid.Parse(args[0])
if err != nil {
u.PrintlnErr(err)
}
name := args[1]
access := args[2]
resp, err := cmd.makeRequestForID(id, name, access)
resp, err := cmd.makeRequestForID(vmID, name, access)
if err != nil {
u.PrintlnErr("Error: "+err.Error())
return 1
......@@ -57,12 +61,12 @@ func (cmd *Create)Run(args []string) int {
}
}
func (cmd *Create)makeRequestForID(vmID, name, access string) (*resty.Response, error) {
func (cmd *Create)makeRequestForID(vmID uuid.UUID, name, access string) (*resty.Response, error) {
client := g.GetInstance().Client
host := g.GetInstance().Host
type TemplateArgs struct {
VMID string
VMID uuid.UUID
Name string
Access string
}
......
......@@ -14,7 +14,7 @@ import (
)
// Converts a VM structure into a pretty string.
func (vm *VMSerialized)String() string {
func (vm *VMNetworkSerialized)String() string {
output, err := json.MarshalIndent(vm, "", " ")
if err != nil {
return err.Error()
......@@ -114,7 +114,7 @@ func printFilteredVMs(c cmd.Command, args []string, route string) int {
// Regular expression examples:
// "." -> matches everything
// "bla" -> matches any VM name containing "bla"
func getFilteredVMs(route string, patterns []string) ([]VMSerialized, error) {
func getFilteredVMs(route string, patterns []string) ([]VMNetworkSerialized, error) {
if len(patterns) < 1 {
return nil, errors.New("At least one ID or regex must be specified")
}
......@@ -139,7 +139,7 @@ func getFilteredVMs(route string, patterns []string) ([]VMSerialized, error) {
return nil, err
}
vmsList := []VMSerialized{}
vmsList := []VMNetworkSerialized{}
if resp.IsSuccess() {
vms, err := getVMs(resp)
......@@ -178,8 +178,8 @@ func getFilteredVMs(route string, patterns []string) ([]VMSerialized, error) {
}
// Retrieves all VMs (no filtering).
func getVMs(resp *resty.Response) ([]VMSerialized, error) {
vms := []VMSerialized{}
func getVMs(resp *resty.Response) ([]VMNetworkSerialized, error) {
vms := []VMNetworkSerialized{}
if err := json.Unmarshal(resp.Body(), &vms); err != nil {
return nil, err
}
......@@ -187,8 +187,8 @@ func getVMs(resp *resty.Response) ([]VMSerialized, error) {
}
// Retrieve a single VM.
func getVM(resp *resty.Response) (*VMSerialized, error) {
var vm *VMSerialized = &VMSerialized{}
func getVM(resp *resty.Response) (*VMNetworkSerialized, error) {
var vm *VMNetworkSerialized = &VMNetworkSerialized{}
if err := json.Unmarshal(resp.Body(), vm); err != nil {
return vm, err
}
......
......@@ -6,19 +6,20 @@ import (
// Make sure these types MATCH their counterparts in nexus-server codebase!
type (
VMSerialized struct {
ID uuid.UUID
Owner string
Name string
Cpus int
Ram int
Nic NicType
TemplateID uuid.UUID
Access map[string]Capabilities
State VMState
Port int
Pwd string
DiskBusy bool // If true the VM's disk is busy (cannot be modified or deleted)
VMNetworkSerialized struct {
ID uuid.UUID `json:"id"`
Owner string `json:"owner"`
Name string `json:"name"`
Cpus int `json:"cpus"`
Ram int `json:"ram"`
Nic NicType `json:"nic"`
UsbDevs []string `json:"usbDevs"` // vendorID:productID
TemplateID uuid.UUID `json:"templateID"`
Access map[string]Capabilities `json:"access"`
State VMState `json:"state"`
Port int `json:"port"`
Pwd string `json:"pwd"`
DiskBusy bool `json:"diskBusy"`
}
Capabilities map[string]int
......
......@@ -52,7 +52,7 @@ func (cmd *Attach)Run(args []string) int {
// wg.Add(len(vms))
for _, vm := range(vms) {
go func(vm VMSerialized) {
go func(vm VMNetworkSerialized) {
exec.RunRemoteViewer(hostname, cert, vm.Name, vm.Port, vm.Pwd, false)
// wg.Done()
} (vm)
......
......@@ -2,9 +2,11 @@ package cmdVM
import (
"fmt"
"strings"
"strconv"
u "nexus-client/utils"
g "nexus-client/globals"
"github.com/google/uuid"
)
type Create struct {
......@@ -26,13 +28,16 @@ func (cmd *Create)PrintUsage() {
u.PrintlnErr(desc)
}
u.PrintlnErr("―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――")
u.PrintlnErr("USAGE: "+cmd.GetName()+" name cpus ram nic template [count|file.csv]")
u.PrintlnErr("USAGE: "+cmd.GetName()+" name cpus ram nic usb template [count|file.csv]")
u.PrintlnErr("―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――")
const usage string = `name Name of the VM to create.
cpus Number of CPUs, between 1 and 16.
ram Amount of RAM in MB, between 512 and 32768.
nic Network interface, either "none" (no network) or "user" (network access).
template ID of the template to VM will be based on.
usb List of USB devices exposed in the VM; either "none" or a list of comma separated
vendorID:productID (4-digit hex number), each specifying a USB device; example
exposing two USB devices: 1fc9:001d,067b:2303
templateID ID of the template to VM will be based on.
count Number of VMs to create (if not specified, one is created).
If specified and > 1, each VM's name is postfixed with [n],
where n ranges from 1..count.
......@@ -46,7 +51,7 @@ func (cmd *Create)Run(args []string) int {
host := g.GetInstance().Host
argc := len(args)
if argc < 5 || argc > 6 {
if argc < 6 || argc > 7 {
cmd.PrintUsage()
return 1
}
......@@ -62,17 +67,22 @@ func (cmd *Create)Run(args []string) int {
u.PrintlnErr("Invalid amount of RAM")
return 1
}
nic := args[3]
template := args[4]
nic := NicType(args[3])
usbDevs := cmd.str2UsbDevices(args[4])
templateID, err := uuid.Parse(args[5])
if err != nil {
u.PrintlnErr(err)
}
count := 1
var csvEntries []string = nil
// If there is a 6th argument, checks whether it's a number or a CSV file.
if argc == 6 {
count, err = strconv.Atoi(args[5])
if argc == 7 {
count, err = strconv.Atoi(args[6])
if err != nil {
// It's not a number, we assume it's a CSV file and parse it.
csvFile := args[5]
csvFile := args[6]
csvEntries, err = u.ReadCSVColumn(csvFile, 0)
if err != nil {
u.PrintlnErr(err.Error())
......@@ -95,8 +105,9 @@ func (cmd *Create)Run(args []string) int {
Name string
Cpus int
Ram int
Nic string
TemplateID string
Nic NicType
UsbDevs []string
TemplateID uuid.UUID
}
vmArgs := &VMArgs {
......@@ -104,7 +115,8 @@ func (cmd *Create)Run(args []string) int {
Cpus: ncpus,
Ram: ram,
Nic: nic,
TemplateID: template,
UsbDevs: usbDevs,
TemplateID: templateID,
}
statusCode := 0
......@@ -141,3 +153,17 @@ func (cmd *Create)Run(args []string) int {
return statusCode
}
// Convert a string of USB devices of the form "1fc9:001d,067b:2303"
// into a slice of string where each element is a string of the form "1fc9:001d".
// Returns an empty slice if the input string is "none".
func (cmd *Create)str2UsbDevices(s string) []string {
usbDevs := []string{}
if s != "none" {
devs := strings.Split(s, ",") // Extracts USB devices
for _, dev := range devs {
usbDevs = append(usbDevs, dev)
}
}
return usbDevs
}
......@@ -7,8 +7,8 @@ import (
const (
major = 1
minor = 5
bugfix = 3
minor = 6
bugfix = 0
)
type Version struct {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment