def _load_catalogs_tsafe(self, refresh=False):
		self._installed_plugins_treeview_tracker = copy.deepcopy(self.config['plugins.installed'])
		for plugin in list(self._installed_plugins_treeview_tracker.keys()):
			# Remove plugins already found to be locally installed.
			if not self._installed_plugins_treeview_tracker[plugin]:
				self._installed_plugins_treeview_tracker.pop(plugin)
		if refresh:
			gui_utilities.glib_idle_add_once(self._model.clear)
		expiration = datetime.timedelta(seconds=smoke_zephyr.utilities.parse_timespan(self.config.get('cache.age', '4h')))
		self._update_status_bar_tsafe('Loading, catalogs...')
		self._load_catalog_local_tsafe()
		catalog_cache = self.catalog_plugins.get_cache()
		now = datetime.datetime.utcnow()
		for catalog_url in self.config['catalogs']:
			catalog_cache_dict = catalog_cache.get_catalog_by_url(catalog_url)
			if not refresh and catalog_cache_dict and catalog_cache_dict['created'] + expiration > now:
				catalog = self._load_catalog_from_cache_tsafe(catalog_cache_dict)
				if catalog is not None:
					continue
				catalog_cache_dict = None
			self.logger.debug("downloading catalog: {}".format(catalog_url))
			self._update_status_bar_tsafe("Loading, downloading catalog: {}".format(catalog_url))
			catalog = self._load_catalog_from_url_tsafe(catalog_url)
			if catalog is None and catalog_cache_dict is not None:
				self.logger.warning('failing over to loading the catalog from the cache')
				self._load_catalog_from_cache_tsafe(catalog_cache_dict)
		if self._installed_plugins_treeview_tracker:
			self._load_missing_plugins_tsafe()
		self._update_status_bar_tsafe('Loading completed')
		self._installed_plugins_treeview_tracker = None
	def _add_catalog_to_tree_tsafe(self, catalog):
		"""
		Create a :py:class:`._ModelNode` instance to representing the catalog, its
		data and add it to the TreeView model.

		:param catalog: The catalog to add to the TreeView.
		:type catalog: :py:class:`.Catalog`
		"""
		catalog_node = _ModelNode(
			id=catalog.id,
			installed=None,
			enabled=True,
			title=catalog.id,
			compatibility=None,
			version=None,
			visible_enabled=False,
			visible_installed=False,
			sensitive_installed=False,
			type=_ROW_TYPE_CATALOG
		)
		for repo in catalog.repositories.values():
			repo_node = _ModelNode(
				id=repo.id,
				installed=None,
				enabled=True,
				title=repo.title,
				compatibility=None,
				version=None,
				visible_enabled=False,
				visible_installed=False,
				sensitive_installed=False,
				type=_ROW_TYPE_REPOSITORY
			)
			catalog_node.children.append(repo_node)

			plugin_collection = self.catalog_plugins.get_collection(catalog.id, repo.id)
			for plugin_info in plugin_collection.values():
				installed = False
				enabled = False
				plugin_name = plugin_info['name']
				install_src = self.config['plugins.installed'].get(plugin_name)
				if install_src and repo.id == install_src['repo_id'] and catalog.id == install_src['catalog_id']:
					installed = True
					# plugin was added to treeview so it is removed from the temporary tracking dict
					self._installed_plugins_treeview_tracker.pop(plugin_name)
					enabled = plugin_name in self.config['plugins.enabled']
				repo_node.children.append(_ModelNamedRow(
					id=plugin_name,
					installed=installed,
					enabled=enabled,
					title=plugin_info['title'],
					compatibility='Yes' if self.catalog_plugins.is_compatible(catalog.id, repo.id, plugin_name) else 'No',
					version=plugin_info['version'],
					visible_enabled=True,
					visible_installed=True,
					sensitive_installed=True,
					type=_ROW_TYPE_PLUGIN
				))
		gui_utilities.glib_idle_add_once(self.__store_add_node, catalog_node)
	def _reload_plugin_tsafe(self, model_row, named_row, enabled=None):
		self._update_status_bar_tsafe('Reloading plugin...')
		pm = self.application.plugin_manager
		if enabled is None:
			enabled = named_row.id in pm.enabled_plugins
		pm.unload(named_row.id)
		try:
			klass = pm.load(named_row.id, reload_module=True)
		except Exception as error:
			self._on_plugin_load_error_tsafe(named_row.id, error)
			klass = None
		else:
			if enabled:
				pm.enable(named_row.id)
			self.__load_errors.pop(named_row.id, None)
		gui_utilities.glib_idle_add_once(self.__reload_plugin_post, model_row, named_row, klass)
		return klass
	def _plugin_install_tsafe(self, catalog_model, repo_model, model_row, named_row):
		self.__installing_plugin = named_row.id
		self.logger.debug("installing plugin '{0}'".format(named_row.id))
		self._update_status_bar_tsafe("Installing plugin {}...".format(named_row.title))
		_show_dialog_error_tsafe = functools.partial(gui_utilities.glib_idle_add_once, gui_utilities.show_dialog_error, 'Failed To Install', self.window)
		try:
			self.catalog_plugins.install_plugin(catalog_model.id, repo_model.id, named_row.id, self.plugin_path)
		except requests.exceptions.ConnectionError:
			self.logger.warning("failed to download plugin {}".format(named_row.id))
			_show_dialog_error_tsafe("Failed to download {} plugin, check your internet connection.".format(named_row.id))
			self._update_status_bar_tsafe("Installing plugin {} failed.".format(named_row.title))
			self.__installing_plugin = None
			return
		except Exception:
			self.logger.warning("failed to install plugin {}".format(named_row.id), exc_info=True)
			_show_dialog_error_tsafe("Failed to install {} plugin.".format(named_row.id))
			self._update_status_bar_tsafe("Installing plugin {} failed.".format(named_row.title))
			self.__installing_plugin = None
			return

		self.config['plugins.installed'][named_row.id] = {'catalog_id': catalog_model.id, 'repo_id': repo_model.id, 'plugin_id': named_row.id}
		self.logger.info("installed plugin '{}' from catalog:{}, repository:{}".format(named_row.id, catalog_model.id, repo_model.id))
		plugin = self._reload_plugin_tsafe(model_row, named_row)
		if self.config['plugins.pip.install_dependencies']:
			packages = smoke_zephyr.requirements.check_requirements(tuple(plugin.req_packages.keys()))
			if packages:
				self.logger.debug("installing missing or incompatible packages from PyPi for plugin '{0}'".format(named_row.id))
				self._update_status_bar_tsafe(
					"Installing {:,} dependenc{} for plugin {} from PyPi.".format(len(packages), 'y' if len(packages) == 1 else 'ies', named_row.title)
				)
				pip_results = self._pip_install(packages)
				if pip_results is None:
					self.logger.warning('pip install failed')
					_show_dialog_error_tsafe(
						"Failed to run pip to install package(s) for plugin {}.".format(named_row.id)
					)
				elif pip_results.status:
					self.logger.warning('pip install failed, exit status: ' + str(pip_results.status))
					_show_dialog_error_tsafe(
						"Failed to install pip package(s) for plugin {}.".format(named_row.id)
					)
				else:
					plugin = self._reload_plugin_tsafe(model_row, named_row)
		self.__installing_plugin = None
		gui_utilities.glib_idle_add_once(self.__plugin_install_post, catalog_model, repo_model, model_row, named_row)
