mirror of
https://github.com/containers/podman.git
synced 2025-06-22 18:08:11 +08:00
87
cmd/podmanV2/containers/start.go
Normal file
87
cmd/podmanV2/containers/start.go
Normal file
@ -0,0 +1,87 @@
|
||||
package containers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/containers/libpod/cmd/podmanV2/common"
|
||||
"github.com/containers/libpod/cmd/podmanV2/registry"
|
||||
"github.com/containers/libpod/cmd/podmanV2/utils"
|
||||
"github.com/containers/libpod/libpod/define"
|
||||
"github.com/containers/libpod/pkg/domain/entities"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
startDescription = `Starts one or more containers. The container name or ID can be used.`
|
||||
startCommand = &cobra.Command{
|
||||
Use: "start [flags] CONTAINER [CONTAINER...]",
|
||||
Short: "Start one or more containers",
|
||||
Long: startDescription,
|
||||
RunE: start,
|
||||
PreRunE: preRunE,
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
Example: `podman start --latest
|
||||
podman start 860a4b231279 5421ab43b45
|
||||
podman start --interactive --attach imageID`,
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
startOptions entities.ContainerStartOptions
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.Commands = append(registry.Commands, registry.CliCommand{
|
||||
Mode: []entities.EngineMode{entities.ABIMode},
|
||||
Command: startCommand,
|
||||
})
|
||||
flags := startCommand.Flags()
|
||||
flags.BoolVarP(&startOptions.Attach, "attach", "a", false, "Attach container's STDOUT and STDERR")
|
||||
flags.StringVar(&startOptions.DetachKeys, "detach-keys", common.GetDefaultDetachKeys(), "Select the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`")
|
||||
flags.BoolVarP(&startOptions.Interactive, "interactive", "i", false, "Keep STDIN open even if not attached")
|
||||
flags.BoolVarP(&startOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
||||
flags.BoolVar(&startOptions.SigProxy, "sig-proxy", false, "Proxy received signals to the process (default true if attaching, false otherwise)")
|
||||
if registry.IsRemote() {
|
||||
_ = flags.MarkHidden("latest")
|
||||
_ = flags.MarkHidden("sig-proxy")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func start(cmd *cobra.Command, args []string) error {
|
||||
var errs utils.OutputErrors
|
||||
if len(args) > 1 && startOptions.Attach {
|
||||
return errors.Errorf("you cannot start and attach multiple containers at once")
|
||||
}
|
||||
|
||||
sigProxy := startOptions.SigProxy || startOptions.Attach
|
||||
if cmd.Flag("sig-proxy").Changed {
|
||||
sigProxy = startOptions.SigProxy
|
||||
}
|
||||
|
||||
if sigProxy && !startOptions.Attach {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "you cannot use sig-proxy without --attach")
|
||||
}
|
||||
if startOptions.Attach {
|
||||
startOptions.Stdin = os.Stdin
|
||||
startOptions.Stderr = os.Stderr
|
||||
startOptions.Stdout = os.Stdout
|
||||
}
|
||||
|
||||
responses, err := registry.ContainerEngine().ContainerStart(registry.GetContext(), args, startOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, r := range responses {
|
||||
if r.Err == nil {
|
||||
fmt.Println(r.Id)
|
||||
} else {
|
||||
errs = append(errs, r.Err)
|
||||
}
|
||||
}
|
||||
// TODO need to understand an implement exitcodes
|
||||
return errs.PrintErrors()
|
||||
}
|
@ -186,3 +186,24 @@ type ExecOptions struct {
|
||||
User string
|
||||
WorkDir string
|
||||
}
|
||||
|
||||
// ContainerStartOptions describes the val from the
|
||||
// CLI needed to start a container
|
||||
type ContainerStartOptions struct {
|
||||
Attach bool
|
||||
DetachKeys string
|
||||
Interactive bool
|
||||
Latest bool
|
||||
SigProxy bool
|
||||
Stdout *os.File
|
||||
Stderr *os.File
|
||||
Stdin *os.File
|
||||
}
|
||||
|
||||
// ContainerStartReport describes the response from starting
|
||||
// containers from the cli
|
||||
type ContainerStartReport struct {
|
||||
Id string
|
||||
Err error
|
||||
ExitCode int
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ type ContainerEngine interface {
|
||||
ContainerPause(ctx context.Context, namesOrIds []string, options PauseUnPauseOptions) ([]*PauseUnpauseReport, error)
|
||||
ContainerRestart(ctx context.Context, namesOrIds []string, options RestartOptions) ([]*RestartReport, error)
|
||||
ContainerRm(ctx context.Context, namesOrIds []string, options RmOptions) ([]*RmReport, error)
|
||||
ContainerStart(ctx context.Context, namesOrIds []string, options ContainerStartOptions) ([]*ContainerStartReport, error)
|
||||
ContainerStop(ctx context.Context, namesOrIds []string, options StopOptions) ([]*StopReport, error)
|
||||
ContainerTop(ctx context.Context, options TopOptions) (*StringSliceReport, error)
|
||||
ContainerUnpause(ctx context.Context, namesOrIds []string, options PauseUnPauseOptions) ([]*PauseUnpauseReport, error)
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/libpod/define"
|
||||
"github.com/containers/libpod/libpod/events"
|
||||
"github.com/containers/libpod/libpod/image"
|
||||
"github.com/containers/libpod/pkg/checkpoint"
|
||||
"github.com/containers/libpod/pkg/domain/entities"
|
||||
@ -509,3 +510,110 @@ func (ic *ContainerEngine) ContainerExec(ctx context.Context, nameOrId string, o
|
||||
ec, err = terminal.ExecAttachCtr(ctx, ctr, options.Tty, options.Privileged, options.Envs, options.Cmd, options.User, options.WorkDir, &options.Streams, options.PreserveFDs, options.DetachKeys)
|
||||
return define.TranslateExecErrorToExitCode(ec, err), err
|
||||
}
|
||||
|
||||
func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []string, options entities.ContainerStartOptions) ([]*entities.ContainerStartReport, error) {
|
||||
var reports []*entities.ContainerStartReport
|
||||
var exitCode = define.ExecErrorCodeGeneric
|
||||
ctrs, err := getContainersByContext(false, options.Latest, namesOrIds, ic.Libpod)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// There can only be one container if attach was used
|
||||
for _, ctr := range ctrs {
|
||||
ctrState, err := ctr.State()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctrRunning := ctrState == define.ContainerStateRunning
|
||||
|
||||
if options.Attach {
|
||||
err = terminal.StartAttachCtr(ctx, ctr, options.Stdout, options.Stderr, options.Stdin, options.DetachKeys, options.SigProxy, !ctrRunning, ctr.PodID() != "")
|
||||
if errors.Cause(err) == define.ErrDetach {
|
||||
// User manually detached
|
||||
// Exit cleanly immediately
|
||||
reports = append(reports, &entities.ContainerStartReport{
|
||||
Id: ctr.ID(),
|
||||
Err: nil,
|
||||
ExitCode: 0,
|
||||
})
|
||||
return reports, nil
|
||||
}
|
||||
|
||||
if errors.Cause(err) == define.ErrWillDeadlock {
|
||||
logrus.Debugf("Deadlock error: %v", err)
|
||||
reports = append(reports, &entities.ContainerStartReport{
|
||||
Id: ctr.ID(),
|
||||
Err: err,
|
||||
ExitCode: define.ExitCode(err),
|
||||
})
|
||||
return reports, errors.Errorf("attempting to start container %s would cause a deadlock; please run 'podman system renumber' to resolve", ctr.ID())
|
||||
}
|
||||
|
||||
if ctrRunning {
|
||||
reports = append(reports, &entities.ContainerStartReport{
|
||||
Id: ctr.ID(),
|
||||
Err: nil,
|
||||
ExitCode: 0,
|
||||
})
|
||||
return reports, err
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
reports = append(reports, &entities.ContainerStartReport{
|
||||
Id: ctr.ID(),
|
||||
Err: err,
|
||||
ExitCode: exitCode,
|
||||
})
|
||||
return reports, errors.Wrapf(err, "unable to start container %s", ctr.ID())
|
||||
}
|
||||
|
||||
if ecode, err := ctr.Wait(); err != nil {
|
||||
if errors.Cause(err) == define.ErrNoSuchCtr {
|
||||
// Check events
|
||||
event, err := ic.Libpod.GetLastContainerEvent(ctr.ID(), events.Exited)
|
||||
if err != nil {
|
||||
logrus.Errorf("Cannot get exit code: %v", err)
|
||||
exitCode = define.ExecErrorCodeNotFound
|
||||
} else {
|
||||
exitCode = event.ContainerExitCode
|
||||
}
|
||||
}
|
||||
} else {
|
||||
exitCode = int(ecode)
|
||||
}
|
||||
reports = append(reports, &entities.ContainerStartReport{
|
||||
Id: ctr.ID(),
|
||||
Err: err,
|
||||
ExitCode: exitCode,
|
||||
})
|
||||
return reports, nil
|
||||
} // end attach
|
||||
|
||||
// Start the container if it's not running already.
|
||||
if !ctrRunning {
|
||||
// Handle non-attach start
|
||||
// If the container is in a pod, also set to recursively start dependencies
|
||||
report := &entities.ContainerStartReport{
|
||||
Id: ctr.ID(),
|
||||
ExitCode: 125,
|
||||
}
|
||||
if err := ctr.Start(ctx, ctr.PodID() != ""); err != nil {
|
||||
//if lastError != nil {
|
||||
// fmt.Fprintln(os.Stderr, lastError)
|
||||
//}
|
||||
report.Err = err
|
||||
if errors.Cause(err) == define.ErrWillDeadlock {
|
||||
report.Err = errors.Wrapf(err, "please run 'podman system renumber' to resolve deadlocks")
|
||||
reports = append(reports, report)
|
||||
continue
|
||||
}
|
||||
report.Err = errors.Wrapf(err, "unable to start container %q", ctr.ID())
|
||||
reports = append(reports, report)
|
||||
continue
|
||||
}
|
||||
report.ExitCode = 0
|
||||
reports = append(reports, report)
|
||||
}
|
||||
}
|
||||
return reports, nil
|
||||
}
|
||||
|
@ -313,3 +313,7 @@ func (ic *ContainerEngine) ContainerAttach(ctx context.Context, nameOrId string,
|
||||
func (ic *ContainerEngine) ContainerExec(ctx context.Context, nameOrId string, options entities.ExecOptions) (int, error) {
|
||||
return 125, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []string, options entities.ContainerStartOptions) ([]*entities.ContainerStartReport, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
Reference in New Issue
Block a user