The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/6377
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === Partially implements Create Image (for directory which is a no-op). Other storage drivers will return ErrNotImplemented.
From 600825ac9a562005c128a66736c759111026f17a Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 31 Oct 2019 11:51:29 +0000 Subject: [PATCH 01/22] lxd/storage/volumes: Makes storagePoolVolumeTypePut logic consistent with storagePoolVolumeSnapshotTypePut Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage_volumes.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lxd/storage_volumes.go b/lxd/storage_volumes.go index 0277b83c03..1f7f31cea4 100644 --- a/lxd/storage_volumes.go +++ b/lxd/storage_volumes.go @@ -976,9 +976,13 @@ func storagePoolVolumeTypePut(d *Daemon, r *http.Request, volumeTypeName string) // means that modifying a snapshot's description gets routed here rather // than the dedicated snapshot editing route. So need to handle snapshot // volumes here too. - err = d.cluster.StoragePoolVolumeUpdate(vol.Name, volumeType, poolID, req.Description, req.Config) - if err != nil { - return response.SmartError(err) + + // Update the database if description changed. + if req.Description != vol.Description { + err = d.cluster.StoragePoolVolumeUpdate(vol.Name, volumeType, poolID, req.Description, vol.Config) + if err != nil { + response.SmartError(err) + } } } } else { From 8375d6cdda473179a5d1145c7e463f6f8219d7ac Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 31 Oct 2019 11:52:08 +0000 Subject: [PATCH 02/22] lxd/storage/volumes/snapshot: Moves storagePoolVolumeSnapshotTypePut DB logic Moves DB logic from legacy storage functions into API directly (as just DB updates) as its just a description update. This will then work with both old and new storage layers. Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage_volumes_snapshot.go | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/lxd/storage_volumes_snapshot.go b/lxd/storage_volumes_snapshot.go index f38af7fef8..16794ab836 100644 --- a/lxd/storage_volumes_snapshot.go +++ b/lxd/storage_volumes_snapshot.go @@ -398,6 +398,7 @@ func storagePoolVolumeSnapshotTypeGet(d *Daemon, r *http.Request) response.Respo return response.SyncResponseETag(true, &snapshot, etag) } +// storagePoolVolumeSnapshotTypePut allows a snapshot's description to be changed. func storagePoolVolumeSnapshotTypePut(d *Daemon, r *http.Request) response.Response { // Get the name of the storage pool the volume is supposed to be // attached to. @@ -420,7 +421,7 @@ func storagePoolVolumeSnapshotTypePut(d *Daemon, r *http.Request) response.Respo // Check that the storage volume type is valid. if volumeType != storagePoolVolumeTypeCustom { - return response.BadRequest(fmt.Errorf("invalid storage volume type %s", volumeTypeName)) + return response.BadRequest(fmt.Errorf("Invalid storage volume type %s", volumeTypeName)) } resp := ForwardedResponseIfTargetIsRemote(d, r) @@ -439,13 +440,13 @@ func storagePoolVolumeSnapshotTypePut(d *Daemon, r *http.Request) response.Respo return resp } - _, volume, err := d.cluster.StoragePoolNodeVolumeGetType(fullSnapshotName, volumeType, poolID) + _, vol, err := d.cluster.StoragePoolNodeVolumeGetType(fullSnapshotName, volumeType, poolID) if err != nil { return response.SmartError(err) } // Validate the ETag - etag := []interface{}{snapshotName, volume.Description, volume.Config} + etag := []interface{}{snapshotName, vol.Description, vol.Config} err = util.EtagCheck(r, etag) if err != nil { return response.PreconditionFailed(err) @@ -457,22 +458,22 @@ func storagePoolVolumeSnapshotTypePut(d *Daemon, r *http.Request) response.Respo return response.BadRequest(err) } - var do func(*operations.Operation) error - var opDescription db.OperationType - do = func(op *operations.Operation) error { - err = storagePoolVolumeSnapshotUpdate(d.State(), poolName, volume.Name, volumeType, req.Description) - if err != nil { - return err + do := func(op *operations.Operation) error { + // Update the database if description changed. + if req.Description != vol.Description { + err = d.cluster.StoragePoolVolumeUpdate(vol.Name, volumeType, poolID, req.Description, vol.Config) + if err != nil { + return err + } } - opDescription = db.OperationVolumeSnapshotDelete return nil } resources := map[string][]string{} resources["storage_volume_snapshots"] = []string{volumeName} - op, err := operations.OperationCreate(d.State(), "", operations.OperationClassTask, opDescription, resources, nil, do, nil, nil) + op, err := operations.OperationCreate(d.State(), "", operations.OperationClassTask, db.OperationSnapshotUpdate, resources, nil, do, nil, nil) if err != nil { return response.InternalError(err) } From 441d1ad5bda2aeb4f370dd954b804938391d943e Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 31 Oct 2019 11:53:28 +0000 Subject: [PATCH 03/22] lxd/storage/volumes/utils: Removes unused storagePoolVolumeSnapshotUpdate Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage_volumes_utils.go | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/lxd/storage_volumes_utils.go b/lxd/storage_volumes_utils.go index c70e8acb8a..ab7791e742 100644 --- a/lxd/storage_volumes_utils.go +++ b/lxd/storage_volumes_utils.go @@ -207,28 +207,6 @@ func storagePoolVolumeUpdate(state *state.State, poolName string, volumeName str return nil } -func storagePoolVolumeSnapshotUpdate(state *state.State, poolName string, volumeName string, volumeType int, newDescription string) error { - s, err := storagePoolVolumeInit(state, "default", poolName, volumeName, volumeType) - if err != nil { - return err - } - - oldWritable := s.GetStoragePoolVolumeWritable() - oldDescription := oldWritable.Description - - poolID, err := state.Cluster.StoragePoolGetID(poolName) - if err != nil { - return err - } - - // Update the database if something changed - if newDescription != oldDescription { - return state.Cluster.StoragePoolVolumeUpdate(volumeName, volumeType, poolID, newDescription, oldWritable.Config) - } - - return nil -} - func storagePoolVolumeUsedByContainersGet(s *state.State, project, poolName string, volumeName string) ([]string, error) { insts, err := instanceLoadByProject(s, project) if err != nil { From f524067312ef9617c79933745764bbc6e9c55ab9 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 31 Oct 2019 13:24:31 +0000 Subject: [PATCH 04/22] lxd/storage/backend/lxd: Adds basic debug logging Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/backend_lxd.go | 80 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go index 5619577fb0..c88e0ddc31 100644 --- a/lxd/storage/backend_lxd.go +++ b/lxd/storage/backend_lxd.go @@ -15,6 +15,9 @@ import ( "github.com/lxc/lxd/lxd/storage/memorypipe" "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/api" + log "github.com/lxc/lxd/shared/log15" + "github.com/lxc/lxd/shared/logger" + "github.com/lxc/lxd/shared/logging" ) type lxdBackend struct { @@ -22,6 +25,7 @@ type lxdBackend struct { id int64 name string state *state.State + logger logger.Logger } func (b *lxdBackend) DaemonState() *state.State { @@ -51,6 +55,10 @@ func (b *lxdBackend) MigrationTypes(contentType drivers.ContentType) []migration // create creates the storage pool layout on the storage device. func (b *lxdBackend) create(dbPool *api.StoragePool, op *operations.Operation) error { + logger := logging.AddContext(b.logger, log.Ctx{"args": dbPool}) + logger.Debug("create started") + defer logger.Debug("created finished") + revertPath := true // Create the storage path. @@ -103,11 +111,19 @@ func (b *lxdBackend) newVolume(volType drivers.VolumeType, contentType drivers.C } func (b *lxdBackend) GetResources() (*api.ResourcesStoragePool, error) { + logger := logging.AddContext(b.logger, nil) + logger.Debug("GetResources started") + defer logger.Debug("GetResources finished") + return b.driver.GetResources() } // Delete removes the pool. func (b *lxdBackend) Delete(op *operations.Operation) error { + logger := logging.AddContext(b.logger, nil) + logger.Debug("Delete started") + defer logger.Debug("Delete finished") + // Delete the low-level storage. err := b.driver.Delete(op) if err != nil { @@ -126,11 +142,19 @@ func (b *lxdBackend) Delete(op *operations.Operation) error { // Mount mounts the storage pool. func (b *lxdBackend) Mount() (bool, error) { + logger := logging.AddContext(b.logger, nil) + logger.Debug("Mount started") + defer logger.Debug("Mount finished") + return b.driver.Mount() } // Unmount unmounts the storage pool. func (b *lxdBackend) Unmount() (bool, error) { + logger := logging.AddContext(b.logger, nil) + logger.Debug("Unmount started") + defer logger.Debug("Unmount finished") + return b.driver.Unmount() } @@ -224,6 +248,10 @@ func (b *lxdBackend) CreateImage(img api.Image, op *operations.Operation) error // DeleteImage removes an image from the database and underlying storage device if needed. func (b *lxdBackend) DeleteImage(fingerprint string, op *operations.Operation) error { + logger := logging.AddContext(b.logger, log.Ctx{"fingerprint": fingerprint}) + logger.Debug("DeleteImage started") + defer logger.Debug("DeleteImage finished") + regexSHA256, err := regexp.Compile("^[0-9a-f]{64}$") if err != nil { return err @@ -248,6 +276,10 @@ func (b *lxdBackend) DeleteImage(fingerprint string, op *operations.Operation) e // CreateCustomVolume creates an empty custom volume. func (b *lxdBackend) CreateCustomVolume(volName, desc string, config map[string]string, op *operations.Operation) error { + logger := logging.AddContext(b.logger, log.Ctx{"volName": volName, "desc": desc, "config": config}) + logger.Debug("CreateCustomVolume started") + defer logger.Debug("CreateCustomVolume finished") + // Validate config. err := b.driver.ValidateVolume(b.newVolume(drivers.VolumeTypeCustom, drivers.ContentTypeFS, volName, config), false) if err != nil { @@ -281,6 +313,10 @@ func (b *lxdBackend) CreateCustomVolume(volName, desc string, config map[string] // CreateCustomVolumeFromCopy creates a custom volume from an existing custom volume. // It copies the snapshots from the source volume by default, but can be disabled if requested. func (b *lxdBackend) CreateCustomVolumeFromCopy(volName, desc string, config map[string]string, srcPoolName, srcVolName string, srcVolOnly bool, op *operations.Operation) error { + logger := logging.AddContext(b.logger, log.Ctx{"volName": volName, "desc": desc, "config": config, "srcPoolName": srcPoolName, "srcVolName": srcVolName, "srcVolOnly": srcVolOnly}) + logger.Debug("CreateCustomVolumeFromCopy started") + defer logger.Debug("CreateCustomVolumeFromCopy finished") + // Setup the source pool backend instance. var srcPool *lxdBackend if b.name == srcPoolName { @@ -395,6 +431,10 @@ func (b *lxdBackend) CreateCustomVolumeFromCopy(volName, desc string, config map // MigrateCustomVolume sends a volume for migration. func (b *lxdBackend) MigrateCustomVolume(conn io.ReadWriteCloser, args migration.VolumeSourceArgs, op *operations.Operation) error { + logger := logging.AddContext(b.logger, log.Ctx{"volName": args.Name, "args": args}) + logger.Debug("MigrateCustomVolume started") + defer logger.Debug("MigrateCustomVolume finished") + vol := b.newVolume(drivers.VolumeTypeCustom, drivers.ContentTypeFS, args.Name, nil) err := b.driver.MigrateVolume(vol, conn, args, op) if err != nil { @@ -406,6 +446,10 @@ func (b *lxdBackend) MigrateCustomVolume(conn io.ReadWriteCloser, args migration // CreateCustomVolumeFromMigration receives a volume being migrated. func (b *lxdBackend) CreateCustomVolumeFromMigration(conn io.ReadWriteCloser, args migration.VolumeTargetArgs, op *operations.Operation) error { + logger := logging.AddContext(b.logger, log.Ctx{"volName": args.Name, "args": args}) + logger.Debug("CreateCustomVolumeFromMigration started") + defer logger.Debug("CreateCustomVolumeFromMigration finished") + // Create slice to record DB volumes created if revert needed later. revertDBVolumes := []string{} defer func() { @@ -455,6 +499,10 @@ func (b *lxdBackend) CreateCustomVolumeFromMigration(conn io.ReadWriteCloser, ar // RenameCustomVolume renames a custom volume and its snapshots. func (b *lxdBackend) RenameCustomVolume(volName string, newVolName string, op *operations.Operation) error { + logger := logging.AddContext(b.logger, log.Ctx{"volName": volName, "newVolName": newVolName}) + logger.Debug("RenameCustomVolume started") + defer logger.Debug("RenameCustomVolume finished") + if shared.IsSnapshot(volName) { return fmt.Errorf("Volume name cannot be a snapshot") } @@ -518,6 +566,10 @@ func (b *lxdBackend) RenameCustomVolume(volName string, newVolName string, op *o // UpdateCustomVolume applies the supplied config to the custom volume. func (b *lxdBackend) UpdateCustomVolume(volName, newDesc string, newConfig map[string]string, op *operations.Operation) error { + logger := logging.AddContext(b.logger, log.Ctx{"volName": volName, "newDesc": newDesc, "newConfig": newConfig}) + logger.Debug("UpdateCustomVolume started") + defer logger.Debug("UpdateCustomVolume finished") + if shared.IsSnapshot(volName) { return fmt.Errorf("Volume name cannot be a snapshot") } @@ -609,6 +661,10 @@ func (b *lxdBackend) UpdateCustomVolume(volName, newDesc string, newConfig map[s // DeleteCustomVolume removes a custom volume and its snapshots. func (b *lxdBackend) DeleteCustomVolume(volName string, op *operations.Operation) error { + logger := logging.AddContext(b.logger, log.Ctx{"volName": volName}) + logger.Debug("DeleteCustomVolume started") + defer logger.Debug("DeleteCustomVolume finished") + _, _, isSnap := shared.ContainerGetParentAndSnapshotName(volName) if isSnap { return fmt.Errorf("Volume name cannot be a snapshot") @@ -667,16 +723,28 @@ func (b *lxdBackend) SetCustomVolumeQuota(vol api.StorageVolume, quota uint64) e // MountCustomVolume mounts a custom volume. func (b *lxdBackend) MountCustomVolume(volName string, op *operations.Operation) (bool, error) { + logger := logging.AddContext(b.logger, log.Ctx{"volName": volName}) + logger.Debug("MountCustomVolume started") + defer logger.Debug("MountCustomVolume finished") + return b.driver.MountVolume(drivers.VolumeTypeCustom, volName, op) } // UnmountCustomVolume unmounts a custom volume. func (b *lxdBackend) UnmountCustomVolume(volName string, op *operations.Operation) (bool, error) { + logger := logging.AddContext(b.logger, log.Ctx{"volName": volName}) + logger.Debug("UnmountCustomVolume started") + defer logger.Debug("UnmountCustomVolume finished") + return b.driver.UnmountVolume(drivers.VolumeTypeCustom, volName, op) } // CreateCustomVolumeSnapshot creates a snapshot of a custom volume. func (b *lxdBackend) CreateCustomVolumeSnapshot(volName string, newSnapshotName string, op *operations.Operation) error { + logger := logging.AddContext(b.logger, log.Ctx{"volName": volName, "newSnapshotName": newSnapshotName}) + logger.Debug("CreateCustomVolumeSnapshot started") + defer logger.Debug("CreateCustomVolumeSnapshot finished") + if shared.IsSnapshot(volName) { return fmt.Errorf("Volume cannot be snapshot") } @@ -732,6 +800,10 @@ func (b *lxdBackend) CreateCustomVolumeSnapshot(volName string, newSnapshotName // RenameCustomVolumeSnapshot renames a custom volume. func (b *lxdBackend) RenameCustomVolumeSnapshot(volName string, newSnapshotName string, op *operations.Operation) error { + logger := logging.AddContext(b.logger, log.Ctx{"volName": volName, "newSnapshotName": newSnapshotName}) + logger.Debug("RenameCustomVolumeSnapshot started") + defer logger.Debug("RenameCustomVolumeSnapshot finished") + parentName, oldSnapshotName, isSnap := shared.ContainerGetParentAndSnapshotName(volName) if !isSnap { return fmt.Errorf("Volume name must be a snapshot") @@ -759,6 +831,10 @@ func (b *lxdBackend) RenameCustomVolumeSnapshot(volName string, newSnapshotName // DeleteCustomVolumeSnapshot removes a custom volume snapshot. func (b *lxdBackend) DeleteCustomVolumeSnapshot(volName string, op *operations.Operation) error { + logger := logging.AddContext(b.logger, log.Ctx{"volName": volName}) + logger.Debug("DeleteCustomVolumeSnapshot started") + defer logger.Debug("DeleteCustomVolumeSnapshot finished") + parentName, snapName, isSnap := shared.ContainerGetParentAndSnapshotName(volName) if !isSnap { return fmt.Errorf("Volume name must be a snapshot") @@ -781,6 +857,10 @@ func (b *lxdBackend) DeleteCustomVolumeSnapshot(volName string, op *operations.O // RestoreCustomVolume restores a custom volume from a snapshot. func (b *lxdBackend) RestoreCustomVolume(volName string, snapshotName string, op *operations.Operation) error { + logger := logging.AddContext(b.logger, log.Ctx{"volName": volName, "snapshotName": snapshotName}) + logger.Debug("RestoreCustomVolume started") + defer logger.Debug("RestoreCustomVolume finished") + if shared.IsSnapshot(volName) { return fmt.Errorf("Volume cannot be snapshot") } From c08aada7660e7d72ba0bf93ebca596aa9d88e057 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 31 Oct 2019 13:24:47 +0000 Subject: [PATCH 05/22] lxd/storage/backend/mock: Adds logger support Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/backend_mock.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lxd/storage/backend_mock.go b/lxd/storage/backend_mock.go index aa5f5f67f9..05aa1b9b4f 100644 --- a/lxd/storage/backend_mock.go +++ b/lxd/storage/backend_mock.go @@ -8,11 +8,13 @@ import ( "github.com/lxc/lxd/lxd/state" "github.com/lxc/lxd/lxd/storage/drivers" "github.com/lxc/lxd/shared/api" + "github.com/lxc/lxd/shared/logger" ) type mockBackend struct { - name string - state *state.State + name string + state *state.State + logger logger.Logger } func (b *mockBackend) DaemonState() *state.State { From e1a482df3cb1956d0a1f79b91d95e698f0f8de0f Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 31 Oct 2019 13:25:36 +0000 Subject: [PATCH 06/22] lxd/storage/load: Initialises logger Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/load.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lxd/storage/load.go b/lxd/storage/load.go index d25163f7fd..2c7298e4e7 100644 --- a/lxd/storage/load.go +++ b/lxd/storage/load.go @@ -8,6 +8,9 @@ import ( "github.com/lxc/lxd/lxd/state" "github.com/lxc/lxd/lxd/storage/drivers" "github.com/lxc/lxd/shared/api" + log "github.com/lxc/lxd/shared/log15" + "github.com/lxc/lxd/shared/logger" + "github.com/lxc/lxd/shared/logging" ) // MockBackend controls whether to run the storage logic in mock mode. @@ -56,6 +59,7 @@ func CreatePool(state *state.State, poolID int64, dbPool *api.StoragePool, op *o pool := mockBackend{} pool.name = dbPool.Name pool.state = state + pool.logger = logging.AddContext(logger.Log, log.Ctx{"driver": "mock", "pool": pool.name}) return &pool, nil } @@ -71,6 +75,7 @@ func CreatePool(state *state.State, poolID int64, dbPool *api.StoragePool, op *o pool.id = poolID pool.name = dbPool.Name pool.state = state + pool.logger = logging.AddContext(logger.Log, log.Ctx{"driver": dbPool.Driver, "pool": pool.name}) // Create the pool itself on the storage device.. err = pool.create(dbPool, op) @@ -88,6 +93,7 @@ func GetPoolByName(state *state.State, name string) (Pool, error) { pool := mockBackend{} pool.name = name pool.state = state + pool.logger = logging.AddContext(logger.Log, log.Ctx{"driver": "mock", "pool": pool.name}) return &pool, nil } @@ -114,6 +120,7 @@ func GetPoolByName(state *state.State, name string) (Pool, error) { pool.id = poolID pool.name = dbPool.Name pool.state = state + pool.logger = logging.AddContext(logger.Log, log.Ctx{"driver": dbPool.Driver, "pool": pool.name}) return &pool, nil } From 63a1244d0886cfc6fd0c2a90f81a15b356597c39 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 31 Oct 2019 15:48:34 +0000 Subject: [PATCH 07/22] lxd/storage/drivers/driver/common: Adds driver logger with pool context Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/drivers/driver_common.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lxd/storage/drivers/driver_common.go b/lxd/storage/drivers/driver_common.go index bf6dc8e158..6712aec86e 100644 --- a/lxd/storage/drivers/driver_common.go +++ b/lxd/storage/drivers/driver_common.go @@ -6,6 +6,7 @@ import ( "github.com/lxc/lxd/lxd/migration" "github.com/lxc/lxd/lxd/state" + "github.com/lxc/lxd/shared/logger" ) type common struct { @@ -14,14 +15,16 @@ type common struct { getVolID func(volType VolumeType, volName string) (int64, error) getCommonRules func() map[string]func(string) error state *state.State + logger logger.Logger } -func (d *common) init(state *state.State, name string, config map[string]string, volIDFunc func(volType VolumeType, volName string) (int64, error), commonRulesFunc func() map[string]func(string) 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), commonRulesFunc func() map[string]func(string) error) { d.name = name d.config = config d.getVolID = volIDFunc d.getCommonRules = commonRulesFunc d.state = state + d.logger = logger } // validateVolume validates a volume config against common rules and optional driver specific rules. From 0724ac3f79933834040ddd4a2794742ff1057eae Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 31 Oct 2019 15:48:54 +0000 Subject: [PATCH 08/22] lxd/storage/drivers/interface: Updates with pool context logger Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/drivers/interface.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lxd/storage/drivers/interface.go b/lxd/storage/drivers/interface.go index 09710b17ef..f98b634586 100644 --- a/lxd/storage/drivers/interface.go +++ b/lxd/storage/drivers/interface.go @@ -7,13 +7,14 @@ import ( "github.com/lxc/lxd/lxd/operations" "github.com/lxc/lxd/lxd/state" "github.com/lxc/lxd/shared/api" + "github.com/lxc/lxd/shared/logger" ) // driver is the extended internal interface. type driver interface { Driver - init(state *state.State, name string, config map[string]string, volIDFunc func(volType VolumeType, volName string) (int64, error), commonRulesFunc func() map[string]func(string) error) + init(state *state.State, name string, config map[string]string, logger logger.Logger, volIDFunc func(volType VolumeType, volName string) (int64, error), commonRulesFunc func() map[string]func(string) error) } // Driver represents a low-level storage driver. From 2f1737528f8e891d265e0a4622525a6fa09b1e92 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 31 Oct 2019 15:49:18 +0000 Subject: [PATCH 09/22] lxd/storage/utils: Updates VolumeValidateConfig to use update driver loader Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lxd/storage/utils.go b/lxd/storage/utils.go index acc5e6069c..b22e8c1ada 100644 --- a/lxd/storage/utils.go +++ b/lxd/storage/utils.go @@ -526,7 +526,7 @@ var StorageVolumeConfigKeys = map[string]func(value string) ([]string, error){ // VolumeValidateConfig validations volume config. func VolumeValidateConfig(name string, config map[string]string, parentPool *api.StoragePool) error { // Validate volume config using the new driver interface if supported. - driver, err := drivers.Load(nil, parentPool.Driver, parentPool.Name, parentPool.Config, nil, validateVolumeCommonRules) + driver, err := drivers.Load(nil, parentPool.Driver, parentPool.Name, parentPool.Config, nil, nil, validateVolumeCommonRules) if err != drivers.ErrUnknownDriver { // Note: This legacy validation function doesn't have the concept of validating // different volumes types, so the types are hard coded as Custom and FS. From 01e5b3d84dfa84064a0a0cfb9907334a91d26ea2 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 31 Oct 2019 15:49:44 +0000 Subject: [PATCH 10/22] lxd/storage/load: Updates loaders to support contextual loggers Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/load.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lxd/storage/load.go b/lxd/storage/load.go index 2c7298e4e7..1c134d75d6 100644 --- a/lxd/storage/load.go +++ b/lxd/storage/load.go @@ -63,8 +63,10 @@ func CreatePool(state *state.State, poolID int64, dbPool *api.StoragePool, op *o return &pool, nil } + logger := logging.AddContext(logger.Log, log.Ctx{"driver": dbPool.Driver, "pool": dbPool.Name}) + // Load the storage driver. - driver, err := drivers.Load(state, dbPool.Driver, dbPool.Name, dbPool.Config, volIDFuncMake(state, poolID), validateVolumeCommonRules) + driver, err := drivers.Load(state, dbPool.Driver, dbPool.Name, dbPool.Config, logger, volIDFuncMake(state, poolID), validateVolumeCommonRules) if err != nil { return nil, err } @@ -75,7 +77,7 @@ func CreatePool(state *state.State, poolID int64, dbPool *api.StoragePool, op *o pool.id = poolID pool.name = dbPool.Name pool.state = state - pool.logger = logging.AddContext(logger.Log, log.Ctx{"driver": dbPool.Driver, "pool": pool.name}) + pool.logger = logger // Create the pool itself on the storage device.. err = pool.create(dbPool, op) @@ -108,8 +110,10 @@ func GetPoolByName(state *state.State, name string) (Pool, error) { dbPool.Config = map[string]string{} } + logger := logging.AddContext(logger.Log, log.Ctx{"driver": dbPool.Driver, "pool": dbPool.Name}) + // Load the storage driver. - driver, err := drivers.Load(state, dbPool.Driver, dbPool.Name, dbPool.Config, volIDFuncMake(state, poolID), validateVolumeCommonRules) + driver, err := drivers.Load(state, dbPool.Driver, dbPool.Name, dbPool.Config, logger, volIDFuncMake(state, poolID), validateVolumeCommonRules) if err != nil { return nil, err } @@ -120,7 +124,7 @@ func GetPoolByName(state *state.State, name string) (Pool, error) { pool.id = poolID pool.name = dbPool.Name pool.state = state - pool.logger = logging.AddContext(logger.Log, log.Ctx{"driver": dbPool.Driver, "pool": pool.name}) + pool.logger = logger return &pool, nil } From 4ef30c990afdcdcd13b1e65bd671357051aafc5f Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 31 Oct 2019 15:50:03 +0000 Subject: [PATCH 11/22] lxd/storage/drivers/load: Updates loaders to support contextual loggers Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/drivers/load.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lxd/storage/drivers/load.go b/lxd/storage/drivers/load.go index a10fdfd01f..17ca227f7b 100644 --- a/lxd/storage/drivers/load.go +++ b/lxd/storage/drivers/load.go @@ -2,6 +2,7 @@ package drivers import ( "github.com/lxc/lxd/lxd/state" + "github.com/lxc/lxd/shared/logger" ) var drivers = map[string]func() driver{ @@ -9,7 +10,7 @@ var drivers = map[string]func() driver{ } // Load returns a Driver for an existing low-level storage pool. -func Load(state *state.State, driverName string, name string, config map[string]string, volIDFunc func(volType VolumeType, volName string) (int64, error), commonRulesFunc func() map[string]func(string) error) (Driver, error) { +func Load(state *state.State, driverName string, name string, config map[string]string, logger logger.Logger, volIDFunc func(volType VolumeType, volName string) (int64, error), commonRulesFunc func() map[string]func(string) error) (Driver, error) { // Locate the driver loader. driverFunc, ok := drivers[driverName] if !ok { @@ -17,7 +18,7 @@ func Load(state *state.State, driverName string, name string, config map[string] } d := driverFunc() - d.init(state, name, config, volIDFunc, commonRulesFunc) + d.init(state, name, config, logger, volIDFunc, commonRulesFunc) return d, nil } @@ -38,7 +39,7 @@ func SupportedDrivers() []Info { supportedDrivers := []Info{} for driverName := range drivers { - driver, err := Load(nil, driverName, "", nil, nil, nil) + driver, err := Load(nil, driverName, "", nil, nil, nil, nil) if err != nil { continue } From 186b2606d298baee35bdc5994d5a9b5730a9cef9 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 31 Oct 2019 16:38:45 +0000 Subject: [PATCH 12/22] container/lxc: Hooks up root device usage to new storage package Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/container_lxc.go | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go index 2f0b0200aa..8dc40f7292 100644 --- a/lxd/container_lxc.go +++ b/lxd/container_lxc.go @@ -41,7 +41,8 @@ import ( "github.com/lxc/lxd/lxd/project" "github.com/lxc/lxd/lxd/seccomp" "github.com/lxc/lxd/lxd/state" - 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/lxd/template" "github.com/lxc/lxd/lxd/util" "github.com/lxc/lxd/shared" @@ -324,7 +325,7 @@ func containerLXCCreate(s *state.State, args db.InstanceArgs) (container, error) // Fill in any default volume config volumeConfig := map[string]string{} - err = driver.VolumeFillDefault(storagePool, volumeConfig, pool) + err = storagePools.VolumeFillDefault(storagePool, volumeConfig, pool) if err != nil { c.Delete() return nil, err @@ -3580,7 +3581,7 @@ func (c *containerLXC) Delete() error { // Delete the container from disk if c.storage != nil && !isImport { _, poolName, _ := c.storage.GetContainerPoolInfo() - containerMountPoint := driver.GetContainerMountPoint(c.Project(), poolName, c.Name()) + containerMountPoint := storagePools.GetContainerMountPoint(c.Project(), poolName, c.Name()) if shared.PathExists(c.Path()) || shared.PathExists(containerMountPoint) { err := c.storage.ContainerDelete(c) @@ -5904,9 +5905,26 @@ func (c *containerLXC) diskState() map[string]api.InstanceStateDisk { continue } - usage, err := c.storage.ContainerGetUsage(c) - if err != nil { - continue + var usage int64 + + // Check if we can load new storage layer for pool driver type. + pool, err := storagePools.GetPoolByName(c.state, dev.Config["pool"]) + if err != storageDrivers.ErrUnknownDriver { + if err != nil { + logger.Errorf("Error loading storage pool for %s: %v", c.Name(), err) + continue + } + + usage, err = pool.GetInstanceUsage(c) + if err != nil { + logger.Errorf("Error getting disk usage for %s: %v", c.Name(), err) + continue + } + } else { + usage, err = c.storage.ContainerGetUsage(c) + if err != nil { + continue + } } disk[dev.Name] = api.InstanceStateDisk{Usage: usage} @@ -6718,7 +6736,7 @@ func (c *containerLXC) State() string { // Various container paths func (c *containerLXC) Path() string { name := project.Prefix(c.Project(), c.Name()) - return driver.ContainerPath(name, c.IsSnapshot()) + return storagePools.ContainerPath(name, c.IsSnapshot()) } func (c *containerLXC) DevicesPath() string { From 8490022477076fa5efe22579cae74d367b38ef25 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 31 Oct 2019 16:39:45 +0000 Subject: [PATCH 13/22] lxd/storage/backend/lxd: Updates name of instance arg to inst from i For clarity we don't use i to mean instance. Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/backend_lxd.go | 40 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go index c88e0ddc31..60fb8c7bf4 100644 --- a/lxd/storage/backend_lxd.go +++ b/lxd/storage/backend_lxd.go @@ -158,43 +158,43 @@ func (b *lxdBackend) Unmount() (bool, error) { return b.driver.Unmount() } -func (b *lxdBackend) CreateInstance(i Instance, op *operations.Operation) error { +func (b *lxdBackend) CreateInstance(inst Instance, op *operations.Operation) error { return ErrNotImplemented } -func (b *lxdBackend) CreateInstanceFromBackup(i Instance, sourcePath string, op *operations.Operation) error { +func (b *lxdBackend) CreateInstanceFromBackup(inst Instance, sourcePath string, op *operations.Operation) error { return ErrNotImplemented } -func (b *lxdBackend) CreateInstanceFromCopy(i Instance, src Instance, snapshots bool, op *operations.Operation) error { +func (b *lxdBackend) CreateInstanceFromCopy(inst Instance, src Instance, snapshots bool, op *operations.Operation) error { return ErrNotImplemented } -func (b *lxdBackend) CreateInstanceFromImage(i Instance, fingerprint string, op *operations.Operation) error { +func (b *lxdBackend) CreateInstanceFromImage(inst Instance, fingerprint string, op *operations.Operation) error { return ErrNotImplemented } -func (b *lxdBackend) CreateInstanceFromMigration(i Instance, conn io.ReadWriteCloser, args migration.SinkArgs, op *operations.Operation) error { +func (b *lxdBackend) CreateInstanceFromMigration(inst Instance, conn io.ReadWriteCloser, args migration.SinkArgs, op *operations.Operation) error { return ErrNotImplemented } -func (b *lxdBackend) RenameInstance(i Instance, newName string, op *operations.Operation) error { +func (b *lxdBackend) RenameInstance(inst Instance, newName string, op *operations.Operation) error { return ErrNotImplemented } -func (b *lxdBackend) DeleteInstance(i Instance, op *operations.Operation) error { +func (b *lxdBackend) DeleteInstance(inst Instance, op *operations.Operation) error { return ErrNotImplemented } -func (b *lxdBackend) MigrateInstance(i Instance, snapshots bool, args migration.SourceArgs) (migration.StorageSourceDriver, error) { +func (b *lxdBackend) MigrateInstance(inst Instance, snapshots bool, args migration.SourceArgs) (migration.StorageSourceDriver, error) { return nil, ErrNotImplemented } -func (b *lxdBackend) RefreshInstance(i Instance, src Instance, snapshots bool, op *operations.Operation) error { +func (b *lxdBackend) RefreshInstance(inst Instance, src Instance, snapshots bool, op *operations.Operation) error { return ErrNotImplemented } -func (b *lxdBackend) BackupInstance(i Instance, targetPath string, optimized bool, snapshots bool, op *operations.Operation) error { +func (b *lxdBackend) BackupInstance(inst Instance, targetPath string, optimized bool, snapshots bool, op *operations.Operation) error { return ErrNotImplemented } @@ -202,43 +202,43 @@ func (b *lxdBackend) GetInstanceUsage(i Instance) (uint64, error) { return 0, ErrNotImplemented } -func (b *lxdBackend) SetInstanceQuota(i Instance, quota uint64) error { +func (b *lxdBackend) SetInstanceQuota(inst Instance, quota uint64) error { return ErrNotImplemented } -func (b *lxdBackend) MountInstance(i Instance) (bool, error) { +func (b *lxdBackend) MountInstance(inst Instance) (bool, error) { return true, ErrNotImplemented } -func (b *lxdBackend) UnmountInstance(i Instance) (bool, error) { +func (b *lxdBackend) UnmountInstance(inst Instance) (bool, error) { return true, ErrNotImplemented } -func (b *lxdBackend) GetInstanceDisk(i Instance) (string, string, error) { +func (b *lxdBackend) GetInstanceDisk(inst Instance) (string, string, error) { return "", "", ErrNotImplemented } -func (b *lxdBackend) CreateInstanceSnapshot(i Instance, name string, op *operations.Operation) error { +func (b *lxdBackend) CreateInstanceSnapshot(inst Instance, name string, op *operations.Operation) error { return ErrNotImplemented } -func (b *lxdBackend) RenameInstanceSnapshot(i Instance, newName string, op *operations.Operation) error { +func (b *lxdBackend) RenameInstanceSnapshot(inst Instance, newName string, op *operations.Operation) error { return ErrNotImplemented } -func (b *lxdBackend) DeleteInstanceSnapshot(i Instance, op *operations.Operation) error { +func (b *lxdBackend) DeleteInstanceSnapshot(inst Instance, op *operations.Operation) error { return ErrNotImplemented } -func (b *lxdBackend) RestoreInstanceSnapshot(i Instance, op *operations.Operation) error { +func (b *lxdBackend) RestoreInstanceSnapshot(inst Instance, op *operations.Operation) error { return ErrNotImplemented } -func (b *lxdBackend) MountInstanceSnapshot(i Instance) (bool, error) { +func (b *lxdBackend) MountInstanceSnapshot(inst Instance) (bool, error) { return true, ErrNotImplemented } -func (b *lxdBackend) UnmountInstanceSnapshot(i Instance) (bool, error) { +func (b *lxdBackend) UnmountInstanceSnapshot(inst Instance) (bool, error) { return true, ErrNotImplemented } From 0a8db6591970e4b5282a4c2c68f7db2fbfce6543 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 31 Oct 2019 16:40:18 +0000 Subject: [PATCH 14/22] lxd/storage/backend/lxd: Implements GetInstanceUsage Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/backend_lxd.go | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go index 60fb8c7bf4..1b8d2c0ad5 100644 --- a/lxd/storage/backend_lxd.go +++ b/lxd/storage/backend_lxd.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/lxc/lxd/lxd/db" + "github.com/lxc/lxd/lxd/instance/instancetype" "github.com/lxc/lxd/lxd/migration" "github.com/lxc/lxd/lxd/operations" "github.com/lxc/lxd/lxd/state" @@ -198,8 +199,17 @@ func (b *lxdBackend) BackupInstance(inst Instance, targetPath string, optimized return ErrNotImplemented } -func (b *lxdBackend) GetInstanceUsage(i Instance) (uint64, error) { - return 0, ErrNotImplemented +// GetInstanceUsage returns the disk usage of the Instance's root device. +func (b *lxdBackend) GetInstanceUsage(inst Instance) (int64, error) { + logger := logging.AddContext(b.logger, log.Ctx{"instance": inst.Name()}) + logger.Debug("GetInstanceUsage started") + defer logger.Debug("GetInstanceUsage finished") + + if inst.Type() == instancetype.Container { + return b.driver.GetVolumeUsage(drivers.VolumeTypeContainer, inst.Name()) + } + + return -1, ErrNotImplemented } func (b *lxdBackend) SetInstanceQuota(inst Instance, quota uint64) error { @@ -712,13 +722,9 @@ func (b *lxdBackend) DeleteCustomVolume(volName string, op *operations.Operation return nil } -func (b *lxdBackend) GetCustomVolumeUsage(vol api.StorageVolume) (uint64, error) { - return 0, ErrNotImplemented -} - -// SetCustomVolumeQuota modifies the custom volume's quota. -func (b *lxdBackend) SetCustomVolumeQuota(vol api.StorageVolume, quota uint64) error { - return ErrNotImplemented +// GetCustomVolumeUsage returns the disk space used by the custom volume. +func (b *lxdBackend) GetCustomVolumeUsage(volName string) (int64, error) { + return b.driver.GetVolumeUsage(drivers.VolumeTypeCustom, volName) } // MountCustomVolume mounts a custom volume. From 563b047a22b5f556354027ccd34b1514f3f9cb25 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 31 Oct 2019 16:40:54 +0000 Subject: [PATCH 15/22] lxd/storage/backend/mock: Changes GetInstanceUsage signature Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/backend_mock.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lxd/storage/backend_mock.go b/lxd/storage/backend_mock.go index 05aa1b9b4f..6770735c8e 100644 --- a/lxd/storage/backend_mock.go +++ b/lxd/storage/backend_mock.go @@ -98,7 +98,7 @@ func (b *mockBackend) BackupInstance(i Instance, targetPath string, optimized bo return nil } -func (b *mockBackend) GetInstanceUsage(i Instance) (uint64, error) { +func (b *mockBackend) GetInstanceUsage(i Instance) (int64, error) { return 0, nil } @@ -178,14 +178,10 @@ func (b *mockBackend) CreateCustomVolumeFromMigration(conn io.ReadWriteCloser, a return nil } -func (b *mockBackend) GetCustomVolumeUsage(vol api.StorageVolume) (uint64, error) { +func (b *mockBackend) GetCustomVolumeUsage(volName string) (int64, error) { return 0, nil } -func (b *mockBackend) SetCustomVolumeQuota(vol api.StorageVolume, quota uint64) error { - return nil -} - func (b *mockBackend) MountCustomVolume(volName string, op *operations.Operation) (bool, error) { return true, nil } From c0aeb63175ca37a9a1938339f3d2c891cf63f4dd Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 31 Oct 2019 16:41:22 +0000 Subject: [PATCH 16/22] lxd/storage/drivers/driver/dir: Implements GetVolumeUsage Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/drivers/driver_dir.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/lxd/storage/drivers/driver_dir.go b/lxd/storage/drivers/driver_dir.go index 34af147f26..bafb1fb06f 100644 --- a/lxd/storage/drivers/driver_dir.go +++ b/lxd/storage/drivers/driver_dir.go @@ -119,6 +119,31 @@ func (d *dir) GetResources() (*api.ResourcesStoragePool, error) { return vfsResources(GetPoolMountPath(d.name)) } +// GetVolumeUsage returns the disk space used by the volume. +func (d *dir) GetVolumeUsage(volType VolumeType, volName string) (int64, error) { + volPath := GetVolumeMountPath(d.name, volType, volName) + ok, err := quota.Supported(volPath) + if err != nil || !ok { + return -1, fmt.Errorf("The backing filesystem doesn't support quotas") + } + + // Get the volume ID for the volume to access quota. + volID, err := d.getVolID(volType, volName) + if err != nil { + return -1, err + } + + projectID := d.quotaProjectID(volID) + + // Get project quota used. + size, err := quota.GetProjectUsage(volPath, projectID) + if err != nil { + return -1, err + } + + return size, nil +} + // ValidateVolume validates the supplied volume config. func (d *dir) ValidateVolume(vol Volume, removeUnknownKeys bool) error { return d.validateVolume(vol, nil, removeUnknownKeys) From 8eba4831a53bec9c23edacf09c23bd62c9866edf Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 31 Oct 2019 16:41:42 +0000 Subject: [PATCH 17/22] lxd/storage/drivers/interface: Adds GetVolumeUsage Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/drivers/interface.go | 1 + 1 file changed, 1 insertion(+) diff --git a/lxd/storage/drivers/interface.go b/lxd/storage/drivers/interface.go index f98b634586..50bab56cb3 100644 --- a/lxd/storage/drivers/interface.go +++ b/lxd/storage/drivers/interface.go @@ -37,6 +37,7 @@ type Driver interface { DeleteVolume(volType VolumeType, volName string, op *operations.Operation) error RenameVolume(volType VolumeType, volName string, newName string, op *operations.Operation) error UpdateVolume(vol Volume, changedConfig map[string]string) error + GetVolumeUsage(volType VolumeType, volName string) (int64, error) // MountVolume mounts a storage volume, returns true if we caused a new mount, false if // already mounted. From f3e2a461d9210c5af086d510a05a1ad3db962d92 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 31 Oct 2019 16:42:01 +0000 Subject: [PATCH 18/22] lxd/storage/interfaces: Changes GetInstanceUsage signature Removes Snapshots from Instance interface for now as causing issues when used from main package. Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/interfaces.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lxd/storage/interfaces.go b/lxd/storage/interfaces.go index 45f5e22b25..49a4ea02ce 100644 --- a/lxd/storage/interfaces.go +++ b/lxd/storage/interfaces.go @@ -19,7 +19,6 @@ type Instance interface { Path() string IsRunning() bool - Snapshots() ([]Instance, error) TemplateApply(trigger string) error } @@ -52,7 +51,7 @@ type Pool interface { RefreshInstance(i Instance, src Instance, snapshots bool, op *operations.Operation) error BackupInstance(i Instance, targetPath string, optimized bool, snapshots bool, op *operations.Operation) error - GetInstanceUsage(i Instance) (uint64, error) + GetInstanceUsage(i Instance) (int64, error) SetInstanceQuota(i Instance, quota uint64) error MountInstance(i Instance) (bool, error) @@ -77,7 +76,7 @@ type Pool interface { UpdateCustomVolume(volName, newDesc string, newConfig map[string]string, op *operations.Operation) error RenameCustomVolume(volName string, newVolName string, op *operations.Operation) error DeleteCustomVolume(volName string, op *operations.Operation) error - GetCustomVolumeUsage(vol api.StorageVolume) (uint64, error) + GetCustomVolumeUsage(volName string) (int64, error) MountCustomVolume(volName string, op *operations.Operation) (bool, error) UnmountCustomVolume(volName string, op *operations.Operation) (bool, error) From 86470aa6a0c4c9f285a337f8882c696a7dccf19f Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 31 Oct 2019 17:54:00 +0000 Subject: [PATCH 19/22] lxd/images: Links imageCreateInPool to new storage package Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/images.go | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/lxd/images.go b/lxd/images.go index 67b95e67b4..77b543cd06 100644 --- a/lxd/images.go +++ b/lxd/images.go @@ -33,6 +33,8 @@ import ( "github.com/lxc/lxd/lxd/operations" "github.com/lxc/lxd/lxd/response" "github.com/lxc/lxd/lxd/state" + storagePools "github.com/lxc/lxd/lxd/storage" + storageDrivers "github.com/lxc/lxd/lxd/storage/drivers" "github.com/lxc/lxd/lxd/task" "github.com/lxc/lxd/lxd/util" "github.com/lxc/lxd/shared" @@ -626,17 +628,31 @@ func imageCreateInPool(d *Daemon, info *api.Image, storagePool string) error { return fmt.Errorf("No storage pool specified") } - // Initialize a new storage interface. - s, err := storagePoolInit(d.State(), storagePool) - if err != nil { - return err - } + // Check if we can load new storage layer for pool driver type. + pool, err := storagePools.GetPoolByName(d.State(), storagePool) + if err != storageDrivers.ErrUnknownDriver { + if err != nil { + return err + } + + err = pool.CreateImage(info.Fingerprint, nil) + if err != nil { + return err + } + } else { + // Initialize a new storage interface. + s, err := storagePoolInit(d.State(), storagePool) + if err != nil { + return err + } + + // Create the storage volume for the image on the requested storage + // pool. + err = s.ImageCreate(info.Fingerprint, nil) + if err != nil { + return err + } - // Create the storage volume for the image on the requested storage - // pool. - err = s.ImageCreate(info.Fingerprint, nil) - if err != nil { - return err } return nil @@ -1084,6 +1100,7 @@ func autoUpdateImage(d *Daemon, op *operations.Operation, id int, info *api.Imag // Update the image on each pool where it currently exists. hash := fingerprint + for _, poolName := range poolNames { newInfo, err := d.ImageDownload(op, source.Server, source.Protocol, source.Certificate, "", source.Alias, info.Type, false, true, poolName, false, project) From ef6bfab7b2be3a4e8ab858f07199f5823d1f7e75 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 31 Oct 2019 17:54:18 +0000 Subject: [PATCH 20/22] lxd/storage/backend/lxd: Implements CreateImage Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/backend_lxd.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go index 1b8d2c0ad5..3a51642a92 100644 --- a/lxd/storage/backend_lxd.go +++ b/lxd/storage/backend_lxd.go @@ -252,7 +252,17 @@ func (b *lxdBackend) UnmountInstanceSnapshot(inst Instance) (bool, error) { return true, ErrNotImplemented } -func (b *lxdBackend) CreateImage(img api.Image, op *operations.Operation) error { +// CreateImage creates an optimized volume of the image if supported by the storage pool driver. +func (b *lxdBackend) CreateImage(fingerprint string, op *operations.Operation) error { + logger := logging.AddContext(b.logger, log.Ctx{"fingerprint": fingerprint}) + logger.Debug("CreateImage started") + defer logger.Debug("CreateImage finished") + + if !b.driver.Info().OptimizedImages { + return nil // Nothing to do for drivers that don't support optimized images volumes. + } + + // TODO volume creation with a filler function to populate volume/snapshot with image. return ErrNotImplemented } From 68b7d0c8b5feefef67c52b85ed49b1453e53e230 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 31 Oct 2019 17:54:38 +0000 Subject: [PATCH 21/22] lxd/storage/backend/mock: Updates CreateImage definition Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/backend_mock.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lxd/storage/backend_mock.go b/lxd/storage/backend_mock.go index 6770735c8e..5cbab80ec3 100644 --- a/lxd/storage/backend_mock.go +++ b/lxd/storage/backend_mock.go @@ -142,7 +142,7 @@ func (b *mockBackend) UnmountInstanceSnapshot(i Instance) (bool, error) { return true, nil } -func (b *mockBackend) CreateImage(img api.Image, op *operations.Operation) error { +func (b *mockBackend) CreateImage(fingerprint string, op *operations.Operation) error { return nil } From f62b64dc3b032ee90b97bcd84accf7378deb512c Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 31 Oct 2019 17:54:56 +0000 Subject: [PATCH 22/22] lxd/storage/interfaces: Updates CreateImage definition Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/interfaces.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lxd/storage/interfaces.go b/lxd/storage/interfaces.go index 49a4ea02ce..d8853c0096 100644 --- a/lxd/storage/interfaces.go +++ b/lxd/storage/interfaces.go @@ -67,7 +67,7 @@ type Pool interface { UnmountInstanceSnapshot(i Instance) (bool, error) // Images. - CreateImage(img api.Image, op *operations.Operation) error + CreateImage(fingerprint string, op *operations.Operation) error DeleteImage(fingerprint string, op *operations.Operation) error // Custom volumes.
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel