[lxc-devel] [lxd/master] lxd/project: Adds project package and updates references to it

tomponline on Github lxc-bot at linuxcontainers.org
Fri Jul 12 17:14:50 UTC 2019


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 393 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190712/9e9bd7ff/attachment-0001.bin>
-------------- next part --------------
From e95debe2beef8e0b83058716ea5b666f0ea92773 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 12 Jul 2019 18:04:34 +0100
Subject: [PATCH] lxd/project: Adds project package and updates references to
 it

For use with device package.

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/api_internal.go           |  45 ++++-----
 lxd/api_project.go            |   8 --
 lxd/apparmor.go               |   7 +-
 lxd/container_lxc.go          |  25 ++---
 lxd/networks_utils.go         |  15 +--
 lxd/project/project.go        |  13 +++
 lxd/storage.go                |   9 +-
 lxd/storage_btrfs.go          |  67 ++++++-------
 lxd/storage_ceph.go           |  47 ++++-----
 lxd/storage_ceph_migration.go |  33 ++++---
 lxd/storage_ceph_utils.go     |  45 ++++-----
 lxd/storage_dir.go            |  35 +++----
 lxd/storage_lvm.go            |  51 +++++-----
 lxd/storage_lvm_utils.go      |  23 ++---
 lxd/storage_migration.go      |   7 +-
 lxd/storage_zfs.go            | 179 +++++++++++++++++-----------------
 lxd/storage_zfs_utils.go      |  27 ++---
 17 files changed, 328 insertions(+), 308 deletions(-)
 create mode 100644 lxd/project/project.go

