From bd79050b9bdb71bb526d94ade685e80007fefc1d Mon Sep 17 00:00:00 2001 From: "allen.wang" Date: Fri, 28 Dec 2018 15:14:33 +0800 Subject: [PATCH] add daemon config allow-multi-snapshotter to allow multi snapshotter in pouchd Signed-off-by: allen.wang --- ctrd/client.go | 55 +++++++++++++++++++++++++++++++++++ ctrd/interface.go | 1 + daemon/config/config.go | 3 ++ daemon/daemon.go | 2 +- daemon/daemon_utils.go | 56 ------------------------------------ main.go | 1 + test/cli_snapshotter_test.go | 33 +++++++++++++++++++++ 7 files changed, 94 insertions(+), 57 deletions(-) diff --git a/ctrd/client.go b/ctrd/client.go index 3d72aa51d..2e4f83d2e 100644 --- a/ctrd/client.go +++ b/ctrd/client.go @@ -13,6 +13,8 @@ import ( "github.com/containerd/containerd" eventstypes "github.com/containerd/containerd/api/events" "github.com/containerd/containerd/api/services/introspection/v1" + "github.com/containerd/containerd/plugin" + "github.com/containerd/containerd/snapshots" "github.com/containerd/typeurl" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -305,3 +307,56 @@ func (c *Client) collectContainerdEvents() { } } } + +// CheckSnapshotterValid checks whether the given snapshotter is valid +func (c *Client) CheckSnapshotterValid(snapshotter string, allowMultiSnapshotter bool) error { + var ( + driverFound = false + ) + + plugins, err := c.Plugins(context.Background(), []string{fmt.Sprintf("type==%s", plugin.SnapshotPlugin)}) + if err != nil { + logrus.Errorf("failed to get containerd plugins: %v", err) + return err + } + + for _, p := range plugins { + if p.Status != PluginStatusOk { + continue + } + + if p.ID == snapshotter { + driverFound = true + continue + } + + // if allowMultiSnapshotter, ignore check snapshots exist + if !allowMultiSnapshotter { + // check if other snapshotter exists snapshots + exist, err := c.checkSnapshotsExist(p.ID) + if err != nil { + return fmt.Errorf("failed to check snapshotter driver %s: %v", p.ID, err) + } + + if exist { + return fmt.Errorf("current snapshotter driver is %s, cannot change to %s", p.ID, snapshotter) + } + } + } + + if !driverFound { + return fmt.Errorf("containerd not support snapshotter driver %s", snapshotter) + } + + return nil +} + +func (c *Client) checkSnapshotsExist(snapshotter string) (existSnapshot bool, err error) { + fn := func(c context.Context, s snapshots.Info) error { + existSnapshot = true + return nil + } + + err = c.WalkSnapshot(context.Background(), snapshotter, fn) + return +} diff --git a/ctrd/interface.go b/ctrd/interface.go index a57684ffa..180d1797f 100644 --- a/ctrd/interface.go +++ b/ctrd/interface.go @@ -27,6 +27,7 @@ type APIClient interface { Version(ctx context.Context) (containerd.Version, error) Cleanup() error Plugins(ctx context.Context, filters []string) ([]Plugin, error) + CheckSnapshotterValid(snapshotter string, allowMultiSnapshotter bool) error } // ContainerAPIClient provides access to containerd container features. diff --git a/daemon/config/config.go b/daemon/config/config.go index fddf2cb61..83e81b2e6 100644 --- a/daemon/config/config.go +++ b/daemon/config/config.go @@ -117,6 +117,9 @@ type Config struct { // Snapshotter is passed to containerd, default to overlayfs Snapshotter string `json:"snapshotter,omitempty"` + + // AllowMultiSnapshotter allows multi snapshotter, default false + AllowMultiSnapshotter bool `json:"allow-multi-snapshotter,omitempty"` } // GetCgroupDriver gets cgroup driver used in runc. diff --git a/daemon/daemon.go b/daemon/daemon.go index 663c1f032..d9b3472ea 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -105,7 +105,7 @@ func NewDaemon(cfg *config.Config) *Daemon { ctrd.SetSnapshotterName(cfg.Snapshotter) } - if err = checkSnapshotterValid(ctrd.CurrentSnapshotterName(), ctrdClient); err != nil { + if err = ctrdClient.CheckSnapshotterValid(ctrd.CurrentSnapshotterName(), cfg.AllowMultiSnapshotter); err != nil { logrus.Errorf("failed to check snapshotter driver: %v", err) return nil } diff --git a/daemon/daemon_utils.go b/daemon/daemon_utils.go index f2a7d06cd..be99c06d6 100644 --- a/daemon/daemon_utils.go +++ b/daemon/daemon_utils.go @@ -1,7 +1,6 @@ package daemon import ( - "context" "fmt" "io/ioutil" "os" @@ -9,11 +8,6 @@ import ( "strings" "github.com/alibaba/pouch/apis/types" - "github.com/alibaba/pouch/ctrd" - - "github.com/containerd/containerd/plugin" - "github.com/containerd/containerd/snapshots" - "github.com/sirupsen/logrus" ) var ( @@ -58,53 +52,3 @@ func initialRuntime(baseDir string, runtimes map[string]types.Runtime) error { return nil } - -// checkSnapshotterValid checks whether the given snapshotter is valid -func checkSnapshotterValid(snapshotter string, ctrdClient ctrd.APIClient) error { - var ( - driverFound = false - ) - - plugins, err := ctrdClient.Plugins(context.Background(), []string{fmt.Sprintf("type==%s", plugin.SnapshotPlugin)}) - if err != nil { - logrus.Errorf("failed to get containerd plugins: %v", err) - return err - } - - for _, p := range plugins { - if p.Status != ctrd.PluginStatusOk { - continue - } - - if p.ID == snapshotter { - driverFound = true - continue - } - - // check if other snapshotter exists snapshots - exist, err := checkSnapshotsExist(p.ID, ctrdClient) - if exist { - return fmt.Errorf("current snapshotter driver is %s, cannot change to %s", p.ID, snapshotter) - } - - if err != nil { - return fmt.Errorf("failed to check snapshotter driver %s: %v", p.ID, err) - } - } - - if !driverFound { - return fmt.Errorf("containerd not support snapshotter driver %s", snapshotter) - } - - return nil -} - -func checkSnapshotsExist(snapshotter string, ctrdClient ctrd.APIClient) (existSnapshot bool, err error) { - fn := func(c context.Context, s snapshots.Info) error { - existSnapshot = true - return nil - } - - err = ctrdClient.WalkSnapshot(context.Background(), snapshotter, fn) - return -} diff --git a/main.go b/main.go index 912c5e9b5..193807a87 100644 --- a/main.go +++ b/main.go @@ -99,6 +99,7 @@ func setupFlags(cmd *cobra.Command) { flagSet.StringVar(&cfg.QuotaDriver, "quota-driver", "", "Set quota driver(grpquota/prjquota), if not set, it will set by kernel version") flagSet.StringVar(&cfg.ConfigFile, "config-file", "/etc/pouch/config.json", "Configuration file of pouchd") flagSet.StringVar(&cfg.Snapshotter, "snapshotter", "overlayfs", "Snapshotter driver of pouchd, it will be passed to containerd") + flagSet.BoolVar(&cfg.AllowMultiSnapshotter, "allow-multi-snapshotter", false, "If set true, pouchd will allow multi snapshotter") // volume config flagSet.StringVar(&cfg.VolumeConfig.DriverAlias, "volume-driver-alias", "", "Set volume driver alias, [;name1=alias1]") diff --git a/test/cli_snapshotter_test.go b/test/cli_snapshotter_test.go index 3b1caf50e..f1f19aac8 100644 --- a/test/cli_snapshotter_test.go +++ b/test/cli_snapshotter_test.go @@ -96,6 +96,39 @@ func (suite *PouchSnapshotterSuite) TestOldSnapshotterNotClean(c *check.C) { dcfg.KillDaemon() } +// TestAllowMultiSnapshotter tests pouchd with two snapshotter +func (suite *PouchSnapshotterSuite) TestAllowMultiSnapshotter(c *check.C) { + dcfg, err := StartDefaultDaemon("--snapshotter", "overlayfs", "--allow-multi-snapshotter") + c.Assert(err, check.IsNil) + + fileSystemInfo, err := mount.Lookup(dcfg.HomeDir) + c.Assert(err, check.IsNil) + + if fileSystemInfo.FSType != "btrfs" { + dcfg.KillDaemon() + c.Skip("btrfs is not supported! Ignore test suite TestOldSnapshotterNotClean.") + } + + result := RunWithSpecifiedDaemon(dcfg, "pull", busyboxImage) + c.Assert(result.ExitCode, check.Equals, 0) + dcfg.KillDaemon() + time.Sleep(10 * time.Second) + + dcfg, err = StartDefaultDaemon("--snapshotter", "btrfs", "--allow-multi-snapshotter") + c.Assert(err, check.IsNil) + + dcfg.KillDaemon() + time.Sleep(10 * time.Second) + + // clean image + dcfg, err = StartDefaultDaemon("--snapshotter", "overlayfs") + c.Assert(err, check.IsNil) + + result = RunWithSpecifiedDaemon(dcfg, "rmi", busyboxImage) + c.Assert(result.ExitCode, check.Equals, 0) + dcfg.KillDaemon() +} + // checkSnapshotsDir returns snapshots directory names by given snapshotter name func checkSnapshotsDir(homeDir string, snapshotter string) ([]string, error) { const snapshotterPrefix = "io.containerd.snapshotter.v1."