Skip to content
This repository was archived by the owner on Feb 8, 2021. It is now read-only.

Commit e7c86e3

Browse files
committed
Enable pod support
Share a pod with existing container, with `--net container:xxx`. Signed-off-by: Zhang Wei <zhangwei555@huawei.com>
1 parent b8fb9cc commit e7c86e3

5 files changed

Lines changed: 100 additions & 12 deletions

File tree

create.go

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"os"
77
"os/exec"
88
"path/filepath"
9+
"regexp"
910
"strconv"
1011
"strings"
1112
"syscall"
@@ -99,16 +100,25 @@ func runContainer(context *cli.Context, createOnly bool) error {
99100
sharedContainer = spec.Annotations["ocid/sandbox_name"]
100101
}
101102
} else {
102-
for _, ns := range spec.Linux.Namespaces {
103+
for i, ns := range spec.Linux.Namespaces {
103104
if ns.Path != "" {
104-
if strings.Contains(ns.Path, "/") {
105-
return fmt.Errorf("Runv doesn't support path to namespace file, it supports containers name as shared namespaces only")
106-
}
107105
if ns.Type == "mount" {
108106
// TODO support it!
109107
return fmt.Errorf("Runv doesn't support shared mount namespace currently")
110108
}
111-
sharedContainer = ns.Path
109+
if sharedContainer, err = findSharedContainer(context.GlobalString("root"), ns.Path); err != nil {
110+
return fmt.Errorf("failed to find shared container: %v", err)
111+
}
112+
113+
cstate, err := getContainer(context, sharedContainer)
114+
if err != nil {
115+
return fmt.Errorf("can't get state file for container %q: %v", sharedContainer, err)
116+
}
117+
spec.Linux.Namespaces[i] = specs.LinuxNamespace{
118+
Type: ns.Type,
119+
Path: fmt.Sprintf("/proc/%d/ns/%s", cstate.InitProcessPid, ns.Type),
120+
}
121+
112122
_, err = os.Stat(filepath.Join(root, sharedContainer, stateJson))
113123
if err != nil {
114124
return fmt.Errorf("The container %q is not existing or not ready", sharedContainer)
@@ -117,6 +127,10 @@ func runContainer(context *cli.Context, createOnly bool) error {
117127
if err != nil {
118128
return fmt.Errorf("The container %q is not ready", sharedContainer)
119129
}
130+
131+
if err = updateSpec(spec, ocffile); err != nil {
132+
return fmt.Errorf("update spec file failed: %v", err)
133+
}
120134
}
121135
}
122136
}
@@ -249,7 +263,7 @@ func createContainer(context *cli.Context, container, namespace string, config *
249263
return err
250264
}
251265

252-
return ociCreate(context, container, func(stdin, stdout, stderr string) (int, error) {
266+
return ociCreate(context, container, "init", func(stdin, stdout, stderr string) (int, error) {
253267
r := &types.CreateContainerRequest{
254268
Id: container,
255269
Runtime: "runv-create",
@@ -275,7 +289,7 @@ func createContainer(context *cli.Context, container, namespace string, config *
275289

276290
}
277291

278-
func ociCreate(context *cli.Context, container string, createFunc createFunction) error {
292+
func ociCreate(context *cli.Context, container, process string, createFunc createFunction) error {
279293
path, err := osext.Executable()
280294
if err != nil {
281295
return fmt.Errorf("cannot find self executable path for %s: %v\n", os.Args[0], err)
@@ -325,7 +339,7 @@ func ociCreate(context *cli.Context, container string, createFunc createFunction
325339
if context.GlobalBool("debug") {
326340
args = append(args, "--debug")
327341
}
328-
args = append(args, "shim", "--container", container, "--process", "init")
342+
args = append(args, "shim", "--container", container, "--process", process)
329343
if context.String("pid-file") != "" {
330344
args = append(args, "--proxy-exit-code", "--proxy-signal")
331345
}
@@ -352,6 +366,7 @@ func ociCreate(context *cli.Context, container string, createFunc createFunction
352366
return err
353367
}
354368
}
369+
355370
if context.String("pid-file") != "" {
356371
err = createPidFile(context.String("pid-file"), cmd.Process.Pid)
357372
if err != nil {
@@ -394,3 +409,37 @@ func retrieveNslPID(labels []string) int {
394409
}
395410
return -1
396411
}
412+
413+
func findSharedContainer(root, nsPath string) (container string, err error) {
414+
absRoot, err := filepath.Abs(root)
415+
if err != nil {
416+
return "", err
417+
}
418+
list, err := ioutil.ReadDir(absRoot)
419+
if err != nil {
420+
return "", err
421+
}
422+
423+
if strings.Contains(nsPath, "/") {
424+
pidexp := regexp.MustCompile(`/proc/(\d+)/ns/*`)
425+
matches := pidexp.FindStringSubmatch(nsPath)
426+
if len(matches) != 2 {
427+
return "", fmt.Errorf("malformed ns path: %s", nsPath)
428+
}
429+
pid := matches[1]
430+
431+
for _, item := range list {
432+
shimPidFile := filepath.Join(absRoot, item.Name(), "shim-init.pid")
433+
spidByte, err := ioutil.ReadFile(shimPidFile)
434+
if err != nil {
435+
return "", fmt.Errorf("failed to read shim pid file %q: %v", shimPidFile, err)
436+
}
437+
spid := strings.TrimSpace(string(spidByte))
438+
if pid == spid {
439+
return item.Name(), nil
440+
}
441+
}
442+
return "", fmt.Errorf("can't find container with shim pid %s", pid)
443+
}
444+
return nsPath, nil
445+
}

exec.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ func runProcess(context *cli.Context, container string, config *specs.Process) (
208208
monitorTtySize(c, container, process)
209209
}
210210

211-
err = ociCreate(context, container, func(stdin, stdout, stderr string) (int, error) {
211+
err = ociCreate(context, container, process, func(stdin, stdout, stderr string) (int, error) {
212212
p := &types.AddProcessRequest{
213213
Id: container,
214214
Pid: process,

list.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ in json format:
5050
},
5151
},
5252
Action: func(context *cli.Context) {
53-
s, err := getContainers(context)
53+
s, err := getContainers(context.GlobalString("root"))
5454
if err != nil {
5555
fatal(err)
5656
}
@@ -91,8 +91,7 @@ in json format:
9191
},
9292
}
9393

94-
func getContainers(context *cli.Context) ([]containerState, error) {
95-
root := context.GlobalString("root")
94+
func getContainers(root string) ([]containerState, error) {
9695
absRoot, err := filepath.Abs(root)
9796
if err != nil {
9897
return nil, err

shim.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,26 @@ var shimCommand = cli.Command{
6565
defer signal.Stop(sigc)
6666
}
6767

68+
stateDir := filepath.Join(root, container)
69+
if _, err = os.Stat(stateDir); err == nil {
70+
// state dir exist, write shim pid into it
71+
shimFile := filepath.Join(stateDir, "shim-"+process+".pid")
72+
f, err := os.OpenFile(shimFile, os.O_WRONLY|os.O_CREATE, 0640)
73+
if err != nil {
74+
glog.Errorf("can't create shim pid file: %v", err)
75+
goto eventHandle
76+
}
77+
defer f.Close()
78+
shimPid := fmt.Sprintf("%d", os.Getpid())
79+
_, err = f.Write([]byte(shimPid))
80+
if err != nil {
81+
glog.Errorf("can't write pid %q to shim pid file: %v", shimPid, err)
82+
goto eventHandle
83+
}
84+
defer os.Remove(shimFile)
85+
}
86+
87+
eventHandle:
6888
// wait until exit
6989
evChan := containerEvents(c, container)
7090
for e := range evChan {

spec.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,23 @@ func loadSpec(ocffile string) (*specs.Spec, error) {
103103
}
104104
return &spec, nil
105105
}
106+
107+
func updateSpec(spec *specs.Spec, ocffile string) error {
108+
if _, err := os.Stat(ocffile); err != nil {
109+
if os.IsNotExist(err) {
110+
return fmt.Errorf("%q doesn't exists", ocffile)
111+
}
112+
return fmt.Errorf("Stat %q error: %v", ocffile, err)
113+
}
114+
115+
data, err := json.Marshal(spec)
116+
if err != nil {
117+
return fmt.Errorf("failed to marshal spec file during update: %v", err)
118+
}
119+
120+
if err = ioutil.WriteFile(ocffile, data, 0640); err != nil {
121+
return err
122+
}
123+
124+
return nil
125+
}

0 commit comments

Comments
 (0)