Skip to content

Commit d3e0c16

Browse files
committed
Adds runtime v2 support for Windows shim's
Implements the various requirements for the runtime v2 code to abstract away the unix/linux code into the appropriate platform level abstractions to use the runtime v2 on Windows as well. Adds support in the Makefile.windows to actually build the runtime v2 code for Windows by setting a shell environment BUILD_WINDOWS_V2=1 before calling make. (Note this disables the compilation of the Windows runtime v1) Signed-off-by: Justin Terry (VM) <[email protected]>
1 parent d47bda9 commit d3e0c16

9 files changed

Lines changed: 323 additions & 93 deletions

File tree

Makefile.windows

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,10 @@ BINARY_SUFFIX=".exe"
2323
ifeq ($(GOARCH),amd64)
2424
TESTFLAGS_RACE= -race
2525
endif
26+
27+
# add support for building the Windows v2 runtime
28+
# based on the containerd-shim-runhcs-v1 shim rather
29+
# than the existing runtime on hcsshim
30+
ifeq (${BUILD_WINDOWS_V2},1)
31+
BUILDTAGS += windows_v2
32+
endif

cmd/containerd/builtins_windows.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// +build !windows_v2
2+
13
/*
24
Copyright The containerd Authors.
35
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// +build windows_v2
2+
3+
/*
4+
Copyright The containerd Authors.
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
*/
18+
19+
package main
20+
21+
import (
22+
_ "github.com/containerd/containerd/diff/windows"
23+
_ "github.com/containerd/containerd/runtime/v2"
24+
_ "github.com/containerd/containerd/snapshots/windows"
25+
)

runtime/v2/shim/shim.go

Lines changed: 3 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// +build !windows
2-
31
/*
42
Copyright The containerd Authors.
53
@@ -19,29 +17,22 @@
1917
package shim
2018

2119
import (
22-
"bytes"
2320
"context"
2421
"flag"
2522
"fmt"
26-
"net"
2723
"os"
28-
"os/exec"
29-
"os/signal"
3024
"runtime"
3125
"runtime/debug"
3226
"strings"
33-
"syscall"
3427
"time"
3528

3629
"github.com/containerd/containerd/events"
3730
"github.com/containerd/containerd/namespaces"
3831
shimapi "github.com/containerd/containerd/runtime/v2/task"
3932
"github.com/containerd/ttrpc"
40-
"github.com/containerd/typeurl"
4133
"github.com/gogo/protobuf/proto"
4234
"github.com/pkg/errors"
4335
"github.com/sirupsen/logrus"
44-
"golang.org/x/sys/unix"
4536
)
4637

4738
// Client for a shim server
@@ -178,7 +169,7 @@ func NewShimClient(ctx context.Context, svc shimapi.TaskService, signals chan os
178169
// Serve the shim server
179170
func (s *Client) Serve() error {
180171
dump := make(chan os.Signal, 32)
181-
signal.Notify(dump, syscall.SIGUSR1)
172+
setupDumpStacks(dump)
182173

183174
path, err := os.Getwd()
184175
if err != nil {
@@ -211,23 +202,11 @@ func (s *Client) Serve() error {
211202
// serve serves the ttrpc API over a unix socket at the provided path
212203
// this function does not block
213204
func serve(ctx context.Context, server *ttrpc.Server, path string) error {
214-
var (
215-
l net.Listener
216-
err error
217-
)
218-
if path == "" {
219-
l, err = net.FileListener(os.NewFile(3, "socket"))
220-
path = "[inherited from parent]"
221-
} else {
222-
if len(path) > 106 {
223-
return errors.Errorf("%q: unix socket path too long (> 106)", path)
224-
}
225-
l, err = net.Listen("unix", "\x00"+path)
226-
}
205+
l, path, err := serveListener(path)
227206
if err != nil {
228207
return err
229208
}
230-
logrus.WithField("socket", path).Debug("serving api on unix socket")
209+
logrus.WithField("socket", path).Debug("serving api on abstract socket")
231210
go func() {
232211
defer l.Close()
233212
if err := server.Serve(ctx, l); err != nil &&
@@ -238,22 +217,6 @@ func serve(ctx context.Context, server *ttrpc.Server, path string) error {
238217
return nil
239218
}
240219

241-
func handleSignals(logger *logrus.Entry, signals chan os.Signal) error {
242-
logger.Info("starting signal loop")
243-
for {
244-
select {
245-
case s := <-signals:
246-
switch s {
247-
case unix.SIGCHLD:
248-
if err := Reap(); err != nil {
249-
logger.WithError(err).Error("reap exit status")
250-
}
251-
case unix.SIGPIPE:
252-
}
253-
}
254-
}
255-
}
256-
257220
func dumpStacks(logger *logrus.Entry) {
258221
var (
259222
buf []byte
@@ -273,29 +236,3 @@ type remoteEventsPublisher struct {
273236
address string
274237
containerdBinaryPath string
275238
}
276-
277-
func (l *remoteEventsPublisher) Publish(ctx context.Context, topic string, event events.Event) error {
278-
ns, _ := namespaces.Namespace(ctx)
279-
encoded, err := typeurl.MarshalAny(event)
280-
if err != nil {
281-
return err
282-
}
283-
data, err := encoded.Marshal()
284-
if err != nil {
285-
return err
286-
}
287-
cmd := exec.CommandContext(ctx, l.containerdBinaryPath, "--address", l.address, "publish", "--topic", topic, "--namespace", ns)
288-
cmd.Stdin = bytes.NewReader(data)
289-
c, err := Default.Start(cmd)
290-
if err != nil {
291-
return err
292-
}
293-
status, err := Default.Wait(cmd, c)
294-
if err != nil {
295-
return err
296-
}
297-
if status != 0 {
298-
return errors.New("failed to publish event")
299-
}
300-
return nil
301-
}

runtime/v2/shim/shim_nix.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// +build !windows
2+
3+
/*
4+
Copyright The containerd Authors.
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
*/
18+
19+
package shim
20+
21+
import (
22+
"bytes"
23+
"context"
24+
"net"
25+
"os"
26+
"os/exec"
27+
"os/signal"
28+
"syscall"
29+
30+
"github.com/containerd/containerd/events"
31+
"github.com/containerd/containerd/namespaces"
32+
"github.com/containerd/typeurl"
33+
"github.com/pkg/errors"
34+
"github.com/sirupsen/logrus"
35+
"golang.org/x/sys/unix"
36+
)
37+
38+
func setupDumpStacks(dump chan<- os.Signal) {
39+
signal.Notify(dump, syscall.SIGUSR1)
40+
}
41+
42+
func serveListener(path string) (net.Listener, string, error) {
43+
var (
44+
l net.Listener
45+
err error
46+
)
47+
if path == "" {
48+
l, err = net.FileListener(os.NewFile(3, "socket"))
49+
path = "[inherited from parent]"
50+
} else {
51+
if len(path) > 106 {
52+
return nil, path, errors.Errorf("%q: unix socket path too long (> 106)", path)
53+
}
54+
l, err = net.Listen("unix", "\x00"+path)
55+
}
56+
if err != nil {
57+
return nil, path, err
58+
}
59+
return l, path, nil
60+
}
61+
62+
func handleSignals(logger *logrus.Entry, signals chan os.Signal) error {
63+
logger.Info("starting signal loop")
64+
for {
65+
select {
66+
case s := <-signals:
67+
switch s {
68+
case unix.SIGCHLD:
69+
if err := Reap(); err != nil {
70+
logger.WithError(err).Error("reap exit status")
71+
}
72+
case unix.SIGPIPE:
73+
}
74+
}
75+
}
76+
}
77+
78+
func (l *remoteEventsPublisher) Publish(ctx context.Context, topic string, event events.Event) error {
79+
ns, _ := namespaces.Namespace(ctx)
80+
encoded, err := typeurl.MarshalAny(event)
81+
if err != nil {
82+
return err
83+
}
84+
data, err := encoded.Marshal()
85+
if err != nil {
86+
return err
87+
}
88+
cmd := exec.CommandContext(ctx, l.containerdBinaryPath, "--address", l.address, "publish", "--topic", topic, "--namespace", ns)
89+
cmd.Stdin = bytes.NewReader(data)
90+
c, err := Default.Start(cmd)
91+
if err != nil {
92+
return err
93+
}
94+
status, err := Default.Wait(cmd, c)
95+
if err != nil {
96+
return err
97+
}
98+
if status != 0 {
99+
return errors.New("failed to publish event")
100+
}
101+
return nil
102+
}

