Commit 57e4c0a3 authored by Anael Beutot's avatar Anael Beutot
Browse files

Plugin persistence

Save loaded plugins list on every plugin install/remove
Load plugins list on startup
parent 28472677
Loading
Loading
Loading
Loading
+45 −2
Original line number Diff line number Diff line
@@ -12,7 +12,9 @@ import struct
import socket
import termios
import tempfile
import threading
from fcntl import ioctl
import cPickle as pickle
from itertools import chain, imap
from subprocess import Popen, PIPE, STDOUT

@@ -215,6 +217,35 @@ class Handler(BasePlugin):
            self.main.stop()
            raise

    def start(self):
        BasePlugin.start(self)
        # load plugins if persistent file is here
        if os.path.isfile(self.main.config.plugins_store_path):
            logger.debug('Loading previous plugins')
            try:
                with open(self.main.config.plugins_store_path) as f:
                    to_load = pickle.load(f)
            except EnvironmentError as exc:
                logger.error('Cannot load previous plugins: %s (%s)',
                             exc.errno, exc.strerror)
            except pickle.UnpicklingError as exc:
                logger.error('Cannot read file, bad format, %s', exc)
            else:
                def plugins_install():
                    for p in to_load:
                        try:
                            self.plugin_install(self.main.rpc.rpc_con, None, p)
                        except Exception:
                            logger.error('Error while loading plugin %s', p)
                        else:
                            logger.debug('Successfuly loaded plugin %s', p)

                th = threading.Thread(target=plugins_install)
                th.daemon = True
                th.start()
        else:
            logger.debug('No previously loaded plugins')

    def stop(self):
        # remove script cache directory
        shutil.rmtree(self.scripts_dir, ignore_errors=True)
@@ -230,6 +261,18 @@ class Handler(BasePlugin):
        self.shells.clear()
        BasePlugin.stop(self)

    def update_plugin_index(self):
        self.tag_db['__main__']['plugins'].update_value()
        # write plugins to file
        try:
            with open(self.main.config.plugins_store_path, 'w') as f:
                pickle.dump([p for p in self.plugins], f)
        except EnvironmentError as exc:
            logger.error('Cannot save loaded plugins: %s (%s)',
                         exc.errno, exc.strerror)
        else:
            logger.debug('Plugins state saved')

    def execute_command(self, command):
        """Execute an arbitrary shell command on the host.

@@ -369,14 +412,14 @@ class Handler(BasePlugin):
        plugin_logger = logger.getChild('plugin.%s' % name)
        self.plugins[name] = Plugin(plugin_logger, TagDB(self.tag_db),
                                    name, sha1, content)
        self.tag_db['__main__']['plugins'].update_value()
        self.update_plugin_index()

    def plugin_uninstall(self, name):
        plugin = self.plugins.pop(name, None)
        if plugin is None:
            raise KeyError('Plugin %r is not running' % name)
        plugin.uninstall()
        self.tag_db['__main__']['plugins'].update_value()
        self.update_plugin_index()

    def plugin_run(self, name, method, owner, batch=None, **kwargs):
        if name not in self.plugins: