[lxc-devel] [lxd/master] Wester162

wester162 on Github lxc-bot at linuxcontainers.org
Thu Nov 26 00:40:04 UTC 2020


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 915 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20201125/e83a857d/attachment.bin>
-------------- next part --------------
From f74d2cd2be44a6f79e5629b5d50a56af0c9df8b4 Mon Sep 17 00:00:00 2001
From: Alex Oliver <oliver.alex96 at gmail.com>
Date: Sat, 21 Nov 2020 20:17:37 -0600
Subject: [PATCH 1/7] lxd/instance: WIP support for cached drivers in /1.0

Implemented functions based on the storagePoolDriversCache system to create
a cache for the lxd/qemu drivers, working on issue #7869. Because there are
only two drivers to be added at this point, the creation of the cache is
hard-coded to only include LXC/QEMU, though this could be expanded similar
to the storage pool at a later date.

The current implementation's QEMU path is hard-coded to a known functional
value on my local system to ensure that the caching functionality works,
and a final version will need to pull the value of qemuBinary (/qemuPath?)
as described in the issue comments on github.

Signed-off-by: Alex J Oliver <oliver.alex96 at gmail.com>
---
 lxd/instance.go | 63 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/lxd/instance.go b/lxd/instance.go
index 45aed86b17..674ffa890e 100644
--- a/lxd/instance.go
+++ b/lxd/instance.go
@@ -8,6 +8,8 @@ import (
 	"path/filepath"
 	"strconv"
 	"strings"
+	"sync"
+	"sync/atomic"
 	"time"
 
 	"github.com/pkg/errors"
@@ -932,3 +934,64 @@ func containerDetermineNextSnapshotName(d *Daemon, c instance.Instance, defaultP
 
 	return pattern, nil
 }
+
+// Instance Driver Cache
+// I don't forsee anything trying to simultaneously edit/read these values, but in a case of Cargo Cult Programming I'm going to go ahead
+// and use the atomic value setup from the storage cache for the time being. Worst case it's a very tiny performance hit?
+var instanceDriversCacheVal atomic.Value
+var instanceDriversCacheLock sync.Mutex
+
+// Declare qemuBinary so it can be set by qemuStart for use here
+var qemuPath string = "qemu-system-x86_64" //hard coded value is for testing purposes only
+
+//SetQemuPath Setter function for the qemuPath variable
+//Attempts to call this from driver_qemu.go result in it being an undefined function in that scope.
+//Clearly I'm doing something wrong.
+func SetQemuPath(path string) {
+	qemuPath = path
+	return
+}
+
+func readInstanceDriversCache() map[string]string {
+	// Get the cached list of instance drivers in use on this LXD instance
+	// and call Create if the cache is empty.
+
+	drivers := instanceDriversCacheVal.Load()
+	if drivers == nil {
+		createInstanceDriversCache()
+		drivers = instanceDriversCacheVal.Load()
+	}
+
+	return drivers.(map[string]string)
+}
+
+func createInstanceDriversCache() {
+	// Create the list of instance drivers in use on this LXD instance
+	// namely LXC and QEMU. Given that LXC and QEMU cannot update while
+	// the LXD instance is running, this shouldn't ever be called more
+	// than once.
+
+	data := map[string]string{}
+
+	// Get LXC driver information
+	data["lxc"] = liblxc.Version()
+
+	// Get QEMU driver information
+
+	//Need to update this to use qemuBinary properly. There's also likely a more graceful way of doing the byte slice -> string conversion
+	out, err := exec.Command(qemuPath, "--version").Output()
+
+	if err != nil {
+		data["qemu"] = "0"
+	} else {
+		fieldOut := strings.Fields(string(out))
+		data["qemu"] = fieldOut[3]
+	}
+
+	//Store the value in the cache
+	instanceDriversCacheLock.Lock()
+	instanceDriversCacheVal.Store(data)
+	instanceDriversCacheLock.Unlock()
+
+	return
+}

From 72956b3a3dbfefa4225014f21d239c24c4669455 Mon Sep 17 00:00:00 2001
From: Alex Oliver <oliver.alex96 at gmail.com>
Date: Sat, 21 Nov 2020 20:17:59 -0600
Subject: [PATCH 2/7] lxd/api_1.0: Add support for cached driver values

Pulls the Driver and DriverVersion values from a cache to prevent
hitting go-lxc repeatedly. Supports any additional drivers present
in the cache, such as qemu.

Signed-off-by: Alex J Oliver <oliver.alex96 at gmail.com>
---
 lxd/api_1.0.go | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/lxd/api_1.0.go b/lxd/api_1.0.go
index 72212579a2..cac3539e4d 100644
--- a/lxd/api_1.0.go
+++ b/lxd/api_1.0.go
@@ -6,8 +6,6 @@ import (
 	"os"
 	"strings"
 
-	liblxc "gopkg.in/lxc/go-lxc.v2"
-
 	lxd "github.com/lxc/lxd/client"
 	"github.com/lxc/lxd/lxd/cluster"
 	"github.com/lxc/lxd/lxd/config"
@@ -201,8 +199,6 @@ func api10Get(d *Daemon, r *http.Request) response.Response {
 		Architectures:          architectures,
 		Certificate:            certificate,
 		CertificateFingerprint: certificateFingerprint,
-		Driver:                 "lxc",
-		DriverVersion:          liblxc.Version(),
 		Kernel:                 uname.Sysname,
 		KernelArchitecture:     uname.Machine,
 		KernelVersion:          uname.Release,
@@ -226,6 +222,22 @@ func api10Get(d *Daemon, r *http.Request) response.Response {
 		"shiftfs":                   fmt.Sprintf("%v", d.os.Shiftfs),
 	}
 
+	instanceDrivers := readInstanceDriversCache()
+	for driver, version := range instanceDrivers {
+		if env.Driver != "" {
+			env.Driver = env.Driver + " | " + driver
+		} else {
+			env.Driver = driver
+		}
+
+		// Get the version of the instance drivers in use.
+		if env.DriverVersion != "" {
+			env.DriverVersion = env.DriverVersion + " | " + version
+		} else {
+			env.DriverVersion = version
+		}
+	}
+
 	if d.os.LXCFeatures != nil {
 		env.LXCFeatures = map[string]string{}
 		for k, v := range d.os.LXCFeatures {

From 79de4e522f0bef3c29803a200b2f02b970a0ec7b Mon Sep 17 00:00:00 2001
From: Alex Oliver <oliver.alex96 at gmail.com>
Date: Wed, 25 Nov 2020 18:04:01 -0600
Subject: [PATCH 3/7] lxd/instance: Add support for Info() to Instance
 interface

Signed-off-by: Alex J Oliver <oliver.alex96 at gmail.com>
---
 lxd/instance/instance_interface.go | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/lxd/instance/instance_interface.go b/lxd/instance/instance_interface.go
index c096230bf3..d6d94d6d99 100644
--- a/lxd/instance/instance_interface.go
+++ b/lxd/instance/instance_interface.go
@@ -57,6 +57,7 @@ type Instance interface {
 	RegisterDevices()
 	SaveConfigFile() error
 
+	Info() Info
 	IsPrivileged() bool
 
 	// Snapshots & migration & backups.
@@ -164,3 +165,9 @@ type CriuMigrationArgs struct {
 	PreDumpDir   string
 	Features     liblxc.CriuFeatures
 }
+
+// Info represents information about an instance driver.
+type Info struct {
+	Name    string // Name of an instance driver, e.g. "lxc"
+	Version string // Version number of a loaded instance driver
+}

From 257cfd19bba4d9bf6d60a29de8e48fa737c8e1ce Mon Sep 17 00:00:00 2001
From: Alex Oliver <oliver.alex96 at gmail.com>
Date: Wed, 25 Nov 2020 18:06:19 -0600
Subject: [PATCH 4/7] lxd/instance/drivers: Implement Info() function

Signed-off-by: Alex J Oliver <oliver.alex96 at gmail.com>
---
 lxd/instance/drivers/driver_lxc.go | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/lxd/instance/drivers/driver_lxc.go b/lxd/instance/drivers/driver_lxc.go
index 054c698372..db680fe9e7 100644
--- a/lxd/instance/drivers/driver_lxc.go
+++ b/lxd/instance/drivers/driver_lxc.go
@@ -7042,3 +7042,11 @@ func (c *lxc) SaveConfigFile() error {
 
 	return nil
 }
+
+// Returns "lxc" and the currently loaded version of LXC
+func (c *lxc) Info() instance.Info {
+	return instance.Info{
+		Name:    "lxc",
+		Version: liblxc.Version(),
+	}
+}

From c159ffb80233550cb6c196fe39aa8137c7d74e32 Mon Sep 17 00:00:00 2001
From: Alex Oliver <oliver.alex96 at gmail.com>
Date: Wed, 25 Nov 2020 18:09:41 -0600
Subject: [PATCH 5/7] lxd/instance/drivers: Add drivers package support for
 supported drivers.

Signed-off-by: Alex J Oliver <oliver.alex96 at gmail.com>
---
 lxd/instance/drivers/load.go | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/lxd/instance/drivers/load.go b/lxd/instance/drivers/load.go
index f478c75ed4..757032f351 100644
--- a/lxd/instance/drivers/load.go
+++ b/lxd/instance/drivers/load.go
@@ -15,6 +15,11 @@ import (
 	"github.com/lxc/lxd/shared/api"
 )
 
+var instanceDrivers = map[string]func() instance.Instance{
+	"lxc":  func() instance.Instance { return &lxc{} },
+	"qemu": func() instance.Instance { return &qemu{} },
+}
+
 func init() {
 	// Expose load to the instance package, to avoid circular imports.
 	instance.Load = load
@@ -96,3 +101,15 @@ func create(s *state.State, args db.InstanceArgs) (instance.Instance, error) {
 
 	return nil, fmt.Errorf("Instance type invalid")
 }
+
+// SupportedInstanceDrivers returns a slice of Info structs for all supported drivers
+func SupportedInstanceDrivers() []instance.Info {
+	supportedDrivers := make([]instance.Info, 0, len(instanceDrivers))
+
+	for _, instanceDriver := range instanceDrivers {
+		driver := instanceDriver()
+		supportedDrivers = append(supportedDrivers, driver.Info())
+	}
+
+	return supportedDrivers
+}

From f2f193362cafbd0badef81d7d812f19fa65e3b9e Mon Sep 17 00:00:00 2001
From: Alex Oliver <oliver.alex96 at gmail.com>
Date: Wed, 25 Nov 2020 18:12:35 -0600
Subject: [PATCH 6/7] lxd/main: Remove driver-specific logic from instance.go

Signed-off-by: Alex J Oliver <oliver.alex96 at gmail.com>
---
 lxd/instance.go | 36 +++++-------------------------------
 1 file changed, 5 insertions(+), 31 deletions(-)

diff --git a/lxd/instance.go b/lxd/instance.go
index 674ffa890e..a4813a7922 100644
--- a/lxd/instance.go
+++ b/lxd/instance.go
@@ -21,6 +21,7 @@ import (
 	"github.com/lxc/lxd/lxd/db"
 	deviceConfig "github.com/lxc/lxd/lxd/device/config"
 	"github.com/lxc/lxd/lxd/instance"
+	"github.com/lxc/lxd/lxd/instance/drivers"
 	"github.com/lxc/lxd/lxd/instance/instancetype"
 	"github.com/lxc/lxd/lxd/operations"
 	"github.com/lxc/lxd/lxd/project"
@@ -935,26 +936,10 @@ func containerDetermineNextSnapshotName(d *Daemon, c instance.Instance, defaultP
 	return pattern, nil
 }
 
-// Instance Driver Cache
-// I don't forsee anything trying to simultaneously edit/read these values, but in a case of Cargo Cult Programming I'm going to go ahead
-// and use the atomic value setup from the storage cache for the time being. Worst case it's a very tiny performance hit?
 var instanceDriversCacheVal atomic.Value
 var instanceDriversCacheLock sync.Mutex
 
-// Declare qemuBinary so it can be set by qemuStart for use here
-var qemuPath string = "qemu-system-x86_64" //hard coded value is for testing purposes only
-
-//SetQemuPath Setter function for the qemuPath variable
-//Attempts to call this from driver_qemu.go result in it being an undefined function in that scope.
-//Clearly I'm doing something wrong.
-func SetQemuPath(path string) {
-	qemuPath = path
-	return
-}
-
 func readInstanceDriversCache() map[string]string {
-	// Get the cached list of instance drivers in use on this LXD instance
-	// and call Create if the cache is empty.
 
 	drivers := instanceDriversCacheVal.Load()
 	if drivers == nil {
@@ -968,24 +953,13 @@ func readInstanceDriversCache() map[string]string {
 func createInstanceDriversCache() {
 	// Create the list of instance drivers in use on this LXD instance
 	// namely LXC and QEMU. Given that LXC and QEMU cannot update while
-	// the LXD instance is running, this shouldn't ever be called more
-	// than once.
+	// the LXD instance is running, only one cache is ever needed.
 
 	data := map[string]string{}
 
-	// Get LXC driver information
-	data["lxc"] = liblxc.Version()
-
-	// Get QEMU driver information
-
-	//Need to update this to use qemuBinary properly. There's also likely a more graceful way of doing the byte slice -> string conversion
-	out, err := exec.Command(qemuPath, "--version").Output()
-
-	if err != nil {
-		data["qemu"] = "0"
-	} else {
-		fieldOut := strings.Fields(string(out))
-		data["qemu"] = fieldOut[3]
+	info := drivers.SupportedInstanceDrivers()
+	for _, entry := range info {
+		data[entry.Name] = entry.Version
 	}
 
 	//Store the value in the cache

From ead2141f80ca05346b012c4f0bf59618103f1051 Mon Sep 17 00:00:00 2001
From: Alex Oliver <oliver.alex96 at gmail.com>
Date: Wed, 25 Nov 2020 18:26:30 -0600
Subject: [PATCH 7/7] lxd/instance/drivers: Implement Info() in driver_qemu.go

There seems to be some kind of runtime bug in the code where the
vm.architecture value is 0 when in this function, and as a result
the binary for qemu cannot be found, and the version number cannot
be properly found.

Bug is reproducable on a system with qemu version 4.2.1 installed

Signed-off-by: Alex J Oliver <oliver.alex96 at gmail.com>
---
 lxd/instance/drivers/driver_qemu.go | 49 +++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/lxd/instance/drivers/driver_qemu.go b/lxd/instance/drivers/driver_qemu.go
index abd05b2e85..c10c116e97 100644
--- a/lxd/instance/drivers/driver_qemu.go
+++ b/lxd/instance/drivers/driver_qemu.go
@@ -5157,3 +5157,52 @@ func (vm *qemu) writeInstanceData() error {
 
 	return nil
 }
+
+// Returns "qemu" and the currently loaded qemu version, 0 if not found.
+// Unsure if this is the proper behavior for a not found, but the logic is there.
+// TODO: This seems to be getting a 0 value for vm.architecture, and as a result cannot find the binary, giving a 0 for the version no.
+func (vm *qemu) Info() instance.Info {
+
+	var qemuVersion, qemuBinary, qemuPath string
+	var out []byte
+	var err error
+	qemuBinary, _, err = vm.qemuArchConfig()
+	println("vm architecture ", vm.architecture)
+	println("qemuBinary: " + qemuBinary)
+	if err == nil {
+		qemuPath, err = exec.LookPath(qemuBinary)
+		if err == nil {
+			out, err = exec.Command(qemuPath, "--version").Output()
+			if err != nil {
+				qemuVersion = "0"
+			} else {
+				qemuVersion = strings.Fields(string(out))[3]
+			}
+		} else {
+			qemuVersion = "-1"
+		}
+	} else {
+		qemuVersion = "-2"
+	}
+	// if err != nil {
+	// 	qemuVersion = "0"
+	// 	println("QEMUBINARY ERROR %d", err)
+	// }
+
+	// qemuPath, err := exec.LookPath(qemuBinary)
+	// if err != nil {
+	// 	qemuVersion = "0"
+	// }
+
+	//out, err = exec.Command(qemuPath, "--version").Output()
+	// if err != nil {
+	// 	qemuVersion = "0"
+	// } else {
+	// 	qemuVersion = strings.Fields(string(out))[3]
+	// }
+
+	return instance.Info{
+		Name:    "qemu",
+		Version: qemuVersion,
+	}
+}


More information about the lxc-devel mailing list