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 }