// 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) } } }
// 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 *pod, v1pod *v1alpha.Pod) { v1pod.Pid = -1 switch p.getState() { case Embryo: v1pod.State = v1alpha.PodState_POD_STATE_EMBRYO // When a pod is in embryo state, there is not much // information to return. return case Preparing: v1pod.State = v1alpha.PodState_POD_STATE_PREPARING case AbortedPrepare: v1pod.State = v1alpha.PodState_POD_STATE_ABORTED_PREPARE case Prepared: v1pod.State = v1alpha.PodState_POD_STATE_PREPARED case Running: v1pod.State = v1alpha.PodState_POD_STATE_RUNNING v1pod.Networks = getNetworks(p) case Deleting: v1pod.State = v1alpha.PodState_POD_STATE_DELETING case Exited: v1pod.State = v1alpha.PodState_POD_STATE_EXITED case Garbage: v1pod.State = v1alpha.PodState_POD_STATE_GARBAGE default: v1pod.State = v1alpha.PodState_POD_STATE_UNDEFINED return } createdAt, err := p.getCreationTime() 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.getStartTime() 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.getGCMarkedTime() 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.getPID() 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 { if err := waitForMachinedRegistration(v1pod.Id); err != nil { // If there's an error, it means we're not registered to machined // in a reasonable time. Just output the cgroup we're in. stderr.PrintE("checking for machined registration failed", err) } // Get cgroup for the "name=systemd" controller. pid, err := p.getContainerPID1() if err != nil { stderr.PrintE(fmt.Sprintf("failed to get the container PID1 for pod %q", p.uuid), err) } else { cgroup, err := cgroup.GetCgroupPathByPid(pid, "name=systemd") if err != nil { stderr.PrintE(fmt.Sprintf("failed to get the cgroup path for pod %q", p.uuid), err) } else { // 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. v1pod.Cgroup = strings.TrimSuffix(cgroup, "/init.scope") } } } for _, app := range v1pod.Apps { readStatus := false if p.isRunning() { 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 { statusDir, err := p.getStatusDir() if err != nil { stderr.PrintE("failed to get pod exit status directory", err) } else { value, err := p.readIntFromFile(filepath.Join(statusDir, app.Name)) if err != nil && !os.IsNotExist(err) { stderr.PrintE(fmt.Sprintf("failed to read status for app %q", app.Name), err) } else { app.ExitCode = int32(value) } } } } }