mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 06:03:57 +08:00
Prepare startContainer() to have more action
Currently startContainer() is used to create and to run a container. In the next patch it will be used to restore a container. Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This commit is contained in:
@@ -62,7 +62,7 @@ command(s) that get executed on start, edit the args parameter of the spec. See
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
status, err := startContainer(context, spec, true)
|
status, err := startContainer(context, spec, CT_ACT_CREATE, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,6 +135,7 @@ func execProcess(context *cli.Context) (int, error) {
|
|||||||
consoleSocket: context.String("console-socket"),
|
consoleSocket: context.String("console-socket"),
|
||||||
detach: detach,
|
detach: detach,
|
||||||
pidFile: context.String("pid-file"),
|
pidFile: context.String("pid-file"),
|
||||||
|
action: CT_ACT_RUN,
|
||||||
}
|
}
|
||||||
return r.run(p)
|
return r.run(p)
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-101
@@ -5,13 +5,8 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
|
||||||
"github.com/opencontainers/runc/libcontainer"
|
"github.com/opencontainers/runc/libcontainer"
|
||||||
"github.com/opencontainers/runc/libcontainer/configs"
|
|
||||||
"github.com/opencontainers/runc/libcontainer/specconv"
|
|
||||||
"github.com/opencontainers/runtime-spec/specs-go"
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -92,111 +87,22 @@ using the runc checkpoint command.`,
|
|||||||
return fmt.Errorf("runc restore requires root")
|
return fmt.Errorf("runc restore requires root")
|
||||||
}
|
}
|
||||||
|
|
||||||
imagePath := context.String("image-path")
|
spec, err := setupSpec(context)
|
||||||
id := context.Args().First()
|
|
||||||
if id == "" {
|
|
||||||
return errEmptyID
|
|
||||||
}
|
|
||||||
if imagePath == "" {
|
|
||||||
imagePath = getDefaultImagePath(context)
|
|
||||||
}
|
|
||||||
bundle := context.String("bundle")
|
|
||||||
if bundle != "" {
|
|
||||||
if err := os.Chdir(bundle); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spec, err := loadSpec(specConfig)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
config, err := specconv.CreateLibcontainerConfig(&specconv.CreateOpts{
|
options := criuOptions(context)
|
||||||
CgroupName: id,
|
status, err := startContainer(context, spec, CT_ACT_RESTORE, options)
|
||||||
UseSystemdCgroup: context.GlobalBool("systemd-cgroup"),
|
|
||||||
NoPivotRoot: context.Bool("no-pivot"),
|
|
||||||
Spec: spec,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
status, err := restoreContainer(context, spec, config, imagePath)
|
// exit with the container's exit status so any external supervisor is
|
||||||
if err == nil {
|
// notified of the exit with the correct exit status.
|
||||||
os.Exit(status)
|
os.Exit(status)
|
||||||
}
|
return nil
|
||||||
return err
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func restoreContainer(context *cli.Context, spec *specs.Spec, config *configs.Config, imagePath string) (int, error) {
|
|
||||||
var (
|
|
||||||
rootuid = 0
|
|
||||||
rootgid = 0
|
|
||||||
id = context.Args().First()
|
|
||||||
)
|
|
||||||
factory, err := loadFactory(context)
|
|
||||||
if err != nil {
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
container, err := factory.Load(id)
|
|
||||||
if err != nil {
|
|
||||||
container, err = factory.Create(id, config)
|
|
||||||
if err != nil {
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
options := criuOptions(context)
|
|
||||||
|
|
||||||
status, err := container.Status()
|
|
||||||
if err != nil {
|
|
||||||
logrus.Error(err)
|
|
||||||
}
|
|
||||||
if status == libcontainer.Running {
|
|
||||||
fatalf("Container with id %s already running", id)
|
|
||||||
}
|
|
||||||
|
|
||||||
setManageCgroupsMode(context, options)
|
|
||||||
|
|
||||||
if err = setEmptyNsMask(context, options); err != nil {
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensure that the container is always removed if we were the process
|
|
||||||
// that created it.
|
|
||||||
detach := context.Bool("detach")
|
|
||||||
if !detach {
|
|
||||||
defer destroy(container)
|
|
||||||
}
|
|
||||||
process := &libcontainer.Process{}
|
|
||||||
tty, err := setupIO(process, rootuid, rootgid, false, detach, "")
|
|
||||||
if err != nil {
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
|
|
||||||
notifySocket := newNotifySocket(context, os.Getenv("NOTIFY_SOCKET"), id)
|
|
||||||
if notifySocket != nil {
|
|
||||||
notifySocket.setupSpec(context, spec)
|
|
||||||
notifySocket.setupSocket()
|
|
||||||
}
|
|
||||||
|
|
||||||
handler := newSignalHandler(!context.Bool("no-subreaper"), notifySocket)
|
|
||||||
if err := container.Restore(process, options); err != nil {
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
// We don't need to do a tty.recvtty because config.Terminal is always false.
|
|
||||||
defer tty.Close()
|
|
||||||
if err := tty.ClosePostStart(); err != nil {
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
if pidFile := context.String("pid-file"); pidFile != "" {
|
|
||||||
if err := createPidFile(pidFile, process); err != nil {
|
|
||||||
_ = process.Signal(syscall.SIGKILL)
|
|
||||||
_, _ = process.Wait()
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return handler.forward(process, tty, detach)
|
|
||||||
}
|
|
||||||
|
|
||||||
func criuOptions(context *cli.Context) *libcontainer.CriuOpts {
|
func criuOptions(context *cli.Context) *libcontainer.CriuOpts {
|
||||||
imagePath := getCheckpointImagePath(context)
|
imagePath := getCheckpointImagePath(context)
|
||||||
if err := os.MkdirAll(imagePath, 0655); err != nil {
|
if err := os.MkdirAll(imagePath, 0655); err != nil {
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ command(s) that get executed on start, edit the args parameter of the spec. See
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
status, err := startContainer(context, spec, false)
|
status, err := startContainer(context, spec, CT_ACT_RUN, nil)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// exit with the container's exit status so any external supervisor is
|
// exit with the container's exit status so any external supervisor is
|
||||||
// notified of the exit with the correct exit status.
|
// notified of the exit with the correct exit status.
|
||||||
|
|||||||
+27
-10
@@ -220,8 +220,9 @@ type runner struct {
|
|||||||
pidFile string
|
pidFile string
|
||||||
consoleSocket string
|
consoleSocket string
|
||||||
container libcontainer.Container
|
container libcontainer.Container
|
||||||
create bool
|
action CtAct
|
||||||
notifySocket *notifySocket
|
notifySocket *notifySocket
|
||||||
|
criuOpts *libcontainer.CriuOpts
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) run(config *specs.Process) (int, error) {
|
func (r *runner) run(config *specs.Process) (int, error) {
|
||||||
@@ -253,12 +254,8 @@ func (r *runner) run(config *specs.Process) (int, error) {
|
|||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
detach = r.detach || r.create
|
detach = r.detach || (r.action == CT_ACT_CREATE)
|
||||||
startFn = r.container.Start
|
|
||||||
)
|
)
|
||||||
if !r.create {
|
|
||||||
startFn = r.container.Run
|
|
||||||
}
|
|
||||||
// Setting up IO is a two stage process. We need to modify process to deal
|
// Setting up IO is a two stage process. We need to modify process to deal
|
||||||
// with detaching containers, and then we get a tty after the container has
|
// with detaching containers, and then we get a tty after the container has
|
||||||
// started.
|
// started.
|
||||||
@@ -269,7 +266,18 @@ func (r *runner) run(config *specs.Process) (int, error) {
|
|||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
defer tty.Close()
|
defer tty.Close()
|
||||||
if err = startFn(process); err != nil {
|
|
||||||
|
switch r.action {
|
||||||
|
case CT_ACT_CREATE:
|
||||||
|
err = r.container.Start(process)
|
||||||
|
case CT_ACT_RESTORE:
|
||||||
|
err = r.container.Restore(process, r.criuOpts)
|
||||||
|
case CT_ACT_RUN:
|
||||||
|
err = r.container.Run(process)
|
||||||
|
default:
|
||||||
|
panic("Unknown action")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
r.destroy()
|
r.destroy()
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
@@ -313,7 +321,7 @@ func (r *runner) terminate(p *libcontainer.Process) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) checkTerminal(config *specs.Process) error {
|
func (r *runner) checkTerminal(config *specs.Process) error {
|
||||||
detach := r.detach || r.create
|
detach := r.detach || (r.action == CT_ACT_CREATE)
|
||||||
// Check command-line for sanity.
|
// Check command-line for sanity.
|
||||||
if detach && config.Terminal && r.consoleSocket == "" {
|
if detach && config.Terminal && r.consoleSocket == "" {
|
||||||
return fmt.Errorf("cannot allocate tty if runc will detach without setting console socket")
|
return fmt.Errorf("cannot allocate tty if runc will detach without setting console socket")
|
||||||
@@ -337,7 +345,15 @@ func validateProcessSpec(spec *specs.Process) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func startContainer(context *cli.Context, spec *specs.Spec, create bool) (int, error) {
|
type CtAct uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
CT_ACT_CREATE CtAct = iota + 1
|
||||||
|
CT_ACT_RUN
|
||||||
|
CT_ACT_RESTORE
|
||||||
|
)
|
||||||
|
|
||||||
|
func startContainer(context *cli.Context, spec *specs.Spec, action CtAct, criuOpts *libcontainer.CriuOpts) (int, error) {
|
||||||
id := context.Args().First()
|
id := context.Args().First()
|
||||||
if id == "" {
|
if id == "" {
|
||||||
return -1, errEmptyID
|
return -1, errEmptyID
|
||||||
@@ -372,7 +388,8 @@ func startContainer(context *cli.Context, spec *specs.Spec, create bool) (int, e
|
|||||||
detach: context.Bool("detach"),
|
detach: context.Bool("detach"),
|
||||||
pidFile: context.String("pid-file"),
|
pidFile: context.String("pid-file"),
|
||||||
preserveFDs: context.Int("preserve-fds"),
|
preserveFDs: context.Int("preserve-fds"),
|
||||||
create: create,
|
action: action,
|
||||||
|
criuOpts: criuOpts,
|
||||||
}
|
}
|
||||||
return r.run(&spec.Process)
|
return r.run(&spec.Process)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user