diff --git a/Makefile b/Makefile index 12b891e..fb0d2eb 100644 --- a/Makefile +++ b/Makefile @@ -307,6 +307,7 @@ install-ui: install-gui: install-glade install-ui install-files: set-versions dbus-service-install desktop-files install-plugins install-post-boot install-ga install-gui + install -d $(PYTHON_INST_DIR)/api install -d $(PYTHON_INST_DIR)/gui install -d $(PYTHON_INST_DIR)/gui/data/icons install -d $(PYTHON_INST_DIR)/branding @@ -356,6 +357,7 @@ install-files: set-versions dbus-service-install desktop-files install-plugins i install -m 644 -p $(SRC_DIR)/*.py $(PYTHON_INST_DIR)/ + install -m 644 -p $(SRC_DIR)/api/*.py $(PYTHON_INST_DIR)/api install -m 644 -p $(SRC_DIR)/gui/*.py $(PYTHON_INST_DIR)/gui install -m 644 -p $(SRC_DIR)/migrate/*.py $(PYTHON_INST_DIR)/migrate install -m 644 -p $(SRC_DIR)/branding/*.py $(PYTHON_INST_DIR)/branding diff --git a/rel-eng/packages/subscription-manager b/rel-eng/packages/subscription-manager index c569df4..b7ea50a 100644 --- a/rel-eng/packages/subscription-manager +++ b/rel-eng/packages/subscription-manager @@ -1 +1 @@ -1.15.9-3 ./ +1.15.9-4 ./ diff --git a/setup.py b/setup.py index ebac808..b27670b 100644 --- a/setup.py +++ b/setup.py @@ -23,6 +23,7 @@ setup(name="subscription-manager", author="Adrian Likins", author_email="alikins@redhat.com", packages=['src/subscription_manager', + 'src/subscription_manager/api', 'src/subscription_manager/gui', 'src/subscription_manager/plugin', 'src/subscription_manager/plugin/ostree', diff --git a/src/initial-setup/com_redhat_subscription_manager/gui/spokes/rhsm_gui.py b/src/initial-setup/com_redhat_subscription_manager/gui/spokes/rhsm_gui.py index 73cb2ca..09ca0b6 100644 --- a/src/initial-setup/com_redhat_subscription_manager/gui/spokes/rhsm_gui.py +++ b/src/initial-setup/com_redhat_subscription_manager/gui/spokes/rhsm_gui.py @@ -22,7 +22,6 @@ import sys from pyanaconda.ui.gui.spokes import NormalSpoke from pyanaconda.ui.common import FirstbootOnlySpokeMixIn from pyanaconda.ui.categories.system import SystemCategory -from pyanaconda.ui.gui import GUIObject log = logging.getLogger(__name__) @@ -81,6 +80,8 @@ class RHSMSpoke(FirstbootOnlySpokeMixIn, NormalSpoke): # each attaching different handlers. self._registergui.close_window_callback = self._close_window_callback + self._registergui._error_screen = registergui.CHOOSE_SERVER_PAGE + # we have a ref to _register_box, but need to remove it from # the regustergui.window (a GtkDialog), and add it to the main # box in the action area of our initial-setup screen. @@ -91,10 +92,12 @@ class RHSMSpoke(FirstbootOnlySpokeMixIn, NormalSpoke): self._registergui.initialize() def _close_window_callback(self): - pass + self._registergui.goto_error_screen() def finished(self): self._registergui.done() + self._registergui.cancel_button.hide() + self._registergui.register_button.hide() self._done = True # Update gui widgets to reflect state of self.data diff --git a/src/subscription_manager/async.py b/src/subscription_manager/async.py index 05433f9..41a9aab 100644 --- a/src/subscription_manager/async.py +++ b/src/subscription_manager/async.py @@ -61,7 +61,7 @@ class AsyncPool(object): Run pool stash refresh asynchronously. """ ga_GObject.idle_add(self._watch_thread) - threading.Thread(target=self._run_refresh, + threading.Thread(target=self._run_refresh, name="AsyncPoolRefreshThread", args=(active_on, callback, data)).start() @@ -105,11 +105,11 @@ class AsyncBind(object): ga_GObject.idle_add(except_callback, e, selection) def bind(self, pool, quantity, except_callback, bind_callback=None, cert_callback=None): - threading.Thread(target=self._run_bind, + threading.Thread(target=self._run_bind, name="AsyncBindBindThread", args=(pool, quantity, bind_callback, cert_callback, except_callback)).start() def unbind(self, serial, selection, callback, except_callback): - threading.Thread(target=self._run_unbind, + threading.Thread(target=self._run_unbind, name="AsyncBindUnbindThread", args=(serial, selection, callback, except_callback)).start() @@ -177,10 +177,13 @@ class AsyncRepoOverridesUpdate(object): ga_GObject.idle_add(callback, *args) def load_data(self, success_callback, failure_callback): - threading.Thread(target=self._load_data, args=(success_callback, failure_callback)).start() + threading.Thread(target=self._load_data, name="AsyncRepoOverridesUpdateLoadDataThread", + args=(success_callback, failure_callback)).start() def update_overrides(self, to_add, to_remove, success_callback, except_callback): - threading.Thread(target=self._update, args=(to_add, to_remove, success_callback, except_callback)).start() + threading.Thread(target=self._update, name="AsyncRepoOverridesUpdateUpdateOverridesThread", + args=(to_add, to_remove, success_callback, except_callback)).start() def remove_all_overrides(self, repo_ids, success_callback, except_callback): - threading.Thread(target=self._remove_all, args=(repo_ids, success_callback, except_callback)).start() + threading.Thread(target=self._remove_all, name="AsyncRepoOverridesUpdateRemoveAllOverridesThread", + args=(repo_ids, success_callback, except_callback)).start() diff --git a/src/subscription_manager/ga_loader.py b/src/subscription_manager/ga_loader.py index 59a00f6..1d7912e 100644 --- a/src/subscription_manager/ga_loader.py +++ b/src/subscription_manager/ga_loader.py @@ -94,9 +94,6 @@ class GaImporter(object): return None def load_module(self, fullname): - log.debug("ga_loader class %s loading virtual module %s from %s", - self.__class__.__name__, - fullname, self.virtual_modules[fullname]) if fullname in sys.modules: return sys.modules[fullname] @@ -150,14 +147,6 @@ class GaImporter(object): """ return self._new_module(self.namespace) - def _dirprint(self, module): - return - print "module ", module, type(module) - for i in dir(module): - if i == "__builtins__": - continue - print "\t%s = %s" % (i, getattr(module, i)) - class GaImporterGtk3(GaImporter): virtual_modules = {'subscription_manager.ga': None, diff --git a/src/subscription_manager/gui/allsubs.py b/src/subscription_manager/gui/allsubs.py index fe27082..5d6d7af 100644 --- a/src/subscription_manager/gui/allsubs.py +++ b/src/subscription_manager/gui/allsubs.py @@ -363,9 +363,7 @@ class AllSubscriptionsTab(widgets.SubscriptionManagerTab): # show pulsating progress bar while we wait for results self.pb = progress.Progress(pb_title, pb_label) self.timer = ga_GObject.timeout_add(100, self.pb.pulse) - tl = self.content.get_toplevel() - if tl.is_toplevel(): - self.pb.set_parent_window(tl) + self.pb.set_transient_for(self.parent_win) # fire off async refresh async_stash = async.AsyncPool(self.pool_stash) @@ -410,11 +408,7 @@ class AllSubscriptionsTab(widgets.SubscriptionManagerTab): self.pb = progress.Progress(_("Attaching"), _("Attaching subscription. Please wait.")) self.timer = ga_GObject.timeout_add(100, self.pb.pulse) - content_toplevel = self.content.get_toplevel() - # get_toplevel() can return a GtkWindow that is within another - # GtkWindow. See the get_toplevel() gtk docs - if content_toplevel.is_toplevel(): - self.pb.set_parent_window(content_toplevel) + self.pb.set_transient_for(self.parent_win) # Spin off a thread to handle binding the selected pool. # After it has completed the actual bind call, available # subs will be refreshed, but we won't re-run compliance @@ -451,10 +445,7 @@ class AllSubscriptionsTab(widgets.SubscriptionManagerTab): self.contract_selection = ContractSelectionWindow( self._contract_selected, self._contract_selection_cancelled) - content_toplevel = self.content.get_toplevel() - self.log.debug("content_toplevel %s", content_toplevel) - if content_toplevel.is_toplevel(): - self.contract_selection.set_parent_window(content_toplevel) + self.contract_selection.set_parent_window(self.parent_win) #self.log.debug("user_data %s", pw.get_user_data()) merged_pools.sort_virt_to_top() diff --git a/src/subscription_manager/gui/contract_selection.py b/src/subscription_manager/gui/contract_selection.py index 70233d2..9c5572e 100644 --- a/src/subscription_manager/gui/contract_selection.py +++ b/src/subscription_manager/gui/contract_selection.py @@ -168,14 +168,6 @@ class ContractSelectionWindow(widgets.SubmanBaseWidget): 'quantity_increment': quantity_increment, }) - def toplevel(self): - tl = self.get_toplevel() - if tl.is_toplevel(): - return tl - else: - self.log.debug("no toplevel window?") - return None - def set_parent_window(self, window): self.log.debug('window %s', window) self.contract_selection_window.set_transient_for(window) diff --git a/src/subscription_manager/gui/firstboot/rhsm_login.py b/src/subscription_manager/gui/firstboot/rhsm_login.py index 791607d..7c06f19 100644 --- a/src/subscription_manager/gui/firstboot/rhsm_login.py +++ b/src/subscription_manager/gui/firstboot/rhsm_login.py @@ -255,6 +255,7 @@ class moduleClass(RhsmFirstbootModule, registergui.RegisterScreen): else: return registergui.CHOOSE_SERVER_PAGE + @property def error_screen(self): return self._get_initial_screen() diff --git a/src/subscription_manager/gui/mysubstab.py b/src/subscription_manager/gui/mysubstab.py index 4c5922d..adc471c 100644 --- a/src/subscription_manager/gui/mysubstab.py +++ b/src/subscription_manager/gui/mysubstab.py @@ -146,9 +146,7 @@ class MySubscriptionsTab(widgets.SubscriptionManagerTab): self.pb = progress.Progress(_("Removing"), _("Removing subscription. Please wait.")) self.timer = ga_GObject.timeout_add(100, self.pb.pulse) - content_toplevel = self.content.get_toplevel() - if content_toplevel.is_toplevel(): - self.pb.set_parent_window(content_toplevel) + self.pb.set_transient_for(self.parent_win) self.async_bind.unbind(serial, selection, self._unsubscribe_callback, self._handle_unbind_exception) else: # unregistered, just delete the certs directly diff --git a/src/subscription_manager/gui/networkConfig.py b/src/subscription_manager/gui/networkConfig.py index 503839b..7efd0b1 100644 --- a/src/subscription_manager/gui/networkConfig.py +++ b/src/subscription_manager/gui/networkConfig.py @@ -264,7 +264,7 @@ class NetworkConfigDialog(widgets.SubmanBaseWidget): self._display_progress_bar() threading.Thread(target=self.test_connection_wrapper, args=(proxy_host, proxy_port, proxy_user, proxy_password), - name='test_connection_thread').start() + name='TestNetworkConnectionThread').start() def deleted(self, event, data): self.write_values() @@ -279,7 +279,7 @@ class NetworkConfigDialog(widgets.SubmanBaseWidget): else: self.progress_bar = progress.Progress(_("Testing Connection"), _("Please wait")) self.timer = ga_GObject.timeout_add(100, self.progress_bar.pulse) - self.progress_bar.set_parent_window(self.networkConfigDialog) + self.progress_bar.set_transient_for(self.networkConfigDialog) def _clear_progress_bar(self): if not self.progress_bar: # progress bar could be none iff self.test_connection is called directly diff --git a/src/subscription_manager/gui/progress.py b/src/subscription_manager/gui/progress.py index 61b2b2d..5aa938e 100644 --- a/src/subscription_manager/gui/progress.py +++ b/src/subscription_manager/gui/progress.py @@ -75,7 +75,7 @@ class Progress(widgets.SubmanBaseWidget): def set_status_label(self, text): self.statusLabel.set_text(text) - def set_parent_window(self, window): + def set_transient_for(self, window): self.progressWindow.set_transient_for(window) def _on_delete_event(self, widget, event): diff --git a/src/subscription_manager/gui/registergui.py b/src/subscription_manager/gui/registergui.py index c56ec5b..123c783 100644 --- a/src/subscription_manager/gui/registergui.py +++ b/src/subscription_manager/gui/registergui.py @@ -294,6 +294,7 @@ class RegisterScreen(widgets.SubmanBaseWidget): screen.container, tab_label=None) self._current_screen = CHOOSE_SERVER_PAGE + self._error_screen = DONT_CHANGE # values that will be set by the screens self.username = None @@ -337,15 +338,24 @@ class RegisterScreen(widgets.SubmanBaseWidget): # for subman gui, we don't need to switch screens on error # but for firstboot, we will go back to the info screen if # we have it. + @property def error_screen(self): - return DONT_CHANGE + return self._error_screen + + def goto_error_screen(self): + self._set_navigation_sensitive(True) + self._set_screen(self.error_screen) # FIXME: This exists because standalone gui needs to update the nav # buttons in it's own top level window, while firstboot needs to # update the buttons in the main firstboot window. Firstboot version # has additional logic for rhel5/rhel6 differences. + # FIXME: just split this into a registerWidget and a registerDialog def _set_navigation_sensitive(self, sensitive): - self.cancel_button.set_sensitive(sensitive) + # We could unsens the cancel button here, but since we use it as + # a 'do over' button that sends the dialog back to the start, just + # leave it enabled, to avoid leaving un unsens after an async error + # handler. self.register_button.set_sensitive(sensitive) def _set_screen(self, screen): @@ -421,6 +431,10 @@ class RegisterScreen(widgets.SubmanBaseWidget): # XXX it would be cool here to do some async spinning while the # main window gui refreshes itself + if failed: + self.goto_error_screen() + return + # FIXME: subman-gui needs this but initial-setup doesnt self.close_window_callback() @@ -1151,16 +1165,16 @@ class ChooseServerScreen(Screen): show_error_window(_("Unable to reach the server at %s:%s%s") % (hostname, port, prefix), self._parent.window) - return self._parent.error_screen() + return self._parent.error_screen except MissingCaCertException: show_error_window(_("CA certificate for subscription service has not been installed."), self._parent.window) - return self._parent.error_screen() + return self._parent.error_screen except ServerUrlParseError: show_error_window(_("Please provide a hostname with optional port and/or prefix: hostname[:port][/prefix]"), self._parent.window) - return self._parent.error_screen() + return self._parent.error_screen log.debug("Writing server data to rhsm.conf") CFG.save() diff --git a/src/subscription_manager/gui/reposgui.py b/src/subscription_manager/gui/reposgui.py index 2b6a391..4c00ead 100644 --- a/src/subscription_manager/gui/reposgui.py +++ b/src/subscription_manager/gui/reposgui.py @@ -250,7 +250,7 @@ class RepositoriesDialog(widgets.SubmanBaseWidget, HasSortableWidget): def _show_progress_bar(self, title, label, progress_parent=None): self.pb = progress.Progress(title, label, True) self.timer = ga_GObject.timeout_add(100, self.pb.pulse) - self.pb.set_parent_window(progress_parent or self._get_dialog_widget()) + self.pb.set_transient_for(progress_parent or self._get_dialog_widget()) def _clear_progress_bar(self): if self.pb: diff --git a/src/subscription_manager/gui/utils.py b/src/subscription_manager/gui/utils.py index 6535c7d..6c77ff7 100644 --- a/src/subscription_manager/gui/utils.py +++ b/src/subscription_manager/gui/utils.py @@ -264,5 +264,6 @@ class AsyncWidgetUpdater(object): ga_GObject.idle_add(widget_update.finished) def update(self, widget_update, backend_method, args=None, kwargs=None, exception_msg=None, callback=None): - threading.Thread(target=self.worker, args=(widget_update, - backend_method, args, kwargs, exception_msg, callback)).start() + threading.Thread(target=self.worker, name="AsyncWidgetUpdaterThread", + args=(widget_update, backend_method, args, + kwargs, exception_msg, callback)).start() diff --git a/subscription-manager.spec b/subscription-manager.spec index a44c4db..c762947 100644 --- a/subscription-manager.spec +++ b/subscription-manager.spec @@ -3,10 +3,22 @@ # For optional building of ostree-plugin sub package. Unrelated to systemd # but the same versions apply at the moment. %global has_ostree %use_systemd -%global use_old_firstboot (0%{?rhel} && 0%{?rhel} <= 6) +%global use_firstboot 0 +%global use_initial_setup 1 %global rhsm_plugins_dir /usr/share/rhsm-plugins %global use_gtk3 %use_systemd -%global use_initial_setup %use_systemd +%global rhel7_minor %(%{__grep} -o "7.[0-9]*" /etc/redhat-release |%{__sed} -s 's/7.//') + +%if 0%{?rhel} == 7 +%global use_initial_setup 1 +%global use_firstboot 0 +%endif + +# 6 < rhel < 7 +%if 0%{?rhel} == 6 +%global use_initial_setup 0 +%global use_firstboot 1 +%endif %global _hardened_build 1 %{!?__global_ldflags: %global __global_ldflags -Wl,-z,relro -Wl,-z,now} @@ -37,7 +49,7 @@ Name: subscription-manager Version: 1.15.9 -Release: 3%{?dist} +Release: 4%{?dist} Summary: Tools and libraries for subscription and repository management Group: System Environment/Base License: GPLv2 @@ -178,28 +190,26 @@ This package contains a GTK+ graphical interface for configuring and registering a system with a Red Hat Entitlement platform and manage subscriptions. +%if %use_firstboot %package -n subscription-manager-firstboot Summary: Firstboot screens for subscription manager Group: System Environment/Base Requires: %{name}-gui = %{version}-%{release} - -# Required for firstboot before RHEL 7: -%if %use_old_firstboot Requires: rhn-setup-gnome -%endif # Fedora can figure this out automatically, but RHEL cannot: Requires: librsvg2 %description -n subscription-manager-firstboot This package contains the firstboot screens for subscription-manager. +%endif %if %use_initial_setup %package -n subscription-manager-initial-setup-addon Summary: initial-setup screens for subscription-manager Group: System Environment/Base Requires: %{name}-gui = %{version}-%{release} -Requires: initial-setup-gui +Requires: initial-setup-gui >= 0.3.9.24-1 Obsoletes: subscription-manager-firstboot < 1.15.3-1 %description -n subscription-manager-initial-setup-addon @@ -354,6 +364,7 @@ rm -rf %{buildroot} # python package dirs %dir %{_datadir}/rhsm %dir %{_datadir}/rhsm/subscription_manager +%dir %{_datadir}/rhsm/subscription_manager/api %dir %{_datadir}/rhsm/subscription_manager/branding %dir %{_datadir}/rhsm/subscription_manager/model %dir %{_datadir}/rhsm/subscription_manager/plugin @@ -361,6 +372,7 @@ rm -rf %{buildroot} # code, python modules and packages %{_datadir}/rhsm/subscription_manager/*.py* +%{_datadir}/rhsm/subscription_manager/api/*.py* %{_datadir}/rhsm/subscription_manager/branding/*.py* # our gtk2/gtk3 compat modules @@ -469,8 +481,9 @@ rm -rf %{buildroot} %{_datadir}/anaconda/addons/com_redhat_subscription_manager/gui/spokes/*.py* %{_datadir}/anaconda/addons/com_redhat_subscription_manager/categories/*.py* %{_datadir}/anaconda/addons/com_redhat_subscription_manager/ks/*.py* -%else +%endif +%if %use_firstboot %files -n subscription-manager-firstboot %defattr(-,root,root,-) %{_datadir}/rhn/up2date_client/firstboot/rhsm_login.py* @@ -529,6 +542,16 @@ fi %endif %changelog +* Thu Aug 06 2015 Chris Rog 1.15.9-4 +- Fix spec file build errors (alikins@redhat.com) +- Require initial-setup >= 0.3.9.24, no fb on el7 (alikins@redhat.com) +- Remove use of Widget.is_toplevel() (alikins@redhat.com) +- Only build initial-setup rpm on rhel > 7.1 (alikins@redhat.com) +- 1243704: Goto error screen on 'cancel' (alikins@redhat.com) +- Add new api package to RPM. (awood@redhat.com) +- Turn off ga loading debug messages. (alikins@redhat.com) +- Specify a thread name for any threads we start. (alikins@redhat.com) + * Fri Jul 31 2015 Chris Rog 1.15.9-3 - 1248746: Fix layout of contract dialog (GTK3) (mstead@redhat.com) - 1248821: Add Gtk.Window to ga_gtk2.Gtk (alikins@redhat.com)