Beispiel #1
0
def factory_reset(master_controller=INJECTED):
    import glob
    import shutil

    logger.info('Wiping master eeprom...')
    master_controller.start()
    master_controller.factory_reset()
    master_controller.stop()

    logger.info('Removing databases...')
    # Delete databases.
    for f in constants.get_all_database_files():
        if os.path.exists(f):
            os.remove(f)

    # Delete plugins
    logger.info('Removing plugins...')
    plugin_dir = constants.get_plugin_dir()
    plugins = [
        name for name in os.listdir(plugin_dir)
        if os.path.isdir(os.path.join(plugin_dir, name))
    ]
    for plugin in plugins:
        shutil.rmtree(plugin_dir + plugin)

    config_files = constants.get_plugin_configfiles()
    for config_file in glob.glob(config_files):
        os.remove(config_file)
Beispiel #2
0
    def __init__(self,
                 web_interface=INJECTED, output_controller=INJECTED,
                 shutter_controller=INJECTED,
                 runtime_path=None,
                 plugins_path=None,
                 plugin_config_path=None):
        # type: (WebInterface, OutputController, ShutterController, str, str, str) -> None
        self._webinterface = web_interface
        self._output_controller = output_controller
        self._shuttercontroller = shutter_controller
        self._runtime_path = runtime_path or constants.get_plugin_runtime_dir()
        self._plugins_path = plugins_path or constants.get_plugin_dir()
        self._plugin_config_path = constants.get_plugin_config_dir()

        self._stopped = True
        self._logs = {}  # type: Dict[str, List[str]]
        self._runners = {}  # type: Dict[str, PluginRunner]
        self._runner_watchdogs = {}  # type: Dict[str, RunnerWatchdog]
        self._dependencies_timer = None  # type: Optional[Timer]
        self._dependencies_lock = Lock()

        self._metrics_controller = None
        self._metrics_collector = None
        self._web_service = None
Beispiel #3
0
    def restore_full_backup(self, data):
        """
        Restore a full backup containing the master eeprom and the sqlite databases.

        :param data: The backup to restore.
        :type data: Tar containing multiple files: master.eep, config.db, scheduled.db, power.db,
        eeprom_extensions.db, metrics.db and plugins as a string of bytes.
        :returns: dict with 'output' key.
        """
        import glob
        import shutil
        import tempfile
        import subprocess

        tmp_dir = tempfile.mkdtemp()
        tmp_sqlite_dir = '{0}/sqlite'.format(tmp_dir)
        try:
            with open('{0}/backup.tar'.format(tmp_dir), 'wb') as backup_file:
                backup_file.write(data)

            retcode = subprocess.call(
                'cd {0}; tar xf backup.tar'.format(tmp_dir), shell=True)
            if retcode != 0:
                raise Exception('The backup tar could not be extracted.')

            # Check if the sqlite db's are in a folder or not for backwards compatibility
            src_dir = tmp_sqlite_dir if os.path.isdir(
                tmp_sqlite_dir) else tmp_dir

            with open('{0}/master.eep'.format(src_dir), 'r') as eeprom_file:
                eeprom_content = eeprom_file.read()
                self.master_restore(eeprom_content)

            for filename, target in {
                    'config.db':
                    constants.get_config_database_file(),
                    'users.db':
                    constants.get_config_database_file(),
                    'power.db':
                    constants.get_power_database_file(),
                    'eeprom_extensions.db':
                    constants.get_eeprom_extension_database_file(),
                    'metrics.db':
                    constants.get_metrics_database_file(),
                    'gateway.db':
                    constants.get_gateway_database_file()
            }.items():
                source = '{0}/{1}'.format(src_dir, filename)
                if os.path.exists(source):
                    shutil.copyfile(source, target)

            # Restore the plugins if there are any
            backup_plugin_dir = '{0}/plugins'.format(tmp_dir)
            backup_plugin_content_dir = '{0}/content'.format(backup_plugin_dir)
            backup_plugin_config_files = '{0}/config/pi_*'.format(
                backup_plugin_dir)

            if os.path.isdir(backup_plugin_dir):
                plugin_dir = constants.get_plugin_dir()
                plugins = [
                    name for name in os.listdir(backup_plugin_content_dir)
                    if os.path.isdir(
                        os.path.join(backup_plugin_content_dir, name))
                ]
                for plugin in plugins:
                    dest_dir = '{0}{1}'.format(plugin_dir, plugin)
                    if os.path.isdir(dest_dir):
                        shutil.rmtree(dest_dir)
                    shutil.copytree(
                        '{0}/{1}/'.format(backup_plugin_content_dir, plugin),
                        '{0}{1}'.format(plugin_dir, plugin))

                config_files = constants.get_plugin_config_dir()
                for config_file in glob.glob(backup_plugin_config_files):
                    shutil.copy(config_file, '{0}/'.format(config_files))

            return {'output': 'Restore complete'}

        finally:
            shutil.rmtree(tmp_dir)
            # Restart the Cherrypy server after 1 second. Lets the current request terminate.
            threading.Timer(1, lambda: os._exit(0)).start()
