Skip to content
This repository has been archived by the owner on Nov 8, 2022. It is now read-only.

Commit

Permalink
Expose plugin load timeout as a configurable option
Browse files Browse the repository at this point in the history
  • Loading branch information
obourdon committed Sep 10, 2016
1 parent 14a1611 commit b425920
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 10 deletions.
13 changes: 12 additions & 1 deletion control/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const (
defaultListenAddr string = "127.0.0.1"
defaultListenPort int = 8082
defaultMaxRunningPlugins int = 3
defaultPluginLoadTimeout int = 3
defaultPluginTrust int = 1
defaultAutoDiscoverPath string = ""
defaultKeyringPaths string = ""
Expand Down Expand Up @@ -70,6 +71,7 @@ type pluginConfigItem struct {
// match the field mapping that is defined here
type Config struct {
MaxRunningPlugins int `json:"max_running_plugins"yaml:"max_running_plugins"`
PluginLoadTimeout int `json:"plugin_load_timeout"yaml:"plugin_load_timeout"`
PluginTrust int `json:"plugin_trust_level"yaml:"plugin_trust_level"`
AutoDiscoverPath string `json:"auto_discover_path"yaml:"auto_discover_path"`
KeyringPaths string `json:"keyring_paths"yaml:"keyring_paths"`
Expand Down Expand Up @@ -99,6 +101,11 @@ const (
"type": "integer",
"minimum": 1
},
"plugin_load_timeout": {
"type": "integer",
"minimum": 3,
"maximum": 60
},
"keyring_paths" : {
"type": "string"
},
Expand All @@ -125,6 +132,7 @@ func GetDefaultConfig() *Config {
ListenAddr: defaultListenAddr,
ListenPort: defaultListenPort,
MaxRunningPlugins: defaultMaxRunningPlugins,
PluginLoadTimeout: defaultPluginLoadTimeout,
PluginTrust: defaultPluginTrust,
AutoDiscoverPath: defaultAutoDiscoverPath,
KeyringPaths: defaultKeyringPaths,
Expand All @@ -151,6 +159,10 @@ func (c *Config) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(v, &(c.MaxRunningPlugins)); err != nil {
return fmt.Errorf("%v (while parsing 'control::max_running_plugins')", err)
}
case "plugin_load_timeout":
if err := json.Unmarshal(v, &(c.PluginLoadTimeout)); err != nil {
return fmt.Errorf("%v (while parsing 'control::plugin_load_timeout')", err)
}
case "plugin_trust_level":
if err := json.Unmarshal(v, &(c.PluginTrust)); err != nil {
return fmt.Errorf("%v (while parsing 'control::plugin_trust_level')", err)
Expand Down Expand Up @@ -179,7 +191,6 @@ func (c *Config) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(v, &(c.ListenPort)); err != nil {
return err
}

default:
return fmt.Errorf("Unrecognized key '%v' in global config file while parsing 'control'", k)
}
Expand Down
2 changes: 2 additions & 0 deletions control/control.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ type managesPlugins interface {
SetMetricCatalog(catalogsMetrics)
GenerateArgs(logLevel int) plugin.Arg
SetPluginConfig(*pluginConfig)
SetPluginLoadTimeout(int)
}

type catalogsMetrics interface {
Expand Down Expand Up @@ -172,6 +173,7 @@ func OptSetConfig(cfg *Config) PluginControlOpt {
return func(c *pluginControl) {
c.Config = cfg
c.pluginManager.SetPluginConfig(cfg.Plugins)
c.pluginManager.SetPluginLoadTimeout(c.Config.PluginLoadTimeout)
}
}

Expand Down
1 change: 1 addition & 0 deletions control/control_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ func (m *MockPluginManagerBadSwap) UnloadPlugin(c core.Plugin) (*loadedPlugin, s
func (m *MockPluginManagerBadSwap) get(string) (*loadedPlugin, error) { return nil, nil }
func (m *MockPluginManagerBadSwap) teardown() {}
func (m *MockPluginManagerBadSwap) SetPluginConfig(*pluginConfig) {}
func (m *MockPluginManagerBadSwap) SetPluginLoadTimeout(int) {}
func (m *MockPluginManagerBadSwap) SetMetricCatalog(catalogsMetrics) {}
func (m *MockPluginManagerBadSwap) SetEmitter(gomit.Emitter) {}
func (m *MockPluginManagerBadSwap) GenerateArgs(int) plugin.Arg { return plugin.Arg{} }
Expand Down
7 changes: 6 additions & 1 deletion control/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ var (
Usage: fmt.Sprintf("The maximum number of instances of a loaded plugin to run (default: %v)", defaultMaxRunningPlugins),
EnvVar: "SNAP_MAX_PLUGINS",
}
flPluginLoadTimeout = cli.StringFlag{
Name: "plugin-load-timeout",
Usage: fmt.Sprintf("The maximum number seconds a plugin can take to load (default: %v)", defaultPluginLoadTimeout),
EnvVar: "SNAP_PLUGIN_LOAD_TIMEOUT",
}
flPluginTrust = cli.StringFlag{
Name: "plugin-trust, t",
Usage: fmt.Sprintf("0-2 (Disabled, Enabled, Warning; default: %v)", defaultPluginTrust),
Expand Down Expand Up @@ -65,5 +70,5 @@ var (
EnvVar: "SNAP_CONTROL_LISTEN_ADDR",
}

Flags = []cli.Flag{flNumberOfPLs, flAutoDiscover, flPluginTrust, flKeyringPaths, flCache, flControlRpcPort, flControlRpcAddr}
Flags = []cli.Flag{flNumberOfPLs, flPluginLoadTimeout, flAutoDiscover, flPluginTrust, flKeyringPaths, flCache, flControlRpcPort, flControlRpcAddr}
)
27 changes: 19 additions & 8 deletions control/plugin_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,11 @@ func (lp *loadedPlugin) Policy() *cpolicy.ConfigPolicy {
// the struct representing the object responsible for
// loading and unloading plugins
type pluginManager struct {
metricCatalog catalogsMetrics
loadedPlugins *loadedPlugins
logPath string
pluginConfig *pluginConfig
pluginLoadTimeout int
metricCatalog catalogsMetrics
loadedPlugins *loadedPlugins
logPath string
pluginConfig *pluginConfig
}

func newPluginManager(opts ...pluginManagerOpt) *pluginManager {
Expand All @@ -243,9 +244,10 @@ func newPluginManager(opts ...pluginManagerOpt) *pluginManager {
logPath = `c:\temp`
}
p := &pluginManager{
loadedPlugins: newLoadedPlugins(),
logPath: logPath,
pluginConfig: newPluginConfig(),
pluginLoadTimeout: defaultPluginLoadTimeout,
loadedPlugins: newLoadedPlugins(),
logPath: logPath,
pluginConfig: newPluginConfig(),
}

for _, opt := range opts {
Expand All @@ -264,6 +266,11 @@ func OptSetPluginConfig(cf *pluginConfig) pluginManagerOpt {
}
}

// SetPluginLoadTimeout sets plugin load timeout
func (p *pluginManager) SetPluginLoadTimeout(to int) {
p.pluginLoadTimeout = to
}

// SetPluginConfig sets plugin config
func (p *pluginManager) SetPluginConfig(cf *pluginConfig) {
p.pluginConfig = cf
Expand Down Expand Up @@ -294,7 +301,11 @@ func (p *pluginManager) LoadPlugin(details *pluginDetails, emitter gomit.Emitter
return nil, serror.New(err)
}

resp, err := ePlugin.Run(time.Second * 3)
pmLogger.WithFields(log.Fields{
"_block": "load-plugin",
"path": filepath.Base(lPlugin.Details.Exec),
}).Debug(fmt.Sprintf("plugin load timeout set to %ds", p.pluginLoadTimeout))
resp, err := ePlugin.Run(time.Second * time.Duration(p.pluginLoadTimeout))
if err != nil {
pmLogger.WithFields(log.Fields{
"_block": "load-plugin",
Expand Down
1 change: 1 addition & 0 deletions docs/SNAPD.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ $ $SNAP_PATH/bin/snapd [global options] command [command options] [arguments...]
--max-procs, -c '1' Set max cores to use for snap Agent. Default is 1 core. [$GOMAXPROCS]
--auto-discover, -a Auto discover paths separated by colons. [$SNAP_AUTODISCOVER_PATH]
--max-running-plugins, -m '3' The maximum number of instances of a loaded plugin to run [$SNAP_MAX_PLUGINS]
--plugin-load-timeout '3' The maximum number of seconds a plugin can take to load [$SNAP_PLUGIN_LOAD_TIMEOUT]
--cache-expiration '500ms' The time limit for which a metric cache entry is valid [$SNAP_CACHE_EXPIRATION]
--plugin-trust, -t '1' 0-2 (Disabled, Enabled, Warning) [$SNAP_TRUST_LEVEL]
--keyring-paths, -k Keyring paths for signing verification separated by colons [$SNAP_KEYRING_PATHS]
Expand Down
4 changes: 4 additions & 0 deletions docs/SNAPD_CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ control:
# plugin loaded in the system. Default value is 3
max_running_plugins: 3

# plugin_load_timeout sets the maximal time allowed for a plugin to load
# Default value is 3
plugin_load_timeout: 10

# keyring_paths sets the directory(s) to search for keyring files for signed
# plugins. This can be a comma separated list of directories
keyring_paths: /opt/snap/plugins/keyrings
Expand Down
1 change: 1 addition & 0 deletions examples/configs/snap-config-sample.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"listen_addr": "0.0.0.0",
"listen_port": 10082,
"max_running_plugins": 1,
"plugin_load_timeout": 10,
"keyring_paths": "/some/path/with/keyring/files",
"plugin_trust_level": 0,
"plugins": {
Expand Down
4 changes: 4 additions & 0 deletions examples/configs/snap-config-sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ control:
# plugin loaded in the system. Default value is 3
max_running_plugins: 1

# plugin_load_timeout sets the maximal time allowed for a plugin to load
# Default value is 3
plugin_load_timeout: 10

# keyring_paths sets the directory(s) to search for keyring files for signed
# plugins. This can be a comma separated list of directories
keyring_paths: /some/path/with/keyring/files
Expand Down
1 change: 1 addition & 0 deletions snapd.go
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,7 @@ func applyCmdLineFlags(cfg *Config, ctx *cli.Context) {
cfg.LogColors = setBoolVal(cfg.LogColors, ctx, "log-colors")
// next for the flags related to the control package
cfg.Control.MaxRunningPlugins = setIntVal(cfg.Control.MaxRunningPlugins, ctx, "max-running-plugins")
cfg.Control.PluginLoadTimeout = setIntVal(cfg.Control.PluginLoadTimeout, ctx, "plugin-load-timeout")
cfg.Control.PluginTrust = setIntVal(cfg.Control.PluginTrust, ctx, "plugin-trust")
cfg.Control.AutoDiscoverPath = setStringVal(cfg.Control.AutoDiscoverPath, ctx, "auto-discover")
cfg.Control.KeyringPaths = setStringVal(cfg.Control.KeyringPaths, ctx, "keyring-paths")
Expand Down

0 comments on commit b425920

Please sign in to comment.