Yaniv Dary has uploaded a new change for review.

Change subject: packaging: setup: Ask whether to backup the database
......................................................................

packaging: setup: Ask whether to backup the database

Also rollback db at cleanup stage (env overridable) to allow starting the
engine service early if needed.

Change-Id: I8e113bddaeeb71b00f5a524db0be3a24fa6f9907
Bug-Url: https://bugzilla.redhat.com/1059286
Signed-off-by: Yedidyah Bar David <[email protected]>
(cherry picked from commit 98c2062406a0c0b4acd74cae7279c3ff5b91730f)
---
M packaging/setup/ovirt_engine_setup/dwhconstants.py
M packaging/setup/plugins/ovirt-engine-setup/ovirt-engine-dwh/db/schema.py
2 files changed, 203 insertions(+), 37 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-dwh refs/changes/46/27046/1

diff --git a/packaging/setup/ovirt_engine_setup/dwhconstants.py 
b/packaging/setup/ovirt_engine_setup/dwhconstants.py
index ff17357..741fec6 100644
--- a/packaging/setup/ovirt_engine_setup/dwhconstants.py
+++ b/packaging/setup/ovirt_engine_setup/dwhconstants.py
@@ -207,6 +207,20 @@
     PGPASS_FILE = 'OVESETUP_DWH_DB/pgPassFile'
     NEW_DATABASE = 'OVESETUP_DWH_DB/newDatabase'
 
+    @osetupattrs(
+        answerfile=True,
+        summary=True,
+        description=_('Backup DWH database'),
+    )
+    def PERFORM_BACKUP(self):
+        return 'OVESETUP_DWH_DB/performBackup'
+
+    @osetupattrs(
+        answerfile=True,
+    )
+    def RESTORE_BACKUP_LATE:
+        return 'OVESETUP_DWH_DB/restoreBackupLate'
+
 
 @util.export
 @util.codegen
diff --git 
a/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine-dwh/db/schema.py 
b/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine-dwh/db/schema.py
index 6dce348..1e54086 100644
--- a/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine-dwh/db/schema.py
+++ b/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine-dwh/db/schema.py
@@ -33,6 +33,7 @@
 from ovirt_engine_setup import constants as osetupcons
 from ovirt_engine_setup import dwhconstants as odwhcons
 from ovirt_engine_setup import database
+from ovirt_engine_setup import dialog
 
 
 @util.export
@@ -42,9 +43,8 @@
     class SchemaTransaction(transaction.TransactionElement):
         """yum transaction element."""
 
-        def __init__(self, parent, backup=None):
+        def __init__(self, parent):
             self._parent = parent
-            self._backup = backup
 
         def __str__(self):
             return _("DWH schema Transaction")
@@ -53,39 +53,19 @@
             pass
 
         def abort(self):
-            self._parent.logger.info(_('Rolling back DWH database schema'))
-            try:
-                dbovirtutils = database.OvirtUtils(
-                    plugin=self._parent,
-                    dbenvkeys=odwhcons.Const.DWH_DB_ENV_KEYS,
+            if (
+                self._parent.environment[
+                    odwhcons.DBEnv.RESTORE_BACKUP_LATE
+                ] and
+                self._parent._backup
+            ):
+                self._parent._needRollback = True
+                self._parent.logger.warning(
+                    _('Rollback of DWH database postponed to Stage "Clean up"')
                 )
-                self._parent.logger.info(
-                    _('Clearing DWH database {database}').format(
-                        database=self._parent.environment[
-                            odwhcons.DBEnv.DATABASE
-                        ],
-                    )
-                )
-                dbovirtutils.clearDatabase()
-                if self._backup is not None and os.path.exists(self._backup):
-                    self._parent.logger.info(
-                        _('Restoring DWH database {database}').format(
-                            database=self._parent.environment[
-                                odwhcons.DBEnv.DATABASE
-                            ],
-                        )
-                    )
-                    dbovirtutils.restore(backupFile=self._backup)
-            except Exception as e:
-                self._parent.logger.debug(
-                    'Exception during DWH database restore',
-                    exc_info=True,
-                )
-                self._parent.logger.error(
-                    _('DWH database rollback failed: {error}').format(
-                        error=e,
-                    )
-                )
+            else:
+                self._parent.logger.info(_('Rolling back DWH database schema'))
+                self._parent._rollbackDatabase()
 
         def commit(self):
             pass
@@ -159,6 +139,160 @@
                 )
             )
 
