| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- // Copyright 2019 Yunion
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package containerd
- import (
- "context"
- "fmt"
- "strconv"
- "time"
- "github.com/containerd/containerd"
- "github.com/containerd/containerd/errdefs"
- "github.com/containerd/containerd/runtime/restart"
- "github.com/containerd/typeurl"
- "github.com/opencontainers/runtime-spec/specs-go"
- "yunion.io/x/log"
- "yunion.io/x/pkg/errors"
- )
- func init() {
- const prefix = "types.containerd.io"
- // register TypeUrls for commonly marshaled external types
- major := strconv.Itoa(specs.VersionMajor)
- typeurl.Register(&specs.Spec{}, prefix, "opencontainers/runtime-spec", major, "Spec")
- typeurl.Register(&specs.Process{}, prefix, "opencontainers/runtime-spec", major, "Process")
- typeurl.Register(&specs.LinuxResources{}, prefix, "opencontainers/runtime-spec", major, "LinuxResources")
- typeurl.Register(&specs.WindowsResources{}, prefix, "opencontainers/runtime-spec", major, "WindowsResources")
- }
- // NewClient 创建 containerd 客户端
- // 参考 nerdctl 的实现方式,使用 containerd.Client
- func NewClient(ctx context.Context, address, namespace string) (*containerd.Client, error) {
- // 使用 containerd.New 创建客户端,参考 nerdctl 实现
- client, err := containerd.New(address,
- containerd.WithDefaultNamespace(namespace),
- )
- if err != nil {
- return nil, errors.Wrapf(err, "create containerd client at %s", address)
- }
- return client, nil
- }
- type ProcessStatus string
- const (
- ProcessStatusCreated ProcessStatus = "created"
- ProcessStatusRunning ProcessStatus = "running"
- ProcessStatusStopped ProcessStatus = "stopped"
- ProcessStatusUnknown ProcessStatus = "unknown"
- ProcessStatusRestarting ProcessStatus = "restarting"
- )
- func ContainerStatus(ctx context.Context, c containerd.Container) ProcessStatus {
- ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
- defer cancel()
- task, err := c.Task(ctx, nil)
- if err != nil {
- if errdefs.IsNotFound(err) {
- return ProcessStatusCreated
- }
- log.Warningf("failed to get task for container %s: %v", c.ID(), err)
- return ProcessStatusUnknown
- }
- status, err := task.Status(ctx)
- if err != nil {
- log.Warningf("failed to get status for task %s: %v", task.ID(), err)
- return ProcessStatusUnknown
- }
- labels, err := c.Labels(ctx)
- if err != nil {
- log.Warningf("failed to get labels for container %s: %v", c.ID(), err)
- return ProcessStatusUnknown
- }
- switch s := status.Status; s {
- case containerd.Stopped:
- if labels[restart.StatusLabel] == string(containerd.Running) && restart.Reconcile(status, labels) {
- s := fmt.Sprintf("Restarting (%d) %v", status.ExitStatus, status.ExitTime)
- log.Infof("container %s is restarting: %s", c.ID(), s)
- return ProcessStatusRestarting
- }
- return ProcessStatusStopped
- case containerd.Running:
- return ProcessStatusRunning
- }
- return ProcessStatus(status.Status)
- }
|