Ensure Host Network Service exists
If HNS does not exist on the Docker host, the daemon may fail with unexpected and difficult to diagnose errors. This check prevents the daemon from starting on a system that does not have the correct prerequisites. Signed-off-by: Darren Stahl <darst@microsoft.com>
This commit is contained in:
parent
7d70d0fac3
commit
1edcc63560
2 changed files with 97 additions and 0 deletions
|
@ -27,8 +27,10 @@ import (
|
|||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/options"
|
||||
blkiodev "github.com/opencontainers/runc/libcontainer/configs"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/sys/windows"
|
||||
"golang.org/x/sys/windows/svc/mgr"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -238,6 +240,29 @@ func checkSystem() error {
|
|||
return fmt.Errorf("Failed to load vmcompute.dll. Ensure that the Containers role is installed.")
|
||||
}
|
||||
|
||||
// Ensure that the required Host Network Service and vmcompute services
|
||||
// are running. Docker will fail in unexpected ways if this is not present.
|
||||
var requiredServices = []string{"hns", "vmcompute"}
|
||||
if err := ensureServicesInstalled(requiredServices); err != nil {
|
||||
return errors.Wrap(err, "a required service is not installed, ensure the Containers feature is installed")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ensureServicesInstalled(services []string) error {
|
||||
m, err := mgr.Connect()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer m.Disconnect()
|
||||
for _, service := range services {
|
||||
s, err := m.OpenService(service)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to open service %s", service)
|
||||
}
|
||||
s.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
72
daemon/daemon_windows_test.go
Normal file
72
daemon/daemon_windows_test.go
Normal file
|
@ -0,0 +1,72 @@
|
|||
// +build windows
|
||||
|
||||
package daemon
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/sys/windows/svc/mgr"
|
||||
)
|
||||
|
||||
const existingService = "Power"
|
||||
|
||||
func TestEnsureServicesExist(t *testing.T) {
|
||||
m, err := mgr.Connect()
|
||||
if err != nil {
|
||||
t.Fatal("failed to connect to service manager, this test needs admin")
|
||||
}
|
||||
defer m.Disconnect()
|
||||
s, err := m.OpenService(existingService)
|
||||
if err != nil {
|
||||
t.Fatalf("expected to find known inbox service %q, this test needs a known inbox service to run correctly", existingService)
|
||||
}
|
||||
defer s.Close()
|
||||
|
||||
input := []string{existingService}
|
||||
err = ensureServicesInstalled(input)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error for input %q: %q", input, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnsureServicesExistErrors(t *testing.T) {
|
||||
m, err := mgr.Connect()
|
||||
if err != nil {
|
||||
t.Fatal("failed to connect to service manager, this test needs admin")
|
||||
}
|
||||
defer m.Disconnect()
|
||||
s, err := m.OpenService(existingService)
|
||||
if err != nil {
|
||||
t.Fatalf("expected to find known inbox service %q, this test needs a known inbox service to run correctly", existingService)
|
||||
}
|
||||
defer s.Close()
|
||||
|
||||
for _, testcase := range []struct {
|
||||
input []string
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
input: []string{"daemon_windows_test_fakeservice"},
|
||||
expectedError: "failed to open service daemon_windows_test_fakeservice",
|
||||
},
|
||||
{
|
||||
input: []string{"daemon_windows_test_fakeservice1", "daemon_windows_test_fakeservice2"},
|
||||
expectedError: "failed to open service daemon_windows_test_fakeservice1",
|
||||
},
|
||||
{
|
||||
input: []string{existingService, "daemon_windows_test_fakeservice"},
|
||||
expectedError: "failed to open service daemon_windows_test_fakeservice",
|
||||
},
|
||||
} {
|
||||
t.Run(strings.Join(testcase.input, ";"), func(t *testing.T) {
|
||||
err := ensureServicesInstalled(testcase.input)
|
||||
if err == nil {
|
||||
t.Fatalf("expected error for input %v", testcase.input)
|
||||
}
|
||||
if !strings.Contains(err.Error(), testcase.expectedError) {
|
||||
t.Fatalf("expected error %q to contain %q", err.Error(), testcase.expectedError)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue