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)
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
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()
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)