Skip to content

Commit 9dd72da

Browse files
committed
feature:support live-restore
Signed-off-by: ningmingxiao <ning.mingxiao@zte.com.cn>
1 parent dfb811b commit 9dd72da

File tree

6 files changed

+177
-20
lines changed

6 files changed

+177
-20
lines changed

cmd/nerdctl/container/container_run_restart_linux_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ func TestRunRestart(t *testing.T) {
5353
"--name", testContainerName,
5454
"-p", fmt.Sprintf("127.0.0.1:%d:80", hostPort),
5555
testutil.NginxAlpineImage).AssertOK()
56-
56+
inspectedContainer := base.InspectContainer(testContainerName)
57+
pid := inspectedContainer.State.Pid
5758
check := func(httpGetRetry int) error {
5859
resp, err := nettestutil.HTTPGet(fmt.Sprintf("http://127.0.0.1:%d", hostPort), httpGetRetry, false)
5960
if err != nil {
@@ -87,6 +88,9 @@ func TestRunRestart(t *testing.T) {
8788
}
8889
time.Sleep(sleep)
8990
}
91+
inspectedContainer = base.InspectContainer(testContainerName)
92+
assert.Equal(t, inspectedContainer.State.Status, "running")
93+
assert.Equal(t, inspectedContainer.State.Pid, pid)
9094
base.DumpDaemonLogs(10)
9195
t.Fatalf("the container does not seem to be restarted")
9296
}

