func getPodDefaultIP(workDir string) (string, error) { // get pod lock l, err := lock.NewLock(workDir, lock.Dir) if err != nil { return "", err } // get file descriptor for lock fd, err := l.Fd() if err != nil { return "", err } // use this descriptor as method of reading pod network configuration nets, err := netinfo.LoadAt(fd) if err != nil { return "", err } // kvm flavored container must have at first position default vm<->host network if len(nets) == 0 { return "", fmt.Errorf("pod has no configured networks") } for _, net := range nets { if net.NetName == "default" || net.NetName == "default-restricted" { return net.IP.String(), nil } } return "", fmt.Errorf("pod has no default network!") }
/* * NewNetPreserveNetNameTest checks if netName is set if network is configured via flannel */ func NewNetPreserveNetNameTest() testutils.Test { return testutils.TestFunc(func(t *testing.T) { ctx := testutils.NewRktRunCtx() defer ctx.Cleanup() netdir, ntFlannel, err := mockFlannelNetwork(t, ctx) if err != nil { t.Errorf("Can't mock flannel network: %v", err) } defer os.RemoveAll(netdir) defer os.Remove(ntFlannel.SubnetFile) podUUIDFile := filepath.Join(ctx.DataDir(), "pod_uuid") defer os.Remove(podUUIDFile) // start container with 'flannel' network testImageArgs := []string{"--exec=/inspect"} testImage := patchTestACI("rkt-inspect-networking.aci", testImageArgs...) defer os.Remove(testImage) cmd := fmt.Sprintf("%s --debug --insecure-options=image run --uuid-file-save=%s --net=%s --mds-register=false %s", ctx.Cmd(), podUUIDFile, ntFlannel.Name, testImage) spawnAndWaitOrFail(t, cmd, 0) podUUID, err := ioutil.ReadFile(podUUIDFile) if err != nil { t.Fatalf("Can't read pod UUID: %v", err) } // read net-info.json created for pod podDir := filepath.Join(ctx.DataDir(), "pods", "run", string(podUUID)) podDirfd, err := syscall.Open(podDir, syscall.O_RDONLY|syscall.O_DIRECTORY, 0) if err != nil { t.Fatalf("Can't open pod directory for reading! %v", err) } info, err := netinfo.LoadAt(podDirfd) if err != nil { t.Fatalf("Can't open net-info.json for reading: %v", err) } if len(info) != 2 { t.Fatalf("Incorrect number of networks: %v", len(info)) } found := false for _, net := range info { if net.NetName == ntFlannel.Name { found = true break } } if !found { t.Fatalf("Network '%s' not found!\nnetInfo[0]: %v\nnetInfo[1]: %v", ntFlannel.Name, info[0], info[1]) } }) }
// Load creates the Networking object from saved state. // Assumes the current netns is that of the host. func Load(podRoot string, podID *types.UUID) (*Networking, error) { // the current directory is pod root pdirfd, err := syscall.Open(podRoot, syscall.O_RDONLY|syscall.O_DIRECTORY, 0) if err != nil { return nil, errwrap.Wrap(fmt.Errorf("failed to open pod root directory (%v)", podRoot), err) } defer syscall.Close(pdirfd) nis, err := netinfo.LoadAt(pdirfd) if err != nil { return nil, err } var nets []activeNet for _, ni := range nis { n, err := loadNet(ni.ConfPath) if err != nil { if !os.IsNotExist(err) { stderr.PrintE(fmt.Sprintf("error loading %q; ignoring", ni.ConfPath), err) } continue } // make a copy of ni to make it a unique object as it's saved via ptr rti := ni n.runtime = &rti nets = append(nets, *n) } p := podEnv{ podRoot: podRoot, podID: *podID, } podNS, err := p.podNSLoad() if err != nil { return nil, err } p.podNS = podNS return &Networking{ podEnv: p, nets: nets, }, nil }
// Load creates the Networking object from saved state. // Assumes the current netns is that of the host. func Load(podRoot string, podID *types.UUID) (*Networking, error) { // the current directory is pod root pdirfd, err := syscall.Open(podRoot, syscall.O_RDONLY|syscall.O_DIRECTORY, 0) if err != nil { return nil, fmt.Errorf("Failed to open pod root directory (%v): %v", podRoot, err) } defer syscall.Close(pdirfd) nis, err := netinfo.LoadAt(pdirfd) if err != nil { return nil, err } hostNS, err := os.Open(selfNetNS) if err != nil { return nil, err } nets := []activeNet{} for _, ni := range nis { n, err := loadNet(ni.ConfPath) if err != nil { if !os.IsNotExist(err) { log.Printf("Error loading %q: %v; ignoring", ni.ConfPath, err) } continue } // make a copy of ni to make it a unique object as it's saved via ptr rti := ni nets = append(nets, activeNet{ conf: n.conf, runtime: &rti, }) } return &Networking{ podEnv: podEnv{ podRoot: podRoot, podID: *podID, }, hostNS: hostNS, nets: nets, }, nil }
// getPod returns a pod struct representing the given pod. // The returned lock is always left in an open but unlocked state. // The pod must be closed using pod.Close() func getPod(uuid *types.UUID) (*pod, error) { if err := initPods(); err != nil { return nil, err } p := &pod{uuid: uuid} // we try open the pod in all possible directories, in the same order the states occur l, err := lock.NewLock(p.embryoPath(), lock.Dir) if err == nil { p.isEmbryo = true } else if err == lock.ErrNotExist { l, err = lock.NewLock(p.preparePath(), lock.Dir) if err == nil { // treat as aborted prepare until lock is tested p.isAbortedPrepare = true } else if err == lock.ErrNotExist { l, err = lock.NewLock(p.preparedPath(), lock.Dir) if err == nil { p.isPrepared = true } else if err == lock.ErrNotExist { l, err = lock.NewLock(p.runPath(), lock.Dir) if err == nil { // treat as exited until lock is tested p.isExited = true } else if err == lock.ErrNotExist { l, err = lock.NewLock(p.exitedGarbagePath(), lock.Dir) if err == lock.ErrNotExist { l, err = lock.NewLock(p.garbagePath(), lock.Dir) if err == nil { p.isGarbage = true } else { return nil, fmt.Errorf("pod %q not found", uuid) } } else if err == nil { p.isExitedGarbage = true p.isExited = true // ExitedGarbage is _always_ implicitly exited } } } } } if err != nil && err != lock.ErrNotExist { return nil, errwrap.Wrap(fmt.Errorf("error opening pod %q", uuid), err) } if !p.isPrepared && !p.isEmbryo { // preparing, run, exitedGarbage, and garbage dirs use exclusive locks to indicate preparing/aborted, running/exited, and deleting/marked if err = l.TrySharedLock(); err != nil { if err != lock.ErrLocked { l.Close() return nil, errwrap.Wrap(errors.New("unexpected lock error"), err) } if p.isExitedGarbage { // locked exitedGarbage is also being deleted p.isExitedDeleting = true } else if p.isExited { // locked exited and !exitedGarbage is not exited (default in the run dir) p.isExited = false } else if p.isAbortedPrepare { // locked in preparing is preparing, not aborted (default in the preparing dir) p.isAbortedPrepare = false p.isPreparing = true } else if p.isGarbage { // locked in non-exited garbage is deleting p.isDeleting = true } err = nil } else { l.Unlock() } } p.FileLock = l if p.isRunning() { cfd, err := p.Fd() if err != nil { return nil, errwrap.Wrap(fmt.Errorf("error acquiring pod %v dir fd", uuid), err) } p.nets, err = netinfo.LoadAt(cfd) // ENOENT is ok -- assume running with --net=host if err != nil && !os.IsNotExist(err) { return nil, errwrap.Wrap(fmt.Errorf("error opening pod %v netinfo", uuid), err) } } return p, nil }
// getPod returns a pod struct representing the given pod. // The returned lock is always left in an open but unlocked state. // The pod must be closed using pod.Close() func getPod(dataDir string, uuid *types.UUID) (*Pod, error) { if err := initPods(dataDir); err != nil { return nil, err } p := &Pod{UUID: uuid, dataDir: dataDir} // dirStates is a list of directories -> state that directory existing // implies. // Its order matches the order states occur. dirStates := []struct { dir string impliedStates []*bool }{ {dir: p.embryoPath(), impliedStates: []*bool{&p.isEmbryo}}, // For prepare, assume it's aborted prepare until it gets updated below {dir: p.preparePath(), impliedStates: []*bool{&p.isAbortedPrepare}}, {dir: p.preparedPath(), impliedStates: []*bool{&p.isPrepared}}, // For run, assume exited until the lock is tested {dir: p.runPath(), impliedStates: []*bool{&p.isExited}}, // Exited garbage implies exited {dir: p.exitedGarbagePath(), impliedStates: []*bool{&p.isExitedGarbage, &p.isExited}}, {dir: p.garbagePath(), impliedStates: []*bool{&p.isGarbage}}, } var l *lock.FileLock var err error for _, dirState := range dirStates { l, err = lock.NewLock(dirState.dir, lock.Dir) if err == nil { for _, s := range dirState.impliedStates { *s = true } break } if err == lock.ErrNotExist { continue } // unexpected lock error return nil, errwrap.Wrap(fmt.Errorf("error opening pod %q", uuid), err) } if !p.isPrepared && !p.isEmbryo { // preparing, run, exitedGarbage, and garbage dirs use exclusive locks to indicate preparing/aborted, running/exited, and deleting/marked if err = l.TrySharedLock(); err != nil { if err != lock.ErrLocked { l.Close() return nil, errwrap.Wrap(errors.New("unexpected lock error"), err) } if p.isExitedGarbage { // locked exitedGarbage is also being deleted p.isExitedDeleting = true } else if p.isExited { // locked exited and !exitedGarbage is not exited (default in the run dir) p.isExited = false } else if p.isAbortedPrepare { // locked in preparing is preparing, not aborted (default in the preparing dir) p.isAbortedPrepare = false p.isPreparing = true } else if p.isGarbage { // locked in non-exited garbage is deleting p.isDeleting = true } err = nil } else { l.Unlock() } } p.FileLock = l if p.isRunning() { cfd, err := p.Fd() if err != nil { return nil, errwrap.Wrap(fmt.Errorf("error acquiring pod %v dir fd", uuid), err) } p.Nets, err = netinfo.LoadAt(cfd) // ENOENT is ok -- assume running with --net=host if err != nil && !os.IsNotExist(err) { return nil, errwrap.Wrap(fmt.Errorf("error opening pod %v netinfo", uuid), err) } } return p, nil }