From 22d60d98747169568dcaf3c103e0e52f44b74474 Mon Sep 17 00:00:00 2001 From: Andrew Vagin Date: Wed, 25 May 2016 21:27:34 +0300 Subject: [PATCH] checkpoint: add the empty-ns option For example: ./runc checkpoint --empty-ns network CTID In this case criu creates a network namespace, but doesn't restore it. We are going to use this option to restore docker containers and Docker sets a hook to restore a network namespace. https://github.com/xemul/criu/issues/165 Signed-off-by: Andrew Vagin --- checkpoint.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/checkpoint.go b/checkpoint.go index 0e77d6cd1..abbd308f5 100644 --- a/checkpoint.go +++ b/checkpoint.go @@ -6,9 +6,11 @@ import ( "fmt" "strconv" "strings" + "syscall" "github.com/codegangsta/cli" "github.com/opencontainers/runc/libcontainer" + "github.com/opencontainers/runtime-spec/specs-go" ) var checkpointCommand = cli.Command{ @@ -29,6 +31,7 @@ checkpointed.`, cli.StringFlag{Name: "page-server", Value: "", Usage: "ADDRESS:PORT of the page server"}, cli.BoolFlag{Name: "file-locks", Usage: "handle file locks, for safety"}, cli.StringFlag{Name: "manage-cgroups-mode", Value: "", Usage: "cgroups mode: 'soft' (default), 'full' and 'strict'."}, + cli.StringSliceFlag{Name: "empty-ns", Usage: "create a namespace, but don't restore its properies"}, }, Action: func(context *cli.Context) error { container, err := getContainer(context) @@ -40,6 +43,9 @@ checkpointed.`, // these are the mandatory criu options for a container setPageServer(context, options) setManageCgroupsMode(context, options) + if err := setEmptyNsMask(context, options); err != nil { + return err + } if err := container.Checkpoint(options); err != nil { return err } @@ -88,3 +94,22 @@ func setManageCgroupsMode(context *cli.Context, options *libcontainer.CriuOpts) } } } + +var namespaceMapping = map[specs.NamespaceType]int{ + specs.NetworkNamespace: syscall.CLONE_NEWNET, +} + +func setEmptyNsMask(context *cli.Context, options *libcontainer.CriuOpts) error { + var nsmask int + + for _, ns := range context.StringSlice("empty-ns") { + f, exists := namespaceMapping[specs.NamespaceType(ns)] + if !exists { + return fmt.Errorf("namespace %q is not supported", ns) + } + nsmask |= f + } + + options.EmptyNs = uint32(nsmask) + return nil +}