// deletePod cleans up files and resource associated with the pod // pod must be under exclusive lock and be in either ExitedGarbage // or Garbage state func deletePod(p *pod) { if !p.isExitedGarbage && !p.isGarbage { panic(fmt.Sprintf("logic error: deletePod called with non-garbage pod %q (status %q)", p.uuid, p.getState())) } if p.isExitedGarbage { s, err := store.NewStore(getDataDir()) if err != nil { stderr("Cannot open store: %v", err) return } defer s.Close() stage1TreeStoreID, err := p.getStage1TreeStoreID() if err != nil { stderr("Error getting stage1 treeStoreID: %v", err) return } stage1RootFS := s.GetTreeStoreRootFS(stage1TreeStoreID) // execute stage1's GC if err := stage0.GC(p.path(), p.uuid, stage1RootFS, globalFlags.Debug); err != nil { stderr("Stage1 GC of pod %q failed: %v", p.uuid, err) return } if p.usesOverlay() { apps, err := p.getApps() if err != nil { stderr("Error retrieving app hashes from pod manifest: %v", err) return } for _, a := range apps { dest := filepath.Join(common.AppPath(p.path(), a.Name), "rootfs") if err := syscall.Unmount(dest, 0); err != nil { // machine could have been rebooted and mounts lost. // ignore "does not exist" and "not a mount point" errors if err != syscall.ENOENT && err != syscall.EINVAL { stderr("Error unmounting app at %v: %v", dest, err) } } } s1 := filepath.Join(common.Stage1ImagePath(p.path()), "rootfs") if err := syscall.Unmount(s1, 0); err != nil { // machine could have been rebooted and mounts lost. // ignore "does not exist" and "not a mount point" errors if err != syscall.ENOENT && err != syscall.EINVAL { stderr("Error unmounting stage1 at %v: %v", s1, err) return } } } } if err := os.RemoveAll(p.path()); err != nil { stderr("Unable to remove pod %q: %v", p.uuid, err) } }
// deletePod cleans up files and resource associated with the pod // pod must be under exclusive lock and be in either ExitedGarbage // or Garbage state func deletePod(p *pkgPod.Pod) { podState := p.State() if podState != pkgPod.ExitedGarbage && podState != pkgPod.Garbage { stderr.Panicf("logic error: deletePod called with non-garbage pod %q (status %q)", p.UUID, p.State()) } if podState == pkgPod.ExitedGarbage { s, err := imagestore.NewStore(storeDir()) if err != nil { stderr.PrintE("cannot open store", err) return } defer s.Close() ts, err := treestore.NewStore(treeStoreDir(), s) if err != nil { stderr.PrintE("cannot open store", err) return } if globalFlags.Debug { stage0.InitDebug() } if err := mountPodStage1(ts, p); err == nil { if err = stage0.GC(p.Path(), p.UUID); err != nil { stderr.PrintE(fmt.Sprintf("problem performing stage1 GC on %q", p.UUID), err) } // an overlay fs can be mounted over itself, let's unmount it here // if we mounted it before to avoid problems when running // stage0.MountGC if p.UsesOverlay() { stage1Mnt := common.Stage1RootfsPath(p.Path()) if err := syscall.Unmount(stage1Mnt, 0); err != nil { stderr.PrintE("error unmounting stage1", err) } } } else { stderr.PrintE("skipping stage1 GC", err) } // unmount all leftover mounts if err := stage0.MountGC(p.Path(), p.UUID.String()); err != nil { stderr.PrintE(fmt.Sprintf("GC of leftover mounts for pod %q failed", p.UUID), err) return } } if err := os.RemoveAll(p.Path()); err != nil { stderr.PrintE(fmt.Sprintf("unable to remove pod %q", p.UUID), err) os.Exit(254) } }
// emptyExitedGarbage discards sufficiently aged pods from exitedGarbageDir() func emptyExitedGarbage(gracePeriod time.Duration) error { if err := walkPods(includeExitedGarbageDir, func(p *pod) { gp := p.path() st := &syscall.Stat_t{} if err := syscall.Lstat(gp, st); err != nil { if err != syscall.ENOENT { stderr("Unable to stat %q, ignoring: %v", gp, err) } return } if expiration := time.Unix(st.Ctim.Unix()).Add(gracePeriod); time.Now().After(expiration) { if err := p.ExclusiveLock(); err != nil { return } stdout("Garbage collecting pod %q", p.uuid) s, err := store.NewStore(globalFlags.Dir) if err != nil { stderr("Cannot open store: %v", err) return } stage1ID, err := p.getStage1Hash() if err != nil { stderr("Error getting stage1 hash") return } stage1RootFS := s.GetTreeStoreRootFS(stage1ID.String()) // execute stage1's GC if err := stage0.GC(p.path(), p.uuid, stage1RootFS, globalFlags.Debug); err != nil { stderr("Stage1 GC of pod %q failed: %v", p.uuid, err) return } if err := os.RemoveAll(gp); err != nil { stderr("Unable to remove pod %q: %v", p.uuid, err) } } }); err != nil { return err } return nil }
// deletePod cleans up files and resource associated with the pod // pod must be under exclusive lock and be in either ExitedGarbage // or Garbage state func deletePod(p *pod) { if !p.isExitedGarbage && !p.isGarbage { stderr.Panicf("logic error: deletePod called with non-garbage pod %q (status %q)", p.uuid, p.getState()) } if p.isExitedGarbage { s, err := store.NewStore(getDataDir()) if err != nil { stderr.PrintE("cannot open store", err) return } defer s.Close() // execute stage1's GC stage1TreeStoreID, err := p.getStage1TreeStoreID() if err != nil { stderr.PrintE("error getting stage1 treeStoreID", err) stderr.Print("skipping stage1 GC") } else { if globalFlags.Debug { stage0.InitDebug() } stage1RootFS := s.GetTreeStoreRootFS(stage1TreeStoreID) if err = stage0.GC(p.path(), p.uuid, stage1RootFS); err != nil { stderr.PrintE(fmt.Sprintf("problem performing stage1 GC on %q", p.uuid), err) } } // unmount all leftover mounts if err := stage0.MountGC(p.path(), p.uuid.String()); err != nil { stderr.PrintE(fmt.Sprintf("GC of leftover mounts for pod %q failed", p.uuid), err) return } } if err := os.RemoveAll(p.path()); err != nil { stderr.PrintE(fmt.Sprintf("unable to remove pod %q", p.uuid), err) os.Exit(1) } }
// deletePod cleans up files and resource associated with the pod // pod must be under exclusive lock and be in either ExitedGarbage // or Garbage state func deletePod(p *pod) { if !p.isExitedGarbage && !p.isGarbage { panic(fmt.Sprintf("Logic error: deletePod called with non-garbage pod %q (status %q)", p.uuid, p.getState())) } if p.isExitedGarbage { s, err := store.NewStore(getDataDir()) if err != nil { stderr("Cannot open store: %v", err) return } defer s.Close() // execute stage1's GC stage1TreeStoreID, err := p.getStage1TreeStoreID() if err != nil { stderr("Error getting stage1 treeStoreID: %v", err) stderr("Skipping stage1 GC") } else { stage1RootFS := s.GetTreeStoreRootFS(stage1TreeStoreID) if err = stage0.GC(p.path(), p.uuid, stage1RootFS, globalFlags.Debug); err != nil { stderr("Problem performing stage1 GC on %q: %v", p.uuid, err) } } // unmount all leftover mounts if err := stage0.MountGC(p.path(), p.uuid.String()); err != nil { stderr("GC of leftover mounts for pod %q failed: %v\n", p.uuid, err) return } } if err := os.RemoveAll(p.path()); err != nil { stderr("Unable to remove pod %q: %v", p.uuid, err) os.Exit(1) } }
// emptyExitedGarbage discards sufficiently aged pods from exitedGarbageDir() func emptyExitedGarbage(gracePeriod time.Duration) error { if err := walkPods(includeExitedGarbageDir, func(p *pod) { gp := p.path() st := &syscall.Stat_t{} if err := syscall.Lstat(gp, st); err != nil { if err != syscall.ENOENT { stderr("Unable to stat %q, ignoring: %v", gp, err) } return } if expiration := time.Unix(st.Ctim.Unix()).Add(gracePeriod); time.Now().After(expiration) { if err := p.ExclusiveLock(); err != nil { return } stdout("Garbage collecting pod %q", p.uuid) s, err := store.NewStore(globalFlags.Dir) if err != nil { stderr("Cannot open store: %v", err) return } stage1ID, err := p.getStage1Hash() if err != nil { stderr("Error getting stage1 hash") return } stage1RootFS := s.GetTreeStoreRootFS(stage1ID.String()) if p.usesOverlay() { apps, err := p.getAppsHashes() if err != nil { stderr("Error retrieving app hashes from pod manifest: %v", err) return } for _, a := range apps { dest := filepath.Join(common.AppImagePath(p.path(), a), "rootfs") if err := syscall.Unmount(dest, 0); err != nil { // machine could have been rebooted and mounts lost. // ignore "does not exist" and "not a mount point" errors if err != syscall.ENOENT && err != syscall.EINVAL { stderr("Error unmounting app at %v: %v", dest, err) } } } s1 := filepath.Join(common.Stage1ImagePath(p.path()), "rootfs") if err := syscall.Unmount(s1, 0); err != nil { // machine could have been rebooted and mounts lost. // ignore "does not exist" and "not a mount point" errors if err != syscall.ENOENT && err != syscall.EINVAL { stderr("Error unmounting stage1 at %v: %v", s1, err) return } } } // execute stage1's GC if err := stage0.GC(p.path(), p.uuid, stage1RootFS, globalFlags.Debug); err != nil { stderr("Stage1 GC of pod %q failed: %v", p.uuid, err) return } if err := os.RemoveAll(gp); err != nil { stderr("Unable to remove pod %q: %v", p.uuid, err) } } }); err != nil { return err } return nil }