pkg/logging/logging.go

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ func getContainerWait(ctx context.Context, address string, config *logging.Confi
207207

208208
type ContainerWaitFunc func(ctx context.Context, address string, config *logging.Config) (<-chan containerd.ExitStatus, error)
209209

210-
func loggingProcessAdapter(ctx context.Context, driver Driver, dataStore, address string, getContainerWait ContainerWaitFunc, config *logging.Config) error {
210+
func loggingProcessAdapter(ctx context.Context, driver Driver, dataStore string, config *logging.Config) error {
211211
if err := driver.PreProcess(ctx, dataStore, config); err != nil {
212212
return err
213213
}
@@ -220,6 +220,17 @@ func loggingProcessAdapter(ctx context.Context, driver Driver, dataStore, addres
220220
if err != nil {
221221
return err
222222
}
223+
224+
stdoutChan, err := waitIOClose(config.Stdout)
225+
if err != nil {
226+
return err
227+
}
228+
229+
stderrChan, err := waitIOClose(config.Stderr)
230+
if err != nil {
231+
return err
232+
}
233+
223234
go func() {
224235
<-ctx.Done() // delivered on SIGTERM
225236
stdoutR.Cancel()
@@ -273,13 +284,8 @@ func loggingProcessAdapter(ctx context.Context, driver Driver, dataStore, addres
273284
// close pipeStdoutW and pipeStderrW upon container exit
274285
defer pipeStdoutW.Close()
275286
defer pipeStderrW.Close()
276-
277-
exitCh, err := getContainerWait(ctx, address, config)
278-
if err != nil {
279-
log.G(ctx).Errorf("failed to get container task wait channel: %v", err)
280-
return
281-
}
282-
<-exitCh
287+
<-stdoutChan
288+
<-stderrChan
283289
}()
284290
wg.Wait()
285291
return driver.PostProcess()
@@ -314,7 +320,7 @@ func loggerFunc(dataStore string) (logging.LoggerFunc, error) {
314320
return err
315321
}
316322
// getContainerWait is extracted as parameter to allow mocking in tests.
317-
return loggingProcessAdapter(ctx, driver, dataStore, logConfig.Address, getContainerWait, config)
323+
return loggingProcessAdapter(ctx, driver, dataStore, config)
318324
})
319325
} else if !errors.Is(err, os.ErrNotExist) {
320326
// the file does not exist if the container was created with nerdctl < 0.20

pkg/logging/logging_bsd.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//go:build darwin || freebsd || netbsd || openbsd || dragonfly
2+
// +build darwin freebsd netbsd openbsd dragonfly
3+
4+
/*
5+
Copyright The containerd Authors.
6+
7+
Licensed under the Apache License, Version 2.0 (the "License");
8+
you may not use this file except in compliance with the License.
9+
You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing, software
14+
distributed under the License is distributed on an "AS IS" BASIS,
15+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
See the License for the specific language governing permissions and
17+
limitations under the License.
18+
*/
19+
20+
package logging
21+
22+
import (
23+
"fmt"
24+
"io"
25+
26+
"github.com/muesli/cancelreader"
27+
"golang.org/x/sys/unix"
28+
)
29+
30+
func waitIOClose(reader io.Reader) (chan struct{}, error) {
31+
closeIO := make(chan struct{})
32+
33+
file, ok := reader.(cancelreader.File)
34+
if !ok {
35+
return nil, fmt.Errorf("reader is not an cancelreader.File")
36+
}
37+
38+
kq, err := unix.Kqueue()
39+
if err != nil {
40+
return nil, fmt.Errorf("create kqueue: %w", err)
41+
}
42+
kev := unix.Kevent_t{
43+
Ident: uint64(file.Fd()),
44+
Filter: unix.EVFILT_READ,
45+
Flags: unix.EV_ADD | unix.EV_ENABLE,
46+
}
47+
48+
events := make([]unix.Kevent_t, 1)
49+
_, err = unix.Kevent(kq, []unix.Kevent_t{kev}, events, nil)
50+
if err != nil {
51+
return nil, err
52+
}
53+
go func() {
54+
for {
55+
n, err := unix.Kevent(kq, nil, events, nil)
56+
if err != nil {
57+
continue
58+
}
59+
for i := 0; i < n; i++ {
60+
if events[i].Flags&unix.EV_EOF != 0 {
61+
close(closeIO)
62+
break
63+
}
64+
}
65+
}
66+
}()
67+
return closeIO, nil
68+
}

pkg/logging/logging_linux.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//go:build linux
2+
// +build linux
3+
4+
/*
5+
Copyright The containerd Authors.
6+
7+
Licensed under the Apache License, Version 2.0 (the "License");
8+
you may not use this file except in compliance with the License.
9+
You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing, software
14+
distributed under the License is distributed on an "AS IS" BASIS,
15+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
See the License for the specific language governing permissions and
17+
limitations under the License.
18+
*/
19+
20+
package logging
21+
22+
import (
23+
"fmt"
24+
"io"
25+
26+
"github.com/muesli/cancelreader"
27+
"golang.org/x/sys/unix"
28+
)
29+
30+
func waitIOClose(reader io.Reader) (chan struct{}, error) {
31+
closeIO := make(chan struct{})
32+
epfd, err := unix.EpollCreate1(0)
33+
if err != nil {
34+
return nil, err
35+
}
36+
file, ok := reader.(cancelreader.File)
37+
if !ok {
38+
return nil, fmt.Errorf("reader is not an cancelreader.File")
39+
}
40+
fd := file.Fd()
41+
event := unix.EpollEvent{
42+
Events: unix.EPOLLHUP,
43+
Fd: int32(fd),
44+
}
45+
if err := unix.EpollCtl(epfd, unix.EPOLL_CTL_ADD, int(fd), &event); err != nil {
46+
return nil, err
47+
}
48+
events := make([]unix.EpollEvent, 1)
49+
go func() {
50+
for {
51+
n, err := unix.EpollWait(epfd, events, -1)
52+
if err != nil {
53+
continue
54+
}
55+
for i := 0; i < n; i++ {
56+
if events[i].Events&unix.EPOLLHUP != 0 {
57+
close(closeIO)
58+
break
59+
}
60+
}
61+
}
62+
}()
63+
return closeIO, nil
64+
}

pkg/logging/logging_test.go

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import (
2525
"testing"
2626
"time"
2727

28-
containerd "github.com/containerd/containerd/v2/client"
2928
"github.com/containerd/containerd/v2/core/runtime/v2/logging"
3029
)
3130

@@ -78,15 +77,7 @@ func TestLoggingProcessAdapter(t *testing.T) {
7877
// Execute the logging process adapter
7978
ctx, cancel := context.WithCancel(context.Background())
8079
defer cancel()
81-
82-
var getContainerWaitMock ContainerWaitFunc = func(ctx context.Context, address string, config *logging.Config) (<-chan containerd.ExitStatus, error) {
83-
exitChan := make(chan containerd.ExitStatus, 1)
84-
time.Sleep(50 * time.Millisecond)
85-
exitChan <- containerd.ExitStatus{}
86-
return exitChan, nil
87-
}
88-
89-
err := loggingProcessAdapter(ctx, driver, "testDataStore", "", getContainerWaitMock, config)
80+
err := loggingProcessAdapter(ctx, driver, "testDataStore", config)
9081
if err != nil {
9182
t.Fatal(err)
9283
}

pkg/logging/logging_windows.go

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

0 commit comments

Comments
 (0)