[lxc-devel] [lxd/master] Implement storage patch mechanism

stgraber on Github lxc-bot at linuxcontainers.org
Wed Jan 15 05:52:34 UTC 2020


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200114/c9110de1/attachment-0001.bin>
-------------- next part --------------
From 424caa0553e474ee48ca23b465a93686bd660611 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 15 Jan 2020 00:42:06 -0500
Subject: [PATCH 1/4] lxd/storage/drivers: Rename drivers_ to driver_
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/storage/drivers/{drivers_lvm.go => driver_lvm.go}             | 0
 lxd/storage/drivers/{drivers_lvm_utils.go => driver_lvm_utils.go} | 0
 .../drivers/{drivers_lvm_volumes.go => driver_lvm_volumes.go}     | 0
 3 files changed, 0 insertions(+), 0 deletions(-)
 rename lxd/storage/drivers/{drivers_lvm.go => driver_lvm.go} (100%)
 rename lxd/storage/drivers/{drivers_lvm_utils.go => driver_lvm_utils.go} (100%)
 rename lxd/storage/drivers/{drivers_lvm_volumes.go => driver_lvm_volumes.go} (100%)

diff --git a/lxd/storage/drivers/drivers_lvm.go b/lxd/storage/drivers/driver_lvm.go
similarity index 100%
rename from lxd/storage/drivers/drivers_lvm.go
rename to lxd/storage/drivers/driver_lvm.go
diff --git a/lxd/storage/drivers/drivers_lvm_utils.go b/lxd/storage/drivers/driver_lvm_utils.go
similarity index 100%
rename from lxd/storage/drivers/drivers_lvm_utils.go
rename to lxd/storage/drivers/driver_lvm_utils.go
diff --git a/lxd/storage/drivers/drivers_lvm_volumes.go b/lxd/storage/drivers/driver_lvm_volumes.go
similarity index 100%
rename from lxd/storage/drivers/drivers_lvm_volumes.go
rename to lxd/storage/drivers/driver_lvm_volumes.go

From dd55ce01c1799c2f01b6c7ecf785c80d1d5ad35d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 15 Jan 2020 00:17:47 -0500
Subject: [PATCH 2/4] lxd/storage/drivers: Implement patch mechanism
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/storage/drivers/driver_common.go | 21 +++++++++++++++++++++
 lxd/storage/drivers/interface.go     |  1 +
 2 files changed, 22 insertions(+)

