Repository: threefoldtech/zos
Pull request #1273 (2021-05-17 13:32:25)

Zos3/unify size unit
The idea behind this PR is to unify the "capacity" calculations so code and documents does not become too complex. now all calculations are using a new type "Unit" a single unit now is now equal to 1 byte. but changing that in the future should be easy by only modifying the multiplications factors (Gigabyte, Megabyte, etc...)

Some changes in this PR does not directly relate to the change, but are smaller bug fixes that surfaced up during testing.


Patch:
diff --git a/client/node.go b/client/node.go
index f4538ef8..6185e0e0 100644
--- a/client/node.go
+++ b/client/node.go
@@ -55,7 +55,7 @@ func (n *NodeClient) response(r *http.Response, o interface{}, codes ...int) err
 }
 
 func (n *NodeClient) url(path ...string) string {
-	url := "http://[" + n.ip.String() + "]:2021/api/v1/" + filepath.Join(path...) + "/"
+	url := "http://[" + n.ip.String() + "]:2021/api/v1/" + filepath.Join(path...)
 	return url
 }
 
@@ -64,10 +64,6 @@ func (n *NodeClient) url(path ...string) string {
 // deployed. the user then can pull on the workload status until it passes (or fail)
 func (n *NodeClient) Deploy(dl *gridtypes.Deployment, update bool) error {
 	dl.TwinID = n.client.id
-	// if err := dl.Sign(n.client.sk); err != nil {
-	// 	return wid, errors.Wrap(err, "failed to sign the workload")
-	// }
-
 	var buf bytes.Buffer
 
 	if err := json.NewEncoder(&buf).Encode(dl); err != nil {
@@ -127,8 +123,8 @@ func (n *NodeClient) Get(twin, deployment uint32) (dl gridtypes.Deployment, err
 }
 
 // Delete deletes a workload by id
-func (n *NodeClient) Delete(wid string) (err error) {
-	url := n.url("deployment", wid)
+func (n *NodeClient) Delete(twin, deployment uint32) (err error) {
+	url := n.url("deployment", fmt.Sprint(twin), fmt.Sprint(deployment))
 
 	request, err := http.NewRequest(http.MethodDelete, url, nil)
 	if err != nil {
@@ -144,7 +140,7 @@ func (n *NodeClient) Delete(wid string) (err error) {
 		return err
 	}
 
-	if err := n.response(response, &wid, http.StatusOK); err != nil {
+	if err := n.response(response, nil, http.StatusAccepted); err != nil {
 		return err
 	}
 
diff --git a/cmds/modules/capacityd/register.go b/cmds/modules/capacityd/register.go
index 562a13ba..ca22fd83 100644
--- a/cmds/modules/capacityd/register.go
+++ b/cmds/modules/capacityd/register.go
@@ -37,9 +37,9 @@ func registration(ctx context.Context, cl zbus.Client) error {
 
 	log.Debug().
 		Uint64("cru", cap.CRU).
-		Uint64("mru", cap.MRU).
-		Uint64("sru", cap.SRU).
-		Uint64("hru", cap.HRU).
+		Uint64("mru", uint64(cap.MRU)).
+		Uint64("sru", uint64(cap.SRU)).
+		Uint64("hru", uint64(cap.HRU)).
 		Msg("node capacity")
 
 	fm, err := env.FarmerClient()
diff --git a/cmds/modules/provisiond/main.go b/cmds/modules/provisiond/main.go
index 90828f23..e7444419 100644
--- a/cmds/modules/provisiond/main.go
+++ b/cmds/modules/provisiond/main.go
@@ -9,6 +9,7 @@ import (
 	"time"
 
 	"github.com/cenkalti/backoff/v3"
+	"github.com/gorilla/handlers"
 	"github.com/gorilla/mux"
 	"github.com/pkg/errors"
 	"github.com/rusart/muxprom"
@@ -142,16 +143,16 @@ func action(cli *cli.Context) error {
 
 	provisioners := primitives.NewPrimitivesProvisioner(cl)
 
-	// update initial capacity with
-	reserved, err := getNodeReserved(cl)
-	if err != nil {
-		return errors.Wrap(err, "failed to get node reserved capacity")
-	}
 	cap, err := capacity.NewResourceOracle(stubs.NewStorageModuleStub(cl)).Total()
 	if err != nil {
 		return errors.Wrap(err, "failed to get node capacity")
 	}
 
+	// update initial capacity with
+	reserved, err := getNodeReserved(cl, cap)
+	if err != nil {
+		return errors.Wrap(err, "failed to get node reserved capacity")
+	}
 	var current gridtypes.Capacity
 	if !app.IsFirstBoot(module) {
 		// if this is the first boot of this module.
@@ -273,9 +274,16 @@ func action(cli *cli.Context) error {
 
 	// register static files
 	v1.PathPrefix("").Handler(http.StripPrefix("/api/v1", http.FileServer(http.FS(swaggerFs))))
+	r := handlers.LoggingHandler(os.Stderr, router)
+	r = handlers.CORS(
+		handlers.AllowedOrigins([]string{"*"}),
+		handlers.AllowedHeaders([]string{"Content-Type"}),
+		handlers.ExposedHeaders([]string{"Pages"}),
+	)(r)
+
 	httpServer := &http.Server{
 		Addr:    httpAddr,
-		Handler: router,
+		Handler: r,
 	}
 
 	utils.OnDone(ctx, func(_ error) {
@@ -291,14 +299,15 @@ func action(cli *cli.Context) error {
 	return nil
 }
 
-func getNodeReserved(cl zbus.Client) (counter primitives.Counters, err error) {
+func getNodeReserved(cl zbus.Client, available gridtypes.Capacity) (counter primitives.Counters, err error) {
+	// fill in reserved storage
 	storage := stubs.NewStorageModuleStub(cl)
 	fs, err := storage.GetCacheFS(context.TODO())
 	if err != nil {
 		return counter, err
 	}
 
-	var v *primitives.AtomicValue
+	var v *primitives.AtomicUnit
 	switch fs.DiskType {
 	case zos.HDDDevice:
 		v = &counter.HRU
@@ -308,8 +317,16 @@ func getNodeReserved(cl zbus.Client) (counter primitives.Counters, err error) {
 		return counter, fmt.Errorf("unknown cache disk type '%s'", fs.DiskType)
 	}
 
-	v.Increment(fs.Usage.Size / gib)
-	counter.MRU.Increment(2)
+	v.Increment(fs.Usage.Size)
+
+	// we reserve 10% of memory to ZOS itself, with a min of 2G
+	counter.MRU.Increment(
+		gridtypes.Max(
+			available.MRU*10/100,
+			2*gridtypes.Gigabyte,
+		),
+	)
+
 	return
 }
 
diff --git a/go.mod b/go.mod
index 3aed2f05..cdaa8959 100644
--- a/go.mod
+++ b/go.mod
@@ -32,6 +32,7 @@ require (
 	github.com/gomodule/redigo v2.0.0+incompatible
 	github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
 	github.com/google/uuid v1.2.0
+	github.com/gorilla/handlers v1.5.1 // indirect
 	github.com/gorilla/mux v1.8.0
 	github.com/hanwen/go-fuse/v2 v2.1.0 // indirect
 	github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d
@@ -44,7 +45,7 @@ require (
 	github.com/mattn/go-sqlite3 v1.14.7 // indirect
 	github.com/mdlayher/netlink v1.4.0 // indirect
 	github.com/mitchellh/go-wordwrap v1.0.1 // indirect
-	github.com/nsf/termbox-go v1.1.0 // indirect
+	github.com/nsf/termbox-go v1.1.1 // indirect
 	github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d
 	github.com/patrickmn/go-cache v2.1.0+incompatible
 	github.com/pkg/errors v0.9.1
diff --git a/go.sum b/go.sum
index cde4c80c..fe2eb8c1 100644
--- a/go.sum
+++ b/go.sum
@@ -388,6 +388,8 @@ github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi
 github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
 github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
+github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
+github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
 github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
 github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
 github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
@@ -545,6 +547,8 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORR
 github.com/gordonklaus/ineffassign v0.0.0-20200809085317-e36bfde3bb78/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
 github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
 github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
+github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
+github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
 github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
 github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
 github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
@@ -823,6 +827,8 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA
 github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
 github.com/nsf/termbox-go v1.1.0 h1:R+GIXVMaDxDQ2VHem5vO5h0mI8ZxLECTUNw1ZzXODzI=
 github.com/nsf/termbox-go v1.1.0/go.mod h1:T0cTdVuOwf7pHQNtfhnEbzHbcNyCEcVU4YPpouCbVxo=
+github.com/nsf/termbox-go v1.1.1 h1:nksUPLCb73Q++DwbYUBEglYBRPZyoXJdrj5L+TkjyZY=
+github.com/nsf/termbox-go v1.1.1/go.mod h1:T0cTdVuOwf7pHQNtfhnEbzHbcNyCEcVU4YPpouCbVxo=
 github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
 github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
 github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
diff --git a/pkg/capacity/resource.go b/pkg/capacity/resource.go
index 44b1d566..ff024da1 100644
--- a/pkg/capacity/resource.go
+++ b/pkg/capacity/resource.go
@@ -6,6 +6,7 @@ import (
 
 	"github.com/shirou/gopsutil/cpu"
 	"github.com/shirou/gopsutil/mem"
+	"github.com/threefoldtech/zos/pkg/gridtypes"
 	"github.com/threefoldtech/zos/pkg/gridtypes/zos"
 )
 
@@ -14,30 +15,31 @@ func (r *ResourceOracle) cru() (uint64, error) {
 	return uint64(n), err
 }
 
-func (r *ResourceOracle) mru() (uint64, error) {
+func (r *ResourceOracle) mru() (gridtypes.Unit, error) {
 	vm, err := mem.VirtualMemory()
 	if err != nil {
 		return 0, err
 	}
 
-	total := float64(vm.Total) / float64(GiB)
-	return uint64(math.Round(total)), nil
+	// we round the value to nearest Gigabyte
+	total := math.Round(float64(vm.Total)/float64(gridtypes.Gigabyte)) * float64(gridtypes.Gigabyte)
+	return gridtypes.Unit(total), nil
 }
 
-func (r *ResourceOracle) sru() (uint64, error) {
+func (r *ResourceOracle) sru() (gridtypes.Unit, error) {
 	total, err := r.storage.Total(context.TODO(), zos.SSDDevice)
 	if err != nil {
 		return 0, err
 	}
 
-	return total / GiB, nil
+	return gridtypes.Unit(total), nil
 }
 
-func (r *ResourceOracle) hru() (uint64, error) {
+func (r *ResourceOracle) hru() (gridtypes.Unit, error) {
 	total, err := r.storage.Total(context.TODO(), zos.HDDDevice)
 	if err != nil {
 		return 0, err
 	}
 
-	return total / GiB, nil
+	return gridtypes.Unit(total), nil
 }
diff --git a/pkg/capacity/size.go b/pkg/capacity/size.go
deleted file mode 100644
index cd43438f..00000000
--- a/pkg/capacity/size.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package capacity
-
-// Storage size
-const (
-	// Decimal
-
-	KB = 1000
-	MB = 1000 * KB
-	GB = 1000 * MB
-	TB = 1000 * GB
-	PB = 1000 * TB
-
-	// Binary
-
-	KiB = 1024
-	MiB = 1024 * KiB
-	GiB = 1024 * MiB
-	TiB = 1024 * GiB
-	PiB = 1024 * TiB
-)
diff --git a/pkg/container.go b/pkg/container.go
index f4947cfe..f47fbdae 100644
--- a/pkg/container.go
+++ b/pkg/container.go
@@ -5,6 +5,7 @@ package pkg
 
 import (
 	"github.com/threefoldtech/zos/pkg/container/logger"
+	"github.com/threefoldtech/zos/pkg/gridtypes"
 	"github.com/threefoldtech/zos/pkg/gridtypes/zos"
 )
 
@@ -49,8 +50,8 @@ type Container struct {
 	Interactive bool
 	// CPU count limit
 	CPU uint
-	// Memory limit in bytes
-	Memory uint64
+	// Memory limit in
+	Memory gridtypes.Unit
 	// Logs backends
 	Logs []logger.Logs
 	// Stats container metrics backend
diff --git a/pkg/container/container.go b/pkg/container/container.go
index 82055cf0..bb4663d4 100644
--- a/pkg/container/container.go
+++ b/pkg/container/container.go
@@ -182,7 +182,7 @@ func (c *Module) Run(ns string, data pkg.Container) (id pkg.ContainerID, err err
 		removeRunMount(),
 		withNetworkNamespace(data.Network.Namespace),
 		withMounts(data.Mounts),
-		WithMemoryLimit(data.Memory),
+		WithMemoryLimit(uint64(data.Memory)),
 		WithCPUCount(data.CPU),
 	}
 
diff --git a/pkg/flist.go b/pkg/flist.go
index ee396778..9ca3499a 100644
--- a/pkg/flist.go
+++ b/pkg/flist.go
@@ -1,6 +1,7 @@
 package pkg
 
 import (
+	"github.com/threefoldtech/zos/pkg/gridtypes"
 	"github.com/threefoldtech/zos/pkg/gridtypes/zos"
 )
 
@@ -12,7 +13,7 @@ var (
 	//DefaultMountOptions has sane values for mount
 	DefaultMountOptions = MountOptions{
 		ReadOnly: false,
-		Limit:    256, //Mib
+		Limit:    256 * gridtypes.Megabyte, //Mib
 		Type:     zos.SSDDevice,
 	}
 
@@ -26,8 +27,8 @@ var (
 type MountOptions struct {
 	// ReadOnly
 	ReadOnly bool
-	// Limit size of read-write layer in Mib
-	Limit uint64
+	// Limit size of read-write layer
+	Limit gridtypes.Unit
 	// Type of disk to use
 	Type zos.DeviceType
 }
diff --git a/pkg/flist/flist.go b/pkg/flist/flist.go
index 6401ab96..9ed23f54 100644
--- a/pkg/flist/flist.go
+++ b/pkg/flist/flist.go
@@ -23,6 +23,7 @@ import (
 	"github.com/rs/zerolog/log"
 	"github.com/threefoldtech/zos/pkg"
 	"github.com/threefoldtech/zos/pkg/environment"
+	"github.com/threefoldtech/zos/pkg/gridtypes"
 	"github.com/threefoldtech/zos/pkg/stubs"
 )
 
@@ -49,7 +50,7 @@ type volumeAllocator interface {
 	// more space is available in such a pool, `ErrNotEnoughSpace` is returned.
 	// It is up to the caller to handle such a situation and decide if he wants
 	// to try again on a different devicetype
-	CreateFilesystem(ctx context.Context, name string, size uint64, poolType pkg.DeviceType) (pkg.Filesystem, error)
+	CreateFilesystem(ctx context.Context, name string, size gridtypes.Unit, poolType pkg.DeviceType) (pkg.Filesystem, error)
 
 	// ReleaseFilesystem signals that the named filesystem is no longer needed.
 	// The filesystem will be unmounted and subsequently removed.
@@ -233,7 +234,7 @@ func (f *flistModule) mount(name, url, storage string, opts pkg.MountOptions) (s
 				return "", fmt.Errorf("invalid mount option, missing disk type and/or size")
 			}
 			newAllocation = true
-			backend, err = f.storage.CreateFilesystem(ctx, name, opts.Limit*mib, opts.Type)
+			backend, err = f.storage.CreateFilesystem(ctx, name, opts.Limit, opts.Type)
 			if err != nil {
 				return "", errors.Wrap(err, "failed to create read-write subvolume for 0-fs")
 			}
diff --git a/pkg/gridtypes/common.go b/pkg/gridtypes/common.go
index 90930344..3199a289 100644
--- a/pkg/gridtypes/common.go
+++ b/pkg/gridtypes/common.go
@@ -7,6 +7,41 @@ import (
 	"time"
 )
 
+// Unit defines a capacity unit in "bytes"
+// Any "value" of type Unit must be in bytes only
+// hence use the Unit mutliplies below to set the
+// write value
+type Unit uint64
+
+const (
+	// Kilobyte unit multiplier
+	Kilobyte Unit = 1024
+	// Megabyte unit multiplier
+	Megabyte Unit = 1024 * Kilobyte
+	// Gigabyte unit multiplier
+	Gigabyte Unit = 1024 * Megabyte
+	// Terabyte unit multiplier
+	Terabyte Unit = 1024 * Gigabyte
+)
+
+// Max return max of u, and v
+func Max(u, v Unit) Unit {
+	if u > v {
+		return u
+	}
+
+	return v
+}
+
+// Min return min of u, and v
+func Min(u, v Unit) Unit {
+	if u < v {
+		return u
+	}
+
+	return v
+}
+
 // Timestamp type
 type Timestamp int64
 
diff --git a/pkg/gridtypes/workload.go b/pkg/gridtypes/workload.go
index 6f3cd83e..fd162973 100644
--- a/pkg/gridtypes/workload.go
+++ b/pkg/gridtypes/workload.go
@@ -57,9 +57,9 @@ func (t WorkloadType) String() string {
 //Capacity the expected capacity of a workload
 type Capacity struct {
 	CRU   uint64 `json:"cru"`
-	SRU   uint64 `json:"sru"`
-	HRU   uint64 `json:"hru"`
-	MRU   uint64 `json:"mru"`
+	SRU   Unit   `json:"sru"`
+	HRU   Unit   `json:"hru"`
+	MRU   Unit   `json:"mru"`
 	IPV4U uint64 `json:"ipv4u"`
 }
 
diff --git a/pkg/gridtypes/zos/container.go b/pkg/gridtypes/zos/container.go
index b94d51ce..c61e5f75 100644
--- a/pkg/gridtypes/zos/container.go
+++ b/pkg/gridtypes/zos/container.go
@@ -3,7 +3,6 @@ package zos
 import (
 	"fmt"
 	"io"
-	"math"
 	"net"
 	"sort"
 
@@ -84,12 +83,12 @@ type Stats struct {
 type ContainerCapacity struct {
 	// Number of CPU
 	CPU uint `json:"cpu"`
-	// Memory in MiB
-	Memory uint64 `json:"memory"`
+	// Memory
+	Memory gridtypes.Unit `json:"memory"`
 	//DiskType is the type of disk to use for root fs
 	DiskType DeviceType `json:"disk_type"`
-	// DiskSize of the root fs in MiB
-	DiskSize uint64 `json:"disk_size"`
+	// DiskSize of the root fs
+	DiskSize gridtypes.Unit `json:"disk_size"`
 }
 
 // Challenge creates signature challenge
@@ -112,16 +111,14 @@ func (c ContainerCapacity) Challenge(w io.Writer) error {
 func (c ContainerCapacity) capacity() (gridtypes.Capacity, error) {
 	rsu := gridtypes.Capacity{
 		CRU: uint64(c.CPU),
-		// round mru to 4 digits precision
-		MRU: uint64(math.Round(float64(c.Memory)/1024*10000) / 10000),
+		MRU: c.Memory,
 	}
-	storageSize := math.Round(float64(c.DiskSize)/1024*10000) / 10000
-	storageSize = math.Max(0, storageSize-50) // we offer the 50 first GB of storage for container root
+	storageSize := c.DiskSize
 	switch c.DiskType {
 	case HDDDevice:
-		rsu.HRU = uint64(storageSize)
+		rsu.HRU = storageSize
 	case SSDDevice:
-		rsu.SRU = uint64(storageSize)
+		rsu.SRU = storageSize
 	}
 
 	return rsu, nil
diff --git a/pkg/gridtypes/zos/volume.go b/pkg/gridtypes/zos/volume.go
index 205cdacd..bc530ddb 100644
--- a/pkg/gridtypes/zos/volume.go
+++ b/pkg/gridtypes/zos/volume.go
@@ -9,8 +9,8 @@ import (
 
 // Volume defines a mount point
 type Volume struct {
-	// Size of the volume in GiB
-	Size uint64 `json:"size"`
+	// Size of the volume
+	Size gridtypes.Unit `json:"size"`
 	// Type of disk underneath the volume
 	Type DeviceType `json:"type"`
 }
diff --git a/pkg/gridtypes/zos/zdb.go b/pkg/gridtypes/zos/zdb.go
index 21985026..43b8f656 100644
--- a/pkg/gridtypes/zos/zdb.go
+++ b/pkg/gridtypes/zos/zdb.go
@@ -31,11 +31,11 @@ func (m ZDBMode) Valid() error {
 
 // ZDB namespace creation info
 type ZDB struct {
-	Size     uint64     `json:"size"`
-	Mode     ZDBMode    `json:"mode"`
-	Password string     `json:"password"`
-	DiskType DeviceType `json:"disk_type"`
-	Public   bool       `json:"public"`
+	Size     gridtypes.Unit `json:"size"`
+	Mode     ZDBMode        `json:"mode"`
+	Password string         `json:"password"`
+	DiskType DeviceType     `json:"disk_type"`
+	Public   bool           `json:"public"`
 }
 
 //Valid implementation
diff --git a/pkg/primitives/container.go b/pkg/primitives/container.go
index 410d6266..f9fe14a0 100644
--- a/pkg/primitives/container.go
+++ b/pkg/primitives/container.go
@@ -216,7 +216,7 @@ func (p *Primitives) containerProvisionImpl(ctx context.Context, wl *gridtypes.W
 			Entrypoint:  config.Entrypoint,
 			Interactive: config.Interactive,
 			CPU:         config.ContainerCapacity.CPU,
-			Memory:      config.ContainerCapacity.Memory * mib,
+			Memory:      config.ContainerCapacity.Memory,
 			Logs:        logs,
 			Stats:       config.Stats,
 			Elevated:    elevated,
diff --git a/pkg/primitives/counters.go b/pkg/primitives/counters.go
index da1d4010..435b17a1 100644
--- a/pkg/primitives/counters.go
+++ b/pkg/primitives/counters.go
@@ -6,16 +6,16 @@ import (
 	"github.com/threefoldtech/zos/pkg/gridtypes"
 )
 
-// AtomicValue value for safe increment/decrement
-type AtomicValue uint64
+// AtomicUnit value for safe increment/decrement
+type AtomicUnit gridtypes.Unit
 
 // Increment counter atomically by one
-func (c *AtomicValue) Increment(v uint64) uint64 {
-	return atomic.AddUint64((*uint64)(c), v)
+func (c *AtomicUnit) Increment(v gridtypes.Unit) gridtypes.Unit {
+	return gridtypes.Unit(atomic.AddUint64((*uint64)(c), uint64(v)))
 }
 
 // Decrement counter atomically by one
-func (c *AtomicValue) Decrement(v uint64) uint64 {
+func (c *AtomicUnit) Decrement(v gridtypes.Unit) gridtypes.Unit {
 	// spinlock until the decrement succeeds
 	for {
 		current := c.Current()
@@ -28,15 +28,15 @@ func (c *AtomicValue) Decrement(v uint64) uint64 {
 		n := current - dec
 		// only swap if `current`, and therefore the above calculations,
 		// are still valid
-		if atomic.CompareAndSwapUint64((*uint64)(c), current, n) {
-			return n
+		if atomic.CompareAndSwapUint64((*uint64)(c), uint64(current), uint64(n)) {
+			return gridtypes.Unit(n)
 		}
 	}
 }
 
 // Current returns the current value
-func (c *AtomicValue) Current() uint64 {
-	return atomic.LoadUint64((*uint64)(c))
+func (c *AtomicUnit) Current() gridtypes.Unit {
+	return gridtypes.Unit(atomic.LoadUint64((*uint64)(c)))
 }
 
 // Counters tracks the amount of primitives workload deployed and
@@ -44,11 +44,11 @@ func (c *AtomicValue) Current() uint64 {
 type Counters struct {
 	//types map[gridtypes.WorkloadType]AtomicValue
 
-	SRU  AtomicValue // SSD storage in bytes
-	HRU  AtomicValue // HDD storage in bytes
-	MRU  AtomicValue // Memory storage in bytes
-	CRU  AtomicValue // CPU count absolute
-	IPv4 AtomicValue // IPv4 count absolute
+	SRU  AtomicUnit // SSD storage in bytes
+	HRU  AtomicUnit // HDD storage in bytes
+	MRU  AtomicUnit // Memory storage in bytes
+	CRU  AtomicUnit // CPU count absolute
+	IPv4 AtomicUnit // IPv4 count absolute
 }
 
 const (
@@ -58,18 +58,18 @@ const (
 
 // Increment is called by the provision.Engine when a reservation has been provisionned
 func (c *Counters) Increment(cap gridtypes.Capacity) {
-	c.CRU.Increment(cap.CRU)
+	c.CRU.Increment(gridtypes.Unit(cap.CRU))
 	c.MRU.Increment(cap.MRU)
 	c.SRU.Increment(cap.SRU)
 	c.HRU.Increment(cap.HRU)
-	c.IPv4.Increment(cap.IPV4U)
+	c.IPv4.Increment(gridtypes.Unit(cap.IPV4U))
 }
 
 // Decrement is called by the provision.Engine when a reservation has been decommissioned
 func (c *Counters) Decrement(cap gridtypes.Capacity) {
-	c.CRU.Decrement(cap.CRU)
+	c.CRU.Decrement(gridtypes.Unit(cap.CRU))
 	c.MRU.Decrement(cap.MRU)
 	c.SRU.Decrement(cap.SRU)
 	c.HRU.Decrement(cap.HRU)
-	c.IPv4.Decrement(cap.IPV4U)
+	c.IPv4.Decrement(gridtypes.Unit(cap.IPV4U))
 }
diff --git a/pkg/primitives/kubernetes.go b/pkg/primitives/kubernetes.go
index 46dc46a2..986751a1 100644
--- a/pkg/primitives/kubernetes.go
+++ b/pkg/primitives/kubernetes.go
@@ -85,10 +85,14 @@ func (p *Primitives) kubernetesProvisionImpl(ctx context.Context, wl *gridtypes.
 	result.ID = wl.ID.String()
 	result.IP = config.IP.String()
 
-	cpu, memory, disk, err := vmSize(&config)
+	cap, err := config.Capacity()
 	if err != nil {
 		return result, errors.Wrap(err, "could not interpret vm size")
 	}
+	// cpu, memory, disk, err := vmSize(&config)
+	// if err != nil {
+	// 	return result, errors.Wrap(err, "could not interpret vm size")
+	// }
 
 	if _, err = vm.Inspect(ctx, wl.ID.String()); err == nil {
 		// vm is already running, nothing to do here
@@ -110,7 +114,7 @@ func (p *Primitives) kubernetesProvisionImpl(ctx context.Context, wl *gridtypes.
 		}
 		diskPath = info.Path
 	} else {
-		diskPath, err = storage.Allocate(ctx, diskName, int64(disk))
+		diskPath, err = storage.Allocate(ctx, diskName, cap.SRU)
 		if err != nil {
 			return result, errors.Wrap(err, "failed to reserve filesystem for vm")
 		}
@@ -160,13 +164,13 @@ func (p *Primitives) kubernetesProvisionImpl(ctx context.Context, wl *gridtypes.
 	}
 
 	if needsInstall {
-		if err = p.kubernetesInstall(ctx, wl.ID.String(), cpu, memory, diskPath, imagePath, netInfo, config); err != nil {
+		if err = p.kubernetesInstall(ctx, wl.ID.String(), uint8(cap.CRU), cap.MRU, diskPath, imagePath, netInfo, config); err != nil {
 			vm.Delete(ctx, wl.ID.String())
 			return result, errors.Wrap(err, "failed to install k3s")
 		}
 	}
 
-	err = p.kubernetesRun(ctx, wl.ID.String(), cpu, memory, diskPath, imagePath, netInfo, config)
+	err = p.kubernetesRun(ctx, wl.ID.String(), uint8(cap.CRU), cap.MRU, diskPath, imagePath, netInfo, config)
 	if err != nil {
 		// attempt to delete the vm, should the process still be lingering
 		vm.Delete(ctx, wl.ID.String())
@@ -175,7 +179,7 @@ func (p *Primitives) kubernetesProvisionImpl(ctx context.Context, wl *gridtypes.
 	return result, err
 }
 
-func (p *Primitives) kubernetesInstall(ctx context.Context, name string, cpu uint8, memory uint64, diskPath string, imagePath string, networkInfo pkg.VMNetworkInfo, cfg Kubernetes) error {
+func (p *Primitives) kubernetesInstall(ctx context.Context, name string, cpu uint8, memory gridtypes.Unit, diskPath string, imagePath string, networkInfo pkg.VMNetworkInfo, cfg Kubernetes) error {
 	vm := stubs.NewVMModuleStub(p.zbus)
 
 	cmdline := fmt.Sprintf("console=ttyS0 reboot=k panic=1 k3os.mode=install k3os.install.silent k3os.debug k3os.install.device=/dev/vda k3os.token=%s k3os.k3s_args=\"--flannel-iface=eth0\"", cfg.ClusterSecret)
@@ -212,7 +216,7 @@ func (p *Primitives) kubernetesInstall(ctx context.Context, name string, cpu uin
 	installVM := pkg.VM{
 		Name:        name,
 		CPU:         cpu,
-		Memory:      int64(memory),
+		Memory:      memory,
 		Network:     networkInfo,
 		KernelImage: imagePath + "/k3os-vmlinux",
 		InitrdImage: imagePath + "/k3os-initrd-amd64",
@@ -258,7 +262,7 @@ func (p *Primitives) kubernetesInstall(ctx context.Context, name string, cpu uin
 	return vm.Delete(ctx, name)
 }
 
-func (p *Primitives) kubernetesRun(ctx context.Context, name string, cpu uint8, memory uint64, diskPath string, imagePath string, networkInfo pkg.VMNetworkInfo, cfg Kubernetes) error {
+func (p *Primitives) kubernetesRun(ctx context.Context, name string, cpu uint8, memory gridtypes.Unit, diskPath string, imagePath string, networkInfo pkg.VMNetworkInfo, cfg Kubernetes) error {
 	vm := stubs.NewVMModuleStub(p.zbus)
 
 	disks := make([]pkg.VMDisk, 1)
@@ -268,7 +272,7 @@ func (p *Primitives) kubernetesRun(ctx context.Context, name string, cpu uint8,
 	kubevm := pkg.VM{
 		Name:        name,
 		CPU:         cpu,
-		Memory:      int64(memory),
+		Memory:      memory,
 		Network:     networkInfo,
 		KernelImage: imagePath + "/k3os-vmlinux",
 		InitrdImage: imagePath + "/k3os-initrd-amd64",
@@ -425,14 +429,3 @@ func (p *Primitives) getPubIPConfig(wl *gridtypes.WorkloadWithID, name string) (
 
 	return data.IP.IPNet, data.Gateway, nil
 }
-
-// returns the vCpu's, memory, disksize for a vm size
-// memory and disk size is expressed in MiB
-func vmSize(vm *Kubernetes) (cpu uint8, memory uint64, storage uint64, err error) {
-	cap, err := vm.Capacity()
-	if err != nil {
-		return 0, 0, 0, err
-	}
-
-	return uint8(cap.CRU), cap.MRU * 1024, cap.SRU * 1024, nil
-}
diff --git a/pkg/primitives/statistics.go b/pkg/primitives/statistics.go
index 2f7d35a0..9f930bba 100644
--- a/pkg/primitives/statistics.go
+++ b/pkg/primitives/statistics.go
@@ -11,6 +11,7 @@ import (
 	"github.com/rs/zerolog/log"
 	"github.com/shirou/gopsutil/mem"
 	"github.com/threefoldtech/zos/pkg/gridtypes"
+	"github.com/threefoldtech/zos/pkg/gridtypes/zos"
 	"github.com/threefoldtech/zos/pkg/provision"
 	"github.com/threefoldtech/zos/pkg/provision/mw"
 )
@@ -37,7 +38,7 @@ type Statistics struct {
 	total    gridtypes.Capacity
 	counters Counters
 	reserved Counters
-	mem      uint64
+	mem      gridtypes.Unit
 
 	nodeID string
 }
@@ -53,25 +54,36 @@ func NewStatistics(total, initial gridtypes.Capacity, reserved Counters, nodeID
 	log.Debug().Msgf("initial used capacity %+v", initial)
 	var counters Counters
 	counters.Increment(initial)
-	ram := math.Ceil(float64(vm.Total) / (1024 * 1024 * 1024))
+
 	return &Statistics{
 		inner:    inner,
 		total:    total,
 		counters: counters,
 		reserved: reserved,
-		mem:      uint64(ram),
+		mem:      gridtypes.Unit(vm.Total),
 		nodeID:   nodeID,
 	}
 }
 
 // Current returns the current used capacity
 func (s *Statistics) Current() gridtypes.Capacity {
+	used := s.counters.MRU.Current() + s.reserved.MRU.Current()
+	vm, err := mem.VirtualMemory()
+	if err != nil {
+		// this should never happen
+		panic("failed to get memory consumption")
+	}
+
+	// used memory is maximum of actual used on the node or the
+	// reserved memory by workloads.
+	used = gridtypes.Unit(math.Max(float64(vm.Used), float64(used)))
+
 	return gridtypes.Capacity{
-		CRU:   s.counters.CRU.Current() + s.reserved.CRU.Current(),
-		MRU:   s.counters.MRU.Current() + s.reserved.MRU.Current(),
+		CRU:   uint64(s.counters.CRU.Current() + s.reserved.CRU.Current()),
+		MRU:   used,
 		HRU:   s.counters.HRU.Current() + s.reserved.HRU.Current(),
 		SRU:   s.counters.SRU.Current() + s.reserved.SRU.Current(),
-		IPV4U: s.counters.IPv4.Current(),
+		IPV4U: uint64(s.counters.IPv4.Current()),
 	}
 }
 
@@ -99,6 +111,12 @@ func (s *Statistics) Provision(ctx context.Context, wl *gridtypes.WorkloadWithID
 		return nil, errors.Wrap(err, "failed to calculate workload needed capacity")
 	}
 
+	// we add extra overhead for some workload types here
+	if wl.Type == zos.KubernetesType {
+		// we add the min of 5% of allocated memory or 1G
+		needed.MRU += gridtypes.Min(needed.MRU*5/100, gridtypes.Gigabyte)
+	} // TODO: other types ?
+
 	if err := s.hasEnoughCapacity(&current, &needed); err != nil {
 		return nil, errors.Wrap(err, "failed to satisfy required capacity")
 	}
diff --git a/pkg/primitives/volume.go b/pkg/primitives/volume.go
index 4857fb98..aee60c17 100644
--- a/pkg/primitives/volume.go
+++ b/pkg/primitives/volume.go
@@ -11,11 +11,6 @@ import (
 	"github.com/threefoldtech/zos/pkg/stubs"
 )
 
-const (
-	// gigabyte to byte conversion
-	gigabyte uint64 = 1024 * 1024 * 1024
-)
-
 // Volume defines a mount point
 type Volume = zos.Volume
 
@@ -30,14 +25,14 @@ func (p *Primitives) volumeProvisionImpl(ctx context.Context, wl *gridtypes.Work
 
 	vol.ID = wl.ID.String()
 	storageClient := stubs.NewStorageModuleStub(p.zbus)
-	size := config.Size * gigabyte
+	size := config.Size
 	fs, err := storageClient.Path(ctx, wl.ID.String())
 	if err == nil {
 		// todo: validate that the volume type has not been changed.
 		// filesystem exist. do we need to (resize)
 		log.Info().Stringer("id", wl.ID).Msg("volume already deployed")
 		if fs.Usage.Size != size {
-			log.Info().Stringer("id", wl.ID).Uint64("size", size).Msg("resizing volume")
+			log.Info().Stringer("id", wl.ID).Uint64("size", uint64(size)).Msg("resizing volume")
 			_, err := storageClient.UpdateFilesystem(ctx, wl.ID.String(), size)
 			if err != nil {
 				return vol, err
diff --git a/pkg/primitives/zdb.go b/pkg/primitives/zdb.go
index 8abaad1f..23a1228c 100644
--- a/pkg/primitives/zdb.go
+++ b/pkg/primitives/zdb.go
@@ -50,7 +50,7 @@ func (p *Primitives) zdbProvisionImpl(ctx context.Context, wl *gridtypes.Workloa
 
 	// if we reached here, we need to create the 0-db namespace
 	log.Debug().Msg("allocating storage for namespace")
-	allocation, err := storage.Allocate(ctx, nsID, config.DiskType, config.Size*gigabyte, config.Mode)
+	allocation, err := storage.Allocate(ctx, nsID, config.DiskType, config.Size, config.Mode)
 	if err != nil {
 		return zos.ZDBResult{}, errors.Wrap(err, "failed to allocate storage")
 	}
@@ -117,7 +117,7 @@ func (p *Primitives) zdbRootFS(ctx context.Context) (string, error) {
 
 	for _, typ := range []zos.DeviceType{zos.HDDDevice, zos.SSDDevice} {
 		rootFS, err = flist.Mount(ctx, zdbFlistURL, "", pkg.MountOptions{
-			Limit:    10,
+			Limit:    10 * gridtypes.Megabyte,
 			ReadOnly: false,
 			Type:     typ,
 		})
@@ -335,7 +335,7 @@ func (p *Primitives) createZDBNamespace(containerID pkg.ContainerID, nsID string
 		return errors.Wrapf(err, "failed to make namespace %s public in 0-db: %s", nsID, containerID)
 	}
 
-	if err := zdbCl.NamespaceSetSize(nsID, config.Size*gigabyte); err != nil {
+	if err := zdbCl.NamespaceSetSize(nsID, uint64(config.Size)); err != nil {
 		return errors.Wrapf(err, "failed to set size on namespace %s in 0-db: %s", nsID, containerID)
 	}
 
diff --git a/pkg/provision/api/api.go b/pkg/provision/api/api.go
index 9e84e9aa..2d0774ee 100644
--- a/pkg/provision/api/api.go
+++ b/pkg/provision/api/api.go
@@ -31,7 +31,7 @@ func (a *Workloads) setup(router *mux.Router) error {
 		mw.NewAuthMiddleware(a.engine.Twins()),
 	)
 
-	workloads.Path("/").HandlerFunc(mw.AsHandlerFunc(a.createOrUpdate)).Methods(http.MethodPost, http.MethodPut).Name("workload-create-or-update")
+	workloads.Path("").HandlerFunc(mw.AsHandlerFunc(a.createOrUpdate)).Methods(http.MethodPost, http.MethodPut).Name("workload-create-or-update")
 	workloads.Path("/{twin}/{id}").HandlerFunc(mw.AsHandlerFunc(a.get)).Methods(http.MethodGet).Name("workload-get")
 	workloads.Path("/{twin}/{id}").HandlerFunc(mw.AsHandlerFunc(a.delete)).Methods(http.MethodDelete).Name("workload-delete")
 	return nil
diff --git a/pkg/provision/api/reservation.go b/pkg/provision/api/reservation.go
index 69f78482..d389adb8 100644
--- a/pkg/provision/api/reservation.go
+++ b/pkg/provision/api/reservation.go
@@ -3,6 +3,7 @@ package api
 import (
 	"context"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net/http"
 	"strconv"
@@ -45,6 +46,8 @@ func (a *Workloads) createOrUpdate(request *http.Request) (interface{}, mw.Respo
 
 	if err == context.DeadlineExceeded {
 		return nil, mw.Unavailable(ctx.Err())
+	} else if errors.Is(err, provision.ErrDeploymentUpgradeValidationError) {
+		return nil, mw.BadRequest(err)
 	} else if err != nil {
 		return nil, mw.Error(err)
 	}
@@ -92,6 +95,8 @@ func (a *Workloads) delete(request *http.Request) (interface{}, mw.Response) {
 	err = a.engine.Deprovision(ctx, twin, id, "requested by user")
 	if err == context.DeadlineExceeded {
 		return nil, mw.Unavailable(ctx.Err())
+	} else if errors.Is(err, provision.ErrDeploymentNotExists) {
+		return nil, mw.NotFound(err)
 	} else if err != nil {
 		return nil, mw.Error(err)
 	}
@@ -111,7 +116,7 @@ func (a *Workloads) get(request *http.Request) (interface{}, mw.Response) {
 	}
 
 	deployment, err := a.engine.Storage().Get(twin, id)
-	if err == provision.ErrDeploymentNotExists {
+	if errors.Is(err, provision.ErrDeploymentNotExists) {
 		return nil, mw.NotFound(fmt.Errorf("workload not found"))
 	} else if err != nil {
 		return nil, mw.Error(err)
diff --git a/pkg/provision/engine.go b/pkg/provision/engine.go
index 218ce4ac..018eb29d 100644
--- a/pkg/provision/engine.go
+++ b/pkg/provision/engine.go
@@ -235,6 +235,11 @@ func (e *NativeEngine) Deprovision(ctx context.Context, twin, id uint32, reason
 		return err
 	}
 
+	log.Debug().
+		Uint32("twin", deployment.TwinID).
+		Uint32("deployment", deployment.DeploymentID).
+		Msg("schedule for deprovision")
+
 	job := engineJob{
 		Target: deployment,
 		Op:     opDeprovision,
@@ -255,7 +260,7 @@ func (e *NativeEngine) Update(ctx context.Context, update gridtypes.Deployment)
 	// that this update is acceptable.
 	_, err = deployment.Upgrade(&update)
 	if err != nil {
-		return err
+		return errors.Wrap(ErrDeploymentUpgradeValidationError, err.Error())
 	}
 
 	// all is okay we can push the job
diff --git a/pkg/provision/interface.go b/pkg/provision/interface.go
index 85bccf39..7eb8c3da 100644
--- a/pkg/provision/interface.go
+++ b/pkg/provision/interface.go
@@ -44,6 +44,9 @@ var (
 	// ErrDidNotChange special error that can be returned by the provisioner
 	// if returned the engine does no update workload data
 	ErrDidNotChange = fmt.Errorf("did not change")
+	// ErrDeploymentUpgradeValidationError error, is returned if the deployment
+	// failed to compute upgrade steps
+	ErrDeploymentUpgradeValidationError = fmt.Errorf("upgrade validation error")
 )
 
 // Storage interface
diff --git a/pkg/storage.go b/pkg/storage.go
index 51d57537..0d54a342 100644
--- a/pkg/storage.go
+++ b/pkg/storage.go
@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"path/filepath"
 
+	"github.com/threefoldtech/zos/pkg/gridtypes"
 	"github.com/threefoldtech/zos/pkg/gridtypes/zos"
 )
 
@@ -111,8 +112,8 @@ type StoragePolicy struct {
 
 // Usage struct
 type Usage struct {
-	Size uint64
-	Used uint64
+	Size gridtypes.Unit
+	Used gridtypes.Unit
 }
 
 // Filesystem represents a storage space that can be used as a filesystem
@@ -140,10 +141,10 @@ type VolumeAllocater interface {
 	// more space is available in such a pool, `ErrNotEnoughSpace` is returned.
 	// It is up to the caller to handle such a situation and decide if he wants
 	// to try again on a different devicetype
-	CreateFilesystem(name string, size uint64, poolType DeviceType) (Filesystem, error)
+	CreateFilesystem(name string, size gridtypes.Unit, poolType DeviceType) (Filesystem, error)
 
 	// UpdateFilesystem changes a filesystem size to given value.
-	UpdateFilesystem(name string, size uint64) (Filesystem, error)
+	UpdateFilesystem(name string, size gridtypes.Unit) (Filesystem, error)
 	// ReleaseFilesystem signals that the named filesystem is no longer needed.
 	// The filesystem will be unmounted and subsequently removed.
 	// All data contained in the filesystem will be lost, and the
@@ -181,7 +182,7 @@ func (d *VDisk) Name() string {
 // VDiskModule interface
 type VDiskModule interface {
 	// AllocateDisk with given id and size, return path to virtual disk
-	Allocate(id string, size int64) (string, error)
+	Allocate(id string, size gridtypes.Unit) (string, error)
 	// DeallocateVDisk removes a virtual disk
 	Deallocate(id string) error
 	// Exists checks if disk with that ID already allocated
diff --git a/pkg/storage/disk.go b/pkg/storage/disk.go
index 614685d8..0c0cf0f2 100644
--- a/pkg/storage/disk.go
+++ b/pkg/storage/disk.go
@@ -10,13 +10,12 @@ import (
 	"github.com/g0rbe/go-chattr"
 	"github.com/pkg/errors"
 	"github.com/threefoldtech/zos/pkg"
+	"github.com/threefoldtech/zos/pkg/gridtypes"
 )
 
 const (
 	// vdiskVolumeName is the name of the volume used to store vdisks
 	vdiskVolumeName = "vdisks"
-
-	mib = 1024 * 1024
 )
 
 type vdiskModule struct {
@@ -49,14 +48,14 @@ func (d *vdiskModule) findDisk(id string) (string, error) {
 	return "", os.ErrNotExist
 }
 
-// AllocateDisk with given size, return path to virtual disk (size in MB)
-func (d *vdiskModule) Allocate(id string, size int64) (string, error) {
+// AllocateDisk with given size, return path to virtual disk
+func (d *vdiskModule) Allocate(id string, size gridtypes.Unit) (string, error) {
 	path, err := d.findDisk(id)
 	if err == nil {
 		return path, errors.Wrapf(os.ErrExist, "disk with id '%s' already exists", id)
 	}
 
-	base, err := d.module.VDiskFindCandidate(uint64(size))
+	base, err := d.module.VDiskFindCandidate(size)
 	if err != nil {
 		return "", errors.Wrapf(err, "failed to find a candidate to host vdisk of size '%d'", size)
 	}
@@ -84,7 +83,7 @@ func (d *vdiskModule) Allocate(id string, size int64) (string, error) {
 		return "", err
 	}
 
-	err = syscall.Fallocate(int(file.Fd()), 0, 0, size*mib)
+	err = syscall.Fallocate(int(file.Fd()), 0, 0, int64(size))
 	return path, err
 }
 
diff --git a/pkg/storage/filesystem/filesystem.go b/pkg/storage/filesystem/filesystem.go
index 3caf003b..2cc71b2d 100644
--- a/pkg/storage/filesystem/filesystem.go
+++ b/pkg/storage/filesystem/filesystem.go
@@ -7,7 +7,7 @@ import (
 	"github.com/threefoldtech/zos/pkg"
 )
 
-// Usage struct
+// Usage struct (in bytes)
 type Usage struct {
 	Size uint64
 	Used uint64
diff --git a/pkg/storage/storage.go b/pkg/storage/storage.go
index ed11e61b..06c61522 100644
--- a/pkg/storage/storage.go
+++ b/pkg/storage/storage.go
@@ -19,6 +19,7 @@ import (
 	"github.com/threefoldtech/zos/pkg"
 	"github.com/threefoldtech/zos/pkg/app"
 	"github.com/threefoldtech/zos/pkg/capacity"
+	"github.com/threefoldtech/zos/pkg/gridtypes"
 	"github.com/threefoldtech/zos/pkg/gridtypes/zos"
 	"github.com/threefoldtech/zos/pkg/storage/filesystem"
 )
@@ -340,13 +341,13 @@ func (s *Module) shutdownUnusedPools() error {
 }
 
 // UpdateFilesystem updates filesystem size
-func (s *Module) UpdateFilesystem(name string, size uint64) (pkg.Filesystem, error) {
+func (s *Module) UpdateFilesystem(name string, size gridtypes.Unit) (pkg.Filesystem, error) {
 	_, volume, fs, err := s.path(name)
 	if err != nil {
 		return pkg.Filesystem{}, err
 	}
 
-	if err := volume.Limit(size); err != nil {
+	if err := volume.Limit(uint64(size)); err != nil {
 		return fs, err
 	}
 
@@ -355,7 +356,7 @@ func (s *Module) UpdateFilesystem(name string, size uint64) (pkg.Filesystem, err
 }
 
 // CreateFilesystem with the given size in a storage pool.
-func (s *Module) CreateFilesystem(name string, size uint64, poolType pkg.DeviceType) (pkg.Filesystem, error) {
+func (s *Module) CreateFilesystem(name string, size gridtypes.Unit, poolType pkg.DeviceType) (pkg.Filesystem, error) {
 	log.Info().Msgf("Creating new volume with size %d", size)
 	if strings.HasPrefix(name, "zdb") {
 		return pkg.Filesystem{}, fmt.Errorf("invalid volume name. zdb prefix is reserved")
@@ -377,8 +378,8 @@ func (s *Module) CreateFilesystem(name string, size uint64, poolType pkg.DeviceT
 		Name:   fs.Name(),
 		Path:   fs.Path(),
 		Usage: pkg.Usage{
-			Size: usage.Size,
-			Used: usage.Used,
+			Size: gridtypes.Unit(usage.Size),
+			Used: gridtypes.Unit(usage.Used),
 		},
 		DiskType: poolType,
 	}, nil
@@ -463,8 +464,8 @@ func (s *Module) ListFilesystems() ([]pkg.Filesystem, error) {
 				Name:   v.Name(),
 				Path:   v.Path(),
 				Usage: pkg.Usage{
-					Size: usage.Size,
-					Used: usage.Used,
+					Size: gridtypes.Unit(usage.Size),
+					Used: gridtypes.Unit(usage.Used),
 				},
 				DiskType: pool.Type(),
 			})
@@ -505,8 +506,8 @@ func (s *Module) path(name string) (filesystem.Pool, filesystem.Volume, pkg.File
 					Name:   fs.Name(),
 					Path:   fs.Path(),
 					Usage: pkg.Usage{
-						Size: usage.Size,
-						Used: usage.Used,
+						Size: gridtypes.Unit(usage.Size),
+						Used: gridtypes.Unit(usage.Used),
 					},
 					DiskType: pool.Type(),
 				}, nil
@@ -518,7 +519,7 @@ func (s *Module) path(name string) (filesystem.Pool, filesystem.Volume, pkg.File
 }
 
 // VDiskFindCandidate find a suitbale location for creating a vdisk of the given size
-func (s *Module) VDiskFindCandidate(size uint64) (path string, err error) {
+func (s *Module) VDiskFindCandidate(size gridtypes.Unit) (path string, err error) {
 	candidates, err := s.findCandidates(size, zos.SSDDevice)
 	if err != nil {
 		return path, err
@@ -663,13 +664,13 @@ func (s *Module) ensureCache() error {
 // createSubvolWithQuota creates a subvolume with the given name and limits it to the given size
 // if the requested disk type does not have a storage pool with enough free size available, an error is returned
 // this methods does set a quota limit equal to size on the created volume
-func (s *Module) createSubvolWithQuota(size uint64, name string, poolType pkg.DeviceType) (filesystem.Volume, error) {
+func (s *Module) createSubvolWithQuota(size gridtypes.Unit, name string, poolType pkg.DeviceType) (filesystem.Volume, error) {
 	volume, err := s.createSubvol(size, name, poolType)
 	if err != nil {
 		return nil, err
 	}
 
-	if err = volume.Limit(size); err != nil {
+	if err = volume.Limit(uint64(size)); err != nil {
 		log.Error().Err(err).Str("volume", volume.Path()).Msg("failed to set volume size limit")
 		return nil, err
 	}
@@ -680,7 +681,7 @@ func (s *Module) createSubvolWithQuota(size uint64, name string, poolType pkg.De
 // createSubvol creates a subvolume with the given name
 // if the requested disk type does not have a storage pool with enough free size available, an error is returned
 // this method does not set any quota on the subvolume, for this uses createSubvolWithQuota
-func (s *Module) createSubvol(size uint64, name string, poolType pkg.DeviceType) (filesystem.Volume, error) {
+func (s *Module) createSubvol(size gridtypes.Unit, name string, poolType pkg.DeviceType) (filesystem.Volume, error) {
 	var err error
 
 	if poolType != zos.HDDDevice && poolType != zos.SSDDevice {
@@ -713,7 +714,7 @@ type candidate struct {
 	Available uint64
 }
 
-func (s *Module) findCandidates(size uint64, poolType pkg.DeviceType) ([]candidate, error) {
+func (s *Module) findCandidates(size gridtypes.Unit, poolType pkg.DeviceType) ([]candidate, error) {
 
 	// Look for candidates in mounted pools first
 	candidates, err := s.checkForCandidates(size, poolType, true)
@@ -741,7 +742,7 @@ func (s *Module) findCandidates(size uint64, poolType pkg.DeviceType) ([]candida
 	return candidates, nil
 }
 
-func (s *Module) checkForCandidates(size uint64, poolType pkg.DeviceType, mounted bool) ([]candidate, error) {
+func (s *Module) checkForCandidates(size gridtypes.Unit, poolType pkg.DeviceType, mounted bool) ([]candidate, error) {
 	var candidates []candidate
 	for _, pool := range s.pools {
 		_, poolIsMounted := pool.Mounted()
@@ -780,10 +781,10 @@ func (s *Module) checkForCandidates(size uint64, poolType pkg.DeviceType, mounte
 		log.Debug().
 			Uint64("max size", usage.Size).
 			Uint64("reserved", reserved).
-			Uint64("new size", reserved+size).
+			Uint64("new size", reserved+uint64(size)).
 			Msgf("usage of pool %s", pool.Name())
 		// Make sure adding this filesystem would not bring us over the disk limit
-		if reserved+size > usage.Size {
+		if reserved+uint64(size) > usage.Size {
 			log.Info().Msgf("Disk does not have enough space left to hold filesystem")
 
 			if !poolIsMounted && !mounted {
diff --git a/pkg/storage/zdb.go b/pkg/storage/zdb.go
index 5fde0276..b6f889bd 100644
--- a/pkg/storage/zdb.go
+++ b/pkg/storage/zdb.go
@@ -11,6 +11,7 @@ import (
 	"github.com/pkg/errors"
 
 	"github.com/threefoldtech/zos/pkg"
+	"github.com/threefoldtech/zos/pkg/gridtypes"
 	"github.com/threefoldtech/zos/pkg/gridtypes/zos"
 	"github.com/threefoldtech/zos/pkg/storage/filesystem"
 	"github.com/threefoldtech/zos/pkg/storage/zdbpool"
@@ -56,10 +57,10 @@ func (s *Module) Find(nsID string) (allocation pkg.Allocation, err error) {
 // Allocate is responsible to make sure the subvolume used by a 0-db as enough storage capacity
 // of specified size, type and mode
 // it returns the volume ID and its path or an error if it couldn't allocate enough storage
-func (s *Module) Allocate(nsID string, diskType pkg.DeviceType, size uint64, mode pkg.ZDBMode) (allocation pkg.Allocation, err error) {
+func (s *Module) Allocate(nsID string, diskType pkg.DeviceType, size gridtypes.Unit, mode pkg.ZDBMode) (allocation pkg.Allocation, err error) {
 	log := log.With().
 		Str("type", string(diskType)).
-		Uint64("size", size).
+		Uint64("size", uint64(size)).
 		Str("mode", string(mode)).
 		Logger()
 
@@ -165,7 +166,7 @@ type zdbcandidate struct {
 	Free uint64
 }
 
-func (s *Module) checkForZDBCandidateVolumes(size uint64, poolType pkg.DeviceType, targetMode zdbpool.IndexMode) ([]zdbcandidate, error) {
+func (s *Module) checkForZDBCandidateVolumes(size gridtypes.Unit, poolType pkg.DeviceType, targetMode zdbpool.IndexMode) ([]zdbcandidate, error) {
 	var candidates []zdbcandidate
 	for _, pool := range s.pools {
 		// ignore pools that are not mounted for now
@@ -203,7 +204,7 @@ func (s *Module) checkForZDBCandidateVolumes(size uint64, poolType pkg.DeviceTyp
 				return nil, err
 			}
 
-			if volumeUsage.Size+size > usage.Size {
+			if volumeUsage.Size+uint64(size) > usage.Size {
 				// not enough space on this volume
 				continue
 			}
@@ -226,7 +227,7 @@ func (s *Module) checkForZDBCandidateVolumes(size uint64, poolType pkg.DeviceTyp
 				candidates,
 				zdbcandidate{
 					Volume: volume,
-					Free:   usage.Size - (volumeUsage.Size + size),
+					Free:   usage.Size - (volumeUsage.Size + uint64(size)),
 				})
 		}
 	}
diff --git a/pkg/storage/zdbpool/ns_header.go b/pkg/storage/zdbpool/ns_header.go
index 54323ea3..ad1656c2 100644
--- a/pkg/storage/zdbpool/ns_header.go
+++ b/pkg/storage/zdbpool/ns_header.go
@@ -5,6 +5,7 @@ import (
 	"io"
 
 	"github.com/pkg/errors"
+	"github.com/threefoldtech/zos/pkg/gridtypes"
 )
 
 const (
@@ -31,7 +32,7 @@ type Header struct {
 	Version  uint32
 	Name     string
 	Password string
-	MaxSize  uint64
+	MaxSize  gridtypes.Unit
 }
 
 // WriteHeader writes header data to writer
@@ -59,7 +60,7 @@ func WriteHeader(w io.Writer, h Header) error {
 		binary.LittleEndian,
 		extendedHeader{
 			Version: 1,
-			MaxSize: h.MaxSize,
+			MaxSize: uint64(h.MaxSize),
 		}); err != nil {
 		return err
 	}
@@ -74,7 +75,7 @@ func ReadHeader(r io.Reader) (header Header, err error) {
 		return header, err
 	}
 	header.Version = 0
-	header.MaxSize = uint64(bh.MaxSize)
+	header.MaxSize = gridtypes.Unit(bh.MaxSize)
 	name := make([]byte, bh.NameLength)
 	passwrd := make([]byte, bh.PasswordLength)
 	// the next reads are important to advance the reader to the position
@@ -99,7 +100,7 @@ func ReadHeader(r io.Reader) (header Header, err error) {
 	}
 
 	header.Version = eh.Version
-	header.MaxSize = eh.MaxSize
+	header.MaxSize = gridtypes.Unit(eh.MaxSize)
 
 	return
 }
diff --git a/pkg/storage/zdbpool/pool.go b/pkg/storage/zdbpool/pool.go
index 61134104..848fac18 100644
--- a/pkg/storage/zdbpool/pool.go
+++ b/pkg/storage/zdbpool/pool.go
@@ -6,6 +6,7 @@ import (
 	"path/filepath"
 
 	"github.com/pkg/errors"
+	"github.com/threefoldtech/zos/pkg/gridtypes"
 )
 
 // Prefix is a string used as prefix in the filesystem volume used
@@ -25,7 +26,7 @@ func New(path string) ZDBPool {
 // NSInfo is a struct containing information about a 0-db namespace
 type NSInfo struct {
 	Name string
-	Size uint64
+	Size gridtypes.Unit
 }
 
 // Reserved return the amount of storage that has been reserved by all the
@@ -47,7 +48,7 @@ func (p *ZDBPool) Reserved() (uint64, error) {
 // Create a namespace. Note that this create only reserve the name
 // space size (and create namespace descriptor) this must be followed
 // by an actual zdb NSNEW call to create the database files.
-func (p *ZDBPool) Create(name, password string, size uint64) error {
+func (p *ZDBPool) Create(name, password string, size gridtypes.Unit) error {
 	dir := filepath.Join(p.path, name)
 	if err := os.MkdirAll(dir, 0755); err != nil {
 		return errors.Wrapf(err, "namespace '%s' directory creation failed", dir)
diff --git a/pkg/stubs/storage_stub.go b/pkg/stubs/storage_stub.go
index 4da0e523..708781aa 100644
--- a/pkg/stubs/storage_stub.go
+++ b/pkg/stubs/storage_stub.go
@@ -4,6 +4,7 @@ import (
 	"context"
 	zbus "github.com/threefoldtech/zbus"
 	pkg "github.com/threefoldtech/zos/pkg"
+	gridtypes "github.com/threefoldtech/zos/pkg/gridtypes"
 	zos "github.com/threefoldtech/zos/pkg/gridtypes/zos"
 )
 
@@ -24,7 +25,7 @@ func NewStorageModuleStub(client zbus.Client) *StorageModuleStub {
 	}
 }
 
-func (s *StorageModuleStub) Allocate(ctx context.Context, arg0 string, arg1 zos.DeviceType, arg2 uint64, arg3 zos.ZDBMode) (ret0 pkg.Allocation, ret1 error) {
+func (s *StorageModuleStub) Allocate(ctx context.Context, arg0 string, arg1 zos.DeviceType, arg2 gridtypes.Unit, arg3 zos.ZDBMode) (ret0 pkg.Allocation, ret1 error) {
 	args := []interface{}{arg0, arg1, arg2, arg3}
 	result, err := s.client.RequestContext(ctx, s.module, s.object, "Allocate", args...)
 	if err != nil {
@@ -64,7 +65,7 @@ func (s *StorageModuleStub) BrokenPools(ctx context.Context) (ret0 []pkg.BrokenP
 	return
 }
 
-func (s *StorageModuleStub) CreateFilesystem(ctx context.Context, arg0 string, arg1 uint64, arg2 zos.DeviceType) (ret0 pkg.Filesystem, ret1 error) {
+func (s *StorageModuleStub) CreateFilesystem(ctx context.Context, arg0 string, arg1 gridtypes.Unit, arg2 zos.DeviceType) (ret0 pkg.Filesystem, ret1 error) {
 	args := []interface{}{arg0, arg1, arg2}
 	result, err := s.client.RequestContext(ctx, s.module, s.object, "CreateFilesystem", args...)
 	if err != nil {
@@ -192,7 +193,7 @@ func (s *StorageModuleStub) Total(ctx context.Context, arg0 zos.DeviceType) (ret
 	return
 }
 
-func (s *StorageModuleStub) UpdateFilesystem(ctx context.Context, arg0 string, arg1 uint64) (ret0 pkg.Filesystem, ret1 error) {
+func (s *StorageModuleStub) UpdateFilesystem(ctx context.Context, arg0 string, arg1 gridtypes.Unit) (ret0 pkg.Filesystem, ret1 error) {
 	args := []interface{}{arg0, arg1}
 	result, err := s.client.RequestContext(ctx, s.module, s.object, "UpdateFilesystem", args...)
 	if err != nil {
diff --git a/pkg/stubs/vdisk_stub.go b/pkg/stubs/vdisk_stub.go
index 89062307..51ea8f4d 100644
--- a/pkg/stubs/vdisk_stub.go
+++ b/pkg/stubs/vdisk_stub.go
@@ -4,6 +4,7 @@ import (
 	"context"
 	zbus "github.com/threefoldtech/zbus"
 	pkg "github.com/threefoldtech/zos/pkg"
+	gridtypes "github.com/threefoldtech/zos/pkg/gridtypes"
 )
 
 type VDiskModuleStub struct {
@@ -23,7 +24,7 @@ func NewVDiskModuleStub(client zbus.Client) *VDiskModuleStub {
 	}
 }
 
-func (s *VDiskModuleStub) Allocate(ctx context.Context, arg0 string, arg1 int64) (ret0 string, ret1 error) {
+func (s *VDiskModuleStub) Allocate(ctx context.Context, arg0 string, arg1 gridtypes.Unit) (ret0 string, ret1 error) {
 	args := []interface{}{arg0, arg1}
 	result, err := s.client.RequestContext(ctx, s.module, s.object, "Allocate", args...)
 	if err != nil {
diff --git a/pkg/stubs/zdb_stub.go b/pkg/stubs/zdb_stub.go
index 8bd726a4..695bb5d0 100644
--- a/pkg/stubs/zdb_stub.go
+++ b/pkg/stubs/zdb_stub.go
@@ -4,6 +4,7 @@ import (
 	"context"
 	zbus "github.com/threefoldtech/zbus"
 	pkg "github.com/threefoldtech/zos/pkg"
+	gridtypes "github.com/threefoldtech/zos/pkg/gridtypes"
 	zos "github.com/threefoldtech/zos/pkg/gridtypes/zos"
 )
 
@@ -24,7 +25,7 @@ func NewZDBAllocaterStub(client zbus.Client) *ZDBAllocaterStub {
 	}
 }
 
-func (s *ZDBAllocaterStub) Allocate(ctx context.Context, arg0 string, arg1 zos.DeviceType, arg2 uint64, arg3 zos.ZDBMode) (ret0 pkg.Allocation, ret1 error) {
+func (s *ZDBAllocaterStub) Allocate(ctx context.Context, arg0 string, arg1 zos.DeviceType, arg2 gridtypes.Unit, arg3 zos.ZDBMode) (ret0 pkg.Allocation, ret1 error) {
 	args := []interface{}{arg0, arg1, arg2, arg3}
 	result, err := s.client.RequestContext(ctx, s.module, s.object, "Allocate", args...)
 	if err != nil {
diff --git a/pkg/vm.go b/pkg/vm.go
index 2951932f..9c391264 100644
--- a/pkg/vm.go
+++ b/pkg/vm.go
@@ -3,6 +3,8 @@ package pkg
 import (
 	"fmt"
 	"net"
+
+	"github.com/threefoldtech/zos/pkg/gridtypes"
 )
 
 //go:generate zbusc -module vmd -version 0.0.1 -name manager -package stubs github.com/threefoldtech/zos/pkg+VMModule stubs/vmd_stub.go
@@ -51,8 +53,8 @@ type VM struct {
 	Name string
 	// CPU is number of cores assigned to the VM
 	CPU uint8
-	// Memory size in Mib
-	Memory int64
+	// Memory size
+	Memory gridtypes.Unit
 	// Network is network info
 	Network VMNetworkInfo
 	// KernelImage path to uncompressed linux kernel ELF
diff --git a/pkg/vm/machine.go b/pkg/vm/machine.go
index 8257a359..403b56ba 100644
--- a/pkg/vm/machine.go
+++ b/pkg/vm/machine.go
@@ -99,7 +99,7 @@ func (i *Interface) getType() (InterfaceType, int, error) {
 type Interfaces []Interface
 
 // MemMib is memory size in mib
-type MemMib int64
+type MemMib uint64
 
 func (m MemMib) String() string {
 	return fmt.Sprintf("size=%dM", int64(m))
diff --git a/pkg/vm/manager.go b/pkg/vm/manager.go
index 46f0eca4..175fe9ae 100644
--- a/pkg/vm/manager.go
+++ b/pkg/vm/manager.go
@@ -18,6 +18,7 @@ import (
 	"github.com/rs/zerolog/log"
 	"github.com/threefoldtech/zbus"
 	"github.com/threefoldtech/zos/pkg"
+	"github.com/threefoldtech/zos/pkg/gridtypes"
 )
 
 const (
@@ -287,7 +288,7 @@ func (m *Module) Run(vm pkg.VM) error {
 		},
 		Config: Config{
 			CPU:       CPU(vm.CPU),
-			Mem:       MemMib(vm.Memory),
+			Mem:       MemMib(vm.Memory / gridtypes.Megabyte),
 			HTEnabled: false,
 		},
 		Interfaces:  nics,
diff --git a/pkg/zdb.go b/pkg/zdb.go
index 270ecd39..1ba83998 100644
--- a/pkg/zdb.go
+++ b/pkg/zdb.go
@@ -1,6 +1,9 @@
 package pkg
 
-import "github.com/threefoldtech/zos/pkg/gridtypes/zos"
+import (
+	"github.com/threefoldtech/zos/pkg/gridtypes"
+	"github.com/threefoldtech/zos/pkg/gridtypes/zos"
+)
 
 //go:generate mkdir -p stubs
 //go:generate zbusc -module storage -version 0.0.1 -name storage -package stubs github.com/threefoldtech/zos/pkg+ZDBAllocater stubs/zdb_stub.go
@@ -33,7 +36,7 @@ type ZDBAllocater interface {
 	// it returns the volume ID and its path or an error if it couldn't allocate enough storage
 	// Note: if allocation already exists with the namespace name, the current allocation is returned
 	// so no need to call Find before calling allocate
-	Allocate(namespace string, diskType DeviceType, size uint64, mode ZDBMode) (Allocation, error)
+	Allocate(namespace string, diskType DeviceType, size gridtypes.Unit, mode ZDBMode) (Allocation, error)
 
 	// Find searches the system for the current allocation for the namespace
 	// Return error = "not found" if no allocation exists.
diff --git a/qemu/vm.sh b/qemu/vm.sh
index 0eb93b75..5ed4f849 100755
--- a/qemu/vm.sh
+++ b/qemu/vm.sh
@@ -8,6 +8,7 @@ kernelargs=""
 bridge=zos0
 graphics="-nographic -nodefaults"
 smp=1
+mem=3
 
 usage() {
    cat <<EOF
@@ -20,6 +21,7 @@ Usage: vm -n $name [ -r ] [ -d ]
    -i: kernel image to boot
    -b: bridge for network (default zos)
    -g: open GUI
+   -m: memory in Gigabytes
    -h: help
 
 EOF
@@ -27,7 +29,7 @@ EOF
 }
 
 
-while getopts "c:n:i:rdb:gs:" opt; do
+while getopts "c:n:i:rdb:gs:m:" opt; do
    case $opt in
    i )  image=$OPTARG ;;
    r )  reset=1 ;;
@@ -37,6 +39,7 @@ while getopts "c:n:i:rdb:gs:" opt; do
    b )  bridge=$OPTARG ;;
    g )  graphics="" ;;
    s )  smp=$OPTARG ;;
+   m )  mem=$OPTARG ;;
    h )  usage ; exit 0 ;;
    \?)  usage ; exit 1 ;;
    esac
@@ -73,7 +76,10 @@ fi
 echo "boot $image"
 
 qemu-system-x86_64 -kernel $image \
-    -m 3072 -enable-kvm -cpu host -smp $smp \
+    -m $(( mem * 1024 )) \
+    -enable-kvm \
+    -cpu host \
+    -smp $smp \
     -uuid $uuid \
     -netdev bridge,id=zos0,br=${bridge} -device virtio-net-pci,netdev=zos0,mac="${basemac}1" \
     -drive file=fat:rw:$basepath/overlay,format=raw \


Test patch:
diff --git a/pkg/flist/flist_test.go b/pkg/flist/flist_test.go
index bb128b68..e36e2446 100644
--- a/pkg/flist/flist_test.go
+++ b/pkg/flist/flist_test.go
@@ -16,6 +16,7 @@ import (
 	"github.com/stretchr/testify/mock"
 	"github.com/stretchr/testify/require"
 	"github.com/threefoldtech/zos/pkg"
+	"github.com/threefoldtech/zos/pkg/gridtypes"
 	"github.com/threefoldtech/zos/pkg/gridtypes/zos"
 )
 
@@ -32,7 +33,7 @@ type StorageMock struct {
 }
 
 // CreateFilesystem create filesystem mock
-func (s *StorageMock) CreateFilesystem(ctx context.Context, name string, size uint64, poolType pkg.DeviceType) (pkg.Filesystem, error) {
+func (s *StorageMock) CreateFilesystem(ctx context.Context, name string, size gridtypes.Unit, poolType pkg.DeviceType) (pkg.Filesystem, error) {
 	args := s.Called(ctx, name, size, poolType)
 	return pkg.Filesystem{
 		Path: args.String(0),
diff --git a/pkg/gridtypes/zos/types_test.go b/pkg/gridtypes/zos/types_test.go
index d22d74a5..2b61bb6a 100644
--- a/pkg/gridtypes/zos/types_test.go
+++ b/pkg/gridtypes/zos/types_test.go
@@ -22,7 +22,7 @@ func TestWorkloadData(t *testing.T) {
 	require.IsType(&Volume{}, data)
 	volume := data.(*Volume)
 
-	require.Equal(uint64(10), volume.Size)
+	require.Equal(gridtypes.Unit(10), volume.Size)
 	require.Equal(SSDDevice, volume.Type)
 }
 
diff --git a/pkg/primitives/counters_test.go b/pkg/primitives/counters_test.go
index 78b5d4dc..cd7e01e8 100644
--- a/pkg/primitives/counters_test.go
+++ b/pkg/primitives/counters_test.go
@@ -4,28 +4,29 @@ import (
 	"testing"
 
 	"github.com/stretchr/testify/assert"
+	"github.com/threefoldtech/zos/pkg/gridtypes"
 )
 
 func TestCounterDecrement(t *testing.T) {
 	t.Run("regular_decrement", func(t *testing.T) {
-		counter := AtomicValue(0)
+		counter := AtomicUnit(0)
 		counter.Increment(5)
 		dec := counter.Decrement(3)
-		assert.Equal(t, dec, uint64(2))
-		assert.Equal(t, counter.Current(), uint64(2))
+		assert.Equal(t, dec, gridtypes.Unit(2))
+		assert.Equal(t, counter.Current(), gridtypes.Unit(2))
 	})
 	t.Run("decrement_to_zero", func(t *testing.T) {
-		counter := AtomicValue(0)
+		counter := AtomicUnit(0)
 		counter.Increment(5)
 		dec := counter.Decrement(5)
-		assert.Equal(t, dec, uint64(0))
-		assert.Equal(t, counter.Current(), uint64(0))
+		assert.Equal(t, dec, gridtypes.Unit(0))
+		assert.Equal(t, counter.Current(), gridtypes.Unit(0))
 	})
 	t.Run("decrement_negative", func(t *testing.T) {
-		counter := AtomicValue(0)
+		counter := AtomicUnit(0)
 		counter.Increment(5)
 		dec := counter.Decrement(7)
-		assert.Equal(t, dec, uint64(0))
-		assert.Equal(t, counter.Current(), uint64(0))
+		assert.Equal(t, dec, gridtypes.Unit(0))
+		assert.Equal(t, counter.Current(), gridtypes.Unit(0))
 	})
 }
diff --git a/pkg/storage/zdbpool/ns_header_test.go b/pkg/storage/zdbpool/ns_header_test.go
index 4b787a15..1c3fcf5e 100644
--- a/pkg/storage/zdbpool/ns_header_test.go
+++ b/pkg/storage/zdbpool/ns_header_test.go
@@ -7,6 +7,7 @@ import (
 
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
+	"github.com/threefoldtech/zos/pkg/gridtypes"
 )
 
 func TestReadHeader(t *testing.T) {
@@ -19,7 +20,7 @@ func TestReadHeader(t *testing.T) {
 
 	assert.Equal(t, "test", h.Name)
 	assert.Equal(t, "", h.Password)
-	assert.Equal(t, uint64(1025), h.MaxSize)
+	assert.Equal(t, gridtypes.Unit(1025), h.MaxSize)
 }
 
 func TestReadHeaderExtended(t *testing.T) {
@@ -33,7 +34,7 @@ func TestReadHeaderExtended(t *testing.T) {
 	assert.Equal(t, uint32(1), h.Version)
 	assert.Equal(t, "test", h.Name)
 	assert.Equal(t, "password", h.Password)
-	assert.Equal(t, uint64(1073741824), h.MaxSize) // 1G
+	assert.Equal(t, gridtypes.Unit(1073741824), h.MaxSize) // 1G
 }
 
 func TestWriteHeader(t *testing.T) {
diff --git a/pkg/storage/zdbpool/pool_test.go b/pkg/storage/zdbpool/pool_test.go
index fd48f33d..87863516 100644
--- a/pkg/storage/zdbpool/pool_test.go
+++ b/pkg/storage/zdbpool/pool_test.go
@@ -5,6 +5,7 @@ import (
 
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
+	"github.com/threefoldtech/zos/pkg/gridtypes"
 )
 
 func TestNamespaces(t *testing.T) {
@@ -17,10 +18,10 @@ func TestNamespaces(t *testing.T) {
 
 	require.Equal(t, 2, len(ns))
 	assert.Equal(t, "test", ns[0].Name)
-	assert.Equal(t, uint64(1025), ns[0].Size)
+	assert.Equal(t, gridtypes.Unit(1025), ns[0].Size)
 
 	assert.Equal(t, "test2", ns[1].Name)
-	assert.Equal(t, uint64(123132), ns[1].Size)
+	assert.Equal(t, gridtypes.Unit(123132), ns[1].Size)
 }
 
 func TestReserved(t *testing.T) {