github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/container/kvm/run_linux.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  // +build linux
     5  
     6  package kvm
     7  
     8  import (
     9  	"os/exec"
    10  	"os/user"
    11  	"strconv"
    12  	"syscall"
    13  
    14  	"github.com/juju/errors"
    15  )
    16  
    17  // run the command as user libvirt-qemu and return the combined output.
    18  func runAsLibvirt(command string, args ...string) (string, error) {
    19  	uid, gid, err := getUserUIDGID(libvirtUser)
    20  	if err != nil {
    21  		return "", errors.Trace(err)
    22  	}
    23  
    24  	logger.Debugf("running: %s %v", command, args)
    25  	logger.Debugf("running as uid: %d, gid: %d\n", uid, gid)
    26  
    27  	cmd := exec.Command(command, args...)
    28  	cmd.SysProcAttr = &syscall.SysProcAttr{}
    29  	cmd.SysProcAttr.Credential = &syscall.Credential{
    30  		Uid: uint32(uid),
    31  		Gid: uint32(gid),
    32  	}
    33  
    34  	out, err := cmd.CombinedOutput()
    35  	output := string(out)
    36  	logger.Debugf("output: %v", output)
    37  
    38  	return output, err
    39  
    40  }
    41  
    42  // getUserUIDGID returns integervals for uid and gid for the user. It returns
    43  // -1 when there's an error so no one accidentally thinks 0 is the appropriate
    44  // uid/gid when there's an error.
    45  func getUserUIDGID(name string) (int, int, error) {
    46  	u, err := user.Lookup(libvirtUser)
    47  	if err != nil {
    48  		return -1, -1, errors.Trace(err)
    49  	}
    50  	uid, err := strconv.ParseUint(u.Uid, 10, 32)
    51  	if err != nil {
    52  		return -1, -1, errors.Trace(err)
    53  	}
    54  	gid, err := strconv.ParseUint(u.Gid, 10, 32)
    55  	if err != nil {
    56  		return -1, -1, errors.Trace(err)
    57  	}
    58  	return int(uid), int(gid), nil
    59  }