Example #1
0
func getPodManifestModTime(p *pkgPod.Pod) (time.Time, error) {
	podFile := filepath.Join(p.Path(), "pod")
	fi, err := os.Stat(podFile)
	if err != nil {
		return time.Time{}, err
	}
	return fi.ModTime(), nil
}
Example #2
0
File: gc.go Project: nhlfr/rkt
// 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)
	}
}
Example #3
0
// getPodCgroup gets the cgroup path for a pod. This can be done in one of a couple ways:
//
// 1) stage1-coreos
//
// This one can be tricky because after machined registration, the cgroup might change.
// For these flavors, the cgroup it will end up in after machined moves it is
// written to a file named `subcgroup`, so we use that instead.
//
// 2) All others
//
// Assume that we can simply get the cgroup of the pod's init PID, and use that.
func getPodCgroup(p *pkgPod.Pod, pid int) (string, error) {
	// Note, this file should always exist if the pid is known since it is
	// written before the pid file
	// The contents are of the form:
	// machined-registration (whether it has happened or not, but if stage1 plans to do so):
	//   'machine.slice/machine-rkt\x2dbfb67ff1\x2dc745\x2d4aec\x2db1e1\x2d7ce85a1fd42b.scope'
	// no registration, ran as systemd-unit 'foo.service':
	//   'system.slice/foo.service'
	// stage1-fly: file does not exist
	subCgroupFile := filepath.Join(p.Path(), "subcgroup")
	data, err := ioutil.ReadFile(subCgroupFile)
	// normalize cgroup to include a leading '/'
	if err == nil {
		strCgroup := string(data)
		if strings.HasPrefix(strCgroup, "/") {
			return strCgroup, nil
		}
		return "/" + strCgroup, nil
	}

	if !os.IsNotExist(err) {
		return "", err
	}
	// if it is an "isNotExist", assume this is a stage1 flavor that won't change
	// cgroups. Just give the systemd cgroup of its pid
	// Get cgroup for the "name=systemd" controller; we assume the api-server is
	// running on a system using systemd for returning cgroups, and will just not
	// set it otherwise.
	cgroup, err := v1.GetCgroupPathByPid(pid, "name=systemd")
	if err != nil {
		return "", err
	}
	// If the stage1 systemd > v226, it will put the PID1 into "init.scope"
	// implicit scope unit in the root slice.
	// See https://github.com/coreos/rkt/pull/2331#issuecomment-203540543
	//
	// TODO(yifan): Revisit this when using unified cgroup hierarchy.
	cgroup = strings.TrimSuffix(cgroup, "/init.scope")
	return cgroup, nil
}
Example #4
0
File: export.go Project: nhlfr/rkt
// mountOverlay mounts the app from the overlay-rendered pod to the destination directory.
func mountOverlay(pod *pkgPod.Pod, app *schema.RuntimeApp, dest string) error {
	if _, err := os.Stat(dest); err != nil {
		return err
	}

	s, err := imagestore.NewStore(getDataDir())
	if err != nil {
		return errwrap.Wrap(errors.New("cannot open store"), err)
	}

	ts, err := treestore.NewStore(treeStoreDir(), s)
	if err != nil {
		return errwrap.Wrap(errors.New("cannot open treestore"), err)
	}

	treeStoreID, err := pod.GetAppTreeStoreID(app.Name)
	if err != nil {
		return err
	}
	lower := ts.GetRootFS(treeStoreID)
	imgDir := filepath.Join(filepath.Join(pod.Path(), "overlay"), treeStoreID)
	if _, err := os.Stat(imgDir); err != nil {
		return err
	}
	upper := filepath.Join(imgDir, "upper", app.Name.String())
	if _, err := os.Stat(upper); err != nil {
		return err
	}
	work := filepath.Join(imgDir, "work", app.Name.String())
	if _, err := os.Stat(work); err != nil {
		return err
	}

	if err := overlay.Mount(&overlay.MountCfg{lower, upper, work, dest, ""}); err != nil {
		return errwrap.Wrap(errors.New("problem mounting overlayfs directory"), err)
	}

	return nil
}
Example #5
0
File: gc.go Project: nhlfr/rkt
func mountPodStage1(ts *treestore.Store, p *pkgPod.Pod) error {
	if !p.UsesOverlay() {
		return nil
	}

	s1Id, err := p.GetStage1TreeStoreID()
	if err != nil {
		return errwrap.Wrap(errors.New("error getting stage1 treeStoreID"), err)
	}
	s1rootfs := ts.GetRootFS(s1Id)

	stage1Dir := common.Stage1RootfsPath(p.Path())
	overlayDir := filepath.Join(p.Path(), "overlay")
	imgDir := filepath.Join(overlayDir, s1Id)
	upperDir := filepath.Join(imgDir, "upper")
	workDir := filepath.Join(imgDir, "work")

	opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", s1rootfs, upperDir, workDir)
	if err := syscall.Mount("overlay", stage1Dir, "overlay", 0, opts); err != nil {
		return errwrap.Wrap(errors.New("error mounting stage1"), err)
	}

	return nil
}
Example #6
0
File: app.go Project: kinvolk/rkt
func appState(app *App, pod *pkgPod.Pod) error {
	app.State = AppStateUnknown

	defer func() {
		if pod.IsAfterRun() {
			// If the pod is hard killed, set the app to 'exited' state.
			// Other than this case, status file is guaranteed to be written.
			if app.State != AppStateExited {
				app.State = AppStateExited
				t, err := pod.GCMarkedTime()
				if err != nil {
					fmt.Fprintf(os.Stderr, "Cannot get GC marked time: %v", err)
				}
				if !t.IsZero() {
					finishedAt := t.UnixNano()
					app.FinishedAt = &finishedAt
				}
			}
		}
	}()

	// Check if the app is created.
	fi, err := os.Stat(common.AppCreatedPath(pod.Path(), app.Name))
	if err != nil {
		if !os.IsNotExist(err) {
			return fmt.Errorf("cannot stat app creation file: %v", err)
		}
		return nil
	}

	app.State = AppStateCreated
	createdAt := fi.ModTime().UnixNano()
	app.CreatedAt = &createdAt

	// Check if the app is started.
	fi, err = os.Stat(common.AppStartedPath(pod.Path(), app.Name))
	if err != nil {
		if !os.IsNotExist(err) {
			return fmt.Errorf("cannot stat app started file: %v", err)
		}
		return nil
	}

	app.State = AppStateRunning
	startedAt := fi.ModTime().UnixNano()
	app.StartedAt = &startedAt

	// Check if the app is exited.
	appStatusFile := common.AppStatusPath(pod.Path(), app.Name)
	fi, err = os.Stat(appStatusFile)
	if err != nil {
		if !os.IsNotExist(err) {
			return fmt.Errorf("cannot stat app exited file: %v", err)
		}
		return nil
	}

	app.State = AppStateExited
	finishedAt := fi.ModTime().UnixNano()
	app.FinishedAt = &finishedAt

	// Read exit code.
	exitCode, err := readExitCode(appStatusFile)
	if err != nil {
		return err
	}
	app.ExitCode = &exitCode

	return nil
}