mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-10-22 12:29:49 +00:00
Some virtcontainers pieces of code are importing virtcontainers packages. We need to change those paths to point at kata-containers/runtime/virtcontainers Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
977 lines
20 KiB
Go
977 lines
20 KiB
Go
//
|
|
// Copyright (c) 2016 Intel Corporation
|
|
//
|
|
// 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 main
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"strings"
|
|
"text/tabwriter"
|
|
|
|
"github.com/kata-containers/runtime/virtcontainers/pkg/uuid"
|
|
"github.com/sirupsen/logrus"
|
|
"github.com/urfave/cli"
|
|
|
|
vc "github.com/kata-containers/runtime/virtcontainers"
|
|
)
|
|
|
|
var virtcLog = logrus.New()
|
|
|
|
var listFormat = "%s\t%s\t%s\t%s\n"
|
|
var statusFormat = "%s\t%s\n"
|
|
|
|
var (
|
|
errNeedContainerID = errors.New("Container ID cannot be empty")
|
|
errNeedPodID = errors.New("Pod ID cannot be empty")
|
|
)
|
|
|
|
var podConfigFlags = []cli.Flag{
|
|
cli.GenericFlag{
|
|
Name: "agent",
|
|
Value: new(vc.AgentType),
|
|
Usage: "the guest agent",
|
|
},
|
|
|
|
cli.StringFlag{
|
|
Name: "id",
|
|
Value: "",
|
|
Usage: "the pod identifier (default: auto-generated)",
|
|
},
|
|
|
|
cli.StringFlag{
|
|
Name: "machine-type",
|
|
Value: vc.QemuPC,
|
|
Usage: "hypervisor machine type",
|
|
},
|
|
|
|
cli.GenericFlag{
|
|
Name: "network",
|
|
Value: new(vc.NetworkModel),
|
|
Usage: "the network model",
|
|
},
|
|
|
|
cli.GenericFlag{
|
|
Name: "proxy",
|
|
Value: new(vc.ProxyType),
|
|
Usage: "the agent's proxy",
|
|
},
|
|
|
|
cli.StringFlag{
|
|
Name: "proxy-path",
|
|
Value: "",
|
|
Usage: "path to proxy binary",
|
|
},
|
|
|
|
cli.GenericFlag{
|
|
Name: "shim",
|
|
Value: new(vc.ShimType),
|
|
Usage: "the shim type",
|
|
},
|
|
|
|
cli.StringFlag{
|
|
Name: "shim-path",
|
|
Value: "",
|
|
Usage: "the shim binary path",
|
|
},
|
|
|
|
cli.StringFlag{
|
|
Name: "hyper-ctl-sock-name",
|
|
Value: "",
|
|
Usage: "the hyperstart control socket name",
|
|
},
|
|
|
|
cli.StringFlag{
|
|
Name: "hyper-tty-sock-name",
|
|
Value: "",
|
|
Usage: "the hyperstart tty socket name",
|
|
},
|
|
|
|
cli.UintFlag{
|
|
Name: "cpus",
|
|
Value: 0,
|
|
Usage: "the number of virtual cpus available for this pod",
|
|
},
|
|
|
|
cli.UintFlag{
|
|
Name: "memory",
|
|
Value: 0,
|
|
Usage: "the amount of memory available for this pod in MiB",
|
|
},
|
|
}
|
|
|
|
var ccKernelParams = []vc.Param{
|
|
{
|
|
Key: "init",
|
|
Value: "/usr/lib/systemd/systemd",
|
|
},
|
|
{
|
|
Key: "systemd.unit",
|
|
Value: "clear-containers.target",
|
|
},
|
|
{
|
|
Key: "systemd.mask",
|
|
Value: "systemd-networkd.service",
|
|
},
|
|
{
|
|
Key: "systemd.mask",
|
|
Value: "systemd-networkd.socket",
|
|
},
|
|
}
|
|
|
|
func buildKernelParams(config *vc.HypervisorConfig) error {
|
|
for _, p := range ccKernelParams {
|
|
if err := config.AddKernelParam(p); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func buildPodConfig(context *cli.Context) (vc.PodConfig, error) {
|
|
var agConfig interface{}
|
|
|
|
hyperCtlSockName := context.String("hyper-ctl-sock-name")
|
|
hyperTtySockName := context.String("hyper-tty-sock-name")
|
|
proxyPath := context.String("proxy-path")
|
|
shimPath := context.String("shim-path")
|
|
machineType := context.String("machine-type")
|
|
vmMemory := context.Uint("vm-memory")
|
|
agentType, ok := context.Generic("agent").(*vc.AgentType)
|
|
if ok != true {
|
|
return vc.PodConfig{}, fmt.Errorf("Could not convert agent type")
|
|
}
|
|
|
|
networkModel, ok := context.Generic("network").(*vc.NetworkModel)
|
|
if ok != true {
|
|
return vc.PodConfig{}, fmt.Errorf("Could not convert network model")
|
|
}
|
|
|
|
proxyType, ok := context.Generic("proxy").(*vc.ProxyType)
|
|
if ok != true {
|
|
return vc.PodConfig{}, fmt.Errorf("Could not convert proxy type")
|
|
}
|
|
|
|
shimType, ok := context.Generic("shim").(*vc.ShimType)
|
|
if ok != true {
|
|
return vc.PodConfig{}, fmt.Errorf("Could not convert shim type")
|
|
}
|
|
|
|
kernelPath := "/usr/share/clear-containers/vmlinuz.container"
|
|
if machineType == vc.QemuPCLite {
|
|
kernelPath = "/usr/share/clear-containers/vmlinux.container"
|
|
}
|
|
|
|
hypervisorConfig := vc.HypervisorConfig{
|
|
KernelPath: kernelPath,
|
|
ImagePath: "/usr/share/clear-containers/clear-containers.img",
|
|
HypervisorMachineType: machineType,
|
|
}
|
|
|
|
if err := buildKernelParams(&hypervisorConfig); err != nil {
|
|
return vc.PodConfig{}, err
|
|
}
|
|
|
|
netConfig := vc.NetworkConfig{
|
|
NumInterfaces: 1,
|
|
}
|
|
|
|
switch *agentType {
|
|
case vc.HyperstartAgent:
|
|
agConfig = vc.HyperConfig{
|
|
SockCtlName: hyperCtlSockName,
|
|
SockTtyName: hyperTtySockName,
|
|
}
|
|
default:
|
|
agConfig = nil
|
|
}
|
|
|
|
proxyConfig := getProxyConfig(*proxyType, proxyPath)
|
|
|
|
shimConfig := getShimConfig(*shimType, shimPath)
|
|
|
|
vmConfig := vc.Resources{
|
|
Memory: vmMemory,
|
|
}
|
|
|
|
id := context.String("id")
|
|
if id == "" {
|
|
// auto-generate pod name
|
|
id = uuid.Generate().String()
|
|
}
|
|
|
|
podConfig := vc.PodConfig{
|
|
ID: id,
|
|
VMConfig: vmConfig,
|
|
|
|
HypervisorType: vc.QemuHypervisor,
|
|
HypervisorConfig: hypervisorConfig,
|
|
|
|
AgentType: *agentType,
|
|
AgentConfig: agConfig,
|
|
|
|
NetworkModel: *networkModel,
|
|
NetworkConfig: netConfig,
|
|
|
|
ProxyType: *proxyType,
|
|
ProxyConfig: proxyConfig,
|
|
|
|
ShimType: *shimType,
|
|
ShimConfig: shimConfig,
|
|
|
|
Containers: []vc.ContainerConfig{},
|
|
}
|
|
|
|
return podConfig, nil
|
|
}
|
|
|
|
func getProxyConfig(proxyType vc.ProxyType, path string) vc.ProxyConfig {
|
|
var proxyConfig vc.ProxyConfig
|
|
|
|
switch proxyType {
|
|
case vc.KataProxyType:
|
|
fallthrough
|
|
case vc.CCProxyType:
|
|
proxyConfig = vc.ProxyConfig{
|
|
Path: path,
|
|
}
|
|
}
|
|
|
|
return proxyConfig
|
|
}
|
|
|
|
func getShimConfig(shimType vc.ShimType, path string) interface{} {
|
|
var shimConfig interface{}
|
|
|
|
switch shimType {
|
|
case vc.CCShimType, vc.KataShimType:
|
|
shimConfig = vc.ShimConfig{
|
|
Path: path,
|
|
}
|
|
|
|
default:
|
|
shimConfig = nil
|
|
}
|
|
|
|
return shimConfig
|
|
}
|
|
|
|
// checkRequiredPodArgs checks to ensure the required command-line
|
|
// arguments have been specified for the pod sub-command specified by
|
|
// the context argument.
|
|
func checkRequiredPodArgs(context *cli.Context) error {
|
|
if context == nil {
|
|
return fmt.Errorf("BUG: need Context")
|
|
}
|
|
|
|
// sub-sub-command name
|
|
name := context.Command.Name
|
|
|
|
switch name {
|
|
case "create":
|
|
fallthrough
|
|
case "list":
|
|
fallthrough
|
|
case "run":
|
|
// these commands don't require any arguments
|
|
return nil
|
|
}
|
|
|
|
id := context.String("id")
|
|
if id == "" {
|
|
return errNeedPodID
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// checkRequiredContainerArgs checks to ensure the required command-line
|
|
// arguments have been specified for the container sub-command specified
|
|
// by the context argument.
|
|
func checkRequiredContainerArgs(context *cli.Context) error {
|
|
if context == nil {
|
|
return fmt.Errorf("BUG: need Context")
|
|
}
|
|
|
|
// sub-sub-command name
|
|
name := context.Command.Name
|
|
|
|
podID := context.String("pod-id")
|
|
if podID == "" {
|
|
return errNeedPodID
|
|
}
|
|
|
|
rootfs := context.String("rootfs")
|
|
if name == "create" && rootfs == "" {
|
|
return fmt.Errorf("%s: need rootfs", name)
|
|
}
|
|
|
|
id := context.String("id")
|
|
if id == "" {
|
|
return errNeedContainerID
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func runPod(context *cli.Context) error {
|
|
podConfig, err := buildPodConfig(context)
|
|
if err != nil {
|
|
return fmt.Errorf("Could not build pod config: %s", err)
|
|
}
|
|
|
|
_, err = vc.RunPod(podConfig)
|
|
if err != nil {
|
|
return fmt.Errorf("Could not run pod: %s", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func createPod(context *cli.Context) error {
|
|
podConfig, err := buildPodConfig(context)
|
|
if err != nil {
|
|
return fmt.Errorf("Could not build pod config: %s", err)
|
|
}
|
|
|
|
p, err := vc.CreatePod(podConfig)
|
|
if err != nil {
|
|
return fmt.Errorf("Could not create pod: %s", err)
|
|
}
|
|
|
|
fmt.Printf("Pod %s created\n", p.ID())
|
|
|
|
return nil
|
|
}
|
|
|
|
func checkPodArgs(context *cli.Context, f func(context *cli.Context) error) error {
|
|
if err := checkRequiredPodArgs(context); err != nil {
|
|
return err
|
|
}
|
|
|
|
return f(context)
|
|
}
|
|
|
|
func checkContainerArgs(context *cli.Context, f func(context *cli.Context) error) error {
|
|
if err := checkRequiredContainerArgs(context); err != nil {
|
|
return err
|
|
}
|
|
|
|
return f(context)
|
|
}
|
|
|
|
func deletePod(context *cli.Context) error {
|
|
p, err := vc.DeletePod(context.String("id"))
|
|
if err != nil {
|
|
return fmt.Errorf("Could not delete pod: %s", err)
|
|
}
|
|
|
|
fmt.Printf("Pod %s deleted\n", p.ID())
|
|
|
|
return nil
|
|
}
|
|
|
|
func startPod(context *cli.Context) error {
|
|
p, err := vc.StartPod(context.String("id"))
|
|
if err != nil {
|
|
return fmt.Errorf("Could not start pod: %s", err)
|
|
}
|
|
|
|
fmt.Printf("Pod %s started\n", p.ID())
|
|
|
|
return nil
|
|
}
|
|
|
|
func stopPod(context *cli.Context) error {
|
|
p, err := vc.StopPod(context.String("id"))
|
|
if err != nil {
|
|
return fmt.Errorf("Could not stop pod: %s", err)
|
|
}
|
|
|
|
fmt.Printf("Pod %s stopped\n", p.ID())
|
|
|
|
return nil
|
|
}
|
|
|
|
func pausePod(context *cli.Context) error {
|
|
p, err := vc.PausePod(context.String("id"))
|
|
if err != nil {
|
|
return fmt.Errorf("Could not pause pod: %s", err)
|
|
}
|
|
|
|
fmt.Printf("Pod %s paused\n", p.ID())
|
|
|
|
return nil
|
|
}
|
|
|
|
func resumePod(context *cli.Context) error {
|
|
p, err := vc.ResumePod(context.String("id"))
|
|
if err != nil {
|
|
return fmt.Errorf("Could not resume pod: %s", err)
|
|
}
|
|
|
|
fmt.Printf("Pod %s resumed\n", p.ID())
|
|
|
|
return nil
|
|
}
|
|
|
|
func listPods(context *cli.Context) error {
|
|
podStatusList, err := vc.ListPod()
|
|
if err != nil {
|
|
return fmt.Errorf("Could not list pod: %s", err)
|
|
}
|
|
|
|
w := tabwriter.NewWriter(os.Stdout, 2, 8, 1, '\t', 0)
|
|
fmt.Fprintf(w, listFormat, "POD ID", "STATE", "HYPERVISOR", "AGENT")
|
|
|
|
for _, podStatus := range podStatusList {
|
|
fmt.Fprintf(w, listFormat,
|
|
podStatus.ID, podStatus.State.State, podStatus.Hypervisor, podStatus.Agent)
|
|
}
|
|
|
|
w.Flush()
|
|
|
|
return nil
|
|
}
|
|
|
|
func statusPod(context *cli.Context) error {
|
|
podStatus, err := vc.StatusPod(context.String("id"))
|
|
if err != nil {
|
|
return fmt.Errorf("Could not get pod status: %s", err)
|
|
}
|
|
|
|
w := tabwriter.NewWriter(os.Stdout, 2, 8, 1, '\t', 0)
|
|
fmt.Fprintf(w, listFormat, "POD ID", "STATE", "HYPERVISOR", "AGENT")
|
|
|
|
fmt.Fprintf(w, listFormat+"\n",
|
|
podStatus.ID, podStatus.State.State, podStatus.Hypervisor, podStatus.Agent)
|
|
|
|
fmt.Fprintf(w, statusFormat, "CONTAINER ID", "STATE")
|
|
|
|
for _, contStatus := range podStatus.ContainersStatus {
|
|
fmt.Fprintf(w, statusFormat, contStatus.ID, contStatus.State.State)
|
|
}
|
|
|
|
w.Flush()
|
|
|
|
return nil
|
|
}
|
|
|
|
var runPodCommand = cli.Command{
|
|
Name: "run",
|
|
Usage: "run a pod",
|
|
Flags: podConfigFlags,
|
|
Action: func(context *cli.Context) error {
|
|
return checkPodArgs(context, runPod)
|
|
},
|
|
}
|
|
|
|
var createPodCommand = cli.Command{
|
|
Name: "create",
|
|
Usage: "create a pod",
|
|
Flags: podConfigFlags,
|
|
Action: func(context *cli.Context) error {
|
|
return checkPodArgs(context, createPod)
|
|
},
|
|
}
|
|
|
|
var deletePodCommand = cli.Command{
|
|
Name: "delete",
|
|
Usage: "delete an existing pod",
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "id",
|
|
Value: "",
|
|
Usage: "the pod identifier",
|
|
},
|
|
},
|
|
Action: func(context *cli.Context) error {
|
|
return checkPodArgs(context, deletePod)
|
|
},
|
|
}
|
|
|
|
var startPodCommand = cli.Command{
|
|
Name: "start",
|
|
Usage: "start an existing pod",
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "id",
|
|
Value: "",
|
|
Usage: "the pod identifier",
|
|
},
|
|
},
|
|
Action: func(context *cli.Context) error {
|
|
return checkPodArgs(context, startPod)
|
|
},
|
|
}
|
|
|
|
var stopPodCommand = cli.Command{
|
|
Name: "stop",
|
|
Usage: "stop an existing pod",
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "id",
|
|
Value: "",
|
|
Usage: "the pod identifier",
|
|
},
|
|
},
|
|
Action: func(context *cli.Context) error {
|
|
return checkPodArgs(context, stopPod)
|
|
},
|
|
}
|
|
|
|
var listPodsCommand = cli.Command{
|
|
Name: "list",
|
|
Usage: "list all existing pods",
|
|
Action: func(context *cli.Context) error {
|
|
return checkPodArgs(context, listPods)
|
|
},
|
|
}
|
|
|
|
var statusPodCommand = cli.Command{
|
|
Name: "status",
|
|
Usage: "returns a detailed pod status",
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "id",
|
|
Value: "",
|
|
Usage: "the pod identifier",
|
|
},
|
|
},
|
|
Action: func(context *cli.Context) error {
|
|
return checkPodArgs(context, statusPod)
|
|
},
|
|
}
|
|
|
|
var pausePodCommand = cli.Command{
|
|
Name: "pause",
|
|
Usage: "pause an existing pod",
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "id",
|
|
Value: "",
|
|
Usage: "the pod identifier",
|
|
},
|
|
},
|
|
Action: func(context *cli.Context) error {
|
|
return checkPodArgs(context, pausePod)
|
|
},
|
|
}
|
|
|
|
var resumePodCommand = cli.Command{
|
|
Name: "resume",
|
|
Usage: "unpause a paused pod",
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "id",
|
|
Value: "",
|
|
Usage: "the pod identifier",
|
|
},
|
|
},
|
|
Action: func(context *cli.Context) error {
|
|
return checkPodArgs(context, resumePod)
|
|
},
|
|
}
|
|
|
|
func createContainer(context *cli.Context) error {
|
|
console := context.String("console")
|
|
|
|
interactive := false
|
|
if console != "" {
|
|
interactive = true
|
|
}
|
|
|
|
envs := []vc.EnvVar{
|
|
{
|
|
Var: "PATH",
|
|
Value: "/bin:/usr/bin:/sbin:/usr/sbin",
|
|
},
|
|
}
|
|
|
|
cmd := vc.Cmd{
|
|
Args: strings.Split(context.String("cmd"), " "),
|
|
Envs: envs,
|
|
WorkDir: "/",
|
|
Interactive: interactive,
|
|
Console: console,
|
|
}
|
|
|
|
id := context.String("id")
|
|
if id == "" {
|
|
// auto-generate container name
|
|
id = uuid.Generate().String()
|
|
}
|
|
|
|
containerConfig := vc.ContainerConfig{
|
|
ID: id,
|
|
RootFs: context.String("rootfs"),
|
|
Cmd: cmd,
|
|
}
|
|
|
|
_, c, err := vc.CreateContainer(context.String("pod-id"), containerConfig)
|
|
if err != nil {
|
|
return fmt.Errorf("Could not create container: %s", err)
|
|
}
|
|
|
|
fmt.Printf("Container %s created\n", c.ID())
|
|
|
|
return nil
|
|
}
|
|
|
|
func deleteContainer(context *cli.Context) error {
|
|
c, err := vc.DeleteContainer(context.String("pod-id"), context.String("id"))
|
|
if err != nil {
|
|
return fmt.Errorf("Could not delete container: %s", err)
|
|
}
|
|
|
|
fmt.Printf("Container %s deleted\n", c.ID())
|
|
|
|
return nil
|
|
}
|
|
|
|
func startContainer(context *cli.Context) error {
|
|
c, err := vc.StartContainer(context.String("pod-id"), context.String("id"))
|
|
if err != nil {
|
|
return fmt.Errorf("Could not start container: %s", err)
|
|
}
|
|
|
|
fmt.Printf("Container %s started\n", c.ID())
|
|
|
|
return nil
|
|
}
|
|
|
|
func stopContainer(context *cli.Context) error {
|
|
c, err := vc.StopContainer(context.String("pod-id"), context.String("id"))
|
|
if err != nil {
|
|
return fmt.Errorf("Could not stop container: %s", err)
|
|
}
|
|
|
|
fmt.Printf("Container %s stopped\n", c.ID())
|
|
|
|
return nil
|
|
}
|
|
|
|
func enterContainer(context *cli.Context) error {
|
|
console := context.String("console")
|
|
|
|
interactive := false
|
|
if console != "" {
|
|
interactive = true
|
|
}
|
|
|
|
envs := []vc.EnvVar{
|
|
{
|
|
Var: "PATH",
|
|
Value: "/bin:/usr/bin:/sbin:/usr/sbin",
|
|
},
|
|
}
|
|
|
|
cmd := vc.Cmd{
|
|
Args: strings.Split(context.String("cmd"), " "),
|
|
Envs: envs,
|
|
WorkDir: "/",
|
|
Interactive: interactive,
|
|
Console: console,
|
|
}
|
|
|
|
_, c, _, err := vc.EnterContainer(context.String("pod-id"), context.String("id"), cmd)
|
|
if err != nil {
|
|
return fmt.Errorf("Could not enter container: %s", err)
|
|
}
|
|
|
|
fmt.Printf("Container %s entered\n", c.ID())
|
|
|
|
return nil
|
|
}
|
|
|
|
func statusContainer(context *cli.Context) error {
|
|
contStatus, err := vc.StatusContainer(context.String("pod-id"), context.String("id"))
|
|
if err != nil {
|
|
return fmt.Errorf("Could not get container status: %s", err)
|
|
}
|
|
|
|
w := tabwriter.NewWriter(os.Stdout, 2, 8, 1, '\t', 0)
|
|
fmt.Fprintf(w, statusFormat, "CONTAINER ID", "STATE")
|
|
fmt.Fprintf(w, statusFormat, contStatus.ID, contStatus.State.State)
|
|
|
|
w.Flush()
|
|
|
|
return nil
|
|
}
|
|
|
|
var createContainerCommand = cli.Command{
|
|
Name: "create",
|
|
Usage: "create a container",
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "id",
|
|
Value: "",
|
|
Usage: "the container identifier (default: auto-generated)",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "pod-id",
|
|
Value: "",
|
|
Usage: "the pod identifier",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "rootfs",
|
|
Value: "",
|
|
Usage: "the container rootfs directory",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "cmd",
|
|
Value: "",
|
|
Usage: "the command executed inside the container",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "console",
|
|
Value: "",
|
|
Usage: "the container console",
|
|
},
|
|
},
|
|
Action: func(context *cli.Context) error {
|
|
return checkContainerArgs(context, createContainer)
|
|
},
|
|
}
|
|
|
|
var deleteContainerCommand = cli.Command{
|
|
Name: "delete",
|
|
Usage: "delete an existing container",
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "id",
|
|
Value: "",
|
|
Usage: "the container identifier",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "pod-id",
|
|
Value: "",
|
|
Usage: "the pod identifier",
|
|
},
|
|
},
|
|
Action: func(context *cli.Context) error {
|
|
return checkContainerArgs(context, deleteContainer)
|
|
},
|
|
}
|
|
|
|
var startContainerCommand = cli.Command{
|
|
Name: "start",
|
|
Usage: "start an existing container",
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "id",
|
|
Value: "",
|
|
Usage: "the container identifier",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "pod-id",
|
|
Value: "",
|
|
Usage: "the pod identifier",
|
|
},
|
|
},
|
|
Action: func(context *cli.Context) error {
|
|
return checkContainerArgs(context, startContainer)
|
|
},
|
|
}
|
|
|
|
var stopContainerCommand = cli.Command{
|
|
Name: "stop",
|
|
Usage: "stop an existing container",
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "id",
|
|
Value: "",
|
|
Usage: "the container identifier",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "pod-id",
|
|
Value: "",
|
|
Usage: "the pod identifier",
|
|
},
|
|
},
|
|
Action: func(context *cli.Context) error {
|
|
return checkContainerArgs(context, stopContainer)
|
|
},
|
|
}
|
|
|
|
var enterContainerCommand = cli.Command{
|
|
Name: "enter",
|
|
Usage: "enter an existing container",
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "id",
|
|
Value: "",
|
|
Usage: "the container identifier",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "pod-id",
|
|
Value: "",
|
|
Usage: "the pod identifier",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "cmd",
|
|
Value: "echo",
|
|
Usage: "the command executed inside the container",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "console",
|
|
Value: "",
|
|
Usage: "the process console",
|
|
},
|
|
},
|
|
Action: func(context *cli.Context) error {
|
|
return checkContainerArgs(context, enterContainer)
|
|
},
|
|
}
|
|
|
|
var statusContainerCommand = cli.Command{
|
|
Name: "status",
|
|
Usage: "returns detailed container status",
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "id",
|
|
Value: "",
|
|
Usage: "the container identifier",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "pod-id",
|
|
Value: "",
|
|
Usage: "the pod identifier",
|
|
},
|
|
},
|
|
Action: func(context *cli.Context) error {
|
|
return checkContainerArgs(context, statusContainer)
|
|
},
|
|
}
|
|
|
|
func startCCShim(process *vc.Process, shimPath, url string) error {
|
|
if process.Token == "" {
|
|
return fmt.Errorf("Token cannot be empty")
|
|
}
|
|
|
|
if url == "" {
|
|
return fmt.Errorf("URL cannot be empty")
|
|
}
|
|
|
|
if shimPath == "" {
|
|
return fmt.Errorf("Shim path cannot be empty")
|
|
}
|
|
|
|
cmd := exec.Command(shimPath, "-t", process.Token, "-u", url)
|
|
cmd.Env = os.Environ()
|
|
cmd.Stdin = os.Stdin
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
|
|
return cmd.Run()
|
|
}
|
|
|
|
func main() {
|
|
cli.VersionFlag = cli.BoolFlag{
|
|
Name: "version",
|
|
Usage: "print the version",
|
|
}
|
|
|
|
virtc := cli.NewApp()
|
|
virtc.Name = "VirtContainers CLI"
|
|
virtc.Version = "0.0.1"
|
|
|
|
virtc.Flags = []cli.Flag{
|
|
cli.BoolFlag{
|
|
Name: "debug",
|
|
Usage: "enable debug output for logging",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "log",
|
|
Value: "",
|
|
Usage: "set the log file path where internal debug information is written",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "log-format",
|
|
Value: "text",
|
|
Usage: "set the format used by logs ('text' (default), or 'json')",
|
|
},
|
|
}
|
|
|
|
virtc.Commands = []cli.Command{
|
|
{
|
|
Name: "pod",
|
|
Usage: "pod commands",
|
|
Subcommands: []cli.Command{
|
|
createPodCommand,
|
|
deletePodCommand,
|
|
listPodsCommand,
|
|
pausePodCommand,
|
|
resumePodCommand,
|
|
runPodCommand,
|
|
startPodCommand,
|
|
stopPodCommand,
|
|
statusPodCommand,
|
|
},
|
|
},
|
|
{
|
|
Name: "container",
|
|
Usage: "container commands",
|
|
Subcommands: []cli.Command{
|
|
createContainerCommand,
|
|
deleteContainerCommand,
|
|
startContainerCommand,
|
|
stopContainerCommand,
|
|
enterContainerCommand,
|
|
statusContainerCommand,
|
|
},
|
|
},
|
|
}
|
|
|
|
virtc.Before = func(context *cli.Context) error {
|
|
if context.GlobalBool("debug") {
|
|
virtcLog.Level = logrus.DebugLevel
|
|
}
|
|
|
|
if path := context.GlobalString("log"); path != "" {
|
|
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND|os.O_SYNC, 0640)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
virtcLog.Out = f
|
|
}
|
|
|
|
switch context.GlobalString("log-format") {
|
|
case "text":
|
|
// retain logrus's default.
|
|
case "json":
|
|
virtcLog.Formatter = new(logrus.JSONFormatter)
|
|
default:
|
|
return fmt.Errorf("unknown log-format %q", context.GlobalString("log-format"))
|
|
}
|
|
|
|
// Set virtcontainers logger.
|
|
vc.SetLogger(virtcLog)
|
|
|
|
return nil
|
|
}
|
|
|
|
err := virtc.Run(os.Args)
|
|
if err != nil {
|
|
virtcLog.Fatal(err)
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
}
|