Merge pull request #611 from dmcgowan/snapshot-plugins

Add snapshot plugin type
This commit is contained in:
Michael Crosby 2017-03-07 16:44:35 -08:00 committed by GitHub
commit 2fb3b73b95
6 changed files with 91 additions and 15 deletions

View file

@ -5,4 +5,6 @@ import (
_ "github.com/docker/containerd/linux" _ "github.com/docker/containerd/linux"
_ "github.com/docker/containerd/services/content" _ "github.com/docker/containerd/services/content"
_ "github.com/docker/containerd/services/execution" _ "github.com/docker/containerd/services/execution"
_ "github.com/docker/containerd/snapshot/btrfs"
_ "github.com/docker/containerd/snapshot/overlay"
) )

View file

@ -13,6 +13,7 @@ func defaultConfig() *config {
Level: "info", Level: "info",
Socket: "/run/containerd/debug.sock", Socket: "/run/containerd/debug.sock",
}, },
Snapshotter: "overlay",
} }
} }
@ -39,6 +40,8 @@ type config struct {
Debug debug `toml:"debug"` Debug debug `toml:"debug"`
// Metrics and monitoring settings // Metrics and monitoring settings
Metrics metricsConfig `toml:"metrics"` Metrics metricsConfig `toml:"metrics"`
// Snapshotter specifies which snapshot driver to use
Snapshotter string `toml:"snapshotter"`
// Plugins provides plugin specific configuration for the initialization of a plugin // Plugins provides plugin specific configuration for the initialization of a plugin
Plugins map[string]toml.Primitive `toml:"plugins"` Plugins map[string]toml.Primitive `toml:"plugins"`

View file

@ -21,6 +21,7 @@ import (
"github.com/docker/containerd/content" "github.com/docker/containerd/content"
"github.com/docker/containerd/log" "github.com/docker/containerd/log"
"github.com/docker/containerd/plugin" "github.com/docker/containerd/plugin"
"github.com/docker/containerd/snapshot"
"github.com/docker/containerd/utils" "github.com/docker/containerd/utils"
metrics "github.com/docker/go-metrics" metrics "github.com/docker/go-metrics"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -101,7 +102,11 @@ func main() {
if err != nil { if err != nil {
return err return err
} }
services, err := loadServices(runtimes, store) snapshotter, err := loadSnapshotter(store)
if err != nil {
return err
}
services, err := loadServices(runtimes, store, snapshotter)
if err != nil { if err != nil {
return err return err
} }
@ -248,12 +253,45 @@ func loadRuntimes() (map[string]containerd.Runtime, error) {
return o, nil return o, nil
} }
func loadSnapshotter(store *content.Store) (snapshot.Snapshotter, error) {
for name, sr := range plugin.Registrations() {
if sr.Type != plugin.SnapshotPlugin {
continue
}
moduleName := fmt.Sprintf("snapshot-%s", conf.Snapshotter)
if name != moduleName {
continue
}
log.G(global).Infof("loading snapshot plugin %q...", name)
ic := &plugin.InitContext{
Root: conf.Root,
State: conf.State,
Store: store,
Context: log.WithModule(global, moduleName),
}
if sr.Config != nil {
if err := conf.decodePlugin(name, sr.Config); err != nil {
return nil, err
}
ic.Config = sr.Config
}
sn, err := sr.Init(ic)
if err != nil {
return nil, err
}
return sn.(snapshot.Snapshotter), nil
}
return nil, fmt.Errorf("snapshotter not loaded: %v", conf.Snapshotter)
}
func newGRPCServer() *grpc.Server { func newGRPCServer() *grpc.Server {
s := grpc.NewServer(grpc.UnaryInterceptor(interceptor)) s := grpc.NewServer(grpc.UnaryInterceptor(interceptor))
return s return s
} }
func loadServices(runtimes map[string]containerd.Runtime, store *content.Store) ([]plugin.Service, error) { func loadServices(runtimes map[string]containerd.Runtime, store *content.Store, sn snapshot.Snapshotter) ([]plugin.Service, error) {
var o []plugin.Service var o []plugin.Service
for name, sr := range plugin.Registrations() { for name, sr := range plugin.Registrations() {
if sr.Type != plugin.GRPCPlugin { if sr.Type != plugin.GRPCPlugin {
@ -261,11 +299,12 @@ func loadServices(runtimes map[string]containerd.Runtime, store *content.Store)
} }
log.G(global).Infof("loading grpc service plugin %q...", name) log.G(global).Infof("loading grpc service plugin %q...", name)
ic := &plugin.InitContext{ ic := &plugin.InitContext{
Root: conf.Root, Root: conf.Root,
State: conf.State, State: conf.State,
Context: log.WithModule(global, fmt.Sprintf("service-%s", name)), Context: log.WithModule(global, fmt.Sprintf("service-%s", name)),
Runtimes: runtimes, Runtimes: runtimes,
Store: store, Store: store,
Snapshotter: sn,
} }
if sr.Config != nil { if sr.Config != nil {
if err := conf.decodePlugin(name, sr.Config); err != nil { if err := conf.decodePlugin(name, sr.Config); err != nil {

View file

@ -6,6 +6,7 @@ import (
"github.com/docker/containerd" "github.com/docker/containerd"
"github.com/docker/containerd/content" "github.com/docker/containerd/content"
"github.com/docker/containerd/snapshot"
"golang.org/x/net/context" "golang.org/x/net/context"
"google.golang.org/grpc" "google.golang.org/grpc"
@ -16,6 +17,7 @@ type PluginType int
const ( const (
RuntimePlugin PluginType = iota + 1 RuntimePlugin PluginType = iota + 1
GRPCPlugin GRPCPlugin
SnapshotPlugin
) )
type Registration struct { type Registration struct {
@ -25,12 +27,13 @@ type Registration struct {
} }
type InitContext struct { type InitContext struct {
Root string Root string
State string State string
Runtimes map[string]containerd.Runtime Runtimes map[string]containerd.Runtime
Store *content.Store Store *content.Store
Config interface{} Snapshotter snapshot.Snapshotter
Context context.Context Config interface{}
Context context.Context
} }
type Service interface { type Service interface {

View file

@ -10,17 +10,36 @@ import (
"strings" "strings"
"github.com/docker/containerd" "github.com/docker/containerd"
"github.com/docker/containerd/plugin"
"github.com/docker/containerd/snapshot" "github.com/docker/containerd/snapshot"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/stevvooe/go-btrfs" "github.com/stevvooe/go-btrfs"
) )
type btrfsConfig struct {
Device string `toml:"device"`
}
func init() {
plugin.Register("snapshot-btrfs", &plugin.Registration{
Type: plugin.SnapshotPlugin,
Config: &btrfsConfig{},
Init: func(ic *plugin.InitContext) (interface{}, error) {
conf := ic.Config.(*btrfsConfig)
if conf.Device == "" {
return nil, errors.Errorf("btrfs requires \"device\" configuration")
}
return NewSnapshotter(conf.Device, filepath.Join(ic.Root, "snapshot", "btrfs"))
},
})
}
type Snapshotter struct { type Snapshotter struct {
device string // maybe we can resolve it with path? device string // maybe we can resolve it with path?
root string // root provides paths for internal storage. root string // root provides paths for internal storage.
} }
func NewSnapshotter(device, root string) (*Snapshotter, error) { func NewSnapshotter(device, root string) (snapshot.Snapshotter, error) {
var ( var (
active = filepath.Join(root, "active") active = filepath.Join(root, "active")
snapshots = filepath.Join(root, "snapshots") snapshots = filepath.Join(root, "snapshots")

View file

@ -10,17 +10,27 @@ import (
"sync" "sync"
"github.com/docker/containerd" "github.com/docker/containerd"
"github.com/docker/containerd/plugin"
"github.com/docker/containerd/snapshot" "github.com/docker/containerd/snapshot"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
func init() {
plugin.Register("snapshot-overlay", &plugin.Registration{
Type: plugin.SnapshotPlugin,
Init: func(ic *plugin.InitContext) (interface{}, error) {
return NewSnapshotter(filepath.Join(ic.Root, "snapshot", "overlay"))
},
})
}
type Snapshotter struct { type Snapshotter struct {
root string root string
links *cache links *cache
} }
func NewSnapshotter(root string) (*Snapshotter, error) { func NewSnapshotter(root string) (snapshot.Snapshotter, error) {
if err := os.MkdirAll(root, 0700); err != nil { if err := os.MkdirAll(root, 0700); err != nil {
return nil, err return nil, err
} }