Example #5
0
	def _load_url_treeview_tsafe(self, hostname=None, refresh=False):
		if refresh or not self._url_information['created']:
			self._url_information['data'] = self.application.rpc.graphql_find_file('get_site_templates.graphql')
			self._url_information['created'] = datetime.datetime.utcnow()
		url_information = self._url_information['data']
		if not url_information:
			return

		rows = []
		domains = []
		for edge in url_information['siteTemplates']['edges']:
			template = edge['node']
			for page in template['metadata']['pages']:
				if hostname and template['hostname'] and not template['hostname'].startswith(hostname):
					continue
				page = page.strip('/')
				resource = '/' + '/'.join((template.get('path', '').strip('/'), page)).lstrip('/')
				domains.append(template['hostname'])
				rows.append(_ModelNamedRow(
					hostname=template['hostname'],
					page=page,
					url=self._build_url(template['hostname'], resource, 'http'),
					classifiers=template['metadata']['classifiers'],
					authors=template['metadata']['authors'],
					description=template['metadata']['description'].strip('\n'),
					created=utilities.format_datetime(utilities.datetime_utc_to_local(template['created']))
				))

				if self._server_uses_ssl:
					rows.append(_ModelNamedRow(
						hostname=template['hostname'],
						page=page,
						url=self._build_url(template['hostname'], resource, 'https'),
						classifiers=template['metadata']['classifiers'],
						authors=template['metadata']['authors'],
						description=template['metadata']['description'].strip('\n'),
						created=utilities.format_datetime(utilities.datetime_utc_to_local(template['created']))
					))

		gui_utilities.glib_idle_add_once(self.gobjects['treeselection_url_selector'].unselect_all)
		gui_utilities.glib_idle_add_store_extend(self._url_model, rows, clear=True)
		# make domain list unique in case multiple pages are advertised for the domains
		domains = [[domain] for domain in set(domains)]
		gui_utilities.glib_idle_add_store_extend(self._hostname_list_store, domains, clear=True)
 def _show_dialog_error_tsafe(self, title, message):
     gui_utilities.glib_idle_add_once(gui_utilities.show_dialog_error,
                                      title, self.window, message)
    def _plugin_install_tsafe(self, catalog_model, repo_model, model_row,
                              named_row):
        self.__installing_plugin = named_row.id
        self.logger.debug("installing plugin '{0}'".format(named_row.id))
        self._update_status_bar_tsafe("Installing plugin {}...".format(
            named_row.title))
        _show_dialog_error_tsafe = functools.partial(
            gui_utilities.glib_idle_add_once, gui_utilities.show_dialog_error,
            'Failed To Install', self.window)
        try:
            self.catalog_plugins.install_plugin(catalog_model.id,
                                                repo_model.id, named_row.id,
                                                self.plugin_path)
        except requests.exceptions.ConnectionError:
            self.logger.warning("failed to download plugin {}".format(
                named_row.id))
            _show_dialog_error_tsafe(
                "Failed to download {} plugin, check your internet connection."
                .format(named_row.id))
            self._update_status_bar_tsafe(
                "Installing plugin {} failed.".format(named_row.title))
            self.__installing_plugin = None
            return
        except Exception:
            self.logger.warning("failed to install plugin {}".format(
                named_row.id),
                                exc_info=True)
            _show_dialog_error_tsafe("Failed to install {} plugin.".format(
                named_row.id))
            self._update_status_bar_tsafe(
                "Installing plugin {} failed.".format(named_row.title))
            self.__installing_plugin = None
            return

        self.config['plugins.installed'][named_row.id] = {
            'catalog_id': catalog_model.id,
            'repo_id': repo_model.id,
            'plugin_id': named_row.id
        }
        self.logger.info(
            "installed plugin '{}' from catalog:{}, repository:{}".format(
                named_row.id, catalog_model.id, repo_model.id))
        plugin = self._reload_plugin_tsafe(model_row, named_row)
        if self.config['plugins.pip.install_dependencies']:
            try:
                packages = smoke_zephyr.requirements.check_requirements(
                    tuple(plugin.req_packages.keys()))
            except ValueError:
                self.logger.warning(
                    "requirements check failed for plugin '{}', can not automatically install requirements"
                    .format(named_row.id))
                packages = None
            if packages:
                self.logger.debug(
                    "installing missing or incompatible packages from PyPi for plugin '{0}'"
                    .format(named_row.id))
                self._update_status_bar_tsafe(
                    "Installing {:,} dependenc{} for plugin {} from PyPi.".
                    format(len(packages), 'y' if len(packages) == 1 else 'ies',
                           named_row.title))
                if self.application.plugin_manager.library_path:
                    pip_results = self.application.plugin_manager.install_packages(
                        packages)
                else:
                    self.logger.warning(
                        'no library path to install plugin dependencies')
                    _show_dialog_error_tsafe(
                        "Failed to run pip to install package(s) for plugin {}."
                        .format(named_row.id))
                    # set pip results to none to safely complete and cleanly release installing lock.
                    pip_results = None
                if pip_results is None:
                    self.logger.warning('pip install failed')
                    _show_dialog_error_tsafe(
                        "Failed to run pip to install package(s) for plugin {}."
                        .format(named_row.id))
                elif pip_results.status:
                    self.logger.warning('pip install failed, exit status: ' +
                                        str(pip_results.status))
                    _show_dialog_error_tsafe(
                        "Failed to install pip package(s) for plugin {}.".
                        format(named_row.id))
                else:
                    plugin = self._reload_plugin_tsafe(model_row, named_row)
        self.__installing_plugin = None
        gui_utilities.glib_idle_add_once(self.__plugin_install_post,
                                         catalog_model, repo_model, model_row,
                                         named_row)
	def _update_status_bar_tsafe(self, string_to_set):
		gui_utilities.glib_idle_add_once(self._update_status_bar, string_to_set)
	def _show_dialog_error_tsafe(self, title, message):
		gui_utilities.glib_idle_add_once(gui_utilities.show_dialog_error, title, self.window, message)
 def _update_status_bar_tsafe(self, string_to_set):
     gui_utilities.glib_idle_add_once(self._update_status_bar,
                                      string_to_set)
