- add command executor

- host prepare for deploy on container
- procutils adpat to executor
This commit is contained in:
wanyaoqi
2019-07-13 10:37:01 +08:00
parent b5cddd294e
commit 7bf48c992e
56 changed files with 3091 additions and 771 deletions
+5 -4
View File
@@ -79,10 +79,11 @@ func init() {
}, syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)
signalutils.StartTrap()
cmd := procutils.NewCommand("go", "tool")
cmd.Args = append(cmd.Args, args...)
cmd.Args = append(cmd.Args, tempfile)
if _, err := cmd.Run(); err != nil {
argv := []string{"tool"}
argv = append(argv, args...)
argv = append(argv, tempfile)
cmd := procutils.NewCommand("go", argv...)
if err := cmd.Run(); err != nil {
return err
}
return nil
+95
View File
@@ -0,0 +1,95 @@
package main
import (
"flag"
"net"
"os"
"strings"
"google.golang.org/grpc"
"yunion.io/x/executor/apis"
"yunion.io/x/executor/server"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/util/sysutils"
)
var socketPath string
func init() {
flag.StringVar(&socketPath, "socket-path", "/var/run/exec.sock", "execute service listen socket path")
}
func main() {
if !sysutils.IsRootPermission() {
log.Fatalln("executor must run on root permission")
}
Serve()
}
type SExecuteService struct {
}
func NewExecuteService() *SExecuteService {
return &SExecuteService{}
}
func (s *SExecuteService) fixPathEnv() error {
var paths = []string{
"/usr/local/sbin",
"/usr/local/bin",
"/sbin",
"/bin",
"/usr/sbin",
"/usr/bin",
}
return os.Setenv("PATH", strings.Join(paths, ":"))
}
func (s *SExecuteService) prepareEnv() error {
if err := s.fixPathEnv(); err != nil {
return err
}
return nil
}
func (s *SExecuteService) runService() {
grpcServer := grpc.NewServer()
apis.RegisterExecutorServer(grpcServer, &server.Executor{})
if _, err := os.Stat(socketPath); !os.IsNotExist(err) {
// socket file already exist, remove first
if err := os.Remove(socketPath); err != nil {
log.Fatalln(err)
}
}
listener, err := net.Listen("unix", socketPath)
if err != nil {
log.Fatalln(err)
}
defer listener.Close()
log.Infof("Init net listener on %s succ", socketPath)
err = grpcServer.Serve(listener)
if err != nil {
log.Fatalln(err)
}
}
func (s *SExecuteService) initService() {
if len(socketPath) == 0 {
log.Fatalf("missing socket path")
}
if err := s.prepareEnv(); err != nil {
log.Fatalln(err)
}
}
func (s *SExecuteService) Run() {
s.initService()
s.runService()
}
func Serve() {
NewExecuteService().Run()
}
+1
View File
@@ -132,6 +132,7 @@ require (
k8s.io/client-go v9.0.0+incompatible
k8s.io/klog v0.1.0 // indirect
k8s.io/kubernetes v1.12.3
yunion.io/x/executor v0.0.0-20191202093616-92e2e6119257
yunion.io/x/jsonutils v0.0.0-20191005115334-bb1c187fc0e7
yunion.io/x/log v0.0.0-20190629062853-9f6483a7103d
yunion.io/x/pkg v0.0.0-20191121110824-e03b47b93fe0
+4
View File
@@ -608,6 +608,7 @@ google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRn
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.1 h1:q4XQuHFC6I28BKZpo6IYyb3mNO+l7lSOxRuYTCiDfXk=
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
@@ -653,6 +654,8 @@ k8s.io/kubernetes v1.12.3 h1:5GPfYyyBylqcZUqL+ApYpYTm2IYjH56JUewYC0GbetU=
k8s.io/kubernetes v1.12.3/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
yunion.io/x/executor v0.0.0-20191202093616-92e2e6119257 h1:LZ6eC1uoLDAp7NQlaCy+DKnF31Mgd3LDKlIithziEmY=
yunion.io/x/executor v0.0.0-20191202093616-92e2e6119257/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051 h1:vtZw2iwGrsARNSwRTREGjmr2BWPdxbmXVkb3kI1qu28=
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
yunion.io/x/jsonutils v0.0.0-20191005115334-bb1c187fc0e7 h1:9NcHs2OFMyN8O8SmJ3sFm5AJSVXP3u1N3avJsbyX3RI=
@@ -663,6 +666,7 @@ yunion.io/x/log v0.0.0-20190629062853-9f6483a7103d h1:59zrDL7Ft+hDukguJRmLr/Gdu/
yunion.io/x/log v0.0.0-20190629062853-9f6483a7103d/go.mod h1:LC6f/4FozL0iaAbnFt2eDX9jlsyo3WiOUPm03d7+U4U=
yunion.io/x/pkg v0.0.0-20190620104149-945c25821dbf h1:OsKC+2ghZHwp+Ztm/MwKlLKKRiE7QcPG8eTp0GmsHbg=
yunion.io/x/pkg v0.0.0-20190620104149-945c25821dbf/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/pkg v0.0.0-20190628082551-f4033ba2ea30/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/pkg v0.0.0-20191121110824-e03b47b93fe0 h1:gMENCnVkKO5BlwtbKSKW5liEeHk8FHDxxcFXZcdhlxk=
yunion.io/x/pkg v0.0.0-20191121110824-e03b47b93fe0/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e h1:v+EzIadodSwkdZ/7bremd7J8J50Cise/HCylsOJngmo=
+5 -5
View File
@@ -1679,11 +1679,11 @@ func (b *SBaremetalInstance) SendNicInfo(nic *types.SNicDevInfo, idx int, nicTyp
}
func bindMount(src, dst string) error {
_, err := procutils.NewCommand("touch", dst).Run()
err := procutils.NewCommand("touch", dst).Run()
if err != nil {
return errors.Wrapf(err, "touch %s", dst)
}
_, err = procutils.NewCommand("mount", "-o", "ro,bind", src, dst).Run()
err = procutils.NewCommand("mount", "-o", "ro,bind", src, dst).Run()
if err != nil {
return errors.Wrapf(err, "mount %s %s", src, dst)
}
@@ -1691,7 +1691,7 @@ func bindMount(src, dst string) error {
}
func unbindMount(dst string) error {
_, err := procutils.NewCommand("umount", dst).Run()
err := procutils.NewCommand("umount", dst).Run()
if err != nil {
return errors.Wrapf(err, "umount %s", dst)
}
@@ -1760,7 +1760,7 @@ func (b *SBaremetalInstance) GenerateBootISO() error {
for _, f := range []string{
"isolinux.bin",
} {
_, err = procutils.NewCommand("cp", filepath.Join(o.Options.TftpRoot, f), filepath.Join(isoLinDir, f)).Run()
err = procutils.NewCommand("cp", filepath.Join(o.Options.TftpRoot, f), filepath.Join(isoLinDir, f)).Run()
if err != nil {
return errors.Wrapf(err, "cp %s", f)
}
@@ -1782,7 +1782,7 @@ func (b *SBaremetalInstance) GenerateBootISO() error {
"-o", b.getBootIsoImagePath(),
isoDir,
}
_, err = procutils.NewCommand("mkisofs", args...).Run()
err = procutils.NewCommand("mkisofs", args...).Run()
if err != nil {
return errors.Wrap(err, "procutils.NewCommand mkisofs")
}
+1 -1
View File
@@ -131,7 +131,7 @@ func (ipmi *LanPlusIPMI) GetCommand(args ...string) *procutils.Command {
func (ipmi *LanPlusIPMI) ExecuteCommand(args ...string) ([]string, error) {
cmd := ipmi.GetCommand(args...)
log.Debugf("[LanPlusIPMI] execute command: %s", cmd.String())
out, err := cmd.Run()
out, err := cmd.Output()
if err != nil {
return nil, err
}
+1 -1
View File
@@ -69,7 +69,7 @@ func (s *SServiceBase) CreatePid() error {
s.O.PidFile = absPath
pidDir := filepath.Dir(s.O.PidFile)
if !fileutils2.Exists(pidDir) {
output, err := procutils.NewCommand("mkdir", "-p", pidDir).Run()
output, err := procutils.NewCommand("mkdir", "-p", pidDir).Output()
if err != nil {
return fmt.Errorf("Make pid dir %s failed: %s", pidDir, output)
}
+7 -7
View File
@@ -96,7 +96,7 @@ func (d *SKVMGuestDisk) connect() bool {
} else {
cmd = []string{qemutils.GetQemuNbd(), "-c", d.nbdDev, d.imagePath}
}
_, err := procutils.NewCommand(cmd[0], cmd[1:]...).Run()
_, err := procutils.NewCommand(cmd[0], cmd[1:]...).Output()
if err != nil {
log.Errorln(err.Error())
return false
@@ -134,7 +134,7 @@ func (d *SKVMGuestDisk) Connect() bool {
}
func (d *SKVMGuestDisk) getImageFormat() string {
lines, err := procutils.NewCommand(qemutils.GetQemuImg(), "info", d.imagePath).Run()
lines, err := procutils.NewCommand(qemutils.GetQemuImg(), "info", d.imagePath).Output()
if err != nil {
return ""
}
@@ -228,7 +228,7 @@ func (d *SKVMGuestDisk) LvmDisconnectNotify() {
func (d *SKVMGuestDisk) setupLVMS() (bool, error) {
// Scan all devices and send the metadata to lvmetad
output, err := procutils.NewCommand("pvscan", "--cache").Run()
output, err := procutils.NewCommand("pvscan", "--cache").Output()
if err != nil {
log.Errorf("pvscan error %s", output)
return false, err
@@ -278,7 +278,7 @@ func (d *SKVMGuestDisk) Disconnect() bool {
}
func (d *SKVMGuestDisk) disconnect() bool {
_, err := procutils.NewCommand(qemutils.GetQemuNbd(), "-d", d.nbdDev).Run()
_, err := procutils.NewCommand(qemutils.GetQemuNbd(), "-d", d.nbdDev).Output()
if err != nil {
log.Errorln(err.Error())
return false
@@ -342,15 +342,15 @@ func (d *SKVMGuestDisk) UmountKvmRootfs(fd fsdriver.IRootFsDriver) {
}
func (d *SKVMGuestDisk) MakePartition(fs string) error {
return fileutils2.Mkpartition(d.nbdDev, fs)
return Mkpartition(d.nbdDev, fs)
}
func (d *SKVMGuestDisk) FormatPartition(fs, uuid string) error {
return fileutils2.FormatPartition(fmt.Sprintf("%sp1", d.nbdDev), fs, uuid)
return FormatPartition(fmt.Sprintf("%sp1", d.nbdDev), fs, uuid)
}
func (d *SKVMGuestDisk) ResizePartition() error {
return fileutils2.ResizeDiskFs(d.nbdDev, 0)
return ResizeDiskFs(d.nbdDev, 0)
}
func (d *SKVMGuestDisk) Zerofree() {
+363
View File
@@ -0,0 +1,363 @@
package diskutils
import (
"fmt"
"io"
"io/ioutil"
"path"
"regexp"
"strconv"
"strings"
"github.com/pkg/errors"
"yunion.io/x/log"
"yunion.io/x/pkg/utils"
"yunion.io/x/onecloud/pkg/util/fileutils2"
"yunion.io/x/onecloud/pkg/util/procutils"
"yunion.io/x/onecloud/pkg/util/regutils2"
)
func IsPartedFsString(fsstr string) bool {
return utils.IsInStringArray(strings.ToLower(fsstr), []string{
"ext2", "ext3", "ext4", "xfs",
"fat16", "fat32",
"hfs", "hfs+", "hfsx",
"linux-swap", "linux-swap(v1)",
"ntfs", "reiserfs", "ufs", "btrfs",
})
}
func ParseDiskPartition(dev string, lines []byte) ([][]string, string) {
var (
parts = [][]string{}
label string
labelPartten = regexp.MustCompile(`Partition Table:\s+(?P<label>\w+)`)
partten = regexp.MustCompile(`(?P<idx>\d+)\s+(?P<start>\d+)s\s+(?P<end>\d+)s\s+(?P<count>\d+)s`)
)
for _, line := range strings.Split(string(lines), "\n") {
if len(label) == 0 {
m := regutils2.GetParams(labelPartten, line)
if len(m) > 0 {
label = m["label"]
}
}
m := regutils2.GetParams(partten, line)
if len(m) > 0 {
var (
idx = m["idx"]
start = m["start"]
end = m["end"]
count = m["count"]
devname = dev
)
if '0' <= dev[len(dev)-1] && dev[len(dev)-1] <= '9' {
devname += "p"
}
devname += idx
data := regexp.MustCompile(`\s+`).Split(strings.TrimSpace(line), -1)
var disktype, fs, flag string
var offset = 0
if len(data) > 4 {
if label == "msdos" {
disktype = data[4]
if len(data) > 5 && IsPartedFsString(data[5]) {
fs = data[5]
offset += 1
}
if len(data) > 5+offset {
flag = data[5+offset]
}
} else if label == "gpt" {
if IsPartedFsString(data[4]) {
fs = data[4]
offset += 1
}
if len(data) > 4+offset {
disktype = data[4+offset]
}
if len(data) > 4+offset+1 {
flag = data[4+offset+1]
}
}
}
var bootable = ""
if len(flag) > 0 && strings.Index(flag, "boot") >= 0 {
bootable = "true"
}
parts = append(parts, []string{idx, bootable, start, end, count, disktype, fs,
devname})
}
}
return parts, label
}
func GetDevSector512Count(dev string) int {
sizeStr, _ := fileutils2.FileGetContents(fmt.Sprintf("/sys/block/%s/size", dev))
sizeStr = strings.Trim(sizeStr, "\n")
size, _ := strconv.Atoi(sizeStr)
return size
}
func ResizeDiskFs(diskPath string, sizeMb int) error {
var cmds = []string{"parted", "-a", "none", "-s", diskPath, "--", "unit", "s", "print"}
lines, err := procutils.NewCommand(cmds[0], cmds[1:]...).Output()
if err != nil {
log.Errorf("resize disk fs fail: %s", err)
return err
}
parts, label := ParseDiskPartition(diskPath, lines)
log.Infof("Parts: %v label: %s", parts, label)
maxSector := GetDevSector512Count(path.Base(diskPath))
if label == "gpt" {
proc := procutils.NewCommand("gdisk", diskPath)
stdin, err := proc.StdinPipe()
if err != nil {
return err
}
defer stdin.Close()
outb, err := proc.StdoutPipe()
if err != nil {
return err
}
defer outb.Close()
errb, err := proc.StderrPipe()
if err != nil {
return err
}
defer errb.Close()
if err := proc.Start(); err != nil {
return err
}
for _, s := range []string{"r", "e", "Y", "w", "Y", "Y"} {
io.WriteString(stdin, fmt.Sprintf("%s\n", s))
}
stdoutPut, err := ioutil.ReadAll(outb)
if err != nil {
return err
}
stderrOutPut, err := ioutil.ReadAll(errb)
if err != nil {
return err
}
log.Infof("gdisk: %s %s", stdoutPut, stderrOutPut)
if err = proc.Wait(); err != nil {
if status, succ := procutils.GetExitStatus(err); succ {
if status != 1 {
return err
}
} else {
return err
}
}
}
if len(parts) > 0 && (label == "gpt" ||
(label == "msdos" && parts[len(parts)-1][5] == "primary")) {
var (
part = parts[len(parts)-1]
end int
)
if sizeMb > 0 {
end = sizeMb * 1024 * 2
} else if label == "gpt" {
end = maxSector - 35
} else {
end = maxSector - 1
}
if label == "msdos" && end >= 4294967296 {
end = 4294967295
}
cmds = []string{"parted", "-a", "none", "-s", diskPath, "--",
"unit", "s", "rm", part[0], "mkpart", part[5]}
if len(part[6]) > 0 {
cmds = append(cmds, part[6])
}
cmds = append(cmds, part[2], fmt.Sprintf("%ds", end))
if len(part[1]) > 0 {
cmds = append(cmds, "set", part[0], "boot", "on")
}
log.Infof("resize disk partition: %s", cmds)
output, err := procutils.NewCommand(cmds[0], cmds[1:]...).Output()
if err != nil {
return errors.Wrapf(err, "parted failed %s", output)
}
if len(part[6]) > 0 {
err, _ := ResizePartitionFs(part[7], part[6], false)
if err != nil {
return err
}
}
}
return nil
}
func ResizePartitionFs(fpath, fs string, raiseError bool) (error, bool) {
if len(fs) == 0 {
return nil, false
}
var (
cmds = [][]string{}
uuids = fileutils2.GetDevUuid(fpath)
)
if strings.HasPrefix(fs, "linux-swap") {
if v, ok := uuids["UUID"]; ok {
cmds = [][]string{{"mkswap", "-U", v, fpath}}
} else {
cmds = [][]string{{"mkswap", fpath}}
}
} else if strings.HasPrefix(fs, "ext") {
if !FsckExtFs(fpath) {
if raiseError {
return fmt.Errorf("Failed to fsck ext fs %s", fpath), false
} else {
return nil, false
}
}
cmds = [][]string{{"resize2fs", fpath}}
} else if fs == "xfs" {
var tmpPoint = fmt.Sprintf("/tmp/%s", strings.Replace(fpath, "/", "_", -1))
if _, err := procutils.NewCommand("mountpoint", tmpPoint).Output(); err == nil {
_, err = procutils.NewCommand("umount", "-f", tmpPoint).Output()
if err != nil {
log.Errorln(err)
return err, false
}
}
FsckXfsFs(fpath)
cmds = [][]string{{"mkdir", "-p", tmpPoint},
{"mount", fpath, tmpPoint},
{"sleep", "2"},
{"xfs_growfs", tmpPoint},
{"sleep", "2"},
{"umount", tmpPoint},
{"sleep", "2"},
{"rm", "-fr", tmpPoint}}
}
if len(cmds) > 0 {
for _, cmd := range cmds {
_, err := procutils.NewCommand(cmd[0], cmd[1:]...).Output()
if err != nil {
log.Errorln(err)
if raiseError {
return err, false
} else {
return nil, false
}
}
}
}
return nil, true
}
func FsckExtFs(fpath string) bool {
log.Debugf("Exec command: %v", []string{"e2fsck", "-f", "-p", fpath})
cmd := procutils.NewCommand("e2fsck", "-f", "-p", fpath)
if err := cmd.Start(); err != nil {
log.Errorln(err)
return false
} else {
err = cmd.Wait()
if err != nil {
if status, ok := procutils.GetExitStatus(err); ok {
if status < 4 {
return true
}
}
log.Errorln(err)
return false
} else {
return true
}
}
}
func FsckXfsFs(fpath string) bool {
if _, err := procutils.NewCommand("xfs_check", fpath).Output(); err != nil {
log.Errorln(err)
procutils.NewCommand("xfs_repair", fpath).Output()
return false
}
return true
}
func Mkpartition(imagePath, fsFormat string) error {
var (
parted = "/sbin/parted"
labelType = "gpt"
diskType = fileutils2.FsFormatToDiskType(fsFormat)
)
if len(diskType) == 0 {
return fmt.Errorf("Unknown fsFormat %s", fsFormat)
}
// 创建一个新磁盘分区表类型, ex: mbr gpt msdos ...
_, err := procutils.NewCommand(parted, "-s", imagePath, "mklabel", labelType).Output()
if err != nil {
log.Errorf("mklabel %s %s error %s", imagePath, fsFormat, err)
return err
}
// 创建一个part-type类型的分区, part-type可以是:"primary", "logical", "extended"
// 如果指定fs-type(即diskType)则在创建分区的同时进行格式化
err = procutils.NewCommand(parted, "-s", "-a", "cylinder",
imagePath, "mkpart", "primary", diskType, "0", "100%").Run()
if err != nil {
log.Errorf("mkpart %s %s error %s", imagePath, fsFormat, err)
return err
}
return nil
}
func FormatPartition(path, fs, uuid string) error {
var cmd, cmdUuid []string
switch {
case fs == "swap":
cmd = []string{"mkswap", "-U", uuid}
case fs == "ext2":
cmd = []string{"mkfs.ext2"}
cmdUuid = []string{"tune2fs", "-U", uuid}
case fs == "ext3":
cmd = []string{"mkfs.ext3"}
cmdUuid = []string{"tune2fs", "-U", uuid}
case fs == "ext4":
cmd = []string{"mkfs.ext4", "-O", "^64bit", "-E", "lazy_itable_init=1"}
cmdUuid = []string{"tune2fs", "-U", uuid}
case fs == "ext4dev":
cmd = []string{"mkfs.ext4dev", "-E", "lazy_itable_init=1"}
cmdUuid = []string{"tune2fs", "-U", uuid}
case strings.HasPrefix(fs, "fat"):
cmd = []string{"mkfs.msdos"}
// #case fs == "ntfs":
// # cmd = []string{"/sbin/mkfs.ntfs"}
case fs == "xfs":
cmd = []string{"/sbin/mkfs.xfs", "-f", "-m", "crc=0", "-i", "projid32bit=0", "-n", "ftype=0"}
cmdUuid = []string{"xfs_admin", "-U", uuid}
}
if len(cmd) > 0 {
var cmds = cmd
cmds = append(cmds, path)
if _, err := procutils.NewCommand(cmds[0], cmds[1:]...).Output(); err != nil {
log.Errorln(err)
return err
}
if len(cmdUuid) > 0 {
cmds = cmdUuid
cmds = append(cmds, path)
if _, err := procutils.NewCommand(cmds[0], cmds[1:]...).Output(); err != nil {
log.Errorln(err)
return err
}
}
return nil
}
return fmt.Errorf("Unknown fs %s", fs)
}
+3 -3
View File
@@ -88,7 +88,7 @@ type SKVMGuestLVMPartition struct {
}
func findVgname(partDev string) string {
output, err := procutils.NewCommand("pvscan").Run()
output, err := procutils.NewCommand("pvscan").Output()
if err != nil {
log.Errorf("%s", output)
return ""
@@ -180,7 +180,7 @@ func (p *SKVMGuestLVMPartition) vgActivate(activate bool) bool {
if activate {
param = "-ay"
}
output, err := procutils.NewCommand("vgchange", param, p.vgname).Run()
output, err := procutils.NewCommand("vgchange", param, p.vgname).Output()
if err != nil {
log.Errorf("%s", output)
return false
@@ -189,7 +189,7 @@ func (p *SKVMGuestLVMPartition) vgActivate(activate bool) bool {
}
func (p *SKVMGuestLVMPartition) vgRename(oldname, newname string) bool {
output, err := procutils.NewCommand("vgrename", oldname, newname).Run()
output, err := procutils.NewCommand("vgrename", oldname, newname).Output()
if err != nil {
log.Errorf("%s", output)
return false
+14 -15
View File
@@ -59,7 +59,7 @@ func (p *SKVMGuestDiskPartition) GetPhysicalPartitionType() string {
dev = dev[:idxP]
}
cmd := fmt.Sprintf(`fdisk -l %s | grep "Disk label type:"`, dev)
output, err := procutils.NewCommand("sh", "-c", cmd).Run()
output, err := procutils.NewCommand("sh", "-c", cmd).Output()
if err != nil {
log.Errorf("get disk label type error %s", output)
return ""
@@ -131,7 +131,7 @@ func (p *SKVMGuestDiskPartition) Mount() bool {
}
func (p *SKVMGuestDiskPartition) mount(readonly bool) error {
if _, err := procutils.NewCommand("mkdir", "-p", p.mountPath).Run(); err != nil {
if _, err := procutils.NewCommand("mkdir", "-p", p.mountPath).Output(); err != nil {
log.Errorln(err)
return err
}
@@ -154,7 +154,7 @@ func (p *SKVMGuestDiskPartition) mount(readonly bool) error {
cmds = append(cmds, "-o", opt)
}
cmds = append(cmds, p.partDev, p.mountPath)
_, err := procutils.NewCommand(cmds[0], cmds[1:]...).Run()
_, err := procutils.NewCommand(cmds[0], cmds[1:]...).Output()
return err
}
@@ -172,11 +172,11 @@ func (p *SKVMGuestDiskPartition) fsck() error {
fixCmd = []string{"ntfsfix", p.partDev}
}
if len(checkCmd) > 0 {
_, err := procutils.NewCommand(checkCmd[0], checkCmd[1:]...).Run()
_, err := procutils.NewCommand(checkCmd[0], checkCmd[1:]...).Output()
if err != nil {
log.Warningf("FS %s dirty, try to repair ...", p.partDev)
for i := 0; i < 3; i++ {
_, err := procutils.NewCommand(fixCmd[0], fixCmd[1:]...).Run()
_, err := procutils.NewCommand(fixCmd[0], fixCmd[1:]...).Output()
if err == nil {
break
} else {
@@ -201,13 +201,13 @@ func (p *SKVMGuestDiskPartition) IsMounted() bool {
if !fileutils2.Exists(p.mountPath) {
return false
}
_, err := procutils.NewCommand("mountpoint", p.mountPath).Run()
output, err := procutils.NewCommand("mountpoint", p.mountPath).Output()
if err == nil {
return true
} else {
log.Errorln(err)
log.Errorln(output)
return false
}
return false
}
func (p *SKVMGuestDiskPartition) Umount() bool {
@@ -215,9 +215,9 @@ func (p *SKVMGuestDiskPartition) Umount() bool {
var tries = 0
for tries < 10 {
tries += 1
_, err := procutils.NewCommand("umount", p.mountPath).Run()
_, err := procutils.NewCommand("umount", p.mountPath).Output()
if err == nil {
procutils.NewCommand("blockdev", "--flushbufs", p.partDev).Run()
procutils.NewCommand("blockdev", "--flushbufs", p.partDev).Output()
os.Remove(p.mountPath)
return true
} else {
@@ -243,7 +243,7 @@ func (p *SKVMGuestDiskPartition) Zerofree() {
func (p *SKVMGuestDiskPartition) zerofreeSwap() {
uuids := fileutils2.GetDevUuid(p.partDev)
_, err := procutils.NewCommand("shred", "-n", "0", "-z", p.partDev).Run()
_, err := procutils.NewCommand("shred", "-n", "0", "-z", p.partDev).Output()
if err != nil {
log.Errorf("zerofree swap error: %s", err)
return
@@ -253,14 +253,14 @@ func (p *SKVMGuestDiskPartition) zerofreeSwap() {
cmd = append(cmd, "-U", uuid)
}
cmd = append(cmd, p.partDev)
_, err = procutils.NewCommand(cmd[0], cmd[1:]...).Run()
_, err = procutils.NewCommand(cmd[0], cmd[1:]...).Output()
if err != nil {
log.Errorf("zerofree swap error: %s", err)
}
}
func (p *SKVMGuestDiskPartition) zerofreeExt() {
_, err := procutils.NewCommand("zerofree", p.partDev).Run()
_, err := procutils.NewCommand("zerofree", p.partDev).Output()
if err != nil {
log.Errorf("zerofree ext error: %s", err)
return
@@ -268,8 +268,7 @@ func (p *SKVMGuestDiskPartition) zerofreeExt() {
}
func (p *SKVMGuestDiskPartition) zerofreeNtfs() {
_, err := procutils.NewCommand("ntfswipe", "-f", "-l", "-m", "-p", "-s", "-q",
p.partDev).Run()
err := procutils.NewCommand("ntfswipe", "-f", "-l", "-m", "-p", "-s", "-q", p.partDev).Run()
if err != nil {
log.Errorf("zerofree ntfs error: %s", err)
return
+2 -3
View File
@@ -19,7 +19,6 @@ import (
"io"
"io/ioutil"
"os"
"os/exec"
"path"
"strings"
@@ -141,7 +140,7 @@ func (f *SLocalGuestFS) Zerofiles(dir string, caseInsensitive bool) error {
}
func (f *SLocalGuestFS) Passwd(account, password string, caseInsensitive bool) error {
var proc = exec.Command("chroot", f.mountPath, "passwd", account)
var proc = procutils.NewCommand("chroot", f.mountPath, "passwd", account)
stdin, err := proc.StdinPipe()
if err != nil {
return err
@@ -224,7 +223,7 @@ func (f *SLocalGuestFS) Chmod(sPath string, mode uint32, caseInsensitive bool) e
}
func (f *SLocalGuestFS) UserAdd(user string, caseInsensitive bool) error {
output, err := procutils.NewCommand("chroot", f.mountPath, "useradd", "-m", "-s", "/bin/bash", user).Run()
output, err := procutils.NewCommand("chroot", f.mountPath, "useradd", "-m", "-s", "/bin/bash", user).Output()
if err != nil {
log.Errorf("Useradd fail: %s, %s", err, output)
return fmt.Errorf("%s", output)
+7 -7
View File
@@ -821,7 +821,7 @@ func (s *SGuestDiskSnapshotTask) onReloadBlkdevSucc(res string) {
func (s *SGuestDiskSnapshotTask) onSnapshotBlkdevFail(string) {
snapshotDir := s.disk.GetSnapshotDir()
snapshotPath := path.Join(snapshotDir, s.snapshotId)
_, err := procutils.NewCommand("mv", "-f", snapshotPath, s.disk.GetPath()).Run()
_, err := procutils.NewCommand("mv", "-f", snapshotPath, s.disk.GetPath()).Output()
if err != nil {
log.Errorln(err)
}
@@ -886,17 +886,17 @@ func (s *SGuestSnapshotDeleteTask) doDiskConvert() error {
}
s.tmpPath = snapshotPath + ".swap"
if _, err := procutils.NewCommand("mv", "-f", snapshotPath, s.tmpPath).Run(); err != nil {
if _, err := procutils.NewCommand("mv", "-f", snapshotPath, s.tmpPath).Output(); err != nil {
log.Errorln(err)
if fileutils2.Exists(s.tmpPath) {
procutils.NewCommand("mv", "-f", s.tmpPath, snapshotPath).Run()
procutils.NewCommand("mv", "-f", s.tmpPath, snapshotPath).Output()
}
return err
}
if _, err := procutils.NewCommand("mv", "-f", convertedDisk, snapshotPath).Run(); err != nil {
if _, err := procutils.NewCommand("mv", "-f", convertedDisk, snapshotPath).Output(); err != nil {
log.Errorln(err)
if fileutils2.Exists(s.tmpPath) {
procutils.NewCommand("mv", "-f", s.tmpPath, snapshotPath).Run()
procutils.NewCommand("mv", "-f", s.tmpPath, snapshotPath).Output()
}
return err
}
@@ -918,7 +918,7 @@ func (s *SGuestSnapshotDeleteTask) onReloadBlkdevSucc(err string) {
func (s *SGuestSnapshotDeleteTask) onSnapshotBlkdevFail(res string) {
snapshotPath := path.Join(s.disk.GetSnapshotDir(), s.convertSnapshot)
if _, err := procutils.NewCommand("mv", "-f", s.tmpPath, snapshotPath).Run(); err != nil {
if _, err := procutils.NewCommand("mv", "-f", s.tmpPath, snapshotPath).Output(); err != nil {
log.Errorln(err)
}
s.taskFailed("Reload blkdev failed")
@@ -927,7 +927,7 @@ func (s *SGuestSnapshotDeleteTask) onSnapshotBlkdevFail(res string) {
func (s *SGuestSnapshotDeleteTask) onResumeSucc(res string) {
log.Infof("guest do new snapshot task resume succ %s", res)
if len(s.tmpPath) > 0 {
_, err := procutils.NewCommand("rm", "-f", s.tmpPath).Run()
_, err := procutils.NewCommand("rm", "-f", s.tmpPath).Output()
if err != nil {
log.Errorln(err)
}
+4 -5
View File
@@ -64,7 +64,7 @@ func (m *SGuestManager) GuestCreateFromLibvirt(
iDisk := storage.CreateDisk(diskId)
// use symbol link replace mv, more security
output, err := procutils.NewCommand("ln", "-s", diskPath, iDisk.GetPath()).Run()
output, err := procutils.NewCommand("ln", "-s", diskPath, iDisk.GetPath()).Output()
if err != nil {
return nil, fmt.Errorf("Symbol link disk from %s to %s error %s", diskPath, iDisk.GetPath(), output)
}
@@ -93,7 +93,7 @@ func (m *SGuestManager) GuestCreateFromLibvirt(
func findGuestProcessPid(originId, sufix string) string {
output, err := procutils.NewCommand(
"sh", "-c", fmt.Sprintf("ps -A -o pid,args | grep [q]emu | grep %s | grep %s", originId, sufix)).Run()
"sh", "-c", fmt.Sprintf("ps -A -o pid,args | grep [q]emu | grep %s | grep %s", originId, sufix)).Output()
if err != nil {
log.Errorf("find guest %s error: %s", originId, output)
return ""
@@ -190,9 +190,8 @@ func setAttributeFromLibvirtConfig(
}
func isServerRunning(sufix, uuid string) bool {
_, err := procutils.NewCommand("sh", "-c",
fmt.Sprintf("ps -ef | grep [q]emu | grep %s | grep %s", uuid, sufix)).Run()
return err == nil
return procutils.NewCommand("sh", "-c",
fmt.Sprintf("ps -ef | grep [q]emu | grep %s | grep %s", uuid, sufix)).Run() == nil
}
func (m *SGuestManager) GenerateDescFromXml(libvirtConfig *compute.SLibvirtHostConfig) (jsonutils.JSONObject, error) {
+10 -10
View File
@@ -105,7 +105,7 @@ func (s *SKVMGuestInstance) HomeDir() string {
}
func (s *SKVMGuestInstance) PrepareDir() error {
_, err := procutils.NewCommand("mkdir", "-p", s.HomeDir()).Run()
_, err := procutils.NewCommand("mkdir", "-p", s.HomeDir()).Output()
return err
}
@@ -836,13 +836,13 @@ func (s *SKVMGuestInstance) StartDelete(ctx context.Context, migrated bool) erro
func (s *SKVMGuestInstance) ForceStop() bool {
s.ExitCleanup(true)
if s.IsRunning() {
_, err := procutils.NewCommand("kill", "-9", fmt.Sprintf("%d", s.GetPid())).Run()
_, err := procutils.NewCommand("kill", "-9", fmt.Sprintf("%d", s.GetPid())).Output()
if err != nil {
log.Errorln(err)
return false
}
for _, f := range s.GetCleanFiles() {
_, err := procutils.NewCommand("rm", "-f", f).Run()
_, err := procutils.NewCommand("rm", "-f", f).Output()
if err != nil {
log.Errorln(err)
return false
@@ -902,7 +902,7 @@ func (s *SKVMGuestInstance) Delete(ctx context.Context, migrated bool) error {
if err := s.delTmpDisks(ctx, migrated); err != nil {
return err
}
_, err := procutils.NewCommand("rm", "-rf", s.HomeDir()).Run()
_, err := procutils.NewCommand("rm", "-rf", s.HomeDir()).Output()
return err
}
@@ -916,7 +916,7 @@ func (s *SKVMGuestInstance) Stop() bool {
}
func (s *SKVMGuestInstance) scriptStart() error {
output, err := procutils.NewCommand("sh", s.GetStartScriptPath()).Run()
output, err := procutils.NewCommand("sh", s.GetStartScriptPath()).Output()
if err != nil {
s.scriptStop()
return fmt.Errorf("Start VM Failed %s %s", output, err)
@@ -925,7 +925,7 @@ func (s *SKVMGuestInstance) scriptStart() error {
}
func (s *SKVMGuestInstance) scriptStop() bool {
_, err := procutils.NewCommand("sh", s.GetStopScriptPath()).Run()
_, err := procutils.NewCommand("sh", s.GetStopScriptPath()).Output()
if err != nil {
log.Errorln(err)
return false
@@ -1323,16 +1323,16 @@ func (s *SKVMGuestInstance) ListStateFilePaths() []string {
// 好像不用了
func (s *SKVMGuestInstance) CleanStatefiles() {
for _, stateFile := range s.ListStateFilePaths() {
if _, err := procutils.NewCommand("mountpoint", stateFile).Run(); err == nil {
if _, err = procutils.NewCommand("umount", stateFile).Run(); err != nil {
if _, err := procutils.NewCommand("mountpoint", stateFile).Output(); err == nil {
if _, err = procutils.NewCommand("umount", stateFile).Output(); err != nil {
log.Errorln(err)
}
}
if _, err := procutils.NewCommand("rm", "-rf", stateFile).Run(); err != nil {
if _, err := procutils.NewCommand("rm", "-rf", stateFile).Output(); err != nil {
log.Errorln(err)
}
}
if _, err := procutils.NewCommand("rm", "-rf", s.GetFuseTmpPath()).Run(); err != nil {
if _, err := procutils.NewCommand("rm", "-rf", s.GetFuseTmpPath()).Output(); err != nil {
log.Errorln(err)
}
}
+21 -3
View File
@@ -17,6 +17,7 @@ package hostman
import (
"os"
execlient "yunion.io/x/executor/client"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/appsrv"
@@ -37,6 +38,8 @@ import (
"yunion.io/x/onecloud/pkg/hostman/storageman"
"yunion.io/x/onecloud/pkg/hostman/storageman/diskhandlers"
"yunion.io/x/onecloud/pkg/hostman/storageman/storagehandler"
"yunion.io/x/onecloud/pkg/hostman/system_service"
"yunion.io/x/onecloud/pkg/util/procutils"
"yunion.io/x/onecloud/pkg/util/sysutils"
)
@@ -46,6 +49,15 @@ type SHostService struct {
func (host *SHostService) InitService() {
common_options.ParseOptions(&options.HostOptions, os.Args, "host.conf", "host")
if len(options.HostOptions.CommonConfigFile) > 0 {
baseOpt := options.HostOptions.BaseOptions.BaseOptions
commonCfg := new(common_options.CommonOptions)
commonCfg.Config = options.HostOptions.CommonConfigFile
common_options.ParseOptions(commonCfg, []string{"host"}, "common.conf", "host")
options.HostOptions.CommonOptions = *commonCfg
// keep base options
options.HostOptions.BaseOptions.BaseOptions = baseOpt
}
isRoot := sysutils.IsRootPermission()
if !isRoot {
log.Fatalf("host service must running with root permissions")
@@ -58,11 +70,17 @@ func (host *SHostService) InitService() {
options.HostOptions.EnableRbac = false // disable rbac
// init base option for pid file
host.SServiceBase.O = &options.HostOptions.BaseOptions
log.Infof("exec socket path: %s", options.HostOptions.ExecutorSocketPath)
if options.HostOptions.EnableRemoteExecutor {
execlient.Init(options.HostOptions.ExecutorSocketPath)
procutils.SetRemoteExecutor()
}
system_service.Init()
}
func (host *SHostService) OnExitService() {
// TODO
}
func (host *SHostService) OnExitService() {}
func (host *SHostService) RunService() {
app := app_common.InitApp(&options.HostOptions.BaseOptions, false)
@@ -24,16 +24,17 @@ import (
"google.golang.org/grpc"
execlient "yunion.io/x/executor/client"
"yunion.io/x/log"
common_options "yunion.io/x/onecloud/pkg/cloudcommon/options"
service "yunion.io/x/onecloud/pkg/cloudcommon/service"
diskutils "yunion.io/x/onecloud/pkg/hostman/diskutils"
nbd "yunion.io/x/onecloud/pkg/hostman/diskutils/nbd"
guestfs "yunion.io/x/onecloud/pkg/hostman/guestfs"
fsdriver "yunion.io/x/onecloud/pkg/hostman/guestfs/fsdriver"
"yunion.io/x/onecloud/pkg/cloudcommon/service"
"yunion.io/x/onecloud/pkg/hostman/diskutils"
"yunion.io/x/onecloud/pkg/hostman/diskutils/nbd"
"yunion.io/x/onecloud/pkg/hostman/guestfs"
"yunion.io/x/onecloud/pkg/hostman/guestfs/fsdriver"
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
fileutils2 "yunion.io/x/onecloud/pkg/util/fileutils2"
"yunion.io/x/onecloud/pkg/util/fileutils2"
"yunion.io/x/onecloud/pkg/util/procutils"
"yunion.io/x/onecloud/pkg/util/sysutils"
"yunion.io/x/onecloud/pkg/util/winutils"
@@ -222,11 +223,11 @@ func (s *SDeployService) PrepareEnv() error {
if err := s.FixPathEnv(); err != nil {
return err
}
output, err := procutils.NewCommand("rmmod", "nbd").Run()
output, err := procutils.NewCommand("rmmod", "nbd").Output()
if err != nil {
log.Errorf("rmmod error: %s", output)
}
output, err = procutils.NewCommand("modprobe", "nbd", "max_part=16").Run()
output, err = procutils.NewCommand("modprobe", "nbd", "max_part=16").Output()
if err != nil {
return fmt.Errorf("Failed to activate nbd device: %s", output)
}
@@ -246,7 +247,7 @@ func (s *SDeployService) PrepareEnv() error {
log.Errorf("Failed to find chntpw tool")
}
output, err = procutils.NewCommand("pvscan").Run()
output, err = procutils.NewCommand("pvscan").Output()
if err != nil {
log.Errorf("Failed exec lvm command pvscan: %s", output)
}
@@ -255,10 +256,15 @@ func (s *SDeployService) PrepareEnv() error {
func (s *SDeployService) InitService() {
common_options.ParseOptions(&DeployOption, os.Args, "host.conf", "deploy-server")
log.Infof("exec socket path: %s", DeployOption.ExecSocketPath)
if DeployOption.EnableRemoteExecutor {
execlient.Init(DeployOption.ExecSocketPath)
procutils.SetRemoteExecutor()
}
if err := s.PrepareEnv(); err != nil {
log.Fatalln(err)
}
fsdriver.Init(DeployOption.PrivatePrefixes)
s.O = &DeployOption.BaseOptions
if len(DeployOption.DeployServerSocketPath) == 0 {
@@ -22,6 +22,8 @@ type SDeployOptions struct {
DeployServerSocketPath string `help:"Deploy server listen socket path" default:"/var/run/deploy.sock"`
PrivatePrefixes []string `help:"IPv4 private prefixes"`
ChntpwPath string `help:"path to chntpw tool" default:"/usr/local/bin/chntpw.static"`
EnableRemoteExecutor bool `help:"Enable remote executor" default:"false"`
ExecSocketPath string `help:"Exec socket paht" default:"/var/run/exec.sock"`
}
var DeployOption SDeployOptions
@@ -107,7 +107,7 @@ func (d *SBaseBridgeDriver) BringupInterface() error {
if options.HostOptions.TunnelPaddingBytes > 0 {
cmd = append(cmd, "mtu", fmt.Sprintf("%d", options.HostOptions.TunnelPaddingBytes))
}
if _, err := procutils.NewCommand(cmd[0], cmd[1:]...).Run(); err != nil {
if _, err := procutils.NewCommand(cmd[0], cmd[1:]...).Output(); err != nil {
return err
}
}
@@ -115,7 +115,7 @@ func (d *SBaseBridgeDriver) BringupInterface() error {
}
func (d *SBaseBridgeDriver) ConfirmToConfig() (bool, error) {
output, err := procutils.NewCommand("ifconfig").Run()
output, err := procutils.NewCommand("ifconfig").Output()
if err != nil {
return false, errors.Wrapf(err, "exec ifconfig %s", output)
}
@@ -188,12 +188,12 @@ func (d *SBaseBridgeDriver) SetupAddresses(mask net.IPMask) error {
if options.HostOptions.TunnelPaddingBytes > 0 {
cmd = append(cmd, "mtu", fmt.Sprintf("%d", options.HostOptions.TunnelPaddingBytes+1500))
}
if _, err := procutils.NewCommand(cmd[0], cmd[1:]...).Run(); err != nil {
if _, err := procutils.NewCommand(cmd[0], cmd[1:]...).Output(); err != nil {
log.Errorln(err)
return fmt.Errorf("Failed to bring up bridge %s", d.bridge)
}
if d.inter != nil {
if _, err := procutils.NewCommand("ifconfig", d.inter.String(), "0", "up").Run(); err != nil {
if _, err := procutils.NewCommand("ifconfig", d.inter.String(), "0", "up").Output(); err != nil {
log.Errorln(err)
return fmt.Errorf("Failed to bring up interface %s", d.inter)
}
@@ -205,13 +205,13 @@ func (d *SBaseBridgeDriver) SetupSlaveAddresses(slaveAddrs [][]string) error {
for _, slaveAddr := range slaveAddrs {
cmd := []string{"ip", "address", "del",
fmt.Sprintf("%s/%s", slaveAddr[0], slaveAddr[1]), "dev", d.inter.String()}
if _, err := procutils.NewCommand(cmd[0], cmd[1:]...).Run(); err != nil {
if _, err := procutils.NewCommand(cmd[0], cmd[1:]...).Output(); err != nil {
log.Errorf("Failed to remove slave address from interface %s: %s", d.inter, err)
}
cmd = []string{"ip", "address", "add",
fmt.Sprintf("%s/%s", slaveAddr[0], slaveAddr[1]), "dev", d.bridge.String()}
if _, err := procutils.NewCommand(cmd[0], cmd[1:]...).Run(); err != nil {
if _, err := procutils.NewCommand(cmd[0], cmd[1:]...).Output(); err != nil {
return fmt.Errorf("Failed to remove slave address from interface %s: %s", d.bridge, err)
}
}
@@ -226,7 +226,7 @@ func (d *SBaseBridgeDriver) SetupRoutes(routes [][]string) error {
} else {
cmd = []string{"route", "add", "-net", r[0], "netmask", r[2], "gw", r[1], "dev", d.bridge.String()}
}
if _, err := procutils.NewCommand(cmd[0], cmd[1:]...).Run(); err != nil {
if _, err := procutils.NewCommand(cmd[0], cmd[1:]...).Output(); err != nil {
log.Errorln(err)
return fmt.Errorf("Failed to add slave address to bridge %s", d.bridge)
}
@@ -51,7 +51,7 @@ type SLinuxBridgeDriver struct {
}
func (l *SLinuxBridgeDriver) Exists() (bool, error) {
data, err := procutils.NewCommand("brctl", "show").Run()
data, err := procutils.NewCommand("brctl", "show").Output()
if err != nil {
return false, err
}
@@ -67,7 +67,7 @@ func (l *SLinuxBridgeDriver) Exists() (bool, error) {
}
func (l *SLinuxBridgeDriver) Interfaces() ([]string, error) {
data, err := procutils.NewCommand("brctl", "show", l.bridge.String()).Run()
data, err := procutils.NewCommand("brctl", "show", l.bridge.String()).Output()
if err != nil {
return nil, err
}
@@ -118,7 +118,7 @@ func (l *SLinuxBridgeDriver) SetupBridgeDev() error {
return err
}
if !exist {
_, err := procutils.NewCommand("brctl", "addbr", l.bridge.String()).Run()
_, err := procutils.NewCommand("brctl", "addbr", l.bridge.String()).Output()
if err != nil {
return fmt.Errorf("Failed to create bridge %s", l.bridge)
}
@@ -127,7 +127,7 @@ func (l *SLinuxBridgeDriver) SetupBridgeDev() error {
}
func (d *SLinuxBridgeDriver) PersistentMac() error {
output, err := procutils.NewCommand("ifconfig", d.bridge.String(), "hw", "ether", d.inter.Mac).Run()
output, err := procutils.NewCommand("ifconfig", d.bridge.String(), "hw", "ether", d.inter.Mac).Output()
if err != nil {
return fmt.Errorf("Linux bridge set mac address failed %s %s", output, err)
}
@@ -141,7 +141,7 @@ func (l *SLinuxBridgeDriver) RegisterHostlocalServer(mac, ip string) error {
// cmd := "iptables -t nat -F"
// cmd1 := strings.Split(cmd, " ")
// output, err := procutils.NewCommand(cmd1[0], cmd1[1:]...).Run()
// output, err := procutils.NewCommand(cmd1[0], cmd1[1:]...).Output()
// if err != nil {
// log.Errorf("Clean iptables failed: %s", output)
// return err
@@ -151,7 +151,7 @@ func (l *SLinuxBridgeDriver) RegisterHostlocalServer(mac, ip string) error {
cmd += " -d 169.254.169.254/32 -p tcp -m tcp --dport 80"
cmd += fmt.Sprintf(" -j DNAT --to-destination %s", metadataServerLoc)
cmd1 := strings.Split(cmd, " ")
output, err := procutils.NewCommand(cmd1[0], cmd1[1:]...).Run()
output, err := procutils.NewCommand(cmd1[0], cmd1[1:]...).Output()
if err != nil {
log.Errorf("Inject DNAT rule failed: %s", output)
return err
@@ -159,7 +159,7 @@ func (l *SLinuxBridgeDriver) RegisterHostlocalServer(mac, ip string) error {
cmd = "sysctl -w net.ipv4.ip_forward=1"
cmd1 = strings.Split(cmd, " ")
output, err = procutils.NewCommand(cmd1[0], cmd1[1:]...).Run()
output, err = procutils.NewCommand(cmd1[0], cmd1[1:]...).Output()
if err != nil {
log.Errorf("Enable ip forwarding failed: %s", output)
return err
@@ -176,8 +176,7 @@ func (l *SLinuxBridgeDriver) SetupInterface() error {
return err
}
if l.inter != nil && !utils.IsInStringArray(l.inter.String(), infs) {
_, err := procutils.NewCommand(
"brctl", "addif", l.bridge.String(), l.inter.String()).Run()
err := procutils.NewCommand("brctl", "addif", l.bridge.String(), l.inter.String()).Run()
if err != nil {
return fmt.Errorf("Failed to add interface %s", l.inter)
}
+7 -8
View File
@@ -40,7 +40,7 @@ func (o *SOVSBridgeDriver) CleanupConfig() {
}
func (o *SOVSBridgeDriver) Exists() (bool, error) {
data, err := procutils.NewCommand("ovs-vsctl", "list-br").Run()
data, err := procutils.NewCommand("ovs-vsctl", "list-br").Output()
if err != nil {
return false, err
}
@@ -53,7 +53,7 @@ func (o *SOVSBridgeDriver) Exists() (bool, error) {
}
func (o *SOVSBridgeDriver) Interfaces() ([]string, error) {
data, err := procutils.NewCommand("ovs-vsctl", "list-ifaces", o.bridge.String()).Run()
data, err := procutils.NewCommand("ovs-vsctl", "list-ifaces", o.bridge.String()).Output()
if err != nil {
return nil, err
}
@@ -74,10 +74,10 @@ func (o *SOVSBridgeDriver) SetupInterface() error {
}
if o.inter != nil && !utils.IsInStringArray(o.inter.String(), infs) {
output, err := procutils.NewCommand("ovs-vsctl", "--", "--may-exist",
err := procutils.NewCommand("ovs-vsctl", "--", "--may-exist",
"add-port", o.bridge.String(), o.inter.String()).Run()
if err != nil {
return fmt.Errorf("Failed to add interface %s", output)
return fmt.Errorf("Failed to add interface %s", err)
}
}
return nil
@@ -89,7 +89,7 @@ func (o *SOVSBridgeDriver) SetupBridgeDev() error {
return err
}
if !exist {
_, err := procutils.NewCommand("ovs-vsctl", "--", "--may-exist", "add-br", o.bridge.String()).Run()
_, err := procutils.NewCommand("ovs-vsctl", "--", "--may-exist", "add-br", o.bridge.String()).Output()
return err
}
return nil
@@ -100,7 +100,7 @@ func (d *SOVSBridgeDriver) PersistentMac() error {
"ovs-vsctl", "set", "Bridge", d.bridge.String(),
"other-config:hwaddr=" + d.inter.Mac,
}
output, err := procutils.NewCommand(args[0], args[1:]...).Run()
output, err := procutils.NewCommand(args[0], args[1:]...).Output()
if err != nil {
return fmt.Errorf("Ovs bridge set mac address failed %s %s", output, err)
}
@@ -221,9 +221,8 @@ func (o *SOVSBridgeDriver) AddFlow(cond string, priority int, actions string) st
}
func (o *SOVSBridgeDriver) DoAddFlow(cond string, pri int, actions, swt string) error {
_, err := procutils.NewCommand("ovs-ofctl", "add-flow", swt,
return procutils.NewCommand("ovs-ofctl", "add-flow", swt,
fmt.Sprintf("%s priority=%d actions=%s", cond, pri, actions)).Run()
return err
}
func (o *SOVSBridgeDriver) DelFlow(cond string) string {
+83 -13
View File
@@ -16,16 +16,19 @@ package hostinfo
import (
"context"
"errors"
"fmt"
"io/ioutil"
"net"
"os"
"path"
"reflect"
"regexp"
"strconv"
"strings"
"time"
"github.com/pkg/errors"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/util/version"
@@ -136,12 +139,73 @@ func (h *SHostInfo) Init() error {
return nil
}
func (h *SHostInfo) generateLocalNetworkConfig() (string, error) {
output, err := procutils.NewCommand("ip", "route", "get", "1").Output()
if err != nil {
return "", errors.Wrap(err, "ip route get")
}
lines := strings.Split(string(output), "\n")
if len(lines) == 0 {
return "", fmt.Errorf("can't find local ip address")
}
fields := strings.Fields(lines[0])
if len(fields) != 7 {
return "", fmt.Errorf("failed to parse output %v", lines)
}
ip := fields[len(fields)-1]
log.Infof("found ip address %s", ip)
netIp := net.ParseIP(strings.TrimSpace(ip))
if netIp == nil {
return "", fmt.Errorf("failed to parse found ip address %s", ip)
}
if netIp.To4() == nil {
return "", fmt.Errorf("not support ipv6 address %s", ip)
}
dev := fields[len(fields)-3]
log.Infof("found net dev %s", dev)
_, err = net.InterfaceByName(dev)
if err != nil {
return "", errors.Wrap(err, "interface by name")
}
// not a physical device
if !fileutils2.Exists(path.Join("/sys/class/net", dev, "device")) {
return "", errors.Errorf("found dev %s not a physical device", dev)
}
bridgeName := "br"
index := 0
for {
if _, err := net.InterfaceByName(bridgeName + strconv.Itoa(index)); err != nil {
bridgeName = bridgeName + strconv.Itoa(index)
break
}
index += 1
}
log.Infof("new bridge name %s", bridgeName)
return fmt.Sprintf("%s/%s/%s", dev, bridgeName, ip), nil
}
func (h *SHostInfo) parseConfig() error {
if mem, err := h.GetMemory(); err != nil {
return err
} else if mem < 64 { // MB
return fmt.Errorf("Not enough memory!")
}
if len(options.HostOptions.Networks) == 0 {
netConf, err := h.generateLocalNetworkConfig()
if err != nil {
return err
}
options.HostOptions.Networks = []string{netConf}
if len(options.HostOptions.Config) > 0 {
if err = fileutils2.FilePutContents(
options.HostOptions.Config,
jsonutils.Marshal(options.HostOptions).YAMLString(),
false,
); err != nil {
log.Errorf("write config file failed %s", err)
}
}
}
for _, n := range options.HostOptions.Networks {
nic, err := NewNIC(n)
if err != nil {
@@ -180,17 +244,22 @@ func (h *SHostInfo) prepareEnv() error {
return fmt.Errorf("Option report_interval must no longer than 5 min")
}
_, err := procutils.NewCommand("mkdir", "-p", options.HostOptions.ServersPath).Run()
_, err := procutils.NewCommand("mkdir", "-p", options.HostOptions.ServersPath).Output()
if err != nil {
return fmt.Errorf("Failed to create path %s", options.HostOptions.ServersPath)
}
_, err = procutils.NewCommand(qemutils.GetQemu(""), "-version").Run()
if len(qemutils.GetQemu("")) == 0 {
return fmt.Errorf("Qemu not installed")
}
_, err = procutils.NewCommand(qemutils.GetQemu(""), "-version").Output()
if err != nil {
return fmt.Errorf("Qemu/Kvm not installed")
}
if !fileutils2.Exists("/sbin/ethtool") {
_, err = procutils.NewCommand("/sbin/ethtool", "-h").Output()
if err != nil {
return fmt.Errorf("Ethtool not installed")
}
@@ -205,11 +274,11 @@ func (h *SHostInfo) prepareEnv() error {
ioParams["queue/iosched/quantum"] = "32"
}
fileutils2.ChangeAllBlkdevsParams(ioParams)
_, err = procutils.NewCommand("modprobe", "tun").Run()
_, err = procutils.NewCommand("modprobe", "tun").Output()
if err != nil {
return fmt.Errorf("Failed to activate tun/tap device")
}
output, err := procutils.NewCommand("modprobe", "vhost_net").Run()
output, err := procutils.NewCommand("modprobe", "vhost_net").Output()
if err != nil {
log.Errorf("modprobe error: %s", output)
}
@@ -256,7 +325,7 @@ func (h *SHostInfo) prepareEnv() error {
}
func (h *SHostInfo) detectHostInfo() error {
output, err := procutils.NewCommand("dmidecode", "-t", "1").Run()
output, err := procutils.NewCommand("dmidecode", "-t", "1").Output()
if err != nil {
return err
}
@@ -373,7 +442,7 @@ func (h *SHostInfo) EnableNativeHugepages() error {
err = timeutils2.CommandWithTimeout(1, "sh", "-c", fmt.Sprintf("echo %d > /proc/sys/vm/nr_hugepages", preAllocPagesNum)).Run()
if err != nil {
log.Errorln(err)
_, err = procutils.NewCommand("sh", "-c", "echo 0 > /proc/sys/vm/nr_hugepages").Run()
_, err = procutils.NewCommand("sh", "-c", "echo 0 > /proc/sys/vm/nr_hugepages").Output()
if err != nil {
log.Warningln(err)
}
@@ -412,7 +481,7 @@ func (h *SHostInfo) TuneSystem() {
func (h *SHostInfo) resetIptables() error {
for _, tbl := range []string{"filter", "nat", "mangle"} {
_, err := procutils.NewCommand("iptables", "-t", tbl, "-F").Run()
_, err := procutils.NewCommand("iptables", "-t", tbl, "-F").Output()
if err != nil {
return fmt.Errorf("Fail to clean NAT iptable: %s", err)
}
@@ -434,7 +503,7 @@ func (h *SHostInfo) detectNestSupport() {
}
func (h *SHostInfo) detectiveOsDist() {
files, err := procutils.NewCommand("sh", "-c", "ls /etc/*elease").Run()
files, err := procutils.NewCommand("sh", "-c", "ls /etc/*elease").Output()
if err != nil {
log.Errorln(err)
return
@@ -459,7 +528,7 @@ func (h *SHostInfo) detectiveOsDist() {
}
func (h *SHostInfo) detectiveKernelVersion() {
out, err := procutils.NewCommand("uname", "-r").Run()
out, err := procutils.NewCommand("uname", "-r").Output()
if err != nil {
log.Errorln(err)
}
@@ -478,7 +547,7 @@ func (h *SHostInfo) detectiveSyssoftwareInfo() error {
func (h *SHostInfo) detectiveQemuVersion() error {
cmd := qemutils.GetQemu(options.HostOptions.DefaultQemuVersion)
version, err := procutils.NewCommand(cmd, "--version").Run()
version, err := procutils.NewCommand(cmd, "--version").Output()
if err != nil {
log.Errorln(err)
return err
@@ -497,7 +566,7 @@ func (h *SHostInfo) detectiveQemuVersion() error {
}
func (h *SHostInfo) detectiveOvsVersion() {
version, err := procutils.NewCommand("ovs-vsctl", "--version").Run()
version, err := procutils.NewCommand("ovs-vsctl", "--version").Output()
if err != nil {
log.Errorln(err)
} else {
@@ -514,6 +583,7 @@ func (h *SHostInfo) detectiveOvsVersion() {
}
func (h *SHostInfo) GetMasterNicIpAndMask() (string, int) {
log.Errorf("MasterNic %#v", h.MasterNic)
if h.MasterNic != nil {
mask, _ := h.MasterNic.Mask.Size()
return h.MasterNic.Addr, mask
+3 -3
View File
@@ -87,7 +87,7 @@ func DetectCpuInfo() (*SCPUInfo, error) {
if err != nil {
return nil, errors.Wrap(err, "parse cpu info")
}
bret, err := procutils.NewCommand("dmidecode", "-t", "4").Run()
bret, err := procutils.NewCommand("dmidecode", "-t", "4").Output()
if err != nil {
return nil, errors.Wrap(err, "get dmidecode info -t 4")
}
@@ -95,7 +95,7 @@ func DetectCpuInfo() (*SCPUInfo, error) {
if err != nil {
return nil, errors.Wrap(err, "parse dmi cpuinfo")
}
cpuArch, err := procutils.NewCommand("uname", "-p").Run()
cpuArch, err := procutils.NewCommand("uname", "-p").Output()
if err != nil {
return nil, errors.Wrap(err, "get cpu architecture")
}
@@ -154,7 +154,7 @@ func DetectMemoryInfo() (*SMemory, error) {
smem.Total = int(info.Total / 1024 / 1024)
smem.Free = int(info.Available / 1024 / 1024)
smem.Used = smem.Total - smem.Free
ret, err := procutils.NewCommand("dmidecode", "-t", "17").Run()
ret, err := procutils.NewCommand("dmidecode", "-t", "17").Output()
if err != nil {
return nil, err
}
+17 -3
View File
@@ -333,7 +333,7 @@ func (dev *sGPUBaseDevice) GetVGACmd() string {
func (dev *sGPUBaseDevice) CustomProbe() error {
// vfio kernel driver check
for _, driver := range []string{"vfio", "vfio_iommu_type1", "vfio-pci"} {
if _, err := procutils.Run("modprobe", driver); err != nil {
if err := procutils.NewCommand("modprobe", driver).Run(); err != nil {
return fmt.Errorf("modprobe %s: %v", driver, err)
}
}
@@ -422,9 +422,22 @@ func (gpu *sGPUHPCDevice) GetPassthroughCmd(index int) string {
return fmt.Sprintf(" -device vfio-pci,host=%s,multifunction=on", gpu.GetAddr())
}
func ParseOutput(output []byte) []string {
lines := make([]string, 0)
for _, line := range strings.Split(string(output), "\n") {
lines = append(lines, strings.TrimSpace(line))
}
return lines
}
func bashOutput(cmd string) ([]string, error) {
args := []string{"-c", cmd}
return procutils.Run("bash", args...)
output, err := procutils.NewCommand("bash", args...).Output()
if err != nil {
return nil, err
} else {
return ParseOutput(output), nil
}
}
func gpuPCIString() ([]string, error) {
@@ -522,10 +535,11 @@ func (d *PCIDevice) checkSameIOMMUGroupDevice() error {
func (d *PCIDevice) IsBootVGA() (bool, error) {
addr := d.Addr
paths, err := procutils.Run("find", "/sys/devices", "-name", "boot_vga")
output, err := procutils.NewCommand("find", "/sys/devices", "-name", "boot_vga").Output()
if err != nil {
return false, err
}
paths := ParseOutput(output)
for _, p := range paths {
if strings.Contains(p, addr) {
if content, err := fileutils2.FileGetContents(p); err != nil {
+3
View File
@@ -107,6 +107,9 @@ type SHostOptions struct {
DeployServerSocketPath string `help:"Deploy server listen socket path" default:"/var/run/deploy.sock"`
DefaultRequestWorkerCount int `default:"8" help:"default request worker count"`
EnableRemoteExecutor bool `help:"Enable remote executor" default:"false"`
ExecutorSocketPath string `help:"Executor socket path" default:"/var/run/exec.sock"`
CommonConfigFile string `help:"common config file for container"`
}
var HostOptions SHostOptions
+1 -1
View File
@@ -321,7 +321,7 @@ func cleanDailyFiles(storagePath, subDir string, keepDay int) {
if date.Before(markTime) {
log.Infof("Cron Job Clean Recycle Bin: start delete %s", file.Name())
subDirPath := path.Join(recycleDir, file.Name())
if _, err := procutils.NewCommand("rm", "-rf", subDirPath).Run(); err != nil {
if _, err := procutils.NewCommand("rm", "-rf", subDirPath).Output(); err != nil {
log.Errorf("clean recycle dir %s error %s", subDirPath, err)
}
}
+18 -18
View File
@@ -322,10 +322,10 @@ func (d *SLocalDisk) GetDiskSetupScripts(diskIndex int) string {
func (d *SLocalDisk) PostCreateFromImageFuse() {
mntPath := path.Join(d.Storage.GetFuseMountPath(), d.Id)
if _, err := procutils.NewCommand("umount", mntPath).Run(); err != nil {
if _, err := procutils.NewCommand("umount", mntPath).Output(); err != nil {
log.Errorln(err)
}
if _, err := procutils.NewCommand("rm", "-rf", mntPath).Run(); err != nil {
if _, err := procutils.NewCommand("rm", "-rf", mntPath).Output(); err != nil {
log.Errorln(err)
}
tmpPath := d.Storage.GetFuseTmpPath()
@@ -342,14 +342,14 @@ func (d *SLocalDisk) PostCreateFromImageFuse() {
func (d *SLocalDisk) CreateSnapshot(snapshotId string) error {
snapshotDir := d.GetSnapshotDir()
if !fileutils2.Exists(snapshotDir) {
_, err := procutils.NewCommand("mkdir", "-p", snapshotDir).Run()
_, err := procutils.NewCommand("mkdir", "-p", snapshotDir).Output()
if err != nil {
log.Errorln(err)
return err
}
}
snapshotPath := path.Join(snapshotDir, snapshotId)
_, err := procutils.NewCommand("mv", "-f", d.getPath(), snapshotPath).Run()
_, err := procutils.NewCommand("mv", "-f", d.getPath(), snapshotPath).Output()
if err != nil {
log.Errorln(err)
return err
@@ -372,7 +372,7 @@ func (d *SLocalDisk) DeleteSnapshot(snapshotId, convertSnapshot string, pendingD
snapshotDir := d.GetSnapshotDir()
if len(convertSnapshot) > 0 {
if !fileutils2.Exists(snapshotDir) {
_, err := procutils.NewCommand("mkdir", "-p", snapshotDir).Run()
err := procutils.NewCommand("mkdir", "-p", snapshotDir).Run()
if err != nil {
log.Errorln(err)
return err
@@ -393,16 +393,16 @@ func (d *SLocalDisk) DeleteSnapshot(snapshotId, convertSnapshot string, pendingD
procutils.NewCommand("rm", "-f", output).Run()
return err
}
if _, err = procutils.NewCommand("rm", "-f", convertSnapshotPath).Run(); err != nil {
if err = procutils.NewCommand("rm", "-f", convertSnapshotPath).Run(); err != nil {
log.Errorln(err)
return err
}
if _, err = procutils.NewCommand("mv", "-f", output, convertSnapshotPath).Run(); err != nil {
if err = procutils.NewCommand("mv", "-f", output, convertSnapshotPath).Run(); err != nil {
log.Errorln(err)
return err
}
if !pendingDelete {
_, err = procutils.NewCommand("rm", "-f", path.Join(snapshotDir, snapshotId)).Run()
err = procutils.NewCommand("rm", "-f", path.Join(snapshotDir, snapshotId)).Run()
if err != nil {
log.Errorln(err)
return err
@@ -410,7 +410,7 @@ func (d *SLocalDisk) DeleteSnapshot(snapshotId, convertSnapshot string, pendingD
}
return nil
} else {
_, err := procutils.NewCommand("rm", "-f", path.Join(snapshotDir, snapshotId)).Run()
err := procutils.NewCommand("rm", "-f", path.Join(snapshotDir, snapshotId)).Run()
if err != nil {
log.Errorln(err)
return err
@@ -428,12 +428,12 @@ func (d *SLocalDisk) PrepareSaveToGlance(ctx context.Context, params interface{}
return nil, err
}
destDir := d.Storage.GetImgsaveBackupPath()
if _, err := procutils.NewCommand("mkdir", "-p", destDir).Run(); err != nil {
if err := procutils.NewCommand("mkdir", "-p", destDir).Run(); err != nil {
log.Errorln(err)
return nil, err
}
backupPath := path.Join(destDir, fmt.Sprintf("%s.%s", d.Id, appctx.AppContextTaskId(ctx)))
if _, err := procutils.NewCommand("cp", "--sparse=always", "-f", d.GetPath(), backupPath).Run(); err != nil {
if err := procutils.NewCommand("cp", "--sparse=always", "-f", d.GetPath(), backupPath).Run(); err != nil {
log.Errorln(err)
procutils.NewCommand("rm", "-f", backupPath).Run()
return nil, err
@@ -461,7 +461,7 @@ func (d *SLocalDisk) ResetFromSnapshot(ctx context.Context, params interface{})
func (d *SLocalDisk) resetFromSnapshot(snapshotPath string, outOfChain bool) (jsonutils.JSONObject, error) {
diskTmpPath := d.GetPath() + "_reset.tmp"
if output, err := procutils.NewCommand("mv", "-f", d.GetPath(), diskTmpPath).Run(); err != nil {
if output, err := procutils.NewCommand("mv", "-f", d.GetPath(), diskTmpPath).Output(); err != nil {
err = errors.Wrapf(err, "mv disk to tmp failed: %s", output)
return nil, err
}
@@ -478,13 +478,14 @@ func (d *SLocalDisk) resetFromSnapshot(snapshotPath string, outOfChain bool) (js
return nil, err
}
} else {
if output, err := procutils.NewCommand("cp", "-f", snapshotPath, d.GetPath()).Run(); err != nil {
if output, err := procutils.NewCommand("cp", "-f", snapshotPath, d.GetPath()).Output(); err != nil {
err = errors.Wrapf(err, "cp snapshot to disk %s", output)
procutils.NewCommand("mv", "-f", diskTmpPath, d.GetPath()).Run()
return nil, err
}
}
output, err := procutils.NewCommand("rm", "-f", diskTmpPath).Run()
output, err := procutils.NewCommand("rm", "-f", diskTmpPath).Output()
if err != nil {
err = errors.Wrapf(err, "rm disk tmp path %s", output)
return nil, err
@@ -511,7 +512,7 @@ func (d *SLocalDisk) CleanupSnapshots(ctx context.Context, params interface{}) (
log.Errorln(err)
return nil, err
}
if procutils.NewCommand("mv", "-f", output, snapshotPath).Run(); err != nil {
if err := procutils.NewCommand("mv", "-f", output, snapshotPath).Run(); err != nil {
procutils.NewCommand("rm", "-f", output).Run()
log.Errorln(err)
return nil, err
@@ -520,7 +521,7 @@ func (d *SLocalDisk) CleanupSnapshots(ctx context.Context, params interface{}) (
for _, snapshotId := range cleanupParams.DeleteSnapshots {
snapId, _ := snapshotId.GetString()
if _, err := procutils.NewCommand("rm", "-f", path.Join(snapshotDir, snapId)).Run(); err != nil {
if err := procutils.NewCommand("rm", "-f", path.Join(snapshotDir, snapId)).Run(); err != nil {
log.Errorln(err)
return nil, err
}
@@ -537,8 +538,7 @@ func (d *SLocalDisk) DeleteAllSnapshot() error {
return d.Storage.DeleteDiskfile(snapshotDir)
} else {
log.Infof("Delete disk(%s) snapshot dir %s", d.Id, snapshotDir)
_, err := procutils.NewCommand("rm", "-rf", snapshotDir).Run()
return err
return procutils.NewCommand("rm", "-rf", snapshotDir).Run()
}
}
+1 -2
View File
@@ -76,8 +76,7 @@ func (r *SRbdImageCache) Acquire(ctx context.Context, zone, srcUrl, format strin
r.imageName = localImageCache.GetName()
if !r.Load() {
log.Debugf("convert local image %s to rbd pool %s", r.imageId, r.Manager.GetPath())
_, err := procutils.NewCommand(qemutils.GetQemuImg(), "convert", "-O", "raw", localImageCache.GetPath(), r.GetPath()).Run()
err := procutils.NewCommand(qemutils.GetQemuImg(), "convert", "-O", "raw", localImageCache.GetPath(), r.GetPath()).Run()
if err != nil {
log.Errorf("failed to convert image %s", options.HostOptions.ServersPath)
return false
+2 -2
View File
@@ -439,11 +439,11 @@ func requestDeleteSnapshot(
log.Errorln(err)
return
}
if out, err := procutils.NewCommand("rm", "-f", convertSnapshotPath).Run(); err != nil {
if out, err := procutils.NewCommand("rm", "-f", convertSnapshotPath).Output(); err != nil {
log.Errorf("%s", out)
return
}
if out, err := procutils.NewCommand("mv", "-f", outfile, convertSnapshotPath).Run(); err != nil {
if out, err := procutils.NewCommand("mv", "-f", outfile, convertSnapshotPath).Output(); err != nil {
log.Errorf("%s", out)
return
}
+8 -11
View File
@@ -144,7 +144,7 @@ func (s *SLocalStorage) CreateDisk(diskId string) IDisk {
func (s *SLocalStorage) Accessible() bool {
if !fileutils2.Exists(s.Path) {
if _, err := procutils.NewCommand("mkdir", "-p", s.Path).Run(); err != nil {
if err := procutils.NewCommand("mkdir", "-p", s.Path).Run(); err != nil {
log.Errorln(err)
}
}
@@ -162,14 +162,12 @@ func (s *SLocalStorage) DeleteDiskfile(diskpath string) error {
destDir = s.getRecyclePath()
destFile = fmt.Sprintf("%s.%d", path.Base(diskpath), time.Now().Unix())
)
if _, err := procutils.NewCommand("mkdir", "-p", destDir).Run(); err != nil {
if err := procutils.NewCommand("mkdir", "-p", destDir).Run(); err != nil {
return err
}
_, err := procutils.NewCommand("mv", "-f", diskpath, path.Join(destDir, destFile)).Run()
return err
return procutils.NewCommand("mv", "-f", diskpath, path.Join(destDir, destFile)).Run()
} else {
_, err := procutils.NewCommand("rm", "-rf", diskpath).Run()
return err
return procutils.NewCommand("rm", "-rf", diskpath).Run()
}
}
@@ -207,11 +205,10 @@ func (s *SLocalStorage) SaveToGlance(ctx context.Context, params interface{}) (j
imagecacheManager := s.Manager.LocalStorageImagecacheManager
if len(imagecacheManager.GetId()) > 0 {
_, err := procutils.NewCommand("rm", "-f", imagePath).Run()
return nil, err
return nil, procutils.NewCommand("rm", "-f", imagePath).Run()
} else {
dstPath := path.Join(imagecacheManager.GetPath(), imageId)
if _, err := procutils.NewCommand("mv", imagePath, dstPath).Run(); err != nil {
if err := procutils.NewCommand("mv", imagePath, dstPath).Run(); err != nil {
log.Errorf("Fail to move saved image to cache: %s", err)
}
imagecacheManager.LoadImageCache(imageId)
@@ -317,7 +314,7 @@ func (s *SLocalStorage) DeleteSnapshots(ctx context.Context, params interface{})
return nil, hostutils.ParamsError
}
snapshotDir := path.Join(s.GetSnapshotDir(), diskId+options.HostOptions.SnapshotDirSuffix)
output, err := procutils.NewCommand("rm", "-rf", snapshotDir).Run()
output, err := procutils.NewCommand("rm", "-rf", snapshotDir).Output()
if err != nil {
return nil, fmt.Errorf("Delete snapshot dir failed: %s", output)
}
@@ -343,7 +340,7 @@ func (s *SLocalStorage) DestinationPrepareMigrate(
templateId, _ := diskinfo.GetString("template_id")
// prepare disk snapshot dir
if len(snapshots) > 0 && !fileutils2.Exists(disk.GetSnapshotDir()) {
_, err := procutils.NewCommand("mkdir", "-p", disk.GetSnapshotDir()).Run()
_, err := procutils.NewCommand("mkdir", "-p", disk.GetSnapshotDir()).Output()
if err != nil {
return err
}
+6 -4
View File
@@ -92,7 +92,7 @@ func (s *SNFSStorage) SetStorageInfo(storageId, storageName string, conf jsonuti
}
func (s *SNFSStorage) checkAndMount() error {
if _, err := procutils.NewCommand("mountpoint", s.Path).Run(); err == nil {
if err := procutils.NewCommand("mountpoint", s.Path).Run(); err == nil {
return nil
}
if s.StorageConf == nil {
@@ -106,10 +106,12 @@ func (s *SNFSStorage) checkAndMount() error {
if err != nil {
return fmt.Errorf("Storage conf missing nfs_shared_dir")
}
output, err := procutils.NewCommand(
"mount", "-t", "nfs", fmt.Sprintf("%s:%s", host, sharedDir), s.Path).RunWithTimeout(10 * time.Second)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
err = procutils.NewCommandContext(ctx,
"mount", "-t", "nfs", fmt.Sprintf("%s:%s", host, sharedDir), s.Path).Run()
if err != nil {
return fmt.Errorf("%s", output)
return err
}
return nil
}
+2 -1
View File
@@ -658,7 +658,8 @@ func (s *SRbdStorage) saveToGlance(ctx context.Context, imageId, imagePath strin
format = options.HostOptions.DefaultImageSaveFormat
}
_, err = procutils.NewCommand(qemutils.GetQemuImg(), "convert", "-f", "raw", "-O", format, imagePath, tmpImageFile).Run()
err = procutils.NewCommand(qemutils.GetQemuImg(),
"convert", "-f", "raw", "-O", format, imagePath, tmpImageFile).Run()
if err != nil {
return err
}
@@ -66,7 +66,7 @@ func storageVerifyMountPoint(ctx context.Context, w http.ResponseWriter, r *http
hostutils.Response(ctx, w, httperrors.NewMissingParameterError("mount_point"))
return
}
output, err := procutils.NewCommand("mountpoint", mountPoint).Run()
output, err := procutils.NewCommand("mountpoint", mountPoint).Output()
if err == nil {
appsrv.SendStruct(w, map[string]interface{}{"is_mount_point": true})
} else {
+14 -10
View File
@@ -38,16 +38,20 @@ type ISystemService interface {
type NewServiceFunc func()
var serviceMap = map[string]ISystemService{
"ntpd": NewNtpdService(),
"telegraf": NewTelegrafService(),
"host_sdnagent": NewHostSdnagentService(),
"openvswitch": NewOpenvswitchService(),
"fluentbit": NewFluentbitService(),
"kube_agent": NewKubeAgentService(),
"lxcfs": NewLxcfsService(),
"docker": NewDockerService(),
"host-deployer": NewHostDeployerService(),
var serviceMap map[string]ISystemService
func Init() {
serviceMap = map[string]ISystemService{
"ntpd": NewNtpdService(),
"telegraf": NewTelegrafService(),
"host_sdnagent": NewHostSdnagentService(),
"openvswitch": NewOpenvswitchService(),
"fluentbit": NewFluentbitService(),
"kube_agent": NewKubeAgentService(),
"lxcfs": NewLxcfsService(),
"docker": NewDockerService(),
"host-deployer": NewHostDeployerService(),
}
}
func GetService(name string) ISystemService {
+7 -12
View File
@@ -28,33 +28,28 @@ type SSystemdServiceManager struct {
}
func (manager *SSystemdServiceManager) Detect() bool {
_, err := procutils.NewCommand("systemctl", "--version").Run()
return err == nil
return procutils.NewCommand("systemctl", "--version").Run() == nil
}
func (manager *SSystemdServiceManager) Start(srvname string) error {
_, err := procutils.NewCommand("systemctl", "restart", srvname).Run()
return err
return procutils.NewCommand("systemctl", "restart", srvname).Run()
}
func (manager *SSystemdServiceManager) Enable(srvname string) error {
_, err := procutils.NewCommand("systemctl", "enable", srvname).Run()
return err
return procutils.NewCommand("systemctl", "enable", srvname).Run()
}
func (manager *SSystemdServiceManager) Stop(srvname string) error {
_, err := procutils.NewCommand("systemctl", "stop", srvname).Run()
return err
return procutils.NewCommand("systemctl", "stop", srvname).Run()
}
func (manager *SSystemdServiceManager) Disable(srvname string) error {
_, err := procutils.NewCommand("systemctl", "disable", srvname).Run()
return err
return procutils.NewCommand("systemctl", "disable", srvname).Run()
}
func (manager *SSystemdServiceManager) GetStatus(srvname string) SServiceStatus {
res, _ := procutils.NewCommand("systemctl", "status", srvname).Run()
res2, _ := procutils.NewCommand("systemctl", "is-enabled", srvname).Run()
res, _ := procutils.NewCommand("systemctl", "status", srvname).Output()
res2, _ := procutils.NewCommand("systemctl", "is-enabled", srvname).Output()
return parseSystemdStatus(string(res), string(res2), srvname)
}
+7 -12
View File
@@ -28,33 +28,28 @@ type SSysVServiceManager struct {
}
func (manager *SSysVServiceManager) Detect() bool {
_, err := procutils.NewCommand("chkconfig", "--version").Run()
return err == nil
return procutils.NewCommand("chkconfig", "--version").Run() == nil
}
func (manager *SSysVServiceManager) Start(srvname string) error {
_, err := procutils.NewCommand("service", srvname, "restart").Run()
return err
return procutils.NewCommand("service", srvname, "restart").Run()
}
func (manager *SSysVServiceManager) Enable(srvname string) error {
_, err := procutils.NewCommand("chkconfig", srvname, "on").Run()
return err
return procutils.NewCommand("chkconfig", srvname, "on").Run()
}
func (manager *SSysVServiceManager) Stop(srvname string) error {
_, err := procutils.NewCommand("service", srvname, "stop").Run()
return err
return procutils.NewCommand("service", srvname, "stop").Run()
}
func (manager *SSysVServiceManager) Disable(srvname string) error {
_, err := procutils.NewCommand("chkconfig", srvname, "off").Run()
return err
return procutils.NewCommand("chkconfig", srvname, "off").Run()
}
func (manager *SSysVServiceManager) GetStatus(srvname string) SServiceStatus {
res, _ := procutils.NewCommand("chkconfig", "--list", srvname).Run()
res2, _ := procutils.NewCommand("service", srvname, "status").Run()
res, _ := procutils.NewCommand("chkconfig", "--list", srvname).Output()
res2, _ := procutils.NewCommand("service", srvname, "status").Output()
return parseSysvStatus(string(res), string(res2), srvname)
}
+6 -9
View File
@@ -81,8 +81,7 @@ func getGroupPath() string {
}
func CgroupIsMounted() bool {
_, err := procutils.NewCommand("mountpoint", cgroupsPath).Run()
return err == nil
return procutils.NewCommand("mountpoint", cgroupsPath).Run() == nil
}
func ModuleIsMounted(module string) bool {
@@ -97,8 +96,7 @@ func ModuleIsMounted(module string) bool {
log.Errorln(err)
}
}
_, err := procutils.NewCommand("mountpoint", fullPath).Run()
return err == nil
return procutils.NewCommand("mountpoint", fullPath).Run() == nil
}
func RootTaskPath(module string) string {
@@ -318,11 +316,11 @@ func (c *CGroupTask) PushPid(pid string, isRoot bool) {
func (c *CGroupTask) init() bool {
if !CgroupIsMounted() {
if !fileutils2.Exists(cgroupsPath) {
if _, err := procutils.NewCommand("mkdir", "-p", cgroupsPath).Run(); err != nil {
if err := procutils.NewCommand("mkdir", "-p", cgroupsPath).Run(); err != nil {
log.Errorln(err)
}
}
if _, err := procutils.NewCommand("mount", "-t", "tmpfs", "-o", "uid=0,gid=0,mode=0755",
if err := procutils.NewCommand("mount", "-t", "tmpfs", "-o", "uid=0,gid=0,mode=0755",
"cgroup", cgroupsPath).Run(); err != nil {
log.Errorln(err)
return false
@@ -345,13 +343,12 @@ func (c *CGroupTask) init() bool {
if !ModuleIsMounted(module) {
moduleDir := path.Join(cgroupsPath, module)
if !fileutils2.Exists(moduleDir) {
if _, err := procutils.NewCommand("mkdir", moduleDir).Run(); err != nil {
if _, err := procutils.NewCommand("mkdir", moduleDir).Output(); err != nil {
log.Errorln(err)
return false
}
}
log.Errorln(module)
if _, err := procutils.NewCommand("mount", "-t", "cgroup", "-o",
if err := procutils.NewCommand("mount", "-t", "cgroup", "-o",
module, module, moduleDir).Run(); err != nil {
log.Errorln(err)
return false
+4 -4
View File
@@ -15,10 +15,11 @@
package fileutils2
import (
"os/exec"
"regexp"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/util/procutils"
)
const (
@@ -30,10 +31,9 @@ var (
)
func GetBlkidType(filepath string) string {
cmd := exec.Command("blkid", filepath)
out, err := cmd.CombinedOutput()
out, err := procutils.NewCommand("blkid", filepath).Output()
if err != nil {
log.Errorf("blkid fail %s %s", filepath, err)
log.Errorf("blkid fail %s %s", filepath, out)
return ""
}
matches := blkidTypeRegexp.FindStringSubmatch(string(out))
+29 -383
View File
@@ -17,25 +17,18 @@ package fileutils2
import (
"bufio"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"path"
"path/filepath"
"regexp"
"strconv"
"strings"
"syscall"
"github.com/pkg/errors"
"golang.org/x/sys/unix"
"yunion.io/x/log"
"yunion.io/x/pkg/utils"
"yunion.io/x/onecloud/pkg/util/procutils"
"yunion.io/x/onecloud/pkg/util/regutils2"
)
func Cleandir(sPath string, keepdir bool) error {
@@ -124,7 +117,7 @@ func FilePutContents(filename string, content string, modAppend bool) error {
func IsBlockDevMounted(dev string) bool {
devPath := "/dev/" + dev
mounts, err := procutils.NewCommand("mount").Run()
mounts, err := procutils.NewCommand("mount").Output()
if err != nil {
return false
}
@@ -141,7 +134,7 @@ func IsBlockDeviceUsed(dev string) bool {
dev = dev[strings.LastIndex(dev, "/")+1:]
}
devStr := fmt.Sprintf(" %s\n", dev)
devs, _ := procutils.NewCommand("cat", "/proc/partitions").Run()
devs, _ := procutils.NewCommand("cat", "/proc/partitions").Output()
if idx := strings.Index(string(devs), devStr); idx > 0 {
return true
}
@@ -185,7 +178,7 @@ func FileGetContents(file string) (string, error) {
}
func GetFsFormat(diskPath string) string {
ret, err := procutils.NewCommand("blkid", "-o", "value", "-s", "TYPE", diskPath).Run()
ret, err := procutils.NewCommand("blkid", "-o", "value", "-s", "TYPE", diskPath).Output()
if err != nil {
return ""
}
@@ -267,384 +260,13 @@ func FsFormatToDiskType(fsFormat string) string {
}
}
func Mkpartition(imagePath, fsFormat string) error {
var (
parted = "/sbin/parted"
labelType = "gpt"
diskType = FsFormatToDiskType(fsFormat)
)
if len(diskType) == 0 {
return fmt.Errorf("Unknown fsFormat %s", fsFormat)
}
// 创建一个新磁盘分区表类型, ex: mbr gpt msdos ...
_, err := procutils.NewCommand(parted, "-s", imagePath, "mklabel", labelType).Run()
if err != nil {
log.Errorf("mklabel %s %s error %s", imagePath, fsFormat, err)
return err
}
// 创建一个part-type类型的分区, part-type可以是:"primary", "logical", "extended"
// 如果指定fs-type(即diskType)则在创建分区的同时进行格式化
_, err = procutils.NewCommand(parted, "-s", "-a", "cylinder",
imagePath, "mkpart", "primary", diskType, "0", "100%").Run()
if err != nil {
log.Errorf("mkpart %s %s error %s", imagePath, fsFormat, err)
return err
}
return nil
}
func FormatPartition(path, fs, uuid string) error {
var cmd, cmdUuid []string
switch {
case fs == "swap":
cmd = []string{"mkswap", "-U", uuid}
case fs == "ext2":
cmd = []string{"mkfs.ext2"}
cmdUuid = []string{"tune2fs", "-U", uuid}
case fs == "ext3":
cmd = []string{"mkfs.ext3"}
cmdUuid = []string{"tune2fs", "-U", uuid}
case fs == "ext4":
cmd = []string{"mkfs.ext4", "-O", "^64bit", "-E", "lazy_itable_init=1"}
cmdUuid = []string{"tune2fs", "-U", uuid}
case fs == "ext4dev":
cmd = []string{"mkfs.ext4dev", "-E", "lazy_itable_init=1"}
cmdUuid = []string{"tune2fs", "-U", uuid}
case strings.HasPrefix(fs, "fat"):
cmd = []string{"mkfs.msdos"}
// #case fs == "ntfs":
// # cmd = []string{"/sbin/mkfs.ntfs"}
case fs == "xfs":
cmd = []string{"/sbin/mkfs.xfs", "-f", "-m", "crc=0", "-i", "projid32bit=0", "-n", "ftype=0"}
cmdUuid = []string{"xfs_admin", "-U", uuid}
}
if len(cmd) > 0 {
var cmds = cmd
cmds = append(cmds, path)
if _, err := procutils.NewCommand(cmds[0], cmds[1:]...).Run(); err != nil {
log.Errorln(err)
return err
}
if len(cmdUuid) > 0 {
cmds = cmdUuid
cmds = append(cmds, path)
if _, err := procutils.NewCommand(cmds[0], cmds[1:]...).Run(); err != nil {
log.Errorln(err)
return err
}
}
return nil
}
return fmt.Errorf("Unknown fs %s", fs)
}
func IsPartedFsString(fsstr string) bool {
return utils.IsInStringArray(strings.ToLower(fsstr), []string{
"ext2", "ext3", "ext4", "xfs",
"fat16", "fat32",
"hfs", "hfs+", "hfsx",
"linux-swap", "linux-swap(v1)",
"ntfs", "reiserfs", "ufs", "btrfs",
})
}
func ParseDiskPartition(dev string, lines []byte) ([][]string, string) {
var (
parts = [][]string{}
label string
labelPartten = regexp.MustCompile(`Partition Table:\s+(?P<label>\w+)`)
partten = regexp.MustCompile(`(?P<idx>\d+)\s+(?P<start>\d+)s\s+(?P<end>\d+)s\s+(?P<count>\d+)s`)
)
for _, line := range strings.Split(string(lines), "\n") {
if len(label) == 0 {
m := regutils2.GetParams(labelPartten, line)
if len(m) > 0 {
label = m["label"]
}
}
m := regutils2.GetParams(partten, line)
if len(m) > 0 {
var (
idx = m["idx"]
start = m["start"]
end = m["end"]
count = m["count"]
devname = dev
)
if '0' <= dev[len(dev)-1] && dev[len(dev)-1] <= '9' {
devname += "p"
}
devname += idx
data := regexp.MustCompile(`\s+`).Split(strings.TrimSpace(line), -1)
var disktype, fs, flag string
var offset = 0
if len(data) > 4 {
if label == "msdos" {
disktype = data[4]
if len(data) > 5 && IsPartedFsString(data[5]) {
fs = data[5]
offset += 1
}
if len(data) > 5+offset {
flag = data[5+offset]
}
} else if label == "gpt" {
if IsPartedFsString(data[4]) {
fs = data[4]
offset += 1
}
if len(data) > 4+offset {
disktype = data[4+offset]
}
if len(data) > 4+offset+1 {
flag = data[4+offset+1]
}
}
}
var bootable = ""
if len(flag) > 0 && strings.Index(flag, "boot") >= 0 {
bootable = "true"
}
parts = append(parts, []string{idx, bootable, start, end, count, disktype, fs,
devname})
}
}
return parts, label
}
func GetDevSector512Count(dev string) int {
sizeStr, _ := FileGetContents(fmt.Sprintf("/sys/block/%s/size", dev))
sizeStr = strings.Trim(sizeStr, "\n")
size, _ := strconv.Atoi(sizeStr)
return size
}
func ResizeDiskFs(diskPath string, sizeMb int) error {
var cmds = []string{"parted", "-a", "none", "-s", diskPath, "--", "unit", "s", "print"}
lines, err := procutils.NewCommand(cmds[0], cmds[1:]...).Run()
if err != nil {
log.Errorf("resize disk fs fail: %s", err)
return err
}
parts, label := ParseDiskPartition(diskPath, lines)
log.Infof("Parts: %v label: %s", parts, label)
maxSector := GetDevSector512Count(path.Base(diskPath))
if label == "gpt" {
proc := exec.Command("gdisk", diskPath)
stdin, err := proc.StdinPipe()
if err != nil {
return err
}
defer stdin.Close()
outb, err := proc.StdoutPipe()
if err != nil {
return err
}
defer outb.Close()
errb, err := proc.StderrPipe()
if err != nil {
return err
}
defer errb.Close()
if err := proc.Start(); err != nil {
return err
}
for _, s := range []string{"r", "e", "Y", "w", "Y", "Y"} {
io.WriteString(stdin, fmt.Sprintf("%s\n", s))
}
stdoutPut, err := ioutil.ReadAll(outb)
if err != nil {
return err
}
stderrOutPut, err := ioutil.ReadAll(errb)
if err != nil {
return err
}
log.Infof("gdisk: %s %s", stdoutPut, stderrOutPut)
if err = proc.Wait(); err != nil {
log.Errorln(err)
if exiterr, ok := err.(*exec.ExitError); ok {
ws := exiterr.Sys().(syscall.WaitStatus)
if ws.ExitStatus() != 1 {
return err
}
} else {
return err
}
}
}
if len(parts) > 0 && (label == "gpt" ||
(label == "msdos" && parts[len(parts)-1][5] == "primary")) {
var (
part = parts[len(parts)-1]
end int
)
if sizeMb > 0 {
end = sizeMb * 1024 * 2
} else if label == "gpt" {
end = maxSector - 35
} else {
end = maxSector - 1
}
if label == "msdos" && end >= 4294967296 {
end = 4294967295
}
cmds = []string{"parted", "-a", "none", "-s", diskPath, "--",
"unit", "s", "rm", part[0], "mkpart", part[5]}
if len(part[6]) > 0 {
cmds = append(cmds, part[6])
}
cmds = append(cmds, part[2], fmt.Sprintf("%ds", end))
if len(part[1]) > 0 {
cmds = append(cmds, "set", part[0], "boot", "on")
}
log.Infof("resize disk partition: %s", cmds)
output, err := procutils.NewCommand(cmds[0], cmds[1:]...).Run()
if err != nil {
return errors.Wrapf(err, "parted failed %s", output)
}
if len(part[6]) > 0 {
err, _ := ResizePartitionFs(part[7], part[6], false)
if err != nil {
return err
}
}
}
return nil
}
func FsckExtFs(fpath string) bool {
log.Debugf("Exec command: %v", []string{"e2fsck", "-f", "-p", fpath})
cmd := exec.Command("e2fsck", "-f", "-p", fpath)
if err := cmd.Start(); err != nil {
log.Errorln(err)
return false
} else {
err = cmd.Wait()
if err != nil {
if exiterr, ok := err.(*exec.ExitError); ok {
ws := exiterr.Sys().(syscall.WaitStatus)
if ws.ExitStatus() < 4 {
return true
}
}
log.Errorln(err)
return false
} else {
return true
}
}
}
func FsckXfsFs(fpath string) bool {
if _, err := procutils.NewCommand("xfs_check", fpath).Run(); err != nil {
log.Errorln(err)
procutils.NewCommand("xfs_repair", fpath).Run()
return false
}
return true
}
func ResizePartitionFs(fpath, fs string, raiseError bool) (error, bool) {
if len(fs) == 0 {
return nil, false
}
var (
cmds = [][]string{}
uuids = GetDevUuid(fpath)
)
if strings.HasPrefix(fs, "linux-swap") {
if v, ok := uuids["UUID"]; ok {
cmds = [][]string{{"mkswap", "-U", v, fpath}}
} else {
cmds = [][]string{{"mkswap", fpath}}
}
} else if strings.HasPrefix(fs, "ext") {
if !FsckExtFs(fpath) {
if raiseError {
return fmt.Errorf("Failed to fsck ext fs %s", fpath), false
} else {
return nil, false
}
}
cmds = [][]string{{"resize2fs", fpath}}
} else if fs == "xfs" {
var tmpPoint = fmt.Sprintf("/tmp/%s", strings.Replace(fpath, "/", "_", -1))
if _, err := procutils.NewCommand("mountpoint", tmpPoint).Run(); err == nil {
_, err = procutils.NewCommand("umount", "-f", tmpPoint).Run()
if err != nil {
log.Errorln(err)
return err, false
}
}
FsckXfsFs(fpath)
cmds = [][]string{{"mkdir", "-p", tmpPoint},
{"mount", fpath, tmpPoint},
{"sleep", "2"},
{"xfs_growfs", tmpPoint},
{"sleep", "2"},
{"umount", tmpPoint},
{"sleep", "2"},
{"rm", "-fr", tmpPoint}}
}
if len(cmds) > 0 {
for _, cmd := range cmds {
_, err := procutils.NewCommand(cmd[0], cmd[1:]...).Run()
if err != nil {
log.Errorln(err)
if raiseError {
return err, false
} else {
return nil, false
}
}
}
}
return nil, true
}
func GetDevUuid(dev string) map[string]string {
lines, err := procutils.NewCommand("blkid", dev).Run()
if err != nil {
return nil
}
for _, l := range strings.Split(string(lines), "\n") {
if strings.HasPrefix(l, dev) {
var ret = map[string]string{}
for _, part := range strings.Split(l, " ") {
data := strings.Split(part, "=")
if len(data) == 2 && strings.HasSuffix(data[0], "UUID") {
if data[1][0] == '"' || data[1][0] == '\'' {
ret[data[0]] = data[1][1 : len(data[1])-1]
} else {
ret[data[0]] = data[1]
}
}
}
return ret
}
}
return nil
}
func GetDevOfPath(spath string) string {
spath, err := filepath.Abs(spath)
if err != nil {
log.Errorln(err)
return ""
}
lines, err := procutils.NewCommand("mount").Run()
lines, err := procutils.NewCommand("mount").Output()
if err != nil {
log.Errorln(err)
return ""
@@ -677,7 +299,7 @@ func GetDevId(spath string) string {
if len(dev) == 0 {
return ""
}
devInfo, err := procutils.NewCommand("ls", "-l", dev).Run()
devInfo, err := procutils.NewCommand("ls", "-l", dev).Output()
if err != nil {
log.Errorln(err)
return ""
@@ -687,3 +309,27 @@ func GetDevId(spath string) string {
data[4] = data[4][:len(data[4])-1]
return strings.Join(data, ":")
}
func GetDevUuid(dev string) map[string]string {
lines, err := procutils.NewCommand("blkid", dev).Output()
if err != nil {
return nil
}
for _, l := range strings.Split(string(lines), "\n") {
if strings.HasPrefix(l, dev) {
var ret = map[string]string{}
for _, part := range strings.Split(l, " ") {
data := strings.Split(part, "=")
if len(data) == 2 && strings.HasSuffix(data[0], "UUID") {
if data[1][0] == '"' || data[1][0] == '\'' {
ret[data[0]] = data[1][1 : len(data[1])-1]
} else {
ret[data[0]] = data[1]
}
}
}
return ret
}
}
return nil
}
+5 -5
View File
@@ -38,18 +38,18 @@ func MountFusefs(fetcherfsPath, url, tmpdir, token, mntpath string, blocksize in
}
// is mounted
if _, err := procutils.NewCommand("mountpoint", mntpath).Run(); err == nil {
procutils.NewCommand("umount", mntpath).Run()
if err := procutils.NewCommand("mountpoint", mntpath).Run(); err == nil {
procutils.NewCommand("umount", mntpath).Output()
}
if !fileutils2.Exists(tmpdir) {
if _, err := procutils.NewCommand("mkdir", "-p", tmpdir).Run(); err != nil {
if err := procutils.NewCommand("mkdir", "-p", tmpdir).Run(); err != nil {
return err
}
}
if !fileutils2.Exists(mntpath) {
if _, err := procutils.NewCommand("mkdir", "-p", mntpath).Run(); err != nil {
if err := procutils.NewCommand("mkdir", "-p", mntpath).Run(); err != nil {
return err
}
}
@@ -61,7 +61,7 @@ func MountFusefs(fetcherfsPath, url, tmpdir, token, mntpath string, blocksize in
var cmd = []string{fetcherfsPath, "-s", "-o", opts, mntpath}
log.Infof("%s", strings.Join(cmd, " "))
_, err := procutils.NewCommand(cmd[0], cmd[1:]...).Run()
err := procutils.NewCommand(cmd[0], cmd[1:]...).Run()
if err != nil {
log.Errorf("Mount fetcherfs filed: %s", err)
procutils.NewCommand("umount", mntpath).Run()
+2 -2
View File
@@ -376,7 +376,7 @@ func GetSecretInterfaceAddress() (string, []byte) {
}
func (n *SNetInterface) GetRoutes(gwOnly bool) [][]string {
output, err := procutils.NewCommand("route", "-n").Run()
output, err := procutils.NewCommand("route", "-n").Output()
if err != nil {
return nil
}
@@ -410,7 +410,7 @@ func (n *SNetInterface) getAddresses(output []string) [][]string {
}
func (n *SNetInterface) GetAddresses() [][]string {
output, err := procutils.NewCommand("ip", "address", "show", "dev", n.name).Run()
output, err := procutils.NewCommand("ip", "address", "show", "dev", n.name).Output()
if err != nil {
log.Errorln(err)
return nil
+4 -4
View File
@@ -26,7 +26,7 @@ import (
)
func GetDbPorts(brname string) []string {
output, err := procutils.NewCommand("ovs-vsctl", "list-ifaces", brname).Run()
output, err := procutils.NewCommand("ovs-vsctl", "list-ifaces", brname).Output()
if err != nil {
log.Errorln(err)
return nil
@@ -43,7 +43,7 @@ func GetDbPorts(brname string) []string {
}
func GetDpPorts(brname string) []string {
output, err := procutils.NewCommand("ovs-dpctl", "show").Run()
output, err := procutils.NewCommand("ovs-dpctl", "show").Output()
if err != nil {
log.Errorln(err)
return nil
@@ -64,7 +64,7 @@ func GetDpPorts(brname string) []string {
}
func GetBridges() []string {
output, err := procutils.NewCommand("ovs-vsctl", "list-br").Run()
output, err := procutils.NewCommand("ovs-vsctl", "list-br").Output()
if err != nil {
log.Errorln(err)
return nil
@@ -82,7 +82,7 @@ func GetBridges() []string {
func RemovePortFromBridge(brname, port string) {
log.Infof("remove_port_from_bridge %s %s", brname, port)
if _, err := procutils.NewCommand("ovs-vsctl", "del-port", brname, port).Run(); err != nil {
if err := procutils.NewCommand("ovs-vsctl", "del-port", brname, port).Run(); err != nil {
log.Errorln(err)
}
}
+94
View File
@@ -0,0 +1,94 @@
package procutils
import (
"context"
"io"
"os/exec"
"syscall"
"yunion.io/x/executor/client"
)
var execInstance Executor
func init() {
execInstance = new(defaultExecutor)
}
func SetRemoteExecutor() {
execInstance = new(remoteExecutor)
}
type Cmd interface {
StdinPipe() (io.WriteCloser, error)
StdoutPipe() (io.ReadCloser, error)
StderrPipe() (io.ReadCloser, error)
CombinedOutput() ([]byte, error)
Start() error
Wait() error
Run() error
Kill() error
}
type Executor interface {
CommandContext(ctx context.Context, name string, args ...string) Cmd
Command(name string, args ...string) Cmd
GetExitStatus(err error) (int, bool)
}
type defaultCmd struct {
*exec.Cmd
}
func (c *defaultCmd) Kill() error {
return c.Process.Kill()
}
type defaultExecutor struct{}
func (e *defaultExecutor) Command(name string, args ...string) Cmd {
cmd := exec.Command(name, args...)
cmd.SysProcAttr = &syscall.SysProcAttr{
Setsid: true,
}
return &defaultCmd{cmd}
}
func (e *defaultExecutor) CommandContext(ctx context.Context, name string, args ...string) Cmd {
cmd := exec.CommandContext(ctx, name, args...)
cmd.SysProcAttr = &syscall.SysProcAttr{
Setsid: true,
}
return &defaultCmd{cmd}
}
func (e *defaultExecutor) GetExitStatus(err error) (int, bool) {
if exiterr, ok := err.(*exec.ExitError); ok {
ws := exiterr.Sys().(syscall.WaitStatus)
return ws.ExitStatus(), true
} else {
return 0, false
}
}
type remoteExecutor struct{}
func (e *remoteExecutor) Command(name string, args ...string) Cmd {
cmd := client.Command(name, args...)
return cmd
}
func (e *remoteExecutor) CommandContext(ctx context.Context, name string, args ...string) Cmd {
cmd := client.CommandContext(ctx, name, args...)
return cmd
}
func (e *remoteExecutor) GetExitStatus(err error) (int, bool) {
if exiterr, ok := err.(*client.ExitError); ok {
ws := exiterr.Sys().(syscall.WaitStatus)
return ws.ExitStatus(), true
} else {
return 0, false
}
}
+43 -109
View File
@@ -15,11 +15,9 @@
package procutils
import (
"bytes"
"context"
"os/exec"
"io"
"strings"
"syscall"
"time"
"yunion.io/x/log"
@@ -30,140 +28,76 @@ var (
)
type Command struct {
Path string
Args []string
path string
args []string
cmd Cmd
}
func NewCommand(name string, args ...string) *Command {
return &Command{
Path: name,
Args: args,
path: name,
args: args,
cmd: execInstance.Command(name, args...),
}
}
func ParseOutput(output []byte) []string {
lines := make([]string, 0)
for _, line := range strings.Split(string(output), "\n") {
lines = append(lines, strings.TrimSpace(line))
func NewCommandContext(ctx context.Context, name string, args ...string) *Command {
return &Command{
path: name,
args: args,
cmd: execInstance.CommandContext(ctx, name, args...),
}
return lines
}
func Run(name string, args ...string) ([]string, error) {
ret, err := NewCommand(name, args...).Run()
func (c *Command) StdinPipe() (io.WriteCloser, error) {
return c.cmd.StdinPipe()
}
func (c *Command) StdoutPipe() (io.ReadCloser, error) {
return c.cmd.StdoutPipe()
}
func (c *Command) StderrPipe() (io.ReadCloser, error) {
return c.cmd.StderrPipe()
}
func (c *Command) Run() error {
log.Debugf("Exec command: %s %v", c.path, c.args)
err := c.cmd.Run()
if err != nil {
return nil, err
log.Errorf("Execute command %q , error: %v", c, err)
}
return ParseOutput(ret), nil
return err
}
// Doesn't have timeout
func (c *Command) Run() ([]byte, error) {
log.Debugf("Exec command: %s %v", c.Path, c.Args)
output, err := RunCommandWithoutTimeout(c.Path, c.Args...)
func (c *Command) Output() ([]byte, error) {
log.Debugf("Exec command: %s %v", c.path, c.args)
output, err := c.cmd.CombinedOutput()
if err != nil {
log.Errorf("Execute command %q , error: %v , output: %s", c, err, string(output))
}
return output, err
}
// Have default timeout 3 * time.Second
func (c *Command) RunWithTimeout(timeout time.Duration) ([]byte, error) {
if timeout <= 0 {
timeout = Timeout
}
output, err := RunCommandWithTimeout(timeout, c.Path, c.Args...)
if err != nil {
log.Errorf("Execute command %q , error: %v , output: %s", c, err, string(output))
}
return output, err
func (c *Command) Start() error {
return c.cmd.Start()
}
func (c *Command) RunWithContext(ctx context.Context) ([]byte, error) {
output, err := RunCommandWithContext(ctx, c.Path, c.Args...)
if err != nil {
log.Errorf("Execute command %q , error: %v , output: %s", c, err, string(output))
}
return output, err
func (c *Command) Wait() error {
return c.cmd.Wait()
}
func (c *Command) String() string {
ss := []string{c.Path}
ss = append(ss, c.Args...)
ss := []string{c.path}
ss = append(ss, c.args...)
return strings.Join(ss, " ")
}
func RunCommandWithoutTimeout(name string, args ...string) ([]byte, error) {
return RunCommandWithContext(context.Background(), name, args...)
func (c *Command) Kill() error {
return c.cmd.Kill()
}
func RunCommandWithTimeout(timeout time.Duration, name string, args ...string) ([]byte, error) {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
return RunCommandWithContext(ctx, name, args...)
}
func RunCommandWithContext(ctx context.Context, name string, args ...string) ([]byte, error) {
cmd := exec.CommandContext(ctx, name, args...)
cmd.SysProcAttr = &syscall.SysProcAttr{
Setsid: true,
}
var buf bytes.Buffer
cmd.Stdout = &buf
cmd.Stderr = &buf
if err := cmd.Start(); err != nil {
return buf.Bytes(), err
}
if err := cmd.Wait(); err != nil {
return buf.Bytes(), err
}
return buf.Bytes(), nil
}
// https://gist.github.com/kylelemons/1525278
func Pipeline(cmds ...*exec.Cmd) ([]byte, []byte, error) {
// Requires at least one command
if len(cmds) < 1 {
return nil, nil, nil
}
// Collect the output from the command(s)
var output bytes.Buffer
var stderr bytes.Buffer
last := len(cmds) - 1
for i, cmd := range cmds[:last] {
var err error
// Connect each command's stdin to the previous command's stdout
if cmds[i+1].Stdin, err = cmd.StdoutPipe(); err != nil {
return nil, nil, err
}
// Connect each command's stderr to a buffer
cmd.Stderr = &stderr
}
// Connect the output and error for the last command
cmds[last].Stdout, cmds[last].Stderr = &output, &stderr
// Start each command
for _, cmd := range cmds {
if err := cmd.Start(); err != nil {
return output.Bytes(), stderr.Bytes(), err
}
}
// Wait for each command to complete
for _, cmd := range cmds {
if err := cmd.Wait(); err != nil {
return output.Bytes(), stderr.Bytes(), err
}
}
// Return the pipeline output and the collected standard error
return output.Bytes(), stderr.Bytes(), nil
func GetExitStatus(err error) (int, bool) {
return execInstance.GetExitStatus(err)
}
+3 -4
View File
@@ -16,11 +16,11 @@ package qemuimg
import (
"fmt"
"os/exec"
"regexp"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/util/procutils"
"yunion.io/x/onecloud/pkg/util/qemutils"
"yunion.io/x/onecloud/pkg/util/version"
)
@@ -36,10 +36,9 @@ var (
)
func getQemuImgVersion() string {
cmd := exec.Command(qemutils.GetQemuImg(), "--version")
out, err := cmd.CombinedOutput()
out, err := procutils.NewCommand(qemutils.GetQemuImg(), "--version").Output()
if err != nil {
log.Errorf("check qemu-img version fail %s", err)
log.Errorf("check qemu-img version fail %s", out)
return ""
}
matches := qemuImgVersionRegexp.FindStringSubmatch(string(out))
+69 -29
View File
@@ -15,21 +15,22 @@
package qemuimg
import (
"bytes"
"errors"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"strconv"
"strings"
"github.com/pkg/errors"
"yunion.io/x/log"
"yunion.io/x/pkg/utils"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/util/fileutils2"
"yunion.io/x/onecloud/pkg/util/procutils"
"yunion.io/x/onecloud/pkg/util/qemutils"
)
@@ -110,21 +111,52 @@ func (img *SQemuImage) parse() error {
img.ActualSizeBytes = fileInfo.Size()
}
}
cmd := exec.Command(qemutils.GetQemuImg(), "info", img.Path)
cmd := procutils.NewCommand(qemutils.GetQemuImg(), "info", img.Path)
var stdin io.WriteCloser
var err error
if len(img.Password) > 0 {
cmd.Stdin = bytes.NewBuffer([]byte(img.Password))
stdin, err = cmd.StdinPipe()
if err != nil {
return errors.Wrap(err, "cmd stdin pipe")
}
defer stdin.Close()
}
var out bytes.Buffer
var errOut bytes.Buffer
cmd.Stdout = &out
cmd.Stderr = &errOut
err := cmd.Run()
outb, err := cmd.StdoutPipe()
if err != nil {
log.Errorf("qemu-img info %s fail %s: %s", img.Path, err, errOut.String())
return fmt.Errorf("qemu-img info error %s", errOut.String())
return err
}
for {
line, err := out.ReadString('\n')
defer outb.Close()
errb, err := cmd.StderrPipe()
if err != nil {
return err
}
defer errb.Close()
err = cmd.Start()
if len(img.Password) > 0 {
io.WriteString(stdin, img.Password+"\n")
}
out, err := ioutil.ReadAll(outb)
if err != nil {
return err
}
errOut, err := ioutil.ReadAll(errb)
if err != nil {
return err
}
err = cmd.Wait()
if err != nil {
log.Errorf("qemu-img info %s fail %s: %s", img.Path, err, errOut)
return fmt.Errorf("qemu-img info error %s", errOut)
}
lines := strings.Split(string(out), "\n")
for i := 0; i < len(lines); i++ {
line := lines[i]
if len(line) > 0 {
line = strings.TrimSpace(line)
switch {
@@ -159,12 +191,8 @@ func (img *SQemuImage) parse() error {
}
}
if err != nil {
if err == io.EOF {
break
} else {
log.Errorf("read output fail %s", err)
return fmt.Errorf("read output fail %s", err)
}
log.Errorf("read output fail %s", err)
return fmt.Errorf("read output fail %s", err)
}
}
if img.Format == RAW && fileutils2.IsFile(img.Path) {
@@ -206,7 +234,19 @@ func (img *SQemuImage) doConvert(name string, format TImageFormat, options []str
}
cmdline = append(cmdline, img.Path, name)
log.Infof("XXXX qemu-img command: %s", cmdline)
cmd := exec.Command("ionice", cmdline...)
cmd := procutils.NewCommand("ionice", cmdline...)
var stdin io.WriteCloser
var err error
if len(img.Password) > 0 || len(password) > 0 {
stdin, err = cmd.StdinPipe()
if err != nil {
return errors.Wrap(err, "convert stdin")
}
}
err = cmd.Start()
if err != nil {
return errors.Wrap(err, "do convert")
}
if len(img.Password) > 0 || len(password) > 0 {
input := ""
if len(img.Password) > 0 {
@@ -215,9 +255,9 @@ func (img *SQemuImage) doConvert(name string, format TImageFormat, options []str
if len(password) > 0 {
input = fmt.Sprintf("%s%s\r", input, password)
}
cmd.Stdin = bytes.NewBuffer([]byte(input))
io.WriteString(stdin, input+"\n")
}
err := cmd.Run()
err = cmd.Wait()
if err != nil {
log.Errorf("clone fail %s", err)
os.Remove(name)
@@ -255,7 +295,7 @@ func (img *SQemuImage) convert(format TImageFormat, options []string, compact bo
if err != nil {
return err
}
cmd := exec.Command("mv", "-f", tmpPath, img.Path)
cmd := procutils.NewCommand("mv", "-f", tmpPath, img.Path)
err = cmd.Run()
if err != nil {
log.Errorf("convert move temp file error %s", err)
@@ -281,7 +321,7 @@ func (img *SQemuImage) Copy(name string) (*SQemuImage, error) {
if !img.IsValid() {
return nil, fmt.Errorf("self is not valid")
}
cmd := exec.Command("cp", "--sparse=always", img.Path, name)
cmd := procutils.NewCommand("cp", "--sparse=always", img.Path, name)
err := cmd.Run()
if err != nil {
log.Errorf("copy fail %s", err)
@@ -403,7 +443,7 @@ func (img *SQemuImage) create(sizeMB int, format TImageFormat, options []string)
if sizeMB > 0 {
args = append(args, fmt.Sprintf("%dM", sizeMB))
}
cmd := exec.Command("ionice", args...)
cmd := procutils.NewCommand("ionice", args...)
output, err := cmd.Output()
if err != nil {
log.Errorf("%v create error %s %s", args, output, err)
@@ -450,7 +490,7 @@ func (img *SQemuImage) Resize(sizeMB int) error {
if !img.IsValid() {
return fmt.Errorf("self is not valid")
}
cmd := exec.Command("ionice", "-c", strconv.Itoa(int(img.IoLevel)),
cmd := procutils.NewCommand("ionice", "-c", strconv.Itoa(int(img.IoLevel)),
qemutils.GetQemuImg(), "resize", img.Path, fmt.Sprintf("%dM", sizeMB))
err := cmd.Run()
if err != nil {
@@ -470,7 +510,7 @@ func (img *SQemuImage) Rebase(backPath string, force bool) error {
args = append(args, "-u")
}
args = append(args, "-b", backPath, img.Path)
cmd := exec.Command("ionice", args...)
cmd := procutils.NewCommand("ionice", args...)
err := cmd.Run()
if err != nil {
log.Errorf("rebase fail %s", err)
@@ -498,7 +538,7 @@ func (img *SQemuImage) Fallocate() error {
if !img.IsValid() {
return fmt.Errorf("self is not valid")
}
cmd := exec.Command("fallocate", "-l", fmt.Sprintf("%dm", img.GetSizeMB()), img.Path)
cmd := procutils.NewCommand("fallocate", "-l", fmt.Sprintf("%dm", img.GetSizeMB()), img.Path)
return cmd.Run()
}
+2 -3
View File
@@ -22,12 +22,11 @@ import (
)
func setHostname7(name string) error {
_, err := procutils.NewCommand("hostnamectl", "set-hostname", name).Run()
return err
return procutils.NewCommand("hostnamectl", "set-hostname", name).Run()
}
func setHostname6(name string) error {
_, err := procutils.NewCommand("hostname", name).Run()
err := procutils.NewCommand("hostname", name).Run()
if err != nil {
return err
}
+3 -3
View File
@@ -102,7 +102,7 @@ func ModprobeKvmModule(name string, remove, nest bool) bool {
if nest {
params = append(params, "nested=1")
}
if _, err := procutils.NewCommand(params[0], params[1:]...).Run(); err != nil {
if err := procutils.NewCommand(params[0], params[1:]...).Run(); err != nil {
return false
}
return true
@@ -134,7 +134,7 @@ func detectNestSupport() string {
}
func isNestSupport(name string) bool {
output, err := procutils.NewCommand("modinfo", name).Run()
output, err := procutils.NewCommand("modinfo", name).Output()
if err != nil {
log.Errorln(err)
return false
@@ -188,7 +188,7 @@ func GetKernelModuleParameter(name, moduel string) string {
}
func IsKernelModuleLoaded(name string) bool {
output, err := procutils.NewCommand("lsmod").Run()
output, err := procutils.NewCommand("lsmod").Output()
if err != nil {
log.Errorln(err)
return false
+1 -1
View File
@@ -32,7 +32,7 @@ func TarSparseFile(origin, tar string) error {
log.Errorln(err)
return err
}
_, err := procutils.NewCommand("tar", "-Scf", tar, originFile).Run()
err := procutils.NewCommand("tar", "-Scf", tar, originFile).Run()
if err != nil {
log.Errorf("Tar sparse file error: %s", err)
}
+4 -3
View File
@@ -16,11 +16,12 @@ package timeutils2
import (
"fmt"
"os/exec"
"runtime/debug"
"time"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/util/procutils"
)
func AddTimeout(second time.Duration, callback func()) {
@@ -37,9 +38,9 @@ func AddTimeout(second time.Duration, callback func()) {
}()
}
func CommandWithTimeout(timeout int, cmds ...string) *exec.Cmd {
func CommandWithTimeout(timeout int, cmds ...string) *procutils.Command {
if timeout > 0 {
cmds = append([]string{"timeout", "--signal=KILL", fmt.Sprintf("%ds", timeout)}, cmds...)
}
return exec.Command(cmds[0], cmds[1:]...)
return procutils.NewCommand(cmds[0], cmds[1:]...)
}
+12 -21
View File
@@ -19,18 +19,15 @@ import (
"fmt"
"io"
"io/ioutil"
"os/exec"
"path"
"regexp"
"strconv"
"strings"
"syscall"
"time"
"yunion.io/x/log"
"yunion.io/x/pkg/utils"
"yunion.io/x/onecloud/pkg/util/fileutils2"
"yunion.io/x/onecloud/pkg/util/procutils"
"yunion.io/x/onecloud/pkg/util/regutils2"
)
@@ -61,11 +58,7 @@ func NewWinRegTool(spath string) *SWinRegTool {
}
func CheckTool(spath string) bool {
if fileutils2.Exists(spath) && exec.Command(spath, "-h").Run() == nil {
return true
} else {
return false
}
return procutils.NewCommand(spath, "-h").Run() == nil
}
type SWinRegTool struct {
@@ -103,7 +96,7 @@ func (w *SWinRegTool) CheckPath() bool {
}
func (w *SWinRegTool) GetUsers() map[string]bool {
output, err := procutils.NewCommand(GetChntpwPath(), "-l", w.SamPath).Run()
output, err := procutils.NewCommand(GetChntpwPath(), "-l", w.SamPath).Output()
if err != nil {
log.Errorln(err)
return nil
@@ -126,7 +119,7 @@ func (w *SWinRegTool) GetUsers() map[string]bool {
}
func (w *SWinRegTool) samChange(user string, seq ...string) error {
proc := exec.Command(GetChntpwPath(), "-u", user, w.SamPath, w.SystemPath, w.SecurityPath)
proc := procutils.NewCommand(GetChntpwPath(), "-u", user, w.SamPath, w.SystemPath, w.SecurityPath)
stdin, err := proc.StdinPipe()
if err != nil {
return err
@@ -170,13 +163,12 @@ func (w *SWinRegTool) samChange(user string, seq ...string) error {
}()
select {
case <-time.After(time.Millisecond * 100):
proc.Process.Kill()
proc.Kill()
return fmt.Errorf("Failed to change SAM password, not exit cleanly")
case err := <-done:
if err != nil {
if exiterr, ok := err.(*exec.ExitError); ok {
ws := exiterr.Sys().(syscall.WaitStatus)
if ws.ExitStatus() == 2 {
if exitStatus, ok := procutils.GetExitStatus(err); ok {
if exitStatus == 2 {
return nil
}
}
@@ -225,7 +217,7 @@ func (w *SWinRegTool) GetRegFile(regPath string) (string, []string) {
}
func (w *SWinRegTool) showRegistry(spath string, keySeg []string, verb string) ([]string, error) {
proc := exec.Command(GetChntpwPath(), spath)
proc := procutils.NewCommand(GetChntpwPath(), spath)
stdin, err := proc.StdinPipe()
if err != nil {
return nil, err
@@ -262,7 +254,7 @@ func (w *SWinRegTool) showRegistry(spath string, keySeg []string, verb string) (
}()
select {
case <-time.After(time.Millisecond * 100):
proc.Process.Kill()
proc.Kill()
case err := <-done:
if err != nil {
return nil, err
@@ -319,7 +311,7 @@ func (w *SWinRegTool) listRegistry(spath string, keySeg []string) ([]string, []s
}
func (w *SWinRegTool) cmdRegistry(spath string, ops []string, retcode int) bool {
proc := exec.Command(GetChntpwPath(), "-e", spath)
proc := procutils.NewCommand(GetChntpwPath(), "-e", spath)
stdin, err := proc.StdinPipe()
if err != nil {
log.Errorln(err)
@@ -369,12 +361,11 @@ func (w *SWinRegTool) cmdRegistry(spath string, ops []string, retcode int) bool
}()
select {
case <-time.After(time.Millisecond * 100):
proc.Process.Kill()
proc.Kill()
case err := <-done:
if err != nil {
if exiterr, ok := err.(*exec.ExitError); ok {
ws := exiterr.Sys().(syscall.WaitStatus)
if ws.ExitStatus() == retcode {
if exitStatus, ok := procutils.GetExitStatus(err); ok {
if exitStatus == retcode {
return true
}
}
+4
View File
@@ -798,6 +798,10 @@ k8s.io/kubernetes/pkg/scheduler/api
k8s.io/kubernetes/pkg/scheduler/api/v1
# sigs.k8s.io/yaml v1.1.0
sigs.k8s.io/yaml
# yunion.io/x/executor v0.0.0-20191202093616-92e2e6119257
yunion.io/x/executor/apis
yunion.io/x/executor/client
yunion.io/x/executor/server
# yunion.io/x/jsonutils v0.0.0-20191005115334-bb1c187fc0e7
yunion.io/x/jsonutils
# yunion.io/x/log v0.0.0-20190629062853-9f6483a7103d
+970
View File
@@ -0,0 +1,970 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: executor.proto
package apis
import (
context "context"
fmt "fmt"
proto "github.com/golang/protobuf/proto"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type Command struct {
Path []byte `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`
Args [][]byte `protobuf:"bytes,2,rep,name=args,proto3" json:"args,omitempty"`
Env [][]byte `protobuf:"bytes,3,rep,name=env,proto3" json:"env,omitempty"`
Dir []byte `protobuf:"bytes,4,opt,name=dir,proto3" json:"dir,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Command) Reset() { *m = Command{} }
func (m *Command) String() string { return proto.CompactTextString(m) }
func (*Command) ProtoMessage() {}
func (*Command) Descriptor() ([]byte, []int) {
return fileDescriptor_12d1cdcda51e000f, []int{0}
}
func (m *Command) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Command.Unmarshal(m, b)
}
func (m *Command) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Command.Marshal(b, m, deterministic)
}
func (m *Command) XXX_Merge(src proto.Message) {
xxx_messageInfo_Command.Merge(m, src)
}
func (m *Command) XXX_Size() int {
return xxx_messageInfo_Command.Size(m)
}
func (m *Command) XXX_DiscardUnknown() {
xxx_messageInfo_Command.DiscardUnknown(m)
}
var xxx_messageInfo_Command proto.InternalMessageInfo
func (m *Command) GetPath() []byte {
if m != nil {
return m.Path
}
return nil
}
func (m *Command) GetArgs() [][]byte {
if m != nil {
return m.Args
}
return nil
}
func (m *Command) GetEnv() [][]byte {
if m != nil {
return m.Env
}
return nil
}
func (m *Command) GetDir() []byte {
if m != nil {
return m.Dir
}
return nil
}
type Input struct {
Sn uint32 `protobuf:"varint,1,opt,name=sn,proto3" json:"sn,omitempty"`
Input []byte `protobuf:"bytes,2,opt,name=input,proto3" json:"input,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Input) Reset() { *m = Input{} }
func (m *Input) String() string { return proto.CompactTextString(m) }
func (*Input) ProtoMessage() {}
func (*Input) Descriptor() ([]byte, []int) {
return fileDescriptor_12d1cdcda51e000f, []int{1}
}
func (m *Input) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Input.Unmarshal(m, b)
}
func (m *Input) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Input.Marshal(b, m, deterministic)
}
func (m *Input) XXX_Merge(src proto.Message) {
xxx_messageInfo_Input.Merge(m, src)
}
func (m *Input) XXX_Size() int {
return xxx_messageInfo_Input.Size(m)
}
func (m *Input) XXX_DiscardUnknown() {
xxx_messageInfo_Input.DiscardUnknown(m)
}
var xxx_messageInfo_Input proto.InternalMessageInfo
func (m *Input) GetSn() uint32 {
if m != nil {
return m.Sn
}
return 0
}
func (m *Input) GetInput() []byte {
if m != nil {
return m.Input
}
return nil
}
type Stdout struct {
Stdout []byte `protobuf:"bytes,1,opt,name=stdout,proto3" json:"stdout,omitempty"`
Closed bool `protobuf:"varint,2,opt,name=closed,proto3" json:"closed,omitempty"`
RuntimeError []byte `protobuf:"bytes,3,opt,name=runtime_error,json=runtimeError,proto3" json:"runtime_error,omitempty"`
Start bool `protobuf:"varint,4,opt,name=start,proto3" json:"start,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Stdout) Reset() { *m = Stdout{} }
func (m *Stdout) String() string { return proto.CompactTextString(m) }
func (*Stdout) ProtoMessage() {}
func (*Stdout) Descriptor() ([]byte, []int) {
return fileDescriptor_12d1cdcda51e000f, []int{2}
}
func (m *Stdout) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Stdout.Unmarshal(m, b)
}
func (m *Stdout) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Stdout.Marshal(b, m, deterministic)
}
func (m *Stdout) XXX_Merge(src proto.Message) {
xxx_messageInfo_Stdout.Merge(m, src)
}
func (m *Stdout) XXX_Size() int {
return xxx_messageInfo_Stdout.Size(m)
}
func (m *Stdout) XXX_DiscardUnknown() {
xxx_messageInfo_Stdout.DiscardUnknown(m)
}
var xxx_messageInfo_Stdout proto.InternalMessageInfo
func (m *Stdout) GetStdout() []byte {
if m != nil {
return m.Stdout
}
return nil
}
func (m *Stdout) GetClosed() bool {
if m != nil {
return m.Closed
}
return false
}
func (m *Stdout) GetRuntimeError() []byte {
if m != nil {
return m.RuntimeError
}
return nil
}
func (m *Stdout) GetStart() bool {
if m != nil {
return m.Start
}
return false
}
type Stderr struct {
Stderr []byte `protobuf:"bytes,1,opt,name=stderr,proto3" json:"stderr,omitempty"`
Closed bool `protobuf:"varint,2,opt,name=closed,proto3" json:"closed,omitempty"`
RuntimeError []byte `protobuf:"bytes,3,opt,name=runtime_error,json=runtimeError,proto3" json:"runtime_error,omitempty"`
Start bool `protobuf:"varint,4,opt,name=start,proto3" json:"start,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Stderr) Reset() { *m = Stderr{} }
func (m *Stderr) String() string { return proto.CompactTextString(m) }
func (*Stderr) ProtoMessage() {}
func (*Stderr) Descriptor() ([]byte, []int) {
return fileDescriptor_12d1cdcda51e000f, []int{3}
}
func (m *Stderr) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Stderr.Unmarshal(m, b)
}
func (m *Stderr) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Stderr.Marshal(b, m, deterministic)
}
func (m *Stderr) XXX_Merge(src proto.Message) {
xxx_messageInfo_Stderr.Merge(m, src)
}
func (m *Stderr) XXX_Size() int {
return xxx_messageInfo_Stderr.Size(m)
}
func (m *Stderr) XXX_DiscardUnknown() {
xxx_messageInfo_Stderr.DiscardUnknown(m)
}
var xxx_messageInfo_Stderr proto.InternalMessageInfo
func (m *Stderr) GetStderr() []byte {
if m != nil {
return m.Stderr
}
return nil
}
func (m *Stderr) GetClosed() bool {
if m != nil {
return m.Closed
}
return false
}
func (m *Stderr) GetRuntimeError() []byte {
if m != nil {
return m.RuntimeError
}
return nil
}
func (m *Stderr) GetStart() bool {
if m != nil {
return m.Start
}
return false
}
type StartResponse struct {
Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
Error []byte `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *StartResponse) Reset() { *m = StartResponse{} }
func (m *StartResponse) String() string { return proto.CompactTextString(m) }
func (*StartResponse) ProtoMessage() {}
func (*StartResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_12d1cdcda51e000f, []int{4}
}
func (m *StartResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StartResponse.Unmarshal(m, b)
}
func (m *StartResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_StartResponse.Marshal(b, m, deterministic)
}
func (m *StartResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_StartResponse.Merge(m, src)
}
func (m *StartResponse) XXX_Size() int {
return xxx_messageInfo_StartResponse.Size(m)
}
func (m *StartResponse) XXX_DiscardUnknown() {
xxx_messageInfo_StartResponse.DiscardUnknown(m)
}
var xxx_messageInfo_StartResponse proto.InternalMessageInfo
func (m *StartResponse) GetSuccess() bool {
if m != nil {
return m.Success
}
return false
}
func (m *StartResponse) GetError() []byte {
if m != nil {
return m.Error
}
return nil
}
type WaitCommand struct {
Sn uint32 `protobuf:"varint,1,opt,name=sn,proto3" json:"sn,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *WaitCommand) Reset() { *m = WaitCommand{} }
func (m *WaitCommand) String() string { return proto.CompactTextString(m) }
func (*WaitCommand) ProtoMessage() {}
func (*WaitCommand) Descriptor() ([]byte, []int) {
return fileDescriptor_12d1cdcda51e000f, []int{5}
}
func (m *WaitCommand) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_WaitCommand.Unmarshal(m, b)
}
func (m *WaitCommand) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_WaitCommand.Marshal(b, m, deterministic)
}
func (m *WaitCommand) XXX_Merge(src proto.Message) {
xxx_messageInfo_WaitCommand.Merge(m, src)
}
func (m *WaitCommand) XXX_Size() int {
return xxx_messageInfo_WaitCommand.Size(m)
}
func (m *WaitCommand) XXX_DiscardUnknown() {
xxx_messageInfo_WaitCommand.DiscardUnknown(m)
}
var xxx_messageInfo_WaitCommand proto.InternalMessageInfo
func (m *WaitCommand) GetSn() uint32 {
if m != nil {
return m.Sn
}
return 0
}
type WaitResponse struct {
ExitStatus uint32 `protobuf:"varint,1,opt,name=exit_status,json=exitStatus,proto3" json:"exit_status,omitempty"`
ErrContent []byte `protobuf:"bytes,2,opt,name=err_content,json=errContent,proto3" json:"err_content,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *WaitResponse) Reset() { *m = WaitResponse{} }
func (m *WaitResponse) String() string { return proto.CompactTextString(m) }
func (*WaitResponse) ProtoMessage() {}
func (*WaitResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_12d1cdcda51e000f, []int{6}
}
func (m *WaitResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_WaitResponse.Unmarshal(m, b)
}
func (m *WaitResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_WaitResponse.Marshal(b, m, deterministic)
}
func (m *WaitResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_WaitResponse.Merge(m, src)
}
func (m *WaitResponse) XXX_Size() int {
return xxx_messageInfo_WaitResponse.Size(m)
}
func (m *WaitResponse) XXX_DiscardUnknown() {
xxx_messageInfo_WaitResponse.DiscardUnknown(m)
}
var xxx_messageInfo_WaitResponse proto.InternalMessageInfo
func (m *WaitResponse) GetExitStatus() uint32 {
if m != nil {
return m.ExitStatus
}
return 0
}
func (m *WaitResponse) GetErrContent() []byte {
if m != nil {
return m.ErrContent
}
return nil
}
type Sn struct {
Sn uint32 `protobuf:"varint,1,opt,name=sn,proto3" json:"sn,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Sn) Reset() { *m = Sn{} }
func (m *Sn) String() string { return proto.CompactTextString(m) }
func (*Sn) ProtoMessage() {}
func (*Sn) Descriptor() ([]byte, []int) {
return fileDescriptor_12d1cdcda51e000f, []int{7}
}
func (m *Sn) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Sn.Unmarshal(m, b)
}
func (m *Sn) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Sn.Marshal(b, m, deterministic)
}
func (m *Sn) XXX_Merge(src proto.Message) {
xxx_messageInfo_Sn.Merge(m, src)
}
func (m *Sn) XXX_Size() int {
return xxx_messageInfo_Sn.Size(m)
}
func (m *Sn) XXX_DiscardUnknown() {
xxx_messageInfo_Sn.DiscardUnknown(m)
}
var xxx_messageInfo_Sn proto.InternalMessageInfo
func (m *Sn) GetSn() uint32 {
if m != nil {
return m.Sn
}
return 0
}
type StartInput struct {
Sn uint32 `protobuf:"varint,1,opt,name=sn,proto3" json:"sn,omitempty"`
HasStdin bool `protobuf:"varint,2,opt,name=has_stdin,json=hasStdin,proto3" json:"has_stdin,omitempty"`
HasStdout bool `protobuf:"varint,3,opt,name=has_stdout,json=hasStdout,proto3" json:"has_stdout,omitempty"`
HasStderr bool `protobuf:"varint,4,opt,name=has_stderr,json=hasStderr,proto3" json:"has_stderr,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *StartInput) Reset() { *m = StartInput{} }
func (m *StartInput) String() string { return proto.CompactTextString(m) }
func (*StartInput) ProtoMessage() {}
func (*StartInput) Descriptor() ([]byte, []int) {
return fileDescriptor_12d1cdcda51e000f, []int{8}
}
func (m *StartInput) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StartInput.Unmarshal(m, b)
}
func (m *StartInput) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_StartInput.Marshal(b, m, deterministic)
}
func (m *StartInput) XXX_Merge(src proto.Message) {
xxx_messageInfo_StartInput.Merge(m, src)
}
func (m *StartInput) XXX_Size() int {
return xxx_messageInfo_StartInput.Size(m)
}
func (m *StartInput) XXX_DiscardUnknown() {
xxx_messageInfo_StartInput.DiscardUnknown(m)
}
var xxx_messageInfo_StartInput proto.InternalMessageInfo
func (m *StartInput) GetSn() uint32 {
if m != nil {
return m.Sn
}
return 0
}
func (m *StartInput) GetHasStdin() bool {
if m != nil {
return m.HasStdin
}
return false
}
func (m *StartInput) GetHasStdout() bool {
if m != nil {
return m.HasStdout
}
return false
}
func (m *StartInput) GetHasStderr() bool {
if m != nil {
return m.HasStderr
}
return false
}
type Error struct {
Error []byte `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Error) Reset() { *m = Error{} }
func (m *Error) String() string { return proto.CompactTextString(m) }
func (*Error) ProtoMessage() {}
func (*Error) Descriptor() ([]byte, []int) {
return fileDescriptor_12d1cdcda51e000f, []int{9}
}
func (m *Error) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Error.Unmarshal(m, b)
}
func (m *Error) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Error.Marshal(b, m, deterministic)
}
func (m *Error) XXX_Merge(src proto.Message) {
xxx_messageInfo_Error.Merge(m, src)
}
func (m *Error) XXX_Size() int {
return xxx_messageInfo_Error.Size(m)
}
func (m *Error) XXX_DiscardUnknown() {
xxx_messageInfo_Error.DiscardUnknown(m)
}
var xxx_messageInfo_Error proto.InternalMessageInfo
func (m *Error) GetError() []byte {
if m != nil {
return m.Error
}
return nil
}
func init() {
proto.RegisterType((*Command)(nil), "apis.Command")
proto.RegisterType((*Input)(nil), "apis.Input")
proto.RegisterType((*Stdout)(nil), "apis.Stdout")
proto.RegisterType((*Stderr)(nil), "apis.Stderr")
proto.RegisterType((*StartResponse)(nil), "apis.StartResponse")
proto.RegisterType((*WaitCommand)(nil), "apis.WaitCommand")
proto.RegisterType((*WaitResponse)(nil), "apis.WaitResponse")
proto.RegisterType((*Sn)(nil), "apis.Sn")
proto.RegisterType((*StartInput)(nil), "apis.StartInput")
proto.RegisterType((*Error)(nil), "apis.Error")
}
func init() { proto.RegisterFile("executor.proto", fileDescriptor_12d1cdcda51e000f) }
var fileDescriptor_12d1cdcda51e000f = []byte{
// 485 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0x4f, 0x6b, 0xdb, 0x4e,
0x10, 0x45, 0x7f, 0xec, 0xc8, 0x23, 0x3b, 0x84, 0xfd, 0x85, 0x1f, 0xc2, 0xc5, 0x34, 0xa8, 0xa5,
0xc9, 0xa5, 0x26, 0xb4, 0x1f, 0xa0, 0x87, 0x90, 0x42, 0xe9, 0xa5, 0x48, 0x94, 0x1e, 0x8d, 0x2a,
0x2d, 0xb5, 0xc0, 0x5e, 0x89, 0x99, 0x55, 0x9b, 0xcf, 0xd3, 0x4f, 0x5a, 0x66, 0x76, 0xe5, 0x2a,
0x6d, 0x8e, 0xbd, 0xcd, 0x7b, 0x6f, 0x76, 0x66, 0xf7, 0x3d, 0x21, 0x38, 0xd7, 0x0f, 0xba, 0x1e,
0x6c, 0x87, 0xdb, 0x1e, 0x3b, 0xdb, 0xa9, 0xb8, 0xea, 0x5b, 0xca, 0x3f, 0xc3, 0xd9, 0x5d, 0x77,
0x3c, 0x56, 0xa6, 0x51, 0x0a, 0xe2, 0xbe, 0xb2, 0xfb, 0x2c, 0xb8, 0x0a, 0x6e, 0x96, 0x85, 0xd4,
0xcc, 0x55, 0xf8, 0x8d, 0xb2, 0xf0, 0x2a, 0x62, 0x8e, 0x6b, 0x75, 0x01, 0x91, 0x36, 0xdf, 0xb3,
0x48, 0x28, 0x2e, 0x99, 0x69, 0x5a, 0xcc, 0x62, 0x39, 0xc8, 0x65, 0xfe, 0x1a, 0x66, 0x1f, 0x4c,
0x3f, 0x58, 0x75, 0x0e, 0x21, 0x19, 0x19, 0xb9, 0x2a, 0x42, 0x32, 0xea, 0x12, 0x66, 0x2d, 0x0b,
0x59, 0x28, 0xcd, 0x0e, 0xe4, 0x04, 0xf3, 0xd2, 0x36, 0xdd, 0x60, 0xd5, 0xff, 0x30, 0x27, 0xa9,
0xfc, 0x35, 0x3c, 0x62, 0xbe, 0x3e, 0x74, 0xa4, 0x1b, 0x39, 0x98, 0x14, 0x1e, 0xa9, 0x17, 0xb0,
0xc2, 0xc1, 0xd8, 0xf6, 0xa8, 0x77, 0x1a, 0xb1, 0xc3, 0x2c, 0x92, 0x63, 0x4b, 0x4f, 0xde, 0x33,
0xc7, 0x4b, 0xc9, 0x56, 0x68, 0xe5, 0x86, 0x49, 0xe1, 0x80, 0x5f, 0xaa, 0x11, 0xfd, 0x52, 0x8d,
0x38, 0x59, 0xea, 0xf9, 0x7f, 0xbd, 0xf4, 0x1d, 0xac, 0x4a, 0x2e, 0x0a, 0x4d, 0x7d, 0x67, 0x48,
0xab, 0x0c, 0xce, 0x68, 0xa8, 0x6b, 0x4d, 0x24, 0xcb, 0x93, 0x62, 0x84, 0x3c, 0xc0, 0x4d, 0xf7,
0x56, 0x09, 0xc8, 0x37, 0x90, 0x7e, 0xa9, 0x5a, 0x3b, 0x86, 0xf6, 0x87, 0xbf, 0xf9, 0x27, 0x58,
0xb2, 0x7c, 0x1a, 0xff, 0x1c, 0x52, 0xfd, 0xd0, 0xda, 0x1d, 0xd9, 0xca, 0x0e, 0xe4, 0x1b, 0x81,
0xa9, 0x52, 0x18, 0x69, 0x40, 0xdc, 0xd5, 0x9d, 0xb1, 0xda, 0x8c, 0xb1, 0x80, 0x46, 0xbc, 0x73,
0x4c, 0x7e, 0x09, 0x61, 0x69, 0xfe, 0xda, 0xf3, 0x03, 0x40, 0xde, 0xf1, 0x74, 0xca, 0xcf, 0x60,
0xb1, 0xaf, 0x68, 0x47, 0xb6, 0x69, 0x8d, 0xf7, 0x2e, 0xd9, 0x57, 0x54, 0x32, 0x56, 0x1b, 0x00,
0x2f, 0x72, 0xcc, 0x91, 0xa8, 0x0b, 0xa7, 0x72, 0xd2, 0xbf, 0x65, 0x0e, 0x24, 0x9e, 0xca, 0x1a,
0xf9, 0xfd, 0xb3, 0x93, 0xbf, 0xce, 0x9e, 0x60, 0x62, 0xcf, 0x9b, 0x9f, 0x21, 0x24, 0xf7, 0xfe,
0x43, 0x57, 0xd7, 0xb0, 0x28, 0xb5, 0x69, 0xdc, 0x1d, 0xd3, 0x2d, 0x7f, 0xf0, 0x5b, 0x01, 0x6b,
0x0f, 0x64, 0xd2, 0x4d, 0xa0, 0xae, 0x21, 0x7d, 0xaf, 0x6d, 0xbd, 0xf7, 0x57, 0x48, 0x9c, 0x5a,
0x9a, 0xf5, 0xd2, 0x57, 0xc2, 0xdf, 0x3e, 0x6a, 0xe4, 0x0f, 0xe4, 0xa9, 0x46, 0x8d, 0x78, 0x1b,
0xa8, 0x2d, 0xcc, 0xc4, 0x1f, 0x75, 0x31, 0x0a, 0xa3, 0x59, 0xeb, 0xff, 0x26, 0xcc, 0x29, 0xa7,
0x97, 0x10, 0x73, 0x6e, 0x93, 0x89, 0xca, 0x55, 0x8f, 0xd2, 0x7c, 0x05, 0x29, 0x3f, 0x6e, 0x0c,
0x7f, 0xe5, 0x5a, 0x3c, 0x5c, 0x9f, 0xce, 0xaa, 0x0d, 0xc4, 0x1f, 0xdb, 0xc3, 0x61, 0x32, 0x6d,
0xfa, 0xe0, 0xaf, 0x73, 0xf9, 0x03, 0xbc, 0xfd, 0x15, 0x00, 0x00, 0xff, 0xff, 0x60, 0x42, 0x00,
0x66, 0x13, 0x04, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4
// ExecutorClient is the client API for Executor service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type ExecutorClient interface {
SendInput(ctx context.Context, opts ...grpc.CallOption) (Executor_SendInputClient, error)
FetchStdout(ctx context.Context, in *Sn, opts ...grpc.CallOption) (Executor_FetchStdoutClient, error)
FetchStderr(ctx context.Context, in *Sn, opts ...grpc.CallOption) (Executor_FetchStderrClient, error)
Start(ctx context.Context, in *StartInput, opts ...grpc.CallOption) (*StartResponse, error)
Wait(ctx context.Context, in *Sn, opts ...grpc.CallOption) (*WaitResponse, error)
ExecCommand(ctx context.Context, in *Command, opts ...grpc.CallOption) (*Sn, error)
Kill(ctx context.Context, in *Sn, opts ...grpc.CallOption) (*Error, error)
}
type executorClient struct {
cc *grpc.ClientConn
}
func NewExecutorClient(cc *grpc.ClientConn) ExecutorClient {
return &executorClient{cc}
}
func (c *executorClient) SendInput(ctx context.Context, opts ...grpc.CallOption) (Executor_SendInputClient, error) {
stream, err := c.cc.NewStream(ctx, &_Executor_serviceDesc.Streams[0], "/apis.Executor/SendInput", opts...)
if err != nil {
return nil, err
}
x := &executorSendInputClient{stream}
return x, nil
}
type Executor_SendInputClient interface {
Send(*Input) error
CloseAndRecv() (*Error, error)
grpc.ClientStream
}
type executorSendInputClient struct {
grpc.ClientStream
}
func (x *executorSendInputClient) Send(m *Input) error {
return x.ClientStream.SendMsg(m)
}
func (x *executorSendInputClient) CloseAndRecv() (*Error, error) {
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
m := new(Error)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *executorClient) FetchStdout(ctx context.Context, in *Sn, opts ...grpc.CallOption) (Executor_FetchStdoutClient, error) {
stream, err := c.cc.NewStream(ctx, &_Executor_serviceDesc.Streams[1], "/apis.Executor/FetchStdout", opts...)
if err != nil {
return nil, err
}
x := &executorFetchStdoutClient{stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
}
type Executor_FetchStdoutClient interface {
Recv() (*Stdout, error)
grpc.ClientStream
}
type executorFetchStdoutClient struct {
grpc.ClientStream
}
func (x *executorFetchStdoutClient) Recv() (*Stdout, error) {
m := new(Stdout)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *executorClient) FetchStderr(ctx context.Context, in *Sn, opts ...grpc.CallOption) (Executor_FetchStderrClient, error) {
stream, err := c.cc.NewStream(ctx, &_Executor_serviceDesc.Streams[2], "/apis.Executor/FetchStderr", opts...)
if err != nil {
return nil, err
}
x := &executorFetchStderrClient{stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
}
type Executor_FetchStderrClient interface {
Recv() (*Stderr, error)
grpc.ClientStream
}
type executorFetchStderrClient struct {
grpc.ClientStream
}
func (x *executorFetchStderrClient) Recv() (*Stderr, error) {
m := new(Stderr)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *executorClient) Start(ctx context.Context, in *StartInput, opts ...grpc.CallOption) (*StartResponse, error) {
out := new(StartResponse)
err := c.cc.Invoke(ctx, "/apis.Executor/Start", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *executorClient) Wait(ctx context.Context, in *Sn, opts ...grpc.CallOption) (*WaitResponse, error) {
out := new(WaitResponse)
err := c.cc.Invoke(ctx, "/apis.Executor/Wait", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *executorClient) ExecCommand(ctx context.Context, in *Command, opts ...grpc.CallOption) (*Sn, error) {
out := new(Sn)
err := c.cc.Invoke(ctx, "/apis.Executor/ExecCommand", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *executorClient) Kill(ctx context.Context, in *Sn, opts ...grpc.CallOption) (*Error, error) {
out := new(Error)
err := c.cc.Invoke(ctx, "/apis.Executor/Kill", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// ExecutorServer is the server API for Executor service.
type ExecutorServer interface {
SendInput(Executor_SendInputServer) error
FetchStdout(*Sn, Executor_FetchStdoutServer) error
FetchStderr(*Sn, Executor_FetchStderrServer) error
Start(context.Context, *StartInput) (*StartResponse, error)
Wait(context.Context, *Sn) (*WaitResponse, error)
ExecCommand(context.Context, *Command) (*Sn, error)
Kill(context.Context, *Sn) (*Error, error)
}
// UnimplementedExecutorServer can be embedded to have forward compatible implementations.
type UnimplementedExecutorServer struct {
}
func (*UnimplementedExecutorServer) SendInput(srv Executor_SendInputServer) error {
return status.Errorf(codes.Unimplemented, "method SendInput not implemented")
}
func (*UnimplementedExecutorServer) FetchStdout(req *Sn, srv Executor_FetchStdoutServer) error {
return status.Errorf(codes.Unimplemented, "method FetchStdout not implemented")
}
func (*UnimplementedExecutorServer) FetchStderr(req *Sn, srv Executor_FetchStderrServer) error {
return status.Errorf(codes.Unimplemented, "method FetchStderr not implemented")
}
func (*UnimplementedExecutorServer) Start(ctx context.Context, req *StartInput) (*StartResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Start not implemented")
}
func (*UnimplementedExecutorServer) Wait(ctx context.Context, req *Sn) (*WaitResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Wait not implemented")
}
func (*UnimplementedExecutorServer) ExecCommand(ctx context.Context, req *Command) (*Sn, error) {
return nil, status.Errorf(codes.Unimplemented, "method ExecCommand not implemented")
}
func (*UnimplementedExecutorServer) Kill(ctx context.Context, req *Sn) (*Error, error) {
return nil, status.Errorf(codes.Unimplemented, "method Kill not implemented")
}
func RegisterExecutorServer(s *grpc.Server, srv ExecutorServer) {
s.RegisterService(&_Executor_serviceDesc, srv)
}
func _Executor_SendInput_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(ExecutorServer).SendInput(&executorSendInputServer{stream})
}
type Executor_SendInputServer interface {
SendAndClose(*Error) error
Recv() (*Input, error)
grpc.ServerStream
}
type executorSendInputServer struct {
grpc.ServerStream
}
func (x *executorSendInputServer) SendAndClose(m *Error) error {
return x.ServerStream.SendMsg(m)
}
func (x *executorSendInputServer) Recv() (*Input, error) {
m := new(Input)
if err := x.ServerStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func _Executor_FetchStdout_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(Sn)
if err := stream.RecvMsg(m); err != nil {
return err
}
return srv.(ExecutorServer).FetchStdout(m, &executorFetchStdoutServer{stream})
}
type Executor_FetchStdoutServer interface {
Send(*Stdout) error
grpc.ServerStream
}
type executorFetchStdoutServer struct {
grpc.ServerStream
}
func (x *executorFetchStdoutServer) Send(m *Stdout) error {
return x.ServerStream.SendMsg(m)
}
func _Executor_FetchStderr_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(Sn)
if err := stream.RecvMsg(m); err != nil {
return err
}
return srv.(ExecutorServer).FetchStderr(m, &executorFetchStderrServer{stream})
}
type Executor_FetchStderrServer interface {
Send(*Stderr) error
grpc.ServerStream
}
type executorFetchStderrServer struct {
grpc.ServerStream
}
func (x *executorFetchStderrServer) Send(m *Stderr) error {
return x.ServerStream.SendMsg(m)
}
func _Executor_Start_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(StartInput)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ExecutorServer).Start(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/apis.Executor/Start",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ExecutorServer).Start(ctx, req.(*StartInput))
}
return interceptor(ctx, in, info, handler)
}
func _Executor_Wait_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Sn)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ExecutorServer).Wait(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/apis.Executor/Wait",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ExecutorServer).Wait(ctx, req.(*Sn))
}
return interceptor(ctx, in, info, handler)
}
func _Executor_ExecCommand_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Command)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ExecutorServer).ExecCommand(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/apis.Executor/ExecCommand",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ExecutorServer).ExecCommand(ctx, req.(*Command))
}
return interceptor(ctx, in, info, handler)
}
func _Executor_Kill_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Sn)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ExecutorServer).Kill(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/apis.Executor/Kill",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ExecutorServer).Kill(ctx, req.(*Sn))
}
return interceptor(ctx, in, info, handler)
}
var _Executor_serviceDesc = grpc.ServiceDesc{
ServiceName: "apis.Executor",
HandlerType: (*ExecutorServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Start",
Handler: _Executor_Start_Handler,
},
{
MethodName: "Wait",
Handler: _Executor_Wait_Handler,
},
{
MethodName: "ExecCommand",
Handler: _Executor_ExecCommand_Handler,
},
{
MethodName: "Kill",
Handler: _Executor_Kill_Handler,
},
},
Streams: []grpc.StreamDesc{
{
StreamName: "SendInput",
Handler: _Executor_SendInput_Handler,
ClientStreams: true,
},
{
StreamName: "FetchStdout",
Handler: _Executor_FetchStdout_Handler,
ServerStreams: true,
},
{
StreamName: "FetchStderr",
Handler: _Executor_FetchStderr_Handler,
ServerStreams: true,
},
},
Metadata: "executor.proto",
}
+68
View File
@@ -0,0 +1,68 @@
syntax = "proto3";
package apis;
message Command {
bytes path = 1;
repeated bytes args = 2;
repeated bytes env = 3;
bytes dir = 4;
}
message Input {
uint32 sn = 1;
bytes input = 2;
}
message Stdout {
bytes stdout = 1;
bool closed = 2;
bytes runtime_error = 3;
bool start = 4;
}
message Stderr {
bytes stderr = 1;
bool closed = 2;
bytes runtime_error = 3;
bool start = 4;
}
message StartResponse {
bool success = 1;
bytes error = 2;
}
message WaitCommand {
uint32 sn = 1;
}
message WaitResponse {
uint32 exit_status = 1;
bytes err_content = 2;
}
message Sn {
uint32 sn = 1;
}
message StartInput {
uint32 sn = 1;
bool has_stdin = 2;
bool has_stdout = 3;
bool has_stderr = 4;
}
message Error {
bytes error = 1;
}
service Executor {
rpc SendInput(stream Input) returns (Error);
rpc FetchStdout(Sn) returns (stream Stdout);
rpc FetchStderr(Sn) returns (stream Stderr);
rpc Start(StartInput) returns (StartResponse);
rpc Wait(Sn) returns (WaitResponse);
rpc ExecCommand(Command) returns (Sn);
rpc Kill(Sn) returns (Error);
}
+714
View File
@@ -0,0 +1,714 @@
package client
import (
"bytes"
"context"
"io"
"net"
"os"
"sync"
"syscall"
"time"
"github.com/pkg/errors"
"google.golang.org/grpc"
"yunion.io/x/executor/apis"
)
var exec *Executor
type Executor struct {
socketPath string
}
func Init(socketPath string) {
exec = &Executor{socketPath}
}
func Command(path string, args ...string) *Cmd {
if exec == nil {
panic("executor not init ???")
}
return &Cmd{
Executor: exec,
Path: path,
Args: args,
wg: new(sync.WaitGroup),
stdoutCh: make(chan struct{}),
stderrCh: make(chan struct{}),
}
}
func CommandContext(ctx context.Context, path string, args ...string) *Cmd {
if exec == nil {
panic("executor not init ???")
}
return &Cmd{
Executor: exec,
Path: path,
Args: args,
wg: new(sync.WaitGroup),
stdoutCh: make(chan struct{}),
stderrCh: make(chan struct{}),
ctx: ctx,
}
}
type Cmd struct {
*Executor
ctx context.Context
Path string
Args []string
Env []string
Dir string
conn *grpc.ClientConn
client apis.ExecutorClient
sn *apis.Sn
Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
closeAfterWait []io.Closer
closeAfterAfter []io.Closer
goroutine []func() error
errch chan error
waitDone chan struct{}
stdoutCh chan struct{}
stderrCh chan struct{}
fetchError chan error
streamStdin error
streamStdout error
streamStderr error
wg *sync.WaitGroup
combinedOutput chan struct{}
}
func grcpDialWithUnixSocket(ctx context.Context, socketPath string) (*grpc.ClientConn, error) {
return grpc.DialContext(
ctx, socketPath,
grpc.WithInsecure(), grpc.WithBlock(), grpc.WithTimeout(time.Second*3),
grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) {
return net.DialTimeout("unix", addr, timeout)
}),
)
}
func (c *Cmd) Connect(ctx context.Context, opts ...grpc.CallOption,
) error {
var err error
c.conn, err = grcpDialWithUnixSocket(ctx, c.socketPath)
if err != nil {
return errors.Wrap(err, "grpc dial error")
}
c.client = apis.NewExecutorClient(c.conn)
return nil
}
func (c *Cmd) Run() error {
if err := c.Start(); err != nil {
return err
}
return c.Wait()
}
func (c *Cmd) CombinedOutput() ([]byte, error) {
if c.Stdout != nil {
return nil, errors.New("exec: Stdout already set")
}
if c.Stderr != nil {
return nil, errors.New("exec: Stderr already set")
}
var b bytes.Buffer
c.Stdout = &b
c.Stderr = &b
err := c.Run()
return b.Bytes(), err
}
func (c *Cmd) Output() ([]byte, error) {
if c.Stdout != nil {
return nil, errors.New("exec: Stdout already set")
}
var stdout bytes.Buffer
var stderr bytes.Buffer
c.Stdout = &stdout
c.Stderr = &stderr
// function run return err its mean grpc stream transport error
// cmd execute error indicate by exit code
if err := c.Run(); err != nil {
if e, ok := err.(*ExitError); ok {
e.Stderr = stderr.Bytes()
}
return nil, err
}
return stdout.Bytes(), nil
}
func (c *Cmd) Start() error {
if c.conn != nil {
return errors.New("cmd executing")
}
if err := c.Connect(context.Background()); err != nil {
return err
}
sn, err := c.client.ExecCommand(context.Background(), &apis.Command{
Path: []byte(c.Path),
Args: strArrayToBytesArray(c.Args),
Env: strArrayToBytesArray(c.Env),
Dir: []byte(c.Dir),
})
if err != nil {
c.closeDescriptors()
return errors.Wrap(err, "grcp exec command")
}
c.sn = sn
if c.ctx != nil {
select {
case <-c.ctx.Done():
c.closeDescriptors()
return c.ctx.Err()
default:
}
}
var procIO = [3]*os.File{}
type F func(*Cmd) (*os.File, error)
for i, setupFd := range [3]F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} {
if i == 2 && c.Stderr != nil && interfaceEqual(c.Stderr, c.Stdout) {
procIO[2] = procIO[1]
c.combinedOutput = make(chan struct{}, 2)
continue
}
fd, err := setupFd(c)
if err != nil {
c.closeDescriptors()
return errors.Wrap(err, "setup fd")
}
procIO[i] = fd
}
input := &apis.StartInput{
Sn: c.sn.Sn,
HasStdin: procIO[0] != nil,
HasStdout: procIO[1] != nil,
HasStderr: procIO[2] != nil,
}
res, err := c.client.Start(context.Background(), input)
if err != nil {
c.closeDescriptors()
return errors.Wrap(err, "grpc start cmd")
}
if !res.Success {
c.closeDescriptors()
return errors.New(string(res.Error))
}
if procIO[0] != nil {
go c.sendStdin(procIO[0])
}
if procIO[1] != nil {
go c.fetchStdout(procIO[1])
<-c.stdoutCh
}
if procIO[2] != nil {
go c.fetchStderr(procIO[2])
<-c.stderrCh
}
if c.combinedOutput != nil {
go func(wc io.WriteCloser) {
var closed bool
for {
select {
case <-c.combinedOutput:
if closed {
wc.Close()
return
} else {
closed = true
}
}
}
}(procIO[1])
}
c.errch = make(chan error, len(c.goroutine))
for _, fn := range c.goroutine {
go func(fn func() error) {
c.errch <- fn()
}(fn)
}
if c.ctx != nil {
c.waitDone = make(chan struct{})
go func() {
select {
case <-c.ctx.Done():
c.Kill()
case <-c.waitDone:
}
}()
}
return nil
}
func (c *Cmd) streamError() error {
if c.streamStdin != nil {
return c.streamStdin
}
if c.streamStdout != nil {
return c.streamStdout
}
if c.streamStderr != nil {
return c.streamStderr
}
return nil
}
func (c *Cmd) Kill() error {
e, err := c.client.Kill(context.Background(), c.sn)
if err != nil {
return errors.Wrap(err, "grpc send kill")
}
if len(e.Error) > 0 {
return errors.Errorf("kill process %s", e.Error)
}
return nil
}
func (c *Cmd) Wait() error {
if c.conn == nil {
return errors.New("cmd not executing")
}
res, err := c.client.Wait(context.Background(), c.sn)
if err != nil {
c.closeDescriptors()
return errors.Wrap(err, "grpc wait proc")
}
if c.waitDone != nil {
close(c.waitDone)
}
if err := c.streamError(); err != nil {
c.closeDescriptors()
return err
}
c.wg.Wait()
if len(res.ErrContent) > 0 {
return errors.New(string(res.ErrContent))
}
var copyError error
for range c.goroutine {
if err := <-c.errch; err != nil && copyError == nil {
copyError = err
}
}
c.closeDescriptors()
if res.ExitStatus == 0 {
if copyError != nil {
return copyError
}
return nil
} else {
return &ExitError{ExitStatus: syscall.WaitStatus(res.ExitStatus)}
}
}
func (c *Cmd) closeDescriptors() {
for _, fd := range c.closeAfterWait {
fd.Close()
}
for _, fd := range c.closeAfterAfter {
fd.Close()
}
if c.conn != nil {
c.conn.Close()
}
}
func (c *Cmd) StdinPipe() (io.WriteCloser, error) {
if c.Stdin != nil {
return nil, errors.New("exec: Stdin already set")
}
if c.conn != nil {
return nil, errors.New("exec: StdinPipe after process started")
}
// do not use io.Pipe, block forever
// https://stackoverflow.com/questions/47486128
pr, pw, err := os.Pipe()
if err != nil {
return nil, errors.Wrap(err, "open stdinpipe")
}
c.Stdin = pr
c.closeAfterWait = append(c.closeAfterWait, pr)
wc := &CloseOnce{File: pw}
c.closeAfterAfter = append(c.closeAfterAfter, wc)
return wc, nil
}
func (c *Cmd) stdin() (*os.File, error) {
if c.Stdin == nil {
return nil, nil
}
if f, ok := c.Stdin.(*os.File); ok {
return f, nil
}
pr, pw, err := os.Pipe()
if err != nil {
return nil, err
}
c.closeAfterWait = append(c.closeAfterWait, pr)
c.goroutine = append(c.goroutine, func() error {
_, err := io.Copy(pw, c.Stdin)
if err1 := pw.Close(); err == nil {
err = err1
}
return err
})
return pr, nil
}
func (c *Cmd) stdout() (f *os.File, err error) {
return c.writerDescriptor(c.Stdout)
}
func (c *Cmd) stderr() (f *os.File, err error) {
return c.writerDescriptor(c.Stderr)
}
// interfaceEqual protects against panics from doing equality tests on
// two interfaces with non-comparable underlying types.
func interfaceEqual(a, b interface{}) bool {
defer func() {
recover()
}()
return a == b
}
func (c *Cmd) writerDescriptor(w io.Writer) (*os.File, error) {
if w == nil {
return nil, nil
}
if f, ok := w.(*os.File); ok {
return f, nil
}
pr, pw, err := os.Pipe()
if err != nil {
return nil, err
}
c.closeAfterWait = append(c.closeAfterWait, pw)
c.goroutine = append(c.goroutine, func() error {
_, err := io.Copy(w, pr)
pr.Close() // in case io.Copy stopped due to write error
return err
})
return pw, nil
}
func (c *Cmd) StdoutPipe() (io.ReadCloser, error) {
if c.Stdout != nil {
return nil, errors.New("exec: Stdout already set")
}
if c.conn != nil {
return nil, errors.New("exec: StdoutPipe after process started")
}
pr, pw, err := os.Pipe()
if err != nil {
return nil, errors.Wrap(err, "open stdoutpipe")
}
c.Stdout = pw
c.closeAfterWait = append(c.closeAfterWait, pw)
wc := &CloseOnce{File: pr}
c.closeAfterAfter = append(c.closeAfterAfter, wc)
return wc, nil
}
func (c *Cmd) StderrPipe() (io.ReadCloser, error) {
if c.Stderr != nil {
return nil, errors.New("exec: Stderr already set")
}
if c.conn != nil {
return nil, errors.New("exec: StderrPipe after process started")
}
pr, pw, err := os.Pipe()
if err != nil {
return nil, errors.Wrap(err, "open stderrpipe")
}
c.Stderr = pw
c.closeAfterWait = append(c.closeAfterWait, pw)
wc := &CloseOnce{File: pr}
c.closeAfterAfter = append(c.closeAfterAfter, wc)
return wc, nil
}
func (c *Cmd) sendStdin(r io.Reader) {
stream, err := c.client.SendInput(context.Background())
if err != nil {
c.streamStdin = errors.Wrap(err, "grpc send input")
return
}
var data = make([]byte, 4096)
for {
n, err := r.Read(data)
if err == io.EOF {
e, err := stream.CloseAndRecv()
if err != nil {
c.streamStdin = errors.Wrap(err, "grpc send stdin on close and recv")
return
}
if len(e.Error) > 0 {
c.streamStdin = errors.New(string(e.Error))
return
}
return
} else if err != nil {
c.streamStdin = errors.Wrap(err, "read from stdin")
return
}
err = stream.Send(&apis.Input{
Sn: c.sn.Sn,
Input: data[:n],
})
if err != nil {
c.streamStdin = errors.Wrap(err, "grpc send stdin")
return
}
}
}
func (c *Cmd) closeWithCombined() {
c.combinedOutput <- struct{}{}
}
func (c *Cmd) fetchStdout(w io.WriteCloser) {
if c.combinedOutput != nil {
defer c.closeWithCombined()
} else {
defer w.Close()
}
c.wg.Add(1)
defer c.wg.Done()
stream, err := c.client.FetchStdout(context.Background(), c.sn)
if err != nil {
close(c.stdoutCh)
c.streamStdout = errors.Wrap(err, "grpc fetch stdout")
return
}
data, err := stream.Recv()
close(c.stdoutCh)
if err != nil {
c.streamStdout = errors.Wrap(err, "stream stdout")
return
}
if !data.Start {
c.streamStdout = errors.Wrap(err, "stream stdout not start")
return
}
for {
data, err := stream.Recv()
if err == io.EOF {
close(c.stdoutCh)
return
} else if err != nil {
close(c.stdoutCh)
c.streamStdout = errors.Wrap(err, "grpc stdout recv")
return
}
if data.Closed {
return
} else if len(data.RuntimeError) > 0 {
c.streamStdout = errors.New(string(data.RuntimeError))
return
} else {
err := writeTo(data.Stdout, w)
if err != nil {
c.streamStdout = errors.Wrap(err, "write to stdout")
return
}
}
}
}
func (c *Cmd) fetchStderr(w io.WriteCloser) {
if c.combinedOutput != nil {
defer c.closeWithCombined()
} else {
defer w.Close()
}
c.wg.Add(1)
defer c.wg.Done()
stream, err := c.client.FetchStderr(context.Background(), c.sn)
if err != nil {
close(c.stderrCh)
c.streamStderr = errors.Wrap(err, "grpc fetch stderr")
return
}
data, err := stream.Recv()
close(c.stderrCh)
if err != nil {
c.streamStderr = errors.Wrap(err, "stream stderr")
return
}
if !data.Start {
c.streamStderr = errors.Wrap(err, "stream stderr not start")
return
}
for {
data, err := stream.Recv()
if err == io.EOF {
return
} else if err != nil {
c.streamStderr = errors.Wrap(err, "grpc stderr recv")
return
}
if data.Closed {
return
} else if len(data.RuntimeError) > 0 {
c.streamStderr = errors.New(string(data.RuntimeError))
return
} else {
err := writeTo(data.Stderr, w)
if err != nil {
c.streamStderr = errors.Wrap(err, "write to stderr")
return
}
}
}
}
// Convert integer to decimal string
func itoa(val int) string {
if val < 0 {
return "-" + uitoa(uint(-val))
}
return uitoa(uint(val))
}
// Convert unsigned integer to decimal string
func uitoa(val uint) string {
if val == 0 { // avoid string allocation
return "0"
}
var buf [20]byte // big enough for 64bit value base 10
i := len(buf) - 1
for val >= 10 {
q := val / 10
buf[i] = byte('0' + val - q*10)
i--
val = q
}
// val < 10
buf[i] = byte('0' + val)
return string(buf[i:])
}
// Convert exit status to error string
// Source code in exec posix
func exitStatusToString(status syscall.WaitStatus) string {
res := ""
switch {
case status.Exited():
res = "exit status " + itoa(status.ExitStatus())
case status.Signaled():
res = "signal: " + status.Signal().String()
case status.Stopped():
res = "stop signal: " + status.StopSignal().String()
if status.StopSignal() == syscall.SIGTRAP && status.TrapCause() != 0 {
res += " (trap " + itoa(status.TrapCause()) + ")"
}
case status.Continued():
res = "continued"
}
if status.CoreDump() {
res += " (core dumped)"
}
return res
}
type ExitError struct {
ExitStatus syscall.WaitStatus
Stderr []byte
}
func (e *ExitError) Sys() interface{} {
return e.ExitStatus
}
func (e *ExitError) Error() string {
return exitStatusToString(e.ExitStatus)
}
func strArrayToBytesArray(sa []string) [][]byte {
if len(sa) == 0 {
return nil
}
res := make([][]byte, len(sa))
for i := 0; i < len(sa); i++ {
res[i] = []byte(sa[i])
}
return res
}
func writeTo(data []byte, w io.Writer) error {
var n = 0
var length = len(data)
for n < length {
r, e := w.Write(data[n:])
if e != nil {
return e
}
n += r
}
return nil
}
type CloseOnce struct {
*os.File
once sync.Once
err error
}
func (c *CloseOnce) Close() error {
c.once.Do(c.close)
return c.err
}
func (c *CloseOnce) close() {
c.err = c.File.Close()
}
+298
View File
@@ -0,0 +1,298 @@
package server
import (
"context"
"io"
"os"
"os/exec"
"sync"
"sync/atomic"
"syscall"
"github.com/pkg/errors"
"yunion.io/x/executor/apis"
"yunion.io/x/log"
)
var globalSn uint32
func NewSN() uint32 {
return atomic.AddUint32(&globalSn, 1)
}
func Len(sm *sync.Map) int {
lengh := 0
f := func(key, value interface{}) bool {
lengh++
return true
}
sm.Range(f)
return lengh
}
var cmds = &sync.Map{}
type Commander struct {
// stream apis.Executor_ExecCommandServer
c *exec.Cmd
stdin io.WriteCloser
stdout io.ReadCloser
stderr io.ReadCloser
wg *sync.WaitGroup
stdoutCh chan struct{}
stderrCh chan struct{}
}
func BytesArrayToStrArray(ba [][]byte) []string {
if len(ba) == 0 {
return nil
}
res := make([]string, len(ba))
for i := 0; i < len(ba); i++ {
res[i] = string(ba[i])
}
return res
}
func NewCommander(in *apis.Command) *Commander {
cmd := exec.Command(string(in.Path), BytesArrayToStrArray(in.Args)...)
if len(in.Env) > 0 {
cmd.Env = BytesArrayToStrArray(in.Env)
}
if len(in.Dir) > 0 {
cmd.Dir = string(in.Dir)
}
cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
return &Commander{
c: cmd,
wg: new(sync.WaitGroup),
}
}
type Executor struct{}
func (e *Executor) ExecCommand(ctx context.Context, req *apis.Command) (*apis.Sn, error) {
cm := NewCommander(req)
sn := NewSN()
log.Infof("%d/%d Exec %s", sn, Len(cmds), req.String())
cmds.Store(sn, cm)
return &apis.Sn{Sn: sn}, nil
}
func (e *Executor) Start(ctx context.Context, req *apis.StartInput) (*apis.StartResponse, error) {
icm, ok := cmds.Load(req.Sn)
if !ok {
return nil, errors.Errorf("unknown sn %d", req.Sn)
}
var (
m = icm.(*Commander)
err error
)
if req.HasStdin {
m.stdin, err = m.c.StdinPipe()
if err != nil {
return &apis.StartResponse{
Success: false,
Error: []byte(err.Error()),
}, nil
}
}
if req.HasStdout {
m.stdout, err = m.c.StdoutPipe()
if err != nil {
return &apis.StartResponse{
Success: false,
Error: []byte(err.Error()),
}, nil
}
m.stdoutCh = make(chan struct{})
}
if req.HasStderr {
m.stderr, err = m.c.StderrPipe()
if err != nil {
return &apis.StartResponse{
Success: false,
Error: []byte(err.Error()),
}, nil
}
m.stderrCh = make(chan struct{})
}
if err := m.c.Start(); err != nil {
return &apis.StartResponse{
Success: false,
Error: []byte(err.Error()),
}, nil
}
return &apis.StartResponse{
Success: true,
Error: nil,
}, nil
}
func (e *Executor) Wait(ctx context.Context, in *apis.Sn) (*apis.WaitResponse, error) {
icm, ok := cmds.Load(in.Sn)
if !ok {
return nil, errors.Errorf("unknown sn %d", in.Sn)
}
var (
m = icm.(*Commander)
err error
)
if m.stdout != nil {
<-m.stdoutCh
}
if m.stderr != nil {
<-m.stderrCh
}
m.wg.Wait()
err = m.c.Wait()
var (
exitStatus uint32
errContent string
)
if err != nil {
if exiterr, ok := err.(*exec.ExitError); ok {
// The program has exited with an exit code != 0
// This works on both Unix and Windows. Although package
// syscall is generally platform dependent, WaitStatus is
// defined for both Unix and Windows and in both cases has
// an ExitStatus() method with the same signature.
exitStatus = uint32(exiterr.Sys().(syscall.WaitStatus))
} else {
// command not found or io problem or wait was already called
errContent = err.Error()
}
} else {
exitStatus = 0
}
cmds.Delete(in.Sn)
return &apis.WaitResponse{
ExitStatus: exitStatus,
ErrContent: []byte(errContent),
}, nil
}
func (e *Executor) Kill(ctx context.Context, req *apis.Sn) (*apis.Error, error) {
icm, ok := cmds.Load(req.Sn)
if !ok {
return nil, errors.Errorf("unknown sn %d", req.Sn)
}
m := icm.(*Commander)
err := m.c.Process.Kill()
if err != nil {
return &apis.Error{Error: []byte(err.Error())}, nil
}
return &apis.Error{}, nil
}
func (e *Executor) SendInput(s apis.Executor_SendInputServer) error {
var m *Commander
for {
input, err := s.Recv()
if err == io.EOF {
return s.SendAndClose(&apis.Error{})
} else if err != nil {
return s.SendAndClose(&apis.Error{
Error: []byte(err.Error()),
})
}
if m == nil {
icm, ok := cmds.Load(input.Sn)
if !ok {
return errors.Errorf("unknown sn %d", input.Sn)
}
m = icm.(*Commander)
if m.stdin == nil {
return errors.New("Process stdin not init")
}
}
_, err = m.stdin.Write(input.Input)
if err != nil {
return s.SendAndClose(&apis.Error{
Error: []byte(err.Error()),
})
}
}
}
func (e *Executor) FetchStdout(sn *apis.Sn, s apis.Executor_FetchStdoutServer) error {
icm, ok := cmds.Load(sn.Sn)
if !ok {
return errors.Errorf("unknown sn %d", sn.Sn)
}
var (
m = icm.(*Commander)
data = make([]byte, 4096)
err error
n int
)
if m.stdout == nil {
return errors.New("Process stdout not init")
} else {
close(m.stdoutCh)
}
m.wg.Add(1)
defer m.wg.Done()
s.Send(&apis.Stdout{Start: true})
for {
n, err = m.stdout.Read(data)
if err == io.EOF {
return s.Send(&apis.Stdout{Closed: true})
} else if pe, ok := err.(*os.PathError); ok && pe.Err == os.ErrClosed {
return s.Send(&apis.Stdout{Closed: true})
} else if err != nil {
return s.Send(&apis.Stdout{RuntimeError: []byte(err.Error())})
}
err = s.Send(&apis.Stdout{Stdout: data[:n]})
if err != nil {
return err
}
}
}
func (e *Executor) FetchStderr(sn *apis.Sn, s apis.Executor_FetchStderrServer) error {
icm, ok := cmds.Load(sn.Sn)
if !ok {
return errors.Errorf("unknown sn %d", sn.Sn)
}
var (
m = icm.(*Commander)
data = make([]byte, 4096)
err error
n int
)
if m.stderr == nil {
return errors.New("Process stderr not init")
} else {
close(m.stderrCh)
}
m.wg.Add(1)
defer m.wg.Done()
s.Send(&apis.Stderr{Start: true})
for {
n, err = m.stderr.Read(data)
if err == io.EOF {
return s.Send(&apis.Stderr{Closed: true})
} else if pe, ok := err.(*os.PathError); ok && pe.Err == os.ErrClosed {
return s.Send(&apis.Stderr{Closed: true})
} else if err != nil {
return s.Send(&apis.Stderr{RuntimeError: []byte(err.Error())})
}
err = s.Send(&apis.Stderr{Stderr: data[:n]})
if err != nil {
return err
}
}
}