The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/distrobuilder/pull/277

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) ===
This PR contains changes in preparation for VM support.
From 65112ce0b9a49cb33fbec289e38135ff9577be25 Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.h...@canonical.com>
Date: Wed, 12 Feb 2020 17:29:44 +0100
Subject: [PATCH 1/7] shared/definition: Add LXD target

Signed-off-by: Thomas Hipp <thomas.h...@canonical.com>
---
 shared/definition.go | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/shared/definition.go b/shared/definition.go
index 7b586d5..62262a7 100644
--- a/shared/definition.go
+++ b/shared/definition.go
@@ -129,9 +129,21 @@ type DefinitionTargetLXC struct {
        Config        []DefinitionTargetLXCConfig `yaml:"config,omitempty"`
 }
 
+// DefinitionTargetLXDVM represents LXD VM specific options.
+type DefinitionTargetLXDVM struct {
+       Size       uint   `yaml:"size,omitempty"`
+       Filesystem string `yaml:"filesystem,omitempty"`
+}
+
+// DefinitionTargetLXD represents LXD specific options.
+type DefinitionTargetLXD struct {
+       VM DefinitionTargetLXDVM `yaml:"vm,omitempty"`
+}
+
 // A DefinitionTarget specifies target dependent files.
 type DefinitionTarget struct {
        LXC DefinitionTargetLXC `yaml:"lxc,omitempty"`
+       LXD DefinitionTargetLXD `yaml:"lxd,omitempty"`
 }
 
 // A DefinitionFile represents a file which is to be created inside to chroot.

From 39d263ae2a10b14070485c9dd6fdd66ab0282779 Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.h...@canonical.com>
Date: Wed, 12 Feb 2020 17:32:20 +0100
Subject: [PATCH 2/7] shared/definition: Add VM field to target

This add a VM field to target which is for internal use only. It makes
it simpler to deal with VMs as it removes the necessity of passing the
value of the --vm flag.

Signed-off-by: Thomas Hipp <thomas.h...@canonical.com>
---
 shared/definition.go | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/shared/definition.go b/shared/definition.go
index 62262a7..ff0c30d 100644
--- a/shared/definition.go
+++ b/shared/definition.go
@@ -142,8 +142,9 @@ type DefinitionTargetLXD struct {
 
 // A DefinitionTarget specifies target dependent files.
 type DefinitionTarget struct {
-       LXC DefinitionTargetLXC `yaml:"lxc,omitempty"`
-       LXD DefinitionTargetLXD `yaml:"lxd,omitempty"`
+       LXC  DefinitionTargetLXC `yaml:"lxc,omitempty"`
+       LXD  DefinitionTargetLXD `yaml:"lxd,omitempty"`
+       Type string              // This field is internal only and used only 
for simplicity.
 }
 
 // A DefinitionFile represents a file which is to be created inside to chroot.
@@ -278,6 +279,9 @@ func (d *Definition) SetDefaults() {
        if d.Image.Description == "" {
                d.Image.Description = "{{ image.distribution|capfirst }} {{ 
image.release }} {{ image.architecture_mapped }}{% if image.variant != 
\"default\" %} ({{ image.variant }}){% endif %} ({{ image.serial }})"
        }
+
+       // Set default target type. This will only be overriden if building VMs 
for LXD.
+       d.Targets.Type = "container"
 }
 
 // Validate validates the Definition.

From e41a1a15767bead9333b30c78f2f8188892bf927 Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.h...@canonical.com>
Date: Wed, 12 Feb 2020 17:34:08 +0100
Subject: [PATCH 3/7] shared/definition: Add GetTypes to filter

This adds a new `types` filter which is used for differentiating between
containers and VMs.

Signed-off-by: Thomas Hipp <thomas.h...@canonical.com>
---
 shared/definition.go | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/shared/definition.go b/shared/definition.go
index ff0c30d..23a4006 100644
--- a/shared/definition.go
+++ b/shared/definition.go
@@ -17,6 +17,7 @@ type Filter interface {
        GetReleases() []string
        GetArchitectures() []string
        GetVariants() []string
+       GetTypes() []string
 }
 
 // A DefinitionFilter defines filters for various actions.
@@ -24,6 +25,7 @@ type DefinitionFilter struct {
        Releases      []string `yaml:"releases,omitempty"`
        Architectures []string `yaml:"architectures,omitempty"`
        Variants      []string `yaml:"variants,omitempty"`
+       Types         []string `yaml:"types,omitempty"`
 }
 
 // GetReleases returns a list of releases.
@@ -41,6 +43,11 @@ func (d *DefinitionFilter) GetVariants() []string {
        return d.Variants
 }
 
