[lxc-devel] [lxd/master] liblxc: detect version at runtime

brauner on Github lxc-bot at linuxcontainers.org
Mon Oct 30 14:34:09 UTC 2017


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 425 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20171030/3405f27e/attachment.bin>
-------------- next part --------------
From d09be5aaddf3173e9c756a68cadfb369c563fcc5 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Mon, 30 Oct 2017 15:32:48 +0100
Subject: [PATCH] liblxc: detect version at runtime

This requires us to link against liblxc.

Closes #3934.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 lxd/container_lxc.go | 20 +++++++--------
 lxd/migrate.go       |  2 +-
 shared/util_linux.go | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 81 insertions(+), 12 deletions(-)

diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 0efecaf91..880221133 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -109,7 +109,7 @@ func lxcSetConfigItem(c *lxc.Container, key string, value string) error {
 		return fmt.Errorf("Uninitialized go-lxc struct")
 	}
 
-	if !lxc.VersionAtLeast(2, 1, 0) {
+	if !shared.RuntimeLiblxcVersionAtLeast(2, 1, 0) {
 		switch key {
 		case "lxc.uts.name":
 			key = "lxc.utsname"
@@ -155,7 +155,7 @@ func lxcSetConfigItem(c *lxc.Container, key string, value string) error {
 	}
 
 	if strings.HasPrefix(key, "lxc.prlimit.") {
-		if !lxc.VersionAtLeast(2, 1, 0) {
+		if !shared.RuntimeLiblxcVersionAtLeast(2, 1, 0) {
 			return fmt.Errorf(`Process limits require libxc >= 2.1`)
 		}
 	}
@@ -211,7 +211,7 @@ func lxcValidConfig(rawLxc string) error {
 		}
 
 		networkKeyPrefix := "lxc.net."
-		if !lxc.VersionAtLeast(2, 1, 0) {
+		if !shared.RuntimeLiblxcVersionAtLeast(2, 1, 0) {
 			networkKeyPrefix = "lxc.network."
 		}
 
@@ -219,7 +219,7 @@ func lxcValidConfig(rawLxc string) error {
 			fields := strings.Split(key, ".")
 
 			allowedIPKeys := []string{"ipv4.address", "ipv6.address"}
-			if !lxc.VersionAtLeast(2, 1, 0) {
+			if !shared.RuntimeLiblxcVersionAtLeast(2, 1, 0) {
 				allowedIPKeys = []string{"ipv4", "ipv6"}
 			}
 
@@ -1340,7 +1340,7 @@ func (c *containerLXC) initLXC() error {
 			}
 
 			networkKeyPrefix := "lxc.net"
-			if !lxc.VersionAtLeast(2, 1, 0) {
+			if !shared.RuntimeLiblxcVersionAtLeast(2, 1, 0) {
 				networkKeyPrefix = "lxc.network"
 			}
 
@@ -1452,7 +1452,7 @@ func (c *containerLXC) initLXC() error {
 
 			// Deal with a rootfs
 			if tgtPath == "" {
-				if !lxc.VersionAtLeast(2, 1, 0) {
+				if !shared.RuntimeLiblxcVersionAtLeast(2, 1, 0) {
 					// Set the rootfs backend type if supported (must happen before any other lxc.rootfs)
 					err := lxcSetConfigItem(cc, "lxc.rootfs.backend", "dir")
 					if err == nil {
@@ -1464,7 +1464,7 @@ func (c *containerLXC) initLXC() error {
 				}
 
 				// Set the rootfs path
-				if lxc.VersionAtLeast(2, 1, 0) {
+				if shared.RuntimeLiblxcVersionAtLeast(2, 1, 0) {
 					rootfsPath := fmt.Sprintf("dir:%s", c.RootfsPath())
 					err = lxcSetConfigItem(cc, "lxc.rootfs.path", rootfsPath)
 				} else {
@@ -1922,7 +1922,7 @@ func (c *containerLXC) startCommon() (string, error) {
 			}
 		} else if m["type"] == "nic" {
 			networkKeyPrefix := "lxc.net"
-			if !lxc.VersionAtLeast(2, 1, 0) {
+			if !shared.RuntimeLiblxcVersionAtLeast(2, 1, 0) {
 				networkKeyPrefix = "lxc.network"
 			}
 
@@ -4487,7 +4487,7 @@ func (c *containerLXC) Migrate(cmd uint, stateDir string, function string, stop
 	/* This feature was only added in 2.0.1, let's not ask for it
 	 * before then or migrations will fail.
 	 */
-	if !lxc.VersionAtLeast(2, 0, 1) {
+	 if !shared.RuntimeLiblxcVersionAtLeast(2, 0, 1) {
 		preservesInodes = false
 	}
 
@@ -6922,7 +6922,7 @@ func (c *containerLXC) setNetworkPriority() error {
 func (c *containerLXC) getHostInterface(name string) string {
 	if c.IsRunning() {
 		networkKeyPrefix := "lxc.net"
-		if !lxc.VersionAtLeast(2, 1, 0) {
+		if !shared.RuntimeLiblxcVersionAtLeast(2, 1, 0) {
 			networkKeyPrefix = "lxc.network"
 		}
 
diff --git a/lxd/migrate.go b/lxd/migrate.go
index 555fb0714..197d25a1e 100644
--- a/lxd/migrate.go
+++ b/lxd/migrate.go
@@ -486,7 +486,7 @@ func (s *migrationSourceWs) Do(migrateOp *operation) error {
 			return abort(err)
 		}
 
-		if lxc.VersionAtLeast(2, 0, 4) {
+		if shared.RuntimeLiblxcVersionAtLeast(2, 0, 4) {
 			/* What happens below is slightly convoluted. Due to various
 			 * complications with networking, there's no easy way for criu
 			 * to exit and leave the container in a frozen state for us to
diff --git a/shared/util_linux.go b/shared/util_linux.go
index 78d782924..80e2de9f2 100644
--- a/shared/util_linux.go
+++ b/shared/util_linux.go
@@ -12,6 +12,7 @@ import (
 	"path/filepath"
 	"reflect"
 	"strings"
+	"strconv"
 	"sync"
 	"sync/atomic"
 	"syscall"
@@ -20,7 +21,7 @@ import (
 	"github.com/lxc/lxd/shared/logger"
 )
 
-// #cgo LDFLAGS: -lutil -lpthread
+// #cgo LDFLAGS: -lutil -lpthread -llxc
 /*
 #define _GNU_SOURCE
 #include <errno.h>
@@ -37,6 +38,7 @@ import (
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/un.h>
+#include <lxc/lxccontainer.h>
 
 #ifndef AT_SYMLINK_FOLLOW
 #define AT_SYMLINK_FOLLOW    0x400
@@ -864,3 +866,70 @@ func Statvfs(path string) (*syscall.Statfs_t, error) {
 
 	return &st, nil
 }
+
+func RuntimeLiblxcVersionAtLeast(major int, minor int, micro int) bool {
+	version := C.GoString(C.lxc_get_version())
+	parts := strings.Split(version, ".")
+	partsLen := len(parts)
+	if partsLen == 0 {
+		return false
+	}
+
+	develParts := strings.Split(parts[partsLen - 1], "-")
+	if len(develParts) == 2 && develParts[1] == "devel" {
+		return true
+	}
+
+	maj := -1
+	min := -1
+	mic := -1
+
+	for i, v := range parts {
+		num, err := strconv.Atoi(v)
+		if err != nil {
+			return false
+		}
+
+		if i > 2 {
+			return false
+		}
+
+		switch i {
+		case 0:
+			maj = num
+		case 1:
+			min = num
+		case 2:
+			mic = num
+		}
+	}
+
+	/* Major version is greater. */
+	if maj > major {
+		return true
+	}
+
+	if maj < major {
+		return false
+	}
+
+	/* Minor number is greater.*/
+	if min > minor {
+		return true
+	}
+
+	if min < minor {
+		return false
+	}
+
+	/* Patch number is greater. */
+	if mic > micro {
+		return true
+	}
+
+	if mic < micro {
+		return false
+	}
+
+	return true
+}


More information about the lxc-devel mailing list