From 9dee8cbea85fd437bf8bb897d2fd621496865837 Mon Sep 17 00:00:00 2001 From: zc Date: Mon, 2 Mar 2020 16:11:49 +0800 Subject: [PATCH] inspect through systemd engine --- engine/systemd/status.go | 59 ++++++++++++++++++++++++++++++++ engine/systemd/systemd.go | 16 +++++++-- engine/systemd/unit.go | 6 ++++ engine/systemd/virtualization.go | 25 +++++++++++--- 4 files changed, 99 insertions(+), 7 deletions(-) create mode 100644 engine/systemd/status.go diff --git a/engine/systemd/status.go b/engine/systemd/status.go new file mode 100644 index 000000000..47d60d813 --- /dev/null +++ b/engine/systemd/status.go @@ -0,0 +1,59 @@ +package systemd + +import ( + "bufio" + "bytes" + "encoding/csv" + "encoding/json" + "strings" + + "github.com/pkg/errors" +) + +type serviceStatus struct { + SubState string + ActiveState string + Environment string + Description string + User string +} + +func newServiceStatus(buf *bytes.Buffer) *serviceStatus { + status := map[string]string{} + scanner := bufio.NewScanner(buf) + for scanner.Scan() { + text := scanner.Text() + parts := strings.SplitN(text, "=", 2) + status[parts[0]] = parts[1] + } + return &serviceStatus{ + SubState: status["SubState"], + ActiveState: status["ActiveState"], + Environment: status["Environment"], + Description: status["Description"], + User: status["User"], + } +} + +func (s *serviceStatus) running() bool { + return s.SubState == "running" && s.ActiveState == "active" +} + +func (s *serviceStatus) env() ([]string, error) { + reader := csv.NewReader(strings.NewReader(s.Environment)) + reader.Comma = ' ' + records, err := reader.ReadAll() + if err != nil { + return nil, errors.Wrap(err, s.Environment) + } + return records[0], nil +} + +func (s *serviceStatus) labels() (map[string]string, error) { + desc := &unitDesciption{} + description := strings.ReplaceAll(s.Description, "\\x5c", "\\") + if err := json.Unmarshal([]byte(description), desc); err != nil { + return nil, errors.Wrap(err, s.Description) + } + return desc.Labels, nil +} diff --git a/engine/systemd/systemd.go b/engine/systemd/systemd.go index 84bc4b43c..d55f91bda 100644 --- a/engine/systemd/systemd.go +++ b/engine/systemd/systemd.go @@ -23,9 +23,19 @@ const ( ) type SystemdSSH struct { + hostIP string client *ssh.Client } +func NewSystemdSSH(endpoint string, config *ssh.ClientConfig) (*SystemdSSH, error) { + parts := strings.Split(endpoint, ":") + client, err := ssh.Dial("tcp", endpoint, config) + return &SystemdSSH{ + hostIP: parts[0], + client: client, + }, err +} + func MakeClient(ctx context.Context, config coretypes.Config, nodename, endpoint, ca, cert, key string) (api engine.API, err error) { signer, err := ssh.ParsePrivateKey([]byte(key)) if err != nil { @@ -38,8 +48,10 @@ func MakeClient(ctx context.Context, config coretypes.Config, nodename, endpoint }, HostKeyCallback: func(_ string, _ net.Addr, _ ssh.PublicKey) error { return nil }, } - sshClient, err := ssh.Dial("tcp", strings.TrimPrefix(endpoint, SSHPrefixKey), sshConfig) - return &SystemdSSH{sshClient}, err + return NewSystemdSSH( + strings.TrimPrefix(endpoint, SSHPrefixKey), + sshConfig, + ) } func (s *SystemdSSH) WithSession(f func(*ssh.Session) error) (err error) { diff --git a/engine/systemd/unit.go b/engine/systemd/unit.go index a50988f5f..cd009199c 100644 --- a/engine/systemd/unit.go +++ b/engine/systemd/unit.go @@ -134,6 +134,11 @@ func (b *unitBuilder) buildExec() *unitBuilder { return b } + user := b.opts.User + if user == "" { + user = "root" + } + env := []string{} for _, e := range b.opts.Env { env = append(env, fmt.Sprintf(`"%s"`, e)) @@ -153,6 +158,7 @@ func (b *unitBuilder) buildExec() *unitBuilder { b.serviceBuffer = append(b.serviceBuffer, []string{ fmt.Sprintf("ExecStart=/usr/bin/cgexec -g memory,cpuset:%s %s", b.cgroupPath(), strings.Join(b.opts.Cmd, " ")), + fmt.Sprintf("User=%s", user), fmt.Sprintf("Environment=%s", strings.Join(env, " ")), fmt.Sprintf("StandardOutput=%s", stdioType), fmt.Sprintf("StandardError=%s", stdioType), diff --git a/engine/systemd/virtualization.go b/engine/systemd/virtualization.go index fc1d20383..1f6264e4c 100644 --- a/engine/systemd/virtualization.go +++ b/engine/systemd/virtualization.go @@ -20,7 +20,7 @@ const ( cmdSystemdReload = `/bin/systemctl daemon-reload` cmdSystemdRestart = `/bin/systemctl restart %s` cmdSystemdStop = `/bin/systemctl stop %s` - cmdSystemdStatus = `/bin/systemctl status %s --property SubState,ActiveState` + cmdSystemdStatus = `/bin/systemctl show %s --property SubState,ActiveState,Environment,Description --no-pager` ) func (s *SystemdSSH) VirtualizationCreate(ctx context.Context, opts *enginetypes.VirtualizationCreateOptions) (created *enginetypes.VirtualizationCreated, err error) { @@ -85,15 +85,30 @@ func (s *SystemdSSH) VirtualizationRemove(ctx context.Context, ID string, volume } func (s *SystemdSSH) VirtualizationInspect(ctx context.Context, ID string) (info *enginetypes.VirtualizationInfo, err error) { - _, stderr, err := s.runSingleCommand(ctx, fmt.Sprintf(cmdSystemdStatus, ID), nil) + stdout, stderr, err := s.runSingleCommand(ctx, fmt.Sprintf(cmdSystemdStatus, ID), nil) if err != nil { return nil, errors.Wrap(err, stderr.String()) } + serviceStatus := newServiceStatus(stdout) + + env, err := serviceStatus.env() + if err != nil { + return + } + + labels, err := serviceStatus.labels() + if err != nil { + return + } + return &enginetypes.VirtualizationInfo{ - ID: ID, - User: "root", - Running: false, + ID: ID, + User: "root", + Running: serviceStatus.running(), + Env: env, + Labels: labels, + Networks: map[string]string{"host": s.hostIP}, }, nil }