[lxc-devel] [lxd/master] LXD init: Verify ZFS pool when in interactive mode.

dnegreira on Github lxc-bot at linuxcontainers.org
Tue Dec 11 23:29:59 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 773 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20181211/0164e7d1/attachment.bin>
-------------- next part --------------
From e257b2cbe243030f129f1d3ab7e02da42b768926 Mon Sep 17 00:00:00 2001
From: David Negreira <David at otherreality.net>
Date: Wed, 12 Dec 2018 00:27:23 +0100
Subject: [PATCH 1/2] lxd/storage_zfs_utils: Add zfsPoolVolumeExists

Signed-off-by: David Negreira <David at otherreality.net>
---
 lxd/storage_zfs_utils.go | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index f6583a8b46..4ce07da45f 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -89,6 +89,23 @@ func zfsPoolCheck(pool string) error {
 	return nil
 }
 
+// zfsPoolVolumeExists verifies if a specific ZFS pool or volume exists.
+func zfsPoolVolumeExists(dataset string) (bool, error) {
+	output, err := shared.RunCommand(
+		"zfs", "list", "-Ho", "name")
+
+	if err != nil {
+		return false, err
+	}
+
+	for _, name := range strings.Split(output, "\n") {
+		if name == dataset {
+			return true, nil
+		}
+	}
+	return false, nil
+}
+
 func zfsPoolCreate(pool string, vdev string) error {
 	var output string
 	var err error

From 0fab33b93ea699fc1938ec8f3081c1a148b0c969 Mon Sep 17 00:00:00 2001
From: David Negreira <David at otherreality.net>
Date: Wed, 12 Dec 2018 00:27:28 +0100
Subject: [PATCH 2/2] lxd/init: Checks if a zfs storage pool or dataset exists

Signed-off-by: David Negreira <David at otherreality.net>
---
 lxd/main_init_interactive.go | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/lxd/main_init_interactive.go b/lxd/main_init_interactive.go
index 623b0bfe2e..12aafeb21a 100644
--- a/lxd/main_init_interactive.go
+++ b/lxd/main_init_interactive.go
@@ -495,6 +495,18 @@ func (c *cmdInit) askStoragePool(config *cmdInitData, d lxd.ContainerServer, poo
 
 				// Ask for the number of placement groups
 				pool.Config["ceph.osd.pg_num"] = cli.AskString("Number of placement groups [default=32]: ", "32", nil)
+			}
+			if pool.Driver == "zfs" {
+				if os.Geteuid() != 0 {
+					return fmt.Errorf("In order to create a ZFS pool, we require root privileges")
+				}
+				poolvolumeexists, err := zfsPoolVolumeExists(pool.Name)
+				if err != nil {
+					return err
+				}
+				if poolvolumeexists {
+					return fmt.Errorf("'%s' ZFS pool already exists", pool.Name)
+				}
 			} else if cli.AskBool("Would you like to use an existing block device? (yes/no) [default=no]: ", "no") {
 				deviceExists := func(path string) error {
 					if !shared.IsBlockdevPath(path) {
@@ -551,6 +563,21 @@ func (c *cmdInit) askStoragePool(config *cmdInitData, d lxd.ContainerServer, poo
 				// ask for the name of the existing pool
 				pool.Config["source"] = cli.AskString("Name of the existing OSD storage pool [default=lxd]: ", "lxd", nil)
 				pool.Config["ceph.osd.pool_name"] = pool.Config["source"]
+			}
+			if pool.Driver == "zfs" {
+				if os.Geteuid() != 0 {
+					return fmt.Errorf("In order to create a ZFS pool, we require root privileges")
+				}
+				answer := cli.AskString("Name of the existing ZFS storage pool: ", "", nil)
+				poolvolumeexists, err := zfsPoolVolumeExists(answer)
+				if err != nil {
+					return err
+				}
+				if poolvolumeexists == false {
+					return fmt.Errorf("'%s' ZFS pool or dataset does not exist", answer)
+				} else {
+					pool.Config["source"] = answer
+				}
 			} else {
 				question := fmt.Sprintf("Name of the existing %s pool or dataset: ", strings.ToUpper(pool.Driver))
 				pool.Config["source"] = cli.AskString(question, "", nil)


More information about the lxc-devel mailing list