diff --git a/src/router/routerVMs.go b/src/router/routerVMs.go index b989a0df814cca9353a63987b12e20650beebc29..1eb1b09b871f2c5a2cfccad9580f87e11b6e0dc6 100644 --- a/src/router/routerVMs.go +++ b/src/router/routerVMs.go @@ -101,7 +101,7 @@ func (r *RouterVMs)GetRebootableVMs(c echo.Context) error { // curl --cacert ca.pem -X GET https://localhost:1077/vms/edit -H "Authorization: Bearer <AccessToken>" func (r *RouterVMs)GetEditableVMs(c echo.Context) error { return r.performVMsList(c, caps.CAP_VM_EDIT_ANY, caps.CAP_VM_EDIT, func(vm vms.VM) bool { - return true + return !vm.IsRunning() }) } @@ -121,7 +121,7 @@ func (r *RouterVMs)GetEditableVMAccessVMs(c echo.Context) error { func(vm vms.VM) bool { // First, checks if the user is the VM's owner if vm.IsOwner(user.Email) { - return true + return !vm.IsRunning() } else { // Then, checks that user has CAP_VM_SET_ACCESS and also that // VM access has CAP_VM_SET_ACCESS set for the user @@ -129,7 +129,7 @@ func (r *RouterVMs)GetEditableVMAccessVMs(c echo.Context) error { capabilities, exists := vm.Access[user.Email] if exists { _, visible := capabilities[caps.CAP_VM_SET_ACCESS] - return visible + return visible && !vm.IsRunning() } else { return false } diff --git a/src/vms/vms.go b/src/vms/vms.go index 68938686eee2516f6a34412692804c6f697a35e8..72d2891eddf7b65332f7051ff1437289167352a1 100644 --- a/src/vms/vms.go +++ b/src/vms/vms.go @@ -22,9 +22,9 @@ type ( VMs struct { m map[string]VM dir string // Base directory where VMs are stored - rwlock *sync.RWMutex // RWlock to ensure the coherency of the map (m) of VMs - usedPorts [65536]bool // Indicates which ports are used by the VMs - usedRAM int // Used RAM by running VMs (in MB) + rwlock *sync.RWMutex // RWlock to ensure the VMs' map (m) coherency + usedPorts [65536]bool // Ports used by VMs + usedRAM int // RAM used by running VMs (in MB) } ) @@ -129,13 +129,21 @@ func (vms *VMs)DeleteVM(vmID uuid.UUID) error { return err } - // Deletes the VM's files (and directories). vm.mutex.Lock() + + if vm.IsRunning() { + vm.mutex.Unlock() + return errors.New("VM must be stopped") + } + + // Deletes the VM's files (and directories). if err := vm.delete(); err != nil { vm.mutex.Unlock() return err } + vm.mutex.Unlock() + // Removes the VM from the map. delete(vms.m, vmID.String()) return nil @@ -172,6 +180,10 @@ func (vms *VMs)StartVM(vmID uuid.UUID) (int, string, error) { return 0, "", err } + if vm.IsRunning() { + return 0, "", errors.New("VM must be stopped") + } + totalRAM, availRAM, err := utils.GetRAM() if err != nil { return -1, "", errors.New("Failed obtaining memory info: "+err.Error()) @@ -233,8 +245,13 @@ func (vms *VMs)KillVM(vmID uuid.UUID) error { } vm.mutex.Lock() + defer vm.mutex.Unlock() + + if !vm.IsRunning() { + return errors.New("VM must be running") + } + err = vm.kill() - vm.mutex.Unlock() return err } @@ -249,8 +266,13 @@ func (vms *VMs)ShutdownVM(vmID uuid.UUID) error { } vm.mutex.Lock() + defer vm.mutex.Unlock() + + if !vm.IsRunning() { + return errors.New("VM must be running") + } + err = vm.shutdown() - vm.mutex.Unlock() return err } @@ -265,8 +287,13 @@ func (vms *VMs)RebootVM(vmID uuid.UUID) error { } vm.mutex.Lock() + defer vm.mutex.Unlock() + + if !vm.IsRunning() { + return errors.New("VM must be running") + } + err = vm.reboot() - vm.mutex.Unlock() return err } @@ -285,11 +312,21 @@ func (vms *VMs)IsTemplateUsed(templateID string) bool { // Edit a VM' specs: name, cpus, ram, nic func (vms *VMs)EditVM(vmID uuid.UUID, name string, cpus, ram int, nic NicType, usbDevs []string) error { + vms.rwlock.Lock() + defer vms.rwlock.Unlock() + vm, err := vms.getVMUnsafe(vmID) if err != nil { return err } + vm.mutex.Lock() + defer vm.mutex.Unlock() + + if vm.IsRunning() { + return errors.New("VM must be stopped") + } + // Only updates fields that have changed. if name != "" { vm.Name = name @@ -311,11 +348,6 @@ func (vms *VMs)EditVM(vmID uuid.UUID, name string, cpus, ram int, nic NicType, u return err } - vm.mutex.Lock() - defer vm.mutex.Unlock() - vms.rwlock.Lock() - defer vms.rwlock.Unlock() - if err = vms.updateVM(&vm); err != nil { return err } @@ -343,6 +375,10 @@ func (vms *VMs)SetVMAccess(vmID uuid.UUID, loggedUserEmail, userEmail string, ne vm.mutex.Lock() defer vm.mutex.Unlock() + if vm.IsRunning() { + return errors.New("VM must be stopped") + } + // First, check that the logged user is the VM's owner. if !vm.IsOwner(loggedUserEmail) { // Next, checks the logged user has VM_SET_ACCESS set in her/his VM access. @@ -378,6 +414,10 @@ func (vms *VMs)DeleteVMAccess(vmID uuid.UUID, loggedUserEmail, userEmail string) vm.mutex.Lock() defer vm.mutex.Unlock() + if vm.IsRunning() { + return errors.New("VM must be stopped") + } + // First, check that the logged user is the VM's owner. if !vm.IsOwner(loggedUserEmail) { // Next, checks the logged user has VM_SET_ACCESS set in her/his VM access. @@ -410,6 +450,10 @@ func (vms *VMs)ExportVMFiles(vm *VM, vmDir, tarGzFile string) error { // Imports files from a tar.gz archive into a VM's filesystem, in a specified directory. func (vms *VMs)ImportFilesToVM(vm *VM, tarGzFile, vmDir string) error { + if vm.IsRunning() { + return errors.New("VM must be stopped") + } + // Marks the VM to copy from as being busy. if err := vms.setDiskBusy(vm); err != nil { return errors.New("Failed setting disk busy flag during VM files import: "+err.Error())