Example #1
0
// 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
}
Example #2
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 *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)
				}
			}
		}
	}
}