runtime/v2/shim/shim_windows.go

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// +build windows
2+
3+
/*
4+
Copyright The containerd Authors.
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
*/
18+
19+
package shim
20+
21+
import (
22+
"context"
23+
"net"
24+
"os"
25+
26+
winio "github.com/Microsoft/go-winio"
27+
"github.com/containerd/containerd/events"
28+
"github.com/containerd/ttrpc"
29+
"github.com/pkg/errors"
30+
"github.com/sirupsen/logrus"
31+
)
32+
33+
// setupSignals creates a new signal handler for all signals
34+
func setupSignals() (chan os.Signal, error) {
35+
signals := make(chan os.Signal, 32)
36+
// TODO: JTERRY75: Make this based on events.
37+
return signals, nil
38+
}
39+
40+
func newServer() (*ttrpc.Server, error) {
41+
return ttrpc.NewServer()
42+
}
43+
44+
func subreaper() error {
45+
return nil
46+
}
47+
48+
func setupDumpStacks(dump chan<- os.Signal) {
49+
// TODO: JTERRY75: Make this based on events. signal.Notify(dump, syscall.SIGUSR1)
50+
}
51+
52+
// serve serves the ttrpc API over a unix socket at the provided path
53+
// this function does not block
54+
func serveListener(path string) (net.Listener, string, error) {
55+
if path == "" {
56+
return nil, path, errors.New("'socket' must be npipe path")
57+
}
58+
l, err := winio.ListenPipe(path, nil)
59+
if err != nil {
60+
return nil, path, err
61+
}
62+
return l, path, nil
63+
}
64+
65+
func handleSignals(logger *logrus.Entry, signals chan os.Signal) error {
66+
// TODO: JTERRY75: Make this based on events?
67+
return nil
68+
}
69+
70+
func (l *remoteEventsPublisher) Publish(ctx context.Context, topic string, event events.Event) error {
71+
/* TOOD: JTERRY75: Implement publish for windows
72+
ns, _ := namespaces.Namespace(ctx)
73+
encoded, err := typeurl.MarshalAny(event)
74+
if err != nil {
75+
return err
76+
}
77+
data, err := encoded.Marshal()
78+
if err != nil {
79+
return err
80+
}
81+
cmd := exec.CommandContext(ctx, l.containerdBinaryPath, "--address", l.address, "publish", "--topic", topic, "--namespace", ns)
82+
cmd.Stdin = bytes.NewReader(data)
83+
c, err := Default.Start(cmd)
84+
if err != nil {
85+
return err
86+
}
87+
status, err := Default.Wait(cmd, c)
88+
if err != nil {
89+
return err
90+
}
91+
if status != 0 {
92+
return errors.New("failed to publish event")
93+
}
94+
*/
95+
return nil
96+
}

0 commit comments

Comments
 (0)