[lxc-devel] [lxd/master] Instance: Common driver and profile device validation support
tomponline on Github
lxc-bot at linuxcontainers.org
Thu Jan 30 13:57:56 UTC 2020
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 1611 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200130/5dd0acb7/attachment-0001.bin>
-------------- next part --------------
From 8be13df905cbaed9f1eb57c88014e8f65313261a Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 30 Jan 2020 13:25:21 +0000
Subject: [PATCH 01/12] lxd/device/device/common: Splits device common into own
file
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/device/device_common.go | 58 +++++++++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)
create mode 100644 lxd/device/device_common.go
diff --git a/lxd/device/device_common.go b/lxd/device/device_common.go
new file mode 100644
index 0000000000..2f6551f5d3
--- /dev/null
+++ b/lxd/device/device_common.go
@@ -0,0 +1,58 @@
+package device
+
+import (
+ "fmt"
+
+ deviceConfig "github.com/lxc/lxd/lxd/device/config"
+ "github.com/lxc/lxd/lxd/instance"
+ "github.com/lxc/lxd/lxd/state"
+)
+
+// deviceCommon represents the common struct for all devices.
+type deviceCommon struct {
+ inst instance.Instance
+ name string
+ config deviceConfig.Device
+ state *state.State
+ volatileGet func() map[string]string
+ volatileSet func(map[string]string) error
+}
+
+// init stores the Instance, daemon state, device name and config into device.
+// It also needs to be provided with volatile get and set functions for the device to allow
+// persistent data to be accessed. This is implemented as part of deviceCommon so that the majority
+// of devices don't need to implement it and can just embed deviceCommon.
+func (d *deviceCommon) init(inst instance.Instance, state *state.State, name string, conf deviceConfig.Device, volatileGet VolatileGetter, volatileSet VolatileSetter) {
+ d.inst = inst
+ d.name = name
+ d.config = conf
+ d.state = state
+ d.volatileGet = volatileGet
+ d.volatileSet = volatileSet
+}
+
+// Add returns nil error as majority of devices don't need to do any host-side setup.
+func (d *deviceCommon) Add() error {
+ return nil
+}
+
+// Register returns nil error as majority of devices don't need to do any event registration.
+func (d *deviceCommon) Register() error {
+ return nil
+}
+
+// CanHotPlug returns true as majority of devices can be started/stopped when instance is running.
+// Also returns an empty list of update fields as most devices do not support live updates.
+func (d *deviceCommon) CanHotPlug() (bool, []string) {
+ return true, []string{}
+}
+
+// Update returns an error as most devices do not support live updates without being restarted.
+func (d *deviceCommon) Update(oldDevices deviceConfig.Devices, isRunning bool) error {
+ return fmt.Errorf("Device does not support updates whilst started")
+}
+
+// Remove returns nil error as majority of devices don't need to do any host-side cleanup on delete.
+func (d *deviceCommon) Remove() error {
+ return nil
+}
From 00c762a7f36d8431bc8fb9c67cc197594223b044 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 30 Jan 2020 13:25:39 +0000
Subject: [PATCH 02/12] lxd/device/device: Removes original device.go file
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/device/device.go | 163 -------------------------------------------
1 file changed, 163 deletions(-)
delete mode 100644 lxd/device/device.go
diff --git a/lxd/device/device.go b/lxd/device/device.go
deleted file mode 100644
index af9e4a07ed..0000000000
--- a/lxd/device/device.go
+++ /dev/null
@@ -1,163 +0,0 @@
-package device
-
-import (
- "fmt"
-
- deviceConfig "github.com/lxc/lxd/lxd/device/config"
- "github.com/lxc/lxd/lxd/instance"
- "github.com/lxc/lxd/lxd/state"
-)
-
-// devTypes defines supported top-level device type creation functions.
-var devTypes = map[string]func(deviceConfig.Device) device{
- "nic": nicLoadByType,
- "infiniband": infinibandLoadByType,
- "proxy": func(c deviceConfig.Device) device { return &proxy{} },
- "gpu": func(c deviceConfig.Device) device { return &gpu{} },
- "usb": func(c deviceConfig.Device) device { return &usb{} },
- "unix-char": func(c deviceConfig.Device) device { return &unixCommon{} },
- "unix-block": func(c deviceConfig.Device) device { return &unixCommon{} },
- "unix-hotplug": func(c deviceConfig.Device) device { return &unixHotplug{} },
- "disk": func(c deviceConfig.Device) device { return &disk{} },
- "none": func(c deviceConfig.Device) device { return &none{} },
-}
-
-// VolatileSetter is a function that accepts one or more key/value strings to save into the LXD
-// config for this instance. It should add the volatile device name prefix to each key when saving.
-type VolatileSetter func(map[string]string) error
-
-// VolatileGetter is a function that retrieves any key/value string that exists in the LXD database
-// config for this instance. It should only return keys that match the volatile device name prefix,
-// and should remove the prefix before being returned.
-type VolatileGetter func() map[string]string
-
-// Device represents a device that can be added to an instance.
-type Device interface {
- // CanHotPlug returns true if device can be managed whilst instance is running.
- // It also returns a slice of config fields that can be live updated. If only fields in this
- // list have changed then Update() is called rather than triggering a device remove & add.
- CanHotPlug() (bool, []string)
-
- // Add performs any host-side setup when a device is added to an instance.
- // It is called irrespective of whether the instance is running or not.
- Add() error
-
- // Start peforms any host-side configuration required to start the device for the instance.
- // This can be when a device is plugged into a running instance or the instance is starting.
- // Returns run-time configuration needed for configuring the instance with the new device.
- Start() (*deviceConfig.RunConfig, error)
-
- // Register provides the ability for a device to subcribe to events that LXD can generate.
- // It is called after a device is started (after Start()) or when LXD starts.
- Register() error
-
- // Update performs host-side modifications for a device based on the difference between the
- // current config and previous devices config supplied as an argument. This called if the
- // only config fields that have changed are supplied in the list returned from CanHotPlug().
- // The function also accepts a boolean indicating whether the instance is running or not.
- Update(oldDevices deviceConfig.Devices, running bool) error
-
- // Stop performs any host-side cleanup required when a device is removed from an instance,
- // either due to unplugging it from a running instance or instance is being shutdown.
- // Returns run-time configuration needed for detaching the device from the instance.
- Stop() (*deviceConfig.RunConfig, error)
-
- // Remove performs any host-side cleanup when an instance is removed from an instance.
- Remove() error
-}
-
-// device represents a sealed interface that implements Device, but also contains some internal
-// setup functions for a Device that should only be called by device.New() to avoid exposing devices
-// that are not in a known configured state. This is separate from the Device interface so that
-// Devices created outside of the device package can be used by LXD, but ensures that any devices
-// created by the device package will only be accessible after being configured properly by New().
-type device interface {
- Device
-
- // init stores the Instance, daemon State and Config into device and performs any setup.
- init(instance.Instance, *state.State, string, deviceConfig.Device, VolatileGetter, VolatileSetter)
-
- // validateConfig checks Config stored by init() is valid for the instance type.
- validateConfig() error
-}
-
-// deviceCommon represents the common struct for all devices.
-type deviceCommon struct {
- inst instance.Instance
- name string
- config deviceConfig.Device
- state *state.State
- volatileGet func() map[string]string
- volatileSet func(map[string]string) error
-}
-
-// init stores the Instance, daemon state, device name and config into device.
-// It also needs to be provided with volatile get and set functions for the device to allow
-// persistent data to be accessed. This is implemented as part of deviceCommon so that the majority
-// of devices don't need to implement it and can just embed deviceCommon.
-func (d *deviceCommon) init(inst instance.Instance, state *state.State, name string, conf deviceConfig.Device, volatileGet VolatileGetter, volatileSet VolatileSetter) {
- d.inst = inst
- d.name = name
- d.config = conf
- d.state = state
- d.volatileGet = volatileGet
- d.volatileSet = volatileSet
-}
-
-// Add returns nil error as majority of devices don't need to do any host-side setup.
-func (d *deviceCommon) Add() error {
- return nil
-}
-
-// Register returns nil error as majority of devices don't need to do any event registration.
-func (d *deviceCommon) Register() error {
- return nil
-}
-
-// CanHotPlug returns true as majority of devices can be started/stopped when instance is running.
-// Also returns an empty list of update fields as most devices do not support live updates.
-func (d *deviceCommon) CanHotPlug() (bool, []string) {
- return true, []string{}
-}
-
-// Update returns an error as most devices do not support live updates without being restarted.
-func (d *deviceCommon) Update(oldDevices deviceConfig.Devices, isRunning bool) error {
- return fmt.Errorf("Device does not support updates whilst started")
-}
-
-// Remove returns nil error as majority of devices don't need to do any host-side cleanup on delete.
-func (d *deviceCommon) Remove() error {
- return nil
-}
-
-// New instantiates a new device struct, validates the supplied config and sets it into the device.
-// If the device type is valid, but the other config validation fails then an instantiated device
-// is still returned with the validation error. If an unknown device is requested or the device is
-// not compatible with the instance type then an ErrUnsupportedDevType error is returned.
-func New(inst instance.Instance, state *state.State, name string, conf deviceConfig.Device, volatileGet VolatileGetter, volatileSet VolatileSetter) (Device, error) {
- if conf["type"] == "" {
- return nil, fmt.Errorf("Missing device type for device '%s'", name)
- }
-
- devFunc := devTypes[conf["type"]]
-
- // Check if top-level type is recognised, if it is known type it will return a function.
- if devFunc == nil {
- return nil, ErrUnsupportedDevType
- }
-
- // Run the device create function and check it succeeds.
- dev := devFunc(conf)
- if dev == nil {
- return nil, ErrUnsupportedDevType
- }
-
- // Init the device and run validation of supplied config.
- dev.init(inst, state, name, conf, volatileGet, volatileSet)
- err := dev.validateConfig()
-
- // We still return the instantiated device here, as in some scenarios the caller
- // may still want to use the device (such as when stopping or removing) even if
- // the config validation has failed.
- return dev, err
-}
From 9790359629cda3a0505274a8e916794891482f57 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 30 Jan 2020 13:25:58 +0000
Subject: [PATCH 03/12] lxd/device/device/interface: Splits device interfaces
into own file
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/device/device_interface.go | 66 ++++++++++++++++++++++++++++++++++
1 file changed, 66 insertions(+)
create mode 100644 lxd/device/device_interface.go
diff --git a/lxd/device/device_interface.go b/lxd/device/device_interface.go
new file mode 100644
index 0000000000..52fc2edf89
--- /dev/null
+++ b/lxd/device/device_interface.go
@@ -0,0 +1,66 @@
+package device
+
+import (
+ deviceConfig "github.com/lxc/lxd/lxd/device/config"
+ "github.com/lxc/lxd/lxd/instance"
+ "github.com/lxc/lxd/lxd/state"
+)
+
+// VolatileSetter is a function that accepts one or more key/value strings to save into the LXD
+// config for this instance. It should add the volatile device name prefix to each key when saving.
+type VolatileSetter func(map[string]string) error
+
+// VolatileGetter is a function that retrieves any key/value string that exists in the LXD database
+// config for this instance. It should only return keys that match the volatile device name prefix,
+// and should remove the prefix before being returned.
+type VolatileGetter func() map[string]string
+
+// Device represents a device that can be added to an instance.
+type Device interface {
+ // CanHotPlug returns true if device can be managed whilst instance is running.
+ // It also returns a slice of config fields that can be live updated. If only fields in this
+ // list have changed then Update() is called rather than triggering a device remove & add.
+ CanHotPlug() (bool, []string)
+
+ // Add performs any host-side setup when a device is added to an instance.
+ // It is called irrespective of whether the instance is running or not.
+ Add() error
+
+ // Start peforms any host-side configuration required to start the device for the instance.
+ // This can be when a device is plugged into a running instance or the instance is starting.
+ // Returns run-time configuration needed for configuring the instance with the new device.
+ Start() (*deviceConfig.RunConfig, error)
+
+ // Register provides the ability for a device to subcribe to events that LXD can generate.
+ // It is called after a device is started (after Start()) or when LXD starts.
+ Register() error
+
+ // Update performs host-side modifications for a device based on the difference between the
+ // current config and previous devices config supplied as an argument. This called if the
+ // only config fields that have changed are supplied in the list returned from CanHotPlug().
+ // The function also accepts a boolean indicating whether the instance is running or not.
+ Update(oldDevices deviceConfig.Devices, running bool) error
+
+ // Stop performs any host-side cleanup required when a device is removed from an instance,
+ // either due to unplugging it from a running instance or instance is being shutdown.
+ // Returns run-time configuration needed for detaching the device from the instance.
+ Stop() (*deviceConfig.RunConfig, error)
+
+ // Remove performs any host-side cleanup when an instance is removed from an instance.
+ Remove() error
+}
+
+// device represents a sealed interface that implements Device, but also contains some internal
+// setup functions for a Device that should only be called by device.New() to avoid exposing devices
+// that are not in a known configured state. This is separate from the Device interface so that
+// Devices created outside of the device package can be used by LXD, but ensures that any devices
+// created by the device package will only be accessible after being configured properly by New().
+type device interface {
+ Device
+
+ // init stores the Instance, daemon State and Config into device and performs any setup.
+ init(instance.Instance, *state.State, string, deviceConfig.Device, VolatileGetter, VolatileSetter)
+
+ // validateConfig checks Config stored by init() is valid for the instance type.
+ validateConfig(instance.ConfigReader) error
+}
From 48c183cd0cee7fab25b872de295b06520928bd21 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 30 Jan 2020 13:27:10 +0000
Subject: [PATCH 04/12] lxd/device/device/load: Separates device load functions
into own file
Adds Validate() function for validating devices without needing a concrete instance.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/device/device_load.go | 77 +++++++++++++++++++++++++++++++++++++++
1 file changed, 77 insertions(+)
create mode 100644 lxd/device/device_load.go
diff --git a/lxd/device/device_load.go b/lxd/device/device_load.go
new file mode 100644
index 0000000000..1227dba7bb
--- /dev/null
+++ b/lxd/device/device_load.go
@@ -0,0 +1,77 @@
+package device
+
+import (
+ "fmt"
+
+ deviceConfig "github.com/lxc/lxd/lxd/device/config"
+ "github.com/lxc/lxd/lxd/instance"
+ "github.com/lxc/lxd/lxd/state"
+)
+
+// devTypes defines supported top-level device type creation functions.
+var devTypes = map[string]func(deviceConfig.Device) device{
+ "nic": nicLoadByType,
+ "infiniband": infinibandLoadByType,
+ "proxy": func(c deviceConfig.Device) device { return &proxy{} },
+ "gpu": func(c deviceConfig.Device) device { return &gpu{} },
+ "usb": func(c deviceConfig.Device) device { return &usb{} },
+ "unix-char": func(c deviceConfig.Device) device { return &unixCommon{} },
+ "unix-block": func(c deviceConfig.Device) device { return &unixCommon{} },
+ "unix-hotplug": func(c deviceConfig.Device) device { return &unixHotplug{} },
+ "disk": func(c deviceConfig.Device) device { return &disk{} },
+ "none": func(c deviceConfig.Device) device { return &none{} },
+}
+
+// load instantiates a device and initialises its internal state. It does not validate the config supplied.
+func load(inst instance.Instance, state *state.State, name string, conf deviceConfig.Device, volatileGet VolatileGetter, volatileSet VolatileSetter) (device, error) {
+ if conf["type"] == "" {
+ return nil, fmt.Errorf("Missing device type for device %q", name)
+ }
+
+ devFunc := devTypes[conf["type"]]
+
+ // Check if top-level type is recognised, if it is known type it will return a function.
+ if devFunc == nil {
+ return nil, ErrUnsupportedDevType
+ }
+
+ // Run the device create function and check it succeeds.
+ dev := devFunc(conf)
+ if dev == nil {
+ return nil, ErrUnsupportedDevType
+ }
+
+ // Setup the device's internal variables.
+ dev.init(inst, state, name, conf, volatileGet, volatileSet)
+
+ return dev, nil
+}
+
+// New instantiates a new device struct, validates the supplied config and sets it into the device.
+// If the device type is valid, but the other config validation fails then an instantiated device
+// is still returned with the validation error. If an unknown device is requested or the device is
+// not compatible with the instance type then an ErrUnsupportedDevType error is returned.
+func New(inst instance.Instance, state *state.State, name string, conf deviceConfig.Device, volatileGet VolatileGetter, volatileSet VolatileSetter) (Device, error) {
+ dev, err := load(inst, state, name, conf, volatileGet, volatileSet)
+ if err != nil {
+ return nil, err
+ }
+
+ err = dev.validateConfig(inst)
+
+ // We still return the instantiated device here, as in some scenarios the caller
+ // may still want to use the device (such as when stopping or removing) even if
+ // the config validation has failed.
+ return dev, err
+}
+
+// Validate checks a device's config is valid. This only requires an instance.ConfigReader rather than an full
+// blown instance to allow profile devices to be validated too.
+func Validate(instConfig instance.ConfigReader, state *state.State, name string, conf deviceConfig.Device) error {
+ dev, err := load(nil, state, name, conf, nil, nil)
+ if err != nil {
+ return err
+ }
+
+ return dev.validateConfig(instConfig)
+}
From 7c6e99090383a62ed3d7ea50e6e167f8a287b942 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 30 Jan 2020 13:27:53 +0000
Subject: [PATCH 05/12] lxd/instance/drivers/driver/common: Adds common driver
type
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/instance/drivers/driver_common.go | 74 +++++++++++++++++++++++++++
1 file changed, 74 insertions(+)
create mode 100644 lxd/instance/drivers/driver_common.go
diff --git a/lxd/instance/drivers/driver_common.go b/lxd/instance/drivers/driver_common.go
new file mode 100644
index 0000000000..10d70c9dc1
--- /dev/null
+++ b/lxd/instance/drivers/driver_common.go
@@ -0,0 +1,74 @@
+package drivers
+
+import (
+ "github.com/lxc/lxd/lxd/db"
+ deviceConfig "github.com/lxc/lxd/lxd/device/config"
+ "github.com/lxc/lxd/lxd/instance/instancetype"
+ "github.com/lxc/lxd/lxd/state"
+ "github.com/lxc/lxd/shared/api"
+)
+
+// common provides structure common to all instance types.
+type common struct {
+ dbType instancetype.Type
+ expandedConfig map[string]string
+ expandedDevices deviceConfig.Devices
+ localConfig map[string]string
+ localDevices deviceConfig.Devices
+ profiles []string
+ project string
+ state *state.State
+}
+
+// Type returns the instance's type.
+func (c *common) Type() instancetype.Type {
+ return c.dbType
+}
+
+// ExpandedConfig returns instance's expanded config.
+func (c *common) ExpandedConfig() map[string]string {
+ return c.expandedConfig
+}
+
+// ExpandedDevices returns instance's expanded device config.
+func (c *common) ExpandedDevices() deviceConfig.Devices {
+ return c.expandedDevices
+}
+
+// LocalConfig returns the instance's local config.
+func (c *common) LocalConfig() map[string]string {
+ return c.localConfig
+}
+
+// LocalDevices returns the instance's local device config.
+func (c *common) LocalDevices() deviceConfig.Devices {
+ return c.localDevices
+}
+
+func (c *common) expandConfig(profiles []api.Profile) error {
+ if profiles == nil && len(c.profiles) > 0 {
+ var err error
+ profiles, err = c.state.Cluster.ProfilesGet(c.project, c.profiles)
+ if err != nil {
+ return err
+ }
+ }
+
+ c.expandedConfig = db.ProfilesExpandConfig(c.localConfig, profiles)
+
+ return nil
+}
+
+func (c *common) expandDevices(profiles []api.Profile) error {
+ if profiles == nil && len(c.profiles) > 0 {
+ var err error
+ profiles, err = c.state.Cluster.ProfilesGet(c.project, c.profiles)
+ if err != nil {
+ return err
+ }
+ }
+
+ c.expandedDevices = db.ProfilesExpandDevices(c.localDevices, profiles)
+
+ return nil
+}
From 076616edde0ac55737fb6086a26b25e2b9b337ce Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 30 Jan 2020 13:28:45 +0000
Subject: [PATCH 06/12] lxd/instance/instance/interface: Adds ConfigRead
interface
For accessing an instance's type and config only.
Embeds this into existing Instance interface.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/instance/instance_interface.go | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/lxd/instance/instance_interface.go b/lxd/instance/instance_interface.go
index 59a39167ad..1018ddf780 100644
--- a/lxd/instance/instance_interface.go
+++ b/lxd/instance/instance_interface.go
@@ -14,8 +14,19 @@ import (
"github.com/lxc/lxd/shared/api"
)
+// ConfigReader is used to read instance config.
+type ConfigReader interface {
+ Type() instancetype.Type
+ ExpandedConfig() map[string]string
+ ExpandedDevices() deviceConfig.Devices
+ LocalConfig() map[string]string
+ LocalDevices() deviceConfig.Devices
+}
+
// The Instance interface.
type Instance interface {
+ ConfigReader
+
// Instance actions.
Freeze() error
Shutdown(timeout time.Duration) error
@@ -71,15 +82,11 @@ type Instance interface {
Location() string
Project() string
Name() string
- Type() instancetype.Type
Description() string
Architecture() int
CreationDate() time.Time
LastUsedDate() time.Time
- ExpandedConfig() map[string]string
- ExpandedDevices() deviceConfig.Devices
- LocalConfig() map[string]string
- LocalDevices() deviceConfig.Devices
+
Profiles() []string
InitPID() int
State() string
From e319b22496359e2718cd6ff3043b7eee8b63ead6 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 30 Jan 2020 13:30:00 +0000
Subject: [PATCH 07/12] lxd/instance/drivers/load: Updates validDevices() to
use device.Validate function
This avoids needing to instantiate a concrete instance type for profile validation.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/instance/drivers/load.go | 27 +++++++--------------------
1 file changed, 7 insertions(+), 20 deletions(-)
diff --git a/lxd/instance/drivers/load.go b/lxd/instance/drivers/load.go
index 018ad0fb34..a77e55f8a0 100644
--- a/lxd/instance/drivers/load.go
+++ b/lxd/instance/drivers/load.go
@@ -47,40 +47,27 @@ func load(s *state.State, args db.InstanceArgs, profiles []api.Profile) (instanc
}
// validDevices validate instance device configs.
-func validDevices(state *state.State, cluster *db.Cluster, instanceType instancetype.Type, instanceName string, devices deviceConfig.Devices, expanded bool) error {
+func validDevices(state *state.State, cluster *db.Cluster, instanceType instancetype.Type, devices deviceConfig.Devices, expanded bool) error {
// Empty device list
if devices == nil {
return nil
}
- // Create temporary InstanceArgs, populate it's name, localDevices and expandedDevices properties based
- // on the mode of validation occurring. In non-expanded validation expensive checks should be avoided.
- instArgs := db.InstanceArgs{
- Name: instanceName,
- Type: instanceType,
- Devices: devices.Clone(), // Prevent devices from modifying their config.
+ instConf := &common{
+ dbType: instanceType,
+ localDevices: devices.Clone(),
}
- var expandedDevices deviceConfig.Devices
+ // In non-expanded validation expensive checks should be avoided.
if expanded {
// The devices being validated are already expanded, so just use the same
// devices clone as we used for the main devices config.
- expandedDevices = instArgs.Devices
- }
-
- // Create a temporary Instance for use in device validation.
- var inst instance.Instance
- if instArgs.Type == instancetype.Container {
- inst = LXCInstantiate(state, instArgs, expandedDevices)
- } else if instArgs.Type == instancetype.VM {
- inst = qemuInstantiate(state, instArgs, expandedDevices)
- } else {
- return fmt.Errorf("Invalid instance type")
+ instConf.expandedDevices = instConf.localDevices
}
// Check each device individually using the device package.
for name, config := range devices {
- _, err := device.New(inst, state, name, config, nil, nil)
+ err := device.Validate(instConf, state, name, config)
if err != nil {
return errors.Wrapf(err, "Device validation failed %q", name)
}
From feb032e1dc5b924ea790b07aaee9d25dc0c945e2 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 30 Jan 2020 13:30:41 +0000
Subject: [PATCH 08/12] lxd/instance/instance/utils: Removes instanceName from
validateDevices function
Reinforces that device validation doesn't need instance name, as we might be validating profile devices.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/instance/instance_utils.go | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/lxd/instance/instance_utils.go b/lxd/instance/instance_utils.go
index 9dbc6e8d1c..b418f90dac 100644
--- a/lxd/instance/instance_utils.go
+++ b/lxd/instance/instance_utils.go
@@ -32,11 +32,8 @@ import (
"github.com/lxc/lxd/shared/version"
)
-// ProfileValidationName is an indicator that the instance is just being used for profile validation.
-const ProfileValidationName = ""
-
// ValidDevices is linked from instance/drivers.validDevices to validate device config.
-var ValidDevices func(state *state.State, cluster *db.Cluster, instanceType instancetype.Type, instanceName string, devices deviceConfig.Devices, expanded bool) error
+var ValidDevices func(state *state.State, cluster *db.Cluster, instanceType instancetype.Type, devices deviceConfig.Devices, expanded bool) error
// Load is linked from instance/drivers.load to allow different instance types to be loaded.
var Load func(s *state.State, args db.InstanceArgs, profiles []api.Profile) (Instance, error)
From 451c7509242e5142c4dc187fa9e697f715235d28 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 30 Jan 2020 13:33:09 +0000
Subject: [PATCH 09/12] lxd/instance/drivers/driver/qemu: Embeds common type
and removes dupe functionality
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/instance/drivers/driver_qemu.go | 101 ++++++----------------------
1 file changed, 21 insertions(+), 80 deletions(-)
diff --git a/lxd/instance/drivers/driver_qemu.go b/lxd/instance/drivers/driver_qemu.go
index 556b1bc32a..f816561b0a 100644
--- a/lxd/instance/drivers/driver_qemu.go
+++ b/lxd/instance/drivers/driver_qemu.go
@@ -32,7 +32,6 @@ import (
deviceConfig "github.com/lxc/lxd/lxd/device/config"
"github.com/lxc/lxd/lxd/instance"
"github.com/lxc/lxd/lxd/instance/drivers/qmp"
- "github.com/lxc/lxd/lxd/instance/instancetype"
"github.com/lxc/lxd/lxd/instance/operationlock"
"github.com/lxc/lxd/lxd/maas"
"github.com/lxc/lxd/lxd/operations"
@@ -84,20 +83,22 @@ func qemuLoad(s *state.State, args db.InstanceArgs, profiles []api.Profile) (ins
// have access to the profiles used to do it. This can be safely passed as nil if not required.
func qemuInstantiate(s *state.State, args db.InstanceArgs, expandedDevices deviceConfig.Devices) *qemu {
vm := &qemu{
- state: s,
+ common: common{
+ dbType: args.Type,
+ localConfig: args.Config,
+ localDevices: args.Devices,
+ project: args.Project,
+ state: s,
+ profiles: args.Profiles,
+ },
id: args.ID,
- project: args.Project,
name: args.Name,
description: args.Description,
ephemeral: args.Ephemeral,
architecture: args.Architecture,
- dbType: args.Type,
snapshot: args.Snapshot,
creationDate: args.CreationDate,
lastUsedDate: args.LastUsedDate,
- profiles: args.Profiles,
- localConfig: args.Config,
- localDevices: args.Devices,
stateful: args.Stateful,
node: args.Node,
expiryDate: args.ExpiryDate,
@@ -128,22 +129,24 @@ func qemuInstantiate(s *state.State, args db.InstanceArgs, expandedDevices devic
func qemuCreate(s *state.State, args db.InstanceArgs) (instance.Instance, error) {
// Create the instance struct.
vm := &qemu{
- state: s,
+ common: common{
+ dbType: args.Type,
+ localConfig: args.Config,
+ localDevices: args.Devices,
+ state: s,
+ profiles: args.Profiles,
+ project: args.Project,
+ },
id: args.ID,
- project: args.Project,
name: args.Name,
node: args.Node,
description: args.Description,
ephemeral: args.Ephemeral,
architecture: args.Architecture,
- dbType: args.Type,
snapshot: args.Snapshot,
stateful: args.Stateful,
creationDate: args.CreationDate,
lastUsedDate: args.LastUsedDate,
- profiles: args.Profiles,
- localConfig: args.Config,
- localDevices: args.Devices,
expiryDate: args.ExpiryDate,
}
@@ -191,7 +194,7 @@ func qemuCreate(s *state.State, args db.InstanceArgs) (instance.Instance, error)
return nil, err
}
- err = instance.ValidDevices(s, s.Cluster, vm.Type(), vm.Name(), vm.expandedDevices, true)
+ err = instance.ValidDevices(s, s.Cluster, vm.Type(), vm.expandedDevices, true)
if err != nil {
logger.Error("Failed creating instance", ctxMap)
return nil, errors.Wrap(err, "Invalid devices")
@@ -255,28 +258,19 @@ func qemuCreate(s *state.State, args db.InstanceArgs) (instance.Instance, error)
// qemu is the QEMU virtual machine driver.
type qemu struct {
+ common
+
// Properties.
architecture int
- dbType instancetype.Type
snapshot bool
creationDate time.Time
lastUsedDate time.Time
ephemeral bool
id int
- project string
name string
description string
stateful bool
- // Config.
- expandedConfig map[string]string
- expandedDevices deviceConfig.Devices
- localConfig map[string]string
- localDevices deviceConfig.Devices
- profiles []string
-
- state *state.State
-
// Clustering.
node string
@@ -1977,7 +1971,7 @@ func (vm *qemu) Update(args db.InstanceArgs, userRequested bool) error {
}
// Validate the new devices without using expanded devices validation (expensive checks disabled).
- err = instance.ValidDevices(vm.state, vm.state.Cluster, vm.Type(), vm.Name(), args.Devices, false)
+ err = instance.ValidDevices(vm.state, vm.state.Cluster, vm.Type(), args.Devices, false)
if err != nil {
return errors.Wrap(err, "Invalid devices")
}
@@ -2161,7 +2155,7 @@ func (vm *qemu) Update(args db.InstanceArgs, userRequested bool) error {
}
// Do full expanded validation of the devices diff.
- err = instance.ValidDevices(vm.state, vm.state.Cluster, vm.Type(), vm.Name(), vm.expandedDevices, true)
+ err = instance.ValidDevices(vm.state, vm.state.Cluster, vm.Type(), vm.expandedDevices, true)
if err != nil {
return errors.Wrap(err, "Invalid expanded devices")
}
@@ -3265,11 +3259,6 @@ func (vm *qemu) Name() string {
return vm.name
}
-// Type returns the instance's type.
-func (vm *qemu) Type() instancetype.Type {
- return vm.dbType
-}
-
// Description returns the instance's description.
func (vm *qemu) Description() string {
return vm.description
@@ -3290,54 +3279,6 @@ func (vm *qemu) LastUsedDate() time.Time {
return vm.lastUsedDate
}
-func (vm *qemu) expandConfig(profiles []api.Profile) error {
- if profiles == nil && len(vm.profiles) > 0 {
- var err error
- profiles, err = vm.state.Cluster.ProfilesGet(vm.project, vm.profiles)
- if err != nil {
- return err
- }
- }
-
- vm.expandedConfig = db.ProfilesExpandConfig(vm.localConfig, profiles)
-
- return nil
-}
-
-func (vm *qemu) expandDevices(profiles []api.Profile) error {
- if profiles == nil && len(vm.profiles) > 0 {
- var err error
- profiles, err = vm.state.Cluster.ProfilesGet(vm.project, vm.profiles)
- if err != nil {
- return err
- }
- }
-
- vm.expandedDevices = db.ProfilesExpandDevices(vm.localDevices, profiles)
-
- return nil
-}
-
-// ExpandedConfig returns instance's expanded config.
-func (vm *qemu) ExpandedConfig() map[string]string {
- return vm.expandedConfig
-}
-
-// ExpandedDevices returns instance's expanded device config.
-func (vm *qemu) ExpandedDevices() deviceConfig.Devices {
- return vm.expandedDevices
-}
-
-// LocalConfig returns the instance's local config.
-func (vm *qemu) LocalConfig() map[string]string {
- return vm.localConfig
-}
-
-// LocalDevices returns the instance's local device config.
-func (vm *qemu) LocalDevices() deviceConfig.Devices {
- return vm.localDevices
-}
-
// Profiles returns the instance's profiles.
func (vm *qemu) Profiles() []string {
return vm.profiles
From a7aa674072371bff94719b417c2b5817705f126b Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 30 Jan 2020 13:33:58 +0000
Subject: [PATCH 10/12] lxd: instance.ValidDevices usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/container.go | 2 +-
lxd/container_lxc.go | 6 +++---
lxd/profiles.go | 5 ++---
lxd/profiles_utils.go | 5 ++---
4 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/lxd/container.go b/lxd/container.go
index 844fe79b75..5283d13ec3 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -689,7 +689,7 @@ func instanceCreateInternal(s *state.State, args db.InstanceArgs) (instance.Inst
}
// Validate container devices with the supplied container name and devices.
- err = instance.ValidDevices(s, s.Cluster, args.Type, args.Name, args.Devices, false)
+ err = instance.ValidDevices(s, s.Cluster, args.Type, args.Devices, false)
if err != nil {
return nil, errors.Wrap(err, "Invalid devices")
}
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 6e162807b4..95a6a939fc 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -205,7 +205,7 @@ func containerLXCCreate(s *state.State, args db.InstanceArgs) (instance.Instance
return nil, err
}
- err = instance.ValidDevices(s, s.Cluster, c.Type(), c.Name(), c.expandedDevices, true)
+ err = instance.ValidDevices(s, s.Cluster, c.Type(), c.expandedDevices, true)
if err != nil {
c.Delete()
logger.Error("Failed creating container", ctxMap)
@@ -3922,7 +3922,7 @@ func (c *containerLXC) Update(args db.InstanceArgs, userRequested bool) error {
}
// Validate the new devices without using expanded devices validation (expensive checks disabled).
- err = instance.ValidDevices(c.state, c.state.Cluster, c.Type(), c.Name(), args.Devices, false)
+ err = instance.ValidDevices(c.state, c.state.Cluster, c.Type(), args.Devices, false)
if err != nil {
return errors.Wrap(err, "Invalid devices")
}
@@ -4113,7 +4113,7 @@ func (c *containerLXC) Update(args db.InstanceArgs, userRequested bool) error {
}
// Do full expanded validation of the devices diff.
- err = instance.ValidDevices(c.state, c.state.Cluster, c.Type(), c.Name(), c.expandedDevices, true)
+ err = instance.ValidDevices(c.state, c.state.Cluster, c.Type(), c.expandedDevices, true)
if err != nil {
return errors.Wrap(err, "Invalid expanded devices")
}
diff --git a/lxd/profiles.go b/lxd/profiles.go
index df37752ecb..590a8df759 100644
--- a/lxd/profiles.go
+++ b/lxd/profiles.go
@@ -109,9 +109,8 @@ func profilesPost(d *Daemon, r *http.Request) response.Response {
return response.BadRequest(err)
}
- // Validate instance devices with an ProfileValidationName instanceName to indicate profile validation.
- // At this point we don't know the instance type, so just use Container type for validation.
- err = instance.ValidDevices(d.State(), d.cluster, instancetype.Container, instance.ProfileValidationName, deviceConfig.NewDevices(req.Devices), false)
+ // At this point we don't know the instance type, so just use instancetype.Any type for validation.
+ err = instance.ValidDevices(d.State(), d.cluster, instancetype.Any, deviceConfig.NewDevices(req.Devices), false)
if err != nil {
return response.BadRequest(err)
}
diff --git a/lxd/profiles_utils.go b/lxd/profiles_utils.go
index b2e00869e4..a2e050fed7 100644
--- a/lxd/profiles_utils.go
+++ b/lxd/profiles_utils.go
@@ -21,9 +21,8 @@ func doProfileUpdate(d *Daemon, project, name string, id int64, profile *api.Pro
return err
}
- // Validate instance devices with ProfileValidationName name to indicate profile validation.
- // At this point we don't know the instance type, so just use Container type for validation.
- err = instance.ValidDevices(d.State(), d.cluster, instancetype.Container, instance.ProfileValidationName, deviceConfig.NewDevices(req.Devices), false)
+ // At this point we don't know the instance type, so just use instancetype.Any type for validation.
+ err = instance.ValidDevices(d.State(), d.cluster, instancetype.Any, deviceConfig.NewDevices(req.Devices), false)
if err != nil {
return err
}
From 2a0af09f06482bda5fbf9b6d9fd7d57c6204b4eb Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 30 Jan 2020 13:44:49 +0000
Subject: [PATCH 11/12] lxd/device/device/utils/instance: Adds
instanceSupported function
Helper function to check instance type matches instancetype.Any or one of the instance types supplied.
The instancetype.Any is always supported to allow mixed-instance type profile validation to be supported.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/device/device_utils_instance.go | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/lxd/device/device_utils_instance.go b/lxd/device/device_utils_instance.go
index d001461ee5..2d808c3055 100644
--- a/lxd/device/device_utils_instance.go
+++ b/lxd/device/device_utils_instance.go
@@ -6,6 +6,7 @@ import (
deviceConfig "github.com/lxc/lxd/lxd/device/config"
"github.com/lxc/lxd/lxd/instance"
+ "github.com/lxc/lxd/lxd/instance/instancetype"
"github.com/lxc/lxd/lxd/state"
)
@@ -54,3 +55,20 @@ func instanceGetReservedDevices(s *state.State, m deviceConfig.Device) (map[stri
return reservedDevices, nil
}
+
+// instanceSupported is a helper function to check instance type is supported for validation.
+// Always returns true if supplied instance type is Any, to support profile validation.
+func instanceSupported(instType instancetype.Type, supportedTypes ...instancetype.Type) bool {
+ // If instance type is Any, then profile validation is occurring and we need to support this.
+ if instType == instancetype.Any {
+ return true
+ }
+
+ for _, supportedType := range supportedTypes {
+ if instType == supportedType {
+ return true
+ }
+ }
+
+ return false
+}
From 0ba74d0e96a4b2f004ad174bcf84d1c4f304316b Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 30 Jan 2020 13:46:18 +0000
Subject: [PATCH 12/12] lxd/device: Updates device validateConfig to support
instance.ConfigReader argument
Switches validation implementations to use instance.ConfigReader argument so profile validation can occur without a concrete instance being supplied.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/device/disk.go | 19 +++++++++----------
lxd/device/gpu.go | 5 +++--
lxd/device/infiniband_physical.go | 5 +++--
lxd/device/infiniband_sriov.go | 5 +++--
lxd/device/nic_bridged.go | 5 +++--
lxd/device/nic_ipvlan.go | 5 +++--
lxd/device/nic_macvlan.go | 5 +++--
lxd/device/nic_p2p.go | 5 +++--
lxd/device/nic_physical.go | 7 ++++---
lxd/device/nic_routed.go | 5 +++--
lxd/device/nic_sriov.go | 7 ++++---
lxd/device/none.go | 3 ++-
lxd/device/proxy.go | 5 +++--
lxd/device/unix_common.go | 5 +++--
lxd/device/unix_hotplug.go | 5 +++--
lxd/device/usb.go | 5 +++--
16 files changed, 55 insertions(+), 41 deletions(-)
diff --git a/lxd/device/disk.go b/lxd/device/disk.go
index f2b4eb00c6..ada9b9d2a2 100644
--- a/lxd/device/disk.go
+++ b/lxd/device/disk.go
@@ -49,8 +49,8 @@ func (d *disk) isRequired(devConfig deviceConfig.Device) bool {
}
// validateConfig checks the supplied config for correctness.
-func (d *disk) validateConfig() error {
- if d.inst.Type() != instancetype.Container && d.inst.Type() != instancetype.VM {
+func (d *disk) validateConfig(instConf instance.ConfigReader) error {
+ if !instanceSupported(instConf.Type(), instancetype.Container, instancetype.VM) {
return ErrUnsupportedDevType
}
@@ -87,9 +87,9 @@ func (d *disk) validateConfig() error {
// VMs don't use the "path" property, but containers need it, so if we are validating a profile that can
// be used for all instance types, we must allow any value.
- if d.inst.Name() == instance.ProfileValidationName {
+ if instConf.Type() == instancetype.Any {
rules["path"] = shared.IsAny
- } else if d.inst.Type() == instancetype.Container || d.config["path"] == "/" {
+ } else if instConf.Type() == instancetype.Container || d.config["path"] == "/" {
// If we are validating a container or the root device is being validated, then require the value.
rules["path"] = shared.IsNotEmpty
}
@@ -133,7 +133,7 @@ func (d *disk) validateConfig() error {
// same path, so that if merged profiles share the same the path and then one is removed
// this can still be cleanly removed.
pathCount := 0
- for _, devConfig := range d.inst.LocalDevices() {
+ for _, devConfig := range instConf.LocalDevices() {
if devConfig["type"] == "disk" && d.config["path"] != "" && devConfig["path"] == d.config["path"] {
pathCount++
if pathCount > 1 {
@@ -165,11 +165,10 @@ func (d *disk) validateConfig() error {
return fmt.Errorf("The \"%s\" storage pool doesn't exist", d.config["pool"])
}
- // Only check storate volume is available if we are validating an instance device
- // and not a profile device (check for ProfileValidationName name), and we have least
- // one expanded device (this is so we only do this expensive check after devices
- // have been expanded).
- if d.inst.Name() != instance.ProfileValidationName && len(d.inst.ExpandedDevices()) > 0 && d.config["source"] != "" && d.config["path"] != "/" {
+ // Only check storate volume is available if we are validating an instance device and not a profile
+ // device (check for instancetype.Any), and we have least one expanded device (this is so we only
+ // do this expensive check after devices have been expanded).
+ if instConf.Type() != instancetype.Any && len(instConf.ExpandedDevices()) > 0 && d.config["source"] != "" && d.config["path"] != "/" {
isAvailable, err := d.state.Cluster.StorageVolumeIsAvailable(d.config["pool"], d.config["source"])
if err != nil {
return fmt.Errorf("Check if volume is available: %v", err)
diff --git a/lxd/device/gpu.go b/lxd/device/gpu.go
index 30c5888040..9bb4c39c71 100644
--- a/lxd/device/gpu.go
+++ b/lxd/device/gpu.go
@@ -12,6 +12,7 @@ import (
"golang.org/x/sys/unix"
deviceConfig "github.com/lxc/lxd/lxd/device/config"
+ "github.com/lxc/lxd/lxd/instance"
"github.com/lxc/lxd/lxd/instance/instancetype"
"github.com/lxc/lxd/lxd/resources"
"github.com/lxc/lxd/shared"
@@ -31,8 +32,8 @@ type gpu struct {
}
// validateConfig checks the supplied config for correctness.
-func (d *gpu) validateConfig() error {
- if d.inst.Type() != instancetype.Container {
+func (d *gpu) validateConfig(instConf instance.ConfigReader) error {
+ if !instanceSupported(instConf.Type(), instancetype.Container) {
return ErrUnsupportedDevType
}
diff --git a/lxd/device/infiniband_physical.go b/lxd/device/infiniband_physical.go
index 482f39d817..2c0edefbc6 100644
--- a/lxd/device/infiniband_physical.go
+++ b/lxd/device/infiniband_physical.go
@@ -4,6 +4,7 @@ import (
"fmt"
deviceConfig "github.com/lxc/lxd/lxd/device/config"
+ "github.com/lxc/lxd/lxd/instance"
"github.com/lxc/lxd/lxd/instance/instancetype"
"github.com/lxc/lxd/lxd/resources"
"github.com/lxc/lxd/shared"
@@ -14,8 +15,8 @@ type infinibandPhysical struct {
}
// validateConfig checks the supplied config for correctness.
-func (d *infinibandPhysical) validateConfig() error {
- if d.inst.Type() != instancetype.Container {
+func (d *infinibandPhysical) validateConfig(instConf instance.ConfigReader) error {
+ if !instanceSupported(instConf.Type(), instancetype.Container) {
return ErrUnsupportedDevType
}
diff --git a/lxd/device/infiniband_sriov.go b/lxd/device/infiniband_sriov.go
index b6932e9753..305967a032 100644
--- a/lxd/device/infiniband_sriov.go
+++ b/lxd/device/infiniband_sriov.go
@@ -4,6 +4,7 @@ import (
"fmt"
deviceConfig "github.com/lxc/lxd/lxd/device/config"
+ "github.com/lxc/lxd/lxd/instance"
"github.com/lxc/lxd/lxd/instance/instancetype"
"github.com/lxc/lxd/lxd/resources"
"github.com/lxc/lxd/shared"
@@ -15,8 +16,8 @@ type infinibandSRIOV struct {
}
// validateConfig checks the supplied config for correctness.
-func (d *infinibandSRIOV) validateConfig() error {
- if d.inst.Type() != instancetype.Container {
+func (d *infinibandSRIOV) validateConfig(instConf instance.ConfigReader) error {
+ if !instanceSupported(instConf.Type(), instancetype.Container) {
return ErrUnsupportedDevType
}
diff --git a/lxd/device/nic_bridged.go b/lxd/device/nic_bridged.go
index 699caddf5a..eb93964ffd 100644
--- a/lxd/device/nic_bridged.go
+++ b/lxd/device/nic_bridged.go
@@ -23,6 +23,7 @@ import (
deviceConfig "github.com/lxc/lxd/lxd/device/config"
"github.com/lxc/lxd/lxd/dnsmasq"
firewallConsts "github.com/lxc/lxd/lxd/firewall/consts"
+ "github.com/lxc/lxd/lxd/instance"
"github.com/lxc/lxd/lxd/instance/instancetype"
"github.com/lxc/lxd/lxd/util"
"github.com/lxc/lxd/shared"
@@ -48,8 +49,8 @@ type nicBridged struct {
}
// validateConfig checks the supplied config for correctness.
-func (d *nicBridged) validateConfig() error {
- if d.inst.Type() != instancetype.Container && d.inst.Type() != instancetype.VM {
+func (d *nicBridged) validateConfig(instConf instance.ConfigReader) error {
+ if !instanceSupported(instConf.Type(), instancetype.Container, instancetype.VM) {
return ErrUnsupportedDevType
}
diff --git a/lxd/device/nic_ipvlan.go b/lxd/device/nic_ipvlan.go
index 75c8227f8f..92ae30174e 100644
--- a/lxd/device/nic_ipvlan.go
+++ b/lxd/device/nic_ipvlan.go
@@ -5,6 +5,7 @@ import (
"strings"
deviceConfig "github.com/lxc/lxd/lxd/device/config"
+ "github.com/lxc/lxd/lxd/instance"
"github.com/lxc/lxd/lxd/instance/instancetype"
"github.com/lxc/lxd/lxd/util"
"github.com/lxc/lxd/shared"
@@ -19,8 +20,8 @@ func (d *nicIPVLAN) CanHotPlug() (bool, []string) {
}
// validateConfig checks the supplied config for correctness.
-func (d *nicIPVLAN) validateConfig() error {
- if d.inst.Type() != instancetype.Container {
+func (d *nicIPVLAN) validateConfig(instConf instance.ConfigReader) error {
+ if !instanceSupported(instConf.Type(), instancetype.Container) {
return ErrUnsupportedDevType
}
diff --git a/lxd/device/nic_macvlan.go b/lxd/device/nic_macvlan.go
index 03d34a9e47..46d67dd429 100644
--- a/lxd/device/nic_macvlan.go
+++ b/lxd/device/nic_macvlan.go
@@ -4,6 +4,7 @@ import (
"fmt"
deviceConfig "github.com/lxc/lxd/lxd/device/config"
+ "github.com/lxc/lxd/lxd/instance"
"github.com/lxc/lxd/lxd/instance/instancetype"
"github.com/lxc/lxd/lxd/revert"
"github.com/lxc/lxd/shared"
@@ -14,8 +15,8 @@ type nicMACVLAN struct {
}
// validateConfig checks the supplied config for correctness.
-func (d *nicMACVLAN) validateConfig() error {
- if d.inst.Type() != instancetype.Container && d.inst.Type() != instancetype.VM {
+func (d *nicMACVLAN) validateConfig(instConf instance.ConfigReader) error {
+ if !instanceSupported(instConf.Type(), instancetype.Container, instancetype.VM) {
return ErrUnsupportedDevType
}
diff --git a/lxd/device/nic_p2p.go b/lxd/device/nic_p2p.go
index 2043597110..e0882a8b27 100644
--- a/lxd/device/nic_p2p.go
+++ b/lxd/device/nic_p2p.go
@@ -4,6 +4,7 @@ import (
"fmt"
deviceConfig "github.com/lxc/lxd/lxd/device/config"
+ "github.com/lxc/lxd/lxd/instance"
"github.com/lxc/lxd/lxd/instance/instancetype"
"github.com/lxc/lxd/shared"
)
@@ -13,8 +14,8 @@ type nicP2P struct {
}
// validateConfig checks the supplied config for correctness.
-func (d *nicP2P) validateConfig() error {
- if d.inst.Type() != instancetype.Container && d.inst.Type() != instancetype.VM {
+func (d *nicP2P) validateConfig(instConf instance.ConfigReader) error {
+ if !instanceSupported(instConf.Type(), instancetype.Container, instancetype.VM) {
return ErrUnsupportedDevType
}
diff --git a/lxd/device/nic_physical.go b/lxd/device/nic_physical.go
index b8d4662b72..f8627373d7 100644
--- a/lxd/device/nic_physical.go
+++ b/lxd/device/nic_physical.go
@@ -6,6 +6,7 @@ import (
"github.com/pkg/errors"
deviceConfig "github.com/lxc/lxd/lxd/device/config"
+ "github.com/lxc/lxd/lxd/instance"
"github.com/lxc/lxd/lxd/instance/instancetype"
"github.com/lxc/lxd/lxd/revert"
"github.com/lxc/lxd/lxd/util"
@@ -17,8 +18,8 @@ type nicPhysical struct {
}
// validateConfig checks the supplied config for correctness.
-func (d *nicPhysical) validateConfig() error {
- if d.inst.Type() != instancetype.Container && d.inst.Type() != instancetype.VM {
+func (d *nicPhysical) validateConfig(instConf instance.ConfigReader) error {
+ if !instanceSupported(instConf.Type(), instancetype.Container, instancetype.VM) {
return ErrUnsupportedDevType
}
@@ -30,7 +31,7 @@ func (d *nicPhysical) validateConfig() error {
"boot.priority",
}
- if d.inst.Type() == instancetype.Container {
+ if instConf.Type() == instancetype.Container {
optionalFields = append(optionalFields, "mtu", "hwaddr", "vlan")
}
diff --git a/lxd/device/nic_routed.go b/lxd/device/nic_routed.go
index 6077ce41bc..6198c1fb9c 100644
--- a/lxd/device/nic_routed.go
+++ b/lxd/device/nic_routed.go
@@ -5,6 +5,7 @@ import (
"strings"
deviceConfig "github.com/lxc/lxd/lxd/device/config"
+ "github.com/lxc/lxd/lxd/instance"
"github.com/lxc/lxd/lxd/instance/instancetype"
"github.com/lxc/lxd/lxd/util"
"github.com/lxc/lxd/shared"
@@ -22,8 +23,8 @@ func (d *nicRouted) CanHotPlug() (bool, []string) {
}
// validateConfig checks the supplied config for correctness.
-func (d *nicRouted) validateConfig() error {
- if d.inst.Type() != instancetype.Container {
+func (d *nicRouted) validateConfig(instConf instance.ConfigReader) error {
+ if !instanceSupported(instConf.Type(), instancetype.Container) {
return ErrUnsupportedDevType
}
diff --git a/lxd/device/nic_sriov.go b/lxd/device/nic_sriov.go
index 9269604381..572670616e 100644
--- a/lxd/device/nic_sriov.go
+++ b/lxd/device/nic_sriov.go
@@ -11,6 +11,7 @@ import (
"strings"
deviceConfig "github.com/lxc/lxd/lxd/device/config"
+ "github.com/lxc/lxd/lxd/instance"
"github.com/lxc/lxd/lxd/instance/instancetype"
"github.com/lxc/lxd/lxd/revert"
"github.com/lxc/lxd/shared"
@@ -21,8 +22,8 @@ type nicSRIOV struct {
}
// validateConfig checks the supplied config for correctness.
-func (d *nicSRIOV) validateConfig() error {
- if d.inst.Type() != instancetype.Container && d.inst.Type() != instancetype.VM {
+func (d *nicSRIOV) validateConfig(instConf instance.ConfigReader) error {
+ if !instanceSupported(instConf.Type(), instancetype.Container, instancetype.VM) {
return ErrUnsupportedDevType
}
@@ -38,7 +39,7 @@ func (d *nicSRIOV) validateConfig() error {
}
// For VMs only NIC properties that can be specified on the parent's VF settings are controllable.
- if d.inst.Type() == instancetype.Container {
+ if instConf.Type() == instancetype.Container {
optionalFields = append(optionalFields, "mtu")
}
diff --git a/lxd/device/none.go b/lxd/device/none.go
index 44026a1933..dcd2a70dba 100644
--- a/lxd/device/none.go
+++ b/lxd/device/none.go
@@ -2,6 +2,7 @@ package device
import (
deviceConfig "github.com/lxc/lxd/lxd/device/config"
+ "github.com/lxc/lxd/lxd/instance"
)
type none struct {
@@ -9,7 +10,7 @@ type none struct {
}
// validateConfig checks the supplied config for correctness.
-func (d *none) validateConfig() error {
+func (d *none) validateConfig(instConf instance.ConfigReader) error {
rules := map[string]func(string) error{} // No fields allowed.
err := d.config.Validate(rules)
if err != nil {
diff --git a/lxd/device/proxy.go b/lxd/device/proxy.go
index 1ac382907c..77a1394575 100644
--- a/lxd/device/proxy.go
+++ b/lxd/device/proxy.go
@@ -17,6 +17,7 @@ import (
deviceConfig "github.com/lxc/lxd/lxd/device/config"
firewallConsts "github.com/lxc/lxd/lxd/firewall/consts"
+ "github.com/lxc/lxd/lxd/instance"
"github.com/lxc/lxd/lxd/instance/instancetype"
"github.com/lxc/lxd/lxd/project"
"github.com/lxc/lxd/shared"
@@ -40,8 +41,8 @@ type proxyProcInfo struct {
}
// validateConfig checks the supplied config for correctness.
-func (d *proxy) validateConfig() error {
- if d.inst.Type() != instancetype.Container {
+func (d *proxy) validateConfig(instConf instance.ConfigReader) error {
+ if !instanceSupported(instConf.Type(), instancetype.Container) {
return ErrUnsupportedDevType
}
diff --git a/lxd/device/unix_common.go b/lxd/device/unix_common.go
index ba32170f90..87de76f724 100644
--- a/lxd/device/unix_common.go
+++ b/lxd/device/unix_common.go
@@ -6,6 +6,7 @@ import (
"strings"
deviceConfig "github.com/lxc/lxd/lxd/device/config"
+ "github.com/lxc/lxd/lxd/instance"
"github.com/lxc/lxd/lxd/instance/instancetype"
"github.com/lxc/lxd/shared"
)
@@ -38,8 +39,8 @@ func (d *unixCommon) isRequired() bool {
}
// validateConfig checks the supplied config for correctness.
-func (d *unixCommon) validateConfig() error {
- if d.inst.Type() != instancetype.Container {
+func (d *unixCommon) validateConfig(instConf instance.ConfigReader) error {
+ if !instanceSupported(instConf.Type(), instancetype.Container) {
return ErrUnsupportedDevType
}
diff --git a/lxd/device/unix_hotplug.go b/lxd/device/unix_hotplug.go
index 5e02f96176..628b580077 100644
--- a/lxd/device/unix_hotplug.go
+++ b/lxd/device/unix_hotplug.go
@@ -10,6 +10,7 @@ import (
udev "github.com/farjump/go-libudev"
deviceConfig "github.com/lxc/lxd/lxd/device/config"
+ "github.com/lxc/lxd/lxd/instance"
"github.com/lxc/lxd/lxd/instance/instancetype"
"github.com/lxc/lxd/shared"
)
@@ -41,8 +42,8 @@ func (d *unixHotplug) isRequired() bool {
}
// validateConfig checks the supplied config for correctness.
-func (d *unixHotplug) validateConfig() error {
- if d.inst.Type() != instancetype.Container {
+func (d *unixHotplug) validateConfig(instConf instance.ConfigReader) error {
+ if !instanceSupported(instConf.Type(), instancetype.Container) {
return ErrUnsupportedDevType
}
diff --git a/lxd/device/usb.go b/lxd/device/usb.go
index fd42b33f45..161f79a478 100644
--- a/lxd/device/usb.go
+++ b/lxd/device/usb.go
@@ -8,6 +8,7 @@ import (
"strings"
deviceConfig "github.com/lxc/lxd/lxd/device/config"
+ "github.com/lxc/lxd/lxd/instance"
"github.com/lxc/lxd/lxd/instance/instancetype"
"github.com/lxc/lxd/shared"
)
@@ -42,8 +43,8 @@ func (d *usb) isRequired() bool {
}
// validateConfig checks the supplied config for correctness.
-func (d *usb) validateConfig() error {
- if d.inst.Type() != instancetype.Container {
+func (d *usb) validateConfig(instConf instance.ConfigReader) error {
+ if !instanceSupported(instConf.Type(), instancetype.Container) {
return ErrUnsupportedDevType
}
More information about the lxc-devel
mailing list