+    def _rollbackDatabase(self):
+        try:
+            dbovirtutils = database.OvirtUtils(
+                plugin=self,
+                dbenvkeys=odwhcons.Const.DWH_DB_ENV_KEYS,
+            )
+            self.logger.info(
+                _('Clearing DWH database {database}').format(
+                    database=self.environment[
+                        odwhcons.DBEnv.DATABASE
+                    ],
+                )
+            )
+            dbovirtutils.clearDatabase()
+            if self._backup is not None and os.path.exists(self._backup):
+                self.logger.info(
+                    _('Restoring DWH database {database}').format(
+                        database=self.environment[
+                            odwhcons.DBEnv.DATABASE
+                        ],
+                    )
+                )
+                dbovirtutils.restore(backupFile=self._backup)
+        except Exception as e:
+            self.logger.debug(
+                'Exception during DWH database restore',
+                exc_info=True,
+            )
+            self.logger.error(
+                _('DWH database rollback failed: {error}').format(
+                    error=e,
+                )
+            )
+
+    def _getDBSize(self):
+        # Returns db size in bytes
+        statement = database.Statement(
+            dbenvkeys=odwhcons.Const.DWH_DB_ENV_KEYS,
+            environment=self.environment,
+        )
+        result = statement.execute(
+            statement="SELECT pg_database_size(%(db)s) as size",
+            args=dict(
+                db=self.environment[odwhcons.DBEnv.DATABASE],
+            ),
+            ownConnection=True,
+            transaction=False,
+        )
+        return int(result[0]['size'])
+
+    def _HumanReadableSize(self, bytes):
+        size_in_mb = bytes / pow(2,20)
+        return (
+            _('{size} MB').format(size=size_in_mb)
+            if size_in_mb  < 1024
+            else _('{size:1.1f} GB').format(
+                size=size_in_mb/1024.0,
+            )
+        )
+
+    @plugin.event(
+        stage=plugin.Stages.STAGE_INIT,
+    )
+    def _init(self):
+        self.environment.setdefault(
+            odwhcons.DBEnv.PERFORM_BACKUP,
+            None
+        )
+        self.environment.setdefault(
+            odwhcons.DBEnv.RESTORE_BACKUP_LATE,
+            True
+        )
+        self._needRollback = False
+
+    @plugin.event(
+        stage=plugin.Stages.STAGE_CUSTOMIZATION,
+        condition=lambda self: not self.environment[
+            odwhcons.DBEnv.NEW_DATABASE
+        ],
+        before=(
+            osetupcons.Stages.DIALOG_TITLES_E_DATABASE,
+        ),
+        after=(
+            odwhcons.Stages.DB_CONNECTION_CUSTOMIZATION,
+        ),
+    )
+    def _customization(self):
+        if self.environment[odwhcons.DBEnv.PERFORM_BACKUP] is None:
+            perform_backup = dialog.queryBoolean(
+                dialog=self.dialog,
+                name='OVESETUP_DWH_PERFORM_BACKUP',
+                note=_(
+                    'The detected DWH database size is {dbsize}.\n'
+                    'Setup can backup the existing database. The time and '
+                    'space required for the database backup depend on its '
+                    'size. This process '
+                    'takes time, and in some cases (for instance, when the '
+                    'size is few GBs) may take several hours to complete.\n'
+                    'If you choose to not back up the database, and Setup '
+                    'later fails for some reason, it will not be able to '
+                    'restore the database and all DWH data will be lost.\n'
+                    'Would you like to backup the existing database before '
+                    'upgrading it? '
+                    '(@VALUES@) [@DEFAULT@]: '
+                ).format(
+                    dbsize=self._HumanReadableSize(self._getDBSize()),
+                ),
+                prompt=True,
+                true=_('Yes'),
+                false=_('No'),
+                default=True,
+            )
+            if not perform_backup:
+                self.logger.warning(
+                    _(
+                        'Are you sure you do not want to backup the DWH '
+                        'database?'
+                    )
+                )
+                perform_backup = not dialog.queryBoolean(
+                    dialog=self.dialog,
+                    name='OVESETUP_DWH_VERIFY_NO_BACKUP',
+                    note=_(
+                        'A positive reply makes sense only if '
+                        'you do not need the data in DWH, or have some other, '
+                        'external means to restore it to a working state.\n'
+                        'Are you sure you do not want to backup the DWH '
+                        'database?'
+                        '(@VALUES@) [@DEFAULT@]: '
+                    ).format(
+                        dbsize=self._HumanReadableSize(self._getDBSize()),
+                    ),
+                    prompt=True,
+                    true=_('Yes'),
+                    false=_('No'),
+                    default=False,
+                )
+                if perform_backup:
+                    self.dialog.note(
+                        text=_(
+                            'The DWH Database will be backed up prior to 
upgrade.'
+                        ),
+                    )
+            if not perform_backup:
+                self.logger.warning(
+                    _(
+                        'DWH Database will not be backed up. Rollback in case '
+                        'of failure will not be possible.'
+                    )
+                )
+            self.environment[
+                odwhcons.DBEnv.PERFORM_BACKUP
+            ] = perform_backup
+
     @plugin.event(
         stage=plugin.Stages.STAGE_VALIDATION,
         after=(
@@ -185,16 +319,18 @@
         ),
     )
     def _misc(self):
