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

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) ===
As requested, this is a draft pull request for issue #7869, having implemented most of the things mentioned in the most recent comments.

As noted in the description of commit ead2141 the Info() function in driver_qemu.go isn't quite working yet, there's some runtime bugs that I haven't sorted out relating to finding the path of the qemu binary.

Additionally, there seems to be some kind of race condition in the creation of the driver cache, as either ``lxc`` or ``qemu`` can end up appearing first in the list, though I am unsure where this would be generated so it is not listed in any particular commit.
From f74d2cd2be44a6f79e5629b5d50a56af0c9df8b4 Mon Sep 17 00:00:00 2001
From: Alex Oliver <oliver.ale...@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.ale...@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.ale...@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.ale...@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.ale...@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.ale...@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.ale...@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.ale...@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.ale...@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.ale...@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.ale...@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.ale...@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.ale...@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.ale...@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,
+       }
+}
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to