Example #11
0
	def _load_plugins(self):
		"""
		Load the plugins which are available into the treeview to make them
		visible to the user.
		"""
		self.logger.debug('loading plugins')
		self._update_status_bar('Loading plugins...', idle=True)
		store = self._model
		store.clear()
		pm = self.application.plugin_manager
		self._module_errors = {}
		pm.load_all(on_error=self._on_plugin_load_error)
		model = (_LOCAL_REPOSITORY_ID, None, True, _LOCAL_REPOSITORY_TITLE, None, None, False, False, False, _ROW_TYPE_CATALOG)
		catalog_row = gui_utilities.glib_idle_add_wait(self._store_append, store, None, model)
		models = []
		for name, plugin in pm.loaded_plugins.items():
			if self.config['plugins.installed'].get(name):
				continue
			self.config['plugins.installed'][name] = None
			models.append(self._named_model(
				id=plugin.name,
				installed=True,
				enabled=plugin.name in pm.enabled_plugins,
				title=plugin.title,
				compatibility='Yes' if plugin.is_compatible else 'No',
				version=plugin.version,
				visible_enabled=True,
				visible_installed=True,
				sensitive_installed=False,
				type=_ROW_TYPE_PLUGIN
			))
		gui_utilities.glib_idle_add_once(self._store_extend, store, catalog_row, models)
		del models

		for name in self._module_errors.keys():
			model = (name, True, False, "{0} (Load Failed)".format(name), 'No', 'Unknown', True, True, False, _ROW_TYPE_PLUGIN)
			gui_utilities.glib_idle_add_once(self._store_append, store, catalog_row, model)

		self.logger.debug('loading catalog into plugin treeview')
		for catalog_id in self.catalog_plugins.catalog_ids():
			model = (catalog_id, None, True, catalog_id, None, None, False, False, False, _ROW_TYPE_CATALOG)
			catalog_row = gui_utilities.glib_idle_add_wait(self._store_append, store, None, model)
			for repo in self.catalog_plugins.get_repositories(catalog_id):
				model = (repo.id, None, True, repo.title, None, None, False, False, False, _ROW_TYPE_REPOSITORY)
				repo_row = gui_utilities.glib_idle_add_wait(self._store_append, store, catalog_row, model)
				plugin_collections = self.catalog_plugins.get_collection(catalog_id, repo.id)
				self._add_plugins_to_tree(catalog_id, repo, store, repo_row, plugin_collections)

		catalog_cache = self.catalog_plugins.get_cache()
		for catalog_id in catalog_cache:
			if self.catalog_plugins.catalogs.get(catalog_id, None):
				continue
			named_catalog = catalog_cache[catalog_id]
			model = (catalog_id, None, True, catalog_id, None, None, False, False, False, _ROW_TYPE_CATALOG)
			catalog_row = gui_utilities.glib_idle_add_wait(self._store_append, store, None, model)
			for repo in named_catalog.repositories:
				model = (repo.id, None, True, repo.title, None, None, False, False, False, _ROW_TYPE_REPOSITORY)
				repo_row = gui_utilities.glib_idle_add_wait(self._store_append, store, catalog_row, model)
				self._add_plugins_offline(catalog_id, repo.id, store, repo_row)

		gui_utilities.glib_idle_add_once(self._treeview_unselect)
		self._update_status_bar('Loading completed', idle=True)
