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 }
// 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) } } }