Setup plugin ids and dependencies

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
Michael Crosby
2017-06-08 09:45:22 -07:00
parent 6bbed2c125
commit 94e7f8e943
31 changed files with 331 additions and 319 deletions

View File

@@ -29,7 +29,6 @@ import (
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/log"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/snapshot"
"github.com/containerd/containerd/sys"
"github.com/containerd/containerd/version"
metrics "github.com/docker/go-metrics"
@@ -105,41 +104,42 @@ func main() {
if err := plugin.Load(filepath.Join(conf.Root, "plugins")); err != nil {
return err
}
registerContentStore()
registerMetaDB()
// start debug and metrics APIs
if err := serveDebugAPI(); err != nil {
return err
}
monitor, err := loadMonitor()
if err != nil {
return err
}
runtimes, err := loadRuntimes(monitor)
if err != nil {
return err
}
store, err := resolveContentStore()
if err != nil {
return err
}
meta, err := resolveMetaDB(context)
if err != nil {
return err
}
defer meta.Close()
snapshotter, err := loadSnapshotter(store)
if err != nil {
return err
var (
services []plugin.Service
plugins = make(map[plugin.PluginType][]interface{})
)
for _, init := range plugin.Graph() {
id := init.URI()
log.G(global).WithField("type", init.Type).Infof("loading plugin %q...", id)
if !shouldLoad(init) {
continue
}
ic := plugin.NewContext(plugins)
ic.Root = filepath.Join(conf.Root, id)
ic.Context = log.WithModule(global, id)
if init.Config != nil {
if err := loadPluginConfig(init.ID, init.Config, ic); err != nil {
return err
}
}
p, err := init.Init(ic)
if err != nil {
return err
}
plugins[init.Type] = append(plugins[init.Type], p)
if s, ok := p.(plugin.Service); ok {
services = append(services, s)
}
}
differ, err := loadDiffer(snapshotter, store)
if err != nil {
return err
}
services, err := loadServices(runtimes, store, snapshotter, meta, differ)
if err != nil {
return err
}
// start the GRPC api with the execution service registered
server := newGRPCServer()
for _, service := range services {
@@ -159,7 +159,6 @@ func main() {
log.G(global).Infof("containerd successfully booted in %fs", time.Since(start).Seconds())
return handleSignals(signals, server)
}
if err := app.Run(os.Args); err != nil {
fmt.Fprintf(os.Stderr, "containerd: %s\n", err)
os.Exit(1)
@@ -184,10 +183,6 @@ func before(context *cli.Context) error {
name: "root",
d: &conf.Root,
},
{
name: "state",
d: &conf.State,
},
{
name: "address",
d: &conf.GRPC.Address,
@@ -254,139 +249,27 @@ func serveDebugAPI() error {
return nil
}
func resolveContentStore() (content.Store, error) {
cp := filepath.Join(conf.Root, "content")
return content.NewStore(cp)
func registerContentStore() {
plugin.Register(&plugin.Registration{
Type: plugin.ContentPlugin,
ID: "content",
Init: func(ic *plugin.InitContext) (interface{}, error) {
return content.NewStore(ic.Root)
},
})
}
func resolveMetaDB(ctx *cli.Context) (*bolt.DB, error) {
path := filepath.Join(conf.Root, "meta.db")
db, err := bolt.Open(path, 0644, nil)
if err != nil {
return nil, err
}
return db, nil
}
func loadRuntimes(monitor plugin.TaskMonitor) (map[string]plugin.Runtime, error) {
o := make(map[string]plugin.Runtime)
for name, rr := range plugin.Registrations() {
if rr.Type != plugin.RuntimePlugin {
continue
}
log.G(global).Infof("loading runtime plugin %q...", name)
ic := &plugin.InitContext{
Root: conf.Root,
State: conf.State,
Context: log.WithModule(global, fmt.Sprintf("runtime-%s", name)),
Monitor: monitor,
}
if rr.Config != nil {
if err := conf.decodePlugin(name, rr.Config); err != nil {
func registerMetaDB() {
plugin.Register(&plugin.Registration{
Type: plugin.MetadataPlugin,
ID: "bolt",
Init: func(ic *plugin.InitContext) (interface{}, error) {
if err := os.MkdirAll(ic.Root, 0700); err != nil {
return nil, err
}
ic.Config = rr.Config
}
vr, err := rr.Init(ic)
if err != nil {
return nil, err
}
o[name] = vr.(plugin.Runtime)
}
return o, nil
}
func loadMonitor() (plugin.TaskMonitor, error) {
var monitors []plugin.TaskMonitor
for name, m := range plugin.Registrations() {
if m.Type != plugin.TaskMonitorPlugin {
continue
}
log.G(global).Infof("loading monitor plugin %q...", name)
ic := &plugin.InitContext{
Root: conf.Root,
State: conf.State,
Context: log.WithModule(global, fmt.Sprintf("monitor-%s", name)),
}
mm, err := m.Init(ic)
if err != nil {
return nil, err
}
monitors = append(monitors, mm.(plugin.TaskMonitor))
}
if len(monitors) == 0 {
return plugin.NewNoopMonitor(), nil
}
return plugin.NewMultiTaskMonitor(monitors...), 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,
Content: 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 loadDiffer(snapshotter snapshot.Snapshotter, store content.Store) (plugin.Differ, error) {
for name, sr := range plugin.Registrations() {
if sr.Type != plugin.DiffPlugin {
continue
}
moduleName := fmt.Sprintf("diff-%s", conf.Differ)
if name != moduleName {
continue
}
log.G(global).Infof("loading differ plugin %q...", name)
ic := &plugin.InitContext{
Root: conf.Root,
State: conf.State,
Content: store,
Snapshotter: snapshotter,
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.(plugin.Differ), nil
}
return nil, fmt.Errorf("differ not loaded: %v", conf.Differ)
return bolt.Open(filepath.Join(ic.Root, "meta.db"), 0644, nil)
},
})
}
func newGRPCServer() *grpc.Server {
@@ -397,40 +280,6 @@ func newGRPCServer() *grpc.Server {
return s
}
func loadServices(runtimes map[string]plugin.Runtime,
store content.Store, sn snapshot.Snapshotter,
meta *bolt.DB, differ plugin.Differ) ([]plugin.Service, error) {
var o []plugin.Service
for name, sr := range plugin.Registrations() {
if sr.Type != plugin.GRPCPlugin {
continue
}
log.G(global).Infof("loading grpc service plugin %q...", name)
ic := &plugin.InitContext{
Root: conf.Root,
State: conf.State,
Context: log.WithModule(global, fmt.Sprintf("service-%s", name)),
Runtimes: runtimes,
Content: store,
Meta: meta,
Snapshotter: sn,
Differ: differ,
}
if sr.Config != nil {
if err := conf.decodePlugin(name, sr.Config); err != nil {
return nil, err
}
ic.Config = sr.Config
}
vs, err := sr.Init(ic)
if err != nil {
return nil, err
}
o = append(o, vs.(plugin.Service))
}
return o, nil
}
func serveGRPC(server *grpc.Server) error {
path := conf.GRPC.Address
if path == "" {
@@ -494,3 +343,23 @@ func dumpStacks() {
buf = buf[:stackSize]
logrus.Infof("=== BEGIN goroutine stack dump ===\n%s\n=== END goroutine stack dump ===", buf)
}
func loadPluginConfig(name string, c interface{}, ic *plugin.InitContext) error {
if err := conf.decodePlugin(name, c); err != nil {
return err
}
ic.Config = c
return nil
}
func shouldLoad(r *plugin.Registration) bool {
// only load certain plugins based on the config values
switch r.Type {
case plugin.SnapshotPlugin:
return r.URI() == conf.Snapshotter
case plugin.DiffPlugin:
return r.URI() == conf.Differ
default:
return true
}
}