diff --git a/src/server/exec/QemuSystem.go b/src/server/exec/QemuSystem.go index 2f7d0dd7035f6ca90250f7bb28bd9022c8ab8c20..77764b244a4858103712289f29dfec7b37198141 100644 --- a/src/server/exec/QemuSystem.go +++ b/src/server/exec/QemuSystem.go @@ -78,6 +78,9 @@ func NewQemuSystem(qgaSock string, cpus, ram int, nic string, usbDevs []string, // Enable KVM args := []string{"-enable-kvm"} + // Suppresses several non-needed backends: serial, parallel, floppy, CD-ROM, SD card, etc. + // More info here: https://gitlab.com/qemu-project/qemu/-/issues/322 + args = append(args, "-nodefaults") // CPU args = append(args, "-cpu", "host", "-smp", "cpus="+strconv.Itoa(cpus)) // RAM diff --git a/src/server/router/routerTemplates.go b/src/server/router/routerTemplates.go index af611957b884190d1c23d67f492c1ffe9bbcf3f4..8679d72b2976c36ba893b784850f2c4c052c0181 100644 --- a/src/server/router/routerTemplates.go +++ b/src/server/router/routerTemplates.go @@ -41,12 +41,12 @@ func (r *RouterTemplates)GetTemplates(c echo.Context) error { // If the logged user has CAP_TPL_LIST_ANY, lists all templates. if user.HasCapability(caps.CAP_TPL_LIST_ANY) { // Returns all templates - return c.JSONPretty(http.StatusOK, r.tpl.GetNetworkSerializedTemplates(func(t vms.Template) bool { return true }), " ") + return c.JSONPretty(http.StatusOK, r.tpl.GetNetworkSerializedTemplates(func(template *vms.Template) bool { return true }), " ") } else if user.HasCapability(caps.CAP_TPL_LIST) { // Returns templates owned by the logged user and public templates. return c.JSONPretty(http.StatusOK, - r.tpl.GetNetworkSerializedTemplates(func(t vms.Template) bool { - return t.GetOwner() == user.Email || t.IsPublic() + r.tpl.GetNetworkSerializedTemplates(func(template *vms.Template) bool { + return template.GetOwner() == user.Email || template.IsPublic() }), " ") } else { return echo.NewHTTPError(http.StatusUnauthorized, msgInsufficientCaps) @@ -290,19 +290,19 @@ func (r *RouterTemplates)ExportDisk(c echo.Context) error { } if user.HasCapability(caps.CAP_TPL_READFS_ANY) { - t, err := r.tpl.GetTemplate(tplID) + template, err := r.tpl.GetTemplate(tplID) if err != nil { return echo.NewHTTPError(http.StatusNotFound, err.Error()) } - return c.File(t.GetTemplateDiskPath()) + return c.File(template.GetTemplateDiskPath()) } else if user.HasCapability(caps.CAP_TPL_READFS) { - t, err := r.tpl.GetTemplate(tplID) + template, err := r.tpl.GetTemplate(tplID) if err != nil { return echo.NewHTTPError(http.StatusNotFound, err.Error()) } - if t.IsPublic() || t.GetOwner() == user.Email { - return c.File(t.GetTemplateDiskPath()) + if template.IsPublic() || template.GetOwner() == user.Email { + return c.File(template.GetTemplateDiskPath()) } } diff --git a/src/server/vms/template.go b/src/server/vms/template.go index 4bd6dfdf4360f112f667c7f215fdcbf667fea198..96a58ea55f50e48e713720a20ac6d1ec28f2d06d 100644 --- a/src/server/vms/template.go +++ b/src/server/vms/template.go @@ -27,8 +27,6 @@ const ( templatePrivate = "private" ) -var dummyTemplate = Template{} - // Creates a template from a VM's disk. func NewTemplateFromVM(name, owner, access string, vm *VM) (*Template, error) { vm.mutex.Lock() @@ -149,7 +147,7 @@ func (template *Template)SerializeToNetwork() template.TemplateSerialized { return template.t } -// Creates a template. +// Cr1eates a template. func newTemplate(name, owner, access string) (*Template, error) { id, err := uuid.NewRandom() if err != nil { diff --git a/src/server/vms/templates.go b/src/server/vms/templates.go index d46df9a42159fb2511f8acad4672a2fa055f0376..ac3dbb9d044454fd2cf75251b8911198ab577f46 100644 --- a/src/server/vms/templates.go +++ b/src/server/vms/templates.go @@ -14,10 +14,10 @@ import( ) type ( - TemplateKeeperFn func(tpl Template) bool + TemplateKeeperFn func(tpl *Template) bool Templates struct { - m map[string]Template + m map[string]*Template dir string // Base directory where templates reside rwlock *sync.RWMutex } @@ -35,7 +35,7 @@ func GetTemplatesInstance() *Templates { // NOTE: path is the root directory where templates reside. func InitTemplates() error { templatesDir := paths.GetInstance().TemplatesDir - templates = &Templates { m: make(map[string]Template), dir: templatesDir, rwlock: new(sync.RWMutex) } + templates = &Templates { m: make(map[string]*Template), dir: templatesDir, rwlock: new(sync.RWMutex) } dirs, err := utils.GetSubDirs(templatesDir) if err != nil { @@ -64,18 +64,19 @@ func InitTemplates() error { continue } - templates.m[templateDir] = *template + templates.m[templateDir] = template } return nil } // Returns the list of templates for which TemplateKeeperFn returns true. -func (templates *Templates)GetNetworkSerializedTemplates(keep TemplateKeeperFn) []t.TemplateSerialized { +func (templates *Templates)GetNetworkSerializedTemplates(keepFn TemplateKeeperFn) []t.TemplateSerialized { templates.rwlock.RLock() + list := []t.TemplateSerialized{} for _, tpl := range templates.m { - if keep(tpl) { + if keepFn(tpl) { list = append(list, tpl.SerializeToNetwork()) } } @@ -89,13 +90,13 @@ func (templates *Templates)GetNetworkSerializedTemplates(keep TemplateKeeperFn) } // Returns a template by its ID. -func (templates *Templates)GetTemplate(tplID uuid.UUID) (Template, error) { +func (templates *Templates)GetTemplate(tplID uuid.UUID) (*Template, error) { templates.rwlock.RLock() defer templates.rwlock.RUnlock() template, exists := templates.m[tplID.String()] if !exists { - return dummyTemplate, errors.New("Template not found") + return nil, errors.New("Template not found") } return template, nil } @@ -136,7 +137,7 @@ func (templates *Templates)AddTemplate(template *Template) error { } // Adds template to the map of templates. - templates.m[template.t.ID.String()] = *template + templates.m[template.t.ID.String()] = template return nil } @@ -149,6 +150,8 @@ func (templates *Templates)EditTemplate(tplID uuid.UUID, name, access string) er } // Only updates fields that have changed. + oriVal := tpl.t // Saves original template values. + if name != "" { tpl.t.Name = name } @@ -157,6 +160,8 @@ func (templates *Templates)EditTemplate(tplID uuid.UUID, name, access string) er } if err = tpl.validate(); err != nil { + // Restores original template values. + tpl.t = oriVal return err } @@ -165,10 +170,6 @@ func (templates *Templates)EditTemplate(tplID uuid.UUID, name, access string) er return err } - key := tpl.t.ID.String() - delete(templates.m, key) - templates.m[key] = tpl - return nil } diff --git a/src/server/vms/vm.go b/src/server/vms/vm.go index 6082fd6581ca7ad90e9e0c8b7187fec5f573094d..3e89f86286d59272c64b45e37396d7f4bdf20774 100644 --- a/src/server/vms/vm.go +++ b/src/server/vms/vm.go @@ -52,8 +52,6 @@ const ( vmQGASockFile = "qga.sock" ) -var dummyVM = VM{} - // Custom password generator with the following characters removed: 0, O, l, I var passwordGen, _ = password.NewGenerator(&password.GeneratorInput{ LowerLetters: "abcdefghijkmnopqrstuvwxyz", diff --git a/src/server/vms/vms.go b/src/server/vms/vms.go index 1c385b54b937ab6e1de5aae4365b79be41d25e38..f925002a09f64ae502efe421e453e1105147ccad 100644 --- a/src/server/vms/vms.go +++ b/src/server/vms/vms.go @@ -120,7 +120,7 @@ func (vms *VMs)GetVM(vmID uuid.UUID) (*VM, error) { func (vms *VMs)getVMUnsafe(vmID uuid.UUID) (*VM, error) { vm, exists := vms.m[vmID.String()] if !exists { - return &dummyVM, errors.New("VM not found") + return nil, errors.New("VM not found") } return vm, nil } @@ -378,7 +378,7 @@ func (vms *VMs)EditVM(vmID uuid.UUID, p *params.VMEdit) error { } // Only updates fields that have changed. - prevVal := vm.v // Saves previous params values. + oriVal := vm.v // Saves original VM values. if p.Name != "" { vm.v.Name = p.Name @@ -397,8 +397,8 @@ func (vms *VMs)EditVM(vmID uuid.UUID, p *params.VMEdit) error { } if err = vm.validate(); err != nil { - // Restores previous values. - vm.v = prevVal + // Restores original VM values. + vm.v = oriVal return err }