+// GetTypes returns a list of types.
+func (d *DefinitionFilter) GetTypes() []string {
+       return d.Types
+}
+
 // A DefinitionPackagesSet is a set of packages which are to be installed
 // or removed.
 type DefinitionPackagesSet struct {

From 907bf785d2a15b1094c7e9a145971de65924d7ae Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.h...@canonical.com>
Date: Tue, 29 Oct 2019 13:38:12 +0100
Subject: [PATCH 4/7] shared: Export ChrootMount struct

This exports the ChrootMount struct.

Signed-off-by: Thomas Hipp <thomas.h...@canonical.com>
---
 shared/chroot.go | 33 +++++++++++++++++----------------
 1 file changed, 17 insertions(+), 16 deletions(-)

diff --git a/shared/chroot.go b/shared/chroot.go
index eefdeab..a6ad591 100644
--- a/shared/chroot.go
+++ b/shared/chroot.go
@@ -12,19 +12,20 @@ import (
        lxd "github.com/lxc/lxd/shared"
 )
 
-type chrootMount struct {
-       source string
-       target string
-       fstype string
-       flags  uintptr
-       data   string
-       isDir  bool
+// ChrootMount defines mount args.
+type ChrootMount struct {
+       Source string
+       Target string
+       FSType string
+       Flags  uintptr
+       Data   string
+       IsDir  bool
 }
 
 // ActiveChroots is a map of all active chroots and their exit functions
 var ActiveChroots = make(map[string]func() error)
 
-func setupMounts(rootfs string, mounts []chrootMount) error {
+func setupMounts(rootfs string, mounts []ChrootMount) error {
        // Create a temporary mount path
        err := os.MkdirAll(filepath.Join(rootfs, ".distrobuilder"), 0700)
        if err != nil {
@@ -36,7 +37,7 @@ func setupMounts(rootfs string, mounts []chrootMount) error {
                tmpTarget := filepath.Join(rootfs, ".distrobuilder", 
fmt.Sprintf("%d", i))
 
                // Create the target mountpoint
-               if mount.isDir {
+               if mount.IsDir {
                        err := os.MkdirAll(tmpTarget, 0755)
                        if err != nil {
                                return err
@@ -49,22 +50,22 @@ func setupMounts(rootfs string, mounts []chrootMount) error 
{
                }
 
                // Mount to the temporary path
-               err := syscall.Mount(mount.source, tmpTarget, mount.fstype, 
mount.flags, mount.data)
+               err := syscall.Mount(mount.Source, tmpTarget, mount.FSType, 
mount.Flags, mount.Data)
                if err != nil {
-                       return fmt.Errorf("Failed to mount '%s': %s", 
mount.source, err)
+                       return fmt.Errorf("Failed to mount '%s': %s", 
mount.Source, err)
                }
        }
 
        return nil
 }
 
-func moveMounts(mounts []chrootMount) error {
+func moveMounts(mounts []ChrootMount) error {
        for i, mount := range mounts {
                // Source path
                tmpSource := filepath.Join("/", ".distrobuilder", 
fmt.Sprintf("%d", i))
 
                // Resolve symlinks
-               target := mount.target
+               target := mount.Target
                for {
                        // Get information on current target
                        fi, err := os.Lstat(target)
@@ -93,7 +94,7 @@ func moveMounts(mounts []chrootMount) error {
                }
 
                // Create target path
-               if mount.isDir {
+               if mount.IsDir {
                        err = os.MkdirAll(target, 0755)
                        if err != nil {
                                return err
@@ -108,7 +109,7 @@ func moveMounts(mounts []chrootMount) error {
                // Move the mount to its destination
                err = syscall.Mount(tmpSource, target, "", syscall.MS_MOVE, "")
                if err != nil {
-                       return fmt.Errorf("Failed to mount '%s': %s", 
mount.source, err)
+                       return fmt.Errorf("Failed to mount '%s': %s", 
mount.Source, err)
                }
        }
 
@@ -159,7 +160,7 @@ func SetupChroot(rootfs string, envs DefinitionEnv) (func() 
error, error) {
        }
 
        // Setup all other needed mounts
-       mounts := []chrootMount{
+       mounts := []ChrootMount{
                {"none", "/proc", "proc", 0, "", true},
                {"none", "/sys", "sysfs", 0, "", true},
                {"/dev", "/dev", "", syscall.MS_BIND, "", true},

From 2e5d184154a038f6d7ed252cac21b91a7de2f505 Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.h...@canonical.com>
Date: Tue, 29 Oct 2019 15:07:57 +0100
Subject: [PATCH 5/7] *: Pass custom mounts to SetupChroot()

This allows additional mounts to be passed to SetupChroot()

Signed-off-by: Thomas Hipp <thomas.h...@canonical.com>
---
 distrobuilder/main.go       |  2 +-
 distrobuilder/main_lxc.go   |  2 +-
 distrobuilder/main_lxd.go   |  2 +-
 shared/chroot.go            | 10 +++++++---
 sources/alpine-http.go      |  2 +-
 sources/centos-http.go      |  4 ++--
 sources/oraclelinux-http.go |  2 +-
 sources/ubuntu-http.go      |  2 +-
 8 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/distrobuilder/main.go b/distrobuilder/main.go
index 043d656..e820357 100644
--- a/distrobuilder/main.go
+++ b/distrobuilder/main.go
@@ -251,7 +251,7 @@ func (c *cmdGlobal) preRunBuild(cmd *cobra.Command, args 
[]string) error {
        }
 
        // Setup the mounts and chroot into the rootfs
-       exitChroot, err := shared.SetupChroot(c.sourceDir, 
c.definition.Environment)
+       exitChroot, err := shared.SetupChroot(c.sourceDir, 
c.definition.Environment, nil)
        if err != nil {
                return fmt.Errorf("Failed to setup chroot: %s", err)
        }
diff --git a/distrobuilder/main_lxc.go b/distrobuilder/main_lxc.go
index 0b8fb77..9ce050e 100644
--- a/distrobuilder/main_lxc.go
+++ b/distrobuilder/main_lxc.go
@@ -60,7 +60,7 @@ func (c *cmdLXC) run(cmd *cobra.Command, args []string) error 
{
        }
 
        exitChroot, err := shared.SetupChroot(c.global.sourceDir,
-               c.global.definition.Environment)
+               c.global.definition.Environment, nil)
        if err != nil {
                return err
        }
diff --git a/distrobuilder/main_lxd.go b/distrobuilder/main_lxd.go
index 9aea6dc..73596bb 100644
--- a/distrobuilder/main_lxd.go
+++ b/distrobuilder/main_lxd.go
@@ -85,7 +85,7 @@ func (c *cmdLXD) run(cmd *cobra.Command, args []string) error 
{
        }
 
        exitChroot, err := shared.SetupChroot(c.global.sourceDir,
-               c.global.definition.Environment)
+               c.global.definition.Environment, nil)
        if err != nil {
                return err
        }
diff --git a/shared/chroot.go b/shared/chroot.go
index a6ad591..1c652b3 100644
--- a/shared/chroot.go
+++ b/shared/chroot.go
@@ -152,7 +152,7 @@ func killChrootProcesses(rootfs string) error {
 }
 
 // SetupChroot sets up mount and files, a reverter and then chroots for you
-func SetupChroot(rootfs string, envs DefinitionEnv) (func() error, error) {
+func SetupChroot(rootfs string, envs DefinitionEnv, m []ChrootMount) (func() 
error, error) {
        // Mount the rootfs
        err := syscall.Mount(rootfs, rootfs, "", syscall.MS_BIND, "")
        if err != nil {
@@ -181,7 +181,11 @@ func SetupChroot(rootfs string, envs DefinitionEnv) 
(func() error, error) {
        }
 
        // Setup all needed mounts in a temporary location
-       err = setupMounts(rootfs, mounts)
+       if m != nil && len(m) > 0 {
+               err = setupMounts(rootfs, append(mounts, m...))
+       } else {
+               err = setupMounts(rootfs, mounts)
+       }
        if err != nil {
                return nil, fmt.Errorf("Failed to mount filesystems: %v", err)
        }
@@ -199,7 +203,7 @@ func SetupChroot(rootfs string, envs DefinitionEnv) (func() 
error, error) {
        }
 
        // Move all the mounts into place
-       err = moveMounts(mounts)
+       err = moveMounts(append(mounts, m...))
        if err != nil {
                return nil, err
        }
diff --git a/sources/alpine-http.go b/sources/alpine-http.go
index ecb95a6..4edd5d7 100644
--- a/sources/alpine-http.go
+++ b/sources/alpine-http.go
@@ -98,7 +98,7 @@ func (s *AlpineLinuxHTTP) Run(definition shared.Definition, 
rootfsDir string) er
        // Handle edge builds
        if definition.Image.Release == "edge" {
                // Upgrade to edge
-               exitChroot, err := shared.SetupChroot(rootfsDir, 
definition.Environment)
+               exitChroot, err := shared.SetupChroot(rootfsDir, 
definition.Environment, nil)
                if err != nil {
                        return err
                }
diff --git a/sources/centos-http.go b/sources/centos-http.go
index d23bf1c..9888217 100644
--- a/sources/centos-http.go
+++ b/sources/centos-http.go
@@ -169,7 +169,7 @@ func (s CentOSHTTP) unpackRaw(filePath, rootfsDir string) 
error {
        }
 
        // Setup the mounts and chroot into the rootfs
-       exitChroot, err := shared.SetupChroot(tempRootDir, 
shared.DefinitionEnv{})
+       exitChroot, err := shared.SetupChroot(tempRootDir, 
shared.DefinitionEnv{}, nil)
        if err != nil {
                return fmt.Errorf("Failed to setup chroot: %s", err)
        }
@@ -296,7 +296,7 @@ func (s CentOSHTTP) unpackISO(filePath, rootfsDir string) 
error {
        }
 
        // Setup the mounts and chroot into the rootfs
-       exitChroot, err := shared.SetupChroot(tempRootDir, 
shared.DefinitionEnv{})
+       exitChroot, err := shared.SetupChroot(tempRootDir, 
shared.DefinitionEnv{}, nil)
        if err != nil {
                return fmt.Errorf("Failed to setup chroot: %s", err)
        }
diff --git a/sources/oraclelinux-http.go b/sources/oraclelinux-http.go
index 4906455..6d21904 100644
--- a/sources/oraclelinux-http.go
+++ b/sources/oraclelinux-http.go
@@ -169,7 +169,7 @@ func (s *OracleLinuxHTTP) unpackISO(latestUpdate, filePath, 
rootfsDir string) er
        }
 
        // Setup the mounts and chroot into the rootfs
-       exitChroot, err := shared.SetupChroot(tempRootDir, 
shared.DefinitionEnv{})
+       exitChroot, err := shared.SetupChroot(tempRootDir, 
shared.DefinitionEnv{}, nil)
        if err != nil {
                return fmt.Errorf("Failed to setup chroot: %s", err)
        }
diff --git a/sources/ubuntu-http.go b/sources/ubuntu-http.go
index b82042a..c7ca68c 100644
--- a/sources/ubuntu-http.go
+++ b/sources/ubuntu-http.go
@@ -150,7 +150,7 @@ func (s *UbuntuHTTP) runCoreVariant(definition 
shared.Definition, rootfsDir stri
                return err
        }
 
-       exitChroot, err := shared.SetupChroot(baseImageDir, 
shared.DefinitionEnv{})
+       exitChroot, err := shared.SetupChroot(baseImageDir, 
shared.DefinitionEnv{}, nil)
        if err != nil {
                return err
        }

From 7528172e2c76791abae1dfd958ce3b99b3b2e4df Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.h...@canonical.com>
Date: Wed, 12 Feb 2020 17:37:30 +0100
Subject: [PATCH 6/7] *: Support VM filtering

Signed-off-by: Thomas Hipp <thomas.h...@canonical.com>
---
 distrobuilder/chroot.go         | 10 +++++-----
 distrobuilder/main.go           |  8 ++++----
 distrobuilder/main_build-dir.go |  2 +-
 distrobuilder/main_lxc.go       |  4 ++--
 distrobuilder/main_lxd.go       |  4 ++--
 shared/definition.go            | 22 ++++++++++++++++++----
 shared/definition_test.go       | 26 ++++++++++++++++++++++++--
 7 files changed, 56 insertions(+), 20 deletions(-)

diff --git a/distrobuilder/chroot.go b/distrobuilder/chroot.go
index 0602469..a723d54 100644
--- a/distrobuilder/chroot.go
+++ b/distrobuilder/chroot.go
@@ -8,7 +8,7 @@ import (
        "github.com/lxc/distrobuilder/shared"
 )
 
-func manageRepositories(def *shared.Definition, manager *managers.Manager) 
error {
+func manageRepositories(def *shared.Definition, manager *managers.Manager, 
vmOnly bool) error {
        var err error
 
        if def.Packages.Repositories == nil || len(def.Packages.Repositories) 
== 0 {
@@ -21,7 +21,7 @@ func manageRepositories(def *shared.Definition, manager 
*managers.Manager) error
        }
 
        for _, repo := range def.Packages.Repositories {
-               if !shared.ApplyFilter(&repo, def.Image.Release, 
def.Image.ArchitectureMapped, def.Image.Variant) {
+               if !shared.ApplyFilter(&repo, def.Image.Release, 
def.Image.ArchitectureMapped, def.Image.Variant, def.Targets.Type, vmOnly) {
                        continue
                }
 
@@ -46,7 +46,7 @@ func manageRepositories(def *shared.Definition, manager 
*managers.Manager) error
        return nil
 }
 
-func managePackages(def *shared.Definition, manager *managers.Manager) error {
+func managePackages(def *shared.Definition, manager *managers.Manager, vmOnly 
bool) error {
        var err error
 
        err = manager.Refresh()
@@ -61,7 +61,7 @@ func managePackages(def *shared.Definition, manager 
*managers.Manager) error {
                }
 
                // Run post update hook
-               for _, action := range def.GetRunnableActions("post-update") {
+               for _, action := range def.GetRunnableActions("post-update", 
vmOnly) {
                        err = shared.RunScript(action.Action)
                        if err != nil {
                                return fmt.Errorf("Failed to run post-update: 
%s", err)
@@ -72,7 +72,7 @@ func managePackages(def *shared.Definition, manager 
*managers.Manager) error {
        var validSets []shared.DefinitionPackagesSet
 
        for _, set := range def.Packages.Sets {
-               if !shared.ApplyFilter(&set, def.Image.Release, 
def.Image.ArchitectureMapped, def.Image.Variant) {
+               if !shared.ApplyFilter(&set, def.Image.Release, 
def.Image.ArchitectureMapped, def.Image.Variant, def.Targets.Type, vmOnly) {
                        continue
                }
 
diff --git a/distrobuilder/main.go b/distrobuilder/main.go
index e820357..a963e1e 100644
--- a/distrobuilder/main.go
+++ b/distrobuilder/main.go
@@ -269,13 +269,13 @@ func (c *cmdGlobal) preRunBuild(cmd *cobra.Command, args 
[]string) error {
                manager = 
managers.GetCustom(*c.definition.Packages.CustomManager)
        }
 
-       err = manageRepositories(c.definition, manager)
+       err = manageRepositories(c.definition, manager, false)
        if err != nil {
                return fmt.Errorf("Failed to manage repositories: %s", err)
        }
 
        // Run post unpack hook
-       for _, hook := range c.definition.GetRunnableActions("post-unpack") {
+       for _, hook := range c.definition.GetRunnableActions("post-unpack", 
false) {
                err := shared.RunScript(hook.Action)
                if err != nil {
                        return fmt.Errorf("Failed to run post-unpack: %s", err)
@@ -283,13 +283,13 @@ func (c *cmdGlobal) preRunBuild(cmd *cobra.Command, args 
[]string) error {
        }
 
        // Install/remove/update packages
-       err = managePackages(c.definition, manager)
+       err = managePackages(c.definition, manager, false)
        if err != nil {
                return fmt.Errorf("Failed to manage packages: %s", err)
        }
 
        // Run post packages hook
-       for _, hook := range c.definition.GetRunnableActions("post-packages") {
+       for _, hook := range c.definition.GetRunnableActions("post-packages", 
false) {
                err := shared.RunScript(hook.Action)
                if err != nil {
                        return fmt.Errorf("Failed to run post-packages: %s", 
err)
diff --git a/distrobuilder/main_build-dir.go b/distrobuilder/main_build-dir.go
index 3f8a3a0..e7ab644 100644
--- a/distrobuilder/main_build-dir.go
+++ b/distrobuilder/main_build-dir.go
@@ -28,7 +28,7 @@ func (c *cmdBuildDir) command() *cobra.Command {
                                        return fmt.Errorf("Unknown generator 
'%s'", file.Generator)
                                }
 
-                               if !shared.ApplyFilter(&file, 
c.global.definition.Image.Release, 
c.global.definition.Image.ArchitectureMapped, 
c.global.definition.Image.Variant) {
+                               if !shared.ApplyFilter(&file, 
c.global.definition.Image.Release, 
c.global.definition.Image.ArchitectureMapped, 
c.global.definition.Image.Variant, c.global.definition.Targets.Type, false) {
                                        continue
                                }
 
diff --git a/distrobuilder/main_lxc.go b/distrobuilder/main_lxc.go
index 9ce050e..0990d32 100644
--- a/distrobuilder/main_lxc.go
+++ b/distrobuilder/main_lxc.go
@@ -48,7 +48,7 @@ func (c *cmdLXC) run(cmd *cobra.Command, args []string) error 
{
                        return fmt.Errorf("Unknown generator '%s'", 
file.Generator)
                }
 
-               if !shared.ApplyFilter(&file, 
c.global.definition.Image.Release, 
c.global.definition.Image.ArchitectureMapped, 
c.global.definition.Image.Variant) {
+               if !shared.ApplyFilter(&file, 
c.global.definition.Image.Release, 
c.global.definition.Image.ArchitectureMapped, 
c.global.definition.Image.Variant, c.global.definition.Targets.Type, false) {
                        continue
                }
 
@@ -66,7 +66,7 @@ func (c *cmdLXC) run(cmd *cobra.Command, args []string) error 
{
        }
 
        // Run post files hook
-       for _, action := range 
c.global.definition.GetRunnableActions("post-files") {
+       for _, action := range 
c.global.definition.GetRunnableActions("post-files", false) {
                err := shared.RunScript(action.Action)
                if err != nil {
                        exitChroot()
diff --git a/distrobuilder/main_lxd.go b/distrobuilder/main_lxd.go
index 73596bb..2d2ec5c 100644
--- a/distrobuilder/main_lxd.go
+++ b/distrobuilder/main_lxd.go
@@ -68,7 +68,7 @@ func (c *cmdLXD) run(cmd *cobra.Command, args []string) error 
{
                c.global.flagCacheDir, *c.global.definition)
 
        for _, file := range c.global.definition.Files {
-               if !shared.ApplyFilter(&file, 
c.global.definition.Image.Release, 
c.global.definition.Image.ArchitectureMapped, 
c.global.definition.Image.Variant) {
+               if !shared.ApplyFilter(&file, 
c.global.definition.Image.Release, 
c.global.definition.Image.ArchitectureMapped, 
c.global.definition.Image.Variant, c.global.definition.Targets.Type, false) {
                        continue
                }
 
@@ -91,7 +91,7 @@ func (c *cmdLXD) run(cmd *cobra.Command, args []string) error 
{
        }
 
        // Run post files hook
-       for _, action := range 
c.global.definition.GetRunnableActions("post-files") {
+       for _, action := range 
c.global.definition.GetRunnableActions("post-files", false) {
                err := shared.RunScript(action.Action)
                if err != nil {
                        exitChroot()
diff --git a/shared/definition.go b/shared/definition.go
index 23a4006..d3abca7 100644
--- a/shared/definition.go
+++ b/shared/definition.go
@@ -459,7 +459,7 @@ func (d *Definition) Validate() error {
 
 // GetRunnableActions returns a list of actions depending on the trigger
 // and releases.
-func (d *Definition) GetRunnableActions(trigger string) []DefinitionAction {
+func (d *Definition) GetRunnableActions(trigger string, vmOnly bool) 
[]DefinitionAction {
        out := []DefinitionAction{}
 
        for _, action := range d.Actions {
@@ -467,7 +467,7 @@ func (d *Definition) GetRunnableActions(trigger string) 
[]DefinitionAction {
                        continue
                }
 
-               if !ApplyFilter(&action, d.Image.Release, 
d.Image.ArchitectureMapped, d.Image.Variant) {
+               if !ApplyFilter(&action, d.Image.Release, 
d.Image.ArchitectureMapped, d.Image.Variant, d.Targets.Type, vmOnly) {
                        continue
                }
 
@@ -485,7 +485,7 @@ func (d *Definition) GetEarlyPackages(action string) 
[]string {
        normal := []DefinitionPackagesSet{}
 
        for _, set := range d.Packages.Sets {
-               if set.Early && set.Action == action && ApplyFilter(&set, 
d.Image.Release, d.Image.ArchitectureMapped, d.Image.Variant) {
+               if set.Early && set.Action == action && ApplyFilter(&set, 
d.Image.Release, d.Image.ArchitectureMapped, d.Image.Variant, d.Targets.Type, 
false) {
                        early = append(early, set.Packages...)
                } else {
                        normal = append(normal, set)
@@ -563,7 +563,7 @@ func getFieldByTag(v reflect.Value, t reflect.Type, tag 
string) (reflect.Value,
 }
 
 // ApplyFilter returns true if the filter matches.
-func ApplyFilter(filter Filter, release string, architecture string, variant 
string) bool {
+func ApplyFilter(filter Filter, release string, architecture string, variant 
string, targetType string, vmOnly bool) bool {
        if len(filter.GetReleases()) > 0 && !shared.StringInSlice(release, 
filter.GetReleases()) {
                return false
        }
@@ -576,5 +576,19 @@ func ApplyFilter(filter Filter, release string, 
architecture string, variant str
                return false
        }
 
+       types := filter.GetTypes()
+
+       if vmOnly {
+               if len(types) == 1 && types[0] == "vm" && targetType == "vm" {
+                       return true
+               }
+
+               return false
+       }
+
+       if len(types) > 0 && !shared.StringInSlice(targetType, types) {
+               return false
+       }
+
        return true
 }
diff --git a/shared/definition_test.go b/shared/definition_test.go
index 6186501..6238620 100644
--- a/shared/definition_test.go
+++ b/shared/definition_test.go
@@ -510,7 +510,29 @@ func TestApplyFilter(t *testing.T) {
        repo.Variants = []string{"default"}
        repo.Architectures = []string{"amd64", "i386"}
        repo.Releases = []string{"foo"}
+       repo.Types = []string{"vm"}
 
-       require.True(t, ApplyFilter(&repo, "foo", "amd64", "default"))
-       require.False(t, ApplyFilter(&repo, "", "arm64", "default"))
+       require.True(t, ApplyFilter(&repo, "foo", "amd64", "default", "vm", 
true))
+       require.True(t, ApplyFilter(&repo, "foo", "amd64", "default", "vm", 
false))
+       require.False(t, ApplyFilter(&repo, "foo", "amd64", "default", 
"container", false))
+       require.False(t, ApplyFilter(&repo, "foo", "amd64", "default", 
"container", true))
+       require.False(t, ApplyFilter(&repo, "", "arm64", "default", "vm", 
false))
+
+       repo.Types = []string{"container"}
+       require.False(t, ApplyFilter(&repo, "foo", "amd64", "default", "vm", 
true))
+       require.False(t, ApplyFilter(&repo, "foo", "amd64", "default", "vm", 
false))
+       require.True(t, ApplyFilter(&repo, "foo", "amd64", "default", 
"container", false))
+       require.False(t, ApplyFilter(&repo, "foo", "amd64", "default", 
"container", true))
+
+       repo.Types = []string{"container", "vm"}
+       require.True(t, ApplyFilter(&repo, "foo", "amd64", "default", "vm", 
false))
+       require.True(t, ApplyFilter(&repo, "foo", "amd64", "default", 
"container", false))
+       require.False(t, ApplyFilter(&repo, "foo", "amd64", "default", 
"container", true))
+       require.False(t, ApplyFilter(&repo, "foo", "amd64", "default", "vm", 
true))
+
+       repo.Types = []string{}
+       require.True(t, ApplyFilter(&repo, "foo", "amd64", "default", "vm", 
false))
+       require.True(t, ApplyFilter(&repo, "foo", "amd64", "default", 
"container", false))
+       require.False(t, ApplyFilter(&repo, "foo", "amd64", "default", 
"container", true))
+       require.False(t, ApplyFilter(&repo, "foo", "amd64", "default", "vm", 
true))
 }

From e5d467b3c1333c5ea028ece42e8adece2e8d0c5c Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.h...@canonical.com>
Date: Fri, 14 Feb 2020 11:54:41 +0100
Subject: [PATCH 7/7] distrobuilder: Use overlayfs

Signed-off-by: Thomas Hipp <thomas.h...@canonical.com>
---
 distrobuilder/chroot.go   | 57 +++++++++++++++++++++++++++++++++++++++
 distrobuilder/main_lxc.go | 15 ++++++++---
 distrobuilder/main_lxd.go | 14 +++++++---
 3 files changed, 78 insertions(+), 8 deletions(-)

diff --git a/distrobuilder/chroot.go b/distrobuilder/chroot.go
index a723d54..1e37dba 100644
--- a/distrobuilder/chroot.go
+++ b/distrobuilder/chroot.go
@@ -2,8 +2,13 @@ package main
 
 import (
        "fmt"
+       "os"
+       "path/filepath"
        "strings"
 
+       "github.com/pkg/errors"
+       "golang.org/x/sys/unix"
+
        "github.com/lxc/distrobuilder/managers"
        "github.com/lxc/distrobuilder/shared"
 )
@@ -138,3 +143,55 @@ func optimizePackageSets(sets 
[]shared.DefinitionPackagesSet) []shared.Definitio
 
        return newSets
 }
+
+func getOverlay(cacheDir, sourceDir string) (func(), string, error) {
+       upperDir := filepath.Join(cacheDir, "upper")
+       overlayDir := filepath.Join(cacheDir, "overlay")
+       workDir := filepath.Join(cacheDir, "work")
+
+       err := os.Mkdir(upperDir, 0755)
+       if err != nil {
+               return nil, "", err
+       }
+
+       err = os.Mkdir(overlayDir, 0755)
+       if err != nil {
+               return nil, "", err
+       }
+
+       err = os.Mkdir(workDir, 0755)
+       if err != nil {
+               return nil, "", err
+       }
+
+       opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", sourceDir, 
upperDir, workDir)
+
+       err = unix.Mount("overlay", overlayDir, "overlay", 0, opts)
+       if err != nil {
+               return nil, "", err
+       }
+
+       cleanup := func() {
+               err := unix.Unmount(overlayDir, 0)
+               if err != nil {
+                       fmt.Fprintln(os.Stderr, errors.Wrap(err, "Failed to 
unmount overlay"))
+               }
+
+               err = os.RemoveAll(upperDir)
+               if err != nil {
+                       fmt.Fprintln(os.Stderr, errors.Wrap(err, "Failed to 
remove upper directory"))
+               }
+
+               err = os.RemoveAll(workDir)
+               if err != nil {
+                       fmt.Fprintln(os.Stderr, errors.Wrap(err, "Failed to 
remove work directory"))
+               }
+
+               err = os.Remove(overlayDir)
+               if err != nil {
+                       fmt.Fprintln(os.Stderr, errors.Wrap(err, "Failed to 
remove overlay directory"))
+               }
+       }
+
+       return cleanup, overlayDir, nil
+}
diff --git a/distrobuilder/main_lxc.go b/distrobuilder/main_lxc.go
index 0990d32..00731b8 100644
--- a/distrobuilder/main_lxc.go
+++ b/distrobuilder/main_lxc.go
@@ -3,6 +3,7 @@ package main
 import (
        "fmt"
 
+       "github.com/pkg/errors"
        "github.com/spf13/cobra"
 
        "github.com/lxc/distrobuilder/generators"
@@ -39,7 +40,13 @@ func (c *cmdLXC) commandPack() *cobra.Command {
 }
 
 func (c *cmdLXC) run(cmd *cobra.Command, args []string) error {
-       img := image.NewLXCImage(c.global.sourceDir, c.global.targetDir,
+       cleanup, overlayDir, err := getOverlay(c.global.flagCacheDir, 
c.global.sourceDir)
+       if err != nil {
+               return errors.Wrap(err, "Failed to create overlay")
+       }
+       defer cleanup()
+
+       img := image.NewLXCImage(overlayDir, c.global.targetDir,
                c.global.flagCacheDir, *c.global.definition)
 
        for _, file := range c.global.definition.Files {
@@ -52,14 +59,14 @@ func (c *cmdLXC) run(cmd *cobra.Command, args []string) 
error {
                        continue
                }
 
-               err := generator.RunLXC(c.global.flagCacheDir, 
c.global.sourceDir, img,
+               err := generator.RunLXC(c.global.flagCacheDir, overlayDir, img,
                        file)
                if err != nil {
                        return err
                }
        }
 
-       exitChroot, err := shared.SetupChroot(c.global.sourceDir,
+       exitChroot, err := shared.SetupChroot(overlayDir,
                c.global.definition.Environment, nil)
        if err != nil {
                return err
@@ -82,7 +89,7 @@ func (c *cmdLXC) run(cmd *cobra.Command, args []string) error 
{
        }
 
        // Clean up the chroot by restoring the orginal files.
-       err = generators.RestoreFiles(c.global.flagCacheDir, c.global.sourceDir)
+       err = generators.RestoreFiles(c.global.flagCacheDir, overlayDir)
        if err != nil {
                return fmt.Errorf("Failed to restore cached files: %s", err)
        }
diff --git a/distrobuilder/main_lxd.go b/distrobuilder/main_lxd.go
index 2d2ec5c..8823f39 100644
--- a/distrobuilder/main_lxd.go
+++ b/distrobuilder/main_lxd.go
@@ -1,10 +1,10 @@
 package main
 
 import (
-       "errors"
        "fmt"
 
        lxd "github.com/lxc/lxd/shared"
+       "github.com/pkg/errors"
        "github.com/spf13/cobra"
 
        "github.com/lxc/distrobuilder/generators"
@@ -64,7 +64,13 @@ func (c *cmdLXD) commandPack() *cobra.Command {
 }
 
 func (c *cmdLXD) run(cmd *cobra.Command, args []string) error {
-       img := image.NewLXDImage(c.global.sourceDir, c.global.targetDir,
+       cleanup, overlayDir, err := getOverlay(c.global.flagCacheDir, 
c.global.sourceDir)
+       if err != nil {
+               return errors.Wrap(err, "Failed to create overlay")
+       }
+       defer cleanup()
+
+       img := image.NewLXDImage(overlayDir, c.global.targetDir,
                c.global.flagCacheDir, *c.global.definition)
 
        for _, file := range c.global.definition.Files {
@@ -77,14 +83,14 @@ func (c *cmdLXD) run(cmd *cobra.Command, args []string) 
error {
                        return fmt.Errorf("Unknown generator '%s'", 
file.Generator)
                }
 
-               err := generator.RunLXD(c.global.flagCacheDir, 
c.global.sourceDir,
+               err := generator.RunLXD(c.global.flagCacheDir, overlayDir,
                        img, file)
                if err != nil {
                        return fmt.Errorf("Failed to create LXD data: %s", err)
                }
        }
 
-       exitChroot, err := shared.SetupChroot(c.global.sourceDir,
+       exitChroot, err := shared.SetupChroot(overlayDir,
                c.global.definition.Environment, nil)
        if err != nil {
                return err
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to