Example #1
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 #2
0
// NewPodFromInternalPod converts *pkgPod.Pod to *Pod
func NewPodFromInternalPod(p *pkgPod.Pod) (*Pod, error) {
	pod := &Pod{
		UUID:     p.UUID.String(),
		State:    p.State(),
		Networks: p.Nets,
	}

	startTime, err := p.StartTime()
	if err != nil {
		return nil, err
	}

	if !startTime.IsZero() {
		startedAt := startTime.Unix()
		pod.StartedAt = &startedAt
	}

	if !p.PodManifestAvailable() {
		return pod, nil
	}
	// TODO(vc): we should really hold a shared lock here to prevent gc of the pod
	_, manifest, err := p.PodManifest()
	if err != nil {
		return nil, err
	}

	for _, app := range manifest.Apps {
		pod.AppNames = append(pod.AppNames, app.Name.String())
	}

	if len(manifest.UserAnnotations) > 0 {
		pod.UserAnnotations = make(map[string]string)
		for name, value := range manifest.UserAnnotations {
			pod.UserAnnotations[name] = value
		}
	}

	if len(manifest.UserLabels) > 0 {
		pod.UserLabels = make(map[string]string)
		for name, value := range manifest.UserLabels {
			pod.UserLabels[name] = value
		}
	}

	return pod, nil
}
Example #3
0
// fillPodDetails fills the v1pod's dynamic info in place, e.g. the pod's state,
// the pod's network info, the apps' state, etc. Such information can change
// during the lifecycle of the pod, so we need to read it in every request.
func fillPodDetails(store *imagestore.Store, p *pkgPod.Pod, v1pod *v1alpha.Pod) {
	v1pod.Pid = -1

	switch p.State() {
	case pkgPod.Embryo:
		v1pod.State = v1alpha.PodState_POD_STATE_EMBRYO
		// When a pod is in embryo state, there is not much
		// information to return.
		return
	case pkgPod.Preparing:
		v1pod.State = v1alpha.PodState_POD_STATE_PREPARING
	case pkgPod.AbortedPrepare:
		v1pod.State = v1alpha.PodState_POD_STATE_ABORTED_PREPARE
	case pkgPod.Prepared:
		v1pod.State = v1alpha.PodState_POD_STATE_PREPARED
	case pkgPod.Running:
		v1pod.State = v1alpha.PodState_POD_STATE_RUNNING
		v1pod.Networks = getNetworks(p)
	case pkgPod.Deleting:
		v1pod.State = v1alpha.PodState_POD_STATE_DELETING
	case pkgPod.Exited:
		v1pod.State = v1alpha.PodState_POD_STATE_EXITED
	case pkgPod.Garbage, pkgPod.ExitedGarbage:
		v1pod.State = v1alpha.PodState_POD_STATE_GARBAGE
	default:
		v1pod.State = v1alpha.PodState_POD_STATE_UNDEFINED
		return
	}

	createdAt, err := p.CreationTime()
	if err != nil {
		stderr.PrintE(fmt.Sprintf("failed to get the creation time for pod %q", p.UUID), err)
	} else if !createdAt.IsZero() {
		v1pod.CreatedAt = createdAt.UnixNano()
	}

	startedAt, err := p.StartTime()
	if err != nil {
		stderr.PrintE(fmt.Sprintf("failed to get the start time for pod %q", p.UUID), err)
	} else if !startedAt.IsZero() {
		v1pod.StartedAt = startedAt.UnixNano()

	}

	gcMarkedAt, err := p.GCMarkedTime()
	if err != nil {
		stderr.PrintE(fmt.Sprintf("failed to get the gc marked time for pod %q", p.UUID), err)
	} else if !gcMarkedAt.IsZero() {
		v1pod.GcMarkedAt = gcMarkedAt.UnixNano()
	}

	pid, err := p.Pid()
	if err != nil {
		stderr.PrintE(fmt.Sprintf("failed to get the PID for pod %q", p.UUID), err)
	} else {
		v1pod.Pid = int32(pid)
	}

	if v1pod.State == v1alpha.PodState_POD_STATE_RUNNING {
		pid, err := p.ContainerPid1()
		if err != nil {
			stderr.PrintE(fmt.Sprintf("failed to get the container PID1 for pod %q", p.UUID), err)
		} else {
			cgroup, err := getPodCgroup(p, pid)
			if err != nil {
				stderr.PrintE(fmt.Sprintf("failed to get the cgroup path for pod %q", p.UUID), err)
			} else {
				v1pod.Cgroup = cgroup
			}
		}
	}

	for _, app := range v1pod.Apps {
		readStatus := false

		if p.State() == pkgPod.Running {
			readStatus = true
			app.State = v1alpha.AppState_APP_STATE_RUNNING
		} else if p.AfterRun() {
			readStatus = true
			app.State = v1alpha.AppState_APP_STATE_EXITED
		} else {
			app.State = v1alpha.AppState_APP_STATE_UNDEFINED
		}

		if readStatus {
			exitCode, err := p.AppExitCode(app.Name)
			if err != nil {
				stderr.PrintE(fmt.Sprintf("failed to read status for app %q", app.Name), err)
			}
			app.ExitCode = int32(exitCode)
		}
	}
}
Example #4
0
// printStatus prints the pod's pid and per-app status codes
func printStatus(p *pkgPod.Pod) error {
	if flagFormat != outputFormatTabbed {
		pod, err := lib.NewPodFromInternalPod(p)
		if err != nil {
			return fmt.Errorf("error converting pod: %v", err)
		}
		switch flagFormat {
		case outputFormatJSON:
			result, err := json.Marshal(pod)
			if err != nil {
				return fmt.Errorf("error marshaling the pod: %v", err)
			}
			stdout.Print(string(result))
		case outputFormatPrettyJSON:
			result, err := json.MarshalIndent(pod, "", "\t")
			if err != nil {
				return fmt.Errorf("error marshaling the pod: %v", err)
			}
			stdout.Print(string(result))
		}
		return nil
	}

	state := p.State()
	stdout.Printf("state=%s", state)

	created, err := p.CreationTime()
	if err != nil {
		return fmt.Errorf("unable to get creation time for pod %q: %v", p.UUID, err)
	}
	createdStr := created.Format(defaultTimeLayout)

	stdout.Printf("created=%s", createdStr)

	started, err := p.StartTime()
	if err != nil {
		return fmt.Errorf("unable to get start time for pod %q: %v", p.UUID, err)
	}
	var startedStr string
	if !started.IsZero() {
		startedStr = started.Format(defaultTimeLayout)
		stdout.Printf("started=%s", startedStr)
	}

	if state == pkgPod.Running {
		stdout.Printf("networks=%s", fmtNets(p.Nets))
	}

	if state == pkgPod.Running || state == pkgPod.Deleting || state == pkgPod.ExitedDeleting || state == pkgPod.Exited || state == pkgPod.ExitedGarbage {
		var pid int
		pidCh := make(chan int, 1)

		// Wait slightly because the pid file might not be written yet when the state changes to 'Running'.
		go func() {
			for {
				pid, err := p.Pid()
				if err == nil {
					pidCh <- pid
					return
				}
				time.Sleep(time.Millisecond * 100)
			}
		}()

		select {
		case pid = <-pidCh:
		case <-time.After(time.Second):
			return fmt.Errorf("unable to get PID for pod %q: %v", p.UUID, err)
		}

		stdout.Printf("pid=%d\nexited=%t", pid, (state == pkgPod.Exited || state == pkgPod.ExitedGarbage))

		if state != pkgPod.Running {
			stats, err := getExitStatuses(p)
			if err != nil {
				return fmt.Errorf("unable to get exit statuses for pod %q: %v", p.UUID, err)
			}
			for app, stat := range stats {
				stdout.Printf("app-%s=%d", app, stat)
			}
		}
	}
	return nil
}
Example #5
0
File: status.go Project: nhlfr/rkt
// printStatus prints the pod's pid and per-app status codes
func printStatus(p *pkgPod.Pod) error {
	state := p.State()
	stdout.Printf("state=%s", state)

	created, err := p.CreationTime()
	if err != nil {
		return fmt.Errorf("unable to get creation time for pod %q: %v", p.UUID, err)
	}
	createdStr := created.Format(defaultTimeLayout)

	stdout.Printf("created=%s", createdStr)

	started, err := p.StartTime()
	if err != nil {
		return fmt.Errorf("unable to get start time for pod %q: %v", p.UUID, err)
	}
	var startedStr string
	if !started.IsZero() {
		startedStr = started.Format(defaultTimeLayout)
		stdout.Printf("started=%s", startedStr)
	}

	if state == pkgPod.Running {
		stdout.Printf("networks=%s", fmtNets(p.Nets))
	}

	if state == pkgPod.Running || state == pkgPod.Deleting || state == pkgPod.ExitedDeleting || state == pkgPod.Exited || state == pkgPod.ExitedGarbage {
		var pid int
		pidCh := make(chan int, 1)

		// Wait slightly because the pid file might not be written yet when the state changes to 'Running'.
		go func() {
			for {
				pid, err := p.Pid()
				if err == nil {
					pidCh <- pid
					return
				}
				time.Sleep(time.Millisecond * 100)
			}
		}()

		select {
		case pid = <-pidCh:
		case <-time.After(time.Second):
			return fmt.Errorf("unable to get PID for pod %q: %v", p.UUID, err)
		}

		stdout.Printf("pid=%d\nexited=%t", pid, (state == pkgPod.Exited || state == pkgPod.ExitedGarbage))

		if state != pkgPod.Running {
			stats, err := getExitStatuses(p)
			if err != nil {
				return fmt.Errorf("unable to get exit statuses for pod %q: %v", p.UUID, err)
			}
			for app, stat := range stats {
				stdout.Printf("app-%s=%d", app, stat)
			}
		}
	}
	return nil
}