Example #12
0
	def _update_status_bar(self, string_to_set, idle=False):
		if idle:
			gui_utilities.glib_idle_add_once(self.__update_status_bar, string_to_set)
		else:
			self.__update_status_bar(string_to_set)
Example #13
0
    def _load_url_treeview_tsafe(self, hostname=None, refresh=False):
        if refresh or not self._url_information['created']:
            self._url_information[
                'data'] = self.application.rpc.graphql_find_file(
                    'get_site_templates.graphql')
            self._url_information['created'] = datetime.datetime.utcnow()
        url_information = self._url_information['data']
        if not url_information:
            return

        rows = []
        domains = []
        for edge in url_information['siteTemplates']['edges']:
            template = edge['node']
            for page in template['metadata']['pages']:
                if hostname and template['hostname'] and not template[
                        'hostname'].startswith(hostname):
                    continue
                page = page.strip('/')
                resource = '/' + '/'.join(
                    (template.get('path', '').strip('/'), page)).lstrip('/')
                domains.append(template['hostname'])
                rows.append(
                    _ModelNamedRow(
                        hostname=template['hostname'],
                        page=page,
                        url=self._build_url(template['hostname'], resource,
                                            'http'),
                        classifiers=template['metadata']['classifiers'],
                        authors=template['metadata']['authors'],
                        description=template['metadata']['description'].strip(
                            '\n'),
                        created=utilities.format_datetime(
                            utilities.datetime_utc_to_local(
                                template['created']))))

                if self._server_uses_ssl:
                    rows.append(
                        _ModelNamedRow(
                            hostname=template['hostname'],
                            page=page,
                            url=self._build_url(template['hostname'], resource,
                                                'https'),
                            classifiers=template['metadata']['classifiers'],
                            authors=template['metadata']['authors'],
                            description=template['metadata']
                            ['description'].strip('\n'),
                            created=utilities.format_datetime(
                                utilities.datetime_utc_to_local(
                                    template['created']))))

        gui_utilities.glib_idle_add_once(
            self.gobjects['treeselection_url_selector'].unselect_all)
        gui_utilities.glib_idle_add_store_extend(self._url_model,
                                                 rows,
                                                 clear=True)
        # make domain list unique in case multiple pages are advertised for the domains
        domains = [[domain] for domain in set(domains)]
        gui_utilities.glib_idle_add_store_extend(self._hostname_list_store,
                                                 domains,
                                                 clear=True)