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+ }
0 commit comments