-
Notifications
You must be signed in to change notification settings - Fork 328
/
Copy pathwindowsmanager.go
148 lines (130 loc) · 4.11 KB
/
windowsmanager.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing
// permissions and limitations under the License.
//go:build windows
// +build windows
// Package servicemanagers contains functions related to service manager
package servicemanagers
import (
"fmt"
"os/exec"
"strings"
"github.com/aws/amazon-ssm-agent/agent/setupcli/managers/common"
"golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/mgr"
)
const (
netExecPath = "C:\\Windows\\System32\\net.exe"
serviceName = "AmazonSSMAgent"
)
type windowsManager struct {
managerHelper common.IManagerHelper
}
// StartAgent starts the agent
func (m *windowsManager) StartAgent() error {
output, err := m.managerHelper.RunCommand(netExecPath, "start", serviceName)
if err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
ec := exitError.ExitCode()
// NET HELPMSG 2182 : The requested service has already been started.
if ec == 2182 {
return nil
}
}
output = strings.ToLower(output)
if strings.Contains(output, "service has already been started") {
// service already running
return nil
}
return fmt.Errorf("windows: failed to start agent with output '%s' and error: %v", output, err)
}
return nil
}
// StopAgent stops the agent
func (m *windowsManager) StopAgent() error {
output, err := m.managerHelper.RunCommand(netExecPath, "stop", serviceName)
if err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
ec := exitError.ExitCode()
//NET HELPMSG 3521 : The *** service is not started.
if ec == 3521 {
return nil
}
}
output = strings.ToLower(output)
if strings.Contains(output, "service is not started") {
// Service is already stopped
return nil
}
return fmt.Errorf("windows: failed to stop agent with output '%s' and error: %v", output, err)
}
return nil
}
func (m *windowsManager) windowsServiceStatusToString(state svc.State) string {
switch state {
case svc.Stopped:
return "Stopped"
case svc.StartPending:
return "StartPending"
case svc.StopPending:
return "StopPending"
case svc.Running:
return "Running"
case svc.ContinuePending:
return "ContinuePending"
case svc.PausePending:
return "PausePending"
case svc.Paused:
return "Paused"
default:
return ""
}
}
// GetAgentStatus returns the status of the agent from the perspective of the service manager
func (m *windowsManager) GetAgentStatus() (common.AgentStatus, error) {
manager, err := mgr.Connect()
if err != nil {
return common.UndefinedStatus, fmt.Errorf("failed to connect to windows service manager: %v", err)
}
defer manager.Disconnect()
service, err := manager.OpenService(serviceName)
if err != nil {
return common.UndefinedStatus, fmt.Errorf("failed to open windows service manager: %v", err)
}
defer service.Close()
serviceStatus, err := service.Query()
if err != nil {
return common.UndefinedStatus, fmt.Errorf("failed to query windows service: %v", err)
}
if serviceStatus.State == svc.Running {
return common.Running, nil
} else if serviceStatus.State == svc.Stopped {
return common.Stopped, nil
}
return common.UndefinedStatus, fmt.Errorf("unexpected service status: %s", m.windowsServiceStatusToString(serviceStatus.State))
}
// ReloadManager reloads the service manager configuration files
func (m *windowsManager) ReloadManager() error {
return nil
}
// IsManagerEnvironment returns true if all commands required by the package manager are available
func (m *windowsManager) IsManagerEnvironment() bool {
return true
}
// GetName returns the service manager name
func (m *windowsManager) GetName() string {
return "windows"
}
// GetType returns the service manage type
func (m *windowsManager) GetType() ServiceManager {
return Windows
}