Beispiel #4
0
    def get_full_backup(self):
        """
        Get a backup (tar) of the master eeprom, the sqlite databases and the plugins

        :returns: Tar containing multiple files: master.eep, config.db, scheduled.db, power.db,
        eeprom_extensions.db, metrics.db and plugins as a string of bytes.
        """
        _ = self  # Not static for consistency

        def backup_sqlite_db(input_db_path, backup_db_path):
            """ Backup an sqlite db provided the path to the db to backup and the backup db. """
            # Connect to database
            connection = sqlite3.connect(input_db_path)
            cursor = connection.cursor()

            # Lock database before making a backup
            cursor.execute('begin immediate')

            # Make new backup file
            shutil.copyfile(input_db_path, backup_db_path)

            # Unlock database
            connection.rollback()

        tmp_dir = tempfile.mkdtemp()
        tmp_sqlite_dir = '{0}/sqlite'.format(tmp_dir)
        os.mkdir(tmp_sqlite_dir)

        try:
            with open('{0}/master.eep'.format(tmp_sqlite_dir),
                      'w') as eeprom_file:
                eeprom_file.write(self.get_master_backup())

            for filename, source in {
                    'config.db':
                    constants.get_config_database_file(),
                    'power.db':
                    constants.get_power_database_file(),
                    'eeprom_extensions.db':
                    constants.get_eeprom_extension_database_file(),
                    'metrics.db':
                    constants.get_metrics_database_file(),
                    'gateway.db':
                    constants.get_gateway_database_file()
            }.items():
                if os.path.exists(source):
                    target = '{0}/{1}'.format(tmp_sqlite_dir, filename)
                    backup_sqlite_db(source, target)

            # Backup plugins
            tmp_plugin_dir = '{0}/{1}'.format(tmp_dir, 'plugins')
            tmp_plugin_content_dir = '{0}/{1}'.format(tmp_plugin_dir,
                                                      'content')
            tmp_plugin_config_dir = '{0}/{1}'.format(tmp_plugin_dir, 'config')
            os.mkdir(tmp_plugin_dir)
            os.mkdir(tmp_plugin_content_dir)
            os.mkdir(tmp_plugin_config_dir)

            plugin_dir = constants.get_plugin_dir()
            plugins = [
                name for name in os.listdir(plugin_dir)
                if os.path.isdir(os.path.join(plugin_dir, name))
            ]
            for plugin in plugins:
                shutil.copytree(
                    plugin_dir + plugin,
                    '{0}/{1}/'.format(tmp_plugin_content_dir, plugin))

            config_files = constants.get_plugin_configfiles()
            for config_file in glob.glob(config_files):
                shutil.copy(config_file, '{0}/'.format(tmp_plugin_config_dir))

            # Backup hex files
            tmp_hex_dir = '{0}/{1}'.format(tmp_dir, 'hex')
            os.mkdir(tmp_hex_dir)
            hex_files = constants.get_hex_files()
            for hex_file in glob.glob(hex_files):
                shutil.copy(hex_file, '{0}/'.format(tmp_hex_dir))

            # Backup general config stuff
            tmp_config_dir = '{0}/{1}'.format(tmp_dir, 'config')
            os.mkdir(tmp_config_dir)
            config_dir = constants.get_config_dir()
            for file_name in ['openmotics.conf', 'https.key', 'https.crt']:
                shutil.copy(os.path.join(config_dir, file_name),
                            '{0}/'.format(tmp_config_dir))

            retcode = subprocess.call(
                'cd {0}; tar cf backup.tar *'.format(tmp_dir), shell=True)
            if retcode != 0:
                raise Exception('The backup tar could not be created.')

            with open('{0}/backup.tar'.format(tmp_dir), 'r') as backup_file:
                return backup_file.read()

        finally:
            shutil.rmtree(tmp_dir)