diff --git a/src/client/cmdTemplate/templateCreate.go b/src/client/cmdTemplate/templateCreate.go
index 5266b0dd2d204f79906b614313a1ae66f3cbbacc..74b681a3421e96729f0fb3e3ef9aef5801e17bf3 100644
--- a/src/client/cmdTemplate/templateCreate.go
+++ b/src/client/cmdTemplate/templateCreate.go
@@ -1,6 +1,7 @@
 package cmdTemplate
 
 import (
+    "nexus-common/params"
     u "nexus-client/utils"
     g "nexus-client/globals"
     "github.com/google/uuid"
@@ -65,15 +66,8 @@ func (cmd *Create)makeRequestForID(vmID uuid.UUID, name, access string) (*resty.
     client := g.GetInstance().Client
     host := g.GetInstance().Host
 
-    type TemplateArgs struct {
-        VMID uuid.UUID
-        Name string
-        Access string
-    }
-
-    templateArgs := &TemplateArgs { vmID, name, access }
-
-    resp, err := client.R().SetBody(templateArgs).Post(host+"/templates/vm")
+    p := &params.TplCreate{ vmID, name, access }
+    resp, err := client.R().SetBody(p).Post(host+"/templates/vm")
     if err != nil {
         return nil, err
     }
diff --git a/src/client/cmdTemplate/templateEdit.go b/src/client/cmdTemplate/templateEdit.go
index ddb58b7ef74142c9cbd6b63f144a6e6864c25827..da0fb4c7d98f194706c17d43536e60fc92acee29 100644
--- a/src/client/cmdTemplate/templateEdit.go
+++ b/src/client/cmdTemplate/templateEdit.go
@@ -3,6 +3,7 @@ package cmdTemplate
 import (
     "errors"
     "strings"
+    "nexus-common/params"
     u "nexus-client/utils"
     g "nexus-client/globals"
 )
@@ -11,11 +12,6 @@ type Edit struct {
     Name string
 }
 
-type templateEditParameters struct {
-    Name string
-    Access string
-}
-
 func (cmd *Edit)GetName() string {
     return cmd.Name
 }
@@ -49,13 +45,13 @@ func (cmd *Edit)Run(args []string) int {
         return 1
     }
 
-    templateParams, err := cmd.parseArgs(args[1:])
+    p, err := cmd.parseArgs(args[1:])
     if err != nil {
         u.PrintlnErr(err.Error())
         return 1
     }
 
-    if templateParams == nil {
+    if p == nil {
         cmd.PrintUsage()
         return 1
     }
@@ -63,7 +59,7 @@ func (cmd *Edit)Run(args []string) int {
     tplID := args[0]
     statusCode := 0
 
-    resp, err := client.R().SetBody(templateParams).Put(host+"/templates/"+tplID)
+    resp, err := client.R().SetBody(p).Put(host+"/templates/"+tplID)
     if err != nil {
         u.PrintlnErr("Failed editing template \""+tplID+"\": "+err.Error())
         statusCode = 1
@@ -79,8 +75,8 @@ func (cmd *Edit)Run(args []string) int {
     return statusCode
 }
 
-func (cmd *Edit)parseArgs(args []string) (*templateEditParameters, error) {
-    templateParams := &templateEditParameters {}
+func (cmd *Edit)parseArgs(args []string) (*params.TplCreate, error) {
+    p := &params.TplCreate{}
     atLeastOneArg := false
 
     getStringVal := func(s string, prefix string) string {
@@ -94,13 +90,13 @@ func (cmd *Edit)parseArgs(args []string) (*templateEditParameters, error) {
     for _, arg := range args {
         s := getStringVal(arg, "name=")
         if s != "" {
-            templateParams.Name = s
+            p.Name = s
             atLeastOneArg = true
             continue
         }
         s = getStringVal(arg, "access=")
         if s != "" {
-            templateParams.Access = s
+            p.Access = s
             atLeastOneArg = true
             continue
         }
@@ -108,7 +104,7 @@ func (cmd *Edit)parseArgs(args []string) (*templateEditParameters, error) {
     }
 
     if atLeastOneArg {
-        return templateParams, nil
+        return p, nil
     } else {
         return nil, nil
     }
diff --git a/src/client/cmdUser/userSetCaps.go b/src/client/cmdUser/userSetCaps.go
index b27042097f52cc477134ddaab9a741906b965acf..0bae3d1f5ae1922795842b8ab681cc5f57129e65 100644
--- a/src/client/cmdUser/userSetCaps.go
+++ b/src/client/cmdUser/userSetCaps.go
@@ -6,6 +6,7 @@ import (
     "errors"
     "strings"
     "encoding/csv"
+    "nexus-common/params"
     u "nexus-client/utils"
     g "nexus-client/globals"
 )
@@ -38,10 +39,6 @@ func (cmd *SetCaps)PrintUsage() {
     u.PrintlnErr(usage)
 }
 
-type capsArgs struct {
-    Caps map[string]int `json:"caps"  validate:"required"`
-}
-
 func (cmd *SetCaps)Run(args []string) int {
     argc := len(args)
     if argc < 1 {
@@ -88,7 +85,7 @@ func (cmd *SetCaps)Run(args []string) int {
                 continue
             }
 
-            userCaps := &capsArgs { make(map[string]int) }
+            userCaps := &params.UserSetCaps{ make(map[string]int) }
 
             capsStr := strings.TrimSpace(columns[1])
             if len(capsStr) > 0 {
@@ -114,10 +111,9 @@ func (cmd *SetCaps)Run(args []string) int {
         }
     } else {
         // Argument is an email address
-
         email := args[0]
 
-        userCaps := &capsArgs { make(map[string]int) }
+        userCaps := &params.UserSetCaps{ make(map[string]int) }
         for _, cap := range args[1:] {
             userCaps.Caps[cap] = 1
         }
@@ -133,7 +129,7 @@ func (cmd *SetCaps)Run(args []string) int {
     return statusCode
 }
 
-func (cmd *SetCaps)runRequest(email string, userCaps *capsArgs) error {
+func (cmd *SetCaps)runRequest(email string, userCaps *params.UserSetCaps) error {
     client := g.GetInstance().Client
     host := g.GetInstance().Host
 
diff --git a/src/client/cmdUser/userUpdatePwd.go b/src/client/cmdUser/userUpdatePwd.go
index dc0695c50039ebea5623044bc1e3bbdd16bfcf76..7d045e33a7a673572251d0248e9ae85e1880781d 100644
--- a/src/client/cmdUser/userUpdatePwd.go
+++ b/src/client/cmdUser/userUpdatePwd.go
@@ -1,6 +1,7 @@
 package cmdUser
 
 import (
+    "nexus-common/params"
     u "nexus-client/utils"
     g "nexus-client/globals"
 )
@@ -64,13 +65,8 @@ func (cmd *UpdatePwd)Run(args []string) int {
     }
 
     pwdStr := string(newPwd)
-
-    type PwdArgs struct {
-        Pwd string
-    }
-
-    pwdArgs := &PwdArgs{pwdStr}
-    resp, err := client.R().SetBody(pwdArgs).Put(host+"/users/pwd")
+    p := &params.UserSetPwd{pwdStr}
+    resp, err := client.R().SetBody(p).Put(host+"/users/pwd")
     if err != nil {
         u.PrintlnErr("Error: "+err.Error())
         return 1
diff --git a/src/client/nexus-cli/go.mod b/src/client/nexus-cli/go.mod
index 89ae454c5bdd5dcd4084e77962c26af82c5757f1..903a49e47fd2271885a7957830a7e0519d4832a1 100644
--- a/src/client/nexus-cli/go.mod
+++ b/src/client/nexus-cli/go.mod
@@ -4,6 +4,8 @@ go 1.18
 
 replace nexus-common/caps => ../../common/caps
 
+replace nexus-common/params => ../../common/params
+
 replace nexus-common/vm => ../../common/vm
 
 replace nexus-common/template => ../../common/template
@@ -58,6 +60,7 @@ require (
 	nexus-client/exec v0.0.0-00010101000000-000000000000 // indirect
 	nexus-client/version v0.0.0-00010101000000-000000000000 // indirect
 	nexus-common/caps v0.0.0-00010101000000-000000000000 // indirect
+	nexus-common/params v0.0.0-00010101000000-000000000000 // indirect
 	nexus-common/template v0.0.0-00010101000000-000000000000 // indirect
 	nexus-common/utils v0.0.0-00010101000000-000000000000 // indirect
 	nexus-common/vm v0.0.0-00010101000000-000000000000 // indirect
diff --git a/src/client/nexus-cli/validate b/src/client/nexus-cli/validate
index aefcf26ab774d46667125793a65910b41e1ebd48..5c02d6ae5e375ed360326f57f367545c9d2ef5d4 100755
--- a/src/client/nexus-cli/validate
+++ b/src/client/nexus-cli/validate
@@ -6,11 +6,13 @@ nexus_cli="./nexus-cli"
 
 partial_name="exam 328a2d0eff08"
 full_name="live $partial_name"
-creds_file=creds.pdf
+creds_pdf_file=creds.pdf
+creds_csv_file=creds.csv
 
 del_gen_files () {
     find . -name "$full_name *.tar.gz" -delete
-    rm -f $creds_file
+    rm -f $creds_pdf_file
+    rm -f $creds_csv_file
 }
 
 cleanup () {
@@ -90,9 +92,14 @@ check "vmstart VMs"
 sleep 3
 OK
 
-echo "Generate credentials pdf..."
-$nexus_cli vmcred2pdf "$full_name" $creds_file
-check "vmcred2pdf"
+echo "Generate credentials to PDF..."
+$nexus_cli vmcreds2pdf "$full_name" $creds_pdf_file
+check "vmcreds2pdf"
+OK
+
+echo "Generate credentials to CSV..."
+$nexus_cli vmcreds2csv "$full_name" $creds_csv_file
+check "vmcreds2csv"
 OK
 
 echo "Kill students VMs..."
@@ -106,6 +113,18 @@ $nexus_cli vmexportdir "$full_name" /home
 check "vmexportdir"
 OK
 
+echo "Re-start students VMs with previous credentials..."
+$nexus_cli vmstartwithcreds $creds_csv_file
+check "vmstartwithcreds VMs"
+sleep 10
+OK
+
+echo "Kill students VMs..."
+$nexus_cli vmkill "$full_name"
+sleep 3
+check "vmkill VMs"
+OK
+
 echo "Delete students VMs..."
 $nexus_cli vmdel "$partial_name"
 check "vmdel VMs"
diff --git a/src/client/nexush/go.mod b/src/client/nexush/go.mod
index 2e81f76b12f43593a59853307caf87ab7229890b..4e87fa7b2ce314bc6a23bebd156be83be453de90 100644
--- a/src/client/nexush/go.mod
+++ b/src/client/nexush/go.mod
@@ -4,6 +4,8 @@ go 1.18
 
 replace nexus-common/caps => ../../common/caps
 
+replace nexus-common/params => ../../common/params
+
 replace nexus-common/vm => ../../common/vm
 
 replace nexus-common/template => ../../common/template
@@ -60,6 +62,7 @@ require (
 	nexus-client/utils v0.0.0-00010101000000-000000000000 // indirect
 	nexus-client/version v0.0.0-00010101000000-000000000000 // indirect
 	nexus-common/caps v0.0.0-00010101000000-000000000000 // indirect
+	nexus-common/params v0.0.0-00010101000000-000000000000 // indirect
 	nexus-common/template v0.0.0-00010101000000-000000000000 // indirect
 	nexus-common/utils v0.0.0-00010101000000-000000000000 // indirect
 	nexus-common/vm v0.0.0-00010101000000-000000000000 // indirect
diff --git a/src/client/version/version.go b/src/client/version/version.go
index 91f2cb535c52b8881263bc049ced2f53e1d8c42c..954a8d501a2b7b4b4cccc238d89106d6d90ac770 100644
--- a/src/client/version/version.go
+++ b/src/client/version/version.go
@@ -8,7 +8,7 @@ import (
 const (
     major  = 1
     minor  = 8
-    bugfix = 0
+    bugfix = 1
 )
 
 type Version struct {
diff --git a/src/common/params/go.mod b/src/common/params/go.mod
new file mode 100644
index 0000000000000000000000000000000000000000..9cb3705f5d86654e3aee6736257cff71642871b4
--- /dev/null
+++ b/src/common/params/go.mod
@@ -0,0 +1,3 @@
+module nexus-common/params
+
+go 1.18
diff --git a/src/common/params/templates.go b/src/common/params/templates.go
new file mode 100644
index 0000000000000000000000000000000000000000..6bd01e8e7509730e05be801ca24e3d4ad458fdc9
--- /dev/null
+++ b/src/common/params/templates.go
@@ -0,0 +1,16 @@
+package params
+
+import (
+	"github.com/google/uuid"
+)
+
+type TplCreate struct {
+	VMID uuid.UUID      `json:"vmID" validate:"required"`
+	Name string         `json:"name" validate:"required,min=2"`
+	Access string       `json:"access" validate:"required,min=4"`
+}
+
+type TplEdit struct {
+	Name   string       `json:"name"`
+	Access string       `json:"access"`
+}
diff --git a/src/common/params/users.go b/src/common/params/users.go
new file mode 100644
index 0000000000000000000000000000000000000000..dcb13d200c5b299028db4ecad9c252a6256e343c
--- /dev/null
+++ b/src/common/params/users.go
@@ -0,0 +1,13 @@
+package params
+
+import (
+	"nexus-common/caps"
+)
+
+type UserSetCaps struct {
+	Caps caps.Capabilities
+}
+
+type UserSetPwd struct {
+	Pwd string `json:"pwd" validate:"required,min=8"`
+}
diff --git a/src/common/params/vms.go b/src/common/params/vms.go
new file mode 100644
index 0000000000000000000000000000000000000000..d7c5256654244f49788fbeb1fd619efb0169333d
--- /dev/null
+++ b/src/common/params/vms.go
@@ -0,0 +1,37 @@
+package params
+
+import (
+	"nexus-common/vm"
+	"nexus-common/caps"
+	"github.com/google/uuid"
+)
+
+type VMCreate struct {
+	Name string           `json:"name"       validate:"required,min=4,max=256"`
+	Cpus int              `json:"cpus"       validate:"required,gte=1,lte=16"`
+	Ram int               `json:"ram"        validate:"required,gte=512,lte=32768"`
+	Nic vm.NicType        `json:"nic"        validate:"required`
+	UsbDevs []string      `json:"usbDevs"    validate:"required`
+	TemplateID uuid.UUID  `json:"templateID" validate:"required"`
+}
+
+type VMStartWithCreds struct {
+	Port int              `json:"port"       validate:"required,gte=1100,lte=65535"`
+	Pwd string            `json:"pwd"        validate:"required,min=8,max=64"`
+}
+
+type VMEdit struct {
+	Name string           `json:"name"       validate:"required,min=4,max=256"`
+	Cpus int              `json:"cpus"       validate:"required,gte=1,lte=16"`
+	Ram int               `json:"ram"        validate:"required,gte=512,lte=32768"`
+	Nic vm.NicType        `json:"nic"        validate:"required`
+	UsbDevs []string      `json:"usbDevs"    validate:"required`
+}
+
+type VMAddAccess struct {
+	Access caps.Capabilities `json:"access"  validate:"required"`
+}
+
+type VMExportDir struct {
+	Dir string  `json:"dir"`
+}
diff --git a/src/server/go.mod b/src/server/go.mod
index b7baa9dbcc89c88ab2a048330c733fc9246d0672..9a839d7bc4c62c00a9fc3f1b7e7d942ba2138ca8 100644
--- a/src/server/go.mod
+++ b/src/server/go.mod
@@ -6,6 +6,8 @@ replace nexus-common/template => ../common/template
 
 replace nexus-common/vm => ../common/vm
 
+replace nexus-common/params => ../common/params
+
 replace nexus-common/caps => ../common/caps
 
 replace nexus-server/consts => ./consts
@@ -62,6 +64,7 @@ require (
 	golang.org/x/text v0.3.7 // indirect
 	golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 // indirect
 	nexus-common/caps v0.0.0-00010101000000-000000000000 // indirect
+	nexus-common/params v0.0.0-00010101000000-000000000000 // indirect
 	nexus-common/template v0.0.0-00010101000000-000000000000 // indirect
 	nexus-common/vm v0.0.0-00010101000000-000000000000 // indirect
 	nexus-server/exec v0.0.0-00010101000000-000000000000 // indirect
diff --git a/src/server/router/routerTemplates.go b/src/server/router/routerTemplates.go
index 78042919222bd19ee0a776b4b949e31571385c2c..2038ae72058721041d60f17f87b0c37e5dc5fb6d 100644
--- a/src/server/router/routerTemplates.go
+++ b/src/server/router/routerTemplates.go
@@ -6,6 +6,7 @@ import (
     "net/http"
     "path/filepath"
     "nexus-common/caps"
+    "nexus-common/params"
     "nexus-server/vms"
     "nexus-server/paths"
     "nexus-server/users"
@@ -66,13 +67,8 @@ func (r *RouterTemplates)CreateTemplateFromVM(c echo.Context) error {
         return echo.NewHTTPError(http.StatusUnauthorized, msgInsufficientCaps)
     }
 
-    // Deserializes and validates the client's parameters.
-    type Parameters struct {
-        VMID uuid.UUID      `json:"vmID" validate:"required"`
-        Name string         `json:"name" validate:"required,min=2"`
-        Access string       `json:"access" validate:"required,min=4"`
-    }
-    p := new(Parameters)
+    // Deserializes and validates client's parameters.
+    p := new(params.TplCreate)
     if err := decodeJson(c, &p); err != nil {
         return echo.NewHTTPError(http.StatusBadRequest, err.Error())
     }
@@ -243,14 +239,10 @@ func (r *RouterTemplates)EditTemplateByID(c echo.Context) error {
         return echo.NewHTTPError(http.StatusBadRequest, err.Error())
     }
 
-    // Deserializes and validates the client's parameters.
+    // Deserializes and validates client's parameters.
     // Given these parameters are optional, we can't use a validator on them.
     // Validation is performed in templates.EditTemplate() instead.
-    type Parameters struct {
-        Name   string          `json:"name"`
-        Access string          `json:"access"`
-    }
-    p := new(Parameters)
+    p := new(params.TplEdit)
 
     if user.HasCapability(caps.CAP_TPL_EDIT_ANY) {
         if err := decodeJson(c, &p); err != nil {
diff --git a/src/server/router/routerUsers.go b/src/server/router/routerUsers.go
index e68af79c85f969b49f25d0350c2eb2799cf4b5ad..a2f3c0866a033035b541e6593dac90832ddbb697 100644
--- a/src/server/router/routerUsers.go
+++ b/src/server/router/routerUsers.go
@@ -3,6 +3,7 @@ package router
 import (
     "net/http"
     "nexus-common/caps"
+    "nexus-common/params"
     "nexus-server/users"
     "nexus-server/utils"
     "github.com/labstack/echo/v4"
@@ -128,18 +129,14 @@ func (r *RouterUsers) SetUserCaps(c echo.Context) error {
         return echo.NewHTTPError(http.StatusUnauthorized, msgInsufficientCaps)
     }
 
-    // Deserializes and validates the client's parameters.
-    type Parameters struct {
-        Caps caps.Capabilities
-    }
-    params := &Parameters{make(caps.Capabilities)}
-
-    if err := decodeJson(c, &params); err != nil {
+    // Deserializes and validates client's parameters.
+    p := new(params.UserSetCaps)
+    if err := decodeJson(c, &p); err != nil {
         return echo.NewHTTPError(http.StatusBadRequest, err.Error())
     }
 
     // Checks capabilities are valid.
-    if err := caps.ValidateUserCaps(params.Caps); err != nil {
+    if err := caps.ValidateUserCaps(p.Caps); err != nil {
         return echo.NewHTTPError(http.StatusBadRequest, err.Error())
     }
 
@@ -150,7 +147,7 @@ func (r *RouterUsers) SetUserCaps(c echo.Context) error {
     }
 
     // Updates the user's capabilities.
-    userToUpdate.Caps = params.Caps
+    userToUpdate.Caps = p.Caps
 
     // Updates user and saves the new user file.
     if err = r.users.UpdateUser(&userToUpdate); err != nil {
@@ -163,19 +160,14 @@ func (r *RouterUsers) SetUserCaps(c echo.Context) error {
 // Update the logged user's password.
 // curl --cacert ca.pem -X PUT http://localhost:1077/users/pwd -H 'Content-Type: application/json' -d '{"pwd": "new_password"}' -H "Authorization: Bearer <AccessToken>"
 func (r *RouterUsers) SetUserPwd(c echo.Context) error {
-    // Deserializes the client's parameters.
-    type Parameters struct {
-        Pwd string `json:"pwd" validate:"required,min=8"`
-    }
-    params := &Parameters{}
-
-    // Deserializes the JSON body and checks its validity.
-    if err := decodeJson(c, &params); err != nil {
+    // Deserializes and validates client's parameters.
+    p := new(params.UserSetPwd)
+    if err := decodeJson(c, &p); err != nil {
         return echo.NewHTTPError(http.StatusBadRequest, err.Error())
     }
 
     // Checks the new password is valid.
-    if err := validator.New().Struct(params); err != nil {
+    if err := validator.New().Struct(p); err != nil {
         return echo.NewHTTPError(http.StatusBadRequest, err.Error())
     }
 
@@ -186,7 +178,7 @@ func (r *RouterUsers) SetUserPwd(c echo.Context) error {
     }
 
     // Hashes and udpates the user's password.
-    user.Pwd = utils.HashPassword(params.Pwd)
+    user.Pwd = utils.HashPassword(p.Pwd)
 
     // Updates user and saves the new user file.
     if err = r.users.UpdateUser(user); err != nil {
diff --git a/src/server/router/routerVMs.go b/src/server/router/routerVMs.go
index 06641342fda1c5a2780093f8bb09f83fed1f6980..018c56c4a9b7a2290b9a8cb61ba9063d4bf0c5b2 100644
--- a/src/server/router/routerVMs.go
+++ b/src/server/router/routerVMs.go
@@ -6,7 +6,7 @@ import (
     "net/http"
     "path/filepath"
     "nexus-common/caps"
-    vmc "nexus-common/vm"
+    "nexus-common/params"
     "nexus-server/vms"
     "nexus-server/users"
     "nexus-server/paths"
@@ -179,15 +179,7 @@ func (r *RouterVMs)CreateVM(c echo.Context) error {
     }
 
     // Deserializes and validates client's parameters.
-    type Parameters struct {
-        Name string           `json:"name"       validate:"required,min=4,max=256"`
-        Cpus int              `json:"cpus"       validate:"required,gte=1,lte=16"`
-        Ram int               `json:"ram"        validate:"required,gte=512,lte=32768"`
-        Nic vmc.NicType       `json:"nic"        validate:"required`
-        UsbDevs []string      `json:"usbDevs"    validate:"required`
-        TemplateID uuid.UUID  `json:"templateID" validate:"required"`
-    }
-    p := new(Parameters)
+    p := new(params.VMCreate)
     if err := decodeJson(c, &p); err != nil {
         return echo.NewHTTPError(http.StatusBadRequest, err.Error())
     }
@@ -243,16 +235,12 @@ func (r *RouterVMs)StartVMWithCreds(c echo.Context) error {
     return r.performVMAction(c, caps.CAP_VM_START_ANY, caps.CAP_VM_START, func(c echo.Context, vm *vms.VM) error {
 
         // Deserializes and validates client's parameters.
-        type Parameters struct {
-            Port int              `json:"port"       validate:"required,gte=1100,lte=65535"`
-            Pwd string            `json:"pwd"        validate:"required,min=8,max=64"`
-        }
-        p := new(Parameters)
+        p := new(params.VMStartWithCreds)
         if err := decodeJson(c, &p); err != nil {
             return echo.NewHTTPError(http.StatusBadRequest, err.Error())
         }
 
-        if err := r.vms.StartVMWithCreds(vm.GetID(), p.Port, p.Pwd); err != nil {
+        if err := r.vms.StartVMWithCreds(vm.GetID(), p.Port, true, p.Pwd); err != nil {
             return echo.NewHTTPError(http.StatusBadRequest, err.Error())
         }
         return c.JSONPretty(http.StatusOK, jsonMsg("OK"), "    ")
@@ -308,17 +296,10 @@ func (r *RouterVMs)RebootVM(c echo.Context) error {
 // curl --cacert ca.pem -X PUT https://localhost:1077/vms/e41f3556-ca24-4658-bd79-8c85bd6bff59 -H 'Content-Type: application/json' -d '{"name":"Edited VM","cpus":1,"ram":2048,"nic":"user","usbDevs":["1307:0165","1234:abcd"]}' -H "Authorization: Bearer <AccessToken>"
 func (r *RouterVMs)EditVMByID(c echo.Context) error {
     return r.performVMAction(c, caps.CAP_VM_EDIT_ANY, caps.CAP_VM_EDIT, func(c echo.Context, vm *vms.VM) error {
-        // Deserializes and validates the client's parameters.
+        // Deserializes and validates client's parameters.
         // Given these parameters are optional, we can't use a validator on them.
         // Validation is performed in vm.EditVM() instead.
-        type Parameters struct {
-            Name string           `json:"name"       validate:"required,min=4,max=256"`
-            Cpus int              `json:"cpus"       validate:"required,gte=1,lte=16"`
-            Ram int               `json:"ram"        validate:"required,gte=512,lte=32768"`
-            Nic vmc.NicType       `json:"nic"        validate:"required`
-            UsbDevs []string      `json:"usbDevs"    validate:"required`
-        }
-        p := new(Parameters)
+        p := new(params.VMEdit)
         if err := decodeJson(c, &p); err != nil {
             return echo.NewHTTPError(http.StatusBadRequest, err.Error())
         }
@@ -368,19 +349,16 @@ func (r *RouterVMs)SetVMAccessForUser(c echo.Context) error {
         }
     }
 
-    // Deserializes and validates the client's parameters.
-    type Parameters struct {
-        Access caps.Capabilities `json:"access"  validate:"required"`
-    }
-    params := new(Parameters)
-    if err := decodeJson(c, &params); err != nil {
+    // Deserializes and validates client's parameters.
+    p := new(params.VMAddAccess)
+    if err := decodeJson(c, &p); err != nil {
         return echo.NewHTTPError(http.StatusBadRequest, err.Error())
     }
-    if err := validator.New().Struct(params); err != nil {
+    if err := validator.New().Struct(p); err != nil {
         return echo.NewHTTPError(http.StatusBadRequest, err.Error())
     }
 
-    if err = r.vms.SetVMAccess(vmID, user.Email, email, params.Access); err != nil {
+    if err = r.vms.SetVMAccess(vmID, user.Email, email, p.Access); err != nil {
         return echo.NewHTTPError(http.StatusBadRequest, err.Error())
     }
 
@@ -438,10 +416,7 @@ func (r *RouterVMs)DeleteVMAccessForUser(c echo.Context) error {
 func (r *RouterVMs)ExportVMDir(c echo.Context) error {
     return r.performVMAction(c, caps.CAP_VM_READFS_ANY, caps.CAP_VM_READFS, func(c echo.Context, vm *vms.VM) error {
         // Deserializes and validates the client's parameter.
-        type Parameters struct {
-            Dir string  `json:"dir"`
-        }
-        p := new(Parameters)
+        p := new(params.VMExportDir)
         if err := decodeJson(c, &p); err != nil {
             return echo.NewHTTPError(http.StatusBadRequest, err.Error())
         }
diff --git a/src/server/version/version.go b/src/server/version/version.go
index 8ead9f3ce61a9819c169a0aecff61073339a34c1..4e448ea6c526b0fd90713186b54848bca27ce4b1 100644
--- a/src/server/version/version.go
+++ b/src/server/version/version.go
@@ -7,7 +7,7 @@ import (
 const (
     major  = 1
     minor  = 8
-    bugfix = 0
+    bugfix = 1
 )
 
 type Version struct {
diff --git a/src/server/vms/vms.go b/src/server/vms/vms.go
index 15447add12a3da1a9972cebf8fb5c34b21412db6..438bf6c5c8d010cfa1c200d8c7fe831178a4a93f 100644
--- a/src/server/vms/vms.go
+++ b/src/server/vms/vms.go
@@ -90,6 +90,7 @@ func InitVMs() error {
 // Returns the list of serialized VMs for which VMKeeperFn returns true.
 func (vms *VMs)GetNetworkSerializedVMs(keepFn VMKeeperFn) []vm.VMNetworkSerialized {
     vms.rwlock.RLock()
+
     list := []vm.VMNetworkSerialized{}
     for _, vm := range vms.m {
         vm.mutex.Lock()
@@ -173,16 +174,12 @@ func (vms *VMs)AddVM(vm *VM) error {
 }
 
 // Starts a VM by its ID, using the specified port and password.
-func (vms *VMs)StartVMWithCreds(vmID uuid.UUID, port int, pwd string) error {
+// If checkPort is true, a check is performed on the specified port and if it is already
+// in use, the function fails and returns a corresponding error.
+func (vms *VMs)StartVMWithCreds(vmID uuid.UUID, port int, checkPort bool, pwd string) error {
     vms.rwlock.Lock()
     defer vms.rwlock.Unlock()
 
-    if vms.usedPorts[port] || !utils.IsPortAvailable(port) {
-        return errors.New("Failed starting VM: port already in use")
-    } else {
-        vms.usedPorts[port] = true
-    }
-
     vm, err := vms.getVMUnsafe(vmID)
     if err != nil {
         return err
@@ -195,8 +192,21 @@ func (vms *VMs)StartVMWithCreds(vmID uuid.UUID, port int, pwd string) error {
         return errors.New("Failed starting VM: VM already running")
     }
 
+    if checkPort {
+        if vms.usedPorts[port] {
+            return errors.New("Failed starting VM: port already in use")
+        } else if !utils.IsPortAvailable(port) {
+            return errors.New("Failed starting VM: port not available")
+        } else {
+            vms.usedPorts[port] = true
+        }
+    } else {
+        vms.usedPorts[port] = true
+    }
+
     totalRAM, availRAM, err := utils.GetRAM()
     if err != nil {
+        vms.usedPorts[port] = false
         return errors.New("Failed starting VM: failed obtaining memory info: "+err.Error())
     }
 
@@ -209,42 +219,51 @@ func (vms *VMs)StartVMWithCreds(vmID uuid.UUID, port int, pwd string) error {
     // otherwise, refuses to run it in order to avoid RAM saturation.
     if availRAM - vms.usedRAM <= int(math.Round(float64(totalRAM)*(1.-c.RamUsageLimit))) {
         vms.usedRAM -= estimatedVmRAM
+        vms.usedPorts[port] = false
         return errors.New("Failed starting VM: insufficient free RAM")
     }
 
     // This callback is called once the VM started with vm.start terminates.
     endofExecFn := func (vm *VM) {
+        vms.rwlock.Lock()
+        vms.usedPorts[port] = false
+        vms.usedRAM -= estimatedVmRAM
+        vms.rwlock.Unlock()
         vm.mutex.Lock()
         vm.removeSecretFile()
         vm.resetStates()
         vm.mutex.Unlock()
-        vms.rwlock.Lock()
-        vms.usedPorts[vm.Run.Port] = false
-        vms.usedRAM -= estimatedVmRAM
-        vms.rwlock.Unlock()
     }
 
     if err = vm.start(port, pwd, endofExecFn); err != nil {
+        vms.usedPorts[port] = false
         return err
     }
     return nil
 }
 
-// Starts a VM by its ID using randomly generated port number and password.
-// Returns the port on which the VM is running and the access password.
-func (vms *VMs)StartVM(vmID uuid.UUID) (int, string, error) {
+// Allocates and returns a free port randomly chosen between VMSpiceMinPort and
+// VMSpiceMaxPort (inclusive).
+// Beware: this function updates the vms map.
+func (vms *VMs)allocateFreeRandomPort() int {
+    vms.rwlock.Lock()
+    defer vms.rwlock.Unlock()
 
-    // Locates a free port randomly chosen between VMSpiceMinPort and VMSpiceMaxPort (inclusive).
-    var port int
     for {
-        port = utils.Rand(c.VMSpiceMinPort, c.VMSpiceMaxPort)
+        port := utils.Rand(c.VMSpiceMinPort, c.VMSpiceMaxPort)
         if !vms.usedPorts[port] {
             if utils.IsPortAvailable(port) {
                 vms.usedPorts[port] = true
-                break
+                return port
             }
         }
     }
+}
+
+// Starts a VM by its ID using randomly generated port number and password.
+// Returns the port on which the VM is running and the access password.
+func (vms *VMs)StartVM(vmID uuid.UUID) (int, string, error) {
+    port := vms.allocateFreeRandomPort()
 
     // Randomly generates a 8 characters long password with 4 digits, 0 symbols,
     // allowing upper and lower case letters, disallowing repeat characters.
@@ -254,7 +273,7 @@ func (vms *VMs)StartVM(vmID uuid.UUID) (int, string, error) {
         return -1, "", errors.New("Failed starting VM: password generation error: "+err.Error())
     }
 
-    if err = vms.StartVMWithCreds(vmID, port, pwd); err != nil {
+    if err = vms.StartVMWithCreds(vmID, port, false, pwd); err != nil {
         return -1, "", err
     }
     return port, pwd, nil