[node-patches] Change in ovirt-node[master]: installer: Add upgrade/downgrade/reinstall path

fabiand at fedoraproject.org fabiand at fedoraproject.org
Fri Feb 22 12:18:08 UTC 2013


Fabian Deutsch has uploaded a new change for review.

Change subject: installer: Add upgrade/downgrade/reinstall path
......................................................................

installer: Add upgrade/downgrade/reinstall path

This patch adds the codepath for up-/downgrades and reinstalls.

Change-Id: I1a56227f2512466b78e70b45cfbb8119980e5b60
Signed-off-by: Fabian Deutsch <fabiand at fedoraproject.org>
---
M scripts/tui/src/ovirt/node/config/defaults.py
M scripts/tui/src/ovirt/node/installer/progress_page.py
A scripts/tui/src/ovirt/node/installer/upgrade_page.py
M scripts/tui/src/ovirt/node/installer/welcome_page.py
M scripts/tui/src/ovirt/node/ui/__init__.py
M scripts/tui/src/ovirt/node/ui/urwid_builder.py
M scripts/tui/src/ovirt/node/utils/system.py
7 files changed, 223 insertions(+), 54 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-node refs/changes/11/12311/1

diff --git a/scripts/tui/src/ovirt/node/config/defaults.py b/scripts/tui/src/ovirt/node/config/defaults.py
index 5bca3a9..61f947e 100644
--- a/scripts/tui/src/ovirt/node/config/defaults.py
+++ b/scripts/tui/src/ovirt/node/config/defaults.py
@@ -1199,15 +1199,18 @@
             "OVIRT_VOL_CONFIG_SIZE",
             "OVIRT_VOL_DATA_SIZE",
             "OVIRT_INSTALL",
+            "OVIRT_UPGRADE",
             )
 
     @NodeConfigFileSection.map_and_update_defaults_decorator
     def update(self, init, root_install, overcommit, root_size, efi_size,
-               swap_size, logging_size, config_size, data_size, install):
+               swap_size, logging_size, config_size, data_size, install,
+               upgrade):
         # FIXME no checking!
         return {"OVIRT_INIT": ",".join(init),
                 "OVIRT_ROOT_INSTALL": "y" if root_install else None,
-                "OVIRT_INSTALL": "1" if install else None}
+                "OVIRT_INSTALL": "1" if install else None,
+                "OVIRT_UPGRADE": "1" if install else None}
 
     def retrieve(self):
         cfg = dict(NodeConfigFileSection.retrieve(self))
@@ -1219,10 +1222,23 @@
     def transaction(self):
         return None
 
-    def install_on(self, init):
+    def install_on(self, init, root_size, efi_size, swap_size, logging_size,
+                   config_size, data_size):
         """Convenience function which can be used to set the parameters which
         are going to be picked up by the installer backend to install Node on
         the given storage with the given othere params
         """
         self.update(init=init,
-                    install=True)
+                    install=True,
+                    root_size=root_size,
+                    efi_size=efi_size,
+                    swap_size=swap_size,
+                    logging_size=logging_size,
+                    config_size=config_size,
+                    data_size=data_size)
+
+    def upgrade(self):
+        """Convenience function setting the params to upgrade
+        """
+        self.update(upgrade=True,
+                    install=None)
diff --git a/scripts/tui/src/ovirt/node/installer/progress_page.py b/scripts/tui/src/ovirt/node/installer/progress_page.py
index 83e264d..97e09db 100644
--- a/scripts/tui/src/ovirt/node/installer/progress_page.py
+++ b/scripts/tui/src/ovirt/node/installer/progress_page.py
@@ -50,8 +50,9 @@
         return {}
 
     def ui_content(self):
