mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-08-29 03:51:54 +08:00
- add command executor
- host prepare for deploy on container - procutils adpat to executor
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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=
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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:]...)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+4
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user