diff --git a/lxd/storage/drivers/driver_common.go b/lxd/storage/drivers/driver_common.go
index 785ea72f6b..9bac72e386 100644
--- a/lxd/storage/drivers/driver_common.go
+++ b/lxd/storage/drivers/driver_common.go
@@ -27,6 +27,7 @@ type common struct {
 	getCommonVolumeRules func(vol Volume) map[string]func(string) error
 	state                *state.State
 	logger               logger.Logger
+	patches              map[string]func() error
 }
 
 func (d *common) init(state *state.State, name string, config map[string]string, logger logger.Logger, volIDFunc func(volType VolumeType, volName string) (int64, error), commonVolRulesFunc func(vol Volume) map[string]func(string) error) {
@@ -124,6 +125,26 @@ func (d *common) Config() map[string]string {
 	return confCopy
 }
 
+// ApplyPatch looks for a suitable patch and runs it.
+func (d *common) ApplyPatch(name string) error {
+	if d.patches == nil {
+		return fmt.Errorf("The patch mechanism isn't implemented on pool '%s'", d.name)
+	}
+
+	// Locate the patch.
+	patch, ok := d.patches[name]
+	if !ok {
+		return fmt.Errorf("Patch '%s' isn't implemented on pool '%s'", name, d.name)
+	}
+
+	// Handle cases where a patch isn't needed.
+	if patch == nil {
+		return nil
+	}
+
+	return patch()
+}
+
 // vfsGetResources is a generic GetResources implementation for VFS-only drivers.
 func (d *common) vfsGetResources() (*api.ResourcesStoragePool, error) {
 	// Get the VFS information
diff --git a/lxd/storage/drivers/interface.go b/lxd/storage/drivers/interface.go
index 092c97a5dd..0e4a58a558 100644
--- a/lxd/storage/drivers/interface.go
+++ b/lxd/storage/drivers/interface.go
@@ -40,6 +40,7 @@ type Driver interface {
 	GetResources() (*api.ResourcesStoragePool, error)
 	Validate(config map[string]string) error
 	Update(changedConfig map[string]string) error
+	ApplyPatch(name string) error
 
 	// Volumes.
 	ValidateVolume(vol Volume, removeUnknownKeys bool) error

From 8e2bf1015770519f4f43eb39b87f76e7b3e4857b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 15 Jan 2020 00:26:13 -0500
Subject: [PATCH 3/4] lxd/storage: Add patch mechanism to backend
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/storage/backend_lxd.go         | 29 +++++++++++++++++++++++++++++
 lxd/storage/backend_lxd_patches.go |  5 +++++
 lxd/storage/backend_mock.go        |  4 ++++
 lxd/storage/pool_interface.go      |  2 ++
 4 files changed, 40 insertions(+)
 create mode 100644 lxd/storage/backend_lxd_patches.go

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index 582e225005..0f89357600 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -233,6 +233,35 @@ func (b *lxdBackend) Unmount() (bool, error) {
 	return b.driver.Unmount()
 }
 
+// ApplyPatch runs the requested patch at both backend and driver level.
+func (b *lxdBackend) ApplyPatch(name string) error {
+	// Run early backend patches.
+	patch, ok := lxdEarlyPatches[name]
+	if ok {
+		err := patch(b)
+		if err != nil {
+			return err
+		}
+	}
+
+	// Run the driver patch itself.
+	err := b.driver.ApplyPatch(name)
+	if err != nil {
+		return err
+	}
+
+	// Run late backend patches.
+	patch, ok = lxdLatePatches[name]
+	if ok {
+		err := patch(b)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
 // ensureInstanceSymlink creates a symlink in the instance directory to the instance's mount path
 // if doesn't exist already.
 func (b *lxdBackend) ensureInstanceSymlink(instanceType instancetype.Type, projectName, instanceName, mountPath string) error {
diff --git a/lxd/storage/backend_lxd_patches.go b/lxd/storage/backend_lxd_patches.go
new file mode 100644
index 0000000000..4fb9cf302e
--- /dev/null
+++ b/lxd/storage/backend_lxd_patches.go
@@ -0,0 +1,5 @@
+package storage
+
+var lxdEarlyPatches = map[string]func(b *lxdBackend) error{}
+
+var lxdLatePatches = map[string]func(b *lxdBackend) error{}
diff --git a/lxd/storage/backend_mock.go b/lxd/storage/backend_mock.go
index c2eef25bb8..90f15951ff 100644
--- a/lxd/storage/backend_mock.go
+++ b/lxd/storage/backend_mock.go
@@ -60,6 +60,10 @@ func (b *mockBackend) Unmount() (bool, error) {
 	return true, nil
 }
 
+func (b *mockBackend) ApplyPatch(name string) error {
+	return nil
+}
+
 func (b *mockBackend) CreateInstance(inst instance.Instance, op *operations.Operation) error {
 	return nil
 }
diff --git a/lxd/storage/pool_interface.go b/lxd/storage/pool_interface.go
index 2e1e139ecd..40a995ed2b 100644
--- a/lxd/storage/pool_interface.go
+++ b/lxd/storage/pool_interface.go
@@ -25,6 +25,8 @@ type Pool interface {
 	Mount() (bool, error)
 	Unmount() (bool, error)
 
+	ApplyPatch(name string) error
+
 	// Instances.
 	CreateInstance(inst instance.Instance, op *operations.Operation) error
 	CreateInstanceFromBackup(srcBackup backup.Info, srcData io.ReadSeeker, op *operations.Operation) (func(instance.Instance) error, func(), error)

From ae3bc4fce8ddc5f5ee1b9faffeec76bfc73b3d02 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 15 Jan 2020 00:40:46 -0500
Subject: [PATCH 4/4] lxd/patches: Add storage_create_vm
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/patches.go                            | 23 +++++++++++++++++++++++
 lxd/storage/backend_lxd_patches.go        | 13 ++++++++++++-
 lxd/storage/drivers/driver_btrfs.go       |  6 ++++++
 lxd/storage/drivers/driver_cephfs.go      |  6 ++++++
 lxd/storage/drivers/driver_dir.go         | 10 ++++++++++
 lxd/storage/drivers/driver_lvm.go         |  6 ++++++
 lxd/storage/drivers/driver_zfs.go         |  6 ++++++
 lxd/storage/drivers/driver_zfs_patches.go | 21 +++++++++++++++++++++
 8 files changed, 90 insertions(+), 1 deletion(-)
 create mode 100644 lxd/storage/drivers/driver_zfs_patches.go

diff --git a/lxd/patches.go b/lxd/patches.go
index c5f7a1b5e7..5be31ce745 100644
--- a/lxd/patches.go
+++ b/lxd/patches.go
@@ -20,6 +20,7 @@ import (
 	"github.com/lxc/lxd/lxd/instance"
 	"github.com/lxc/lxd/lxd/rsync"
 	driver "github.com/lxc/lxd/lxd/storage"
+	storagePools "github.com/lxc/lxd/lxd/storage"
 	storageDrivers "github.com/lxc/lxd/lxd/storage/drivers"
 	"github.com/lxc/lxd/shared"
 	log "github.com/lxc/lxd/shared/log15"
@@ -77,6 +78,7 @@ var patches = []patch{
 	{name: "storage_api_rename_container_snapshots_dir_again_again", run: patchStorageApiRenameContainerSnapshotsDir},
 	{name: "clustering_add_roles", run: patchClusteringAddRoles},
 	{name: "clustering_add_roles_again", run: patchClusteringAddRoles},
+	{name: "storage_create_vm", run: patchStorageCreateVM},
 }
 
 type patch struct {
@@ -130,6 +132,27 @@ func patchesApplyAll(d *Daemon) error {
 }
 
 // Patches begin here
+func patchStorageCreateVM(name string, d *Daemon) error {
+	// Load all the pools.
+	pools, _ := d.cluster.StoragePools()
+
+	for _, poolName := range pools {
+		pool, err := storagePools.GetPoolByName(d.State(), poolName)
+		if err != storageDrivers.ErrUnknownDriver {
+			if err != nil {
+				return err
+			}
+
+			err = pool.ApplyPatch("storage_create_vm")
+			if err != nil {
+				return err
+			}
+		}
+	}
+
+	return nil
+}
+
 func patchRenameCustomVolumeLVs(name string, d *Daemon) error {
 	// Ignore the error since it will also fail if there are no pools.
 	pools, _ := d.cluster.StoragePools()
diff --git a/lxd/storage/backend_lxd_patches.go b/lxd/storage/backend_lxd_patches.go
index 4fb9cf302e..4fca84102a 100644
--- a/lxd/storage/backend_lxd_patches.go
+++ b/lxd/storage/backend_lxd_patches.go
@@ -1,5 +1,16 @@
 package storage
 
+import (
+	"github.com/lxc/lxd/lxd/storage/drivers"
+)
+
 var lxdEarlyPatches = map[string]func(b *lxdBackend) error{}
 
-var lxdLatePatches = map[string]func(b *lxdBackend) error{}
+var lxdLatePatches = map[string]func(b *lxdBackend) error{
+	"storage_create_vm": lxdPatchStorageCreateVM,
+}
+
+// Patches start here.
+func lxdPatchStorageCreateVM(b *lxdBackend) error {
+	return b.createStorageStructure(drivers.GetPoolMountPath(b.name))
+}
diff --git a/lxd/storage/drivers/driver_btrfs.go b/lxd/storage/drivers/driver_btrfs.go
index f45ffe75b2..d508709fc8 100644
--- a/lxd/storage/drivers/driver_btrfs.go
+++ b/lxd/storage/drivers/driver_btrfs.go
@@ -27,6 +27,12 @@ type btrfs struct {
 
 // load is used to run one-time action per-driver rather than per-pool.
 func (d *btrfs) load() error {
+	// Register the patches.
+	d.patches = map[string]func() error{
+		"storage_create_vm": nil,
+	}
+
+	// Done if previously loaded.
 	if btrfsLoaded {
 		return nil
 	}
diff --git a/lxd/storage/drivers/driver_cephfs.go b/lxd/storage/drivers/driver_cephfs.go
index bbeacc4478..53fafa9530 100644
--- a/lxd/storage/drivers/driver_cephfs.go
+++ b/lxd/storage/drivers/driver_cephfs.go
@@ -25,6 +25,12 @@ type cephfs struct {
 
 // load is used to run one-time action per-driver rather than per-pool.
 func (d *cephfs) load() error {
+	// Register the patches.
+	d.patches = map[string]func() error{
+		"storage_create_vm": nil,
+	}
+
+	// Done if previously loaded.
 	if cephfsLoaded {
 		return nil
 	}
diff --git a/lxd/storage/drivers/driver_dir.go b/lxd/storage/drivers/driver_dir.go
index 3e0d6f56a1..27707a379d 100644
--- a/lxd/storage/drivers/driver_dir.go
+++ b/lxd/storage/drivers/driver_dir.go
@@ -16,6 +16,16 @@ type dir struct {
 	common
 }
 
+// load is used to run one-time action per-driver rather than per-pool.
+func (d *dir) load() error {
+	// Register the patches.
+	d.patches = map[string]func() error{
+		"storage_create_vm": nil,
+	}
+
+	return nil
+}
+
 // Info returns info about the driver and its environment.
 func (d *dir) Info() Info {
 	return Info{
diff --git a/lxd/storage/drivers/driver_lvm.go b/lxd/storage/drivers/driver_lvm.go
index 1ebf58d703..9eb629d503 100644
--- a/lxd/storage/drivers/driver_lvm.go
+++ b/lxd/storage/drivers/driver_lvm.go
@@ -28,6 +28,12 @@ type lvm struct {
 }
 
 func (d *lvm) load() error {
+	// Register the patches.
+	d.patches = map[string]func() error{
+		"storage_create_vm": nil,
+	}
+
+	// Done if previously loaded.
 	if lvmLoaded {
 		return nil
 	}
diff --git a/lxd/storage/drivers/driver_zfs.go b/lxd/storage/drivers/driver_zfs.go
index 72b79253fe..e77df847f8 100644
--- a/lxd/storage/drivers/driver_zfs.go
+++ b/lxd/storage/drivers/driver_zfs.go
@@ -36,6 +36,12 @@ type zfs struct {
 
 // load is used to run one-time action per-driver rather than per-pool.
 func (d *zfs) load() error {
+	// Register the patches.
+	d.patches = map[string]func() error{
+		"storage_create_vm": d.patchStorageCreateVM,
+	}
+
+	// Done if previously loaded.
 	if zfsLoaded {
 		return nil
 	}
diff --git a/lxd/storage/drivers/driver_zfs_patches.go b/lxd/storage/drivers/driver_zfs_patches.go
new file mode 100644
index 0000000000..fc6eccd146
--- /dev/null
+++ b/lxd/storage/drivers/driver_zfs_patches.go
@@ -0,0 +1,21 @@
+package drivers
+
+import (
+	"path/filepath"
+)
+
+func (d *zfs) patchStorageCreateVM() error {
+	// Create any missing initial dataset.
+	for _, dataset := range d.initialDatasets() {
+		if d.checkDataset(filepath.Join(d.config["zfs.pool_name"], dataset)) {
+			continue
+		}
+
+		err := d.createDataset(filepath.Join(d.config["zfs.pool_name"], dataset), "mountpoint=none")
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}


More information about the lxc-devel mailing list