summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRĂ³man Joost <rjoost@redhat.com>2018-04-23 13:16:06 +1000
committerRoman Joost <rjoost@redhat.com>2018-05-10 04:42:05 +0000
commite24230696853b63e42acd29e376b904cb1a0b7dd (patch)
tree28694319535375fd4bd53aa57bd918accaf7db1a
parent8c11dff6fabb58fa5d4a3c4ae7564499a385d6e4 (diff)
Additional online migration for recipes with no installation row
This patch adds an additional online script to fix missed cases for recipes which have no installation row and are part of non-finished jobs. Bug: 1568224 Change-Id: I1084e2f0926313e3fae325c526ae47e71a0f0106
-rw-r--r--IntegrationTests/src/bkr/inttest/server/test_database_migration.py66
-rw-r--r--Server/bkr/server/data-migrations/insert-installation-row-for-recipes-before-25-take-2.py53
2 files changed, 119 insertions, 0 deletions
diff --git a/IntegrationTests/src/bkr/inttest/server/test_database_migration.py b/IntegrationTests/src/bkr/inttest/server/test_database_migration.py
index bccc111..aaac5cb 100644
--- a/IntegrationTests/src/bkr/inttest/server/test_database_migration.py
+++ b/IntegrationTests/src/bkr/inttest/server/test_database_migration.py
@@ -1476,3 +1476,69 @@ class MigrationTest(unittest.TestCase):
with self.migration_metadata.bind.connect() as connection:
self.assertEqual(1,
connection.scalar('SELECT count(*) FROM installation;'))
+
+ # https://bugzilla.redhat.com/show_bug.cgi?id=1568224
+ def test_scheduled_recipe_has_installation_column_after_upgrade_when_cancelled(self):
+ with self.migration_metadata.bind.connect() as connection:
+ connection.execute(pkg_resources.resource_string('bkr.inttest.server', 'database-dumps/25.sql'))
+ # add a queued job
+ connection.execute(
+ "INSERT INTO osmajor (id, osmajor) "
+ "VALUES (1, 'RedHatEnterpriseLinux6')")
+ connection.execute(
+ "INSERT INTO osversion (osmajor_id, osminor) "
+ "VALUES (1, 9)")
+ connection.execute(
+ "INSERT INTO distro (name, osversion_id) "
+ "VALUES ('RHEL6', 1)")
+ connection.execute(
+ "INSERT INTO distro_tree (distro_id, arch_id, variant) "
+ "VALUES (1, 1, 'Server')")
+ connection.execute(
+ "INSERT INTO job (owner_id, retention_tag_id, status, dirty_version, clean_version) "
+ "VALUES (1, 1, 'Installing', '', '2017-07-27 14:28:20')")
+ connection.execute(
+ "INSERT INTO recipe_set (job_id, status) "
+ "VALUES (1, 'Aborted')")
+ connection.execute(
+ "INSERT INTO recipe (id, type, recipe_set_id, distro_tree_id, status) "
+ "VALUES (1, 'machine_recipe', 1, 1, 'Cancelled')")
+ connection.execute(
+ "INSERT INTO recipe (id, type, recipe_set_id, distro_tree_id, status) "
+ "VALUES (2, 'machine_recipe', 1, 1, 'Aborted')")
+ connection.execute(
+ "INSERT INTO recipe (id, type, recipe_set_id, distro_tree_id, status) "
+ "VALUES (3, 'machine_recipe', 1, 1, 'Installing')")
+ connection.execute(
+ "INSERT INTO installation (created, recipe_id, distro_tree_id, variant, distro_name, initrd_path, kernel_path, osminor, osmajor, arch_id) "
+ "VALUES ('2018-03-02 05:21:45', 3, 1, 'Server', 'RHEL6', 'initrd.img', 'vmlinuz', '9', 'RedHatEnterpriseLinux6', 1)")
+ connection.execute(
+ "INSERT INTO recipe (id, type, recipe_set_id, distro_tree_id, status) "
+ "VALUES (4, 'machine_recipe', 1, 1, 'Waiting')")
+ connection.execute(
+ "INSERT INTO recipe (id, type, recipe_set_id, distro_tree_id, status) "
+ "VALUES (5, 'machine_recipe', 1, 1, 'Running')")
+ connection.execute(
+ "INSERT INTO recipe (id, type, recipe_set_id, distro_tree_id, status) "
+ "VALUES (6, 'machine_recipe', 1, 1, 'Scheduled')")
+ r1, r2, r3, r4, r5, r6 = self.migration_session.query(Recipe).all()
+ for recipe in [r1, r2, r4, r5, r6]:
+ self.assertIsNone(recipe.installation)
+ self.assertIsNotNone(r3.installation)
+ self.migration_session.close()
+
+ migration = DataMigration(name=u'insert-installation-row-for-recipes-before-25-take-2')
+ finished = migration.migrate_one_batch(self.migration_metadata.bind)
+ self.assertTrue(finished)
+
+ for recipe in self.migration_session.query(Recipe).all():
+ self.assertIsNotNone(recipe.installation, 'Installation row for recipeid %s (%s) should exist' % (recipe.id, recipe.status))
+ self.assertEqual(recipe.installation.distro_tree_id, 1)
+ self.assertEqual(recipe.installation.arch.arch, u'i386')
+ self.assertEqual(recipe.installation.variant, u'Server')
+ self.assertEqual(recipe.installation.distro_name, u'RHEL6')
+ self.assertEqual(recipe.installation.osmajor, u'RedHatEnterpriseLinux6')
+ self.assertEqual(recipe.installation.osminor, u'9')
+ with self.migration_metadata.bind.connect() as connection:
+ self.assertEqual(6,
+ connection.scalar('SELECT count(*) FROM installation;'))
diff --git a/Server/bkr/server/data-migrations/insert-installation-row-for-recipes-before-25-take-2.py b/Server/bkr/server/data-migrations/insert-installation-row-for-recipes-before-25-take-2.py
new file mode 100644
index 0000000..bda1cbf
--- /dev/null
+++ b/Server/bkr/server/data-migrations/insert-installation-row-for-recipes-before-25-take-2.py
@@ -0,0 +1,53 @@
+# 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; either version 2 of the License, or
+# (at your option) any later version.
+
+"""
+This is an additional online migration re Alembic revision 3ba776df4c76 and the
+already existing insert-installation-row-for-scheduled-recipes-before-25.py
+migration script. With the deployment of the online migration, we found
+additional regressions in scheduled jobs before the Beaker 25 migration. These
+cases have been documented on Bug 1568224 comments 12 and 13. The cases boil
+down to two distinct situations:
+
+ a) Two recipes in a recipeset where scheduled, one failed to
+ provision due to a bug in the code, while the other provisioned fine.
+ The status of the recipe is a transient state: 'Waiting'
+ b) The recipes have either been cancelled or aborted due to not
+ matching systems or by a cancelled request by the user.
+"""
+
+import logging
+
+
+logger = logging.getLogger(__name__)
+
+
+def migrate_one_batch(engine):
+ with engine.begin() as connection:
+ result = connection.execute("""
+ INSERT INTO installation
+ (created, distro_tree_id, recipe_id, arch_id, distro_name, osmajor, osminor, variant)
+ SELECT UTC_TIMESTAMP(),
+ recipe.distro_tree_id,
+ recipe.id,
+ distro_tree.arch_id,
+ distro.name,
+ osmajor.osmajor,
+ osversion.osminor,
+ distro_tree.variant
+ FROM recipe
+ INNER JOIN distro_tree ON distro_tree.id = recipe.distro_tree_id
+ INNER JOIN distro ON distro.id = distro_tree.distro_id
+ INNER JOIN osversion ON osversion.id = distro.osversion_id
+ INNER JOIN osmajor ON osmajor.id = osversion.osmajor_id
+ INNER JOIN recipe_set ON recipe_set.id = recipe.recipe_set_id
+ INNER JOIN job ON job.id = recipe_set.job_id
+ LEFT OUTER JOIN installation ON installation.recipe_id = recipe.id
+ WHERE job.status not in ('Completed', 'Cancelled', 'Aborted')
+ AND installation.recipe_id is NULL;
+ """)
+
+ logger.info('Created installation row for %d recipes', result.rowcount)
+ return True