[lxc-devel] [lxd/master] Bugfixes
stgraber on Github
lxc-bot at linuxcontainers.org
Tue Mar 7 03:25:33 UTC 2017
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20170307/88fdda11/attachment.bin>
-------------- next part --------------
From 9065ae1c38794c1bb48e145aced582379af5f58e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Mon, 6 Mar 2017 21:46:48 -0500
Subject: [PATCH] global: Use RunCommand everywhere
---
lxd/apparmor.go | 10 ++--
lxd/container_lxc.go | 110 +++++++++++++++++++--------------------
lxd/db_update.go | 5 +-
lxd/devices.go | 12 ++---
lxd/images.go | 10 ++--
lxd/main_init.go | 2 +-
lxd/networks.go | 61 +++++++++++-----------
lxd/networks_iptables.go | 12 ++---
lxd/networks_utils.go | 15 +++---
lxd/patches.go | 25 +++++----
lxd/storage.go | 23 ++-------
lxd/storage_btrfs.go | 69 +++++++++++++------------
lxd/storage_dir.go | 5 +-
lxd/storage_lvm.go | 88 ++++++++++++++++----------------
lxd/storage_shared.go | 5 +-
lxd/storage_zfs.go | 130 +++++++++++++++++++++++------------------------
lxd/util.go | 3 +-
shared/util.go | 28 +++++++---
shared/util_linux.go | 2 +-
19 files changed, 303 insertions(+), 312 deletions(-)
diff --git a/lxd/apparmor.go b/lxd/apparmor.go
index cd4ac6c..89881a8 100644
--- a/lxd/apparmor.go
+++ b/lxd/apparmor.go
@@ -6,7 +6,6 @@ import (
"io"
"io/ioutil"
"os"
- "os/exec"
"path"
"strings"
@@ -395,16 +394,15 @@ func runApparmor(command string, c container) error {
return nil
}
- cmd := exec.Command("apparmor_parser", []string{
+ output, err := shared.RunCommand("apparmor_parser", []string{
fmt.Sprintf("-%sWL", command),
path.Join(aaPath, "cache"),
path.Join(aaPath, "profiles", AAProfileShort(c)),
}...)
- output, err := cmd.CombinedOutput()
if err != nil {
shared.LogError("Running apparmor",
- log.Ctx{"action": command, "output": string(output), "err": err})
+ log.Ctx{"action": command, "output": output, "err": err})
}
return err
@@ -519,7 +517,7 @@ func aaProfile() string {
}
func aaParserSupports(feature string) bool {
- out, err := exec.Command("apparmor_parser", "--version").CombinedOutput()
+ out, err := shared.RunCommand("apparmor_parser", "--version")
if err != nil {
return false
}
@@ -528,7 +526,7 @@ func aaParserSupports(feature string) bool {
minor := 0
micro := 0
- _, err = fmt.Sscanf(strings.Split(string(out), "\n")[0], "AppArmor parser version %d.%d.%d", &major, &minor, µ)
+ _, err = fmt.Sscanf(strings.Split(out, "\n")[0], "AppArmor parser version %d.%d.%d", &major, &minor, µ)
if err != nil {
return false
}
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index efd7c72..9177f77 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -1753,7 +1753,7 @@ func (c *containerLXC) startCommon() (string, error) {
if m["nictype"] == "macvlan" && m["vlan"] != "" {
device := networkGetHostDevice(m["parent"], m["vlan"])
if !shared.PathExists(fmt.Sprintf("/sys/class/net/%s", device)) {
- err := shared.RunCommand("ip", "link", "add", "link", m["parent"], "name", device, "up", "type", "vlan", "id", m["vlan"])
+ _, err := shared.RunCommand("ip", "link", "add", "link", m["parent"], "name", device, "up", "type", "vlan", "id", m["vlan"])
if err != nil {
return "", err
}
@@ -1950,16 +1950,16 @@ func (c *containerLXC) Start(stateful bool) error {
}
// Start the LXC container
- out, err := exec.Command(
+ out, err := shared.RunCommand(
execPath,
"forkstart",
c.name,
c.daemon.lxcpath,
- configPath).CombinedOutput()
+ configPath)
// Capture debug output
- if string(out) != "" {
- for _, line := range strings.Split(strings.TrimRight(string(out), "\n"), "\n") {
+ if out != "" {
+ for _, line := range strings.Split(strings.TrimRight(out, "\n"), "\n") {
shared.LogDebugf("forkstart: %s", line)
}
}
@@ -4170,18 +4170,18 @@ func (c *containerLXC) Migrate(cmd uint, stateDir string, function string, stop
configPath := filepath.Join(c.LogPath(), "lxc.conf")
- var out []byte
- out, migrateErr = exec.Command(
+ var out string
+ out, migrateErr = shared.RunCommand(
execPath,
"forkmigrate",
c.name,
c.daemon.lxcpath,
configPath,
stateDir,
- fmt.Sprintf("%v", preservesInodes)).CombinedOutput()
+ fmt.Sprintf("%v", preservesInodes))
- if string(out) != "" {
- for _, line := range strings.Split(strings.TrimRight(string(out), "\n"), "\n") {
+ if out != "" {
+ for _, line := range strings.Split(strings.TrimRight(out, "\n"), "\n") {
shared.LogDebugf("forkmigrate: %s", line)
}
}
@@ -4194,7 +4194,7 @@ func (c *containerLXC) Migrate(cmd uint, stateDir string, function string, stop
filepath.Join(c.LogPath(), "lxc.conf"),
stateDir,
err,
- string(out))
+ out)
}
} else {
@@ -4413,13 +4413,13 @@ func (c *containerLXC) FileExists(path string) error {
}
// Check if the file exists in the container
- out, err := exec.Command(
+ out, err := shared.RunCommand(
execPath,
"forkcheckfile",
c.RootfsPath(),
fmt.Sprintf("%d", c.InitPID()),
path,
- ).CombinedOutput()
+ )
// Tear down container storage if needed
if !c.IsRunning() {
@@ -4430,12 +4430,12 @@ func (c *containerLXC) FileExists(path string) error {
}
// Process forkcheckfile response
- if string(out) != "" {
- if strings.HasPrefix(string(out), "error:") {
- return fmt.Errorf(strings.TrimPrefix(strings.TrimSuffix(string(out), "\n"), "error: "))
+ if out != "" {
+ if strings.HasPrefix(out, "error:") {
+ return fmt.Errorf(strings.TrimPrefix(strings.TrimSuffix(out, "\n"), "error: "))
}
- for _, line := range strings.Split(strings.TrimRight(string(out), "\n"), "\n") {
+ for _, line := range strings.Split(strings.TrimRight(out, "\n"), "\n") {
shared.LogDebugf("forkcheckfile: %s", line)
}
}
@@ -4462,14 +4462,14 @@ func (c *containerLXC) FilePull(srcpath string, dstpath string) (int64, int64, o
}
// Get the file from the container
- out, err := exec.Command(
+ out, err := shared.RunCommand(
execPath,
"forkgetfile",
c.RootfsPath(),
fmt.Sprintf("%d", c.InitPID()),
dstpath,
srcpath,
- ).CombinedOutput()
+ )
// Tear down container storage if needed
if !c.IsRunning() {
@@ -4487,7 +4487,7 @@ func (c *containerLXC) FilePull(srcpath string, dstpath string) (int64, int64, o
var errStr string
// Process forkgetfile response
- for _, line := range strings.Split(strings.TrimRight(string(out), "\n"), "\n") {
+ for _, line := range strings.Split(strings.TrimRight(out, "\n"), "\n") {
if line == "" {
continue
}
@@ -4604,7 +4604,7 @@ func (c *containerLXC) FilePush(srcpath string, dstpath string, uid int64, gid i
}
// Push the file to the container
- out, err := exec.Command(
+ out, err := shared.RunCommand(
execPath,
"forkputfile",
c.RootfsPath(),
@@ -4618,7 +4618,7 @@ func (c *containerLXC) FilePush(srcpath string, dstpath string, uid int64, gid i
fmt.Sprintf("%d", rootGid),
fmt.Sprintf("%d", int(os.FileMode(0640)&os.ModePerm)),
write,
- ).CombinedOutput()
+ )
// Tear down container storage if needed
if !c.IsRunning() {
@@ -4629,7 +4629,7 @@ func (c *containerLXC) FilePush(srcpath string, dstpath string, uid int64, gid i
}
// Process forkgetfile response
- for _, line := range strings.Split(strings.TrimRight(string(out), "\n"), "\n") {
+ for _, line := range strings.Split(strings.TrimRight(out, "\n"), "\n") {
if line == "" {
continue
}
@@ -4682,13 +4682,13 @@ func (c *containerLXC) FileRemove(path string) error {
}
// Remove the file from the container
- out, err := exec.Command(
+ out, err := shared.RunCommand(
execPath,
"forkremovefile",
c.RootfsPath(),
fmt.Sprintf("%d", c.InitPID()),
path,
- ).CombinedOutput()
+ )
// Tear down container storage if needed
if !c.IsRunning() {
@@ -4699,7 +4699,7 @@ func (c *containerLXC) FileRemove(path string) error {
}
// Process forkremovefile response
- for _, line := range strings.Split(strings.TrimRight(string(out), "\n"), "\n") {
+ for _, line := range strings.Split(strings.TrimRight(out, "\n"), "\n") {
if line == "" {
continue
}
@@ -4906,20 +4906,20 @@ func (c *containerLXC) networkState() map[string]api.ContainerStateNetwork {
}
// Get the network state from the container
- out, err := exec.Command(
+ out, err := shared.RunCommand(
execPath,
"forkgetnet",
- fmt.Sprintf("%d", pid)).CombinedOutput()
+ fmt.Sprintf("%d", pid))
// Process forkgetnet response
if err != nil {
- shared.LogError("Error calling 'lxd forkgetnet", log.Ctx{"container": c.name, "output": string(out), "pid": pid})
+ shared.LogError("Error calling 'lxd forkgetnet", log.Ctx{"container": c.name, "output": out, "pid": pid})
return result
}
networks := map[string]api.ContainerStateNetwork{}
- err = json.Unmarshal(out, &networks)
+ err = json.Unmarshal([]byte(out), &networks)
if err != nil {
shared.LogError("Failure to read forkgetnet json", log.Ctx{"container": c.name, "err": err})
return result
@@ -5143,10 +5143,10 @@ func (c *containerLXC) insertMount(source, target, fstype string, flags int) err
mntsrc := filepath.Join("/dev/.lxd-mounts", filepath.Base(tmpMount))
pidStr := fmt.Sprintf("%d", pid)
- out, err := exec.Command(execPath, "forkmount", pidStr, mntsrc, target).CombinedOutput()
+ out, err := shared.RunCommand(execPath, "forkmount", pidStr, mntsrc, target)
- if string(out) != "" {
- for _, line := range strings.Split(strings.TrimRight(string(out), "\n"), "\n") {
+ if out != "" {
+ for _, line := range strings.Split(strings.TrimRight(out, "\n"), "\n") {
shared.LogDebugf("forkmount: %s", line)
}
}
@@ -5173,10 +5173,10 @@ func (c *containerLXC) removeMount(mount string) error {
// Remove the mount from the container
pidStr := fmt.Sprintf("%d", pid)
- out, err := exec.Command(execPath, "forkumount", pidStr, mount).CombinedOutput()
+ out, err := shared.RunCommand(execPath, "forkumount", pidStr, mount)
- if string(out) != "" {
- for _, line := range strings.Split(strings.TrimRight(string(out), "\n"), "\n") {
+ if out != "" {
+ for _, line := range strings.Split(strings.TrimRight(out, "\n"), "\n") {
shared.LogDebugf("forkumount: %s", line)
}
}
@@ -5562,12 +5562,12 @@ func (c *containerLXC) createNetworkDevice(name string, m types.Device) (string,
if shared.StringInSlice(m["nictype"], []string{"bridged", "p2p"}) {
n2 := deviceNextVeth()
- err := exec.Command("ip", "link", "add", n1, "type", "veth", "peer", "name", n2).Run()
+ _, err := shared.RunCommand("ip", "link", "add", n1, "type", "veth", "peer", "name", n2)
if err != nil {
return "", fmt.Errorf("Failed to create the veth interface: %s", err)
}
- err = exec.Command("ip", "link", "set", n1, "up").Run()
+ _, err = shared.RunCommand("ip", "link", "set", n1, "up")
if err != nil {
return "", fmt.Errorf("Failed to bring up the veth interface %s: %s", n1, err)
}
@@ -5600,14 +5600,14 @@ func (c *containerLXC) createNetworkDevice(name string, m types.Device) (string,
if m["vlan"] != "" {
device = networkGetHostDevice(m["parent"], m["vlan"])
if !shared.PathExists(fmt.Sprintf("/sys/class/net/%s", device)) {
- err := shared.RunCommand("ip", "link", "add", "link", m["parent"], "name", device, "up", "type", "vlan", "id", m["vlan"])
+ _, err := shared.RunCommand("ip", "link", "add", "link", m["parent"], "name", device, "up", "type", "vlan", "id", m["vlan"])
if err != nil {
return "", err
}
}
}
- err := exec.Command("ip", "link", "add", n1, "link", device, "type", "macvlan", "mode", "bridge").Run()
+ _, err := shared.RunCommand("ip", "link", "add", n1, "link", device, "type", "macvlan", "mode", "bridge")
if err != nil {
return "", fmt.Errorf("Failed to create the new macvlan interface: %s", err)
}
@@ -5617,7 +5617,7 @@ func (c *containerLXC) createNetworkDevice(name string, m types.Device) (string,
// Set the MAC address
if m["hwaddr"] != "" {
- err := exec.Command("ip", "link", "set", "dev", dev, "address", m["hwaddr"]).Run()
+ _, err := shared.RunCommand("ip", "link", "set", "dev", dev, "address", m["hwaddr"])
if err != nil {
deviceRemoveInterface(dev)
return "", fmt.Errorf("Failed to set the MAC address: %s", err)
@@ -5625,7 +5625,7 @@ func (c *containerLXC) createNetworkDevice(name string, m types.Device) (string,
}
// Bring the interface up
- err := exec.Command("ip", "link", "set", "dev", dev, "up").Run()
+ _, err := shared.RunCommand("ip", "link", "set", "dev", dev, "up")
if err != nil {
deviceRemoveInterface(dev)
return "", fmt.Errorf("Failed to bring up the interface: %s", err)
@@ -5790,12 +5790,12 @@ func (c *containerLXC) fillNetworkDevice(name string, m types.Device) (types.Dev
}
func (c *containerLXC) createNetworkFilter(name string, bridge string, hwaddr string) error {
- err := shared.RunCommand("ebtables", "-A", "FORWARD", "-s", "!", hwaddr, "-i", name, "-o", bridge, "-j", "DROP")
+ _, err := shared.RunCommand("ebtables", "-A", "FORWARD", "-s", "!", hwaddr, "-i", name, "-o", bridge, "-j", "DROP")
if err != nil {
return err
}
- err = shared.RunCommand("ebtables", "-A", "INPUT", "-s", "!", hwaddr, "-i", name, "-j", "DROP")
+ _, err = shared.RunCommand("ebtables", "-A", "INPUT", "-s", "!", hwaddr, "-i", name, "-j", "DROP")
if err != nil {
return err
}
@@ -5804,8 +5804,8 @@ func (c *containerLXC) createNetworkFilter(name string, bridge string, hwaddr st
}
func (c *containerLXC) removeNetworkFilter(hwaddr string, bridge string) error {
- out, err := exec.Command("ebtables", "-L", "--Lmac2", "--Lx").Output()
- for _, line := range strings.Split(string(out), "\n") {
+ out, err := shared.RunCommand("ebtables", "-L", "--Lmac2", "--Lx")
+ for _, line := range strings.Split(out, "\n") {
line = strings.TrimSpace(line)
fields := strings.Fields(line)
@@ -5813,7 +5813,7 @@ func (c *containerLXC) removeNetworkFilter(hwaddr string, bridge string) error {
match := []string{"ebtables", "-t", "filter", "-A", "INPUT", "-s", "!", hwaddr, "-i", fields[9], "-j", "DROP"}
if reflect.DeepEqual(fields, match) {
fields[3] = "-D"
- err = shared.RunCommand(fields[0], fields[1:]...)
+ _, err = shared.RunCommand(fields[0], fields[1:]...)
if err != nil {
return err
}
@@ -5822,7 +5822,7 @@ func (c *containerLXC) removeNetworkFilter(hwaddr string, bridge string) error {
match := []string{"ebtables", "-t", "filter", "-A", "FORWARD", "-s", "!", hwaddr, "-i", fields[9], "-o", bridge, "-j", "DROP"}
if reflect.DeepEqual(fields, match) {
fields[3] = "-D"
- err = shared.RunCommand(fields[0], fields[1:]...)
+ _, err = shared.RunCommand(fields[0], fields[1:]...)
if err != nil {
return err
}
@@ -6488,34 +6488,34 @@ func (c *containerLXC) setNetworkLimits(name string, m types.Device) error {
}
// Clean any existing entry
- _ = exec.Command("tc", "qdisc", "del", "dev", veth, "root").Run()
- _ = exec.Command("tc", "qdisc", "del", "dev", veth, "ingress").Run()
+ shared.RunCommand("tc", "qdisc", "del", "dev", veth, "root")
+ shared.RunCommand("tc", "qdisc", "del", "dev", veth, "ingress")
// Apply new limits
if m["limits.ingress"] != "" {
- out, err := exec.Command("tc", "qdisc", "add", "dev", veth, "root", "handle", "1:0", "htb", "default", "10").CombinedOutput()
+ out, err := shared.RunCommand("tc", "qdisc", "add", "dev", veth, "root", "handle", "1:0", "htb", "default", "10")
if err != nil {
return fmt.Errorf("Failed to create root tc qdisc: %s", out)
}
- out, err = exec.Command("tc", "class", "add", "dev", veth, "parent", "1:0", "classid", "1:10", "htb", "rate", fmt.Sprintf("%dbit", ingressInt)).CombinedOutput()
+ out, err = shared.RunCommand("tc", "class", "add", "dev", veth, "parent", "1:0", "classid", "1:10", "htb", "rate", fmt.Sprintf("%dbit", ingressInt))
if err != nil {
return fmt.Errorf("Failed to create limit tc class: %s", out)
}
- out, err = exec.Command("tc", "filter", "add", "dev", veth, "parent", "1:0", "protocol", "all", "u32", "match", "u32", "0", "0", "flowid", "1:1").CombinedOutput()
+ out, err = shared.RunCommand("tc", "filter", "add", "dev", veth, "parent", "1:0", "protocol", "all", "u32", "match", "u32", "0", "0", "flowid", "1:1")
if err != nil {
return fmt.Errorf("Failed to create tc filter: %s", out)
}
}
if m["limits.egress"] != "" {
- out, err := exec.Command("tc", "qdisc", "add", "dev", veth, "handle", "ffff:0", "ingress").CombinedOutput()
+ out, err := shared.RunCommand("tc", "qdisc", "add", "dev", veth, "handle", "ffff:0", "ingress")
if err != nil {
return fmt.Errorf("Failed to create ingress tc qdisc: %s", out)
}
- out, err = exec.Command("tc", "filter", "add", "dev", veth, "parent", "ffff:0", "protocol", "all", "u32", "match", "u32", "0", "0", "police", "rate", fmt.Sprintf("%dbit", egressInt), "burst", "1024k", "mtu", "64kb", "drop", "flowid", ":1").CombinedOutput()
+ out, err = shared.RunCommand("tc", "filter", "add", "dev", veth, "parent", "ffff:0", "protocol", "all", "u32", "match", "u32", "0", "0", "police", "rate", fmt.Sprintf("%dbit", egressInt), "burst", "1024k", "mtu", "64kb", "drop", "flowid", ":1")
if err != nil {
return fmt.Errorf("Failed to create ingress tc qdisc: %s", out)
}
diff --git a/lxd/db_update.go b/lxd/db_update.go
index 8109b39..9d274a0 100644
--- a/lxd/db_update.go
+++ b/lxd/db_update.go
@@ -5,7 +5,6 @@ import (
"fmt"
"io/ioutil"
"os"
- "os/exec"
"path/filepath"
"strconv"
"strings"
@@ -481,9 +480,9 @@ func dbUpdateFromV15(currentVersion int, version int, d *Daemon) error {
shared.LogDebug("About to rename cName in lv upgrade", log.Ctx{"lvLinkPath": lvLinkPath, "cName": cName, "newLVName": newLVName})
- output, err := exec.Command("lvrename", vgName, cName, newLVName).CombinedOutput()
+ output, err := shared.RunCommand("lvrename", vgName, cName, newLVName)
if err != nil {
- return fmt.Errorf("Could not rename LV '%s' to '%s': %v\noutput:%s", cName, newLVName, err, string(output))
+ return fmt.Errorf("Could not rename LV '%s' to '%s': %v\noutput:%s", cName, newLVName, err, output)
}
if err := os.Remove(lvLinkPath); err != nil {
diff --git a/lxd/devices.go b/lxd/devices.go
index 238863f..dff4493 100644
--- a/lxd/devices.go
+++ b/lxd/devices.go
@@ -9,7 +9,6 @@ import (
"io/ioutil"
"math/big"
"os"
- "os/exec"
"path"
"path/filepath"
"regexp"
@@ -877,7 +876,8 @@ func deviceNextVeth() string {
}
func deviceRemoveInterface(nic string) error {
- return exec.Command("ip", "link", "del", nic).Run()
+ _, err := shared.RunCommand("ip", "link", "del", nic)
+ return err
}
func deviceMountDisk(srcPath string, dstPath string, readonly bool, recursive bool) error {
@@ -1071,13 +1071,13 @@ func deviceGetParentBlocks(path string) ([]string, error) {
// Accessible zfs filesystems
poolName := strings.Split(device[1], "/")[0]
- output, err := exec.Command("zpool", "status", "-P", "-L", poolName).CombinedOutput()
+ output, err := shared.RunCommand("zpool", "status", "-P", "-L", poolName)
if err != nil {
return nil, fmt.Errorf("Failed to query zfs filesystem information for %s: %s", device[1], output)
}
header := true
- for _, line := range strings.Split(string(output), "\n") {
+ for _, line := range strings.Split(output, "\n") {
fields := strings.Fields(line)
if len(fields) < 5 {
continue
@@ -1125,12 +1125,12 @@ func deviceGetParentBlocks(path string) ([]string, error) {
}
} else if fs == "btrfs" && shared.PathExists(device[1]) {
// Accessible btrfs filesystems
- output, err := exec.Command("btrfs", "filesystem", "show", device[1]).CombinedOutput()
+ output, err := shared.RunCommand("btrfs", "filesystem", "show", device[1])
if err != nil {
return nil, fmt.Errorf("Failed to query btrfs filesystem information for %s: %s", device[1], output)
}
- for _, line := range strings.Split(string(output), "\n") {
+ for _, line := range strings.Split(output, "\n") {
fields := strings.Fields(line)
if len(fields) == 0 || fields[0] != "devid" {
continue
diff --git a/lxd/images.go b/lxd/images.go
index 7b95ee3..c203289 100644
--- a/lxd/images.go
+++ b/lxd/images.go
@@ -117,7 +117,7 @@ func unpack(d *Daemon, file string, path string, sType storageType) error {
return fmt.Errorf("Unsupported image format: %s", extension)
}
- output, err := exec.Command(command, args...).CombinedOutput()
+ output, err := shared.RunCommand(command, args...)
if err != nil {
// Check if we ran out of space
fs := syscall.Statfs_t{}
@@ -136,7 +136,7 @@ func unpack(d *Daemon, file string, path string, sType storageType) error {
}
}
- co := string(output)
+ co := output
shared.LogDebugf("Unpacking failed")
shared.LogDebugf(co)
@@ -801,15 +801,15 @@ func getImageMetadata(fname string) (*imageMetadata, error) {
args = append(args, fname, metadataName)
// read the metadata.yaml
- output, err := exec.Command("tar", args...).CombinedOutput()
+ output, err := shared.RunCommand("tar", args...)
if err != nil {
- outputLines := strings.Split(string(output), "\n")
+ outputLines := strings.Split(output, "\n")
return nil, fmt.Errorf("Could not extract image %s from tar: %v (%s)", metadataName, err, outputLines[0])
}
metadata := imageMetadata{}
- err = yaml.Unmarshal(output, &metadata)
+ err = yaml.Unmarshal([]byte(output), &metadata)
if err != nil {
return nil, fmt.Errorf("Could not parse %s: %v", metadataName, err)
diff --git a/lxd/main_init.go b/lxd/main_init.go
index bb8c3ee..3bc1c49 100644
--- a/lxd/main_init.go
+++ b/lxd/main_init.go
@@ -47,7 +47,7 @@ func cmdInit() error {
if err == nil && len(out) != 0 && !runningInUserns {
_ = loadModule("zfs")
- err := shared.RunCommand("zpool", "list")
+ _, err := shared.RunCommand("zpool", "list")
if err == nil {
backendsAvailable = append(backendsAvailable, "zfs")
}
diff --git a/lxd/networks.go b/lxd/networks.go
index 8a03d56..3ea207b 100644
--- a/lxd/networks.go
+++ b/lxd/networks.go
@@ -8,7 +8,6 @@ import (
"net"
"net/http"
"os"
- "os/exec"
"strconv"
"strings"
@@ -212,7 +211,7 @@ func doNetworkGet(d *Daemon, name string) (api.Network, error) {
} else if shared.PathExists(fmt.Sprintf("/sys/class/net/%s/bonding", n.Name)) {
n.Type = "bond"
} else {
- _, err := exec.Command("ovs-vsctl", "br-exists", n.Name).CombinedOutput()
+ _, err := shared.RunCommand("ovs-vsctl", "br-exists", n.Name)
if err == nil {
n.Type = "bridge"
} else {
@@ -534,12 +533,12 @@ func (n *network) Start() error {
// Create the bridge interface
if !n.IsRunning() {
if n.config["bridge.driver"] == "openvswitch" {
- err := shared.RunCommand("ovs-vsctl", "add-br", n.name)
+ _, err := shared.RunCommand("ovs-vsctl", "add-br", n.name)
if err != nil {
return err
}
} else {
- err := shared.RunCommand("ip", "link", "add", n.name, "type", "bridge")
+ _, err := shared.RunCommand("ip", "link", "add", n.name, "type", "bridge")
if err != nil {
return err
}
@@ -571,7 +570,7 @@ func (n *network) Start() error {
// Cleanup any existing tunnel device
for _, iface := range ifaces {
if strings.HasPrefix(iface.Name, fmt.Sprintf("%s-", n.name)) {
- err = shared.RunCommand("ip", "link", "del", iface.Name)
+ _, err = shared.RunCommand("ip", "link", "del", iface.Name)
if err != nil {
return err
}
@@ -594,7 +593,7 @@ func (n *network) Start() error {
// Attempt to add a dummy device to the bridge to force the MTU
if mtu != "" && n.config["bridge.driver"] != "openvswitch" {
- err = shared.RunCommand("ip", "link", "add", fmt.Sprintf("%s-mtu", n.name), "mtu", mtu, "type", "dummy")
+ _, err = shared.RunCommand("ip", "link", "add", fmt.Sprintf("%s-mtu", n.name), "mtu", mtu, "type", "dummy")
if err == nil {
networkAttachInterface(n.name, fmt.Sprintf("%s-mtu", n.name))
}
@@ -605,13 +604,13 @@ func (n *network) Start() error {
mtu = "1500"
}
- err = shared.RunCommand("ip", "link", "set", n.name, "mtu", mtu)
+ _, err = shared.RunCommand("ip", "link", "set", n.name, "mtu", mtu)
if err != nil {
return err
}
// Bring it up
- err = shared.RunCommand("ip", "link", "set", n.name, "up")
+ _, err = shared.RunCommand("ip", "link", "set", n.name, "up")
if err != nil {
return err
}
@@ -654,12 +653,12 @@ func (n *network) Start() error {
}
// Flush all IPv4 addresses and routes
- err = shared.RunCommand("ip", "-4", "addr", "flush", "dev", n.name, "scope", "global")
+ _, err = shared.RunCommand("ip", "-4", "addr", "flush", "dev", n.name, "scope", "global")
if err != nil {
return err
}
- err = shared.RunCommand("ip", "-4", "route", "flush", "dev", n.name, "proto", "static")
+ _, err = shared.RunCommand("ip", "-4", "route", "flush", "dev", n.name, "proto", "static")
if err != nil {
return err
}
@@ -758,7 +757,7 @@ func (n *network) Start() error {
}
// Add the address
- err = shared.RunCommand("ip", "-4", "addr", "add", "dev", n.name, n.config["ipv4.address"])
+ _, err = shared.RunCommand("ip", "-4", "addr", "add", "dev", n.name, n.config["ipv4.address"])
if err != nil {
return err
}
@@ -775,7 +774,7 @@ func (n *network) Start() error {
if n.config["ipv4.routes"] != "" {
for _, route := range strings.Split(n.config["ipv4.routes"], ",") {
route = strings.TrimSpace(route)
- err = shared.RunCommand("ip", "-4", "route", "add", "dev", n.name, route, "proto", "static")
+ _, err = shared.RunCommand("ip", "-4", "route", "add", "dev", n.name, route, "proto", "static")
if err != nil {
return err
}
@@ -795,12 +794,12 @@ func (n *network) Start() error {
}
// Flush all IPv6 addresses and routes
- err = shared.RunCommand("ip", "-6", "addr", "flush", "dev", n.name, "scope", "global")
+ _, err = shared.RunCommand("ip", "-6", "addr", "flush", "dev", n.name, "scope", "global")
if err != nil {
return err
}
- err = shared.RunCommand("ip", "-6", "route", "flush", "dev", n.name, "proto", "static")
+ _, err = shared.RunCommand("ip", "-6", "route", "flush", "dev", n.name, "proto", "static")
if err != nil {
return err
}
@@ -918,7 +917,7 @@ func (n *network) Start() error {
}
// Add the address
- err = shared.RunCommand("ip", "-6", "addr", "add", "dev", n.name, n.config["ipv6.address"])
+ _, err = shared.RunCommand("ip", "-6", "addr", "add", "dev", n.name, n.config["ipv6.address"])
if err != nil {
return err
}
@@ -935,7 +934,7 @@ func (n *network) Start() error {
if n.config["ipv6.routes"] != "" {
for _, route := range strings.Split(n.config["ipv6.routes"], ",") {
route = strings.TrimSpace(route)
- err = shared.RunCommand("ip", "-6", "route", "add", "dev", n.name, route, "proto", "static")
+ _, err = shared.RunCommand("ip", "-6", "route", "add", "dev", n.name, route, "proto", "static")
if err != nil {
return err
}
@@ -983,7 +982,7 @@ func (n *network) Start() error {
}
// Add the address
- err = shared.RunCommand("ip", "-4", "addr", "add", "dev", n.name, fanAddress)
+ _, err = shared.RunCommand("ip", "-4", "addr", "add", "dev", n.name, fanAddress)
if err != nil {
return err
}
@@ -998,12 +997,12 @@ func (n *network) Start() error {
// Setup the tunnel
if n.config["fan.type"] == "ipip" {
- err = shared.RunCommand("ip", "-4", "route", "flush", "dev", "tunl0")
+ _, err = shared.RunCommand("ip", "-4", "route", "flush", "dev", "tunl0")
if err != nil {
return err
}
- err = shared.RunCommand("ip", "link", "set", "tunl0", "up")
+ _, err = shared.RunCommand("ip", "link", "set", "tunl0", "up")
if err != nil {
return err
}
@@ -1011,14 +1010,14 @@ func (n *network) Start() error {
// Fails if the map is already set
shared.RunCommand("ip", "link", "change", "tunl0", "type", "ipip", "fan-map", fmt.Sprintf("%s:%s", overlay, underlay))
- err = shared.RunCommand("ip", "route", "add", overlay, "dev", "tunl0", "src", addr[0])
+ _, err = shared.RunCommand("ip", "route", "add", overlay, "dev", "tunl0", "src", addr[0])
if err != nil {
return err
}
} else {
vxlanID := fmt.Sprintf("%d", binary.BigEndian.Uint32(overlaySubnet.IP.To4())>>8)
- err = shared.RunCommand("ip", "link", "add", tunName, "type", "vxlan", "id", vxlanID, "dev", devName, "dstport", "0", "local", devAddr, "fan-map", fmt.Sprintf("%s:%s", overlay, underlay))
+ _, err = shared.RunCommand("ip", "link", "add", tunName, "type", "vxlan", "id", vxlanID, "dev", devName, "dstport", "0", "local", devAddr, "fan-map", fmt.Sprintf("%s:%s", overlay, underlay))
if err != nil {
return err
}
@@ -1028,12 +1027,12 @@ func (n *network) Start() error {
return err
}
- err = shared.RunCommand("ip", "link", "set", tunName, "mtu", mtu, "up")
+ _, err = shared.RunCommand("ip", "link", "set", tunName, "mtu", mtu, "up")
if err != nil {
return err
}
- err = shared.RunCommand("ip", "link", "set", n.name, "up")
+ _, err = shared.RunCommand("ip", "link", "set", n.name, "up")
if err != nil {
return err
}
@@ -1105,7 +1104,7 @@ func (n *network) Start() error {
}
// Create the interface
- err = shared.RunCommand(cmd[0], cmd[1:]...)
+ _, err = shared.RunCommand(cmd[0], cmd[1:]...)
if err != nil {
return err
}
@@ -1116,12 +1115,12 @@ func (n *network) Start() error {
return err
}
- err = shared.RunCommand("ip", "link", "set", tunName, "mtu", mtu, "up")
+ _, err = shared.RunCommand("ip", "link", "set", tunName, "mtu", mtu, "up")
if err != nil {
return err
}
- err = shared.RunCommand("ip", "link", "set", n.name, "up")
+ _, err = shared.RunCommand("ip", "link", "set", n.name, "up")
if err != nil {
return err
}
@@ -1174,9 +1173,9 @@ func (n *network) Start() error {
}
// Start dnsmasq (occasionally races, try a few times)
- output, err := tryExec(dnsmasqCmd[0], dnsmasqCmd[1:]...)
+ output, err := shared.TryRunCommand(dnsmasqCmd[0], dnsmasqCmd[1:]...)
if err != nil {
- return fmt.Errorf("Failed to run: %s: %s", strings.Join(dnsmasqCmd, " "), strings.TrimSpace(string(output)))
+ return fmt.Errorf("Failed to run: %s: %s", strings.Join(dnsmasqCmd, " "), strings.TrimSpace(output))
}
// Update the static leases
@@ -1196,12 +1195,12 @@ func (n *network) Stop() error {
// Destroy the bridge interface
if n.config["bridge.driver"] == "openvswitch" {
- err := shared.RunCommand("ovs-vsctl", "del-br", n.name)
+ _, err := shared.RunCommand("ovs-vsctl", "del-br", n.name)
if err != nil {
return err
}
} else {
- err := shared.RunCommand("ip", "link", "del", n.name)
+ _, err := shared.RunCommand("ip", "link", "del", n.name)
if err != nil {
return err
}
@@ -1248,7 +1247,7 @@ func (n *network) Stop() error {
// Cleanup any existing tunnel device
for _, iface := range ifaces {
if strings.HasPrefix(iface.Name, fmt.Sprintf("%s-", n.name)) {
- err = shared.RunCommand("ip", "link", "del", iface.Name)
+ _, err = shared.RunCommand("ip", "link", "del", iface.Name)
if err != nil {
return err
}
diff --git a/lxd/networks_iptables.go b/lxd/networks_iptables.go
index fb2585e..d493d72 100644
--- a/lxd/networks_iptables.go
+++ b/lxd/networks_iptables.go
@@ -2,7 +2,6 @@ package main
import (
"fmt"
- "os/exec"
"strings"
"github.com/lxc/lxd/shared"
@@ -23,7 +22,8 @@ func networkIptablesPrepend(protocol string, netName string, table string, chain
args := append(baseArgs, []string{"-C", chain}...)
args = append(args, rule...)
args = append(args, "-m", "comment", "--comment", fmt.Sprintf("generated for LXD network %s", netName))
- if shared.RunCommand(cmd, args...) == nil {
+ _, err := shared.RunCommand(cmd, args...)
+ if err == nil {
return nil
}
@@ -32,7 +32,7 @@ func networkIptablesPrepend(protocol string, netName string, table string, chain
args = append(args, rule...)
args = append(args, "-m", "comment", "--comment", fmt.Sprintf("generated for LXD network %s", netName))
- err := shared.RunCommand(cmd, args...)
+ _, err = shared.RunCommand(cmd, args...)
if err != nil {
return err
}
@@ -58,12 +58,12 @@ func networkIptablesClear(protocol string, netName string, table string) error {
// List the rules
args := append(baseArgs, "-S")
- output, err := exec.Command(cmd, args...).Output()
+ output, err := shared.RunCommand(cmd, args...)
if err != nil {
return fmt.Errorf("Failed to list %s rules for %s (table %s)", protocol, netName, table)
}
- for _, line := range strings.Split(string(output), "\n") {
+ for _, line := range strings.Split(output, "\n") {
if !strings.Contains(line, fmt.Sprintf("generated for LXD network %s", netName)) {
continue
}
@@ -73,7 +73,7 @@ func networkIptablesClear(protocol string, netName string, table string) error {
fields[0] = "-D"
args = append(baseArgs, fields...)
- err = shared.RunCommand("sh", "-c", fmt.Sprintf("%s %s", cmd, strings.Join(args, " ")))
+ _, err = shared.RunCommand("sh", "-c", fmt.Sprintf("%s %s", cmd, strings.Join(args, " ")))
if err != nil {
return err
}
diff --git a/lxd/networks_utils.go b/lxd/networks_utils.go
index 70e4334..0009e99 100644
--- a/lxd/networks_utils.go
+++ b/lxd/networks_utils.go
@@ -11,7 +11,6 @@ import (
"math/rand"
"net"
"os"
- "os/exec"
"path/filepath"
"regexp"
"strconv"
@@ -35,14 +34,14 @@ func networkAutoAttach(d *Daemon, devName string) error {
func networkAttachInterface(netName string, devName string) error {
if shared.PathExists(fmt.Sprintf("/sys/class/net/%s/bridge", netName)) {
- err := shared.RunCommand("ip", "link", "set", devName, "master", netName)
+ _, err := shared.RunCommand("ip", "link", "set", devName, "master", netName)
if err != nil {
return err
}
} else {
- err := shared.RunCommand("ovs-vsctl", "port-to-br", devName)
+ _, err := shared.RunCommand("ovs-vsctl", "port-to-br", devName)
if err != nil {
- err := shared.RunCommand("ovs-vsctl", "add-port", netName, devName)
+ _, err := shared.RunCommand("ovs-vsctl", "add-port", netName, devName)
if err != nil {
return err
}
@@ -54,14 +53,14 @@ func networkAttachInterface(netName string, devName string) error {
func networkDetachInterface(netName string, devName string) error {
if shared.PathExists(fmt.Sprintf("/sys/class/net/%s/bridge", netName)) {
- err := shared.RunCommand("ip", "link", "set", devName, "nomaster")
+ _, err := shared.RunCommand("ip", "link", "set", devName, "nomaster")
if err != nil {
return err
}
} else {
- err := shared.RunCommand("ovs-vsctl", "port-to-br", devName)
+ _, err := shared.RunCommand("ovs-vsctl", "port-to-br", devName)
if err == nil {
- err := shared.RunCommand("ovs-vsctl", "del-port", netName, devName)
+ _, err := shared.RunCommand("ovs-vsctl", "del-port", netName, devName)
if err != nil {
return err
}
@@ -218,7 +217,7 @@ func networkPingSubnet(subnet *net.IPNet) bool {
cmd = "ping6"
}
- _, err := exec.Command(cmd, "-n", "-q", ip.String(), "-c", "1", "-W", "1").CombinedOutput()
+ _, err := shared.RunCommand(cmd, "-n", "-q", ip.String(), "-c", "1", "-W", "1")
if err != nil {
// Remote didn't answer
return
diff --git a/lxd/patches.go b/lxd/patches.go
index 369860b..4017343 100644
--- a/lxd/patches.go
+++ b/lxd/patches.go
@@ -3,7 +3,6 @@ package main
import (
"fmt"
"os"
- "os/exec"
"path/filepath"
"strings"
"syscall"
@@ -982,7 +981,7 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
newContainerLvName := fmt.Sprintf("%s_%s", storagePoolVolumeApiEndpointContainers, ctLvName)
containerLvDevPath := getLvmDevPath(defaultPoolName, storagePoolVolumeApiEndpointContainers, ctLvName)
if !shared.PathExists(containerLvDevPath) {
- _, err := tryExec("lvrename", defaultPoolName, ctLvName, newContainerLvName)
+ _, err := shared.TryRunCommand("lvrename", defaultPoolName, ctLvName, newContainerLvName)
if err != nil {
return err
}
@@ -1083,7 +1082,7 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
newSnapshotLvName := fmt.Sprintf("%s_%s", storagePoolVolumeApiEndpointContainers, csLvName)
snapshotLvDevPath := getLvmDevPath(defaultPoolName, storagePoolVolumeApiEndpointContainers, csLvName)
if !shared.PathExists(snapshotLvDevPath) {
- _, err := tryExec("lvrename", defaultPoolName, csLvName, newSnapshotLvName)
+ _, err := shared.TryRunCommand("lvrename", defaultPoolName, csLvName, newSnapshotLvName)
if err != nil {
return err
}
@@ -1180,7 +1179,7 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
newImageLvName := fmt.Sprintf("%s_%s", storagePoolVolumeApiEndpointImages, img)
imageLvDevPath := getLvmDevPath(defaultPoolName, storagePoolVolumeApiEndpointImages, img)
if !shared.PathExists(imageLvDevPath) {
- _, err := tryExec("lvrename", defaultPoolName, img, newImageLvName)
+ _, err := shared.TryRunCommand("lvrename", defaultPoolName, img, newImageLvName)
if err != nil {
return err
}
@@ -1262,11 +1261,11 @@ func upgradeFromStorageTypeZfs(name string, d *Daemon, defaultPoolName string, d
// Querying the size of a storage pool only makes sense when it
// is not a dataset.
if poolName == defaultPoolName {
- output, err := exec.Command("zpool", "get", "size", "-p", "-H", defaultPoolName).CombinedOutput()
+ output, err := shared.RunCommand("zpool", "get", "size", "-p", "-H", defaultPoolName)
if err == nil {
- lidx := strings.LastIndex(string(output), "\t")
- fidx := strings.LastIndex(string(output)[:lidx-1], "\t")
- poolConfig["size"] = string(output)[fidx+1 : lidx]
+ lidx := strings.LastIndex(output, "\t")
+ fidx := strings.LastIndex(output[:lidx-1], "\t")
+ poolConfig["size"] = output[fidx+1 : lidx]
}
}
@@ -1334,7 +1333,7 @@ func upgradeFromStorageTypeZfs(name string, d *Daemon, defaultPoolName string, d
ctDataset := fmt.Sprintf("%s/containers/%s", defaultPoolName, ct)
oldContainerMntPoint := shared.VarPath("containers", ct)
if shared.IsMountPoint(oldContainerMntPoint) {
- _, err := tryExec("zfs", "unmount", "-f", ctDataset)
+ _, err := shared.TryRunCommand("zfs", "unmount", "-f", ctDataset)
if err != nil {
shared.LogWarnf("Failed to unmount ZFS filesystem via zfs unmount. Trying lazy umount (MNT_DETACH)...")
err := tryUnmount(oldContainerMntPoint, syscall.MNT_DETACH)
@@ -1362,11 +1361,11 @@ func upgradeFromStorageTypeZfs(name string, d *Daemon, defaultPoolName string, d
// Set new mountpoint for the container's dataset it will be
// automatically mounted.
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"zfs",
"set",
fmt.Sprintf("mountpoint=%s", newContainerMntPoint),
- ctDataset).CombinedOutput()
+ ctDataset)
if err != nil {
shared.LogWarnf("Failed to set new ZFS mountpoint: %s.", output)
failedUpgradeEntities = append(failedUpgradeEntities, fmt.Sprintf("containers/%s: Failed to set new zfs mountpoint: %s", ct, err))
@@ -1482,7 +1481,7 @@ func upgradeFromStorageTypeZfs(name string, d *Daemon, defaultPoolName string, d
// around.
imageDataset := fmt.Sprintf("%s/images/%s", defaultPoolName, img)
if shared.PathExists(oldImageMntPoint) && shared.IsMountPoint(oldImageMntPoint) {
- _, err := tryExec("zfs", "unmount", "-f", imageDataset)
+ _, err := shared.TryRunCommand("zfs", "unmount", "-f", imageDataset)
if err != nil {
shared.LogWarnf("Failed to unmount ZFS filesystem via zfs unmount. Trying lazy umount (MNT_DETACH)...")
err := tryUnmount(oldImageMntPoint, syscall.MNT_DETACH)
@@ -1496,7 +1495,7 @@ func upgradeFromStorageTypeZfs(name string, d *Daemon, defaultPoolName string, d
// Set new mountpoint for the container's dataset it will be
// automatically mounted.
- output, err := exec.Command("zfs", "set", "mountpoint=none", imageDataset).CombinedOutput()
+ output, err := shared.RunCommand("zfs", "set", "mountpoint=none", imageDataset)
if err != nil {
shared.LogWarnf("Failed to set new ZFS mountpoint: %s.", output)
}
diff --git a/lxd/storage.go b/lxd/storage.go
index fb34784..d2b22ea 100644
--- a/lxd/storage.go
+++ b/lxd/storage.go
@@ -5,7 +5,6 @@ import (
"fmt"
"io"
"os"
- "os/exec"
"reflect"
"sync"
"sync/atomic"
@@ -124,7 +123,7 @@ func storageRsyncCopy(source string, dest string) (string, error) {
rsyncVerbosity = "-vi"
}
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"rsync",
"-a",
"-HAX",
@@ -134,9 +133,9 @@ func storageRsyncCopy(source string, dest string) (string, error) {
"--numeric-ids",
rsyncVerbosity,
shared.AddSlash(source),
- dest).CombinedOutput()
+ dest)
- return string(output), err
+ return output, err
}
// storageType defines the type of a storage
@@ -629,22 +628,6 @@ func ShiftIfNecessary(container container, srcIdmap *shared.IdmapSet) error {
}
// Useful functions for unreliable backends
-func tryExec(name string, arg ...string) ([]byte, error) {
- var err error
- var output []byte
-
- for i := 0; i < 20; i++ {
- output, err = exec.Command(name, arg...).CombinedOutput()
- if err == nil {
- break
- }
-
- time.Sleep(500 * time.Millisecond)
- }
-
- return output, err
-}
-
func tryMount(src string, dst string, fs string, flags uintptr, options string) error {
var err error
diff --git a/lxd/storage_btrfs.go b/lxd/storage_btrfs.go
index 5b08583..33abab6 100644
--- a/lxd/storage_btrfs.go
+++ b/lxd/storage_btrfs.go
@@ -59,12 +59,12 @@ func (s *storageBtrfs) StorageCoreInit() error {
return fmt.Errorf("The 'btrfs' tool isn't available")
}
- output, err := exec.Command("btrfs", "version").CombinedOutput()
+ output, err := shared.RunCommand("btrfs", "version")
if err != nil {
return fmt.Errorf("The 'btrfs' tool isn't working properly")
}
- count, err := fmt.Sscanf(strings.SplitN(string(output), " ", 2)[1], "v%s\n", &s.sTypeVersion)
+ count, err := fmt.Sscanf(strings.SplitN(output, " ", 2)[1], "v%s\n", &s.sTypeVersion)
if err != nil || count != 1 {
return fmt.Errorf("The 'btrfs' tool isn't working properly")
}
@@ -118,9 +118,9 @@ func (s *storageBtrfs) StoragePoolCreate() error {
return fmt.Errorf("Failed to create sparse file %s: %s", source, err)
}
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"mkfs.btrfs",
- "-L", s.pool.Name, source).CombinedOutput()
+ "-L", s.pool.Name, source)
if err != nil {
return fmt.Errorf("Failed to create the BTRFS pool: %s", output)
}
@@ -131,9 +131,9 @@ func (s *storageBtrfs) StoragePoolCreate() error {
if filepath.IsAbs(source) {
isBlockDev = shared.IsBlockdevPath(source)
if isBlockDev {
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"mkfs.btrfs",
- "-L", s.pool.Name, source).CombinedOutput()
+ "-L", s.pool.Name, source)
if err != nil {
return fmt.Errorf("Failed to create the BTRFS pool: %s", output)
}
@@ -210,8 +210,8 @@ func (s *storageBtrfs) StoragePoolCreate() error {
}
// Enable quotas
- output, err := exec.Command(
- "btrfs", "quota", "enable", poolMntPoint).CombinedOutput()
+ output, err := shared.RunCommand(
+ "btrfs", "quota", "enable", poolMntPoint)
if err != nil && !runningInUserns {
return fmt.Errorf("Failed to enable quotas on BTRFS pool: %s", output)
}
@@ -992,12 +992,12 @@ func (s *storageBtrfs) ContainerSetQuota(container container, size int64) error
return err
}
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"btrfs",
"qgroup",
"limit",
"-e", fmt.Sprintf("%d", size),
- subvol).CombinedOutput()
+ subvol)
if err != nil {
return fmt.Errorf("Failed to set btrfs quota: %s", output)
@@ -1346,13 +1346,13 @@ func btrfsSubVolumeCreate(subvol string) error {
}
}
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"btrfs",
"subvolume",
"create",
- subvol).CombinedOutput()
+ subvol)
if err != nil {
- shared.LogErrorf("Failed to create BTRFS subvolume \"%s\": %s.", subvol, string(output))
+ shared.LogErrorf("Failed to create BTRFS subvolume \"%s\": %s.", subvol, output)
return err
}
@@ -1360,20 +1360,20 @@ func btrfsSubVolumeCreate(subvol string) error {
}
func btrfsSubVolumeQGroup(subvol string) (string, error) {
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"btrfs",
"qgroup",
"show",
subvol,
"-e",
- "-f").CombinedOutput()
+ "-f")
if err != nil {
return "", fmt.Errorf("btrfs quotas not supported. Try enabling them with 'btrfs quota enable'.")
}
var qgroup string
- for _, line := range strings.Split(string(output), "\n") {
+ for _, line := range strings.Split(output, "\n") {
if line == "" || strings.HasPrefix(line, "qgroupid") || strings.HasPrefix(line, "---") {
continue
}
@@ -1394,19 +1394,19 @@ func btrfsSubVolumeQGroup(subvol string) (string, error) {
}
func (s *storageBtrfs) btrfsPoolVolumeQGroupUsage(subvol string) (int64, error) {
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"btrfs",
"qgroup",
"show",
subvol,
"-e",
- "-f").CombinedOutput()
+ "-f")
if err != nil {
return -1, fmt.Errorf("btrfs quotas not supported. Try enabling them with 'btrfs quota enable'.")
}
- for _, line := range strings.Split(string(output), "\n") {
+ for _, line := range strings.Split(output, "\n") {
if line == "" || strings.HasPrefix(line, "qgroupid") || strings.HasPrefix(line, "---") {
continue
}
@@ -1431,26 +1431,25 @@ func btrfsSubVolumeDelete(subvol string) error {
// Attempt (but don't fail on) to delete any qgroup on the subvolume
qgroup, err := btrfsSubVolumeQGroup(subvol)
if err == nil {
- exec.Command(
+ shared.RunCommand(
"btrfs",
"qgroup",
"destroy",
qgroup,
- subvol).Run()
+ subvol)
}
// Attempt to make the subvolume writable
- exec.Command("btrfs", "property", "set", subvol, "ro", "false").CombinedOutput()
+ shared.RunCommand("btrfs", "property", "set", subvol, "ro", "false")
// Delete the subvolume itself
- err = exec.Command(
+ _, err = shared.RunCommand(
"btrfs",
"subvolume",
"delete",
- subvol,
- ).Run()
+ subvol)
- return nil
+ return err
}
// btrfsPoolVolumesDelete is the recursive variant on btrfsPoolVolumeDelete,
@@ -1483,30 +1482,30 @@ func btrfsSubVolumesDelete(subvol string) error {
* the result will be readonly if "readonly" is True.
*/
func btrfsSnapshot(source string, dest string, readonly bool) error {
- var output []byte
+ var output string
var err error
if readonly {
- output, err = exec.Command(
+ output, err = shared.RunCommand(
"btrfs",
"subvolume",
"snapshot",
"-r",
source,
- dest).CombinedOutput()
+ dest)
} else {
- output, err = exec.Command(
+ output, err = shared.RunCommand(
"btrfs",
"subvolume",
"snapshot",
source,
- dest).CombinedOutput()
+ dest)
}
if err != nil {
return fmt.Errorf(
"subvolume snapshot failed, source=%s, dest=%s, output=%s",
source,
dest,
- string(output),
+ output,
)
}
@@ -1967,17 +1966,17 @@ func (s *storageBtrfs) MigrationSink(live bool, container container, snapshots [
}
func (s *storageBtrfs) btrfsLookupFsUUID(fs string) (string, error) {
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"btrfs",
"filesystem",
"show",
"--raw",
- fs).CombinedOutput()
+ fs)
if err != nil {
return "", fmt.Errorf("Failed to detect UUID.")
}
- outputString := string(output)
+ outputString := output
idx := strings.Index(outputString, "uuid: ")
outputString = outputString[idx+6:]
outputString = strings.TrimSpace(outputString)
diff --git a/lxd/storage_dir.go b/lxd/storage_dir.go
index 1e083e7..074c661 100644
--- a/lxd/storage_dir.go
+++ b/lxd/storage_dir.go
@@ -3,7 +3,6 @@ package main
import (
"fmt"
"os"
- "os/exec"
"path/filepath"
"strings"
@@ -320,9 +319,9 @@ func (s *storageDir) ContainerDelete(container container) error {
err := os.RemoveAll(containerMntPoint)
if err != nil {
// RemovaAll fails on very long paths, so attempt an rm -Rf
- output, err := exec.Command("rm", "-Rf", containerMntPoint).CombinedOutput()
+ output, err := shared.RunCommand("rm", "-Rf", containerMntPoint)
if err != nil {
- return fmt.Errorf("Error removing %s: %s.", containerMntPoint, string(output))
+ return fmt.Errorf("Error removing %s: %s.", containerMntPoint, output)
}
}
}
diff --git a/lxd/storage_lvm.go b/lxd/storage_lvm.go
index 75b767c..2f3e364 100644
--- a/lxd/storage_lvm.go
+++ b/lxd/storage_lvm.go
@@ -16,25 +16,25 @@ import (
)
func storageVGActivate(lvmVolumePath string) error {
- output, err := tryExec("vgchange", "-ay", lvmVolumePath)
+ output, err := shared.TryRunCommand("vgchange", "-ay", lvmVolumePath)
if err != nil {
- return fmt.Errorf("Could not activate volume group \"%s\": %s.", lvmVolumePath, string(output))
+ return fmt.Errorf("Could not activate volume group \"%s\": %s.", lvmVolumePath, output)
}
return nil
}
func storageLVActivate(lvmVolumePath string, readonly bool) error {
- var output []byte
+ var output string
var err error
if readonly {
- output, err = tryExec("lvchange", "-ay", "-pr", lvmVolumePath)
+ output, err = shared.TryRunCommand("lvchange", "-ay", "-pr", lvmVolumePath)
} else {
- output, err = tryExec("lvchange", "-ay", lvmVolumePath)
+ output, err = shared.TryRunCommand("lvchange", "-ay", lvmVolumePath)
}
if err != nil {
- return fmt.Errorf("Could not activate logival volume \"%s\": %s.", lvmVolumePath, string(output))
+ return fmt.Errorf("Could not activate logival volume \"%s\": %s.", lvmVolumePath, output)
}
return nil
@@ -174,30 +174,30 @@ func storageLVMValidateThinPoolName(d *Daemon, vgName string, value string) erro
}
func lvmVGRename(oldName string, newName string) error {
- output, err := tryExec("vgrename", oldName, newName)
+ output, err := shared.TryRunCommand("vgrename", oldName, newName)
if err != nil {
- return fmt.Errorf("Could not rename volume group from \"%s\" to \"%s\": %s.", oldName, newName, string(output))
+ return fmt.Errorf("Could not rename volume group from \"%s\" to \"%s\": %s.", oldName, newName, output)
}
return nil
}
func lvmLVRename(vgName string, oldName string, newName string) error {
- output, err := tryExec("lvrename", vgName, oldName, newName)
+ output, err := shared.TryRunCommand("lvrename", vgName, oldName, newName)
if err != nil {
- return fmt.Errorf("Could not rename volume group from \"%s\" to \"%s\": %s.", oldName, newName, string(output))
+ return fmt.Errorf("Could not rename volume group from \"%s\" to \"%s\": %s.", oldName, newName, output)
}
return nil
}
func xfsGenerateNewUUID(lvpath string) error {
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"xfs_admin",
"-U", "generate",
- lvpath).CombinedOutput()
+ lvpath)
if err != nil {
- return fmt.Errorf("Error generating new UUID: %v\noutput:'%s'", err, string(output))
+ return fmt.Errorf("Error generating new UUID: %v\noutput:'%s'", err, output)
}
return nil
@@ -299,11 +299,11 @@ func (s *storageLvm) StorageCoreInit() error {
}
s.sTypeName = typeName
- output, err := exec.Command("lvm", "version").CombinedOutput()
+ output, err := shared.RunCommand("lvm", "version")
if err != nil {
- return fmt.Errorf("Error getting LVM version: %v\noutput:'%s'", err, string(output))
+ return fmt.Errorf("Error getting LVM version: %v\noutput:'%s'", err, output)
}
- lines := strings.Split(string(output), "\n")
+ lines := strings.Split(output, "\n")
s.sTypeVersion = ""
for idx, line := range lines {
@@ -477,18 +477,18 @@ func (s *storageLvm) StoragePoolCreate() error {
ok, err := storagePVExists(loopDevicePath)
if err == nil && !ok {
// Create a new lvm physical volume.
- output, err := exec.Command("pvcreate", loopDevicePath).CombinedOutput()
+ output, err := shared.RunCommand("pvcreate", loopDevicePath)
if err != nil {
return fmt.Errorf("Failed to create the physical volume for the lvm storage pool: %s.", output)
}
defer func() {
if tryUndo {
- exec.Command("pvremove", loopDevicePath).Run()
+ shared.RunCommand("pvremove", loopDevicePath)
}
}()
}
- msg, err := tryExec("pvscan")
+ msg, err := shared.TryRunCommand("pvscan")
if err != nil {
shared.LogWarnf("Failed to run pvscan: %s.", msg)
}
@@ -497,13 +497,13 @@ func (s *storageLvm) StoragePoolCreate() error {
ok, err = storageVGExists(poolName)
if err == nil && !ok {
// Create a volume group on the physical volume.
- output, err := exec.Command("vgcreate", poolName, loopDevicePath).CombinedOutput()
+ output, err := shared.RunCommand("vgcreate", poolName, loopDevicePath)
if err != nil {
return fmt.Errorf("Failed to create the volume group for the lvm storage pool: %s.", output)
}
}
- msg, err = tryExec("vgscan")
+ msg, err = shared.TryRunCommand("vgscan")
if err != nil {
shared.LogWarnf("Failed to run vgscan: %s.", msg)
}
@@ -525,18 +525,18 @@ func (s *storageLvm) StoragePoolCreate() error {
ok, err := storagePVExists(source)
if err == nil && !ok {
// Create a new lvm physical volume.
- output, err := exec.Command("pvcreate", source).CombinedOutput()
+ output, err := shared.RunCommand("pvcreate", source)
if err != nil {
return fmt.Errorf("Failed to create the physical volume for the lvm storage pool: %s.", output)
}
defer func() {
if tryUndo {
- exec.Command("pvremove", source).Run()
+ shared.RunCommand("pvremove", source)
}
}()
}
- msg, err := tryExec("pvscan")
+ msg, err := shared.TryRunCommand("pvscan")
if err != nil {
shared.LogWarnf("Failed to run pvscan: %s.", msg)
}
@@ -545,13 +545,13 @@ func (s *storageLvm) StoragePoolCreate() error {
ok, err = storageVGExists(poolName)
if err == nil && !ok {
// Create a volume group on the physical volume.
- output, err := exec.Command("vgcreate", poolName, source).CombinedOutput()
+ output, err := shared.RunCommand("vgcreate", poolName, source)
if err != nil {
return fmt.Errorf("Failed to create the volume group for the lvm storage pool: %s.", output)
}
}
- msg, err = tryExec("vgscan")
+ msg, err = shared.TryRunCommand("vgscan")
if err != nil {
shared.LogWarnf("Failed to run vgscan: %s.", msg)
}
@@ -605,7 +605,7 @@ func (s *storageLvm) StoragePoolDelete() error {
poolName := s.getOnDiskPoolName()
// Remove the volume group.
- output, err := exec.Command("vgremove", "-f", poolName).CombinedOutput()
+ output, err := shared.RunCommand("vgremove", "-f", poolName)
if err != nil {
return fmt.Errorf("Failed to destroy the volume group for the lvm storage pool: %s.", output)
}
@@ -1877,30 +1877,30 @@ func (s *storageLvm) createThinLV(vgName string, thinPoolName string, lvName str
lvmThinPoolPath := fmt.Sprintf("%s/%s", vgName, thinPoolName)
lvmPoolVolumeName := getPrefixedLvName(volumeType, lvName)
- output, err := tryExec(
+ output, err := shared.TryRunCommand(
"lvcreate",
"--thin",
"-n", lvmPoolVolumeName,
"--virtualsize", lvSize+"B", lvmThinPoolPath)
if err != nil {
- shared.LogErrorf("Could not create LV \"%s\": %s.", lvmPoolVolumeName, string(output))
+ shared.LogErrorf("Could not create LV \"%s\": %s.", lvmPoolVolumeName, output)
return fmt.Errorf("Could not create thin LV named %s", lvmPoolVolumeName)
}
fsPath := getLvmDevPath(vgName, volumeType, lvName)
switch lvFsType {
case "xfs":
- output, err = tryExec("mkfs.xfs", fsPath)
+ output, err = shared.TryRunCommand("mkfs.xfs", fsPath)
default:
// default = ext4
- output, err = tryExec(
+ output, err = shared.TryRunCommand(
"mkfs.ext4",
"-E", "nodiscard,lazy_itable_init=0,lazy_journal_init=0",
fsPath)
}
if err != nil {
- shared.LogErrorf("Filesystem creation failed: %s.", string(output))
+ shared.LogErrorf("Filesystem creation failed: %s.", output)
return fmt.Errorf("Error making filesystem on image LV: %v", err)
}
@@ -1915,15 +1915,15 @@ func (s *storageLvm) createDefaultThinPool(vgName string, thinPoolName string, l
// Create the thin pool
lvmThinPool := fmt.Sprintf("%s/%s", vgName, thinPoolName)
- var output []byte
+ var output string
if isRecent {
- output, err = tryExec(
+ output, err = shared.TryRunCommand(
"lvcreate",
"--poolmetadatasize", "1G",
"-l", "100%FREE",
"--thinpool", lvmThinPool)
} else {
- output, err = tryExec(
+ output, err = shared.TryRunCommand(
"lvcreate",
"--poolmetadatasize", "1G",
"-L", "1G",
@@ -1931,16 +1931,16 @@ func (s *storageLvm) createDefaultThinPool(vgName string, thinPoolName string, l
}
if err != nil {
- shared.LogErrorf("Could not create thin pool \"%s\": %s.", thinPoolName, string(output))
+ shared.LogErrorf("Could not create thin pool \"%s\": %s.", thinPoolName, output)
return fmt.Errorf("Could not create LVM thin pool named %s", thinPoolName)
}
if !isRecent {
// Grow it to the maximum VG size (two step process required by old LVM)
- output, err = tryExec("lvextend", "--alloc", "anywhere", "-l", "100%FREE", lvmThinPool)
+ output, err = shared.TryRunCommand("lvextend", "--alloc", "anywhere", "-l", "100%FREE", lvmThinPool)
if err != nil {
- shared.LogErrorf("Could not grow thin pool: \"%s\": %s.", thinPoolName, string(output))
+ shared.LogErrorf("Could not grow thin pool: \"%s\": %s.", thinPoolName, output)
return fmt.Errorf("Could not grow LVM thin pool named %s", thinPoolName)
}
}
@@ -1950,10 +1950,10 @@ func (s *storageLvm) createDefaultThinPool(vgName string, thinPoolName string, l
func (s *storageLvm) removeLV(vgName string, volumeType string, lvName string) error {
lvmVolumePath := getLvmDevPath(vgName, volumeType, lvName)
- output, err := tryExec("lvremove", "-f", lvmVolumePath)
+ output, err := shared.TryRunCommand("lvremove", "-f", lvmVolumePath)
if err != nil {
- shared.LogErrorf("Could not remove LV \"%s\": %s.", lvName, string(output))
+ shared.LogErrorf("Could not remove LV \"%s\": %s.", lvName, output)
return fmt.Errorf("Could not remove LV named %s", lvName)
}
@@ -1969,21 +1969,21 @@ func (s *storageLvm) createSnapshotLV(vgName string, origLvName string, origVolu
}
lvmPoolVolumeName := getPrefixedLvName(volumeType, lvName)
- var output []byte
+ var output string
if isRecent {
- output, err = tryExec(
+ output, err = shared.TryRunCommand(
"lvcreate",
"-kn",
"-n", lvmPoolVolumeName,
"-s", sourceLvmVolumePath)
} else {
- output, err = tryExec(
+ output, err = shared.TryRunCommand(
"lvcreate",
"-n", lvmPoolVolumeName,
"-s", sourceLvmVolumePath)
}
if err != nil {
- shared.LogErrorf("Could not create LV snapshot: %s -> %s: %s.", origLvName, lvName, string(output))
+ shared.LogErrorf("Could not create LV snapshot: %s -> %s: %s.", origLvName, lvName, output)
return "", fmt.Errorf("Could not create snapshot LV named %s", lvName)
}
diff --git a/lxd/storage_shared.go b/lxd/storage_shared.go
index c3730f9..64bb980 100644
--- a/lxd/storage_shared.go
+++ b/lxd/storage_shared.go
@@ -2,7 +2,6 @@ package main
import (
"fmt"
- "os/exec"
"github.com/lxc/lxd/shared"
"github.com/lxc/lxd/shared/api"
@@ -82,13 +81,13 @@ func (s *storageShared) setUnprivUserAcl(c container, destPath string) error {
// Attempt to set a POSIX ACL first.
acl := fmt.Sprintf("%d:rx", uid)
- err = exec.Command("setfacl", "-m", acl, destPath).Run()
+ _, err = shared.RunCommand("setfacl", "-m", acl, destPath)
if err == nil {
return nil
}
// Fallback to chmod if the fs doesn't support it.
- err = exec.Command("chmod", "+x", destPath).Run()
+ _, err = shared.RunCommand("chmod", "+x", destPath)
if err != nil {
shared.LogDebugf("Failed to set executable bit on the container path: %s", err)
return err
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index 6079380..e521b5b 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -107,12 +107,12 @@ func (s *storageZfs) StoragePoolCheck() error {
shared.LogDebugf("ZFS storage pool \"%s\" does not exist. Trying to import it.", poolName)
disksPath := shared.VarPath("disks")
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"zpool",
"import",
- "-d", disksPath, poolName).CombinedOutput()
+ "-d", disksPath, poolName)
if err != nil {
- return fmt.Errorf("ZFS storage pool \"%s\" could not be imported: %s.", poolName, string(output))
+ return fmt.Errorf("ZFS storage pool \"%s\" could not be imported: %s.", poolName, output)
}
shared.LogDebugf("ZFS storage pool \"%s\" successfully imported.", poolName)
@@ -1446,13 +1446,13 @@ func (s *storageZfs) ImageUmount(fingerprint string) (bool, error) {
// Helper functions
func (s *storageZfs) zfsPoolCheck(pool string) error {
- output, err := exec.Command(
- "zfs", "get", "type", "-H", "-o", "value", pool).CombinedOutput()
+ output, err := shared.RunCommand(
+ "zfs", "get", "type", "-H", "-o", "value", pool)
if err != nil {
- return fmt.Errorf(strings.Split(string(output), "\n")[0])
+ return fmt.Errorf(strings.Split(output, "\n")[0])
}
- poolType := strings.Split(string(output), "\n")[0]
+ poolType := strings.Split(output, "\n")[0]
if poolType != "filesystem" {
return fmt.Errorf("Unsupported pool type: %s", poolType)
}
@@ -1491,10 +1491,10 @@ func (s *storageZfs) zfsPoolCreate() error {
return fmt.Errorf("Failed to create sparse file %s: %s", vdev, err)
}
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"zpool",
"create", zpoolName, vdev,
- "-f", "-m", "none", "-O", "compression=on").CombinedOutput()
+ "-f", "-m", "none", "-O", "compression=on")
if err != nil {
return fmt.Errorf("Failed to create the ZFS pool: %s", output)
}
@@ -1519,10 +1519,10 @@ func (s *storageZfs) zfsPoolCreate() error {
// safest way is to just store the name of the zfs pool
// we create.
s.pool.Config["source"] = zpoolName
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"zpool",
"create", zpoolName, vdev,
- "-f", "-m", "none", "-O", "compression=on").CombinedOutput()
+ "-f", "-m", "none", "-O", "compression=on")
if err != nil {
return fmt.Errorf("Failed to create the ZFS pool: %s", output)
}
@@ -1536,15 +1536,15 @@ func (s *storageZfs) zfsPoolCreate() error {
if strings.Contains(vdev, "/") {
ok := s.zfsFilesystemEntityExists(vdev, false)
if !ok {
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"zfs",
"create",
"-p",
"-o",
"mountpoint=none",
- vdev).CombinedOutput()
+ vdev)
if err != nil {
- shared.LogErrorf("zfs create failed: %s.", string(output))
+ shared.LogErrorf("zfs create failed: %s.", output)
return fmt.Errorf("Failed to create ZFS filesystem: %s", output)
}
}
@@ -1613,15 +1613,15 @@ func (s *storageZfs) zfsPoolCreate() error {
func (s *storageZfs) zfsPoolVolumeClone(source string, name string, dest string, mountpoint string) error {
poolName := s.getOnDiskPoolName()
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"zfs",
"clone",
"-p",
"-o", fmt.Sprintf("mountpoint=%s", mountpoint),
fmt.Sprintf("%s/%s@%s", poolName, source, name),
- fmt.Sprintf("%s/%s", poolName, dest)).CombinedOutput()
+ fmt.Sprintf("%s/%s", poolName, dest))
if err != nil {
- shared.LogErrorf("zfs clone failed: %s.", string(output))
+ shared.LogErrorf("zfs clone failed: %s.", output)
return fmt.Errorf("Failed to clone the filesystem: %s", output)
}
@@ -1643,15 +1643,15 @@ func (s *storageZfs) zfsPoolVolumeClone(source string, name string, dest string,
destSubvol := dest + strings.TrimPrefix(sub, source)
snapshotMntPoint := getSnapshotMountPoint(s.pool.Name, destSubvol)
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"zfs",
"clone",
"-p",
"-o", fmt.Sprintf("mountpoint=%s", snapshotMntPoint),
fmt.Sprintf("%s/%s@%s", poolName, sub, name),
- fmt.Sprintf("%s/%s", poolName, destSubvol)).CombinedOutput()
+ fmt.Sprintf("%s/%s", poolName, destSubvol))
if err != nil {
- shared.LogErrorf("zfs clone failed: %s.", string(output))
+ shared.LogErrorf("zfs clone failed: %s.", output)
return fmt.Errorf("Failed to clone the sub-volume: %s", output)
}
}
@@ -1661,13 +1661,13 @@ func (s *storageZfs) zfsPoolVolumeClone(source string, name string, dest string,
func (s *storageZfs) zfsPoolVolumeCreate(path string) error {
poolName := s.getOnDiskPoolName()
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"zfs",
"create",
"-p",
- fmt.Sprintf("%s/%s", poolName, path)).CombinedOutput()
+ fmt.Sprintf("%s/%s", poolName, path))
if err != nil {
- shared.LogErrorf("zfs create failed: %s.", string(output))
+ shared.LogErrorf("zfs create failed: %s.", output)
return fmt.Errorf("Failed to create ZFS filesystem: %s", output)
}
@@ -1675,15 +1675,15 @@ func (s *storageZfs) zfsPoolVolumeCreate(path string) error {
}
func (s *storageZfs) zfsFilesystemEntityDelete() error {
- var output []byte
+ var output string
var err error
poolName := s.getOnDiskPoolName()
if strings.Contains(poolName, "/") {
// Command to destroy a zfs dataset.
- output, err = exec.Command("zfs", "destroy", "-r", poolName).CombinedOutput()
+ output, err = shared.RunCommand("zfs", "destroy", "-r", poolName)
} else {
// Command to destroy a zfs pool.
- output, err = exec.Command("zpool", "destroy", "-f", poolName).CombinedOutput()
+ output, err = shared.RunCommand("zpool", "destroy", "-f", poolName)
}
if err != nil {
return fmt.Errorf("Failed to delete the ZFS pool: %s", output)
@@ -1714,14 +1714,14 @@ func (s *storageZfs) zfsPoolVolumeDestroy(path string) error {
poolName := s.getOnDiskPoolName()
// Due to open fds or kernel refs, this may fail for a bit, give it 10s
- output, err := tryExec(
+ output, err := shared.TryRunCommand(
"zfs",
"destroy",
"-r",
fmt.Sprintf("%s/%s", poolName, path))
if err != nil {
- shared.LogErrorf("zfs destroy failed: %s.", string(output))
+ shared.LogErrorf("zfs destroy failed: %s.", output)
return fmt.Errorf("Failed to destroy ZFS filesystem: %s", output)
}
@@ -1818,33 +1818,33 @@ func (s *storageZfs) zfsFilesystemEntityPropertyGet(path string, key string, pre
fsToCheck = fmt.Sprintf("%s/%s", s.getOnDiskPoolName(), path)
}
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"zfs",
"get",
"-H",
"-p",
"-o", "value",
key,
- fsToCheck).CombinedOutput()
+ fsToCheck)
if err != nil {
- return string(output), fmt.Errorf("Failed to get ZFS config: %s", output)
+ return "", fmt.Errorf("Failed to get ZFS config: %s", output)
}
- return strings.TrimRight(string(output), "\n"), nil
+ return strings.TrimRight(output, "\n"), nil
}
func (s *storageZfs) zfsPoolVolumeRename(source string, dest string) error {
var err error
- var output []byte
+ var output string
poolName := s.getOnDiskPoolName()
for i := 0; i < 20; i++ {
- output, err = exec.Command(
+ output, err = shared.RunCommand(
"zfs",
"rename",
"-p",
fmt.Sprintf("%s/%s", poolName, source),
- fmt.Sprintf("%s/%s", poolName, dest)).CombinedOutput()
+ fmt.Sprintf("%s/%s", poolName, dest))
// Success
if err == nil {
@@ -1860,19 +1860,19 @@ func (s *storageZfs) zfsPoolVolumeRename(source string, dest string) error {
}
// Timeout
- shared.LogErrorf("zfs rename failed: %s.", string(output))
+ shared.LogErrorf("zfs rename failed: %s.", output)
return fmt.Errorf("Failed to rename ZFS filesystem: %s", output)
}
func (s *storageZfs) zfsPoolVolumeSet(path string, key string, value string) error {
poolName := s.getOnDiskPoolName()
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"zfs",
"set",
fmt.Sprintf("%s=%s", key, value),
- fmt.Sprintf("%s/%s", poolName, path)).CombinedOutput()
+ fmt.Sprintf("%s/%s", poolName, path))
if err != nil {
- shared.LogErrorf("zfs set failed: %s.", string(output))
+ shared.LogErrorf("zfs set failed: %s.", output)
return fmt.Errorf("Failed to set ZFS config: %s", output)
}
@@ -1881,13 +1881,13 @@ func (s *storageZfs) zfsPoolVolumeSet(path string, key string, value string) err
func (s *storageZfs) zfsPoolVolumeSnapshotCreate(path string, name string) error {
poolName := s.getOnDiskPoolName()
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"zfs",
"snapshot",
"-r",
- fmt.Sprintf("%s/%s@%s", poolName, path, name)).CombinedOutput()
+ fmt.Sprintf("%s/%s@%s", poolName, path, name))
if err != nil {
- shared.LogErrorf("zfs snapshot failed: %s.", string(output))
+ shared.LogErrorf("zfs snapshot failed: %s.", output)
return fmt.Errorf("Failed to create ZFS snapshot: %s", output)
}
@@ -1896,13 +1896,13 @@ func (s *storageZfs) zfsPoolVolumeSnapshotCreate(path string, name string) error
func (s *storageZfs) zfsPoolVolumeSnapshotDestroy(path string, name string) error {
poolName := s.getOnDiskPoolName()
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"zfs",
"destroy",
"-r",
- fmt.Sprintf("%s/%s@%s", poolName, path, name)).CombinedOutput()
+ fmt.Sprintf("%s/%s@%s", poolName, path, name))
if err != nil {
- shared.LogErrorf("zfs destroy failed: %s.", string(output))
+ shared.LogErrorf("zfs destroy failed: %s.", output)
return fmt.Errorf("Failed to destroy ZFS snapshot: %s", output)
}
@@ -1911,12 +1911,12 @@ func (s *storageZfs) zfsPoolVolumeSnapshotDestroy(path string, name string) erro
func (s *storageZfs) zfsPoolVolumeSnapshotRestore(path string, name string) error {
poolName := s.getOnDiskPoolName()
- output, err := tryExec(
+ output, err := shared.TryRunCommand(
"zfs",
"rollback",
fmt.Sprintf("%s/%s@%s", poolName, path, name))
if err != nil {
- shared.LogErrorf("zfs rollback failed: %s.", string(output))
+ shared.LogErrorf("zfs rollback failed: %s.", output)
return fmt.Errorf("Failed to restore ZFS snapshot: %s", output)
}
@@ -1935,12 +1935,12 @@ func (s *storageZfs) zfsPoolVolumeSnapshotRestore(path string, name string) erro
continue
}
- output, err := tryExec(
+ output, err := shared.TryRunCommand(
"zfs",
"rollback",
fmt.Sprintf("%s/%s@%s", poolName, sub, name))
if err != nil {
- shared.LogErrorf("zfs rollback failed: %s.", string(output))
+ shared.LogErrorf("zfs rollback failed: %s.", output)
return fmt.Errorf("Failed to restore ZFS sub-volume snapshot: %s", output)
}
}
@@ -1950,14 +1950,14 @@ func (s *storageZfs) zfsPoolVolumeSnapshotRestore(path string, name string) erro
func (s *storageZfs) zfsPoolVolumeSnapshotRename(path string, oldName string, newName string) error {
poolName := s.getOnDiskPoolName()
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"zfs",
"rename",
"-r",
fmt.Sprintf("%s/%s@%s", poolName, path, oldName),
- fmt.Sprintf("%s/%s@%s", poolName, path, newName)).CombinedOutput()
+ fmt.Sprintf("%s/%s@%s", poolName, path, newName))
if err != nil {
- shared.LogErrorf("zfs snapshot rename failed: %s.", string(output))
+ shared.LogErrorf("zfs snapshot rename failed: %s.", output)
return fmt.Errorf("Failed to rename ZFS snapshot: %s", output)
}
@@ -1965,7 +1965,7 @@ func (s *storageZfs) zfsPoolVolumeSnapshotRename(path string, oldName string, ne
}
func zfsMount(poolName string, path string) error {
- output, err := tryExec(
+ output, err := shared.TryRunCommand(
"zfs",
"mount",
fmt.Sprintf("%s/%s", poolName, path))
@@ -1981,7 +1981,7 @@ func (s *storageZfs) zfsPoolVolumeMount(path string) error {
}
func zfsUmount(poolName string, path string) error {
- output, err := tryExec(
+ output, err := shared.TryRunCommand(
"zfs",
"unmount",
fmt.Sprintf("%s/%s", poolName, path))
@@ -1997,20 +1997,20 @@ func (s *storageZfs) zfsPoolVolumeUmount(path string) error {
}
func (s *storageZfs) zfsPoolListSubvolumes(path string) ([]string, error) {
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"zfs",
"list",
"-t", "filesystem",
"-o", "name",
"-H",
- "-r", path).CombinedOutput()
+ "-r", path)
if err != nil {
- shared.LogErrorf("zfs list failed: %s.", string(output))
+ shared.LogErrorf("zfs list failed: %s.", output)
return []string{}, fmt.Errorf("Failed to list ZFS filesystems: %s", output)
}
children := []string{}
- for _, entry := range strings.Split(string(output), "\n") {
+ for _, entry := range strings.Split(output, "\n") {
if entry == "" {
continue
}
@@ -2034,7 +2034,7 @@ func (s *storageZfs) zfsPoolListSnapshots(path string) ([]string, error) {
fullPath = fmt.Sprintf("%s/%s", poolName, path)
}
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"zfs",
"list",
"-t", "snapshot",
@@ -2042,14 +2042,14 @@ func (s *storageZfs) zfsPoolListSnapshots(path string) ([]string, error) {
"-H",
"-d", "1",
"-s", "creation",
- "-r", fullPath).CombinedOutput()
+ "-r", fullPath)
if err != nil {
- shared.LogErrorf("zfs list failed: %s.", string(output))
+ shared.LogErrorf("zfs list failed: %s.", output)
return []string{}, fmt.Errorf("Failed to list ZFS snapshots: %s", output)
}
children := []string{}
- for _, entry := range strings.Split(string(output), "\n") {
+ for _, entry := range strings.Split(output, "\n") {
if entry == "" {
continue
}
@@ -2120,19 +2120,19 @@ func (s *storageZfs) zfsPoolGetUsers() ([]string, error) {
}
func zfsFilesystemEntityExists(zfsEntity string) bool {
- output, err := exec.Command(
+ output, err := shared.RunCommand(
"zfs",
"get",
"type",
"-H",
"-o",
"name",
- zfsEntity).CombinedOutput()
+ zfsEntity)
if err != nil {
return false
}
- detectedName := strings.TrimSpace(string(output))
+ detectedName := strings.TrimSpace(output)
if detectedName != zfsEntity {
return false
}
diff --git a/lxd/util.go b/lxd/util.go
index cce5ffb..e85a5a8 100644
--- a/lxd/util.go
+++ b/lxd/util.go
@@ -63,5 +63,6 @@ func loadModule(module string) error {
return nil
}
- return shared.RunCommand("modprobe", module)
+ _, err := shared.RunCommand("modprobe", module)
+ return err
}
diff --git a/shared/util.go b/shared/util.go
index a25848c..4e829ea 100644
--- a/shared/util.go
+++ b/shared/util.go
@@ -455,12 +455,12 @@ func IsBlockdevPath(pathName string) bool {
}
func BlockFsDetect(dev string) (string, error) {
- out, err := exec.Command("blkid", "-s", "TYPE", "-o", "value", dev).Output()
+ out, err := RunCommand("blkid", "-s", "TYPE", "-o", "value", dev)
if err != nil {
- return "", fmt.Errorf("Failed to run blkid on: %s", dev)
+ return "", err
}
- return strings.TrimSpace(string(out)), nil
+ return strings.TrimSpace(out), nil
}
// DeepCopy copies src to dest by using encoding/gob so its not that fast.
@@ -756,13 +756,29 @@ func RemoveDuplicatesFromString(s string, sep string) string {
return s
}
-func RunCommand(name string, arg ...string) error {
+func RunCommand(name string, arg ...string) (string, error) {
output, err := exec.Command(name, arg...).CombinedOutput()
if err != nil {
- return fmt.Errorf("Failed to run: %s %s: %s", name, strings.Join(arg, " "), strings.TrimSpace(string(output)))
+ return "", fmt.Errorf("Failed to run: %s %s: %s", name, strings.Join(arg, " "), strings.TrimSpace(string(output)))
}
- return nil
+ return string(output), nil
+}
+
+func TryRunCommand(name string, arg ...string) (string, error) {
+ var err error
+ var output string
+
+ for i := 0; i < 20; i++ {
+ output, err = RunCommand(name, arg...)
+ if err == nil {
+ break
+ }
+
+ time.Sleep(500 * time.Millisecond)
+ }
+
+ return output, err
}
func TimeIsSet(ts time.Time) bool {
diff --git a/shared/util_linux.go b/shared/util_linux.go
index a92e595..68310cb 100644
--- a/shared/util_linux.go
+++ b/shared/util_linux.go
@@ -369,7 +369,7 @@ func GetFileStat(p string) (uid int, gid int, major int, minor int,
func IsMountPoint(name string) bool {
_, err := exec.LookPath("mountpoint")
if err == nil {
- err = exec.Command("mountpoint", "-q", name).Run()
+ _, err = RunCommand("mountpoint", "-q", name)
if err != nil {
return false
}
More information about the lxc-devel
mailing list