-        ws = [ui.Header("header[0]", "%s is beeing installed ..." %
-                        self.application.product.PRODUCT_SHORT),
+        method = "Installing"
+        product = self.application.product.PRODUCT_SHORT
+        ws = [ui.Header("header[0]", "%s %s" % (method, product)),
               ui.Divider("divider[0]"),
               ui.ProgressBar("progressbar", 0),
               ui.Divider("divider[1]"),
@@ -83,16 +84,17 @@
         return self.progress_plugin.logger
 
     def run(self):
-        self.progress_plugin.widgets["action.reboot"].enabled(False)
-        time.sleep(0.3)  # Give the UI some time to build
-        transaction = self.__build_transaction()
-
-        progressbar = self.progress_plugin.widgets["progressbar"]
-        log = self.progress_plugin.widgets["log"]
-        log_lines = []
-
-        txlen = len(transaction)
         try:
+            self.progress_plugin.widgets["action.reboot"].enabled(False)
+            time.sleep(0.3)  # Give the UI some time to build
+            transaction = self.__build_transaction()
+
+            progressbar = self.progress_plugin.widgets["progressbar"]
+            log = self.progress_plugin.widgets["log"]
+            log_lines = []
+
+            txlen = len(transaction)
+
             for idx, tx_element in transaction.step():
                 idx += 1
                 self.logger.debug("Running %s: %s" % (idx, tx_element))
@@ -108,8 +110,9 @@
                 log_lines[-1] = "%s (Done)" % log_lines[-1]
                 log.text("\n".join(log_lines))
         except Exception as e:
-            log.text("Exception: %s" % repr(e))
-            self.logger.debug(traceback.format_exc())
+            msg = "Exception: %s" % repr(e)
+            self.logger.warning(msg, exc_info=True)
+            log.text(msg)
             raise
         finally:
             self.progress_plugin.widgets["action.reboot"].enabled(True)
@@ -118,14 +121,29 @@
         self.progress_plugin.application.ui.force_redraw()
 
     def __build_transaction(self):
+        """Determin what kind of transaction to build
+        Builds transactions for:
+        - Installation
+        - Upgrade
+        """
+        cfg = self.__build_config()
+
+        self.logger.debug("Building transaction")
+
         tx = utils.Transaction("Installation")
 
-        cfg = self.__build_config()
-        tx += [self.UpdateDefaultsFromModels(cfg),
-               self.PartitionAndFormat(cfg["installation.devices"]),
-               self.SetPassword(cfg["root.password_confirmation"]),
-               self.InstallBootloader(cfg["boot.device"]),
-               self.SetKeyboardLayout(cfg["keyboard.layout"])]
+        if cfg["method"] in ["install"]:
+            tx += [self.UpdateDefaultsFromModels(cfg),
+                   self.PartitionAndFormat(cfg["installation.devices"]),
+                   self.SetPassword(cfg["root.password_confirmation"]),
+                   self.InstallImageAndBootloader(cfg["boot.device"]),
+                   self.SetKeyboardLayout(cfg["keyboard.layout"])]
+
+        elif cfg["method"] in ["upgrade", "downgrade", "reinstall"]:
+            tx.title = "Update"
+            tx += [self.InstallImageAndBootloader()]
+
+        self.logger.debug("Built transaction: %s" % tx)
 
         return tx
 
@@ -144,7 +162,7 @@
         return config
 
     class UpdateDefaultsFromModels(utils.Transaction.Element):
-        title = "Write configuration file"
+        title = "Writing configuration file"
 
         def __init__(self, cfg):
             super(InstallerThread.UpdateDefaultsFromModels, self).__init__()
@@ -152,16 +170,18 @@
 
         def prepare(self):
             # Update/Write the config file
+            cfg = self.config
             model = defaults.Installation()
-            model.update(init=[self.config["boot.device"]] +
-                         self.config["installation.devices"],
+
+            model.update(init=[cfg["boot.device"]] +
+                         cfg["installation.devices"],
                          install="1",
-                         root_size=self.config["storage.root_size"],
-                         efi_size=self.config["storage.efi_size"],
-                         swap_size=self.config["storage.swap_size"],
-                         logging_size=self.config["storage.logging_size"],
-                         config_size=self.config["storage.config_size"],
-                         data_size=self.config["storage.data_size"])
+                         root_size=cfg["storage.root_size"],
+                         efi_size=cfg["storage.efi_size"],
+                         swap_size=cfg["storage.swap_size"],
+                         logging_size=cfg["storage.logging_size"],
+                         config_size=cfg["storage.config_size"],
+                         data_size=cfg["storage.data_size"])
 
             kbd = defaults.Keyboard()
             kbd.update(self.config["keyboard.layout"])
@@ -199,13 +219,15 @@
             if not admin_pw_set:
                 raise RuntimeError("Failed to set root password")
 
-    class InstallBootloader(utils.Transaction.Element):
-        title_tpl = "Installing Bootloader Configuration to '%s'"
-
-        def __init__(self, dst):
+    class InstallImageAndBootloader(utils.Transaction.Element):
+        def __init__(self, dst=None):
             self.dst = dst
-            self.title = self.title_tpl % dst
-            super(InstallerThread.InstallBootloader, self).__init__()
+            if dst:
+                self.title = "Installing Image and Bootloader " + \
+                    "Configuration to '%s'" % dst
+            else:
+                self.title = "Updating Image and Bootloader"
+            super(InstallerThread.InstallImageAndBootloader, self).__init__()
 
         def commit(self):
             from ovirtnode.install import Install
diff --git a/scripts/tui/src/ovirt/node/installer/upgrade_page.py b/scripts/tui/src/ovirt/node/installer/upgrade_page.py
new file mode 100644
index 0000000..18d01df
--- /dev/null
+++ b/scripts/tui/src/ovirt/node/installer/upgrade_page.py
@@ -0,0 +1,85 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# password_page.py - Copyright (C) 2013 Red Hat, Inc.
+# Written by Fabian Deutsch <fabiand at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA  02110-1301, USA.  A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+from ovirt.node import plugins, ui, installer, exceptions
+
+"""
+Password confirmation page for the upgarde part of the installer
+"""
+
+
+class Plugin(plugins.NodePlugin):
+    _model = {}
+
+    def name(self):
+        return "Upgrade Password"
+
+    def rank(self):
+        return 150
+
+    def model(self):
+        return self._model or {}
+
+    def validators(self):
+        return {}
+
+    def ui_content(self):
+        ws = [ui.Header("header[0]",
+                        "Require a password for local console access?"),
+              ui.Label("label[0]", "Please enter the current admin " +
+                       "password. You may also change the admin password " +
+                       "if required. If the new password fields are left" +
+                       "blank the password will remain the same."),
+              ui.Label("label[1]", "Password for local console access"),
+              ui.Divider("divider[0]"),
+              ui.PasswordEntry("upgrade.current_password",
+                               "Current Password:"),
+              ui.PasswordEntry("upgrade.password", "Password:"),
+              ui.PasswordEntry("upgrade.password_confirmation",
+                               "Confirm Password:"),
+              ]
+        self.widgets.add(ws)
+        page = ui.Page("password", ws)
+        page.buttons = [ui.QuitButton("button.quit", "Quit"),
+                        ui.Button("button.back", "Back"),
+                        ui.SaveButton("button.next", "Update")]
+        return page
+
+    def on_change(self, changes):
+        if changes.contains_any(["upgrade.current_password"]):
+            msg = "You have not provided a new password, current admin " \
+                "password will be used."
+        if changes.contains_any(["upgrade.password",
+                                 "upgrade.password_confirmation"]):
+            self._model.update(changes)
+            if self._model.get("upgrade.password", "") != \
+                self._model.get("upgrade.password_confirmation", ""):
+                raise exceptions.InvalidData("Passwords must be the same.")
+            else:
+                self.widgets["upgrade.password"].valid(True)
+                self.widgets["upgrade.password_confirmation"].valid(True)
+
+    def on_merge(self, effective_changes):
+        changes = self.pending_changes(False)
+        if changes.contains_any(["button.back"]):
+            self.application.ui.navigate.to_previous_plugin()
+        elif changes.contains_any(["upgrade.password_confirmation",
+                                   "button.next"]):
+            self.application.ui.navigate.to_plugin(installer.progress_page.Plugin)
diff --git a/scripts/tui/src/ovirt/node/installer/welcome_page.py b/scripts/tui/src/ovirt/node/installer/welcome_page.py
index 7533402..c5d4056 100644
--- a/scripts/tui/src/ovirt/node/installer/welcome_page.py
+++ b/scripts/tui/src/ovirt/node/installer/welcome_page.py
@@ -18,7 +18,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 # MA  02110-1301, USA.  A copy of the GNU General Public License is
 # also available at http://www.gnu.org/copyleft/gpl.html.
-from ovirt.node import plugins, ui, utils
+from ovirt.node import plugins, ui, utils, installer, config
 from ovirt.node.utils import virt, system
 import os
 
@@ -65,8 +65,19 @@
         pass
 
     def on_merge(self, effective_changes):
+
         if "button.install" in effective_changes:
             self.application.ui.navigate.to_next_plugin()
+            self._model["method"] = "install"
+
+        elif "button.upgrade" in effective_changes:
+            self.application.ui.navigate.to_plugin(installer.upgrade_page.Plugin)
+            self._model["method"] = "upgrade"
+
+        elif "button.reinstall" in effective_changes:
+            self.application.ui.navigate.to_plugin(installer.upgrade_page.Plugin)
+            self._model["method"] = "reinstall"
+
 
     def ___installation_option(self):
         if self.application.args.dry:
@@ -75,7 +86,7 @@
         media = utils.system.InstallationMedia()
         installed = utils.system.InstalledMedia()
 
-        has_hostvg = os.path.exists("/dev/HostVG")
+        has_hostvg = utils.system.has_hostvg()
         has_root = os.path.exists("/dev/disk/by-label/ROOT")
 
         if has_hostvg and has_root:
diff --git a/scripts/tui/src/ovirt/node/ui/__init__.py b/scripts/tui/src/ovirt/node/ui/__init__.py
index dc8350f..c846040 100644
--- a/scripts/tui/src/ovirt/node/ui/__init__.py
+++ b/scripts/tui/src/ovirt/node/ui/__init__.py
@@ -690,18 +690,21 @@
         self._progress_label.text("\n".join(self.texts))
 
     def run(self):
-        self.plugin.application.show(self)
-        self._close_button.enabled(False)
-        if self.transaction:
-            self.logger.debug("Initiating transaction")
-            self.__run_transaction()
-        else:
-            self.add_update("There were no changes, nothing to do.")
-        self._close_button.enabled(True)
+        try:
+            self.plugin.application.show(self)
+            self._close_button.enabled(False)
+            if self.transaction:
+                self.logger.debug("Initiating transaction")
+                self.__run_transaction()
+            else:
+                self.add_update("There were no changes, nothing to do.")
+            self._close_button.enabled(True)
 
-        # We enforce a redraw, because this the non-mainloop thread
-        self.plugin.application.ui.force_redraw()
-
+            # We enforce a redraw, because this the non-mainloop thread
+            self.plugin.application.ui.force_redraw()
+        except Exception as e:
+            self.logger.warning("An exception in the Transaction: %s" % e,
+                                exc_info=True)
     def __run_transaction(self):
         try:
             self.add_update("Checking pre-conditions ...")
@@ -712,6 +715,8 @@
                 self.plugin.dry_or(lambda: tx_element.commit())
             self.add_update("\nAll changes were applied successfully.")
         except Exception as e:
+            self.logger.info("An exception during the transaction: %s" % e,
+                             exc_info=True)
             self.add_update("\nAn error occurred while applying the changes:")
             self.add_update("%s" % e)
 
diff --git a/scripts/tui/src/ovirt/node/ui/urwid_builder.py b/scripts/tui/src/ovirt/node/ui/urwid_builder.py
index 5b1bd8f..0f1ff02 100644
--- a/scripts/tui/src/ovirt/node/ui/urwid_builder.py
+++ b/scripts/tui/src/ovirt/node/ui/urwid_builder.py
@@ -382,7 +382,7 @@
                ('plugin.widget.label', element_styles["text"]),
                ('plugin.widget.label.keyword', element_styles["label"]),
                ('plugin.widget.progressbar.box', element_styles["disabled"]),
-               ('plugin.widget.progressbar.uncomplete', None),
+               ('plugin.widget.progressbar.uncomplete', element_styles["label"]),
                ('plugin.widget.progressbar.complete', "white",
                 element_styles["disabled"]),
                ('plugin.widget.options', element_styles["label"]),
diff --git a/scripts/tui/src/ovirt/node/utils/system.py b/scripts/tui/src/ovirt/node/utils/system.py
index 5efa2cb..5e2ad7c 100644
--- a/scripts/tui/src/ovirt/node/utils/system.py
+++ b/scripts/tui/src/ovirt/node/utils/system.py
@@ -19,6 +19,7 @@
 # MA  02110-1301, USA.  A copy of the GNU General Public License is
 # also available at http://www.gnu.org/copyleft/gpl.html.
 from ovirt.node import base, utils
+from ovirt.node.config import defaults
 from ovirt.node.utils import process
 import os.path
 import rpm
@@ -53,6 +54,13 @@
     """
     from ovirtnode.ovirtfunctions import cpu_details
     return cpu_details()
+
+
+def has_hostvg():
+    """Determin if a HostVG is present on this system (indicates an existing
+    installation)
+    """
+    return os.path.exists("/dev/HostVG")
 
 
 class ProductInformation(base.Base):
@@ -148,8 +156,8 @@
     """
 
     def load(self):
-            from ovirtnode.ovirtfunctions import get_installed_version_number
-            self.version, self.release = get_installed_version_number()
+        from ovirtnode.ovirtfunctions import get_installed_version_number
+        self.version, self.release = get_installed_version_number()
 
 
 class Keyboard(base.Base):
@@ -176,3 +184,25 @@
 
     def get_current(self):
         return self.kbd.get()
+
+
+class BootInformation(base.Base):
+    """Provide informations about this boot
+    """
+    def __init__(self):
+        self._model = defaults.Installation()
+        super(BootInformation, self).__init__()
+
+    def is_installation(self):
+        #ovirtfunctions.is_install()
+        return self._model.retrieve()["install"] is True
+
+    def is_auto_installation(self):
+        #ovirtfunctions.is_auto_install()
+        cmdline = utils.fs.get_contents("/proc/cmdline")
+        return "BOOTIF" in cmdline and ("storage_init" in cmdline or
+                                        "ovirt_init" in cmdline)
+
+    def is_upgrade(self):
+        #ovirtfunctions.is_upgrade()
+        return self._model.retrieve()["upgrade"] is True


--
To view, visit http://gerrit.ovirt.org/12311
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I1a56227f2512466b78e70b45cfbb8119980e5b60
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-node
Gerrit-Branch: master
Gerrit-Owner: Fabian Deutsch <fabiand at fedoraproject.org>



More information about the node-patches mailing list