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

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) ===

From 481a238a5c3b79530e89c71b044914a6eb41faeb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com>
Date: Wed, 17 Jun 2020 11:58:42 -0400
Subject: [PATCH 1/6] lxd/resources: Fix golint warning
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgra...@ubuntu.com>
---
 lxd/resources/memory.go | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/lxd/resources/memory.go b/lxd/resources/memory.go
index 4a6544a659..b948f39e3b 100644
--- a/lxd/resources/memory.go
+++ b/lxd/resources/memory.go
@@ -153,14 +153,13 @@ func getTotalMemory() uint64 {
                return 0
        }
 
-       var count uint64 = 0
-
        entries, err := ioutil.ReadDir(sysDevicesSystemMemory)
        if err != nil {
                return 0
        }
 
        // Count the number of blocks
+       var count uint64
        for _, entry := range entries {
                // Only consider directories
                if !entry.IsDir() {

From cafae2434c4f0b64463f7abb9494f561549f5328 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com>
Date: Wed, 17 Jun 2020 12:06:29 -0400
Subject: [PATCH 2/6] doc/api-extensions: Fix escaping
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgra...@ubuntu.com>
---
 doc/api-extensions.md | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/doc/api-extensions.md b/doc/api-extensions.md
index ffe908dc68..4c3fbc1542 100644
--- a/doc/api-extensions.md
+++ b/doc/api-extensions.md
@@ -977,17 +977,17 @@ This adds a new `size` field to the output of 
`/1.0/instances/<name>/snapshots/<
 This adds a writable endpoint for cluster members, allowing the editing of 
their roles.
 
 ## container\_nic\_routed\_host\_address
-This introduces the `ipv4.host_address` and `ipv6.host_address` NIC config 
keys that can be used to control the
+This introduces the `ipv4.host\_address` and `ipv6.host\_address` NIC config 
keys that can be used to control the
 host-side veth interface's IP addresses. This can be useful when using 
multiple routed NICs at the same time and
 needing a predictable next-hop address to use.
 
 This also alters the behaviour of `ipv4.gateway` and `ipv6.gateway` NIC config 
keys. When they are set to "auto"
-the container will have its default gateway set to the value of 
`ipv4.host_address` or `ipv6.host_address` respectively.
+the container will have its default gateway set to the value of 
`ipv4.host\_address` or `ipv6.host\_address` respectively.
 
 The default values are:
 
-`ipv4.host_address`: 169.254.0.1
-`ipv6.host_address`: fe80::1
+`ipv4.host\_address`: 169.254.0.1
+`ipv6.host\_address`: fe80::1
 
 This is backward compatible with the previous default behaviour.
 
@@ -1015,11 +1015,11 @@ This introduces two new fields in `/1.0`, `os` and 
`os\_version`.
 Those are taken from the os-release data on the system.
 
 ## container\_nic\_routed\_host\_table
-This introduces the `ipv4.host_table` and `ipv6.host_table` NIC config keys 
that can be used to add static routes
+This introduces the `ipv4.host\_table` and `ipv6.host\_table` NIC config keys 
that can be used to add static routes
 for the instance's IPs to a custom policy routing table by ID.
 
 ## container\_nic\_ipvlan\_host\_table
-This introduces the `ipv4.host_table` and `ipv6.host_table` NIC config keys 
that can be used to add static routes
+This introduces the `ipv4.host\_table` and `ipv6.host\_table` NIC config keys 
that can be used to add static routes
 for the instance's IPs to a custom policy routing table by ID.
 
 ## container\_nic\_ipvlan\_mode

From fb3583c9b612ede7dd7d49cae5b472c6b8ce3a0c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com>
Date: Wed, 17 Jun 2020 12:08:18 -0400
Subject: [PATCH 3/6] api: resource_cpu_isolated
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgra...@ubuntu.com>
---
 doc/api-extensions.md  | 4 ++++
 shared/api/resource.go | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/doc/api-extensions.md b/doc/api-extensions.md
index 4c3fbc1542..a5d7c6a655 100644
--- a/doc/api-extensions.md
+++ b/doc/api-extensions.md
@@ -1073,3 +1073,7 @@ Bridge:
  - Default VLAN
  - VLAN filtering
  - Upper devices
+
+## resources\_cpu\_isolated
+Add an `Isolated` property on CPU threads to indicate if the thread is
+physically `Online` but is configured not to accept tasks.
diff --git a/shared/api/resource.go b/shared/api/resource.go
index 2942972513..0a97eae196 100644
--- a/shared/api/resource.go
+++ b/shared/api/resource.go
@@ -74,6 +74,9 @@ type ResourcesCPUThread struct {
        NUMANode uint64 `json:"numa_node" yaml:"numa_node"`
        Thread   uint64 `json:"thread" yaml:"thread"`
        Online   bool   `json:"online" yaml:"online"`
+
+       // API extension: resource_cpu_isolated
+       Isolated bool   `json:"isolated" yaml:"isolated"`
 }
 
 // ResourcesGPU represents the GPU resources available on the system

From 3f4fe3d2e4024843c996a2cb20277e71626d6e39 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com>
Date: Wed, 17 Jun 2020 12:09:03 -0400
Subject: [PATCH 4/6] lxd/resources: Add Isolated property
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgra...@ubuntu.com>
---
 lxd/resources/cpu.go   | 66 ++++++++++++++++++++++++++++++++++++++++++
 lxd/resources/utils.go |  9 ++++++
 shared/api/resource.go |  2 +-
 3 files changed, 76 insertions(+), 1 deletion(-)

diff --git a/lxd/resources/cpu.go b/lxd/resources/cpu.go
index 148bddfba7..70536f29f6 100644
--- a/lxd/resources/cpu.go
+++ b/lxd/resources/cpu.go
@@ -18,6 +18,68 @@ import (
 
 var sysDevicesCPU = "/sys/devices/system/cpu"
 
+// GetCPUIsolated returns a slice of IDs corresponding to isolated threads.
+func GetCPUIsolated() []int64 {
+       isolatedPath := filepath.Join(sysDevicesCPU, "isolated")
+
+       isolatedCpusInt := []int64{}
+       if sysfsExists(isolatedPath) {
+               buf, err := ioutil.ReadFile(isolatedPath)
+               if err != nil {
+                       return isolatedCpusInt
+               }
+
+               // File might exist even though there are no isolated cpus.
+               isolatedCpus := strings.TrimSpace(string(buf))
+               if isolatedCpus != "" {
+                       isolatedCpusInt, err = ParseCpuset(isolatedCpus)
+                       if err != nil {
+                               return isolatedCpusInt
+                       }
+               }
+       }
+
+       return isolatedCpusInt
+}
+
+// ParseCpuset parses a limits.cpu range into a list of CPU ids.
+func ParseCpuset(cpu string) ([]int64, error) {
+       cpus := []int64{}
+       chunks := strings.Split(cpu, ",")
+       for _, chunk := range chunks {
+               if strings.Contains(chunk, "-") {
+                       // Range
+                       fields := strings.SplitN(chunk, "-", 2)
+                       if len(fields) != 2 {
+                               return nil, fmt.Errorf("Invalid cpuset value: 
%s", cpu)
+                       }
+
+                       low, err := strconv.ParseInt(fields[0], 10, 64)
+                       if err != nil {
+                               return nil, fmt.Errorf("Invalid cpuset value: 
%s", cpu)
+                       }
+
+                       high, err := strconv.ParseInt(fields[1], 10, 64)
+                       if err != nil {
+                               return nil, fmt.Errorf("Invalid cpuset value: 
%s", cpu)
+                       }
+
+                       for i := low; i <= high; i++ {
+                               cpus = append(cpus, i)
+                       }
+               } else {
+                       // Simple entry
+                       nr, err := strconv.ParseInt(chunk, 10, 64)
+                       if err != nil {
+                               return nil, fmt.Errorf("Invalid cpuset value: 
%s", cpu)
+                       }
+                       cpus = append(cpus, nr)
+               }
+       }
+
+       return cpus, nil
+}
+
 func getCPUCache(path string) ([]api.ResourcesCPUCache, error) {
        caches := []api.ResourcesCPUCache{}
 
@@ -92,6 +154,9 @@ func getCPUCache(path string) ([]api.ResourcesCPUCache, 
error) {
 func GetCPU() (*api.ResourcesCPU, error) {
        cpu := api.ResourcesCPU{}
 
+       // Get the isolated CPUs
+       isolated := GetCPUIsolated()
+
        // Temporary storage
        cpuSockets := map[uint64]*api.ResourcesCPUSocket{}
        cpuCores := map[uint64]map[string]*api.ResourcesCPUCore{}
@@ -299,6 +364,7 @@ func GetCPU() (*api.ResourcesCPU, error) {
                        }
                }
                thread.ID = threadNumber
+               thread.Isolated = int64InSlice(threadNumber, isolated)
                thread.Thread = uint64(len(resCore.Threads))
 
                // NUMA node
diff --git a/lxd/resources/utils.go b/lxd/resources/utils.go
index 8290b5c6ab..e5335e03e0 100644
--- a/lxd/resources/utils.go
+++ b/lxd/resources/utils.go
@@ -47,6 +47,15 @@ func stringInSlice(key string, list []string) bool {
        return false
 }
 
+func int64InSlice(key int64, list []int64) bool {
+       for _, entry := range list {
+               if entry == key {
+                       return true
+               }
+       }
+       return false
+}
+
 func sysfsExists(path string) bool {
        _, err := os.Lstat(path)
        if err == nil {
diff --git a/shared/api/resource.go b/shared/api/resource.go
index 0a97eae196..4ccefc43eb 100644
--- a/shared/api/resource.go
+++ b/shared/api/resource.go
@@ -76,7 +76,7 @@ type ResourcesCPUThread struct {
        Online   bool   `json:"online" yaml:"online"`
 
        // API extension: resource_cpu_isolated
-       Isolated bool   `json:"isolated" yaml:"isolated"`
+       Isolated bool `json:"isolated" yaml:"isolated"`
 }
 
 // ResourcesGPU represents the GPU resources available on the system

From b448225849304e84fa2514893b5f50d295a5389a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com>
Date: Wed, 17 Jun 2020 12:21:01 -0400
Subject: [PATCH 5/6] lxd/resources: Don't use shared
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgra...@ubuntu.com>
---
 lxd/resources/system.go | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/lxd/resources/system.go b/lxd/resources/system.go
index bf0a7f494d..a074b54888 100644
--- a/lxd/resources/system.go
+++ b/lxd/resources/system.go
@@ -9,7 +9,6 @@ import (
 
        "github.com/pkg/errors"
 
-       "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
 )
 
@@ -134,14 +133,19 @@ func systemGetType() string {
                return "unknown"
        }
 
+       runDetectVirt := func(flag string) error {
+               cmd := exec.Command("systemd-detect-virt", flag)
+               return cmd.Run()
+       }
+
        // If this returns 0, we're in a container.
-       _, err = shared.RunCommand("systemd-detect-virt", "--container")
+       err = runDetectVirt("--container")
        if err == nil {
                return "container"
        }
 
        // If this returns 0, we're in a VM.
-       _, err = shared.RunCommand("systemd-detect-virt", "--vm")
+       err = runDetectVirt("--vm")
        if err == nil {
                return "virtual-machine"
        }

From 64acf92527cc0a04c31ea3a4d17e89f47bd71ea4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com>
Date: Wed, 17 Jun 2020 12:41:51 -0400
Subject: [PATCH 6/6] lxd/devices: Use resources for cpuset parsing
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgra...@ubuntu.com>
---
 lxd/devices.go                      | 38 ++++++++---------------------
 lxd/instance/drivers/driver_qemu.go |  2 +-
 lxd/instance/instance_utils.go      | 37 ----------------------------
 3 files changed, 11 insertions(+), 66 deletions(-)

diff --git a/lxd/devices.go b/lxd/devices.go
index 3442765652..65aa81ec44 100644
--- a/lxd/devices.go
+++ b/lxd/devices.go
@@ -2,7 +2,6 @@ package main
 
 import (
        "fmt"
-       "io/ioutil"
        "os"
        "path"
        "path/filepath"
@@ -16,6 +15,7 @@ import (
        "github.com/lxc/lxd/lxd/device"
        "github.com/lxc/lxd/lxd/instance"
        "github.com/lxc/lxd/lxd/instance/instancetype"
+       "github.com/lxc/lxd/lxd/resources"
        "github.com/lxc/lxd/lxd/state"
        "github.com/lxc/lxd/shared"
        log "github.com/lxc/lxd/shared/log15"
@@ -55,7 +55,7 @@ static int get_hidraw_devinfo(int fd, struct hidraw_devinfo 
*info)
 import "C"
 
 type deviceTaskCPU struct {
-       id    int
+       id    int64
        strId string
        count *int
 }
@@ -337,34 +337,16 @@ func deviceTaskBalance(s *state.State) {
                }
        }
 
-       effectiveCpusInt, err := instance.ParseCpuset(effectiveCpus)
+       effectiveCpusInt, err := resources.ParseCpuset(effectiveCpus)
        if err != nil {
                logger.Errorf("Error parsing effective CPU set")
                return
        }
 
-       isolatedCpusInt := []int{}
-       if shared.PathExists("/sys/devices/system/cpu/isolated") {
-               buf, err := ioutil.ReadFile("/sys/devices/system/cpu/isolated")
-               if err != nil {
-                       logger.Errorf("Error reading host's isolated cpu")
-                       return
-               }
-
-               // File might exist even though there are no isolated cpus.
-               isolatedCpus := strings.TrimSpace(string(buf))
-               if isolatedCpus != "" {
-                       isolatedCpusInt, err = 
instance.ParseCpuset(isolatedCpus)
-                       if err != nil {
-                               logger.Errorf("Error parsing isolated CPU set: 
%s", string(isolatedCpus))
-                               return
-                       }
-               }
-       }
-
+       isolatedCpusInt := resources.GetCPUIsolated()
        effectiveCpusSlice := []string{}
        for _, id := range effectiveCpusInt {
-               if shared.IntInSlice(id, isolatedCpusInt) {
+               if shared.Int64InSlice(id, isolatedCpusInt) {
                        continue
                }
 
@@ -377,7 +359,7 @@ func deviceTaskBalance(s *state.State) {
        if err != nil && shared.PathExists("/sys/fs/cgroup/cpuset/lxc") {
                logger.Warn("Error setting lxd's cpuset.cpus", log.Ctx{"err": 
err})
        }
-       cpus, err := instance.ParseCpuset(effectiveCpus)
+       cpus, err := resources.ParseCpuset(effectiveCpus)
        if err != nil {
                logger.Error("Error parsing host's cpu set", log.Ctx{"cpuset": 
effectiveCpus, "err": err})
                return
@@ -390,7 +372,7 @@ func deviceTaskBalance(s *state.State) {
                return
        }
 
-       fixedInstances := map[int][]instance.Instance{}
+       fixedInstances := map[int64][]instance.Instance{}
        balancedInstances := map[instance.Instance]int{}
        for _, c := range instances {
                conf := c.ExpandedConfig()
@@ -410,12 +392,12 @@ func deviceTaskBalance(s *state.State) {
                        balancedInstances[c] = count
                } else {
                        // Pinned
-                       containerCpus, err := instance.ParseCpuset(cpulimit)
+                       containerCpus, err := resources.ParseCpuset(cpulimit)
                        if err != nil {
                                return
                        }
                        for _, nr := range containerCpus {
-                               if !shared.IntInSlice(nr, cpus) {
+                               if !shared.Int64InSlice(nr, cpus) {
                                        continue
                                }
 
@@ -431,7 +413,7 @@ func deviceTaskBalance(s *state.State) {
 
        // Balance things
        pinning := map[instance.Instance][]string{}
-       usage := map[int]deviceTaskCPU{}
+       usage := map[int64]deviceTaskCPU{}
 
        for _, id := range cpus {
                cpu := deviceTaskCPU{}
diff --git a/lxd/instance/drivers/driver_qemu.go 
b/lxd/instance/drivers/driver_qemu.go
index dc7c9bbace..8316e05ab4 100644
--- a/lxd/instance/drivers/driver_qemu.go
+++ b/lxd/instance/drivers/driver_qemu.go
@@ -4458,7 +4458,7 @@ func (vm *qemu) cpuTopology(limit string) (int, int, int, 
map[uint64]uint64, map
        }
 
        // Expand the pins.
-       pins, err := instance.ParseCpuset(limit)
+       pins, err := resources.ParseCpuset(limit)
        if err != nil {
                return -1, -1, -1, nil, nil, err
        }
diff --git a/lxd/instance/instance_utils.go b/lxd/instance/instance_utils.go
index 9bbb85f4ee..e9837df99b 100644
--- a/lxd/instance/instance_utils.go
+++ b/lxd/instance/instance_utils.go
@@ -874,40 +874,3 @@ func ValidName(instanceName string, isSnapshot bool) error 
{
 
        return nil
 }
-
-// ParseCpuset parses a limits.cpu range into a list of CPU ids.
-func ParseCpuset(cpu string) ([]int, error) {
-       cpus := []int{}
-       chunks := strings.Split(cpu, ",")
-       for _, chunk := range chunks {
-               if strings.Contains(chunk, "-") {
-                       // Range
-                       fields := strings.SplitN(chunk, "-", 2)
-                       if len(fields) != 2 {
-                               return nil, fmt.Errorf("Invalid cpuset value: 
%s", cpu)
-                       }
-
-                       low, err := strconv.Atoi(fields[0])
-                       if err != nil {
-                               return nil, fmt.Errorf("Invalid cpuset value: 
%s", cpu)
-                       }
-
-                       high, err := strconv.Atoi(fields[1])
-                       if err != nil {
-                               return nil, fmt.Errorf("Invalid cpuset value: 
%s", cpu)
-                       }
-
-                       for i := low; i <= high; i++ {
-                               cpus = append(cpus, i)
-                       }
-               } else {
-                       // Simple entry
-                       nr, err := strconv.Atoi(chunk)
-                       if err != nil {
-                               return nil, fmt.Errorf("Invalid cpuset value: 
%s", cpu)
-                       }
-                       cpus = append(cpus, nr)
-               }
-       }
-       return cpus, nil
-}
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to