// getBasicPod returns *v1alpha.Pod with basic pod information, it also returns a *schema.PodManifest // object. func getBasicPod(p *pod) (*v1alpha.Pod, *schema.PodManifest, error) { pod := &v1alpha.Pod{Id: p.uuid.String(), Pid: -1} // If a pod is in Embryo, Preparing, AbortedPrepare state, // only id and state will be returned. // // If a pod is in other states, the pod manifest and // apps will be returned when 'detailed' is true in the request. // // Valid pid and networks are only returned when a pod is in Running. switch p.getState() { case Embryo: pod.State = v1alpha.PodState_POD_STATE_EMBRYO return pod, nil, nil case Preparing: pod.State = v1alpha.PodState_POD_STATE_PREPARING return pod, nil, nil case AbortedPrepare: pod.State = v1alpha.PodState_POD_STATE_ABORTED_PREPARE return pod, nil, nil case Prepared: pod.State = v1alpha.PodState_POD_STATE_PREPARED return pod, nil, nil case Running: pod.State = v1alpha.PodState_POD_STATE_RUNNING pod.Networks = getNetworks(p) case Deleting: pod.State = v1alpha.PodState_POD_STATE_DELETING case Exited: pod.State = v1alpha.PodState_POD_STATE_EXITED case Garbage: pod.State = v1alpha.PodState_POD_STATE_GARBAGE default: pod.State = v1alpha.PodState_POD_STATE_UNDEFINED return pod, nil, nil } createdAt, err := p.getCreationTime() if err != nil { return nil, nil, err } startedAt, err := p.getStartTime() if err != nil { return nil, nil, err } gcMarkedAt, err := p.getGCMarkedTime() if err != nil { return nil, nil, err } pod.CreatedAt = createdAt.UnixNano() pod.StartedAt = startedAt.UnixNano() pod.GcMarkedAt = gcMarkedAt.UnixNano() manifest, data, err := getPodManifest(p) if err != nil { return nil, nil, err } apps, err := getApplist(p) if err != nil { return nil, nil, err } if pod.State == v1alpha.PodState_POD_STATE_RUNNING || pod.State == v1alpha.PodState_POD_STATE_DELETING || pod.State == v1alpha.PodState_POD_STATE_EXITED { pid, err := p.getPID() if err != nil { return nil, nil, err } pod.Pid = int32(pid) } if pod.State == v1alpha.PodState_POD_STATE_RUNNING { // Get cgroup for the "name=systemd" controller. pid, err := p.getContainerPID1() if err != nil { return nil, nil, err } cgroup, err := cgroup.GetCgroupPathByPid(pid, "name=systemd") if err != nil { return nil, nil, 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. pod.Cgroup = strings.TrimSuffix(cgroup, "/init.scope") } pod.Manifest = data pod.Apps = apps pod.Annotations = convertAnnotationsToKeyValue(manifest.Annotations) return pod, manifest, 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 *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) } } } } }