-        backupFile = None
+        self._backup = None
 
         if not self.environment[
             odwhcons.DBEnv.NEW_DATABASE
+        ] and self.environment[
+            odwhcons.DBEnv.PERFORM_BACKUP
         ]:
             dbovirtutils = database.OvirtUtils(
                 plugin=self,
                 dbenvkeys=odwhcons.Const.DWH_DB_ENV_KEYS,
             )
-            backupFile = dbovirtutils.backup(
+            self._backup = dbovirtutils.backup(
                 dir=odwhcons.FileLocations.OVIRT_ENGINE_DWH_DB_BACKUP_DIR,
                 prefix=odwhcons.Const.OVIRT_ENGINE_DWH_DB_BACKUP_PREFIX,
             )
@@ -202,7 +338,6 @@
         self.environment[otopicons.CoreEnv.MAIN_TRANSACTION].append(
             self.SchemaTransaction(
                 parent=self,
-                backup=backupFile,
             )
         )
 
@@ -246,5 +381,22 @@
             },
         )
 
+    @plugin.event(
+        stage=plugin.Stages.STAGE_CLEANUP,
+        priority=plugin.Stages.PRIORITY_LAST,
+        condition=lambda self: self._needRollback,
+    )
+    def _rollback(self):
+        self.logger.warning(
+            _('Rollback of DWH database started')
+        )
+        self.dialog.note(
+            text=_(
+                'This might be a long process, but it should be safe to '
+                'start the engine service before it finishes, if needed.'
+            ),
+        )
+        self._rollbackDatabase()
+
 
 # vim: expandtab tabstop=4 shiftwidth=4


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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I8e113bddaeeb71b00f5a524db0be3a24fa6f9907
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-dwh
Gerrit-Branch: ovirt-engine-3.4
Gerrit-Owner: Yaniv Dary <[email protected]>
Gerrit-Reviewer: Yedidyah Bar David <[email protected]>
_______________________________________________
Engine-patches mailing list
[email protected]
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to