The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/6415
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) === - Some function renames to change "container" to "instance". - Add support for instance type to some functions.
From bf38ffa62fc0014da3e03528e4dcfb7e5b5888ae Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 10:56:01 +0000 Subject: [PATCH 01/27] lxd/api/internal: Updates use of renamed functions Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/api_internal.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lxd/api_internal.go b/lxd/api_internal.go index cdf6dbc1b9..392b30f81f 100644 --- a/lxd/api_internal.go +++ b/lxd/api_internal.go @@ -871,7 +871,7 @@ func internalImport(d *Daemon, r *http.Request) response.Response { if containerErr == nil { // Remove the storage volume db entry for the container since // force was specified. - err := d.cluster.ContainerRemove(projectName, req.Name) + err := d.cluster.InstanceRemove(projectName, req.Name) if err != nil { return response.SmartError(err) } @@ -916,7 +916,7 @@ func internalImport(d *Daemon, r *http.Request) response.Response { if err != nil { return response.SmartError(err) } - _, err = containerCreateInternal(d.State(), db.InstanceArgs{ + _, err = instanceCreateInternal(d.State(), db.InstanceArgs{ Project: projectName, Architecture: arch, BaseImage: baseImage, @@ -982,7 +982,7 @@ func internalImport(d *Daemon, r *http.Request) response.Response { } if snapErr == nil { - err := d.cluster.ContainerRemove(projectName, snap.Name) + err := d.cluster.InstanceRemove(projectName, snap.Name) if err != nil { return response.SmartError(err) } @@ -1022,7 +1022,7 @@ func internalImport(d *Daemon, r *http.Request) response.Response { snap.Devices[rootDevName] = rootDev } - _, err = containerCreateInternal(d.State(), db.InstanceArgs{ + _, err = instanceCreateInternal(d.State(), db.InstanceArgs{ Project: projectName, Architecture: arch, BaseImage: baseImage, From 14d712908d862a74bf64775d010869a532772fa2 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 10:58:31 +0000 Subject: [PATCH 02/27] lxd/container: Updates return values of instance create and load functions Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/container.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lxd/container.go b/lxd/container.go index 0fcb2fdea6..d3ecf525ef 100644 --- a/lxd/container.go +++ b/lxd/container.go @@ -255,9 +255,9 @@ type container interface { } // containerCreateAsEmpty creates an empty instance. -func containerCreateAsEmpty(d *Daemon, args db.InstanceArgs) (container, error) { +func containerCreateAsEmpty(d *Daemon, args db.InstanceArgs) (Instance, error) { // Create the container. - c, err := containerCreateInternal(d.State(), args) + c, err := instanceCreateInternal(d.State(), args) if err != nil { return nil, err } @@ -402,9 +402,9 @@ func containerCreateFromBackup(s *state.State, info backup.Info, data io.ReadSee return pool, nil } -func containerCreateEmptySnapshot(s *state.State, args db.InstanceArgs) (container, error) { +func containerCreateEmptySnapshot(s *state.State, args db.InstanceArgs) (Instance, error) { // Create the snapshot - c, err := containerCreateInternal(s, args) + c, err := instanceCreateInternal(s, args) if err != nil { return nil, err } @@ -544,7 +544,7 @@ func containerCreateAsCopy(s *state.State, args db.InstanceArgs, sourceContainer if !refresh { // Create the container. - ct, err = containerCreateInternal(s, args) + ct, err = instanceCreateInternal(s, args) if err != nil { return nil, err } @@ -564,7 +564,7 @@ func containerCreateAsCopy(s *state.State, args db.InstanceArgs, sourceContainer parentStoragePool = parentLocalRootDiskDevice["pool"] } - csList := []*container{} + csList := []*Instance{} var snapshots []Instance if !containerOnly { @@ -632,7 +632,7 @@ func containerCreateAsCopy(s *state.State, args db.InstanceArgs, sourceContainer } // Create the snapshots. - cs, err := containerCreateInternal(s, csArgs) + cs, err := instanceCreateInternal(s, csArgs) if err != nil { if !refresh { ct.Delete() @@ -750,7 +750,7 @@ func containerCreateAsSnapshot(s *state.State, args db.InstanceArgs, sourceInsta } // Create the snapshot - c, err := containerCreateInternal(s, args) + c, err := instanceCreateInternal(s, args) if err != nil { return nil, err } From eeb7dccef05d70fdcbf54c66b0c0b123fbf8ddfd Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 10:59:11 +0000 Subject: [PATCH 03/27] lxc/container: Renames containerCreateFromImage to instanceCreateFromImage Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/container.go | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/lxd/container.go b/lxd/container.go index d3ecf525ef..537d524186 100644 --- a/lxd/container.go +++ b/lxd/container.go @@ -419,8 +419,8 @@ func containerCreateEmptySnapshot(s *state.State, args db.InstanceArgs) (Instanc return c, nil } -// containerCreateFromImage creates an instance from a rootfs image. -func containerCreateFromImage(d *Daemon, args db.InstanceArgs, hash string, op *operations.Operation) (container, error) { +// instanceCreateFromImage creates an instance from a rootfs image. +func instanceCreateFromImage(d *Daemon, args db.InstanceArgs, hash string, op *operations.Operation) (Instance, error) { s := d.State() // Get the image properties. @@ -475,59 +475,66 @@ func containerCreateFromImage(d *Daemon, args db.InstanceArgs, hash string, op * // Set the BaseImage field (regardless of previous value). args.BaseImage = hash - // Create the container - c, err := containerCreateInternal(s, args) + // Create the instance. + inst, err := instanceCreateInternal(s, args) if err != nil { - return nil, errors.Wrap(err, "Create container") + return nil, errors.Wrap(err, "Create instance") } + revert := true + defer func() { + if !revert { + return + } + + inst.Delete() + }() + err = s.Cluster.ImageLastAccessUpdate(hash, time.Now().UTC()) if err != nil { - c.Delete() return nil, fmt.Errorf("Error updating image last use date: %s", err) } // Check if we can load new storage layer for pool driver type. - pool, err := storagePools.GetPoolByInstance(d.State(), c) + pool, err := storagePools.GetPoolByInstance(d.State(), inst) if err != storageDrivers.ErrUnknownDriver && err != storageDrivers.ErrNotImplemented { if err != nil { return nil, errors.Wrap(err, "Load instance storage pool") } - err = pool.CreateInstanceFromImage(c, hash, op) + err = pool.CreateInstanceFromImage(inst, hash, op) if err != nil { - c.Delete() return nil, errors.Wrap(err, "Create instance from image") } - } else if c.Type() == instancetype.Container { + } else if inst.Type() == instancetype.Container { metadata := make(map[string]interface{}) var tracker *ioprogress.ProgressTracker if op != nil { tracker = &ioprogress.ProgressTracker{ Handler: func(percent, speed int64) { + // tomp TODO should the container reference here be removed? shared.SetProgressMetadata(metadata, "create_container_from_image_unpack", "Unpack", percent, 0, speed) op.UpdateMetadata(metadata) }} } // Now create the storage from an image. - err = c.Storage().ContainerCreateFromImage(c, hash, tracker) + err = inst.Storage().ContainerCreateFromImage(inst, hash, tracker) if err != nil { - c.Delete() - return nil, errors.Wrap(err, "Create container from image") + return nil, errors.Wrap(err, "Create instance from image") } } else { return nil, fmt.Errorf("Instance type not supported") } // Apply any post-storage configuration. - err = containerConfigureInternal(d.State(), c) + err = containerConfigureInternal(d.State(), inst) if err != nil { - c.Delete() - return nil, errors.Wrap(err, "Configure container") + return nil, errors.Wrap(err, "Configure instance") } - return c, nil + revert = false + return inst, nil } func containerCreateAsCopy(s *state.State, args db.InstanceArgs, sourceContainer Instance, containerOnly bool, refresh bool) (Instance, error) { From 3fc7315e8d4390a79765b9bb733de4c80d4dc237 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 10:59:50 +0000 Subject: [PATCH 04/27] lxd/container: Renames containerCreateInternal to instanceCreateInternal Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/container.go | 71 +++++++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 28 deletions(-) diff --git a/lxd/container.go b/lxd/container.go index 537d524186..bd7d848107 100644 --- a/lxd/container.go +++ b/lxd/container.go @@ -799,8 +799,8 @@ func containerCreateAsSnapshot(s *state.State, args db.InstanceArgs, sourceInsta return c, nil } -func containerCreateInternal(s *state.State, args db.InstanceArgs) (container, error) { - // Set default values +func instanceCreateInternal(s *state.State, args db.InstanceArgs) (Instance, error) { + // Set default values. if args.Project == "" { args.Project = "default" } @@ -832,11 +832,11 @@ func containerCreateInternal(s *state.State, args db.InstanceArgs) (container, e return nil, err } - // Unset expiry date since containers don't expire + // Unset expiry date since containers don't expire. args.ExpiryDate = time.Time{} } - // Validate container config + // Validate container config. err := containerValidConfig(s.OS, args.Config, false, false) if err != nil { return nil, err @@ -848,7 +848,7 @@ func containerCreateInternal(s *state.State, args db.InstanceArgs) (container, e return nil, errors.Wrap(err, "Invalid devices") } - // Validate architecture + // Validate architecture. _, err = osarch.ArchitectureName(args.Architecture) if err != nil { return nil, err @@ -858,7 +858,7 @@ func containerCreateInternal(s *state.State, args db.InstanceArgs) (container, e return nil, fmt.Errorf("Requested architecture isn't supported by this host") } - // Validate profiles + // Validate profiles. profiles, err := s.Cluster.Profiles(args.Project) if err != nil { return nil, err @@ -885,15 +885,15 @@ func containerCreateInternal(s *state.State, args db.InstanceArgs) (container, e args.LastUsedDate = time.Unix(0, 0).UTC() } - var container db.Instance + var dbInst db.Instance + err = s.Cluster.Transaction(func(tx *db.ClusterTx) error { node, err := tx.NodeName() if err != nil { return err } - // TODO: this check should probably be performed by the db - // package itself. + // TODO: this check should probably be performed by the db package itself. exists, err := tx.ProjectExists(args.Project) if err != nil { return errors.Wrapf(err, "Check if project %q exists", args.Project) @@ -932,13 +932,13 @@ func containerCreateInternal(s *state.State, args db.InstanceArgs) (container, e return errors.Wrap(err, "Fetch created snapshot from the database") } - container = db.InstanceSnapshotToInstance(instance, s) + dbInst = db.InstanceSnapshotToInstance(instance, s) return nil } - // Create the container entry - container = db.Instance{ + // Create the instance entry. + dbInst = db.Instance{ Project: args.Project, Name: args.Name, Node: node, @@ -956,28 +956,28 @@ func containerCreateInternal(s *state.State, args db.InstanceArgs) (container, e ExpiryDate: args.ExpiryDate, } - _, err = tx.InstanceCreate(container) + _, err = tx.InstanceCreate(dbInst) if err != nil { - return errors.Wrap(err, "Add container info to the database") + return errors.Wrap(err, "Add instance info to the database") } - // Read back the container, to get ID and creation time. - c, err := tx.InstanceGet(args.Project, args.Name) + // Read back the instance, to get ID and creation time. + dbRow, err := tx.InstanceGet(args.Project, args.Name) if err != nil { - return errors.Wrap(err, "Fetch created container from the database") + return errors.Wrap(err, "Fetch created instance from the database") } - container = *c + dbInst = *dbRow - if container.ID < 1 { - return errors.Wrapf(err, "Unexpected container database ID %d", container.ID) + if dbInst.ID < 1 { + return errors.Wrapf(err, "Unexpected instance database ID %d", dbInst.ID) } return nil }) if err != nil { if err == db.ErrAlreadyDefined { - thing := "Container" + thing := "Instance" if shared.IsSnapshot(args.Name) { thing = "Snapshot" } @@ -986,19 +986,34 @@ func containerCreateInternal(s *state.State, args db.InstanceArgs) (container, e return nil, err } - // Wipe any existing log for this container name + revert := true + defer func() { + if !revert { + return + } + + s.Cluster.InstanceRemove(dbInst.Project, dbInst.Name) + }() + + // Wipe any existing log for this instance name. os.RemoveAll(shared.LogPath(args.Name)) - args = db.ContainerToArgs(&container) + args = db.ContainerToArgs(&dbInst) + + var inst Instance + + if args.Type == instancetype.Container { + inst, err = containerLXCCreate(s, args) + } else { + return nil, fmt.Errorf("Instance type invalid") + } - // Setup the container struct and finish creation (storage and idmap) - c, err := containerLXCCreate(s, args) if err != nil { - s.Cluster.ContainerRemove(args.Project, args.Name) - return nil, errors.Wrap(err, "Create LXC container") + return nil, errors.Wrap(err, "Create instance") } - return c, nil + revert = false + return inst, nil } func containerConfigureInternal(state *state.State, c Instance) error { From be479c678960be804016843d6eb1f41d5eb4d7ad Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 11:00:39 +0000 Subject: [PATCH 05/27] lxd/container/lxc: Updates use of renamed c.state.Cluster.InstanceRemove Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/container_lxc.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go index b52b732806..2071b242bb 100644 --- a/lxd/container_lxc.go +++ b/lxd/container_lxc.go @@ -3614,7 +3614,7 @@ func (c *containerLXC) Delete() error { } // Remove the database record of the instance or snapshot instance. - if err := c.state.Cluster.ContainerRemove(c.Project(), c.Name()); err != nil { + if err := c.state.Cluster.InstanceRemove(c.Project(), c.Name()); err != nil { logger.Error("Failed deleting instance entry", log.Ctx{"project": c.Project(), "instance": c.Name(), "err": err}) return err } @@ -3689,7 +3689,7 @@ func (c *containerLXC) Delete() error { } // Remove the database record - if err := c.state.Cluster.ContainerRemove(c.project, c.Name()); err != nil { + if err := c.state.Cluster.InstanceRemove(c.project, c.Name()); err != nil { logger.Error("Failed deleting container entry", log.Ctx{"name": c.Name(), "err": err}) return err } From 58ad929d5189b1fe0455220f23bf67c063158f33 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 11:01:04 +0000 Subject: [PATCH 06/27] lxd/containers/post: Adds VM support to createFromImage Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/containers_post.go | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/lxd/containers_post.go b/lxd/containers_post.go index e784bb3563..d501b67d9a 100644 --- a/lxd/containers_post.go +++ b/lxd/containers_post.go @@ -118,9 +118,16 @@ func createFromImage(d *Daemon, project string, req *api.InstancesPost) response if err != nil { return err } + + // Detect image type based on instance type requested. + imgType := "container" + if req.Type == "virtual-machine" { + imgType = "virtual-machine" + } + info, err = d.ImageDownload( op, req.Source.Server, req.Source.Protocol, req.Source.Certificate, - req.Source.Secret, hash, "container", true, autoUpdate, "", true, project) + req.Source.Secret, hash, imgType, true, autoUpdate, "", true, project) if err != nil { return err } @@ -136,11 +143,12 @@ func createFromImage(d *Daemon, project string, req *api.InstancesPost) response return err } - _, err = containerCreateFromImage(d, args, info.Fingerprint, op) + _, err = instanceCreateFromImage(d, args, info.Fingerprint, op) return err } resources := map[string][]string{} + // tomp TODO should this be renamed/added to? resources["containers"] = []string{req.Name} op, err := operations.OperationCreate(d.State(), project, operations.OperationClassTask, db.OperationContainerCreate, resources, nil, run, nil, nil) @@ -198,7 +206,7 @@ func createFromMigration(d *Daemon, project string, req *api.InstancesPost) resp return response.NotImplemented(fmt.Errorf("Mode '%s' not implemented", req.Source.Mode)) } - var c container + var c Instance // Parse the architecture name architecture, err := osarch.ArchitectureId(req.Architecture) @@ -293,7 +301,7 @@ func createFromMigration(d *Daemon, project string, req *api.InstancesPost) resp return response.BadRequest(fmt.Errorf("Instance type not container")) } - c = inst.(container) + c = inst } if !req.Source.Refresh { @@ -340,7 +348,7 @@ func createFromMigration(d *Daemon, project string, req *api.InstancesPost) resp } if ps.MigrationType() == migration.MigrationFSType_RSYNC { - c, err = containerCreateFromImage(d, args, req.Source.BaseImage, nil) + c, err = instanceCreateFromImage(d, args, req.Source.BaseImage, nil) if err != nil { return response.InternalError(err) } From da249124590ba32ec28611124b8ca129442069ac Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 11:01:19 +0000 Subject: [PATCH 07/27] lxd/db/containers: Renames ContainerRemove to InstanceRemove Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/db/containers.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lxd/db/containers.go b/lxd/db/containers.go index b2b4cf9d3d..58ff234f32 100644 --- a/lxd/db/containers.go +++ b/lxd/db/containers.go @@ -620,8 +620,8 @@ func (c *ClusterTx) configUpdate(id int, values map[string]string, insertSQL, de return nil } -// ContainerRemove removes the container with the given name from the database. -func (c *Cluster) ContainerRemove(project, name string) error { +// InstanceRemove removes the instance with the given name from the database. +func (c *Cluster) InstanceRemove(project, name string) error { if strings.Contains(name, shared.SnapshotDelimiter) { parts := strings.SplitN(name, shared.SnapshotDelimiter, 2) return c.Transaction(func(tx *ClusterTx) error { From a6882c6c579b3d431af91b4ff6a45c18e0c3b59e Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 11:04:06 +0000 Subject: [PATCH 08/27] lxd/container: Renames containerCreateAsEmpty to containerCreateAsEmpty - Adds revert for safety Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/container.go | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/lxd/container.go b/lxd/container.go index bd7d848107..f25f232e12 100644 --- a/lxd/container.go +++ b/lxd/container.go @@ -254,31 +254,38 @@ type container interface { NextIdmap() (*idmap.IdmapSet, error) } -// containerCreateAsEmpty creates an empty instance. -func containerCreateAsEmpty(d *Daemon, args db.InstanceArgs) (Instance, error) { - // Create the container. - c, err := instanceCreateInternal(d.State(), args) +// instanceCreateAsEmpty creates an empty instance. +func instanceCreateAsEmpty(d *Daemon, args db.InstanceArgs) (Instance, error) { + // Create the instance record. + inst, err := instanceCreateInternal(d.State(), args) if err != nil { return nil, err } + revert := true + defer func() { + if !revert { + return + } + + inst.Delete() + }() + // Check if we can load new storage layer for pool driver type. - pool, err := storagePools.GetPoolByInstance(d.State(), c) + pool, err := storagePools.GetPoolByInstance(d.State(), inst) if err != storageDrivers.ErrUnknownDriver && err != storageDrivers.ErrNotImplemented { if err != nil { return nil, errors.Wrap(err, "Load instance storage pool") } - err = pool.CreateInstance(c, nil) + err = pool.CreateInstance(inst, nil) if err != nil { - c.Delete() return nil, errors.Wrap(err, "Create instance") } - } else if c.Type() == instancetype.Container { + } else if inst.Type() == instancetype.Container { // Now create the empty storage. - err = c.Storage().ContainerCreate(c) + err = inst.Storage().ContainerCreate(inst) if err != nil { - c.Delete() return nil, err } } else { @@ -286,13 +293,13 @@ func containerCreateAsEmpty(d *Daemon, args db.InstanceArgs) (Instance, error) { } // Apply any post-storage configuration. - err = containerConfigureInternal(d.State(), c) + err = containerConfigureInternal(d.State(), inst) if err != nil { - c.Delete() return nil, err } - return c, nil + revert = false + return inst, nil } func containerCreateFromBackup(s *state.State, info backup.Info, data io.ReadSeeker, From 2ad54c4f2bbd19253027be680eabd0f20be4b5ca Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 11:09:46 +0000 Subject: [PATCH 09/27] lxd/containers/post: Updates use of instanceCreateAsEmpty Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/containers_post.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lxd/containers_post.go b/lxd/containers_post.go index d501b67d9a..eced2a1c89 100644 --- a/lxd/containers_post.go +++ b/lxd/containers_post.go @@ -185,7 +185,7 @@ func createFromNone(d *Daemon, project string, req *api.InstancesPost) response. } run := func(op *operations.Operation) error { - _, err := containerCreateAsEmpty(d, args) + _, err := instanceCreateAsEmpty(d, args) return err } @@ -320,7 +320,7 @@ func createFromMigration(d *Daemon, project string, req *api.InstancesPost) resp */ _, _, err = d.cluster.ImageGet(args.Project, req.Source.BaseImage, false, true) if err != nil { - c, err = containerCreateAsEmpty(d, args) + c, err = instanceCreateAsEmpty(d, args) if err != nil { return response.InternalError(err) } @@ -353,7 +353,7 @@ func createFromMigration(d *Daemon, project string, req *api.InstancesPost) resp return response.InternalError(err) } } else { - c, err = containerCreateAsEmpty(d, args) + c, err = instanceCreateAsEmpty(d, args) if err != nil { return response.InternalError(err) } From 1901d15737fbb80e9a122f77451120fee05716dc Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 11:36:17 +0000 Subject: [PATCH 10/27] lxd/storage/backend/lxd: Pass correct content type to storage drivers for VMs Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/backend_lxd.go | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go index f246a6352a..f05cc06bb6 100644 --- a/lxd/storage/backend_lxd.go +++ b/lxd/storage/backend_lxd.go @@ -299,7 +299,12 @@ func (b *lxdBackend) CreateInstance(inst Instance, op *operations.Operation) err b.DeleteInstance(inst, op) }() - vol := b.newVolume(volType, drivers.ContentTypeFS, project.Prefix(inst.Project(), inst.Name()), nil) + contentType := drivers.ContentTypeFS + if inst.Type() == instancetype.VM { + contentType = drivers.ContentTypeBlock + } + + vol := b.newVolume(volType, contentType, project.Prefix(inst.Project(), inst.Name()), nil) err = b.driver.CreateVolume(vol, nil, op) if err != nil { return err @@ -366,7 +371,12 @@ func (b *lxdBackend) CreateInstanceFromImage(inst Instance, fingerprint string, b.DeleteInstance(inst, op) }() - vol := b.newVolume(volType, drivers.ContentTypeFS, project.Prefix(inst.Project(), inst.Name()), nil) + contentType := drivers.ContentTypeFS + if inst.Type() == instancetype.VM { + contentType = drivers.ContentTypeBlock + } + + vol := b.newVolume(volType, contentType, project.Prefix(inst.Project(), inst.Name()), nil) // If the driver doesn't support optimized image volumes then create a new empty volume and // populate it with the contents of the image archive. @@ -384,7 +394,7 @@ func (b *lxdBackend) CreateInstanceFromImage(inst Instance, fingerprint string, return err } - imgVol := b.newVolume(drivers.VolumeTypeImage, drivers.ContentTypeFS, fingerprint, nil) + imgVol := b.newVolume(drivers.VolumeTypeImage, contentType, fingerprint, nil) err = b.driver.CreateVolumeFromCopy(vol, imgVol, false, op) if err != nil { return err @@ -839,9 +849,20 @@ func (b *lxdBackend) EnsureImage(fingerprint string, op *operations.Operation) e return nil } + // Load image info from database. + _, image, err := b.state.Cluster.ImageGetFromAnyProject(fingerprint) + if err != nil { + return err + } + + contentType := drivers.ContentTypeFS + if api.InstanceType(image.Type) == api.InstanceTypeVM { + contentType = drivers.ContentTypeBlock + } + // Create the new image volume. - vol := b.newVolume(drivers.VolumeTypeImage, drivers.ContentTypeFS, fingerprint, nil) - err := b.driver.CreateVolume(vol, b.imageFiller(fingerprint, op), op) + vol := b.newVolume(drivers.VolumeTypeImage, contentType, fingerprint, nil) + err = b.driver.CreateVolume(vol, b.imageFiller(fingerprint, op), op) if err != nil { return err } From ebfc5f673d3abcd1dcfb6ae6acd9d541937f4af9 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 11:57:18 +0000 Subject: [PATCH 11/27] lxd/storage/drivers/utils: Unexports deleteParentSnapshotDirIfEmpty As not used outside of package. Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/drivers/utils.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lxd/storage/drivers/utils.go b/lxd/storage/drivers/utils.go index ffc09539ed..655c2ac58a 100644 --- a/lxd/storage/drivers/utils.go +++ b/lxd/storage/drivers/utils.go @@ -192,9 +192,9 @@ func GetSnapshotVolumeName(parentName, snapshotName string) string { return fmt.Sprintf("%s%s%s", parentName, shared.SnapshotDelimiter, snapshotName) } -// DeleteParentSnapshotDirIfEmpty removes the parent snapshot directory if it is empty. +// deleteParentSnapshotDirIfEmpty removes the parent snapshot directory if it is empty. // It accepts the pool name, volume type and parent volume name. -func DeleteParentSnapshotDirIfEmpty(poolName string, volType VolumeType, volName string) error { +func deleteParentSnapshotDirIfEmpty(poolName string, volType VolumeType, volName string) error { snapshotsPath, err := GetVolumeSnapshotDir(poolName, volType, volName) if err != nil { return err From 5d70b6b162775ef4e1a9de2ab58231e0380d0add Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 11:57:50 +0000 Subject: [PATCH 12/27] lxd/storage/drivers/driver/dir: Updates use of deleteParentSnapshotDirIfEmpty Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/drivers/driver_dir.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lxd/storage/drivers/driver_dir.go b/lxd/storage/drivers/driver_dir.go index 58592d8b36..fdb9507217 100644 --- a/lxd/storage/drivers/driver_dir.go +++ b/lxd/storage/drivers/driver_dir.go @@ -639,7 +639,7 @@ func (d *dir) DeleteVolume(volType VolumeType, volName string, op *operations.Op // Although the volume snapshot directory should already be removed, lets remove it here // to just in case the top-level directory is left. - err = DeleteParentSnapshotDirIfEmpty(d.name, volType, volName) + err = deleteParentSnapshotDirIfEmpty(d.name, volType, volName) if err != nil { return err } @@ -834,7 +834,7 @@ func (d *dir) DeleteVolumeSnapshot(volType VolumeType, volName string, snapshotN } // Remove the parent snapshot directory if this is the last snapshot being removed. - err = DeleteParentSnapshotDirIfEmpty(d.name, volType, volName) + err = deleteParentSnapshotDirIfEmpty(d.name, volType, volName) if err != nil { return err } From 5f3ecea76bc2a302087ac973edd5b2e86cb3b060 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 16:54:27 +0000 Subject: [PATCH 13/27] lxd/container/lxc: Updating DB usage to be instance type agnostic Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/container_lxc.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go index 2071b242bb..a6e5a13c96 100644 --- a/lxd/container_lxc.go +++ b/lxd/container_lxc.go @@ -3544,7 +3544,7 @@ func (c *containerLXC) Delete() error { } // Get the storage pool name of the instance. - poolName, err := c.state.Cluster.ContainerPool(c.Project(), c.Name()) + poolName, err := c.state.Cluster.InstancePool(c.Project(), c.Name()) if err != nil { return err } @@ -4055,7 +4055,12 @@ func writeBackupFile(c Instance) error { return err } - _, volume, err := s.Cluster.StoragePoolNodeVolumeGetTypeByProject(c.Project(), c.Name(), storagePoolVolumeTypeContainer, poolID) + dbType := db.StoragePoolVolumeTypeContainer + if c.Type() == instancetype.VM { + dbType = db.StoragePoolVolumeTypeVM + } + + _, volume, err := s.Cluster.StoragePoolNodeVolumeGetTypeByProject(c.Project(), c.Name(), dbType, poolID) if err != nil { return err } @@ -6897,7 +6902,7 @@ func (c *containerLXC) StatePath() string { } func (c *containerLXC) StoragePool() (string, error) { - poolName, err := c.state.Cluster.ContainerPool(c.Project(), c.Name()) + poolName, err := c.state.Cluster.InstancePool(c.Project(), c.Name()) if err != nil { return "", err } From 1c8ad86c88eb129ac5796561d4563e61c10faf7e Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 16:54:59 +0000 Subject: [PATCH 14/27] lxd/container/post: Updates usage of InstancePool Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/container_post.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lxd/container_post.go b/lxd/container_post.go index d9027961ce..3371b332b9 100644 --- a/lxd/container_post.go +++ b/lxd/container_post.go @@ -178,7 +178,7 @@ func containerPost(d *Daemon, r *http.Request) response.Response { } // Check if we are migrating a ceph-based container. - poolName, err := d.cluster.ContainerPool(project, name) + poolName, err := d.cluster.InstancePool(project, name) if err != nil { err = errors.Wrap(err, "Failed to fetch container's pool name") return response.SmartError(err) @@ -449,7 +449,7 @@ func containerPostClusteringMigrateWithCeph(d *Daemon, c Instance, project, oldN return errors.Wrapf( err, "Move container %s to %s with new name %s", oldName, newNode, newName) } - poolName, err = tx.ContainerPool(project, newName) + poolName, err = tx.InstancePool(project, newName) if err != nil { return errors.Wrapf(err, "Get the container's storage pool name for %s", newName) } From 4f1254a4b996e4543939852487c383116e81b1fc Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 17:19:55 +0000 Subject: [PATCH 15/27] lxd/container/test: Updates instanceCreateInternal usage Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/container_test.go | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/lxd/container_test.go b/lxd/container_test.go index 4d49318e56..92b7711e9b 100644 --- a/lxd/container_test.go +++ b/lxd/container_test.go @@ -26,7 +26,7 @@ func (suite *containerTestSuite) TestContainer_ProfilesDefault() { Name: "testFoo", } - c, err := containerCreateInternal(suite.d.State(), args) + c, err := instanceCreateInternal(suite.d.State(), args) suite.Req.Nil(err) defer c.Delete() @@ -34,7 +34,7 @@ func (suite *containerTestSuite) TestContainer_ProfilesDefault() { suite.Len( profiles, 1, - "No default profile created on containerCreateInternal.") + "No default profile created on instanceCreateInternal.") suite.Equal( "default", @@ -69,7 +69,7 @@ func (suite *containerTestSuite) TestContainer_ProfilesMulti() { Name: "testFoo", } - c, err := containerCreateInternal(suite.d.State(), args) + c, err := instanceCreateInternal(suite.d.State(), args) suite.Req.Nil(err) defer c.Delete() @@ -77,7 +77,7 @@ func (suite *containerTestSuite) TestContainer_ProfilesMulti() { suite.Len( profiles, 2, - "Didn't get both profiles in containerCreateInternal.") + "Didn't get both profiles in instanceCreateInternal.") suite.True( c.IsPrivileged(), @@ -97,7 +97,7 @@ func (suite *containerTestSuite) TestContainer_ProfilesOverwriteDefaultNic() { Name: "testFoo", } - c, err := containerCreateInternal(suite.d.State(), args) + c, err := instanceCreateInternal(suite.d.State(), args) suite.Req.Nil(err) suite.True(c.IsPrivileged(), "This container should be privileged.") @@ -128,7 +128,7 @@ func (suite *containerTestSuite) TestContainer_LoadFromDB() { } // Create the container - c, err := containerCreateInternal(suite.d.State(), args) + c, err := instanceCreateInternal(suite.d.State(), args) suite.Req.Nil(err) defer c.Delete() @@ -159,7 +159,7 @@ func (suite *containerTestSuite) TestContainer_Path_Regular() { Name: "testFoo", } - c, err := containerCreateInternal(suite.d.State(), args) + c, err := instanceCreateInternal(suite.d.State(), args) suite.Req.Nil(err) defer c.Delete() @@ -175,7 +175,7 @@ func (suite *containerTestSuite) TestContainer_LogPath() { Name: "testFoo", } - c, err := containerCreateInternal(suite.d.State(), args) + c, err := instanceCreateInternal(suite.d.State(), args) suite.Req.Nil(err) defer c.Delete() @@ -190,7 +190,7 @@ func (suite *containerTestSuite) TestContainer_IsPrivileged_Privileged() { Name: "testFoo", } - c, err := containerCreateInternal(suite.d.State(), args) + c, err := instanceCreateInternal(suite.d.State(), args) suite.Req.Nil(err) suite.Req.True(c.IsPrivileged(), "This container should be privileged.") @@ -205,7 +205,7 @@ func (suite *containerTestSuite) TestContainer_IsPrivileged_Unprivileged() { Name: "testFoo", } - c, err := containerCreateInternal(suite.d.State(), args) + c, err := instanceCreateInternal(suite.d.State(), args) suite.Req.Nil(err) suite.Req.False(c.IsPrivileged(), "This container should be unprivileged.") @@ -219,7 +219,7 @@ func (suite *containerTestSuite) TestContainer_Rename() { Name: "testFoo", } - c, err := containerCreateInternal(suite.d.State(), args) + c, err := instanceCreateInternal(suite.d.State(), args) suite.Req.Nil(err) defer c.Delete() @@ -228,7 +228,7 @@ func (suite *containerTestSuite) TestContainer_Rename() { } func (suite *containerTestSuite) TestContainer_findIdmap_isolated() { - c1, err := containerCreateInternal(suite.d.State(), db.InstanceArgs{ + c1, err := instanceCreateInternal(suite.d.State(), db.InstanceArgs{ Type: instancetype.Container, Name: "isol-1", Config: map[string]string{ @@ -238,7 +238,7 @@ func (suite *containerTestSuite) TestContainer_findIdmap_isolated() { suite.Req.Nil(err) defer c1.Delete() - c2, err := containerCreateInternal(suite.d.State(), db.InstanceArgs{ + c2, err := instanceCreateInternal(suite.d.State(), db.InstanceArgs{ Type: instancetype.Container, Name: "isol-2", Config: map[string]string{ @@ -269,7 +269,7 @@ func (suite *containerTestSuite) TestContainer_findIdmap_isolated() { } func (suite *containerTestSuite) TestContainer_findIdmap_mixed() { - c1, err := containerCreateInternal(suite.d.State(), db.InstanceArgs{ + c1, err := instanceCreateInternal(suite.d.State(), db.InstanceArgs{ Type: instancetype.Container, Name: "isol-1", Config: map[string]string{ @@ -279,7 +279,7 @@ func (suite *containerTestSuite) TestContainer_findIdmap_mixed() { suite.Req.Nil(err) defer c1.Delete() - c2, err := containerCreateInternal(suite.d.State(), db.InstanceArgs{ + c2, err := instanceCreateInternal(suite.d.State(), db.InstanceArgs{ Type: instancetype.Container, Name: "isol-2", Config: map[string]string{ @@ -310,7 +310,7 @@ func (suite *containerTestSuite) TestContainer_findIdmap_mixed() { } func (suite *containerTestSuite) TestContainer_findIdmap_raw() { - c1, err := containerCreateInternal(suite.d.State(), db.InstanceArgs{ + c1, err := instanceCreateInternal(suite.d.State(), db.InstanceArgs{ Type: instancetype.Container, Name: "isol-1", Config: map[string]string{ @@ -349,7 +349,7 @@ func (suite *containerTestSuite) TestContainer_findIdmap_maxed() { maps := []*idmap.IdmapSet{} for i := 0; i < 7; i++ { - c, err := containerCreateInternal(suite.d.State(), db.InstanceArgs{ + c, err := instanceCreateInternal(suite.d.State(), db.InstanceArgs{ Type: instancetype.Container, Name: fmt.Sprintf("isol-%d", i), Config: map[string]string{ From dbead628dead023e34b038b1d0d8a755dbcd6623 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 18:32:22 +0000 Subject: [PATCH 16/27] lxd/api/internal: InstancePath usage Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/api_internal.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lxd/api_internal.go b/lxd/api_internal.go index 392b30f81f..ff0392ac18 100644 --- a/lxd/api_internal.go +++ b/lxd/api_internal.go @@ -698,7 +698,7 @@ func internalImport(d *Daemon, r *http.Request) response.Response { onDiskPoolName = poolName } snapName := fmt.Sprintf("%s/%s", req.Name, od) - snapPath := driver.ContainerPath(snapName, true) + snapPath := driver.InstancePath(instancetype.Container, projectName, snapName, true) err = lvmContainerDeleteInternal(projectName, poolName, req.Name, true, onDiskPoolName, snapPath) case "ceph": @@ -936,7 +936,7 @@ func internalImport(d *Daemon, r *http.Request) response.Response { return response.SmartError(err) } - containerPath := driver.ContainerPath(project.Prefix(projectName, req.Name), false) + containerPath := driver.InstancePath(instancetype.Container, projectName, req.Name, false) isPrivileged := false if backup.Container.Config["security.privileged"] == "" { isPrivileged = true From 86ed197b6158db87975fa555efc754202759ab66 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 18:33:02 +0000 Subject: [PATCH 17/27] lxd/container/lxc: InstancePath usage Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/container_lxc.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go index a6e5a13c96..193fc6f4e5 100644 --- a/lxd/container_lxc.go +++ b/lxd/container_lxc.go @@ -6854,8 +6854,7 @@ func (c *containerLXC) State() string { // Various container paths func (c *containerLXC) Path() string { - name := project.Prefix(c.Project(), c.Name()) - return storagePools.ContainerPath(name, c.IsSnapshot()) + return storagePools.InstancePath(c.Type(), c.Project(), c.Name(), c.IsSnapshot()) } func (c *containerLXC) DevicesPath() string { From d82f602da78d3a5aec4a8e8e9e4cd3c723a4502b Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 18:33:22 +0000 Subject: [PATCH 18/27] lxd/storage/backend/lxd: InstancePath usage Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/backend_lxd.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go index f05cc06bb6..12212d8211 100644 --- a/lxd/storage/backend_lxd.go +++ b/lxd/storage/backend_lxd.go @@ -178,8 +178,7 @@ func (b *lxdBackend) Unmount() (bool, error) { // 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 { - volStorageName := project.Prefix(projectName, instanceName) - symlinkPath := ContainerPath(volStorageName, false) + symlinkPath := InstancePath(instanceType, projectName, instanceName, false) // Remove any old symlinks left over by previous bugs that may point to a different pool. if shared.PathExists(symlinkPath) { @@ -200,8 +199,7 @@ func (b *lxdBackend) ensureInstanceSymlink(instanceType instancetype.Type, proje // removeInstanceSymlink removes a symlink in the instance directory to the instance's mount path. func (b *lxdBackend) removeInstanceSymlink(instanceType instancetype.Type, projectName, instanceName string) error { - volStorageName := project.Prefix(projectName, instanceName) - symlinkPath := ContainerPath(volStorageName, false) + symlinkPath := InstancePath(instanceType, projectName, instanceName, false) if shared.PathExists(symlinkPath) { err := os.Remove(symlinkPath) @@ -223,7 +221,7 @@ func (b *lxdBackend) ensureInstanceSnapshotSymlink(instanceType instancetype.Typ } parentName, _, _ := shared.ContainerGetParentAndSnapshotName(instanceName) - snapshotSymlink := shared.VarPath("snapshots", project.Prefix(projectName, parentName)) + snapshotSymlink := InstancePath(instanceType, projectName, parentName, true) volStorageName := project.Prefix(projectName, parentName) snapshotTargetPath, err := drivers.GetVolumeSnapshotDir(b.name, volType, volStorageName) @@ -259,7 +257,7 @@ func (b *lxdBackend) removeInstanceSnapshotSymlinkIfUnused(instanceType instance } parentName, _, _ := shared.ContainerGetParentAndSnapshotName(instanceName) - snapshotSymlink := shared.VarPath("snapshots", project.Prefix(projectName, parentName)) + snapshotSymlink := InstancePath(instanceType, projectName, parentName, true) volStorageName := project.Prefix(projectName, parentName) snapshotTargetPath, err := drivers.GetVolumeSnapshotDir(b.name, volType, volStorageName) From d9d9df7a3334378849467201e06af6d0278c7cdf Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 18:33:58 +0000 Subject: [PATCH 19/27] lxd/storage/storage: Renames ContainerPath to InstancePath - Ads VM support Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/storage.go | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/lxd/storage/storage.go b/lxd/storage/storage.go index 4ec18a70e3..a30471982b 100644 --- a/lxd/storage/storage.go +++ b/lxd/storage/storage.go @@ -3,17 +3,27 @@ package storage import ( "os" + "github.com/lxc/lxd/lxd/instance/instancetype" "github.com/lxc/lxd/lxd/project" "github.com/lxc/lxd/shared" ) -// ContainerPath returns the directory of a container or snapshot. -func ContainerPath(name string, isSnapshot bool) string { +// InstancePath returns the directory of an instance or snapshot. +func InstancePath(instanceType instancetype.Type, projectName, instanceName string, isSnapshot bool) string { + fullName := project.Prefix(projectName, instanceName) + if instanceType == instancetype.VM { + if isSnapshot { + return shared.VarPath("virtual-machines-snapshots", fullName) + } + + return shared.VarPath("virtual-machines", fullName) + } + if isSnapshot { - return shared.VarPath("snapshots", name) + return shared.VarPath("snapshots", fullName) } - return shared.VarPath("containers", name) + return shared.VarPath("containers", fullName) } // GetStoragePoolMountPoint returns the mountpoint of the given pool. From 3d9903cf3732847ca46f83e38682481d313c9615 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 18:34:19 +0000 Subject: [PATCH 20/27] lxd/storage/dir: InstancePath usage Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage_dir.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lxd/storage_dir.go b/lxd/storage_dir.go index 15044043d2..846077dda5 100644 --- a/lxd/storage_dir.go +++ b/lxd/storage_dir.go @@ -12,6 +12,7 @@ import ( "golang.org/x/sys/unix" "github.com/lxc/lxd/lxd/backup" + "github.com/lxc/lxd/lxd/instance/instancetype" "github.com/lxc/lxd/lxd/migration" "github.com/lxc/lxd/lxd/operations" "github.com/lxc/lxd/lxd/project" @@ -1198,7 +1199,7 @@ func (s *storageDir) ContainerBackupLoad(info backup.Info, data io.ReadSeeker, t // Create mountpoints containerMntPoint := driver.GetContainerMountPoint(info.Project, s.pool.Name, info.Name) - err = driver.CreateContainerMountpoint(containerMntPoint, driver.ContainerPath(project.Prefix(info.Project, info.Name), false), info.Privileged) + err = driver.CreateContainerMountpoint(containerMntPoint, driver.InstancePath(instancetype.Container, info.Project, info.Name, false), info.Privileged) if err != nil { return errors.Wrap(err, "Create container mount point") } From 9a57538232f3d0ab1cd8c0a01b2d7771da815e1d Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 18:34:42 +0000 Subject: [PATCH 21/27] lxd/storage/zfs: InstancePath usage Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage_zfs.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go index ca7cc6cbc2..da3350bde5 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/backup" + "github.com/lxc/lxd/lxd/instance/instancetype" "github.com/lxc/lxd/lxd/migration" "github.com/lxc/lxd/lxd/operations" "github.com/lxc/lxd/lxd/project" @@ -2113,7 +2114,7 @@ func (s *storageZfs) ContainerBackupCreate(path string, backup backup.Backup, so func (s *storageZfs) doContainerBackupLoadOptimized(info backup.Info, data io.ReadSeeker, tarArgs []string) error { containerName, _, _ := shared.ContainerGetParentAndSnapshotName(info.Name) containerMntPoint := driver.GetContainerMountPoint(info.Project, s.pool.Name, containerName) - err := driver.CreateContainerMountpoint(containerMntPoint, driver.ContainerPath(project.Prefix(info.Project, info.Name), false), info.Privileged) + err := driver.CreateContainerMountpoint(containerMntPoint, driver.InstancePath(instancetype.Container, info.Project, info.Name, false), info.Privileged) if err != nil { return err } From b919f8c90161cdbbd63c7032516096e112866dab Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 18:36:49 +0000 Subject: [PATCH 22/27] lxd/container/test: InstancePath usage Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/container_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lxd/container_test.go b/lxd/container_test.go index 92b7711e9b..40bb744df6 100644 --- a/lxd/container_test.go +++ b/lxd/container_test.go @@ -165,7 +165,7 @@ func (suite *containerTestSuite) TestContainer_Path_Regular() { suite.Req.False(c.IsSnapshot(), "Shouldn't be a snapshot.") suite.Req.Equal(shared.VarPath("containers", "testFoo"), c.Path()) - suite.Req.Equal(shared.VarPath("containers", "testFoo2"), driver.ContainerPath("testFoo2", false)) + suite.Req.Equal(shared.VarPath("containers", "testFoo2"), driver.InstancePath(instancetype.Container, "default", "testFoo2", false)) } func (suite *containerTestSuite) TestContainer_LogPath() { From 86db8038bd0e8f2e554f0d1420e477ac1213afc5 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 16:56:21 +0000 Subject: [PATCH 23/27] lxd/db/storage/pools: Adds VM instance type constant and conversion codes Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/db/storage_pools.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go index b2995b23e0..1f9f30c8f4 100644 --- a/lxd/db/storage_pools.go +++ b/lxd/db/storage_pools.go @@ -1053,6 +1053,7 @@ const ( StoragePoolVolumeTypeContainer = iota StoragePoolVolumeTypeImage StoragePoolVolumeTypeCustom + StoragePoolVolumeTypeVM ) // Leave the string type in here! This guarantees that go treats this is as a @@ -1060,6 +1061,7 @@ const ( // constants which is not what we want. const ( StoragePoolVolumeTypeNameContainer string = "container" + StoragePoolVolumeTypeNameVM string = "virtual-machine" StoragePoolVolumeTypeNameImage string = "image" StoragePoolVolumeTypeNameCustom string = "custom" ) @@ -1081,6 +1083,8 @@ func StoragePoolVolumeTypeToName(volumeType int) (string, error) { switch volumeType { case StoragePoolVolumeTypeContainer: return StoragePoolVolumeTypeNameContainer, nil + case StoragePoolVolumeTypeVM: + return StoragePoolVolumeTypeNameVM, nil case StoragePoolVolumeTypeImage: return StoragePoolVolumeTypeNameImage, nil case StoragePoolVolumeTypeCustom: From a56797fbd3a52281445d7ba69beca06355f8241c Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 16:55:27 +0000 Subject: [PATCH 24/27] lxd/db/containers: Updates pool lookup functions to be instance type agnostic Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/db/containers.go | 28 ++++++++++++++-------------- lxd/db/containers_test.go | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lxd/db/containers.go b/lxd/db/containers.go index 58ff234f32..bb18ebf66c 100644 --- a/lxd/db/containers.go +++ b/lxd/db/containers.go @@ -444,7 +444,7 @@ func (c *ClusterTx) snapshotIDsAndNames(project, name string) (map[int]string, e func (c *ClusterTx) ContainerNodeMove(project, oldName, newName, newNode string) error { // First check that the container to be moved is backed by a ceph // volume. - poolName, err := c.ContainerPool(project, oldName) + poolName, err := c.InstancePool(project, oldName) if err != nil { return errors.Wrap(err, "failed to get container's storage pool name") } @@ -1085,23 +1085,23 @@ WHERE projects.name=? AND instances.name=?` return max } -// ContainerPool returns the storage pool of a given container. +// InstancePool returns the storage pool of a given instance. // -// This is a non-transactional variant of ClusterTx.ContainerPool(). -func (c *Cluster) ContainerPool(project, containerName string) (string, error) { +// This is a non-transactional variant of ClusterTx.InstancePool(). +func (c *Cluster) InstancePool(project, instanceName string) (string, error) { var poolName string err := c.Transaction(func(tx *ClusterTx) error { var err error - poolName, err = tx.ContainerPool(project, containerName) + poolName, err = tx.InstancePool(project, instanceName) return err }) return poolName, err } -// ContainerPool returns the storage pool of a given container. -func (c *ClusterTx) ContainerPool(project, containerName string) (string, error) { - if strings.Contains(containerName, shared.SnapshotDelimiter) { - return c.containerPoolSnapshot(project, containerName) +// InstancePool returns the storage pool of a given instance. +func (c *ClusterTx) InstancePool(project, instanceName string) (string, error) { + if strings.Contains(instanceName, shared.SnapshotDelimiter) { + return c.instancePoolSnapshot(project, instanceName) } // Get container storage volume. Since container names are globally @@ -1113,9 +1113,9 @@ SELECT storage_pools.name FROM storage_pools JOIN storage_volumes ON storage_pools.id=storage_volumes.storage_pool_id JOIN instances ON instances.name=storage_volumes.name JOIN projects ON projects.id=instances.project_id - WHERE projects.name=? AND storage_volumes.node_id=? AND storage_volumes.name=? AND storage_volumes.type=? + WHERE projects.name=? AND storage_volumes.node_id=? AND storage_volumes.name=? AND storage_volumes.type IN(?,?) ` - inargs := []interface{}{project, c.nodeID, containerName, StoragePoolVolumeTypeContainer} + inargs := []interface{}{project, c.nodeID, instanceName, StoragePoolVolumeTypeContainer, StoragePoolVolumeTypeVM} outargs := []interface{}{&poolName} err := c.tx.QueryRow(query, inargs...).Scan(outargs...) @@ -1130,15 +1130,15 @@ SELECT storage_pools.name FROM storage_pools return poolName, nil } -func (c *ClusterTx) containerPoolSnapshot(project, fullName string) (string, error) { +func (c *ClusterTx) instancePoolSnapshot(project, fullName string) (string, error) { poolName := "" query := ` SELECT storage_pools.name FROM storage_pools JOIN storage_volumes ON storage_pools.id=storage_volumes.storage_pool_id JOIN projects ON projects.id=storage_volumes.project_id - WHERE projects.name=? AND storage_volumes.node_id=? AND storage_volumes.name=? AND storage_volumes.type=? + WHERE projects.name=? AND storage_volumes.node_id=? AND storage_volumes.name=? AND storage_volumes.type IN(?,?) ` - inargs := []interface{}{project, c.nodeID, fullName, StoragePoolVolumeTypeContainer} + inargs := []interface{}{project, c.nodeID, fullName, StoragePoolVolumeTypeContainer, StoragePoolVolumeTypeVM} outargs := []interface{}{&poolName} err := c.tx.QueryRow(query, inargs...).Scan(outargs...) diff --git a/lxd/db/containers_test.go b/lxd/db/containers_test.go index be914912bb..4c399a935b 100644 --- a/lxd/db/containers_test.go +++ b/lxd/db/containers_test.go @@ -374,7 +374,7 @@ func TestContainerPool(t *testing.T) { }) require.NoError(t, err) - poolName, err := cluster.ContainerPool("default", "c1") + poolName, err := cluster.InstancePool("default", "c1") require.NoError(t, err) assert.Equal(t, "default", poolName) } From d05b31613e4704f0153b9e184edfe59f25bf8a28 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 6 Nov 2019 17:06:24 +0000 Subject: [PATCH 25/27] lxd/storage/load: InstancePool usage Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage/load.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lxd/storage/load.go b/lxd/storage/load.go index ee3df9df32..bdad09351b 100644 --- a/lxd/storage/load.go +++ b/lxd/storage/load.go @@ -152,7 +152,7 @@ func GetPoolByName(state *state.State, name string) (Pool, error) { // If the pool's driver is not recognised then drivers.ErrUnknownDriver is returned. If the pool's // driver does not support the instance's type then drivers.ErrNotImplemented is returned. func GetPoolByInstance(s *state.State, inst Instance) (Pool, error) { - poolName, err := s.Cluster.ContainerPool(inst.Project(), inst.Name()) + poolName, err := s.Cluster.InstancePool(inst.Project(), inst.Name()) if err != nil { return nil, err } From df08df4ca72fee1db9e6593aae8eb70bf1a23738 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 7 Nov 2019 09:20:20 +0000 Subject: [PATCH 26/27] lxd/db/containers/test: InstancePool usage Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/db/containers_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lxd/db/containers_test.go b/lxd/db/containers_test.go index 4c399a935b..2b2f96c65c 100644 --- a/lxd/db/containers_test.go +++ b/lxd/db/containers_test.go @@ -347,7 +347,7 @@ func TestContainersByNodeName(t *testing.T) { }, result) } -func TestContainerPool(t *testing.T) { +func TestInstancePool(t *testing.T) { cluster, cleanup := db.NewTestCluster(t) defer cleanup() From 8d62d915358260345e1fab2a20ff7ac1fd33512b Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 7 Nov 2019 09:20:34 +0000 Subject: [PATCH 27/27] lxd/storage: InstancePool usage Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/storage.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lxd/storage.go b/lxd/storage.go index 7b50d49119..163bff5435 100644 --- a/lxd/storage.go +++ b/lxd/storage.go @@ -620,7 +620,7 @@ func storagePoolVolumeContainerCreateInit(s *state.State, project string, poolNa func storagePoolVolumeContainerLoadInit(s *state.State, project, containerName string) (storage, error) { // Get the storage pool of a given container. - poolName, err := s.Cluster.ContainerPool(project, containerName) + poolName, err := s.Cluster.InstancePool(project, containerName) if err != nil { return nil, errors.Wrapf(err, "Load storage pool for container %q in project %q", containerName, project) }
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel