-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix and improve Windows service handling
This change addresses several issues how we handle windows services: - Change the DisplayName of the Sidecar itself so it does not conflict with old sidecars. - If a sidecar backend (aka collector) gets renamed, update the DisplayName to avoid a conflict with the existing service. - If backends get renamed, or deleted while the sidecar isn't running there was no way we could cleanup those. Therefore update golang/x/sys to a newer version that supports `ListServices()` so we can search for stale registered services and clean those. - Improve error handling in `ValidateBeforeStart()` which could lead to a panic if a service could not be created. Fixes #319
- Loading branch information
Showing
6 changed files
with
151 additions
and
72 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// +build !windows | ||
|
||
package daemon | ||
|
||
import ( | ||
"github.com/Graylog2/collector-sidecar/backends" | ||
) | ||
|
||
// Dummy function. Only used on Windows | ||
func CleanOldServices(assignedBackends []*backends.Backend) { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
package daemon | ||
|
||
import ( | ||
"fmt" | ||
"github.com/Graylog2/collector-sidecar/backends" | ||
"golang.org/x/sys/windows/svc" | ||
"golang.org/x/sys/windows/svc/eventlog" | ||
"golang.org/x/sys/windows/svc/mgr" | ||
"strings" | ||
"time" | ||
) | ||
|
||
func CleanOldServices(assignedBackends []*backends.Backend) { | ||
registeredServices, err := getRegisteredServices() | ||
if err != nil { | ||
log.Warn("Failed to get registered services. Skipping cleanup. ", err) | ||
return | ||
} | ||
for _, service := range registeredServices { | ||
if strings.Contains(service, ServiceNamePrefix) { | ||
log.Debugf("Found graylog service %s", service) | ||
if !serviceIsAssigned(assignedBackends, service) { | ||
log.Infof("Removing stale graylog service %s", service) | ||
uninstallService(service) | ||
} | ||
} | ||
} | ||
} | ||
|
||
func getRegisteredServices() ([]string, error) { | ||
m, err := mgr.Connect() | ||
if err != nil { | ||
return nil, err | ||
} | ||
defer m.Disconnect() | ||
registeredServices, err := m.ListServices() | ||
if err != nil { | ||
return nil, err | ||
} | ||
return registeredServices, nil | ||
} | ||
|
||
func serviceIsAssigned(assignedBackends []*backends.Backend, serviceName string) bool { | ||
for _, backend := range assignedBackends { | ||
if backend.ServiceType == "svc" && ServiceNamePrefix+backend.Name == serviceName { | ||
return true | ||
} | ||
} | ||
return false | ||
} | ||
|
||
func uninstallService(name string) { | ||
log.Infof("Uninstalling service %s", name) | ||
stopService(name) | ||
|
||
m, err := mgr.Connect() | ||
if err != nil { | ||
log.Errorf("Failed to connect to service manager: %v", err) | ||
return | ||
} | ||
defer m.Disconnect() | ||
|
||
s, err := m.OpenService(name) | ||
// service exist so we try to uninstall it | ||
if err != nil { | ||
log.Debugf("Service %s doesn't exist, no uninstall action needed", name) | ||
return | ||
} | ||
|
||
defer s.Close() | ||
err = s.Delete() | ||
if err != nil { | ||
log.Errorf("Can't delete service %s: %v", name, err) | ||
} | ||
|
||
err = eventlog.Remove(s.Name) | ||
if err != nil { | ||
log.Errorf("RemoveEventLogSource() failed: %s", err) | ||
} | ||
return | ||
} | ||
|
||
func stopService(serviceName string) error { | ||
m, err := mgr.Connect() | ||
if err != nil { | ||
return fmt.Errorf("Failed to connect to service manager: %v", err) | ||
} | ||
defer m.Disconnect() | ||
|
||
ws, err := m.OpenService(serviceName) | ||
if err != nil { | ||
return fmt.Errorf("Could not access service %s: %v", serviceName, err) | ||
} | ||
defer ws.Close() | ||
|
||
status, err := ws.Control(svc.Stop) | ||
if err != nil { | ||
return fmt.Errorf("Could not send stop control: %v", err) | ||
} | ||
|
||
timeout := time.Now().Add(10 * time.Second) | ||
for status.State != svc.Stopped { | ||
if timeout.Before(time.Now()) { | ||
return fmt.Errorf("Timeout waiting for service to go to stopped state: %v", err) | ||
} | ||
time.Sleep(300 * time.Millisecond) | ||
status, err = ws.Query() | ||
if err != nil { | ||
return fmt.Errorf("Could not retrieve service status: %v", err) | ||
} | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters