def get_state(self): backups = self._get_backups() unknown_plugins = self._get_unknown_plugins() return flask.jsonify(backups=backups, backup_in_progress=len(self._in_progress) > 0, unknown_plugins=unknown_plugins, restore_supported=is_os_compatible(["!windows"]))
def on_install_plugins(plugins): if not plugins: return force_user = settings.global_get_boolean(["plugins", "pluginmanager", "pip_force_user"]) pip_args = settings.global_get(["plugins", "pluginmanager", "pip_args"]) def log(line): click.echo(u"\t{}".format(line)) for plugin in plugins: octoprint_compatible = is_octoprint_compatible(*plugin["compatibility"]["octoprint"]) os_compatible = is_os_compatible(plugin["compatibility"]["os"]) compatible = octoprint_compatible and os_compatible if not compatible: if not octoprint_compatible and not os_compatible: click.echo(u"Cannot install plugin {}, it is incompatible to this version of " u"OctoPrint and the underlying operating system".format(plugin["id"])) elif not octoprint_compatible: click.echo(u"Cannot install plugin {}, it is incompatible to this version of " u"OctoPrint".format(plugin["id"])) elif not os_compatible: click.echo(u"Cannot install plugin {}, it is incompatible to the underlying " u"operating system".format(plugin["id"])) continue click.echo(u"Installing plugin {}".format(plugin["id"])) self.__class__._install_plugin(plugin, force_user=force_user, pip_args=pip_args, on_log=log)
def on_install_plugins(plugins): if not plugins: return force_user = settings.global_get_boolean(["plugins", "pluginmanager", "pip_force_user"]) pip_args = settings.global_get(["plugins", "pluginmanager", "pip_args"]) def log(line): click.echo("\t{}".format(line)) for plugin in plugins: octoprint_compatible = is_octoprint_compatible(*plugin["compatibility"]["octoprint"]) os_compatible = is_os_compatible(plugin["compatibility"]["os"]) compatible = octoprint_compatible and os_compatible if not compatible: if not octoprint_compatible and not os_compatible: click.echo("Cannot install plugin {}, it is incompatible to this version of " "OctoPrint and the underlying operating system".format(plugin["id"])) elif not octoprint_compatible: click.echo("Cannot install plugin {}, it is incompatible to this version of " "OctoPrint".format(plugin["id"])) elif not os_compatible: click.echo("Cannot install plugin {}, it is incompatible to the underlying " "operating system".format(plugin["id"])) continue click.echo("Installing plugin {}".format(plugin["id"])) self.__class__._install_plugin(plugin, force_user=force_user, pip_args=pip_args, on_log=log)
def on_install_plugins(plugins): force_user = self._settings.global_get_boolean(["plugins", "pluginmanager", "pip_force_user"]) pip_args = self._settings.global_get(["plugins", "pluginmanager", "pip_args"]) def on_log(line): self._logger.info(line) self._send_client_message("logline", dict(line=line, type="stdout")) for plugin in plugins: octoprint_compatible = is_octoprint_compatible(*plugin["compatibility"]["octoprint"]) os_compatible = is_os_compatible(plugin["compatibility"]["os"]) compatible = octoprint_compatible and os_compatible if not compatible: if not octoprint_compatible and not os_compatible: self._logger.warn(u"Cannot install plugin {}, it is incompatible to this version " u"of OctoPrint and the underlying operating system".format(plugin["id"])) elif not octoprint_compatible: self._logger.warn(u"Cannot install plugin {}, it is incompatible to this version " u"of OctoPrint".format(plugin["id"])) elif not os_compatible: self._logger.warn(u"Cannot install plugin {}, it is incompatible to the underlying " u"operating system".format(plugin["id"])) self._send_client_message("plugin_incompatible", dict(plugin=plugin["id"], octoprint_compatible=octoprint_compatible, os_compatible=os_compatible)) continue self._logger.info(u"Installing plugin {}".format(plugin["id"])) self._send_client_message("installing_plugin", dict(plugin=plugin["id"])) self.__class__._install_plugin(plugin, force_user=force_user, pip_args=pip_args, on_log=on_log)
def on_install_plugins(plugins): force_user = self._settings.global_get_boolean(["plugins", "pluginmanager", "pip_force_user"]) pip_args = self._settings.global_get(["plugins", "pluginmanager", "pip_args"]) def on_log(line): self._logger.info(line) self._send_client_message("logline", dict(line=line, type="stdout")) for plugin in plugins: octoprint_compatible = is_octoprint_compatible(*plugin["compatibility"]["octoprint"]) os_compatible = is_os_compatible(plugin["compatibility"]["os"]) compatible = octoprint_compatible and os_compatible if not compatible: if not octoprint_compatible and not os_compatible: self._logger.warn("Cannot install plugin {}, it is incompatible to this version " "of OctoPrint and the underlying operating system".format(plugin["id"])) elif not octoprint_compatible: self._logger.warn("Cannot install plugin {}, it is incompatible to this version " "of OctoPrint".format(plugin["id"])) elif not os_compatible: self._logger.warn("Cannot install plugin {}, it is incompatible to the underlying " "operating system".format(plugin["id"])) self._send_client_message("plugin_incompatible", dict(plugin=plugin["id"], octoprint_compatible=octoprint_compatible, os_compatible=os_compatible)) continue self._logger.info("Installing plugin {}".format(plugin["id"])) self._send_client_message("installing_plugin", dict(plugin=plugin["id"])) self.__class__._install_plugin(plugin, force_user=force_user, pip_args=pip_args, on_log=on_log)
def test_is_os_compatible(self, current_os, sys_platform, entries, expected): with mock.patch("sys.platform", sys_platform): from octoprint.util.platform import is_os_compatible actual = is_os_compatible(entries, current_os=current_os) self.assertEqual(actual, expected)
def map_repository_entry(entry): if not isinstance(entry, dict): return None result = copy.deepcopy(entry) if not "follow_dependency_links" in result: result["follow_dependency_links"] = False result["is_compatible"] = dict(octoprint=True, os=True) if "compatibility" in entry: if "octoprint" in entry["compatibility"] and entry["compatibility"][ "octoprint"] is not None and isinstance( entry["compatibility"]["octoprint"], (list, tuple)) and len( entry["compatibility"]["octoprint"]): result["is_compatible"]["octoprint"] = is_octoprint_compatible( *entry["compatibility"]["octoprint"]) if "os" in entry["compatibility"] and entry[ "compatibility"]["os"] is not None and isinstance( entry["compatibility"]["os"], (list, tuple)) and len(entry["compatibility"]["os"]): result["is_compatible"]["os"] = is_os_compatible( entry["compatibility"]["os"]) return result
def map_repository_entry(entry): result = copy.deepcopy(entry) if not "follow_dependency_links" in result: result["follow_dependency_links"] = False result["is_compatible"] = dict( octoprint=True, os=True ) if "compatibility" in entry: if "octoprint" in entry["compatibility"] and entry["compatibility"]["octoprint"] is not None and isinstance( entry["compatibility"]["octoprint"], (list, tuple)) and len(entry["compatibility"]["octoprint"]): result["is_compatible"]["octoprint"] = is_octoprint_compatible(*entry["compatibility"]["octoprint"]) if "os" in entry["compatibility"] and entry["compatibility"]["os"] is not None and isinstance( entry["compatibility"]["os"], (list, tuple)) and len(entry["compatibility"]["os"]): result["is_compatible"]["os"] = is_os_compatible(entry["compatibility"]["os"]) return result
def _restore_backup(cls, path, settings=None, plugin_manager=None, datafolder=None, on_install_plugins=None, on_report_unknown_plugins=None, on_invalid_backup=None, on_log_progress=None, on_log_error=None, on_restore_start=None, on_restore_done=None, on_restore_failed=None): if not is_os_compatible(["!windows"]): if callable(on_log_error): on_log_error( u"Restore is not supported on this operating system") if callable(on_restore_failed): on_restore_failed(path) return False restart_command = settings.global_get( ["server", "commands", "serverRestartCommand"]) basedir = settings._basedir cls._clean_dir_backup(basedir, on_log_progress=on_log_progress) plugin_repo = dict() repo_url = settings.global_get( ["plugins", "pluginmanager", "repository"]) if repo_url: plugin_repo = cls._get_plugin_repository_data(repo_url) if callable(on_restore_start): on_restore_start(path) try: with zipfile.ZipFile(path, "r") as zip: # read metadata try: metadata_zipinfo = zip.getinfo("metadata.json") except KeyError: if callable(on_invalid_backup): on_invalid_backup( u"Not an OctoPrint backup, lacks metadata.json") if callable(on_restore_failed): on_restore_failed(path) return False metadata_bytes = zip.read(metadata_zipinfo) metadata = json.loads(metadata_bytes) backup_version = get_comparable_version(metadata["version"], base=True) if backup_version > get_octoprint_version(base=True): if callable(on_invalid_backup): on_invalid_backup( u"Backup is from a newer version of OctoPrint and cannot be applied" ) if callable(on_restore_failed): on_restore_failed(path) return False # unzip to temporary folder temp = tempfile.mkdtemp() try: if callable(on_log_progress): on_log_progress( u"Unpacking backup to {}...".format(temp)) abstemp = os.path.abspath(temp) for member in zip.infolist(): abspath = os.path.abspath( os.path.join(temp, member.filename)) if abspath.startswith(abstemp): zip.extract(member, temp) # sanity check configfile = os.path.join(temp, "basedir", "config.yaml") if not os.path.exists(configfile): if callable(on_invalid_backup): on_invalid_backup(u"Backup lacks config.yaml") if callable(on_restore_failed): on_restore_failed(path) return False import yaml with codecs.open(configfile) as f: configdata = yaml.safe_load(f) if configdata.get("accessControl", dict()).get("enabled", True): userfile = os.path.join(temp, "basedir", "users.yaml") if not os.path.exists(userfile): if callable(on_invalid_backup): on_invalid_backup(u"Backup lacks users.yaml") if callable(on_restore_failed): on_restore_failed(path) return False if callable(on_log_progress): on_log_progress(u"Unpacked") # install available plugins plugins = [] plugin_list_file = os.path.join(temp, "plugin_list.json") if os.path.exists(plugin_list_file): with codecs.open(plugin_list_file, "r") as f: plugins = json.load(f) known_plugins = [] unknown_plugins = [] if plugins: if plugin_repo: for plugin in plugins: if plugin["key"] in plugin_manager.plugins: # already installed continue if plugin["key"] in plugin_repo: # not installed, can be installed from repository url known_plugins.append( plugin_repo[plugin["key"]]) else: # not installed, not installable unknown_plugins.append(plugin) else: # no repo, all plugins are not installable unknown_plugins = plugins if callable(on_log_progress): if known_plugins: on_log_progress( u"Known and installable plugins: {}". format(u", ".join( map(lambda x: x["id"], known_plugins)))) if unknown_plugins: on_log_progress(u"Unknown plugins: {}".format( u", ".join( map(lambda x: x["key"], unknown_plugins)))) if callable(on_install_plugins): on_install_plugins(known_plugins) if callable(on_report_unknown_plugins): on_report_unknown_plugins(unknown_plugins) # move config data basedir_backup = basedir + ".bck" basedir_extracted = os.path.join(temp, "basedir") if callable(on_log_progress): on_log_progress(u"Renaming {} to {}...".format( basedir, basedir_backup)) shutil.move(basedir, basedir_backup) try: if callable(on_log_progress): on_log_progress(u"Moving {} to {}...".format( basedir_extracted, basedir)) shutil.move(basedir_extracted, basedir) except: if callable(on_log_error): on_log_error(u"Error while restoring config data", exc_info=sys.exc_info()) on_log_error(u"Rolling back old config data") shutil.move(basedir_backup, basedir) if callable(on_restore_failed): on_restore_failed(path) return False if unknown_plugins: if callable(on_log_progress): on_log_progress( u"Writing info file about unknown plugins") if not os.path.isdir(datafolder): os.makedirs(datafolder) unknown_plugins_path = os.path.join( datafolder, UNKNOWN_PLUGINS_FILE) try: with codecs.open(unknown_plugins_path, mode="w", encoding="utf-8") as f: json.dump(unknown_plugins, f) except: if callable(on_log_error): on_log_error( u"Could not persist list of unknown plugins to {}" .format(unknown_plugins_path), exc_info=sys.exc_info()) finally: if callable(on_log_progress): on_log_progress(u"Removing temporary unpacked folder") shutil.rmtree(temp) except: exc_info = sys.exc_info() try: if callable(on_log_error): on_log_error(u"Error while running restore", exc_info=exc_info) if callable(on_restore_failed): on_restore_failed(path) finally: del exc_info return False finally: # remove zip if callable(on_log_progress): on_log_progress(u"Removing temporary zip") os.remove(path) # restart server if restart_command: import sarge if callable(on_log_progress): on_log_progress(u"Restarting...") if callable(on_restore_done): on_restore_done(path) try: sarge.run(restart_command, async_=True) except: if callable(on_log_error): on_log_error( u"Error while restarting via command {}".format( restart_command), exc_info=sys.exc_info()) on_log_error(u"Please restart OctoPrint manually") return False else: if callable(on_restore_done): on_restore_done(path) return True
def perform_restore(self): if not is_os_compatible(["!windows"]): return flask.make_response( u"Invalid request, the restores are not supported on the underlying operating system", 400) input_name = "file" input_upload_path = input_name + "." + self._settings.global_get( ["server", "uploads", "pathSuffix"]) if input_upload_path in flask.request.values: # file to restore was uploaded path = flask.request.values[input_upload_path] elif flask.request.json and "path" in flask.request.json: # existing backup is supposed to be restored backup_folder = self.get_plugin_data_folder() path = os.path.realpath( os.path.join(backup_folder, flask.request.json["path"])) if not path.startswith(backup_folder) \ or not os.path.exists(path) \ or is_hidden_path(path): return flask.abort(404) else: return flask.make_response( u"Invalid request, neither a file nor a path of a file to restore provided", 400) def on_install_plugins(plugins): force_user = self._settings.global_get_boolean( ["plugins", "pluginmanager", "pip_force_user"]) pip_args = self._settings.global_get( ["plugins", "pluginmanager", "pip_args"]) def on_log(line): self._logger.info(line) self._send_client_message("logline", dict(line=line, type="stdout")) for plugin in plugins: octoprint_compatible = is_octoprint_compatible( *plugin["compatibility"]["octoprint"]) os_compatible = is_os_compatible(plugin["compatibility"]["os"]) compatible = octoprint_compatible and os_compatible if not compatible: if not octoprint_compatible and not os_compatible: self._logger.warn( u"Cannot install plugin {}, it is incompatible to this version " u"of OctoPrint and the underlying operating system" .format(plugin["id"])) elif not octoprint_compatible: self._logger.warn( u"Cannot install plugin {}, it is incompatible to this version " u"of OctoPrint".format(plugin["id"])) elif not os_compatible: self._logger.warn( u"Cannot install plugin {}, it is incompatible to the underlying " u"operating system".format(plugin["id"])) self._send_client_message( "plugin_incompatible", dict(plugin=plugin["id"], octoprint_compatible=octoprint_compatible, os_compatible=os_compatible)) continue self._logger.info(u"Installing plugin {}".format(plugin["id"])) self._send_client_message("installing_plugin", dict(plugin=plugin["id"])) self.__class__._install_plugin(plugin, force_user=force_user, pip_args=pip_args, on_log=on_log) def on_report_unknown_plugins(plugins): self._send_client_message("unknown_plugins", payload=dict(plugins=plugins)) def on_log_progress(line): self._logger.info(line) self._send_client_message("logline", payload=dict(line=line, stream="stdout")) def on_log_error(line, exc_info=None): self._logger.error(line, exc_info=exc_info) self._send_client_message("logline", payload=dict(line=line, stream="stderr")) if exc_info is not None: exc_type, exc_value, exc_tb = exc_info output = traceback.format_exception(exc_type, exc_value, exc_tb) for line in output: self._send_client_message("logline", payload=dict(line=line.rstrip(), stream="stderr")) def on_restore_start(path): self._send_client_message("restore_started") def on_restore_done(path): self._send_client_message("restore_done") def on_restore_failed(path): self._send_client_message("restore_failed") def on_invalid_backup(line): on_log_error(line) archive = tempfile.NamedTemporaryFile(delete=False) archive.close() shutil.copy(path, archive.name) path = archive.name # noinspection PyTypeChecker thread = threading.Thread( target=self._restore_backup, args=(path, ), kwargs=dict(settings=self._settings, plugin_manager=self._plugin_manager, datafolder=self.get_plugin_data_folder(), on_install_plugins=on_install_plugins, on_report_unknown_plugins=on_report_unknown_plugins, on_invalid_backup=on_invalid_backup, on_log_progress=on_log_progress, on_log_error=on_log_error, on_restore_start=on_restore_start, on_restore_done=on_restore_done, on_restore_failed=on_restore_failed)) thread.daemon = True thread.start() return flask.jsonify(started=True)
def _restore_backup(cls, path, settings=None, plugin_manager=None, datafolder=None, on_install_plugins=None, on_report_unknown_plugins=None, on_invalid_backup=None, on_log_progress=None, on_log_error=None, on_restore_start=None, on_restore_done=None, on_restore_failed=None): if not is_os_compatible(["!windows"]): if callable(on_log_error): on_log_error(u"Restore is not supported on this operating system") if callable(on_restore_failed): on_restore_failed(path) return False restart_command = settings.global_get(["server", "commands", "serverRestartCommand"]) basedir = settings._basedir cls._clean_dir_backup(basedir, on_log_progress=on_log_progress) plugin_repo = dict() repo_url = settings.global_get(["plugins", "pluginmanager", "repository"]) if repo_url: plugin_repo = cls._get_plugin_repository_data(repo_url) if callable(on_restore_start): on_restore_start(path) try: with zipfile.ZipFile(path, "r") as zip: # read metadata try: metadata_zipinfo = zip.getinfo("metadata.json") except KeyError: if callable(on_invalid_backup): on_invalid_backup(u"Not an OctoPrint backup, lacks metadata.json") if callable(on_restore_failed): on_restore_failed(path) return False metadata_bytes = zip.read(metadata_zipinfo) metadata = json.loads(metadata_bytes) backup_version = get_comparable_version(metadata["version"], base=True) if backup_version > get_octoprint_version(base=True): if callable(on_invalid_backup): on_invalid_backup(u"Backup is from a newer version of OctoPrint and cannot be applied") if callable(on_restore_failed): on_restore_failed(path) return False # unzip to temporary folder temp = tempfile.mkdtemp() try: if callable(on_log_progress): on_log_progress(u"Unpacking backup to {}...".format(temp)) abstemp = os.path.abspath(temp) for member in zip.infolist(): abspath = os.path.abspath(os.path.join(temp, member.filename)) if abspath.startswith(abstemp): zip.extract(member, temp) # sanity check configfile = os.path.join(temp, "basedir", "config.yaml") if not os.path.exists(configfile): if callable(on_invalid_backup): on_invalid_backup(u"Backup lacks config.yaml") if callable(on_restore_failed): on_restore_failed(path) return False import yaml with codecs.open(configfile) as f: configdata = yaml.safe_load(f) if configdata.get("accessControl", dict()).get("enabled", True): userfile = os.path.join(temp, "basedir", "users.yaml") if not os.path.exists(userfile): if callable(on_invalid_backup): on_invalid_backup(u"Backup lacks users.yaml") if callable(on_restore_failed): on_restore_failed(path) return False if callable(on_log_progress): on_log_progress(u"Unpacked") # install available plugins with codecs.open(os.path.join(temp, "plugin_list.json"), "r") as f: plugins = json.load(f) known_plugins = [] unknown_plugins = [] if plugins: if plugin_repo: for plugin in plugins: if plugin["key"] in plugin_manager.plugins: # already installed continue if plugin["key"] in plugin_repo: # not installed, can be installed from repository url known_plugins.append(plugin_repo[plugin["key"]]) else: # not installed, not installable unknown_plugins.append(plugin) else: # no repo, all plugins are not installable unknown_plugins = plugins if callable(on_log_progress): if known_plugins: on_log_progress(u"Known and installable plugins: {}".format(u", ".join(map(lambda x: x["id"], known_plugins)))) if unknown_plugins: on_log_progress(u"Unknown plugins: {}".format(u", ".join(map(lambda x: x["key"], unknown_plugins)))) if callable(on_install_plugins): on_install_plugins(known_plugins) if callable(on_report_unknown_plugins): on_report_unknown_plugins(unknown_plugins) # move config data basedir_backup = basedir + ".bck" basedir_extracted = os.path.join(temp, "basedir") if callable(on_log_progress): on_log_progress(u"Renaming {} to {}...".format(basedir, basedir_backup)) os.rename(basedir, basedir_backup) try: if callable(on_log_progress): on_log_progress(u"Moving {} to {}...".format(basedir_extracted, basedir)) os.rename(basedir_extracted, basedir) except: if callable(on_log_error): on_log_error(u"Error while restoring config data", exc_info=sys.exc_info()) on_log_error(u"Rolling back old config data") os.rename(basedir_backup, basedir) if callable(on_restore_failed): on_restore_failed(path) return False if unknown_plugins: if callable(on_log_progress): on_log_progress(u"Writing info file about unknown plugins") if not os.path.isdir(datafolder): os.makedirs(datafolder) unknown_plugins_path = os.path.join(datafolder, UNKNOWN_PLUGINS_FILE) try: with codecs.open(unknown_plugins_path, mode="w", encoding="utf-8") as f: json.dump(unknown_plugins, f) except: if callable(on_log_error): on_log_error(u"Could not persist list of unknown plugins to {}".format(unknown_plugins_path), exc_info = sys.exc_info()) finally: if callable(on_log_progress): on_log_progress(u"Removing temporary unpacked folder") shutil.rmtree(temp) except: exc_info = sys.exc_info() try: if callable(on_log_error): on_log_error(u"Error while running restore", exc_info=exc_info) if callable(on_restore_failed): on_restore_failed(path) finally: del exc_info return False finally: # remove zip if callable(on_log_progress): on_log_progress(u"Removing temporary zip") os.remove(path) # restart server if restart_command: import sarge if callable(on_log_progress): on_log_progress(u"Restarting...") if callable(on_restore_done): on_restore_done(path) try: sarge.run(restart_command, async_=True) except: if callable(on_log_error): on_log_error(u"Error while restarting via command {}".format(restart_command), exc_info=sys.exc_info()) on_log_error(u"Please restart OctoPrint manually") return False else: if callable(on_restore_done): on_restore_done(path) return True
def perform_restore(self): if not is_os_compatible(["!windows"]): return flask.make_response(u"Invalid request, the restores are not supported on the underlying operating system", 400) input_name = "file" input_upload_path = input_name + "." + self._settings.global_get(["server", "uploads", "pathSuffix"]) if input_upload_path in flask.request.values: # file to restore was uploaded path = flask.request.values[input_upload_path] elif flask.request.json and "path" in flask.request.json: # existing backup is supposed to be restored backup_folder = self.get_plugin_data_folder() path = os.path.realpath(os.path.join(backup_folder, flask.request.json["path"])) if not path.startswith(backup_folder) \ or not os.path.exists(path) \ or is_hidden_path(path): return flask.abort(404) else: return flask.make_response(u"Invalid request, neither a file nor a path of a file to restore provided", 400) def on_install_plugins(plugins): force_user = self._settings.global_get_boolean(["plugins", "pluginmanager", "pip_force_user"]) pip_args = self._settings.global_get(["plugins", "pluginmanager", "pip_args"]) def on_log(line): self._logger.info(line) self._send_client_message("logline", dict(line=line, type="stdout")) for plugin in plugins: octoprint_compatible = is_octoprint_compatible(*plugin["compatibility"]["octoprint"]) os_compatible = is_os_compatible(plugin["compatibility"]["os"]) compatible = octoprint_compatible and os_compatible if not compatible: if not octoprint_compatible and not os_compatible: self._logger.warn(u"Cannot install plugin {}, it is incompatible to this version " u"of OctoPrint and the underlying operating system".format(plugin["id"])) elif not octoprint_compatible: self._logger.warn(u"Cannot install plugin {}, it is incompatible to this version " u"of OctoPrint".format(plugin["id"])) elif not os_compatible: self._logger.warn(u"Cannot install plugin {}, it is incompatible to the underlying " u"operating system".format(plugin["id"])) self._send_client_message("plugin_incompatible", dict(plugin=plugin["id"], octoprint_compatible=octoprint_compatible, os_compatible=os_compatible)) continue self._logger.info(u"Installing plugin {}".format(plugin["id"])) self._send_client_message("installing_plugin", dict(plugin=plugin["id"])) self.__class__._install_plugin(plugin, force_user=force_user, pip_args=pip_args, on_log=on_log) def on_report_unknown_plugins(plugins): self._send_client_message("unknown_plugins", payload=dict(plugins=plugins)) def on_log_progress(line): self._logger.info(line) self._send_client_message("logline", payload=dict(line=line, stream="stdout")) def on_log_error(line, exc_info=None): self._logger.error(line, exc_info=exc_info) self._send_client_message("logline", payload=dict(line=line, stream="stderr")) if exc_info is not None: exc_type, exc_value, exc_tb = exc_info output = traceback.format_exception(exc_type, exc_value, exc_tb) for line in output: self._send_client_message("logline", payload=dict(line=line.rstrip(), stream="stderr")) def on_restore_start(path): self._send_client_message("restore_started") def on_restore_done(path): self._send_client_message("restore_done") def on_restore_failed(path): self._send_client_message("restore_failed") def on_invalid_backup(line): on_log_error(line) archive = tempfile.NamedTemporaryFile(delete=False) archive.close() shutil.copy(path, archive.name) path = archive.name # noinspection PyTypeChecker thread = threading.Thread(target=self._restore_backup, args=(path,), kwargs=dict(settings=self._settings, plugin_manager=self._plugin_manager, datafolder=self.get_plugin_data_folder(), on_install_plugins=on_install_plugins, on_report_unknown_plugins=on_report_unknown_plugins, on_invalid_backup=on_invalid_backup, on_log_progress=on_log_progress, on_log_error=on_log_error, on_restore_start=on_restore_start, on_restore_done=on_restore_done, on_restore_failed=on_restore_failed)) thread.daemon = True thread.start() return flask.jsonify(started=True)
def is_wizard_required(self): return self._settings.global_get(["server", "firstRun" ]) and is_os_compatible(["!windows"])
def _restore_supported(cls, settings): return (is_os_compatible(["!windows"]) and not settings.get_boolean(["restore_unsupported"]) and os.environ.get("OCTOPRINT_BACKUP_RESTORE_UNSUPPORTED", False) not in valid_boolean_trues)