diff --git a/lxd/api_internal.go b/lxd/api_internal.go
index 56e4c7c8cb..69e2dd323d 100644
--- a/lxd/api_internal.go
+++ b/lxd/api_internal.go
@@ -20,6 +20,7 @@ import (
 	"github.com/lxc/lxd/lxd/db/cluster"
 	"github.com/lxc/lxd/lxd/db/node"
 	"github.com/lxc/lxd/lxd/db/query"
+	"github.com/lxc/lxd/lxd/project"
 	"github.com/lxc/lxd/shared"
 	"github.com/lxc/lxd/shared/api"
 	"github.com/lxc/lxd/shared/logger"
@@ -419,7 +420,7 @@ type internalImportPost struct {
 }
 
 func internalImport(d *Daemon, r *http.Request) Response {
-	project := projectParam(r)
+	projectName := projectParam(r)
 
 	req := &internalImportPost{}
 	// Parse the request.
@@ -451,7 +452,7 @@ func internalImport(d *Daemon, r *http.Request) Response {
 	containerMntPoints := []string{}
 	containerPoolName := ""
 	for _, poolName := range storagePoolNames {
-		containerMntPoint := getContainerMountPoint(project, poolName, req.Name)
+		containerMntPoint := getContainerMountPoint(projectName, poolName, req.Name)
 		if shared.PathExists(containerMntPoint) {
 			containerMntPoints = append(containerMntPoints, containerMntPoint)
 			containerPoolName = poolName
@@ -570,7 +571,7 @@ func internalImport(d *Daemon, r *http.Request) Response {
 	if len(backup.Snapshots) > 0 {
 		switch backup.Pool.Driver {
 		case "btrfs":
-			snapshotsDirPath := getSnapshotMountPoint(project, poolName, req.Name)
+			snapshotsDirPath := getSnapshotMountPoint(projectName, poolName, req.Name)
 			snapshotsDir, err := os.Open(snapshotsDirPath)
 			if err != nil {
 				return InternalError(err)
@@ -582,7 +583,7 @@ func internalImport(d *Daemon, r *http.Request) Response {
 			}
 			snapshotsDir.Close()
 		case "dir":
-			snapshotsDirPath := getSnapshotMountPoint(project, poolName, req.Name)
+			snapshotsDirPath := getSnapshotMountPoint(projectName, poolName, req.Name)
 			snapshotsDir, err := os.Open(snapshotsDirPath)
 			if err != nil {
 				return InternalError(err)
@@ -623,7 +624,7 @@ func internalImport(d *Daemon, r *http.Request) Response {
 
 			onDiskPoolName := backup.Pool.Config["ceph.osd.pool_name"]
 			snaps, err := cephRBDVolumeListSnapshots(clusterName,
-				onDiskPoolName, projectPrefix(project, req.Name),
+				onDiskPoolName, project.Prefix(projectName, req.Name),
 				storagePoolVolumeTypeNameContainer, userName)
 			if err != nil {
 				if err != db.ErrNoSuchObject {
@@ -696,10 +697,10 @@ func internalImport(d *Daemon, r *http.Request) Response {
 		switch backup.Pool.Driver {
 		case "btrfs":
 			snapName := fmt.Sprintf("%s/%s", req.Name, od)
-			err = btrfsSnapshotDeleteInternal(project, poolName, snapName)
+			err = btrfsSnapshotDeleteInternal(projectName, poolName, snapName)
 		case "dir":
 			snapName := fmt.Sprintf("%s/%s", req.Name, od)
-			err = dirSnapshotDeleteInternal(project, poolName, snapName)
+			err = dirSnapshotDeleteInternal(projectName, poolName, snapName)
 		case "lvm":
 			onDiskPoolName := backup.Pool.Config["lvm.vg_name"]
 			if onDiskPoolName == "" {
@@ -707,7 +708,7 @@ func internalImport(d *Daemon, r *http.Request) Response {
 			}
 			snapName := fmt.Sprintf("%s/%s", req.Name, od)
 			snapPath := containerPath(snapName, true)
-			err = lvmContainerDeleteInternal(project, poolName, req.Name,
+			err = lvmContainerDeleteInternal(projectName, poolName, req.Name,
 				true, onDiskPoolName, snapPath)
 		case "ceph":
 			clusterName := "ceph"
@@ -721,9 +722,9 @@ func internalImport(d *Daemon, r *http.Request) Response {
 			}
 
 			onDiskPoolName := backup.Pool.Config["ceph.osd.pool_name"]
-			snapName := fmt.Sprintf("snapshot_%s", projectPrefix(project, od))
+			snapName := fmt.Sprintf("snapshot_%s", project.Prefix(projectName, od))
 			ret := cephContainerSnapshotDelete(clusterName,
-				onDiskPoolName, projectPrefix(project, req.Name),
+				onDiskPoolName, project.Prefix(projectName, req.Name),
 				storagePoolVolumeTypeNameContainer, snapName, userName)
 			if ret < 0 {
 				err = fmt.Errorf(`Failed to delete snapshot`)
@@ -731,7 +732,7 @@ func internalImport(d *Daemon, r *http.Request) Response {
 		case "zfs":
 			onDiskPoolName := backup.Pool.Config["zfs.pool_name"]
 			snapName := fmt.Sprintf("%s/%s", req.Name, od)
-			err = zfsSnapshotDeleteInternal(project, poolName, snapName,
+			err = zfsSnapshotDeleteInternal(projectName, poolName, snapName,
 				onDiskPoolName)
 		}
 		if err != nil {
@@ -742,7 +743,7 @@ func internalImport(d *Daemon, r *http.Request) Response {
 	for _, snap := range backup.Snapshots {
 		switch backup.Pool.Driver {
 		case "btrfs":
-			snpMntPt := getSnapshotMountPoint(project, backup.Pool.Name, snap.Name)
+			snpMntPt := getSnapshotMountPoint(projectName, backup.Pool.Name, snap.Name)
 			if !shared.PathExists(snpMntPt) || !isBtrfsSubVolume(snpMntPt) {
 				if req.Force {
 					continue
@@ -750,7 +751,7 @@ func internalImport(d *Daemon, r *http.Request) Response {
 				return BadRequest(needForce)
 			}
 		case "dir":
-			snpMntPt := getSnapshotMountPoint(project, backup.Pool.Name, snap.Name)
+			snpMntPt := getSnapshotMountPoint(projectName, backup.Pool.Name, snap.Name)
 			if !shared.PathExists(snpMntPt) {
 				if req.Force {
 					continue
@@ -786,8 +787,8 @@ func internalImport(d *Daemon, r *http.Request) Response {
 
 			onDiskPoolName := backup.Pool.Config["ceph.osd.pool_name"]
 			ctName, csName, _ := containerGetParentAndSnapshotName(snap.Name)
-			ctName = projectPrefix(project, ctName)
-			csName = projectPrefix(project, csName)
+			ctName = project.Prefix(projectName, ctName)
+			csName = project.Prefix(projectName, csName)
 			snapshotName := fmt.Sprintf("snapshot_%s", csName)
 
 			exists := cephRBDSnapshotExists(clusterName,
@@ -879,7 +880,7 @@ func internalImport(d *Daemon, r *http.Request) Response {
 	if containerErr == nil {
 		// Remove the storage volume db entry for the container since
 		// force was specified.
-		err := d.cluster.ContainerRemove(project, req.Name)
+		err := d.cluster.ContainerRemove(projectName, req.Name)
 		if err != nil {
 			return SmartError(err)
 		}
@@ -932,7 +933,7 @@ func internalImport(d *Daemon, r *http.Request) Response {
 		}
 
 		if snapErr == nil {
-			err := d.cluster.ContainerRemove(project, snap.Name)
+			err := d.cluster.ContainerRemove(projectName, snap.Name)
 			if err != nil {
 				return SmartError(err)
 			}
@@ -973,7 +974,7 @@ func internalImport(d *Daemon, r *http.Request) Response {
 		}
 
 		_, err = containerCreateInternal(d.State(), db.ContainerArgs{
-			Project:      project,
+			Project:      projectName,
 			Architecture: arch,
 			BaseImage:    baseImage,
 			Config:       snap.Config,
@@ -991,10 +992,10 @@ func internalImport(d *Daemon, r *http.Request) Response {
 		}
 
 		// Recreate missing mountpoints and symlinks.
-		snapshotMountPoint := getSnapshotMountPoint(project, backup.Pool.Name,
+		snapshotMountPoint := getSnapshotMountPoint(projectName, backup.Pool.Name,
 			snap.Name)
 		sourceName, _, _ := containerGetParentAndSnapshotName(snap.Name)
-		sourceName = projectPrefix(project, sourceName)
+		sourceName = project.Prefix(projectName, sourceName)
 		snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", backup.Pool.Name, "containers-snapshots", sourceName)
 		snapshotMntPointSymlink := shared.VarPath("snapshots", sourceName)
 		err = createSnapshotMountpoint(snapshotMountPoint, snapshotMntPointSymlinkTarget, snapshotMntPointSymlink)
@@ -1029,7 +1030,7 @@ func internalImport(d *Daemon, r *http.Request) Response {
 		return SmartError(err)
 	}
 	_, err = containerCreateInternal(d.State(), db.ContainerArgs{
-		Project:      project,
+		Project:      projectName,
 		Architecture: arch,
 		BaseImage:    baseImage,
 		Config:       backup.Container.Config,
@@ -1048,7 +1049,7 @@ func internalImport(d *Daemon, r *http.Request) Response {
 		return SmartError(err)
 	}
 
-	containerPath := containerPath(projectPrefix(project, req.Name), false)
+	containerPath := containerPath(project.Prefix(projectName, req.Name), false)
 	isPrivileged := false
 	if backup.Container.Config["security.privileged"] == "" {
 		isPrivileged = true
diff --git a/lxd/api_project.go b/lxd/api_project.go
index 8068ec2b87..0ca44d03d6 100644
--- a/lxd/api_project.go
+++ b/lxd/api_project.go
@@ -485,14 +485,6 @@ func projectIsEmpty(project *api.Project) bool {
 	return true
 }
 
-// Add the "<project>_" prefix when the given project name is not "default".
-func projectPrefix(project string, s string) string {
-	if project != "default" {
-		s = fmt.Sprintf("%s_%s", project, s)
-	}
-	return s
-}
-
 // Validate the project configuration
 var projectConfigKeys = map[string]func(value string) error{
 	"features.profiles": shared.IsBool,
diff --git a/lxd/apparmor.go b/lxd/apparmor.go
index f3d94f7a2e..f0392de64f 100644
--- a/lxd/apparmor.go
+++ b/lxd/apparmor.go
@@ -9,6 +9,7 @@ import (
 	"path"
 	"strings"
 
+	"github.com/lxc/lxd/lxd/project"
 	"github.com/lxc/lxd/shared"
 	"github.com/lxc/lxd/shared/logger"
 
@@ -495,19 +496,19 @@ func AANamespace(c container) string {
 	 */
 	lxddir := strings.Replace(strings.Trim(shared.VarPath(""), "/"), "/", "-", -1)
 	lxddir = mkApparmorName(lxddir)
-	name := projectPrefix(c.Project(), c.Name())
+	name := project.Prefix(c.Project(), c.Name())
 	return fmt.Sprintf("lxd-%s_<%s>", name, lxddir)
 }
 
 func AAProfileFull(c container) string {
 	lxddir := shared.VarPath("")
 	lxddir = mkApparmorName(lxddir)
-	name := projectPrefix(c.Project(), c.Name())
+	name := project.Prefix(c.Project(), c.Name())
 	return fmt.Sprintf("lxd-%s_<%s>", name, lxddir)
 }
 
 func AAProfileShort(c container) string {
-	name := projectPrefix(c.Project(), c.Name())
+	name := project.Prefix(c.Project(), c.Name())
 	return fmt.Sprintf("lxd-%s", name)
 }
 
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index e2b9acc843..5483ae3d18 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -32,6 +32,7 @@ import (
 	"github.com/lxc/lxd/lxd/db"
 	"github.com/lxc/lxd/lxd/db/query"
 	"github.com/lxc/lxd/lxd/maas"
+	"github.com/lxc/lxd/lxd/project"
 	"github.com/lxc/lxd/lxd/state"
 	"github.com/lxc/lxd/lxd/template"
 	"github.com/lxc/lxd/lxd/types"
@@ -973,7 +974,7 @@ func (c *containerLXC) initLXC(config bool) error {
 	}
 
 	// Load the go-lxc struct
-	cname := projectPrefix(c.Project(), c.Name())
+	cname := project.Prefix(c.Project(), c.Name())
 	cc, err := lxc.NewContainer(cname, c.state.OS.LxcPath)
 	if err != nil {
 		return err
@@ -3170,7 +3171,7 @@ func (c *containerLXC) Start(stateful bool) error {
 		}
 	}
 
-	name := projectPrefix(c.Project(), c.name)
+	name := project.Prefix(c.Project(), c.name)
 
 	// Start the LXC container
 	_, err = shared.RunCommand(
@@ -6894,7 +6895,7 @@ func (c *containerLXC) Console(terminal *os.File) *exec.Cmd {
 	args := []string{
 		c.state.OS.ExecPath,
 		"forkconsole",
-		projectPrefix(c.Project(), c.Name()),
+		project.Prefix(c.Project(), c.Name()),
 		c.state.OS.LxcPath,
 		filepath.Join(c.LogPath(), "lxc.conf"),
 		"tty=0",
@@ -6934,7 +6935,7 @@ func (c *containerLXC) Exec(command []string, env map[string]string, stdin *os.F
 	}
 
 	// Prepare the subcommand
-	cname := projectPrefix(c.Project(), c.Name())
+	cname := project.Prefix(c.Project(), c.Name())
 	args := []string{
 		c.state.OS.ExecPath,
 		"forkexec",
@@ -7338,7 +7339,7 @@ func (c *containerLXC) insertMountLXD(source, target, fstype string, flags int,
 }
 
 func (c *containerLXC) insertMountLXC(source, target, fstype string, flags int) error {
-	cname := projectPrefix(c.Project(), c.Name())
+	cname := project.Prefix(c.Project(), c.Name())
 	configPath := filepath.Join(c.LogPath(), "lxc.conf")
 	if fstype == "" {
 		fstype = "none"
@@ -7374,7 +7375,7 @@ func (c *containerLXC) removeMount(mount string) error {
 
 	if c.state.OS.LXCFeatures["mount_injection_file"] {
 		configPath := filepath.Join(c.LogPath(), "lxc.conf")
-		cname := projectPrefix(c.Project(), c.Name())
+		cname := project.Prefix(c.Project(), c.Name())
 
 		if !strings.HasPrefix(mount, "/") {
 			mount = "/" + mount
@@ -8555,7 +8556,7 @@ func (c *containerLXC) fillNetworkDevice(name string, m types.Device) (types.Dev
 		}
 
 		// Attempt to include all existing interfaces
-		cname := projectPrefix(c.Project(), c.Name())
+		cname := project.Prefix(c.Project(), c.Name())
 		cc, err := lxc.NewContainer(cname, c.state.OS.LxcPath)
 		if err == nil {
 			defer cc.Release()
@@ -9149,7 +9150,7 @@ func (c *containerLXC) removeNetworkDevice(name string, m types.Device) error {
 	}
 
 	// For some reason, having network config confuses detach, so get our own go-lxc struct
-	cname := projectPrefix(c.Project(), c.Name())
+	cname := project.Prefix(c.Project(), c.Name())
 	cc, err := lxc.NewContainer(cname, c.state.OS.LxcPath)
 	if err != nil {
 		return err
@@ -9975,22 +9976,22 @@ func (c *containerLXC) State() string {
 
 // Various container paths
 func (c *containerLXC) Path() string {
-	name := projectPrefix(c.Project(), c.Name())
+	name := project.Prefix(c.Project(), c.Name())
 	return containerPath(name, c.IsSnapshot())
 }
 
 func (c *containerLXC) DevicesPath() string {
-	name := projectPrefix(c.Project(), c.Name())
+	name := project.Prefix(c.Project(), c.Name())
 	return shared.VarPath("devices", name)
 }
 
 func (c *containerLXC) ShmountsPath() string {
-	name := projectPrefix(c.Project(), c.Name())
+	name := project.Prefix(c.Project(), c.Name())
 	return shared.VarPath("shmounts", name)
 }
 
 func (c *containerLXC) LogPath() string {
-	name := projectPrefix(c.Project(), c.Name())
+	name := project.Prefix(c.Project(), c.Name())
 	return shared.LogPath(name)
 }
 
diff --git a/lxd/networks_utils.go b/lxd/networks_utils.go
index b7e6df7c2e..e12f505f18 100644
--- a/lxd/networks_utils.go
+++ b/lxd/networks_utils.go
@@ -27,6 +27,7 @@ import (
 
 	"github.com/lxc/lxd/lxd/cluster"
 	"github.com/lxc/lxd/lxd/db"
+	"github.com/lxc/lxd/lxd/project"
 	"github.com/lxc/lxd/lxd/state"
 	"github.com/lxc/lxd/shared"
 	"github.com/lxc/lxd/shared/api"
@@ -1247,7 +1248,7 @@ func networkDHCPFindFreeIPv4(usedIPs map[[4]byte]dhcpAllocation, netConfig map[s
 }
 
 // networkUpdateStaticContainer writes a single dhcp-host line for a container/network combination.
-func networkUpdateStaticContainer(network string, project string, cName string, netConfig map[string]string, hwaddr string, ipv4Address string, ipv6Address string) error {
+func networkUpdateStaticContainer(network string, projectName string, cName string, netConfig map[string]string, hwaddr string, ipv4Address string, ipv6Address string) error {
 	line := hwaddr
 
 	// Generate the dhcp-host line
@@ -1267,7 +1268,7 @@ func networkUpdateStaticContainer(network string, project string, cName string,
 		return nil
 	}
 
-	err := ioutil.WriteFile(shared.VarPath("networks", network, "dnsmasq.hosts", projectPrefix(project, cName)), []byte(line+"\n"), 0644)
+	err := ioutil.WriteFile(shared.VarPath("networks", network, "dnsmasq.hosts", project.Prefix(projectName, cName)), []byte(line+"\n"), 0644)
 	if err != nil {
 		return err
 	}
@@ -1370,7 +1371,7 @@ func networkUpdateStatic(s *state.State, networkName string) error {
 		// Apply the changes
 		for entryIdx, entry := range entries {
 			hwaddr := entry[0]
-			project := entry[1]
+			projectName := entry[1]
 			cName := entry[2]
 			ipv4Address := entry[3]
 			ipv6Address := entry[4]
@@ -1379,14 +1380,14 @@ func networkUpdateStatic(s *state.State, networkName string) error {
 			// Look for duplicates
 			duplicate := false
 			for iIdx, i := range entries {
-				if projectPrefix(entry[1], entry[2]) == projectPrefix(i[1], i[2]) {
+				if project.Prefix(entry[1], entry[2]) == project.Prefix(i[1], i[2]) {
 					// Skip ourselves
 					continue
 				}
 
 				if entry[0] == i[0] {
 					// Find broken configurations
-					logger.Errorf("Duplicate MAC detected: %s and %s", projectPrefix(entry[1], entry[2]), projectPrefix(i[1], i[2]))
+					logger.Errorf("Duplicate MAC detected: %s and %s", project.Prefix(entry[1], entry[2]), project.Prefix(i[1], i[2]))
 				}
 
 				if i[3] == "" && i[4] == "" {
@@ -1400,7 +1401,7 @@ func networkUpdateStatic(s *state.State, networkName string) error {
 						duplicate = true
 					} else {
 						line = fmt.Sprintf("%s,%s", line, i[0])
-						logger.Debugf("Found containers with duplicate IPv4/IPv6: %s and %s", projectPrefix(entry[1], entry[2]), projectPrefix(i[1], i[2]))
+						logger.Debugf("Found containers with duplicate IPv4/IPv6: %s and %s", project.Prefix(entry[1], entry[2]), project.Prefix(i[1], i[2]))
 					}
 				}
 			}
@@ -1410,7 +1411,7 @@ func networkUpdateStatic(s *state.State, networkName string) error {
 			}
 
 			// Generate the dhcp-host line
-			err := networkUpdateStaticContainer(network, project, cName, config, hwaddr, ipv4Address, ipv6Address)
+			err := networkUpdateStaticContainer(network, projectName, cName, config, hwaddr, ipv4Address, ipv6Address)
 			if err != nil {
 				return err
 			}
diff --git a/lxd/project/project.go b/lxd/project/project.go
new file mode 100644
index 0000000000..a57f4fabc8
--- /dev/null
+++ b/lxd/project/project.go
@@ -0,0 +1,13 @@
+package project
+
+import (
+	"fmt"
+)
+
+// Prefix Add the "<project>_" prefix when the given project name is not "default".
+func Prefix(project string, s string) string {
+	if project != "default" {
+		s = fmt.Sprintf("%s_%s", project, s)
+	}
+	return s
+}
diff --git a/lxd/storage.go b/lxd/storage.go
index eeee787303..eb28c0bb37 100644
--- a/lxd/storage.go
+++ b/lxd/storage.go
@@ -13,6 +13,7 @@ import (
 
 	"github.com/lxc/lxd/lxd/db"
 	"github.com/lxc/lxd/lxd/migration"
+	"github.com/lxc/lxd/lxd/project"
 	"github.com/lxc/lxd/lxd/state"
 	"github.com/lxc/lxd/shared"
 	"github.com/lxc/lxd/shared/api"
@@ -617,13 +618,13 @@ func getStoragePoolMountPoint(poolName string) string {
 }
 
 // ${LXD_DIR}/storage-pools/<pool>/containers/[<project_name>_]<container_name>
-func getContainerMountPoint(project string, poolName string, containerName string) string {
-	return shared.VarPath("storage-pools", poolName, "containers", projectPrefix(project, containerName))
+func getContainerMountPoint(projectName string, poolName string, containerName string) string {
+	return shared.VarPath("storage-pools", poolName, "containers", project.Prefix(projectName, containerName))
 }
 
 // ${LXD_DIR}/storage-pools/<pool>/containers-snapshots/<snapshot_name>
-func getSnapshotMountPoint(project, poolName string, snapshotName string) string {
-	return shared.VarPath("storage-pools", poolName, "containers-snapshots", projectPrefix(project, snapshotName))
+func getSnapshotMountPoint(projectName, poolName string, snapshotName string) string {
+	return shared.VarPath("storage-pools", poolName, "containers-snapshots", project.Prefix(projectName, snapshotName))
 }
 
 // ${LXD_DIR}/storage-pools/<pool>/images/<fingerprint>
diff --git a/lxd/storage_btrfs.go b/lxd/storage_btrfs.go
index 12cca23881..d323f14f4a 100644
--- a/lxd/storage_btrfs.go
+++ b/lxd/storage_btrfs.go
@@ -17,6 +17,7 @@ import (
 	"golang.org/x/sys/unix"
 
 	"github.com/lxc/lxd/lxd/migration"
+	"github.com/lxc/lxd/lxd/project"
 	"github.com/lxc/lxd/lxd/state"
 	"github.com/lxc/lxd/lxd/util"
 	"github.com/lxc/lxd/shared"
@@ -51,8 +52,8 @@ func (s *storageBtrfs) getContainerSubvolumePath(poolName string) string {
 }
 
 // ${LXD_DIR}/storage-pools/<pool>/containers-snapshots
-func getSnapshotSubvolumePath(project, poolName string, containerName string) string {
-	return shared.VarPath("storage-pools", poolName, "containers-snapshots", projectPrefix(project, containerName))
+func getSnapshotSubvolumePath(projectName, poolName string, containerName string) string {
+	return shared.VarPath("storage-pools", poolName, "containers-snapshots", project.Prefix(projectName, containerName))
 }
 
 // ${LXD_DIR}/storage-pools/<pool>/images
@@ -819,7 +820,7 @@ func (s *storageBtrfs) ContainerStorageReady(container container) bool {
 	return isBtrfsSubVolume(containerMntPoint)
 }
 
-func (s *storageBtrfs) doContainerCreate(project, name string, privileged bool) error {
+func (s *storageBtrfs) doContainerCreate(projectName, name string, privileged bool) error {
 	logger.Debugf("Creating empty BTRFS storage volume for container \"%s\" on storage pool \"%s\"", s.volume.Name, s.pool.Name)
 
 	_, err := s.StoragePoolMount()
@@ -842,7 +843,7 @@ func (s *storageBtrfs) doContainerCreate(project, name string, privileged bool)
 	}
 
 	// Create empty subvolume for container.
-	containerSubvolumeName := getContainerMountPoint(project, s.pool.Name, name)
+	containerSubvolumeName := getContainerMountPoint(projectName, s.pool.Name, name)
 	err = btrfsSubVolumeCreate(containerSubvolumeName)
 	if err != nil {
 		return err
@@ -850,7 +851,7 @@ func (s *storageBtrfs) doContainerCreate(project, name string, privileged bool)
 
 	// Create the mountpoint for the container at:
 	// ${LXD_DIR}/containers/<name>
-	err = createContainerMountpoint(containerSubvolumeName, shared.VarPath("containers", projectPrefix(project, name)), privileged)
+	err = createContainerMountpoint(containerSubvolumeName, shared.VarPath("containers", project.Prefix(projectName, name)), privileged)
 	if err != nil {
 		return err
 	}
@@ -991,7 +992,7 @@ func (s *storageBtrfs) ContainerDelete(container container) error {
 
 	// Delete potential symlink
 	// ${LXD_DIR}/snapshots/<container_name> to ${POOL}/snapshots/<container_name>
-	snapshotSymlink := shared.VarPath("snapshots", projectPrefix(container.Project(), container.Name()))
+	snapshotSymlink := shared.VarPath("snapshots", project.Prefix(container.Project(), container.Name()))
 	if shared.PathExists(snapshotSymlink) {
 		err := os.Remove(snapshotSymlink)
 		if err != nil {
@@ -1045,8 +1046,8 @@ func (s *storageBtrfs) copySnapshot(target container, source container) error {
 
 	targetParentName, _, _ := containerGetParentAndSnapshotName(target.Name())
 	containersPath := getSnapshotMountPoint(target.Project(), s.pool.Name, targetParentName)
-	snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", projectPrefix(target.Project(), targetParentName))
-	snapshotMntPointSymlink := shared.VarPath("snapshots", projectPrefix(target.Project(), targetParentName))
+	snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", project.Prefix(target.Project(), targetParentName))
+	snapshotMntPointSymlink := shared.VarPath("snapshots", project.Prefix(target.Project(), targetParentName))
 	err := createSnapshotMountpoint(containersPath, snapshotMntPointSymlinkTarget, snapshotMntPointSymlink)
 	if err != nil {
 		return err
@@ -1259,7 +1260,7 @@ func (s *storageBtrfs) ContainerRename(container container, newName string) erro
 		return err
 	}
 
-	newSymlink := shared.VarPath("containers", projectPrefix(container.Project(), newName))
+	newSymlink := shared.VarPath("containers", project.Prefix(container.Project(), newName))
 	err = renameContainerMountpoint(oldContainerSubvolumeName, container.Path(), newContainerSubvolumeName, newSymlink)
 	if err != nil {
 		return err
@@ -1274,8 +1275,8 @@ func (s *storageBtrfs) ContainerRename(container container, newName string) erro
 		}
 	}
 
-	oldSnapshotSymlink := shared.VarPath("snapshots", projectPrefix(container.Project(), container.Name()))
-	newSnapshotSymlink := shared.VarPath("snapshots", projectPrefix(container.Project(), newName))
+	oldSnapshotSymlink := shared.VarPath("snapshots", project.Prefix(container.Project(), container.Name()))
+	newSnapshotSymlink := shared.VarPath("snapshots", project.Prefix(container.Project(), newName))
 	if shared.PathExists(oldSnapshotSymlink) {
 		err := os.Remove(oldSnapshotSymlink)
 		if err != nil {
@@ -1381,7 +1382,7 @@ func (s *storageBtrfs) ContainerGetUsage(container container) (int64, error) {
 	return s.btrfsPoolVolumeQGroupUsage(container.Path())
 }
 
-func (s *storageBtrfs) doContainerSnapshotCreate(project string, targetName string, sourceName string) error {
+func (s *storageBtrfs) doContainerSnapshotCreate(projectName string, targetName string, sourceName string) error {
 	logger.Debugf("Creating BTRFS storage volume for snapshot \"%s\" on storage pool \"%s\"", s.volume.Name, s.pool.Name)
 
 	_, err := s.StoragePoolMount()
@@ -1395,7 +1396,7 @@ func (s *storageBtrfs) doContainerSnapshotCreate(project string, targetName stri
 	// ${LXD_DIR}/storage-pools/<pool>/snapshots/. The btrfs tool will
 	// complain if the intermediate path does not exist, so create it if it
 	// doesn't already.
-	snapshotSubvolumePath := getSnapshotSubvolumePath(project, s.pool.Name, sourceName)
+	snapshotSubvolumePath := getSnapshotSubvolumePath(projectName, s.pool.Name, sourceName)
 	if !shared.PathExists(snapshotSubvolumePath) {
 		err := os.MkdirAll(snapshotSubvolumePath, containersDirMode)
 		if err != nil {
@@ -1403,8 +1404,8 @@ func (s *storageBtrfs) doContainerSnapshotCreate(project string, targetName stri
 		}
 	}
 
-	snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", projectPrefix(project, s.volume.Name))
-	snapshotMntPointSymlink := shared.VarPath("snapshots", projectPrefix(project, sourceName))
+	snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", project.Prefix(projectName, s.volume.Name))
+	snapshotMntPointSymlink := shared.VarPath("snapshots", project.Prefix(projectName, sourceName))
 	if !shared.PathExists(snapshotMntPointSymlink) {
 		if !shared.PathExists(snapshotMntPointSymlinkTarget) {
 			err = os.MkdirAll(snapshotMntPointSymlinkTarget, snapshotsDirMode)
@@ -1419,8 +1420,8 @@ func (s *storageBtrfs) doContainerSnapshotCreate(project string, targetName stri
 		}
 	}
 
-	srcContainerSubvolumeName := getContainerMountPoint(project, s.pool.Name, sourceName)
-	snapshotSubvolumeName := getSnapshotMountPoint(project, s.pool.Name, targetName)
+	srcContainerSubvolumeName := getContainerMountPoint(projectName, s.pool.Name, sourceName)
+	snapshotSubvolumeName := getSnapshotMountPoint(projectName, s.pool.Name, targetName)
 	err = s.btrfsPoolVolumesSnapshot(srcContainerSubvolumeName, snapshotSubvolumeName, true, true)
 	if err != nil {
 		return err
@@ -1440,8 +1441,8 @@ func (s *storageBtrfs) ContainerSnapshotCreate(snapshotContainer container, sour
 	return nil
 }
 
-func btrfsSnapshotDeleteInternal(project, poolName string, snapshotName string) error {
-	snapshotSubvolumeName := getSnapshotMountPoint(project, poolName, snapshotName)
+func btrfsSnapshotDeleteInternal(projectName, poolName string, snapshotName string) error {
+	snapshotSubvolumeName := getSnapshotMountPoint(projectName, poolName, snapshotName)
 	// Also delete any leftover .ro snapshot.
 	roSnapshotSubvolumeName := fmt.Sprintf("%s.ro", snapshotSubvolumeName)
 	names := []string{snapshotSubvolumeName, roSnapshotSubvolumeName}
@@ -1454,15 +1455,15 @@ func btrfsSnapshotDeleteInternal(project, poolName string, snapshotName string)
 		}
 	}
 
-	sourceSnapshotMntPoint := shared.VarPath("snapshots", projectPrefix(project, snapshotName))
+	sourceSnapshotMntPoint := shared.VarPath("snapshots", project.Prefix(projectName, snapshotName))
 	os.Remove(sourceSnapshotMntPoint)
 	os.Remove(snapshotSubvolumeName)
 
 	sourceName, _, _ := containerGetParentAndSnapshotName(snapshotName)
-	snapshotSubvolumePath := getSnapshotSubvolumePath(project, poolName, sourceName)
+	snapshotSubvolumePath := getSnapshotSubvolumePath(projectName, poolName, sourceName)
 	os.Remove(snapshotSubvolumePath)
 	if !shared.PathExists(snapshotSubvolumePath) {
-		snapshotMntPointSymlink := shared.VarPath("snapshots", projectPrefix(project, sourceName))
+		snapshotMntPointSymlink := shared.VarPath("snapshots", project.Prefix(projectName, sourceName))
 		os.Remove(snapshotMntPointSymlink)
 	}
 
@@ -1596,8 +1597,8 @@ func (s *storageBtrfs) ContainerSnapshotCreateEmpty(snapshotContainer container)
 		return err
 	}
 
-	snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", projectPrefix(snapshotContainer.Project(), sourceName))
-	snapshotMntPointSymlink := shared.VarPath("snapshots", projectPrefix(snapshotContainer.Project(), sourceName))
+	snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", project.Prefix(snapshotContainer.Project(), sourceName))
+	snapshotMntPointSymlink := shared.VarPath("snapshots", project.Prefix(snapshotContainer.Project(), sourceName))
 	if !shared.PathExists(snapshotMntPointSymlink) {
 		err := createContainerMountpoint(snapshotMntPointSymlinkTarget, snapshotMntPointSymlink, snapshotContainer.IsPrivileged())
 		if err != nil {
@@ -1873,8 +1874,8 @@ func (s *storageBtrfs) doContainerBackupLoadOptimized(info backupInfo, data io.R
 
 		// create mountpoint
 		snapshotMntPoint := getSnapshotMountPoint(info.Project, s.pool.Name, containerName)
-		snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", projectPrefix(info.Project, containerName))
-		snapshotMntPointSymlink := shared.VarPath("snapshots", projectPrefix(info.Project, containerName))
+		snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", project.Prefix(info.Project, containerName))
+		snapshotMntPointSymlink := shared.VarPath("snapshots", project.Prefix(info.Project, containerName))
 		err = createSnapshotMountpoint(snapshotMntPoint, snapshotMntPointSymlinkTarget, snapshotMntPointSymlink)
 		if err != nil {
 			feeder.Close()
@@ -1918,7 +1919,7 @@ func (s *storageBtrfs) doContainerBackupLoadOptimized(info backupInfo, data io.R
 	}
 
 	// Create mountpoints
-	err = createContainerMountpoint(containerMntPoint, shared.VarPath("containers", projectPrefix(info.Project, info.Name)), info.Privileged)
+	err = createContainerMountpoint(containerMntPoint, shared.VarPath("containers", project.Prefix(info.Project, info.Name)), info.Privileged)
 	if err != nil {
 		return err
 	}
@@ -2750,8 +2751,8 @@ func (s *storageBtrfs) MigrationSink(conn *websocket.Conn, op *operation, args M
 			return err
 		}
 
-		snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", containerPool, "containers-snapshots", projectPrefix(args.Container.Project(), containerName))
-		snapshotMntPointSymlink := shared.VarPath("snapshots", projectPrefix(args.Container.Project(), containerName))
+		snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", containerPool, "containers-snapshots", project.Prefix(args.Container.Project(), containerName))
+		snapshotMntPointSymlink := shared.VarPath("snapshots", project.Prefix(args.Container.Project(), containerName))
 		if !shared.PathExists(snapshotMntPointSymlink) {
 			err := os.Symlink(snapshotMntPointSymlinkTarget, snapshotMntPointSymlink)
 			if err != nil {
@@ -2797,14 +2798,14 @@ func (s *storageBtrfs) MigrationSink(conn *websocket.Conn, op *operation, args M
 				return err
 			}
 
-			snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", projectPrefix(args.Container.Project(), containerName))
-			snapshotMntPointSymlink := shared.VarPath("snapshots", projectPrefix(args.Container.Project(), containerName))
+			snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", project.Prefix(args.Container.Project(), containerName))
+			snapshotMntPointSymlink := shared.VarPath("snapshots", project.Prefix(args.Container.Project(), containerName))
 			err = createSnapshotMountpoint(snapshotMntPoint, snapshotMntPointSymlinkTarget, snapshotMntPointSymlink)
 			if err != nil {
 				return err
 			}
 
-			tmpSnapshotMntPoint, err := ioutil.TempDir(containersPath, projectPrefix(args.Container.Project(), containerName))
+			tmpSnapshotMntPoint, err := ioutil.TempDir(containersPath, project.Prefix(args.Container.Project(), containerName))
 			if err != nil {
 				return err
 			}
@@ -2825,7 +2826,7 @@ func (s *storageBtrfs) MigrationSink(conn *websocket.Conn, op *operation, args M
 
 	/* finally, do the real container */
 	containersMntPoint := getContainerMountPoint("default", s.pool.Name, "")
-	tmpContainerMntPoint, err := ioutil.TempDir(containersMntPoint, projectPrefix(args.Container.Project(), containerName))
+	tmpContainerMntPoint, err := ioutil.TempDir(containersMntPoint, project.Prefix(args.Container.Project(), containerName))
 	if err != nil {
 		return err
 	}
diff --git a/lxd/storage_ceph.go b/lxd/storage_ceph.go
index 438d7bdca5..6a1253f102 100644
--- a/lxd/storage_ceph.go
+++ b/lxd/storage_ceph.go
@@ -14,6 +14,7 @@ import (
 	"golang.org/x/sys/unix"
 
 	"github.com/lxc/lxd/lxd/db"
+	"github.com/lxc/lxd/lxd/project"
 	"github.com/lxc/lxd/lxd/state"
 	"github.com/lxc/lxd/shared"
 	"github.com/lxc/lxd/shared/api"
@@ -794,7 +795,7 @@ func (s *storageCeph) ContainerStorageReady(container container) bool {
 	name := container.Name()
 	logger.Debugf(`Checking if RBD storage volume for container "%s" on storage pool "%s" is ready`, name, s.pool.Name)
 
-	ok := cephRBDVolumeExists(s.ClusterName, s.OSDPoolName, projectPrefix(container.Project(), name),
+	ok := cephRBDVolumeExists(s.ClusterName, s.OSDPoolName, project.Prefix(container.Project(), name),
 		storagePoolVolumeTypeNameContainer, s.UserName)
 	if !ok {
 		logger.Debugf(`RBD storage volume for container "%s" on storage pool "%s" does not exist`, name, s.pool.Name)
@@ -880,7 +881,7 @@ func (s *storageCeph) ContainerCreateFromImage(container container, fingerprint
 		}
 	}
 
-	volumeName := projectPrefix(container.Project(), containerName)
+	volumeName := project.Prefix(container.Project(), containerName)
 	err := cephRBDCloneCreate(s.ClusterName, s.OSDPoolName, fingerprint,
 		storagePoolVolumeTypeNameImage, "readonly", s.OSDPoolName,
 		volumeName, storagePoolVolumeTypeNameContainer, s.UserName)
@@ -995,7 +996,7 @@ func (s *storageCeph) ContainerDelete(container container) error {
 		}
 	}
 
-	volumeName := projectPrefix(container.Project(), containerName)
+	volumeName := project.Prefix(container.Project(), containerName)
 	rbdVolumeExists := cephRBDVolumeExists(s.ClusterName, s.OSDPoolName,
 		volumeName, storagePoolVolumeTypeNameContainer, s.UserName)
 
@@ -1199,7 +1200,7 @@ func (s *storageCeph) ContainerCopy(target container, source container,
 
 		// create empty dummy volume
 		err = cephRBDVolumeCreate(s.ClusterName, s.OSDPoolName,
-			projectPrefix(target.Project(), targetContainerName), storagePoolVolumeTypeNameContainer,
+			project.Prefix(target.Project(), targetContainerName), storagePoolVolumeTypeNameContainer,
 			"0", s.UserName)
 		if err != nil {
 			logger.Errorf(`Failed to create RBD storage volume "%s" on storage pool "%s": %s`, targetContainerName, s.pool.Name, err)
@@ -1214,7 +1215,7 @@ func (s *storageCeph) ContainerCopy(target container, source container,
 			}
 
 			err := cephRBDVolumeDelete(s.ClusterName, s.OSDPoolName,
-				projectPrefix(target.Project(), targetContainerName),
+				project.Prefix(target.Project(), targetContainerName),
 				storagePoolVolumeTypeNameContainer, s.UserName)
 			if err != nil {
 				logger.Warnf(`Failed to delete RBD storage volume "%s" on storage pool "%s": %s`, targetContainerName, s.pool.Name, err)
@@ -1225,7 +1226,7 @@ func (s *storageCeph) ContainerCopy(target container, source container,
 		targetVolumeName := fmt.Sprintf(
 			"%s/container_%s",
 			s.OSDPoolName,
-			projectPrefix(target.Project(), targetContainerName))
+			project.Prefix(target.Project(), targetContainerName))
 
 		lastSnap := ""
 		for i, snap := range snapshots {
@@ -1240,7 +1241,7 @@ func (s *storageCeph) ContainerCopy(target container, source container,
 			sourceVolumeName := fmt.Sprintf(
 				"%s/container_%s at snapshot_%s",
 				s.OSDPoolName,
-				projectPrefix(source.Project(), sourceContainerName),
+				project.Prefix(source.Project(), sourceContainerName),
 				snapOnlyName)
 
 			err = s.copyWithSnapshots(
@@ -1261,7 +1262,7 @@ func (s *storageCeph) ContainerCopy(target container, source container,
 				}
 
 				err := cephRBDSnapshotDelete(s.ClusterName,
-					s.OSDPoolName, projectPrefix(target.Project(), targetContainerName),
+					s.OSDPoolName, project.Prefix(target.Project(), targetContainerName),
 					storagePoolVolumeTypeNameContainer,
 					snapOnlyName, s.UserName)
 				if err != nil {
@@ -1280,11 +1281,11 @@ func (s *storageCeph) ContainerCopy(target container, source container,
 				"storage-pools",
 				s.pool.Name,
 				"containers-snapshots",
-				projectPrefix(target.Project(), targetContainerName))
+				project.Prefix(target.Project(), targetContainerName))
 
 			snapshotMntPointSymlink := shared.VarPath(
 				"snapshots",
-				projectPrefix(target.Project(), targetContainerName))
+				project.Prefix(target.Project(), targetContainerName))
 
 			err := createSnapshotMountpoint(
 				containersPath,
@@ -1315,7 +1316,7 @@ func (s *storageCeph) ContainerCopy(target container, source container,
 		sourceVolumeName := fmt.Sprintf(
 			"%s/container_%s",
 			s.OSDPoolName,
-			projectPrefix(source.Project(), sourceContainerName))
+			project.Prefix(source.Project(), sourceContainerName))
 		err = s.copyWithSnapshots(
 			sourceVolumeName,
 			targetVolumeName,
@@ -1327,7 +1328,7 @@ func (s *storageCeph) ContainerCopy(target container, source container,
 		logger.Debugf(`Copied RBD container storage %s to %s`, sourceVolumeName, targetVolumeName)
 
 		// Re-generate the UUID
-		err := s.cephRBDGenerateUUID(projectPrefix(target.Project(), targetContainerName), storagePoolVolumeTypeNameContainer)
+		err := s.cephRBDGenerateUUID(project.Prefix(target.Project(), targetContainerName), storagePoolVolumeTypeNameContainer)
 		if err != nil {
 			return err
 		}
@@ -1385,7 +1386,7 @@ func (s *storageCeph) ContainerUmount(c container, path string) (bool, error) {
 		containerMntPoint = getSnapshotMountPoint(c.Project(), s.pool.Name, name)
 	}
 
-	containerUmountLockID := getContainerUmountLockID(s.pool.Name, projectPrefix(c.Project(), name))
+	containerUmountLockID := getContainerUmountLockID(s.pool.Name, project.Prefix(c.Project(), name))
 	lxdStorageMapLock.Lock()
 	if waitChannel, ok := lxdStorageOngoingOperationMap[containerUmountLockID]; ok {
 		lxdStorageMapLock.Unlock()
@@ -1506,7 +1507,7 @@ func (s *storageCeph) ContainerRename(c container, newName string) error {
 	oldContainerMntPoint := getContainerMountPoint(c.Project(), s.pool.Name, oldName)
 	oldContainerMntPointSymlink := containerPath
 	newContainerMntPoint := getContainerMountPoint(c.Project(), s.pool.Name, newName)
-	newContainerMntPointSymlink := shared.VarPath("containers", projectPrefix(c.Project(), newName))
+	newContainerMntPointSymlink := shared.VarPath("containers", project.Prefix(c.Project(), newName))
 	err = renameContainerMountpoint(
 		oldContainerMntPoint,
 		oldContainerMntPointSymlink,
@@ -1545,7 +1546,7 @@ func (s *storageCeph) ContainerRename(c container, newName string) error {
 	}()
 
 	// Remove old symlink.
-	oldSnapshotPath := shared.VarPath("snapshots", projectPrefix(c.Project(), oldName))
+	oldSnapshotPath := shared.VarPath("snapshots", project.Prefix(c.Project(), oldName))
 	if shared.PathExists(oldSnapshotPath) {
 		err := os.Remove(oldSnapshotPath)
 		if err != nil {
@@ -1562,7 +1563,7 @@ func (s *storageCeph) ContainerRename(c container, newName string) error {
 	}()
 
 	// Create new symlink.
-	newSnapshotPath := shared.VarPath("snapshots", projectPrefix(c.Project(), newName))
+	newSnapshotPath := shared.VarPath("snapshots", project.Prefix(c.Project(), newName))
 	if shared.PathExists(newSnapshotPath) {
 		err := os.Symlink(newSnapshotMntPoint, newSnapshotPath)
 		if err != nil {
@@ -1610,7 +1611,7 @@ func (s *storageCeph) ContainerRestore(target container, source container) error
 	}
 
 	// Re-generate the UUID
-	err = s.cephRBDGenerateUUID(projectPrefix(target.Project(), target.Name()), storagePoolVolumeTypeNameContainer)
+	err = s.cephRBDGenerateUUID(project.Prefix(target.Project(), target.Name()), storagePoolVolumeTypeNameContainer)
 	if err != nil {
 		return err
 	}
@@ -1651,12 +1652,12 @@ func (s *storageCeph) ContainerSnapshotDelete(snapshotContainer container) error
 	snapshotName := fmt.Sprintf("snapshot_%s", sourceContainerSnapOnlyName)
 
 	rbdVolumeExists := cephRBDSnapshotExists(s.ClusterName, s.OSDPoolName,
-		projectPrefix(snapshotContainer.Project(), sourceContainerName), storagePoolVolumeTypeNameContainer,
+		project.Prefix(snapshotContainer.Project(), sourceContainerName), storagePoolVolumeTypeNameContainer,
 		snapshotName, s.UserName)
 
 	if rbdVolumeExists {
 		ret := cephContainerSnapshotDelete(s.ClusterName, s.OSDPoolName,
-			projectPrefix(snapshotContainer.Project(), sourceContainerName),
+			project.Prefix(snapshotContainer.Project(), sourceContainerName),
 			storagePoolVolumeTypeNameContainer, snapshotName, s.UserName)
 		if ret < 0 {
 			msg := fmt.Sprintf(`Failed to delete RBD storage volume for `+
@@ -1693,7 +1694,7 @@ func (s *storageCeph) ContainerSnapshotDelete(snapshotContainer container) error
 
 		// remove the snapshot symlink if possible
 		snapshotSymlink := shared.VarPath("snapshots",
-			projectPrefix(snapshotContainer.Project(), sourceContainerName))
+			project.Prefix(snapshotContainer.Project(), sourceContainerName))
 		if shared.PathExists(snapshotSymlink) {
 			err := os.Remove(snapshotSymlink)
 			if err != nil {
@@ -1715,7 +1716,7 @@ func (s *storageCeph) ContainerSnapshotRename(c container, newName string) error
 	revert := true
 
 	containerOnlyName, snapOnlyName, _ := containerGetParentAndSnapshotName(oldName)
-	containerOnlyName = projectPrefix(c.Project(), containerOnlyName)
+	containerOnlyName = project.Prefix(c.Project(), containerOnlyName)
 	oldSnapOnlyName := fmt.Sprintf("snapshot_%s", snapOnlyName)
 	_, newSnapOnlyName, _ := containerGetParentAndSnapshotName(newName)
 	newSnapOnlyName = fmt.Sprintf("snapshot_%s", newSnapOnlyName)
@@ -1763,7 +1764,7 @@ func (s *storageCeph) ContainerSnapshotStart(c container) (bool, error) {
 	revert := true
 
 	containerOnlyName, snapOnlyName, _ := containerGetParentAndSnapshotName(containerName)
-	containerOnlyName = projectPrefix(c.Project(), containerOnlyName)
+	containerOnlyName = project.Prefix(c.Project(), containerOnlyName)
 
 	// protect
 	prefixedSnapOnlyName := fmt.Sprintf("snapshot_%s", snapOnlyName)
@@ -1893,7 +1894,7 @@ func (s *storageCeph) ContainerSnapshotStop(c container) (bool, error) {
 	logger.Debugf("Unmounted %s", containerMntPoint)
 
 	containerOnlyName, snapOnlyName, _ := containerGetParentAndSnapshotName(containerName)
-	containerOnlyName = projectPrefix(c.Project(), containerOnlyName)
+	containerOnlyName = project.Prefix(c.Project(), containerOnlyName)
 	cloneName := fmt.Sprintf("%s_%s_start_clone", containerOnlyName, snapOnlyName)
 
 	// Unmap the RBD volume
diff --git a/lxd/storage_ceph_migration.go b/lxd/storage_ceph_migration.go
index 899a356aed..517a2d4edf 100644
--- a/lxd/storage_ceph_migration.go
+++ b/lxd/storage_ceph_migration.go
@@ -9,6 +9,7 @@ import (
 
 	"github.com/lxc/lxd/lxd/db"
 	"github.com/lxc/lxd/lxd/migration"
+	"github.com/lxc/lxd/lxd/project"
 	"github.com/lxc/lxd/shared"
 	"github.com/lxc/lxd/shared/logger"
 
@@ -33,7 +34,7 @@ func (s *rbdMigrationSourceDriver) Cleanup() {
 
 	if s.stoppedSnapName != "" {
 		err := cephRBDSnapshotDelete(s.ceph.ClusterName, s.ceph.OSDPoolName,
-			projectPrefix(s.container.Project(), containerName), storagePoolVolumeTypeNameContainer,
+			project.Prefix(s.container.Project(), containerName), storagePoolVolumeTypeNameContainer,
 			s.stoppedSnapName, s.ceph.UserName)
 		if err != nil {
 			logger.Warnf(`Failed to delete RBD snapshot "%s" of container "%s"`, s.stoppedSnapName, containerName)
@@ -42,7 +43,7 @@ func (s *rbdMigrationSourceDriver) Cleanup() {
 
 	if s.runningSnapName != "" {
 		err := cephRBDSnapshotDelete(s.ceph.ClusterName, s.ceph.OSDPoolName,
-			projectPrefix(s.container.Project(), containerName), storagePoolVolumeTypeNameContainer,
+			project.Prefix(s.container.Project(), containerName), storagePoolVolumeTypeNameContainer,
 			s.runningSnapName, s.ceph.UserName)
 		if err != nil {
 			logger.Warnf(`Failed to delete RBD snapshot "%s" of container "%s"`, s.runningSnapName, containerName)
@@ -54,7 +55,7 @@ func (s *rbdMigrationSourceDriver) SendAfterCheckpoint(conn *websocket.Conn, bwl
 	containerName := s.container.Name()
 	s.stoppedSnapName = fmt.Sprintf("migration-send-%s", uuid.NewRandom().String())
 	err := cephRBDSnapshotCreate(s.ceph.ClusterName, s.ceph.OSDPoolName,
-		projectPrefix(s.container.Project(), containerName), storagePoolVolumeTypeNameContainer,
+		project.Prefix(s.container.Project(), containerName), storagePoolVolumeTypeNameContainer,
 		s.stoppedSnapName, s.ceph.UserName)
 	if err != nil {
 		logger.Errorf(`Failed to create snapshot "%s" for RBD storage volume for image "%s" on storage pool "%s": %s`, s.stoppedSnapName, containerName, s.ceph.pool.Name, err)
@@ -62,7 +63,7 @@ func (s *rbdMigrationSourceDriver) SendAfterCheckpoint(conn *websocket.Conn, bwl
 	}
 
 	cur := fmt.Sprintf("%s/container_%s@%s", s.ceph.OSDPoolName,
-		projectPrefix(s.container.Project(), containerName), s.stoppedSnapName)
+		project.Prefix(s.container.Project(), containerName), s.stoppedSnapName)
 	err = s.rbdSend(conn, cur, s.runningSnapName, nil)
 	if err != nil {
 		logger.Errorf(`Failed to send exported diff of RBD storage volume "%s" from snapshot "%s": %s`, cur, s.runningSnapName, err)
@@ -110,7 +111,7 @@ func (s *rbdMigrationSourceDriver) SendWhileRunning(conn *websocket.Conn,
 			sendSnapName := fmt.Sprintf(
 				"%s/container_%s@%s",
 				s.ceph.OSDPoolName,
-				projectPrefix(s.container.Project(), containerName),
+				project.Prefix(s.container.Project(), containerName),
 				snap)
 
 			wrapper := StorageProgressReader(op, "fs_progress", snap)
@@ -130,7 +131,7 @@ func (s *rbdMigrationSourceDriver) SendWhileRunning(conn *websocket.Conn,
 
 	s.runningSnapName = fmt.Sprintf("migration-send-%s", uuid.NewRandom().String())
 	err := cephRBDSnapshotCreate(s.ceph.ClusterName, s.ceph.OSDPoolName,
-		projectPrefix(s.container.Project(), containerName), storagePoolVolumeTypeNameContainer,
+		project.Prefix(s.container.Project(), containerName), storagePoolVolumeTypeNameContainer,
 		s.runningSnapName, s.ceph.UserName)
 	if err != nil {
 		logger.Errorf(`Failed to create snapshot "%s" for RBD storage volume for image "%s" on storage pool "%s": %s`, s.runningSnapName, containerName, s.ceph.pool.Name, err)
@@ -138,7 +139,7 @@ func (s *rbdMigrationSourceDriver) SendWhileRunning(conn *websocket.Conn,
 	}
 
 	cur := fmt.Sprintf("%s/container_%s@%s", s.ceph.OSDPoolName,
-		projectPrefix(s.container.Project(), containerName), s.runningSnapName)
+		project.Prefix(s.container.Project(), containerName), s.runningSnapName)
 	wrapper := StorageProgressReader(op, "fs_progress", containerName)
 	err = s.rbdSend(conn, cur, lastSnap, wrapper)
 	if err != nil {
@@ -191,7 +192,7 @@ func (s *storageCeph) MigrationSource(args MigrationSourceArgs) (MigrationStorag
 	// that we send the oldest to newest snapshot, hopefully saving on xfer
 	// costs. Then, after all that, we send the container itself.
 	snapshots, err := cephRBDVolumeListSnapshots(s.ClusterName,
-		s.OSDPoolName, projectPrefix(args.Container.Project(), containerName),
+		s.OSDPoolName, project.Prefix(args.Container.Project(), containerName),
 		storagePoolVolumeTypeNameContainer, s.UserName)
 	if err != nil {
 		if err != db.ErrNoSuchObject {
@@ -249,8 +250,8 @@ func (s *storageCeph) MigrationSink(conn *websocket.Conn, op *operation, args Mi
 	// set to the correct cluster name for that LXD instance. Yeah, I think
 	// that's actually correct.
 	containerName := args.Container.Name()
-	if !cephRBDVolumeExists(s.ClusterName, s.OSDPoolName, projectPrefix(args.Container.Project(), containerName), storagePoolVolumeTypeNameContainer, s.UserName) {
-		err := cephRBDVolumeCreate(s.ClusterName, s.OSDPoolName, projectPrefix(args.Container.Project(), containerName), storagePoolVolumeTypeNameContainer, "0", s.UserName)
+	if !cephRBDVolumeExists(s.ClusterName, s.OSDPoolName, project.Prefix(args.Container.Project(), containerName), storagePoolVolumeTypeNameContainer, s.UserName) {
+		err := cephRBDVolumeCreate(s.ClusterName, s.OSDPoolName, project.Prefix(args.Container.Project(), containerName), storagePoolVolumeTypeNameContainer, "0", s.UserName)
 		if err != nil {
 			logger.Errorf(`Failed to create RBD storage volume "%s" for cluster "%s" in OSD pool "%s" on storage pool "%s": %s`, containerName, s.ClusterName, s.OSDPoolName, s.pool.Name, err)
 			return err
@@ -259,8 +260,8 @@ func (s *storageCeph) MigrationSink(conn *websocket.Conn, op *operation, args Mi
 	}
 
 	if len(args.Snapshots) > 0 {
-		snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", projectPrefix(args.Container.Project(), containerName))
-		snapshotMntPointSymlink := shared.VarPath("snapshots", projectPrefix(args.Container.Project(), containerName))
+		snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", project.Prefix(args.Container.Project(), containerName))
+		snapshotMntPointSymlink := shared.VarPath("snapshots", project.Prefix(args.Container.Project(), containerName))
 		if !shared.PathExists(snapshotMntPointSymlink) {
 			err := os.Symlink(snapshotMntPointSymlinkTarget, snapshotMntPointSymlink)
 			if err != nil {
@@ -270,7 +271,7 @@ func (s *storageCeph) MigrationSink(conn *websocket.Conn, op *operation, args Mi
 	}
 
 	// Now we're ready to receive the actual fs.
-	recvName := fmt.Sprintf("%s/container_%s", s.OSDPoolName, projectPrefix(args.Container.Project(), containerName))
+	recvName := fmt.Sprintf("%s/container_%s", s.OSDPoolName, project.Prefix(args.Container.Project(), containerName))
 	for _, snap := range args.Snapshots {
 		curSnapName := snap.GetName()
 		ctArgs := snapshotProtobufToContainerArgs(args.Container.Project(), containerName, snap)
@@ -310,7 +311,7 @@ func (s *storageCeph) MigrationSink(conn *websocket.Conn, op *operation, args Mi
 	}
 
 	defer func() {
-		snaps, err := cephRBDVolumeListSnapshots(s.ClusterName, s.OSDPoolName, projectPrefix(args.Container.Project(), containerName), storagePoolVolumeTypeNameContainer, s.UserName)
+		snaps, err := cephRBDVolumeListSnapshots(s.ClusterName, s.OSDPoolName, project.Prefix(args.Container.Project(), containerName), storagePoolVolumeTypeNameContainer, s.UserName)
 		if err == nil {
 			for _, snap := range snaps {
 				snapOnlyName, _, _ := containerGetParentAndSnapshotName(snap)
@@ -318,7 +319,7 @@ func (s *storageCeph) MigrationSink(conn *websocket.Conn, op *operation, args Mi
 					continue
 				}
 
-				err := cephRBDSnapshotDelete(s.ClusterName, s.OSDPoolName, projectPrefix(args.Container.Project(), containerName), storagePoolVolumeTypeNameContainer, snapOnlyName, s.UserName)
+				err := cephRBDSnapshotDelete(s.ClusterName, s.OSDPoolName, project.Prefix(args.Container.Project(), containerName), storagePoolVolumeTypeNameContainer, snapOnlyName, s.UserName)
 				if err != nil {
 					logger.Warnf(`Failed to delete RBD container storage for snapshot "%s" of container "%s"`, snapOnlyName, containerName)
 				}
@@ -345,7 +346,7 @@ func (s *storageCeph) MigrationSink(conn *websocket.Conn, op *operation, args Mi
 	}
 
 	// Re-generate the UUID
-	err = s.cephRBDGenerateUUID(projectPrefix(args.Container.Project(), args.Container.Name()), storagePoolVolumeTypeNameContainer)
+	err = s.cephRBDGenerateUUID(project.Prefix(args.Container.Project(), args.Container.Name()), storagePoolVolumeTypeNameContainer)
 	if err != nil {
 		return err
 	}
diff --git a/lxd/storage_ceph_utils.go b/lxd/storage_ceph_utils.go
index 4f6b3cf9e3..2ae569d358 100644
--- a/lxd/storage_ceph_utils.go
+++ b/lxd/storage_ceph_utils.go
@@ -14,6 +14,7 @@ import (
 	"golang.org/x/sys/unix"
 
 	"github.com/lxc/lxd/lxd/db"
+	"github.com/lxc/lxd/lxd/project"
 	"github.com/lxc/lxd/shared"
 	"github.com/lxc/lxd/shared/api"
 	"github.com/lxc/lxd/shared/logger"
@@ -714,8 +715,8 @@ func (s *storageCeph) copyWithoutSnapshotsFull(target container,
 	logger.Debugf(`Creating non-sparse copy of RBD storage volume for container "%s" to "%s" without snapshots`, source.Name(), target.Name())
 
 	sourceIsSnapshot := source.IsSnapshot()
-	sourceContainerName := projectPrefix(source.Project(), source.Name())
-	targetContainerName := projectPrefix(target.Project(), target.Name())
+	sourceContainerName := project.Prefix(source.Project(), source.Name())
+	targetContainerName := project.Prefix(target.Project(), target.Name())
 	oldVolumeName := fmt.Sprintf("%s/container_%s", s.OSDPoolName,
 		sourceContainerName)
 	newVolumeName := fmt.Sprintf("%s/container_%s", s.OSDPoolName,
@@ -743,7 +744,7 @@ func (s *storageCeph) copyWithoutSnapshotsFull(target container,
 	}
 
 	// Re-generate the UUID
-	err = s.cephRBDGenerateUUID(projectPrefix(target.Project(), target.Name()), storagePoolVolumeTypeNameContainer)
+	err = s.cephRBDGenerateUUID(project.Prefix(target.Project(), target.Name()), storagePoolVolumeTypeNameContainer)
 	if err != nil {
 		return err
 	}
@@ -784,8 +785,8 @@ func (s *storageCeph) copyWithoutSnapshotsSparse(target container,
 		target.Name())
 
 	sourceIsSnapshot := source.IsSnapshot()
-	sourceContainerName := projectPrefix(source.Project(), source.Name())
-	targetContainerName := projectPrefix(target.Project(), target.Name())
+	sourceContainerName := project.Prefix(source.Project(), source.Name())
+	targetContainerName := project.Prefix(target.Project(), target.Name())
 	sourceContainerOnlyName := sourceContainerName
 	sourceSnapshotOnlyName := ""
 	snapshotName := fmt.Sprintf("zombie_snapshot_%s",
@@ -824,7 +825,7 @@ func (s *storageCeph) copyWithoutSnapshotsSparse(target container,
 	}
 
 	// Re-generate the UUID
-	err = s.cephRBDGenerateUUID(projectPrefix(target.Project(), target.Name()), storagePoolVolumeTypeNameContainer)
+	err = s.cephRBDGenerateUUID(project.Prefix(target.Project(), target.Name()), storagePoolVolumeTypeNameContainer)
 	if err != nil {
 		return err
 	}
@@ -1571,7 +1572,7 @@ func (s *storageCeph) cephRBDVolumeDumpToFile(sourceVolumeName string, file stri
 func (s *storageCeph) cephRBDVolumeBackupCreate(tmpPath string, backup backup, source container) error {
 	sourceIsSnapshot := source.IsSnapshot()
 	sourceContainerName := source.Name()
-	sourceContainerOnlyName := projectPrefix(source.Project(), sourceContainerName)
+	sourceContainerOnlyName := project.Prefix(source.Project(), sourceContainerName)
 	sourceSnapshotOnlyName := ""
 
 	// Prepare for rsync
@@ -1589,8 +1590,8 @@ func (s *storageCeph) cephRBDVolumeBackupCreate(tmpPath string, backup backup, s
 	snapshotName := fmt.Sprintf("zombie_snapshot_%s", uuid.NewRandom().String())
 	if sourceIsSnapshot {
 		sourceContainerOnlyName, sourceSnapshotOnlyName, _ = containerGetParentAndSnapshotName(sourceContainerName)
-		sourceContainerOnlyName = projectPrefix(source.Project(), sourceContainerOnlyName)
-		snapshotName = fmt.Sprintf("snapshot_%s", projectPrefix(source.Project(), sourceSnapshotOnlyName))
+		sourceContainerOnlyName = project.Prefix(source.Project(), sourceContainerOnlyName)
+		snapshotName = fmt.Sprintf("snapshot_%s", project.Prefix(source.Project(), sourceSnapshotOnlyName))
 	} else {
 		// This is costly but we need to ensure that all cached data has
 		// been committed to disk. If we don't then the rbd snapshot of
@@ -1683,7 +1684,7 @@ func (s *storageCeph) cephRBDVolumeBackupCreate(tmpPath string, backup backup, s
 	return nil
 }
 
-func (s *storageCeph) doContainerCreate(project, name string, privileged bool) error {
+func (s *storageCeph) doContainerCreate(projectName, name string, privileged bool) error {
 	logger.Debugf(`Creating RBD storage volume for container "%s" on storage pool "%s"`, name, s.pool.Name)
 
 	revert := true
@@ -1697,7 +1698,7 @@ func (s *storageCeph) doContainerCreate(project, name string, privileged bool) e
 	logger.Debugf(`Retrieved size "%s" of RBD storage volume for container "%s" on storage pool "%s"`, RBDSize, name, s.pool.Name)
 
 	// create volume
-	volumeName := projectPrefix(project, name)
+	volumeName := project.Prefix(projectName, name)
 	err = cephRBDVolumeCreate(s.ClusterName, s.OSDPoolName, volumeName, storagePoolVolumeTypeNameContainer, RBDSize, s.UserName)
 	if err != nil {
 		logger.Errorf(`Failed to create RBD storage volume for container "%s" on storage pool "%s": %s`, name, s.pool.Name, err)
@@ -1743,8 +1744,8 @@ func (s *storageCeph) doContainerCreate(project, name string, privileged bool) e
 	}
 	logger.Debugf(`Created filesystem type "%s" on device path "%s" for RBD storage volume for container "%s" on storage pool "%s"`, RBDFilesystem, RBDDevPath, name, s.pool.Name)
 
-	containerPath := shared.VarPath("containers", projectPrefix(project, name))
-	containerMntPoint := getContainerMountPoint(project, s.pool.Name, name)
+	containerPath := shared.VarPath("containers", project.Prefix(projectName, name))
+	containerMntPoint := getContainerMountPoint(projectName, s.pool.Name, name)
 	err = createContainerMountpoint(containerMntPoint, containerPath, privileged)
 	if err != nil {
 		logger.Errorf(`Failed to create mountpoint "%s" for RBD storage volume for container "%s" on storage pool "%s": %s"`, containerMntPoint, name, s.pool.Name, err)
@@ -1770,11 +1771,11 @@ func (s *storageCeph) doContainerCreate(project, name string, privileged bool) e
 	return nil
 }
 
-func (s *storageCeph) doContainerMount(project string, name string) (bool, error) {
+func (s *storageCeph) doContainerMount(projectName string, name string) (bool, error) {
 	RBDFilesystem := s.getRBDFilesystem()
-	containerMntPoint := getContainerMountPoint(project, s.pool.Name, name)
+	containerMntPoint := getContainerMountPoint(projectName, s.pool.Name, name)
 	if shared.IsSnapshot(name) {
-		containerMntPoint = getSnapshotMountPoint(project, s.pool.Name, name)
+		containerMntPoint = getSnapshotMountPoint(projectName, s.pool.Name, name)
 	}
 
 	containerMountLockID := getContainerMountLockID(s.pool.Name, name)
@@ -1798,7 +1799,7 @@ func (s *storageCeph) doContainerMount(project string, name string) (bool, error
 	ourMount := false
 	RBDDevPath := ""
 	if !shared.IsMountPoint(containerMntPoint) {
-		volumeName := projectPrefix(project, name)
+		volumeName := project.Prefix(projectName, name)
 		RBDDevPath, ret = getRBDMappedDevPath(s.ClusterName,
 			s.OSDPoolName, storagePoolVolumeTypeNameContainer,
 			volumeName, true, s.UserName)
@@ -1825,7 +1826,7 @@ func (s *storageCeph) doContainerMount(project string, name string) (bool, error
 	return ourMount, nil
 }
 
-func (s *storageCeph) doContainerSnapshotCreate(project, targetName string, sourceName string) error {
+func (s *storageCeph) doContainerSnapshotCreate(projectName, targetName string, sourceName string) error {
 	logger.Debugf(`Creating RBD storage volume for snapshot "%s" on storage pool "%s"`, targetName, s.pool.Name)
 
 	revert := true
@@ -1833,7 +1834,7 @@ func (s *storageCeph) doContainerSnapshotCreate(project, targetName string, sour
 	_, targetSnapshotOnlyName, _ := containerGetParentAndSnapshotName(targetName)
 	targetSnapshotName := fmt.Sprintf("snapshot_%s", targetSnapshotOnlyName)
 	err := cephRBDSnapshotCreate(s.ClusterName, s.OSDPoolName,
-		projectPrefix(project, sourceName), storagePoolVolumeTypeNameContainer,
+		project.Prefix(projectName, sourceName), storagePoolVolumeTypeNameContainer,
 		targetSnapshotName, s.UserName)
 	if err != nil {
 		logger.Errorf(`Failed to create snapshot for RBD storage volume for snapshot "%s" on storage pool "%s": %s`, targetName, s.pool.Name, err)
@@ -1854,10 +1855,10 @@ func (s *storageCeph) doContainerSnapshotCreate(project, targetName string, sour
 		}
 	}()
 
-	targetContainerMntPoint := getSnapshotMountPoint(project, s.pool.Name, targetName)
+	targetContainerMntPoint := getSnapshotMountPoint(projectName, s.pool.Name, targetName)
 	sourceOnlyName, _, _ := containerGetParentAndSnapshotName(sourceName)
-	snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", projectPrefix(project, sourceOnlyName))
-	snapshotMntPointSymlink := shared.VarPath("snapshots", projectPrefix(project, sourceOnlyName))
+	snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", project.Prefix(projectName, sourceOnlyName))
+	snapshotMntPointSymlink := shared.VarPath("snapshots", project.Prefix(projectName, sourceOnlyName))
 	err = createSnapshotMountpoint(targetContainerMntPoint, snapshotMntPointSymlinkTarget, snapshotMntPointSymlink)
 	if err != nil {
 		logger.Errorf(`Failed to create mountpoint "%s", snapshot symlink target "%s", snapshot mountpoint symlink"%s" for RBD storage volume "%s" on storage pool "%s": %s`, targetContainerMntPoint, snapshotMntPointSymlinkTarget,
diff --git a/lxd/storage_dir.go b/lxd/storage_dir.go
index c2de065511..40ee902a0c 100644
--- a/lxd/storage_dir.go
+++ b/lxd/storage_dir.go
@@ -13,6 +13,7 @@ import (
 	"golang.org/x/sys/unix"
 
 	"github.com/lxc/lxd/lxd/migration"
+	"github.com/lxc/lxd/lxd/project"
 	"github.com/lxc/lxd/lxd/state"
 	"github.com/lxc/lxd/lxd/storage/quota"
 	"github.com/lxc/lxd/shared"
@@ -655,7 +656,7 @@ func (s *storageDir) ContainerDelete(container container) error {
 
 	// Delete potential leftover snapshot symlinks:
 	// ${LXD_DIR}/snapshots/<container_name> to ${POOL}/snapshots/<container_name>
-	snapshotSymlink := shared.VarPath("snapshots", projectPrefix(container.Project(), container.Name()))
+	snapshotSymlink := shared.VarPath("snapshots", project.Prefix(container.Project(), container.Name()))
 	if shared.PathExists(snapshotSymlink) {
 		err := os.Remove(snapshotSymlink)
 		if err != nil {
@@ -708,8 +709,8 @@ func (s *storageDir) copySnapshot(target container, targetPool string, source co
 
 	targetParentName, _, _ := containerGetParentAndSnapshotName(target.Name())
 	containersPath := getSnapshotMountPoint(target.Project(), targetPool, targetParentName)
-	snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", targetPool, "containers-snapshots", projectPrefix(target.Project(), targetParentName))
-	snapshotMntPointSymlink := shared.VarPath("snapshots", projectPrefix(target.Project(), targetParentName))
+	snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", targetPool, "containers-snapshots", project.Prefix(target.Project(), targetParentName))
+	snapshotMntPointSymlink := shared.VarPath("snapshots", project.Prefix(target.Project(), targetParentName))
 	err := createSnapshotMountpoint(containersPath, snapshotMntPointSymlinkTarget, snapshotMntPointSymlink)
 	if err != nil {
 		return err
@@ -857,9 +858,9 @@ func (s *storageDir) ContainerRename(container container, newName string) error
 	}
 
 	oldContainerMntPoint := getContainerMountPoint(container.Project(), s.pool.Name, container.Name())
-	oldContainerSymlink := shared.VarPath("containers", projectPrefix(container.Project(), container.Name()))
+	oldContainerSymlink := shared.VarPath("containers", project.Prefix(container.Project(), container.Name()))
 	newContainerMntPoint := getContainerMountPoint(container.Project(), s.pool.Name, newName)
-	newContainerSymlink := shared.VarPath("containers", projectPrefix(container.Project(), newName))
+	newContainerSymlink := shared.VarPath("containers", project.Prefix(container.Project(), newName))
 	err = renameContainerMountpoint(oldContainerMntPoint, oldContainerSymlink, newContainerMntPoint, newContainerSymlink)
 	if err != nil {
 		return err
@@ -878,8 +879,8 @@ func (s *storageDir) ContainerRename(container container, newName string) error
 
 	// Remove the old snapshot symlink:
 	// ${LXD_DIR}/snapshots/<old_container_name>
-	oldSnapshotSymlink := shared.VarPath("snapshots", projectPrefix(container.Project(), container.Name()))
-	newSnapshotSymlink := shared.VarPath("snapshots", projectPrefix(container.Project(), newName))
+	oldSnapshotSymlink := shared.VarPath("snapshots", project.Prefix(container.Project(), container.Name()))
+	newSnapshotSymlink := shared.VarPath("snapshots", project.Prefix(container.Project(), newName))
 	if shared.PathExists(oldSnapshotSymlink) {
 		err := os.Remove(oldSnapshotSymlink)
 		if err != nil {
@@ -1001,7 +1002,7 @@ onSuccess:
 	// Check if the symlink
 	// ${LXD_DIR}/snapshots/<source_container_name> to ${POOL_PATH}/snapshots/<source_container_name>
 	// exists and if not create it.
-	sourceContainerSymlink := shared.VarPath("snapshots", projectPrefix(sourceContainer.Project(), sourceContainerName))
+	sourceContainerSymlink := shared.VarPath("snapshots", project.Prefix(sourceContainer.Project(), sourceContainerName))
 	sourceContainerSymlinkTarget := getSnapshotMountPoint(sourceContainer.Project(), sourcePool, sourceContainerName)
 	if !shared.PathExists(sourceContainerSymlink) {
 		err = os.Symlink(sourceContainerSymlinkTarget, sourceContainerSymlink)
@@ -1044,8 +1045,8 @@ func (s *storageDir) ContainerSnapshotCreateEmpty(snapshotContainer container) e
 		targetContainerName)
 	sourceName, _, _ := containerGetParentAndSnapshotName(targetContainerName)
 	snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools",
-		s.pool.Name, "containers-snapshots", projectPrefix(snapshotContainer.Project(), sourceName))
-	snapshotMntPointSymlink := shared.VarPath("snapshots", projectPrefix(snapshotContainer.Project(), sourceName))
+		s.pool.Name, "containers-snapshots", project.Prefix(snapshotContainer.Project(), sourceName))
+	snapshotMntPointSymlink := shared.VarPath("snapshots", project.Prefix(snapshotContainer.Project(), sourceName))
 	err = createSnapshotMountpoint(targetContainerMntPoint,
 		snapshotMntPointSymlinkTarget, snapshotMntPointSymlink)
 	if err != nil {
@@ -1058,8 +1059,8 @@ func (s *storageDir) ContainerSnapshotCreateEmpty(snapshotContainer container) e
 	return nil
 }
 
-func dirSnapshotDeleteInternal(project, poolName string, snapshotName string) error {
-	snapshotContainerMntPoint := getSnapshotMountPoint(project, poolName, snapshotName)
+func dirSnapshotDeleteInternal(projectName, poolName string, snapshotName string) error {
+	snapshotContainerMntPoint := getSnapshotMountPoint(projectName, poolName, snapshotName)
 	if shared.PathExists(snapshotContainerMntPoint) {
 		err := os.RemoveAll(snapshotContainerMntPoint)
 		if err != nil {
@@ -1068,7 +1069,7 @@ func dirSnapshotDeleteInternal(project, poolName string, snapshotName string) er
 	}
 
 	sourceContainerName, _, _ := containerGetParentAndSnapshotName(snapshotName)
-	snapshotContainerPath := getSnapshotMountPoint(project, poolName, sourceContainerName)
+	snapshotContainerPath := getSnapshotMountPoint(projectName, poolName, sourceContainerName)
 	empty, _ := shared.PathIsEmpty(snapshotContainerPath)
 	if empty == true {
 		err := os.Remove(snapshotContainerPath)
@@ -1076,7 +1077,7 @@ func dirSnapshotDeleteInternal(project, poolName string, snapshotName string) er
 			return err
 		}
 
-		snapshotSymlink := shared.VarPath("snapshots", projectPrefix(project, sourceContainerName))
+		snapshotSymlink := shared.VarPath("snapshots", project.Prefix(projectName, sourceContainerName))
 		if shared.PathExists(snapshotSymlink) {
 			err := os.Remove(snapshotSymlink)
 			if err != nil {
@@ -1241,7 +1242,7 @@ func (s *storageDir) ContainerBackupLoad(info backupInfo, data io.ReadSeeker, ta
 
 	// Create mountpoints
 	containerMntPoint := getContainerMountPoint(info.Project, s.pool.Name, info.Name)
-	err = createContainerMountpoint(containerMntPoint, containerPath(projectPrefix(info.Project, info.Name), false), info.Privileged)
+	err = createContainerMountpoint(containerMntPoint, containerPath(project.Prefix(info.Project, info.Name), false), info.Privileged)
 	if err != nil {
 		return errors.Wrap(err, "Create container mount point")
 	}
@@ -1265,8 +1266,8 @@ func (s *storageDir) ContainerBackupLoad(info backupInfo, data io.ReadSeeker, ta
 		// Create mountpoints
 		snapshotMntPoint := getSnapshotMountPoint(info.Project, s.pool.Name, info.Name)
 		snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name,
-			"containers-snapshots", projectPrefix(info.Project, info.Name))
-		snapshotMntPointSymlink := shared.VarPath("snapshots", projectPrefix(info.Project, info.Name))
+			"containers-snapshots", project.Prefix(info.Project, info.Name))
+		snapshotMntPointSymlink := shared.VarPath("snapshots", project.Prefix(info.Project, info.Name))
 		err := createSnapshotMountpoint(snapshotMntPoint, snapshotMntPointSymlinkTarget,
 			snapshotMntPointSymlink)
 		if err != nil {
diff --git a/lxd/storage_lvm.go b/lxd/storage_lvm.go
index 2a6d6ac3fa..ae851fbcd9 100644
--- a/lxd/storage_lvm.go
+++ b/lxd/storage_lvm.go
@@ -14,6 +14,7 @@ import (
 	"github.com/pkg/errors"
 
 	"github.com/lxc/lxd/lxd/migration"
+	"github.com/lxc/lxd/lxd/project"
 	"github.com/lxc/lxd/lxd/state"
 	"github.com/lxc/lxd/shared"
 	"github.com/lxc/lxd/shared/api"
@@ -974,8 +975,8 @@ func (s *storageLvm) ContainerCreate(container container) error {
 	if container.IsSnapshot() {
 		containerMntPoint := getSnapshotMountPoint(container.Project(), s.pool.Name, containerName)
 		sourceName, _, _ := containerGetParentAndSnapshotName(containerName)
-		snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", projectPrefix(container.Project(), sourceName))
-		snapshotMntPointSymlink := shared.VarPath("snapshots", projectPrefix(container.Project(), sourceName))
+		snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", project.Prefix(container.Project(), sourceName))
+		snapshotMntPointSymlink := shared.VarPath("snapshots", project.Prefix(container.Project(), sourceName))
 		err := os.MkdirAll(containerMntPoint, 0711)
 		if err != nil {
 			return err
@@ -1082,13 +1083,13 @@ func (s *storageLvm) ContainerCanRestore(container container, sourceContainer co
 	return nil
 }
 
-func lvmContainerDeleteInternal(project, poolName string, ctName string, isSnapshot bool, vgName string, ctPath string) error {
+func lvmContainerDeleteInternal(projectName, poolName string, ctName string, isSnapshot bool, vgName string, ctPath string) error {
 	containerMntPoint := ""
 	containerLvmName := containerNameToLVName(ctName)
 	if isSnapshot {
-		containerMntPoint = getSnapshotMountPoint(project, poolName, ctName)
+		containerMntPoint = getSnapshotMountPoint(projectName, poolName, ctName)
 	} else {
-		containerMntPoint = getContainerMountPoint(project, poolName, ctName)
+		containerMntPoint = getContainerMountPoint(projectName, poolName, ctName)
 	}
 
 	if shared.IsMountPoint(containerMntPoint) {
@@ -1099,12 +1100,12 @@ func lvmContainerDeleteInternal(project, poolName string, ctName string, isSnaps
 		}
 	}
 
-	containerLvmDevPath := getLvmDevPath(project, vgName,
+	containerLvmDevPath := getLvmDevPath(projectName, vgName,
 		storagePoolVolumeAPIEndpointContainers, containerLvmName)
 
 	lvExists, _ := storageLVExists(containerLvmDevPath)
 	if lvExists {
-		err := removeLV(project, vgName, storagePoolVolumeAPIEndpointContainers, containerLvmName)
+		err := removeLV(projectName, vgName, storagePoolVolumeAPIEndpointContainers, containerLvmName)
 		if err != nil {
 			return err
 		}
@@ -1113,8 +1114,8 @@ func lvmContainerDeleteInternal(project, poolName string, ctName string, isSnaps
 	var err error
 	if isSnapshot {
 		sourceName, _, _ := containerGetParentAndSnapshotName(ctName)
-		snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", poolName, "containers-snapshots", projectPrefix(project, sourceName))
-		snapshotMntPointSymlink := shared.VarPath("snapshots", projectPrefix(project, sourceName))
+		snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", poolName, "containers-snapshots", project.Prefix(projectName, sourceName))
+		snapshotMntPointSymlink := shared.VarPath("snapshots", project.Prefix(projectName, sourceName))
 		err = deleteSnapshotMountpoint(containerMntPoint, snapshotMntPointSymlinkTarget, snapshotMntPointSymlink)
 	} else {
 		err = deleteContainerMountpoint(containerMntPoint, ctPath, "lvm")
@@ -1404,7 +1405,7 @@ func (s *storageLvm) ContainerRename(container container, newContainerName strin
 		oldContainerMntPoint := getContainerMountPoint(container.Project(), s.pool.Name, oldName)
 		oldContainerMntPointSymlink := container.Path()
 		newContainerMntPoint := getContainerMountPoint(container.Project(), s.pool.Name, newContainerName)
-		newContainerMntPointSymlink := shared.VarPath("containers", projectPrefix(container.Project(), newContainerName))
+		newContainerMntPointSymlink := shared.VarPath("containers", project.Prefix(container.Project(), newContainerName))
 		err = renameContainerMountpoint(oldContainerMntPoint, oldContainerMntPointSymlink, newContainerMntPoint, newContainerMntPointSymlink)
 		if err != nil {
 			return err
@@ -1419,8 +1420,8 @@ func (s *storageLvm) ContainerRename(container container, newContainerName strin
 			}
 		}
 
-		oldSnapshotSymlink := shared.VarPath("snapshots", projectPrefix(container.Project(), oldName))
-		newSnapshotSymlink := shared.VarPath("snapshots", projectPrefix(container.Project(), newContainerName))
+		oldSnapshotSymlink := shared.VarPath("snapshots", project.Prefix(container.Project(), oldName))
+		newSnapshotSymlink := shared.VarPath("snapshots", project.Prefix(container.Project(), newContainerName))
 		if shared.PathExists(oldSnapshotSymlink) {
 			err := os.Remove(oldSnapshotSymlink)
 			if err != nil {
@@ -1593,7 +1594,7 @@ func (s *storageLvm) ContainerSnapshotStart(container container) (bool, error) {
 	}
 
 	if !wasWritableAtCheck {
-		output, err := shared.TryRunCommand("lvchange", "-prw", fmt.Sprintf("%s/%s_%s", poolName, storagePoolVolumeAPIEndpointContainers, projectPrefix(container.Project(), containerLvmName)))
+		output, err := shared.TryRunCommand("lvchange", "-prw", fmt.Sprintf("%s/%s_%s", poolName, storagePoolVolumeAPIEndpointContainers, project.Prefix(container.Project(), containerLvmName)))
 		if err != nil {
 			logger.Errorf("Failed to make LVM snapshot \"%s\" read-write: %s", containerName, output)
 			return false, err
@@ -1651,7 +1652,7 @@ func (s *storageLvm) ContainerSnapshotStop(container container) (bool, error) {
 	}
 
 	if wasWritableAtCheck {
-		containerLvmName := containerNameToLVName(projectPrefix(container.Project(), containerName))
+		containerLvmName := containerNameToLVName(project.Prefix(container.Project(), containerName))
 		output, err := shared.TryRunCommand("lvchange", "-pr", fmt.Sprintf("%s/%s_%s", poolName, storagePoolVolumeAPIEndpointContainers, containerLvmName))
 		if err != nil {
 			logger.Errorf("Failed to make LVM snapshot read-only: %s", output)
@@ -1837,15 +1838,15 @@ func (s *storageLvm) ContainerBackupLoad(info backupInfo, data io.ReadSeeker, ta
 	return nil
 }
 
-func (s *storageLvm) doContainerBackupLoad(project, containerName string, privileged bool,
+func (s *storageLvm) doContainerBackupLoad(projectName, containerName string, privileged bool,
 	snapshot bool) (string, error) {
 	tryUndo := true
 
 	var containerPath string
 	if snapshot {
-		containerPath = shared.VarPath("snapshots", projectPrefix(project, containerName))
+		containerPath = shared.VarPath("snapshots", project.Prefix(projectName, containerName))
 	} else {
-		containerPath = shared.VarPath("containers", projectPrefix(project, containerName))
+		containerPath = shared.VarPath("containers", project.Prefix(projectName, containerName))
 	}
 	containerLvmName := containerNameToLVName(containerName)
 	thinPoolName := s.getLvmThinpoolName()
@@ -1864,11 +1865,11 @@ func (s *storageLvm) doContainerBackupLoad(project, containerName string, privil
 	}
 
 	if !snapshot {
-		err = lvmCreateLv(project, poolName, thinPoolName, containerLvmName, lvFsType, lvSize,
+		err = lvmCreateLv(projectName, poolName, thinPoolName, containerLvmName, lvFsType, lvSize,
 			storagePoolVolumeAPIEndpointContainers, s.useThinpool)
 	} else {
 		cname, _, _ := containerGetParentAndSnapshotName(containerName)
-		_, err = s.createSnapshotLV(project, poolName, cname, storagePoolVolumeAPIEndpointContainers,
+		_, err = s.createSnapshotLV(projectName, poolName, cname, storagePoolVolumeAPIEndpointContainers,
 			containerLvmName, storagePoolVolumeAPIEndpointContainers, false, s.useThinpool)
 	}
 	if err != nil {
@@ -1877,16 +1878,16 @@ func (s *storageLvm) doContainerBackupLoad(project, containerName string, privil
 
 	defer func() {
 		if tryUndo {
-			lvmContainerDeleteInternal(project, s.pool.Name, containerName, false, poolName,
+			lvmContainerDeleteInternal(projectName, s.pool.Name, containerName, false, poolName,
 				containerPath)
 		}
 	}()
 
 	var containerMntPoint string
 	if snapshot {
-		containerMntPoint = getSnapshotMountPoint(project, s.pool.Name, containerName)
+		containerMntPoint = getSnapshotMountPoint(projectName, s.pool.Name, containerName)
 	} else {
-		containerMntPoint = getContainerMountPoint(project, s.pool.Name, containerName)
+		containerMntPoint = getContainerMountPoint(projectName, s.pool.Name, containerName)
 	}
 	err = os.MkdirAll(containerMntPoint, 0711)
 	if err != nil {
@@ -1895,8 +1896,8 @@ func (s *storageLvm) doContainerBackupLoad(project, containerName string, privil
 
 	if snapshot {
 		cname, _, _ := containerGetParentAndSnapshotName(containerName)
-		snapshotMntPointSymlink := shared.VarPath("snapshots", projectPrefix(project, cname))
-		snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", projectPrefix(project, cname))
+		snapshotMntPointSymlink := shared.VarPath("snapshots", project.Prefix(projectName, cname))
+		snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", project.Prefix(projectName, cname))
 		err = createSnapshotMountpoint(containerMntPoint, snapshotMntPointSymlinkTarget,
 			snapshotMntPointSymlink)
 	} else {
@@ -1906,7 +1907,7 @@ func (s *storageLvm) doContainerBackupLoad(project, containerName string, privil
 		return "", err
 	}
 
-	_, err = s.doContainerMount(project, containerName, false)
+	_, err = s.doContainerMount(projectName, containerName, false)
 	if err != nil {
 		return "", err
 	}
diff --git a/lxd/storage_lvm_utils.go b/lxd/storage_lvm_utils.go
index b33e8e5477..80ea742724 100644
--- a/lxd/storage_lvm_utils.go
+++ b/lxd/storage_lvm_utils.go
@@ -11,6 +11,7 @@ import (
 	"github.com/pkg/errors"
 
 	"github.com/lxc/lxd/lxd/db"
+	"github.com/lxc/lxd/lxd/project"
 	"github.com/lxc/lxd/lxd/state"
 	"github.com/lxc/lxd/shared"
 	"github.com/lxc/lxd/shared/api"
@@ -284,8 +285,8 @@ func (s *storageLvm) createSnapshotContainer(snapshotContainer container, source
 	if targetIsSnapshot {
 		targetContainerMntPoint = getSnapshotMountPoint(sourceContainer.Project(), s.pool.Name, targetContainerName)
 		sourceName, _, _ := containerGetParentAndSnapshotName(sourceContainerName)
-		snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", projectPrefix(sourceContainer.Project(), sourceName))
-		snapshotMntPointSymlink := shared.VarPath("snapshots", projectPrefix(sourceContainer.Project(), sourceName))
+		snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", project.Prefix(sourceContainer.Project(), sourceName))
+		snapshotMntPointSymlink := shared.VarPath("snapshots", project.Prefix(sourceContainer.Project(), sourceName))
 		err = createSnapshotMountpoint(targetContainerMntPoint, snapshotMntPointSymlinkTarget, snapshotMntPointSymlink)
 	} else {
 		targetContainerMntPoint = getContainerMountPoint(sourceContainer.Project(), targetPool, targetContainerName)
@@ -347,8 +348,8 @@ func (s *storageLvm) copySnapshot(target container, source container, refresh bo
 
 	targetParentName, _, _ := containerGetParentAndSnapshotName(target.Name())
 	containersPath := getSnapshotMountPoint(target.Project(), s.pool.Name, targetParentName)
-	snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", projectPrefix(target.Project(), targetParentName))
-	snapshotMntPointSymlink := shared.VarPath("snapshots", projectPrefix(target.Project(), targetParentName))
+	snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", project.Prefix(target.Project(), targetParentName))
+	snapshotMntPointSymlink := shared.VarPath("snapshots", project.Prefix(target.Project(), targetParentName))
 	err = createSnapshotMountpoint(containersPath, snapshotMntPointSymlinkTarget, snapshotMntPointSymlink)
 	if err != nil {
 		return err
@@ -803,8 +804,8 @@ func containerNameToLVName(containerName string) string {
 	return strings.Replace(lvName, shared.SnapshotDelimiter, "-", -1)
 }
 
-func getLvmDevPath(project, lvmPool string, volumeType string, lvmVolume string) string {
-	lvmVolume = projectPrefix(project, lvmVolume)
+func getLvmDevPath(projectName, lvmPool string, volumeType string, lvmVolume string) string {
+	lvmVolume = project.Prefix(projectName, lvmVolume)
 	if volumeType == "" {
 		return fmt.Sprintf("/dev/%s/%s", lvmPool, lvmVolume)
 	}
@@ -820,12 +821,12 @@ func getLVName(lvmPool string, volumeType string, lvmVolume string) string {
 	return fmt.Sprintf("%s/%s_%s", lvmPool, volumeType, lvmVolume)
 }
 
-func getPrefixedLvName(project, volumeType string, lvmVolume string) string {
-	lvmVolume = projectPrefix(project, lvmVolume)
+func getPrefixedLvName(projectName, volumeType string, lvmVolume string) string {
+	lvmVolume = project.Prefix(projectName, lvmVolume)
 	return fmt.Sprintf("%s_%s", volumeType, lvmVolume)
 }
 
-func lvmCreateLv(project, vgName string, thinPoolName string, lvName string, lvFsType string, lvSize string, volumeType string, makeThinLv bool) error {
+func lvmCreateLv(projectName, vgName string, thinPoolName string, lvName string, lvFsType string, lvSize string, volumeType string, makeThinLv bool) error {
 	var output string
 	var err error
 
@@ -838,7 +839,7 @@ func lvmCreateLv(project, vgName string, thinPoolName string, lvName string, lvF
 	lvSizeInt = int64(lvSizeInt/512) * 512
 	lvSizeString := units.GetByteSizeString(lvSizeInt, 0)
 
-	lvmPoolVolumeName := getPrefixedLvName(project, volumeType, lvName)
+	lvmPoolVolumeName := getPrefixedLvName(projectName, volumeType, lvName)
 	if makeThinLv {
 		targetVg := fmt.Sprintf("%s/%s", vgName, thinPoolName)
 		output, err = shared.TryRunCommand("lvcreate", "-Wy", "--yes", "--thin", "-n", lvmPoolVolumeName, "--virtualsize", lvSizeString, targetVg)
@@ -850,7 +851,7 @@ func lvmCreateLv(project, vgName string, thinPoolName string, lvName string, lvF
 		return fmt.Errorf("Could not create thin LV named %s", lvmPoolVolumeName)
 	}
 
-	fsPath := getLvmDevPath(project, vgName, volumeType, lvName)
+	fsPath := getLvmDevPath(projectName, vgName, volumeType, lvName)
 
 	output, err = makeFSType(fsPath, lvFsType, nil)
 	if err != nil {
diff --git a/lxd/storage_migration.go b/lxd/storage_migration.go
index 387f2bef6d..16341e0297 100644
--- a/lxd/storage_migration.go
+++ b/lxd/storage_migration.go
@@ -8,6 +8,7 @@ import (
 
 	"github.com/lxc/lxd/lxd/db"
 	"github.com/lxc/lxd/lxd/migration"
+	"github.com/lxc/lxd/lxd/project"
 	"github.com/lxc/lxd/lxd/types"
 	"github.com/lxc/lxd/shared"
 	"github.com/lxc/lxd/shared/api"
@@ -110,7 +111,7 @@ func (s rsyncStorageSourceDriver) SendWhileRunning(conn *websocket.Conn, op *ope
 			path := send.Path()
 			wrapper := StorageProgressReader(op, "fs_progress", send.Name())
 			state := s.container.DaemonState()
-			err = RsyncSend(projectPrefix(s.container.Project(), ctName), shared.AddSlash(path), conn, wrapper, s.rsyncFeatures, bwlimit, state.OS.ExecPath)
+			err = RsyncSend(project.Prefix(s.container.Project(), ctName), shared.AddSlash(path), conn, wrapper, s.rsyncFeatures, bwlimit, state.OS.ExecPath)
 			if err != nil {
 				return err
 			}
@@ -130,14 +131,14 @@ func (s rsyncStorageSourceDriver) SendWhileRunning(conn *websocket.Conn, op *ope
 		}
 	}
 
-	return RsyncSend(projectPrefix(s.container.Project(), ctName), shared.AddSlash(s.container.Path()), conn, wrapper, s.rsyncFeatures, bwlimit, state.OS.ExecPath)
+	return RsyncSend(project.Prefix(s.container.Project(), ctName), shared.AddSlash(s.container.Path()), conn, wrapper, s.rsyncFeatures, bwlimit, state.OS.ExecPath)
 }
 
 func (s rsyncStorageSourceDriver) SendAfterCheckpoint(conn *websocket.Conn, bwlimit string) error {
 	ctName, _, _ := containerGetParentAndSnapshotName(s.container.Name())
 	// resync anything that changed between our first send and the checkpoint
 	state := s.container.DaemonState()
-	return RsyncSend(projectPrefix(s.container.Project(), ctName), shared.AddSlash(s.container.Path()), conn, nil, s.rsyncFeatures, bwlimit, state.OS.ExecPath)
+	return RsyncSend(project.Prefix(s.container.Project(), ctName), shared.AddSlash(s.container.Path()), conn, nil, s.rsyncFeatures, bwlimit, state.OS.ExecPath)
 }
 
 func (s rsyncStorageSourceDriver) Cleanup() {
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index 2998061f31..9239caf35b 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -15,6 +15,7 @@ import (
 	"golang.org/x/sys/unix"
 
 	"github.com/lxc/lxd/lxd/migration"
+	"github.com/lxc/lxd/lxd/project"
 	"github.com/lxc/lxd/lxd/state"
 	"github.com/lxc/lxd/lxd/util"
 	"github.com/lxc/lxd/shared"
@@ -783,7 +784,7 @@ func (s *storageZfs) ContainerUmount(c container, path string) (bool, error) {
 	logger.Debugf("Unmounting ZFS storage volume for container \"%s\" on storage pool \"%s\"", s.volume.Name, s.pool.Name)
 	name := c.Name()
 
-	fs := fmt.Sprintf("containers/%s", projectPrefix(c.Project(), name))
+	fs := fmt.Sprintf("containers/%s", project.Prefix(c.Project(), name))
 	containerPoolVolumeMntPoint := getContainerMountPoint(c.Project(), s.pool.Name, name)
 
 	containerUmountLockID := getContainerUmountLockID(s.pool.Name, name)
@@ -825,7 +826,7 @@ func (s *storageZfs) ContainerUmount(c container, path string) (bool, error) {
 
 // Things we do have to care about
 func (s *storageZfs) ContainerStorageReady(container container) bool {
-	volumeName := projectPrefix(container.Project(), container.Name())
+	volumeName := project.Prefix(container.Project(), container.Name())
 	fs := fmt.Sprintf("containers/%s", volumeName)
 	return zfsFilesystemEntityExists(s.getOnDiskPoolName(), fs)
 }
@@ -858,7 +859,7 @@ func (s *storageZfs) ContainerCreateFromImage(container container, fingerprint s
 
 	containerPath := container.Path()
 	containerName := container.Name()
-	volumeName := projectPrefix(container.Project(), containerName)
+	volumeName := project.Prefix(container.Project(), containerName)
 	fs := fmt.Sprintf("containers/%s", volumeName)
 	containerPoolVolumeMntPoint := getContainerMountPoint(container.Project(), s.pool.Name, containerName)
 
@@ -977,7 +978,7 @@ func (s *storageZfs) copyWithoutSnapshotsSparse(target container, source contain
 	sourceZfsDatasetSnapshot := ""
 	sourceName, sourceSnapOnlyName, isSnapshotName := containerGetParentAndSnapshotName(sourceContainerName)
 
-	targetZfsDataset := fmt.Sprintf("containers/%s", projectPrefix(target.Project(), targetContainerName))
+	targetZfsDataset := fmt.Sprintf("containers/%s", project.Prefix(target.Project(), targetContainerName))
 
 	if isSnapshotName {
 		sourceZfsDatasetSnapshot = sourceSnapOnlyName
@@ -985,9 +986,9 @@ func (s *storageZfs) copyWithoutSnapshotsSparse(target container, source contain
 
 	revert := true
 	if sourceZfsDatasetSnapshot == "" {
-		if zfsFilesystemEntityExists(poolName, fmt.Sprintf("containers/%s", projectPrefix(source.Project(), sourceName))) {
+		if zfsFilesystemEntityExists(poolName, fmt.Sprintf("containers/%s", project.Prefix(source.Project(), sourceName))) {
 			sourceZfsDatasetSnapshot = fmt.Sprintf("copy-%s", uuid.NewRandom().String())
-			sourceZfsDataset = fmt.Sprintf("containers/%s", projectPrefix(source.Project(), sourceName))
+			sourceZfsDataset = fmt.Sprintf("containers/%s", project.Prefix(source.Project(), sourceName))
 			err := zfsPoolVolumeSnapshotCreate(poolName, sourceZfsDataset, sourceZfsDatasetSnapshot)
 			if err != nil {
 				return err
@@ -1000,8 +1001,8 @@ func (s *storageZfs) copyWithoutSnapshotsSparse(target container, source contain
 			}()
 		}
 	} else {
-		if zfsFilesystemEntityExists(poolName, fmt.Sprintf("containers/%s at snapshot-%s", projectPrefix(source.Project(), sourceName), sourceZfsDatasetSnapshot)) {
-			sourceZfsDataset = fmt.Sprintf("containers/%s", projectPrefix(source.Project(), sourceName))
+		if zfsFilesystemEntityExists(poolName, fmt.Sprintf("containers/%s at snapshot-%s", project.Prefix(source.Project(), sourceName), sourceZfsDatasetSnapshot)) {
+			sourceZfsDataset = fmt.Sprintf("containers/%s", project.Prefix(source.Project(), sourceName))
 			sourceZfsDatasetSnapshot = fmt.Sprintf("snapshot-%s", sourceZfsDatasetSnapshot)
 		}
 	}
@@ -1076,20 +1077,20 @@ func (s *storageZfs) copyWithoutSnapshotFull(target container, source container)
 	snapshotSuffix := ""
 
 	targetName := target.Name()
-	targetDataset := fmt.Sprintf("%s/containers/%s", poolName, projectPrefix(target.Project(), targetName))
+	targetDataset := fmt.Sprintf("%s/containers/%s", poolName, project.Prefix(target.Project(), targetName))
 	targetSnapshotDataset := ""
 
 	if sourceIsSnapshot {
 		sourceParentName, sourceSnapOnlyName, _ := containerGetParentAndSnapshotName(source.Name())
 		snapshotSuffix = fmt.Sprintf("snapshot-%s", sourceSnapOnlyName)
-		sourceDataset = fmt.Sprintf("%s/containers/%s@%s", poolName, projectPrefix(source.Project(), sourceParentName), snapshotSuffix)
-		targetSnapshotDataset = fmt.Sprintf("%s/containers/%s at snapshot-%s", poolName, projectPrefix(target.Project(), targetName), sourceSnapOnlyName)
+		sourceDataset = fmt.Sprintf("%s/containers/%s@%s", poolName, project.Prefix(source.Project(), sourceParentName), snapshotSuffix)
+		targetSnapshotDataset = fmt.Sprintf("%s/containers/%s at snapshot-%s", poolName, project.Prefix(target.Project(), targetName), sourceSnapOnlyName)
 	} else {
 		snapshotSuffix = uuid.NewRandom().String()
-		sourceDataset = fmt.Sprintf("%s/containers/%s@%s", poolName, projectPrefix(source.Project(), sourceName), snapshotSuffix)
-		targetSnapshotDataset = fmt.Sprintf("%s/containers/%s@%s", poolName, projectPrefix(target.Project(), targetName), snapshotSuffix)
+		sourceDataset = fmt.Sprintf("%s/containers/%s@%s", poolName, project.Prefix(source.Project(), sourceName), snapshotSuffix)
+		targetSnapshotDataset = fmt.Sprintf("%s/containers/%s@%s", poolName, project.Prefix(target.Project(), targetName), snapshotSuffix)
 
-		fs := fmt.Sprintf("containers/%s", projectPrefix(source.Project(), sourceName))
+		fs := fmt.Sprintf("containers/%s", project.Prefix(source.Project(), sourceName))
 		err := zfsPoolVolumeSnapshotCreate(poolName, fs, snapshotSuffix)
 		if err != nil {
 			return err
@@ -1132,7 +1133,7 @@ func (s *storageZfs) copyWithoutSnapshotFull(target container, source container)
 	}
 
 	targetContainerMountPoint := getContainerMountPoint(target.Project(), s.pool.Name, targetName)
-	targetfs := fmt.Sprintf("containers/%s", projectPrefix(target.Project(), targetName))
+	targetfs := fmt.Sprintf("containers/%s", project.Prefix(target.Project(), targetName))
 
 	err = zfsPoolVolumeSet(poolName, targetfs, "canmount", "noauto")
 	if err != nil {
@@ -1170,8 +1171,8 @@ func (s *storageZfs) copyWithSnapshots(target container, source container, paren
 	sourceName := source.Name()
 	targetParentName, targetSnapOnlyName, _ := containerGetParentAndSnapshotName(target.Name())
 	containersPath := getSnapshotMountPoint(target.Project(), s.pool.Name, targetParentName)
-	snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", projectPrefix(target.Project(), targetParentName))
-	snapshotMntPointSymlink := shared.VarPath("snapshots", projectPrefix(target.Project(), targetParentName))
+	snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", project.Prefix(target.Project(), targetParentName))
+	snapshotMntPointSymlink := shared.VarPath("snapshots", project.Prefix(target.Project(), targetParentName))
 	err := createSnapshotMountpoint(containersPath, snapshotMntPointSymlinkTarget, snapshotMntPointSymlink)
 	if err != nil {
 		return err
@@ -1179,16 +1180,16 @@ func (s *storageZfs) copyWithSnapshots(target container, source container, paren
 
 	poolName := s.getOnDiskPoolName()
 	sourceParentName, sourceSnapOnlyName, _ := containerGetParentAndSnapshotName(sourceName)
-	currentSnapshotDataset := fmt.Sprintf("%s/containers/%s at snapshot-%s", poolName, projectPrefix(source.Project(), sourceParentName), sourceSnapOnlyName)
+	currentSnapshotDataset := fmt.Sprintf("%s/containers/%s at snapshot-%s", poolName, project.Prefix(source.Project(), sourceParentName), sourceSnapOnlyName)
 	args := []string{"send", currentSnapshotDataset}
 	if parentSnapshot != "" {
 		parentName, parentSnaponlyName, _ := containerGetParentAndSnapshotName(parentSnapshot)
-		parentSnapshotDataset := fmt.Sprintf("%s/containers/%s at snapshot-%s", poolName, projectPrefix(source.Project(), parentName), parentSnaponlyName)
+		parentSnapshotDataset := fmt.Sprintf("%s/containers/%s at snapshot-%s", poolName, project.Prefix(source.Project(), parentName), parentSnaponlyName)
 		args = append(args, "-i", parentSnapshotDataset)
 	}
 
 	zfsSendCmd := exec.Command("zfs", args...)
-	targetSnapshotDataset := fmt.Sprintf("%s/containers/%s at snapshot-%s", poolName, projectPrefix(target.Project(), targetParentName), targetSnapOnlyName)
+	targetSnapshotDataset := fmt.Sprintf("%s/containers/%s at snapshot-%s", poolName, project.Prefix(target.Project(), targetParentName), targetSnapOnlyName)
 	zfsRecvCmd := exec.Command("zfs", "receive", "-F", targetSnapshotDataset)
 
 	zfsRecvCmd.Stdin, _ = zfsSendCmd.StdoutPipe()
@@ -1259,7 +1260,7 @@ func (s *storageZfs) doCrossPoolContainerCopy(target container, source container
 	if err != nil {
 		return err
 	}
-	defer s.ContainerUmount(target, shared.VarPath("containers", projectPrefix(target.Project(), target.Name())))
+	defer s.ContainerUmount(target, shared.VarPath("containers", project.Prefix(target.Project(), target.Name())))
 
 	destContainerMntPoint := getContainerMountPoint(target.Project(), targetPool, target.Name())
 	bwlimit := s.pool.Config["rsync.bwlimit"]
@@ -1364,20 +1365,20 @@ func (s *storageZfs) ContainerCopy(target container, source container, container
 
 		// send actual container
 		tmpSnapshotName := fmt.Sprintf("copy-send-%s", uuid.NewRandom().String())
-		err = zfsPoolVolumeSnapshotCreate(poolName, fmt.Sprintf("containers/%s", projectPrefix(source.Project(), source.Name())), tmpSnapshotName)
+		err = zfsPoolVolumeSnapshotCreate(poolName, fmt.Sprintf("containers/%s", project.Prefix(source.Project(), source.Name())), tmpSnapshotName)
 		if err != nil {
 			return err
 		}
 
-		currentSnapshotDataset := fmt.Sprintf("%s/containers/%s@%s", poolName, projectPrefix(source.Project(), source.Name()), tmpSnapshotName)
+		currentSnapshotDataset := fmt.Sprintf("%s/containers/%s@%s", poolName, project.Prefix(source.Project(), source.Name()), tmpSnapshotName)
 		args := []string{"send", currentSnapshotDataset}
 		if prevSnapOnlyName != "" {
-			parentSnapshotDataset := fmt.Sprintf("%s/containers/%s at snapshot-%s", poolName, projectPrefix(source.Project(), source.Name()), prevSnapOnlyName)
+			parentSnapshotDataset := fmt.Sprintf("%s/containers/%s at snapshot-%s", poolName, project.Prefix(source.Project(), source.Name()), prevSnapOnlyName)
 			args = append(args, "-i", parentSnapshotDataset)
 		}
 
 		zfsSendCmd := exec.Command("zfs", args...)
-		targetSnapshotDataset := fmt.Sprintf("%s/containers/%s@%s", poolName, projectPrefix(target.Project(), target.Name()), tmpSnapshotName)
+		targetSnapshotDataset := fmt.Sprintf("%s/containers/%s@%s", poolName, project.Prefix(target.Project(), target.Name()), tmpSnapshotName)
 		zfsRecvCmd := exec.Command("zfs", "receive", "-F", targetSnapshotDataset)
 
 		zfsRecvCmd.Stdin, _ = zfsSendCmd.StdoutPipe()
@@ -1399,10 +1400,10 @@ func (s *storageZfs) ContainerCopy(target container, source container, container
 			return err
 		}
 
-		zfsPoolVolumeSnapshotDestroy(poolName, fmt.Sprintf("containers/%s", projectPrefix(source.Project(), source.Name())), tmpSnapshotName)
-		zfsPoolVolumeSnapshotDestroy(poolName, fmt.Sprintf("containers/%s", projectPrefix(target.Project(), target.Name())), tmpSnapshotName)
+		zfsPoolVolumeSnapshotDestroy(poolName, fmt.Sprintf("containers/%s", project.Prefix(source.Project(), source.Name())), tmpSnapshotName)
+		zfsPoolVolumeSnapshotDestroy(poolName, fmt.Sprintf("containers/%s", project.Prefix(target.Project(), target.Name())), tmpSnapshotName)
 
-		fs := fmt.Sprintf("containers/%s", projectPrefix(target.Project(), target.Name()))
+		fs := fmt.Sprintf("containers/%s", project.Prefix(target.Project(), target.Name()))
 		err = zfsPoolVolumeSet(poolName, fs, "canmount", "noauto")
 		if err != nil {
 			return err
@@ -1445,8 +1446,8 @@ func (s *storageZfs) ContainerRename(container container, newName string) error
 	}
 
 	// Rename the dataset.
-	oldZfsDataset := fmt.Sprintf("containers/%s", projectPrefix(container.Project(), oldName))
-	newZfsDataset := fmt.Sprintf("containers/%s", projectPrefix(container.Project(), newName))
+	oldZfsDataset := fmt.Sprintf("containers/%s", project.Prefix(container.Project(), oldName))
+	newZfsDataset := fmt.Sprintf("containers/%s", project.Prefix(container.Project(), newName))
 	err = zfsPoolVolumeRename(poolName, oldZfsDataset, newZfsDataset, false)
 	if err != nil {
 		return err
@@ -1476,7 +1477,7 @@ func (s *storageZfs) ContainerRename(container container, newName string) error
 	// Create new mountpoint on the storage pool.
 	oldContainerMntPoint := getContainerMountPoint(container.Project(), s.pool.Name, oldName)
 	oldContainerMntPointSymlink := container.Path()
-	newContainerMntPointSymlink := shared.VarPath("containers", projectPrefix(container.Project(), newName))
+	newContainerMntPointSymlink := shared.VarPath("containers", project.Prefix(container.Project(), newName))
 	err = renameContainerMountpoint(oldContainerMntPoint, oldContainerMntPointSymlink, newContainerMntPoint, newContainerMntPointSymlink)
 	if err != nil {
 		return err
@@ -1493,7 +1494,7 @@ func (s *storageZfs) ContainerRename(container container, newName string) error
 	}
 
 	// Remove old symlink.
-	oldSnapshotPath := shared.VarPath("snapshots", projectPrefix(container.Project(), oldName))
+	oldSnapshotPath := shared.VarPath("snapshots", project.Prefix(container.Project(), oldName))
 	if shared.PathExists(oldSnapshotPath) {
 		err := os.Remove(oldSnapshotPath)
 		if err != nil {
@@ -1502,7 +1503,7 @@ func (s *storageZfs) ContainerRename(container container, newName string) error
 	}
 
 	// Create new symlink.
-	newSnapshotPath := shared.VarPath("snapshots", projectPrefix(container.Project(), newName))
+	newSnapshotPath := shared.VarPath("snapshots", project.Prefix(container.Project(), newName))
 	if shared.PathExists(newSnapshotPath) {
 		err := os.Symlink(newSnapshotMntPoint, newSnapshotPath)
 		if err != nil {
@@ -1558,7 +1559,7 @@ func (s *storageZfs) ContainerRestore(target container, source container) error
 	cName, snapOnlyName, _ := containerGetParentAndSnapshotName(source.Name())
 	snapName := fmt.Sprintf("snapshot-%s", snapOnlyName)
 
-	err = zfsPoolVolumeSnapshotRestore(s.getOnDiskPoolName(), fmt.Sprintf("containers/%s", projectPrefix(source.Project(), cName)), snapName)
+	err = zfsPoolVolumeSnapshotRestore(s.getOnDiskPoolName(), fmt.Sprintf("containers/%s", project.Prefix(source.Project(), cName)), snapName)
 	if err != nil {
 		return err
 	}
@@ -1570,7 +1571,7 @@ func (s *storageZfs) ContainerRestore(target container, source container) error
 func (s *storageZfs) ContainerGetUsage(container container) (int64, error) {
 	var err error
 
-	fs := fmt.Sprintf("containers/%s", projectPrefix(container.Project(), container.Name()))
+	fs := fmt.Sprintf("containers/%s", project.Prefix(container.Project(), container.Name()))
 
 	property := "used"
 
@@ -1610,7 +1611,7 @@ func (s *storageZfs) ContainerGetUsage(container container) (int64, error) {
 	return valueInt, nil
 }
 
-func (s *storageZfs) doContainerSnapshotCreate(project, targetName string, sourceName string) error {
+func (s *storageZfs) doContainerSnapshotCreate(projectName, targetName string, sourceName string) error {
 	snapshotContainerName := targetName
 	logger.Debugf("Creating ZFS storage volume for snapshot \"%s\" on storage pool \"%s\"", snapshotContainerName, s.pool.Name)
 
@@ -1619,13 +1620,13 @@ func (s *storageZfs) doContainerSnapshotCreate(project, targetName string, sourc
 	cName, snapshotSnapOnlyName, _ := containerGetParentAndSnapshotName(snapshotContainerName)
 	snapName := fmt.Sprintf("snapshot-%s", snapshotSnapOnlyName)
 
-	sourceZfsDataset := fmt.Sprintf("containers/%s", projectPrefix(project, cName))
+	sourceZfsDataset := fmt.Sprintf("containers/%s", project.Prefix(projectName, cName))
 	err := zfsPoolVolumeSnapshotCreate(s.getOnDiskPoolName(), sourceZfsDataset, snapName)
 	if err != nil {
 		return err
 	}
 
-	snapshotMntPoint := getSnapshotMountPoint(project, s.pool.Name, snapshotContainerName)
+	snapshotMntPoint := getSnapshotMountPoint(projectName, s.pool.Name, snapshotContainerName)
 	if !shared.PathExists(snapshotMntPoint) {
 		err := os.MkdirAll(snapshotMntPoint, 0700)
 		if err != nil {
@@ -1633,8 +1634,8 @@ func (s *storageZfs) doContainerSnapshotCreate(project, targetName string, sourc
 		}
 	}
 
-	snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", projectPrefix(project, sourceName))
-	snapshotMntPointSymlink := shared.VarPath("snapshots", projectPrefix(project, sourceContainerName))
+	snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", project.Prefix(projectName, sourceName))
+	snapshotMntPointSymlink := shared.VarPath("snapshots", project.Prefix(projectName, sourceContainerName))
 	if !shared.PathExists(snapshotMntPointSymlink) {
 		err := os.Symlink(snapshotMntPointSymlinkTarget, snapshotMntPointSymlink)
 		if err != nil {
@@ -1655,16 +1656,16 @@ func (s *storageZfs) ContainerSnapshotCreate(snapshotContainer container, source
 	return nil
 }
 
-func zfsSnapshotDeleteInternal(project, poolName string, ctName string, onDiskPoolName string) error {
+func zfsSnapshotDeleteInternal(projectName, poolName string, ctName string, onDiskPoolName string) error {
 	sourceContainerName, sourceContainerSnapOnlyName, _ := containerGetParentAndSnapshotName(ctName)
 	snapName := fmt.Sprintf("snapshot-%s", sourceContainerSnapOnlyName)
 
 	if zfsFilesystemEntityExists(onDiskPoolName,
 		fmt.Sprintf("containers/%s@%s",
-			projectPrefix(project, sourceContainerName), snapName)) {
+			project.Prefix(projectName, sourceContainerName), snapName)) {
 		removable, err := zfsPoolVolumeSnapshotRemovable(onDiskPoolName,
 			fmt.Sprintf("containers/%s",
-				projectPrefix(project, sourceContainerName)),
+				project.Prefix(projectName, sourceContainerName)),
 			snapName)
 		if err != nil {
 			return err
@@ -1673,12 +1674,12 @@ func zfsSnapshotDeleteInternal(project, poolName string, ctName string, onDiskPo
 		if removable {
 			err = zfsPoolVolumeSnapshotDestroy(onDiskPoolName,
 				fmt.Sprintf("containers/%s",
-					projectPrefix(project, sourceContainerName)),
+					project.Prefix(projectName, sourceContainerName)),
 				snapName)
 		} else {
 			err = zfsPoolVolumeSnapshotRename(onDiskPoolName,
 				fmt.Sprintf("containers/%s",
-					projectPrefix(project, sourceContainerName)),
+					project.Prefix(projectName, sourceContainerName)),
 				snapName,
 				fmt.Sprintf("copy-%s", uuid.NewRandom().String()))
 		}
@@ -1689,7 +1690,7 @@ func zfsSnapshotDeleteInternal(project, poolName string, ctName string, onDiskPo
 
 	// Delete the snapshot on its storage pool:
 	// ${POOL}/snapshots/<snapshot_name>
-	snapshotContainerMntPoint := getSnapshotMountPoint(project, poolName, ctName)
+	snapshotContainerMntPoint := getSnapshotMountPoint(projectName, poolName, ctName)
 	if shared.PathExists(snapshotContainerMntPoint) {
 		err := os.RemoveAll(snapshotContainerMntPoint)
 		if err != nil {
@@ -1700,7 +1701,7 @@ func zfsSnapshotDeleteInternal(project, poolName string, ctName string, onDiskPo
 	// Check if we can remove the snapshot symlink:
 	// ${LXD_DIR}/snapshots/<container_name> to ${POOL}/snapshots/<container_name>
 	// by checking if the directory is empty.
-	snapshotContainerPath := getSnapshotMountPoint(project, poolName, sourceContainerName)
+	snapshotContainerPath := getSnapshotMountPoint(projectName, poolName, sourceContainerName)
 	empty, _ := shared.PathIsEmpty(snapshotContainerPath)
 	if empty == true {
 		// Remove the snapshot directory for the container:
@@ -1710,7 +1711,7 @@ func zfsSnapshotDeleteInternal(project, poolName string, ctName string, onDiskPo
 			return err
 		}
 
-		snapshotSymlink := shared.VarPath("snapshots", projectPrefix(project, sourceContainerName))
+		snapshotSymlink := shared.VarPath("snapshots", project.Prefix(projectName, sourceContainerName))
 		if shared.PathExists(snapshotSymlink) {
 			err := os.Remove(snapshotSymlink)
 			if err != nil {
@@ -1720,7 +1721,7 @@ func zfsSnapshotDeleteInternal(project, poolName string, ctName string, onDiskPo
 	}
 
 	// Legacy
-	snapPath := shared.VarPath(fmt.Sprintf("snapshots/%s/%s.zfs", projectPrefix(project, sourceContainerName), sourceContainerSnapOnlyName))
+	snapPath := shared.VarPath(fmt.Sprintf("snapshots/%s/%s.zfs", project.Prefix(projectName, sourceContainerName), sourceContainerSnapOnlyName))
 	if shared.PathExists(snapPath) {
 		err := os.Remove(snapPath)
 		if err != nil {
@@ -1729,7 +1730,7 @@ func zfsSnapshotDeleteInternal(project, poolName string, ctName string, onDiskPo
 	}
 
 	// Legacy
-	parent := shared.VarPath(fmt.Sprintf("snapshots/%s", projectPrefix(project, sourceContainerName)))
+	parent := shared.VarPath(fmt.Sprintf("snapshots/%s", project.Prefix(projectName, sourceContainerName)))
 	if ok, _ := shared.PathIsEmpty(parent); ok {
 		err := os.Remove(parent)
 		if err != nil {
@@ -1767,7 +1768,7 @@ func (s *storageZfs) ContainerSnapshotRename(snapshotContainer container, newNam
 
 	if oldZfsDatasetName != newZfsDatasetName {
 		err := zfsPoolVolumeSnapshotRename(
-			s.getOnDiskPoolName(), fmt.Sprintf("containers/%s", projectPrefix(snapshotContainer.Project(), oldcName)), oldZfsDatasetName, newZfsDatasetName)
+			s.getOnDiskPoolName(), fmt.Sprintf("containers/%s", project.Prefix(snapshotContainer.Project(), oldcName)), oldZfsDatasetName, newZfsDatasetName)
 		if err != nil {
 			return err
 		}
@@ -1780,7 +1781,7 @@ func (s *storageZfs) ContainerSnapshotRename(snapshotContainer container, newNam
 		//s.ContainerSnapshotRename(snapshotContainer, oldName)
 	}()
 
-	oldStyleSnapshotMntPoint := shared.VarPath(fmt.Sprintf("snapshots/%s/%s.zfs", projectPrefix(snapshotContainer.Project(), oldcName), oldSnapOnlyName))
+	oldStyleSnapshotMntPoint := shared.VarPath(fmt.Sprintf("snapshots/%s/%s.zfs", project.Prefix(snapshotContainer.Project(), oldcName), oldSnapOnlyName))
 	if shared.PathExists(oldStyleSnapshotMntPoint) {
 		err := os.Remove(oldStyleSnapshotMntPoint)
 		if err != nil {
@@ -1804,8 +1805,8 @@ func (s *storageZfs) ContainerSnapshotRename(snapshotContainer container, newNam
 		}
 	}
 
-	snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", projectPrefix(snapshotContainer.Project(), oldcName))
-	snapshotMntPointSymlink := shared.VarPath("snapshots", projectPrefix(snapshotContainer.Project(), oldcName))
+	snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", project.Prefix(snapshotContainer.Project(), oldcName))
+	snapshotMntPointSymlink := shared.VarPath("snapshots", project.Prefix(snapshotContainer.Project(), oldcName))
 	if !shared.PathExists(snapshotMntPointSymlink) {
 		err := os.Symlink(snapshotMntPointSymlinkTarget, snapshotMntPointSymlink)
 		if err != nil {
@@ -1823,9 +1824,9 @@ func (s *storageZfs) ContainerSnapshotStart(container container) (bool, error) {
 	logger.Debugf("Initializing ZFS storage volume for snapshot \"%s\" on storage pool \"%s\"", s.volume.Name, s.pool.Name)
 
 	cName, sName, _ := containerGetParentAndSnapshotName(container.Name())
-	sourceFs := fmt.Sprintf("containers/%s", projectPrefix(container.Project(), cName))
+	sourceFs := fmt.Sprintf("containers/%s", project.Prefix(container.Project(), cName))
 	sourceSnap := fmt.Sprintf("snapshot-%s", sName)
-	destFs := fmt.Sprintf("snapshots/%s/%s", projectPrefix(container.Project(), cName), sName)
+	destFs := fmt.Sprintf("snapshots/%s/%s", project.Prefix(container.Project(), cName), sName)
 
 	poolName := s.getOnDiskPoolName()
 	snapshotMntPoint := getSnapshotMountPoint(container.Project(), s.pool.Name, container.Name())
@@ -1847,7 +1848,7 @@ func (s *storageZfs) ContainerSnapshotStop(container container) (bool, error) {
 	logger.Debugf("Stopping ZFS storage volume for snapshot \"%s\" on storage pool \"%s\"", s.volume.Name, s.pool.Name)
 
 	cName, sName, _ := containerGetParentAndSnapshotName(container.Name())
-	destFs := fmt.Sprintf("snapshots/%s/%s", projectPrefix(container.Project(), cName), sName)
+	destFs := fmt.Sprintf("snapshots/%s/%s", project.Prefix(container.Project(), cName), sName)
 
 	err := zfsPoolVolumeDestroy(s.getOnDiskPoolName(), destFs)
 	if err != nil {
@@ -1874,12 +1875,12 @@ func (s *storageZfs) doContainerOnlyBackup(tmpPath string, backup backup, source
 	if sourceIsSnapshot {
 		sourceParentName, sourceSnapOnlyName, _ := containerGetParentAndSnapshotName(source.Name())
 		snapshotSuffix = fmt.Sprintf("backup-%s", sourceSnapOnlyName)
-		sourceDataset = fmt.Sprintf("%s/containers/%s@%s", poolName, projectPrefix(source.Project(), sourceParentName), snapshotSuffix)
+		sourceDataset = fmt.Sprintf("%s/containers/%s@%s", poolName, project.Prefix(source.Project(), sourceParentName), snapshotSuffix)
 	} else {
 		snapshotSuffix = uuid.NewRandom().String()
-		sourceDataset = fmt.Sprintf("%s/containers/%s@%s", poolName, projectPrefix(source.Project(), sourceName), snapshotSuffix)
+		sourceDataset = fmt.Sprintf("%s/containers/%s@%s", poolName, project.Prefix(source.Project(), sourceName), snapshotSuffix)
 
-		fs := fmt.Sprintf("containers/%s", projectPrefix(source.Project(), sourceName))
+		fs := fmt.Sprintf("containers/%s", project.Prefix(source.Project(), sourceName))
 		err := zfsPoolVolumeSnapshotCreate(poolName, fs, snapshotSuffix)
 		if err != nil {
 			return err
@@ -1923,11 +1924,11 @@ func (s *storageZfs) doSnapshotBackup(tmpPath string, backup backup, source cont
 
 	poolName := s.getOnDiskPoolName()
 	sourceParentName, sourceSnapOnlyName, _ := containerGetParentAndSnapshotName(sourceName)
-	currentSnapshotDataset := fmt.Sprintf("%s/containers/%s at snapshot-%s", poolName, projectPrefix(source.Project(), sourceParentName), sourceSnapOnlyName)
+	currentSnapshotDataset := fmt.Sprintf("%s/containers/%s at snapshot-%s", poolName, project.Prefix(source.Project(), sourceParentName), sourceSnapOnlyName)
 	args := []string{"send", currentSnapshotDataset}
 	if parentSnapshot != "" {
 		parentName, parentSnaponlyName, _ := containerGetParentAndSnapshotName(parentSnapshot)
-		parentSnapshotDataset := fmt.Sprintf("%s/containers/%s at snapshot-%s", poolName, projectPrefix(source.Project(), parentName), parentSnaponlyName)
+		parentSnapshotDataset := fmt.Sprintf("%s/containers/%s at snapshot-%s", poolName, project.Prefix(source.Project(), parentName), parentSnaponlyName)
 		args = append(args, "-i", parentSnapshotDataset)
 	}
 
@@ -1976,15 +1977,15 @@ func (s *storageZfs) doContainerBackupCreateOptimized(tmpPath string, backup bac
 		// Dump the container to a file
 		poolName := s.getOnDiskPoolName()
 		tmpSnapshotName := fmt.Sprintf("backup-%s", uuid.NewRandom().String())
-		err = zfsPoolVolumeSnapshotCreate(poolName, fmt.Sprintf("containers/%s", projectPrefix(source.Project(), source.Name())), tmpSnapshotName)
+		err = zfsPoolVolumeSnapshotCreate(poolName, fmt.Sprintf("containers/%s", project.Prefix(source.Project(), source.Name())), tmpSnapshotName)
 		if err != nil {
 			return err
 		}
 
-		currentSnapshotDataset := fmt.Sprintf("%s/containers/%s@%s", poolName, projectPrefix(source.Project(), source.Name()), tmpSnapshotName)
+		currentSnapshotDataset := fmt.Sprintf("%s/containers/%s@%s", poolName, project.Prefix(source.Project(), source.Name()), tmpSnapshotName)
 		args := []string{"send", currentSnapshotDataset}
 		if prevSnapOnlyName != "" {
-			parentSnapshotDataset := fmt.Sprintf("%s/containers/%s at snapshot-%s", poolName, projectPrefix(source.Project(), source.Name()), prevSnapOnlyName)
+			parentSnapshotDataset := fmt.Sprintf("%s/containers/%s at snapshot-%s", poolName, project.Prefix(source.Project(), source.Name()), prevSnapOnlyName)
 			args = append(args, "-i", parentSnapshotDataset)
 		}
 
@@ -2003,7 +2004,7 @@ func (s *storageZfs) doContainerBackupCreateOptimized(tmpPath string, backup bac
 			return err
 		}
 
-		zfsPoolVolumeSnapshotDestroy(poolName, fmt.Sprintf("containers/%s", projectPrefix(source.Project(), source.Name())), tmpSnapshotName)
+		zfsPoolVolumeSnapshotDestroy(poolName, fmt.Sprintf("containers/%s", project.Prefix(source.Project(), source.Name())), tmpSnapshotName)
 	}
 	if err != nil {
 		return err
@@ -2024,7 +2025,7 @@ func (s *storageZfs) doContainerBackupCreateVanilla(tmpPath string, backup backu
 	}
 
 	bwlimit := s.pool.Config["rsync.bwlimit"]
-	project := backup.container.Project()
+	projectName := backup.container.Project()
 
 	// Handle snapshots
 	if !backup.containerOnly {
@@ -2053,7 +2054,7 @@ func (s *storageZfs) doContainerBackupCreateVanilla(tmpPath string, backup backu
 				return errors.Wrap(err, "Mount snapshot")
 			}
 
-			snapshotMntPoint := getSnapshotMountPoint(project, s.pool.Name, snap.Name())
+			snapshotMntPoint := getSnapshotMountPoint(projectName, s.pool.Name, snap.Name())
 			target := fmt.Sprintf("%s/%s", snapshotsPath, snapName)
 
 			// Copy the snapshot
@@ -2080,7 +2081,7 @@ func (s *storageZfs) doContainerBackupCreateVanilla(tmpPath string, backup backu
 
 	snapshotSuffix := uuid.NewRandom().String()
 	sourceName := source.Name()
-	fs := fmt.Sprintf("containers/%s", projectPrefix(project, sourceName))
+	fs := fmt.Sprintf("containers/%s", project.Prefix(projectName, sourceName))
 	sourceZfsDatasetSnapshot := fmt.Sprintf("snapshot-%s", snapshotSuffix)
 	poolName := s.getOnDiskPoolName()
 	err = zfsPoolVolumeSnapshotCreate(poolName, fs, sourceZfsDatasetSnapshot)
@@ -2202,7 +2203,7 @@ func (s *storageZfs) doContainerBackupLoadOptimized(info backupInfo, data io.Rea
 			return err
 		}
 
-		snapshotDataset := fmt.Sprintf("%s/containers/%s at snapshot-%s", poolName, projectPrefix(info.Project, containerName), snapshotOnlyName)
+		snapshotDataset := fmt.Sprintf("%s/containers/%s at snapshot-%s", poolName, project.Prefix(info.Project, containerName), snapshotOnlyName)
 		zfsRecvCmd := exec.Command("zfs", "receive", "-F", snapshotDataset)
 		zfsRecvCmd.Stdin = feeder
 		err = zfsRecvCmd.Run()
@@ -2215,8 +2216,8 @@ func (s *storageZfs) doContainerBackupLoadOptimized(info backupInfo, data io.Rea
 
 		// create mountpoint
 		snapshotMntPoint := getSnapshotMountPoint(info.Project, s.pool.Name, fmt.Sprintf("%s/%s", containerName, snapshotOnlyName))
-		snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", projectPrefix(info.Project, containerName))
-		snapshotMntPointSymlink := shared.VarPath("snapshots", projectPrefix(info.Project, containerName))
+		snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", project.Prefix(info.Project, containerName))
+		snapshotMntPointSymlink := shared.VarPath("snapshots", project.Prefix(info.Project, containerName))
 		err = createSnapshotMountpoint(snapshotMntPoint, snapshotMntPointSymlinkTarget, snapshotMntPointSymlink)
 		if err != nil {
 			// can't use defer because it needs to run before the mount
@@ -2234,18 +2235,18 @@ func (s *storageZfs) doContainerBackupLoadOptimized(info backupInfo, data io.Rea
 	}
 	defer feeder.Close()
 
-	containerSnapshotDataset := fmt.Sprintf("%s/containers/%s at backup", poolName, projectPrefix(info.Project, containerName))
+	containerSnapshotDataset := fmt.Sprintf("%s/containers/%s at backup", poolName, project.Prefix(info.Project, containerName))
 	zfsRecvCmd := exec.Command("zfs", "receive", "-F", containerSnapshotDataset)
 	zfsRecvCmd.Stdin = feeder
 
 	err = zfsRecvCmd.Run()
 	os.RemoveAll(unpackPath)
-	zfsPoolVolumeSnapshotDestroy(poolName, fmt.Sprintf("containers/%s", projectPrefix(info.Project, containerName)), "backup")
+	zfsPoolVolumeSnapshotDestroy(poolName, fmt.Sprintf("containers/%s", project.Prefix(info.Project, containerName)), "backup")
 	if err != nil {
 		return err
 	}
 
-	fs := fmt.Sprintf("containers/%s", projectPrefix(info.Project, containerName))
+	fs := fmt.Sprintf("containers/%s", project.Prefix(info.Project, containerName))
 	err = zfsPoolVolumeSet(poolName, fs, "canmount", "noauto")
 	if err != nil {
 		return err
@@ -2558,9 +2559,9 @@ func (s *zfsMigrationSourceDriver) send(conn *websocket.Conn, zfsName string, zf
 		}
 	}
 
-	args = append(args, []string{fmt.Sprintf("%s/containers/%s@%s", poolName, projectPrefix(s.container.Project(), sourceParentName), zfsName)}...)
+	args = append(args, []string{fmt.Sprintf("%s/containers/%s@%s", poolName, project.Prefix(s.container.Project(), sourceParentName), zfsName)}...)
 	if zfsParent != "" {
-		args = append(args, "-i", fmt.Sprintf("%s/containers/%s@%s", poolName, projectPrefix(s.container.Project(), s.container.Name()), zfsParent))
+		args = append(args, "-i", fmt.Sprintf("%s/containers/%s@%s", poolName, project.Prefix(s.container.Project(), s.container.Name()), zfsParent))
 	}
 
 	cmd := exec.Command("zfs", args...)
@@ -2625,7 +2626,7 @@ func (s *zfsMigrationSourceDriver) SendWhileRunning(conn *websocket.Conn, op *op
 	}
 
 	s.runningSnapName = fmt.Sprintf("migration-send-%s", uuid.NewRandom().String())
-	if err := zfsPoolVolumeSnapshotCreate(s.zfs.getOnDiskPoolName(), fmt.Sprintf("containers/%s", projectPrefix(s.container.Project(), s.container.Name())), s.runningSnapName); err != nil {
+	if err := zfsPoolVolumeSnapshotCreate(s.zfs.getOnDiskPoolName(), fmt.Sprintf("containers/%s", project.Prefix(s.container.Project(), s.container.Name())), s.runningSnapName); err != nil {
 		return err
 	}
 
@@ -2639,7 +2640,7 @@ func (s *zfsMigrationSourceDriver) SendWhileRunning(conn *websocket.Conn, op *op
 
 func (s *zfsMigrationSourceDriver) SendAfterCheckpoint(conn *websocket.Conn, bwlimit string) error {
 	s.stoppedSnapName = fmt.Sprintf("migration-send-%s", uuid.NewRandom().String())
-	if err := zfsPoolVolumeSnapshotCreate(s.zfs.getOnDiskPoolName(), fmt.Sprintf("containers/%s", projectPrefix(s.container.Project(), s.container.Name())), s.stoppedSnapName); err != nil {
+	if err := zfsPoolVolumeSnapshotCreate(s.zfs.getOnDiskPoolName(), fmt.Sprintf("containers/%s", project.Prefix(s.container.Project(), s.container.Name())), s.stoppedSnapName); err != nil {
 		return err
 	}
 
@@ -2653,10 +2654,10 @@ func (s *zfsMigrationSourceDriver) SendAfterCheckpoint(conn *websocket.Conn, bwl
 func (s *zfsMigrationSourceDriver) Cleanup() {
 	poolName := s.zfs.getOnDiskPoolName()
 	if s.stoppedSnapName != "" {
-		zfsPoolVolumeSnapshotDestroy(poolName, fmt.Sprintf("containers/%s", projectPrefix(s.container.Project(), s.container.Name())), s.stoppedSnapName)
+		zfsPoolVolumeSnapshotDestroy(poolName, fmt.Sprintf("containers/%s", project.Prefix(s.container.Project(), s.container.Name())), s.stoppedSnapName)
 	}
 	if s.runningSnapName != "" {
-		zfsPoolVolumeSnapshotDestroy(poolName, fmt.Sprintf("containers/%s", projectPrefix(s.container.Project(), s.container.Name())), s.runningSnapName)
+		zfsPoolVolumeSnapshotDestroy(poolName, fmt.Sprintf("containers/%s", project.Prefix(s.container.Project(), s.container.Name())), s.runningSnapName)
 	}
 }
 
@@ -2692,7 +2693,7 @@ func (s *storageZfs) MigrationSource(args MigrationSourceArgs) (MigrationStorage
 	* is that we send the oldest to newest snapshot, hopefully saving on
 	* xfer costs. Then, after all that, we send the container itself.
 	 */
-	snapshots, err := zfsPoolListSnapshots(s.getOnDiskPoolName(), fmt.Sprintf("containers/%s", projectPrefix(args.Container.Project(), args.Container.Name())))
+	snapshots, err := zfsPoolListSnapshots(s.getOnDiskPoolName(), fmt.Sprintf("containers/%s", project.Prefix(args.Container.Project(), args.Container.Name())))
 	if err != nil {
 		return nil, err
 	}
@@ -2766,7 +2767,7 @@ func (s *storageZfs) MigrationSink(conn *websocket.Conn, op *operation, args Mig
 	 * of a snapshot also needs tha actual fs that it has snapshotted
 	 * unmounted, so we do this before receiving anything.
 	 */
-	zfsName := fmt.Sprintf("containers/%s", projectPrefix(args.Container.Project(), args.Container.Name()))
+	zfsName := fmt.Sprintf("containers/%s", project.Prefix(args.Container.Project(), args.Container.Name()))
 	containerMntPoint := getContainerMountPoint(args.Container.Project(), s.pool.Name, args.Container.Name())
 	if shared.IsMountPoint(containerMntPoint) {
 		err := zfsUmount(poolName, zfsName, containerMntPoint)
@@ -2776,8 +2777,8 @@ func (s *storageZfs) MigrationSink(conn *websocket.Conn, op *operation, args Mig
 	}
 
 	if len(args.Snapshots) > 0 {
-		snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", projectPrefix(args.Container.Project(), s.volume.Name))
-		snapshotMntPointSymlink := shared.VarPath("snapshots", projectPrefix(args.Container.Project(), args.Container.Name()))
+		snapshotMntPointSymlinkTarget := shared.VarPath("storage-pools", s.pool.Name, "containers-snapshots", project.Prefix(args.Container.Project(), s.volume.Name))
+		snapshotMntPointSymlink := shared.VarPath("snapshots", project.Prefix(args.Container.Project(), args.Container.Name()))
 		if !shared.PathExists(snapshotMntPointSymlink) {
 			err := os.Symlink(snapshotMntPointSymlinkTarget, snapshotMntPointSymlink)
 			if err != nil {
@@ -2821,7 +2822,7 @@ func (s *storageZfs) MigrationSink(conn *websocket.Conn, op *operation, args Mig
 		}
 
 		wrapper := StorageProgressWriter(op, "fs_progress", snap.GetName())
-		name := fmt.Sprintf("containers/%s at snapshot-%s", projectPrefix(args.Container.Project(), args.Container.Name()), snap.GetName())
+		name := fmt.Sprintf("containers/%s at snapshot-%s", project.Prefix(args.Container.Project(), args.Container.Name()), snap.GetName())
 		if err := zfsRecv(name, wrapper); err != nil {
 			return err
 		}
@@ -2837,7 +2838,7 @@ func (s *storageZfs) MigrationSink(conn *websocket.Conn, op *operation, args Mig
 
 	defer func() {
 		/* clean up our migration-send snapshots that we got from recv. */
-		zfsSnapshots, err := zfsPoolListSnapshots(poolName, fmt.Sprintf("containers/%s", projectPrefix(args.Container.Project(), args.Container.Name())))
+		zfsSnapshots, err := zfsPoolListSnapshots(poolName, fmt.Sprintf("containers/%s", project.Prefix(args.Container.Project(), args.Container.Name())))
 		if err != nil {
 			logger.Errorf("Failed listing snapshots post migration: %s", err)
 			return
@@ -2849,7 +2850,7 @@ func (s *storageZfs) MigrationSink(conn *websocket.Conn, op *operation, args Mig
 				continue
 			}
 
-			zfsPoolVolumeSnapshotDestroy(poolName, fmt.Sprintf("containers/%s", projectPrefix(args.Container.Project(), args.Container.Name())), snap)
+			zfsPoolVolumeSnapshotDestroy(poolName, fmt.Sprintf("containers/%s", project.Prefix(args.Container.Project(), args.Container.Name())), snap)
 		}
 	}()
 
@@ -2888,7 +2889,7 @@ func (s *storageZfs) StorageEntitySetQuota(volumeType int, size int64, data inte
 	switch volumeType {
 	case storagePoolVolumeTypeContainer:
 		c = data.(container)
-		fs = fmt.Sprintf("containers/%s", projectPrefix(c.Project(), c.Name()))
+		fs = fmt.Sprintf("containers/%s", project.Prefix(c.Project(), c.Name()))
 	case storagePoolVolumeTypeCustom:
 		fs = fmt.Sprintf("custom/%s", s.volume.Name)
 	}
diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index 33bc9f717f..5022651865 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -12,6 +12,7 @@ import (
 	"github.com/pborman/uuid"
 	"golang.org/x/sys/unix"
 
+	"github.com/lxc/lxd/lxd/project"
 	"github.com/lxc/lxd/shared"
 	"github.com/lxc/lxd/shared/logger"
 )
@@ -634,12 +635,12 @@ func zfsFilesystemEntityExists(pool string, path string) bool {
 	return detectedName == vdev
 }
 
-func (s *storageZfs) doContainerMount(project, name string, privileged bool) (bool, error) {
+func (s *storageZfs) doContainerMount(projectName, name string, privileged bool) (bool, error) {
 	logger.Debugf("Mounting ZFS storage volume for container \"%s\" on storage pool \"%s\"", s.volume.Name, s.pool.Name)
 
-	volumeName := projectPrefix(project, name)
+	volumeName := project.Prefix(projectName, name)
 	fs := fmt.Sprintf("containers/%s", volumeName)
-	containerPoolVolumeMntPoint := getContainerMountPoint(project, s.pool.Name, name)
+	containerPoolVolumeMntPoint := getContainerMountPoint(projectName, s.pool.Name, name)
 
 	containerMountLockID := getContainerMountLockID(s.pool.Name, name)
 	lxdStorageMapLock.Lock()
@@ -699,13 +700,13 @@ func (s *storageZfs) doContainerMount(project, name string, privileged bool) (bo
 	return ourMount, nil
 }
 
-func (s *storageZfs) doContainerDelete(project, name string) error {
+func (s *storageZfs) doContainerDelete(projectName, name string) error {
 	logger.Debugf("Deleting ZFS storage volume for container \"%s\" on storage pool \"%s\"", s.volume.Name, s.pool.Name)
 
 	poolName := s.getOnDiskPoolName()
 	containerName := name
-	fs := fmt.Sprintf("containers/%s", projectPrefix(project, containerName))
-	containerPoolVolumeMntPoint := getContainerMountPoint(project, s.pool.Name, containerName)
+	fs := fmt.Sprintf("containers/%s", project.Prefix(projectName, containerName))
+	containerPoolVolumeMntPoint := getContainerMountPoint(projectName, s.pool.Name, containerName)
 
 	if zfsFilesystemEntityExists(poolName, fs) {
 		removable := true
@@ -756,7 +757,7 @@ func (s *storageZfs) doContainerDelete(project, name string) error {
 		}
 	}
 
-	err := deleteContainerMountpoint(containerPoolVolumeMntPoint, shared.VarPath("containers", projectPrefix(project, name)), s.GetStorageTypeName())
+	err := deleteContainerMountpoint(containerPoolVolumeMntPoint, shared.VarPath("containers", project.Prefix(projectName, name)), s.GetStorageTypeName())
 	if err != nil {
 		return err
 	}
@@ -765,7 +766,7 @@ func (s *storageZfs) doContainerDelete(project, name string) error {
 	zfsPoolVolumeDestroy(poolName, snapshotZfsDataset)
 
 	// Delete potential leftover snapshot mountpoints.
-	snapshotMntPoint := getSnapshotMountPoint(project, s.pool.Name, containerName)
+	snapshotMntPoint := getSnapshotMountPoint(projectName, s.pool.Name, containerName)
 	if shared.PathExists(snapshotMntPoint) {
 		err := os.RemoveAll(snapshotMntPoint)
 		if err != nil {
@@ -775,7 +776,7 @@ func (s *storageZfs) doContainerDelete(project, name string) error {
 
 	// Delete potential leftover snapshot symlinks:
 	// ${LXD_DIR}/snapshots/<container_name> to ${POOL}/snapshots/<container_name>
-	snapshotSymlink := shared.VarPath("snapshots", projectPrefix(project, containerName))
+	snapshotSymlink := shared.VarPath("snapshots", project.Prefix(projectName, containerName))
 	if shared.PathExists(snapshotSymlink) {
 		err := os.Remove(snapshotSymlink)
 		if err != nil {
@@ -787,15 +788,15 @@ func (s *storageZfs) doContainerDelete(project, name string) error {
 	return nil
 }
 
-func (s *storageZfs) doContainerCreate(project, name string, privileged bool) error {
+func (s *storageZfs) doContainerCreate(projectName, name string, privileged bool) error {
 	logger.Debugf("Creating empty ZFS storage volume for container \"%s\" on storage pool \"%s\"", s.volume.Name, s.pool.Name)
 
-	containerPath := shared.VarPath("containers", projectPrefix(project, name))
+	containerPath := shared.VarPath("containers", project.Prefix(projectName, name))
 	containerName := name
-	fs := fmt.Sprintf("containers/%s", projectPrefix(project, containerName))
+	fs := fmt.Sprintf("containers/%s", project.Prefix(projectName, containerName))
 	poolName := s.getOnDiskPoolName()
 	dataset := fmt.Sprintf("%s/%s", poolName, fs)
-	containerPoolVolumeMntPoint := getContainerMountPoint(project, s.pool.Name, containerName)
+	containerPoolVolumeMntPoint := getContainerMountPoint(projectName, s.pool.Name, containerName)
 
 	// Create volume.
 	msg, err := zfsPoolVolumeCreate(dataset, "mountpoint=none", "canmount=noauto")


More information about the lxc-devel mailing list