Example #1
0
 def test_delete_recipe_task_results_for_deleted_job(self):
     with self.migration_metadata.bind.connect() as connection:
         # populate empty database
         connection.execute(pkg_resources.resource_string('bkr.inttest.server',
                 'database-dumps/22.sql'))
         # populate test jobs
         connection.execute(pkg_resources.resource_string('bkr.inttest.server',
                 'bz1322700-and-bz1337790-migration-setup.sql'))
     # run migration
     upgrade_db(self.migration_metadata)
     # Job one's recipe task results should not be deleted
     self.assertEquals(
             self.migration_session.query(RecipeTaskResult).filter_by(recipe_task_id=1).count(),
             1)
     # Job one's log recipe task results should not be deleted
     self.assertEquals(
             self.migration_session.query(LogRecipeTaskResult).filter_by(recipe_task_result_id=1).count(),
             1)
     # Job two's recipe task results should be deleted
     self.assertEquals(
             self.migration_session.query(RecipeTaskResult).filter_by(recipe_task_id=2).count(),
             0)
     # Job two's log recipe task results should be deleted
     self.assertEquals(
             self.migration_session.query(LogRecipeTaskResult).filter_by(recipe_task_result_id=2).count(),
             0)
Example #2
0
 def test_Installing_status_is_mapped_on_downgrade(self):
     with self.migration_metadata.bind.connect() as connection:
         # populate empty database
         connection.execute(pkg_resources.resource_string('bkr.inttest.server',
                 'database-dumps/22.sql'))
         upgrade_db(self.migration_metadata)
         # create a job in Installing state
         connection.execute(
                 "INSERT INTO job (owner_id, retention_tag_id, dirty_version, clean_version, status) "
                 "VALUES (1, 1, '', '', 'Installing')")
         connection.execute(
                 "INSERT INTO recipe_set (job_id, queue_time, waived, status) "
                 "VALUES (1, '2015-11-09 17:03:04', FALSE, 'Installing')")
         connection.execute(
                 "INSERT INTO recipe (type, recipe_set_id, autopick_random, status) "
                 "VALUES ('machine_recipe', 1, FALSE, 'Installing')")
     # run the downgrade
     downgrade_db(self.migration_metadata, '22')
     # status should be Running so that it works with 22.x
     with self.migration_metadata.bind.connect() as connection:
         self.assertEquals(
                 connection.scalar('SELECT status FROM job WHERE id = 1'),
                 u'Running')
         self.assertEquals(
                 connection.scalar('SELECT status FROM recipe_set WHERE id = 1'),
                 u'Running')
         self.assertEquals(
                 connection.scalar('SELECT status FROM recipe WHERE id = 1'),
                 u'Running')
Example #3
0
 def test_redhat_production_20130304(self):
     connection = self.migration_metadata.bind.connect()
     connection.execute(pkg_resources.resource_string('bkr.inttest.server',
             'database-dumps/redhat-production-20130304.sql'))
     upgrade_db(self.migration_metadata)
     self.check_migrated_schema()
     downgrade_db(self.migration_metadata, 'base')
Example #4
0
 def test_clear_removed_users_from_groups(self):
     with self.migration_metadata.bind.connect() as connection:
         # populate empty database
         connection.execute(pkg_resources.resource_string('bkr.inttest.server',
                 'database-dumps/21.sql'))
         # bob is in the colonel group
         connection.execute(
                 "INSERT INTO tg_user (user_id, user_name, display_name, email_address, disabled, removed) "
                 "VALUES (2, 'bob', 'Bob', '*****@*****.**', 1, '2015-12-01 15:43:28')")
         connection.execute(
                 "INSERT INTO tg_group (group_id, group_name, display_name, ldap) "
                 "VALUES (3, 'colonel', 'Colonel', 0)")
         connection.execute(
                 "INSERT INTO user_group (user_id, group_id, is_owner) "
                 "VALUES (2, 3, 1)")
     # run migration
     upgrade_db(self.migration_metadata)
     colonel = self.migration_session.query(Group).get(3)
     # check that bob is removed from the group
     bob = self.migration_session.query(User).get(2)
     self.assertNotIn(colonel, bob.groups)
     self.assertNotIn(bob, colonel.users)
     self.assertEqual(colonel.activity[0].field_name, u'User')
     self.assertEqual(colonel.activity[0].action, u'Removed')
     self.assertEqual(colonel.activity[0].old_value, u'bob')
     self.assertEqual(colonel.activity[0].service, u'Migration')
     self.assertEqual(colonel.activity[0].user.user_name, u'admin')
Example #5
0
 def test_redhat_production_20140820(self):
     with self.migration_engine.connect() as connection:
         connection.execute(pkg_resources.resource_string('bkr.inttest.server',
                 'database-dumps/redhat-production-20140820.sql'))
     upgrade_db(self.migration_metadata)
     self.check_migrated_schema()
     downgrade_db(self.migration_metadata, 'base')
Example #6
0
 def test_migrate_recipe_set_comments_and_waived_from_nacked(self):
     with self.migration_metadata.bind.connect() as connection:
         # populate empty database
         connection.execute(pkg_resources.resource_string('bkr.inttest.server',
                 'database-dumps/21.sql'))
         # job owned by admin, with a recipe set which has been nacked and commented
         connection.execute(
                 "INSERT INTO job (owner_id, retention_tag_id, dirty_version, clean_version) "
                 "VALUES (1, 1, '', '')")
         connection.execute(
                 "INSERT INTO recipe_set (job_id, queue_time) "
                 "VALUES (1, '2015-11-05 16:31:01')")
         connection.execute(
                 "INSERT INTO recipe_set_nacked (recipe_set_id, response_id, comment, created) "
                 "VALUES (1, 2, 'it broke', '2015-11-05 16:32:40')")
     # run migration
     upgrade_db(self.migration_metadata)
     # check that the comment row was created
     comments = self.migration_session.query(RecipeSetComment).all()
     self.assertEqual(len(comments), 1)
     self.assertEqual(comments[0].recipe_set_id, 1)
     self.assertEqual(comments[0].comment, u'it broke')
     self.assertEqual(comments[0].user.user_name, u'admin')
     self.assertEqual(comments[0].created, datetime.datetime(2015, 11, 5, 16, 32, 40))
     # check that the recipe set is waived
     recipeset = self.migration_session.query(RecipeSet).first()
     self.assertEqual(recipeset.waived, True)
Example #7
0
 def test_check_db(self):
     with self.migration_engine.connect() as connection:
         connection.execute(pkg_resources.resource_string('bkr.inttest.server',
                 'database-dumps/21.sql'))
     self.assertTrue(check_db(self.migration_metadata, '171c07fb4970'))
     self.assertFalse(check_db(self.migration_metadata, 'head'))
     upgrade_db(self.migration_metadata)
     self.assertTrue(check_db(self.migration_metadata, 'head'))
Example #8
0
 def test_already_upgraded(self):
     connection = self.migration_metadata.bind.connect()
     connection.execute(pkg_resources.resource_string('bkr.inttest.server',
             'database-dumps/0.17.sql'))
     upgrade_db(self.migration_metadata)
     # Upgrading an already-upgraded database should be a no-op.
     upgrade_db(self.migration_metadata)
     self.check_migrated_schema()
Example #9
0
 def test_redhat_production_20120216(self):
     connection = self.migration_metadata.bind.connect()
     connection.execute(pkg_resources.resource_string('bkr.inttest.server',
             'database-dumps/redhat-production-20120216.sql'))
     raise unittest.SkipTest('Database migrations are not implemented '
             'far enough into the past yet')
     upgrade_db(self.migration_metadata)
     self.check_migrated_schema()
     downgrade_db(self.migration_metadata, 'base')
Example #10
0
 def test_full_downgrade_then_upgrade(self):
     # The point is to test that the complete *downgrade* sequence is valid, 
     # by then upgrading again and making sure we still have a correct schema.
     connection = self.migration_metadata.bind.connect()
     connection.execute(pkg_resources.resource_string('bkr.inttest.server',
             'database-dumps/0.11.sql'))
     upgrade_db(self.migration_metadata)
     downgrade_db(self.migration_metadata, 'base')
     upgrade_db(self.migration_metadata)
     self.check_migrated_schema()
    def test_migrate_system_groups_to_pools(self):
        connection = self.migration_metadata.bind.connect()

        # create the DB schema for beaker 19
        connection.execute(pkg_resources.resource_string('bkr.inttest.server',
                                                         'database-dumps/19.sql'))
        # populate synthetic data into relevant tables
        connection.execute('INSERT INTO system(id, fqdn, date_added, owner_id, type, status, kernel_type_id) VALUES (1, "test.fqdn.name", "2015-01-01", 1, 1, 1, 1)')
        connection.execute('INSERT INTO system(id, fqdn, date_added, owner_id, type, status, kernel_type_id) VALUES (2, "test1.fqdn.name", "2015-01-01", 1, 1, 1, 1)')
        connection.execute('INSERT INTO system(id, fqdn, date_added, owner_id, type, status, kernel_type_id) VALUES (3, "test2.fqdn.name", "2015-01-01", 1, 1, 1, 1)')
        connection.execute('INSERT INTO tg_group(group_id, group_name, ldap) VALUES (3, "group1", FALSE)')
        connection.execute('INSERT INTO tg_group(group_id, group_name, ldap) VALUES (4, "group2", FALSE)')
        connection.execute('INSERT INTO system_group(system_id, group_id) VALUES (1, 3)')
        connection.execute('INSERT INTO system_group(system_id, group_id) VALUES (2, 3)')
        connection.execute('INSERT INTO system_group(system_id, group_id) VALUES (1, 4)')
        connection.execute('INSERT INTO system_group(system_id, group_id) VALUES (3, 4)')

        # Migrate to system pools
        upgrade_db(self.migration_metadata)

        # check data for system_pool
        created_pools = self.migration_session.query(SystemPool).all()
        self.assertItemsEqual(['group1', 'group2'],
                          [pool.name for pool in created_pools])
        self.assertItemsEqual(['Pool migrated from group group1',
                               'Pool migrated from group group2'],
                              [pool.description for pool in created_pools])
        expected_system_pool_owners = {
            u'group1': u'group1',
            u'group2': u'group2',
        }
        for pool in expected_system_pool_owners.keys():
            p = self.migration_session.query(SystemPool).filter(SystemPool.name == pool).one()
            self.assertEquals(p.owning_group,
                              self.migration_session.query(Group).filter(Group.group_name == pool).one())

        expected_system_pools_map = {
            u'test.fqdn.name': [u'group1', u'group2'],
            u'test1.fqdn.name': [u'group1'],
            u'test2.fqdn.name': [u'group2'],
        }
        for system in expected_system_pools_map.keys():
            s = self.migration_session.query(System).filter(System.fqdn == system).one()
            self.assertItemsEqual([p.name for p in s.pools],
                                  expected_system_pools_map[system])

        min_user_id = min([user.id for user in self.migration_session.query(User).all()])
        for pool in created_pools:
            self.assertEquals(pool.activity[-1].action, u'Created')
            self.assertEquals(pool.activity[-1].field_name, u'Pool')
            self.assertEquals(pool.activity[-1].user.user_id, min_user_id)
            self.assertEquals(pool.activity[-1].new_value, pool.name)
            self.assertEquals(pool.activity[-1].service, u'Migration')
Example #12
0
 def test_migrate_ldap_groups(self):
     group_name = u'my_ldap_group'
     with self.migration_metadata.bind.connect() as connection:
         # populate empty database
         connection.execute(pkg_resources.resource_string('bkr.inttest.server',
                 'database-dumps/21.sql'))
         connection.execute(
                 "INSERT INTO tg_group (group_name, ldap) "
                 "VALUES ('%s', 1)" % group_name)
     # run migration
     upgrade_db(self.migration_metadata)
     # check that the group row was created
     group = self.migration_session.query(Group)\
             .filter(Group.group_name == group_name).one()
     self.assertEqual(group.group_name, group_name)
     self.assertEqual(group.membership_type, GroupMembershipType.ldap)
Example #13
0
 def test_clear_meaningless_system_activities(self):
     with self.migration_metadata.bind.connect() as connection:
         # populate empty database
         connection.execute(pkg_resources.resource_string('bkr.inttest.server',
                 'database-dumps/20.sql'))
         connection.execute('INSERT INTO system(id, fqdn, date_added, owner_id, type, status, kernel_type_id) VALUES (1, "test.fqdn.name", "2015-12-15", 1, 1, 1, 1)')
         connection.execute("INSERT INTO activity "
                 "(id, user_id, created, type, field_name, service, action, old_value, new_value) "
                 "VALUES (1, NULL, '2015-12-15 01:11:56', 'system_activity', 'System Acess Policy', "
                 "'HTTP', 'changed', 'Custom Access Policy', 'Custom access policy')")
         connection.execute("INSERT INTO system_activity (id, system_id) "
                 "VALUES (1, 1)")
     # run migration
     upgrade_db(self.migration_metadata)
     # check that systtem activity and activity have been deleted
     self.assertEquals(
             self.migration_session.query(SystemActivity).filter_by(id=1).count(),
             0)
Example #14
0
 def test_clear_removed_users_from_access_policies(self):
     with self.migration_metadata.bind.connect() as connection:
         # populate empty database
         connection.execute(pkg_resources.resource_string('bkr.inttest.server',
                 'database-dumps/21.sql'))
         # fred is in a custom access policy (1) and a pool access policy (2)
         connection.execute(
                 "INSERT INTO tg_user (user_id, user_name, display_name, email_address, disabled, removed) "
                 "VALUES (2, 'fred', 'Fred', '*****@*****.**', 1, '2015-12-01 17:18:56')")
         connection.execute("INSERT INTO system_access_policy (id) VALUES (1)")
         connection.execute(
                 "INSERT INTO system_access_policy_rule (policy_id, user_id, group_id, permission) "
                 "VALUES (1, 2, NULL, 'reserve')")
         connection.execute("INSERT INTO system "
                 "(id, fqdn, date_added, owner_id, type, status, kernel_type_id, "
                 " custom_access_policy_id, active_access_policy_id) "
                 "VALUES (1, 'test.example.invalid', '2015-01-01', 1, 'Machine', 'Automated', 1, 1, 1)")
         connection.execute("INSERT INTO system_access_policy (id) VALUES (2)")
         connection.execute(
                 "INSERT INTO system_access_policy_rule (policy_id, user_id, group_id, permission) "
                 "VALUES (2, 2, NULL, 'loan_self')")
         connection.execute(
                 "INSERT INTO system_pool (id, name, owning_user_id, access_policy_id) "
                 "VALUES (1, 'colonel-hard-wear', 1, 2)")
     # run migration
     upgrade_db(self.migration_metadata)
     # check that fred is removed from the system access policy
     system = self.migration_session.query(System).get(1)
     self.assertEqual([], system.custom_access_policy.rules)
     self.assertEqual(system.activity[0].field_name, u'Access Policy Rule')
     self.assertEqual(system.activity[0].action, u'Removed')
     self.assertEqual(system.activity[0].old_value, u'<grant reserve to fred>')
     self.assertEqual(system.activity[0].service, u'Migration')
     self.assertEqual(system.activity[0].user.user_name, u'admin')
     # check that fred is removed from the pool access policy
     pool = self.migration_session.query(SystemPool).get(1)
     self.assertEqual([], pool.access_policy.rules)
     self.assertEqual(pool.activity[0].field_name, u'Access Policy Rule')
     self.assertEqual(pool.activity[0].action, u'Removed')
     self.assertEqual(pool.activity[0].old_value, u'<grant loan_self to fred>')
     self.assertEqual(pool.activity[0].service, u'Migration')
     self.assertEqual(pool.activity[0].user.user_name, u'admin')
    def test_migrate_system_access_policies_to_custom_access_policies(self):
        connection = self.migration_metadata.bind.connect()

        # create the DB schema for beaker 19
        connection.execute(pkg_resources.resource_string('bkr.inttest.server',
                                                         'database-dumps/19.sql'))
        # populate synthetic data into relevant tables
        connection.execute('INSERT INTO system(id, fqdn, date_added, owner_id, type, status, kernel_type_id) VALUES (1, "test.fqdn.name", "2015-01-01", 1, 1, 1, 1)')
        connection.execute('INSERT INTO system(id, fqdn, date_added, owner_id, type, status, kernel_type_id) VALUES (2, "test1.fqdn.name", "2015-01-01", 1, 1, 1, 1)')
        connection.execute('INSERT INTO system(id, fqdn, date_added, owner_id, type, status, kernel_type_id) VALUES (3, "test2.fqdn.name", "2015-01-01", 1, 1, 1, 1)')
        connection.execute('INSERT INTO system_access_policy(id, system_id) VALUES (1, 2)')
        connection.execute('INSERT INTO system_access_policy(id, system_id) VALUES (2, 1)')
        connection.execute('INSERT INTO system_access_policy(id, system_id) VALUES (3, 3)')

        # Migrate
        upgrade_db(self.migration_metadata)

        # check the data has been migrated successfully
        systems = self.migration_session.query(System).all()
        expected_system_policy_map = {
            'test.fqdn.name':2,
            'test1.fqdn.name':1,
            'test2.fqdn.name':3
        }
        for s in systems:
            self.assertEquals(s.custom_access_policy_id,
                              expected_system_policy_map[s.fqdn])
            self.assertEquals(s.active_access_policy_id,
                              expected_system_policy_map[s.fqdn])

        # downgrade test
        downgrade_db(self.migration_metadata, '1c444555ea3d')
        # XXX self.metadata.reflect() isn't for some reason detecting
        # the schema changes
        migration_metadata = sqlalchemy.MetaData(bind=self.migration_engine)
        migration_metadata.reflect()
        self.assertIn('system_id',
                      migration_metadata.tables['system_access_policy'].columns.keys())
        self.assertNotIn('system_access_policy_id',
                      migration_metadata.tables['system_pool'].columns.keys())
Example #16
0
 def test_migrate_recipe_reviewed_status_from_nacked(self):
     with self.migration_metadata.bind.connect() as connection:
         # populate empty database
         connection.execute(pkg_resources.resource_string('bkr.inttest.server',
                 'database-dumps/21.sql'))
         # job owned by admin, with a recipe set which has been acked
         connection.execute(
                 "INSERT INTO job (owner_id, retention_tag_id, dirty_version, clean_version) "
                 "VALUES (1, 1, '', '')")
         connection.execute(
                 "INSERT INTO recipe_set (job_id, queue_time) "
                 "VALUES (1, '2015-11-09 17:03:04')")
         connection.execute(
                 "INSERT INTO recipe (type, recipe_set_id, autopick_random) "
                 "VALUES ('machine_recipe', 1, FALSE)")
         connection.execute(
                 "INSERT INTO recipe_set_nacked (recipe_set_id, response_id, comment, created) "
                 "VALUES (1, 1, NULL, '2015-11-09 17:32:03')")
     # run migration
     upgrade_db(self.migration_metadata)
     # check that the recipe is marked as reviewed by admin
     recipe = self.migration_session.query(Recipe).get(1)
     self.assertEqual(recipe.get_reviewed_state(User.by_user_name(u'admin')), True)
Example #17
0
 def test_delete_duplicate_osmajor_install_options(self):
     with self.migration_metadata.bind.connect() as connection:
         # populate empty database
         connection.execute(pkg_resources.resource_string('bkr.inttest.server',
                 'database-dumps/20.sql'))
         # RedHatEnterpriseLinux6 has duplicate rows in osmajor_install_options,
         # RedHatEnterpriseLinux7 just has one row
         connection.execute(
                 "INSERT INTO osmajor (id, osmajor) "
                 "VALUES (1, 'RedHatEnterpriseLinux6')")
         connection.execute(
                 "INSERT INTO osmajor_install_options (osmajor_id, arch_id, ks_meta) "
                 "VALUES (1, NULL, 'testone'), (1, NULL, 'testtwo')")
         connection.execute(
                 "INSERT INTO osmajor (id, osmajor) "
                 "VALUES (2, 'RedHatEnterpriseLinux7')")
         connection.execute(
                 "INSERT INTO osmajor_install_options (osmajor_id, arch_id, ks_meta) "
                 "VALUES (2, NULL, 'testthree')")
     # run migration
     upgrade_db(self.migration_metadata)
     # check that there is only one row per osmajor-arch combination
     row_counts = self.migration_session.query(OSMajorInstallOptions.osmajor_id,
                 OSMajorInstallOptions.arch_id, func.count())\
             .group_by(OSMajorInstallOptions.osmajor_id,
                 OSMajorInstallOptions.arch_id)
     for osmajor_id, arch_id, count in row_counts:
         self.assertEquals(count, 1,
                 'Expected to find only one row in osmajor_install_options '
                 'for osmajor_id %s, arch_id %s' % (osmajor_id, arch_id))
     # check that the most recent install options are kept, older ones are deleted
     installopts = self.migration_session.query(OSMajorInstallOptions)\
             .join(OSMajorInstallOptions.osmajor)\
             .filter(OSMajor.osmajor == u'RedHatEnterpriseLinux6',
                     OSMajorInstallOptions.arch == None)\
             .one()
     self.assertEquals(installopts.ks_meta, u'testtwo')
 def test_delete_orphaned_system_access_policies(self):
     connection = self.migration_metadata.bind.connect()
     # populate empty database
     connection.execute(pkg_resources.resource_string('bkr.inttest.server',
             'database-dumps/20.sql'))
     # access policy 1 is referenced, access policy 2 is an orphan
     connection.execute("INSERT INTO system_access_policy (id) VALUES (1)")
     connection.execute("INSERT INTO system_access_policy_rule "
             "(policy_id, user_id, group_id, permission) "
             "VALUES (1, NULL, NULL, 'view')")
     connection.execute("INSERT INTO system "
             "(fqdn, date_added, owner_id, type, status, kernel_type_id, "
             " custom_access_policy_id, active_access_policy_id) "
             "VALUES ('test.example.invalid', '2015-01-01', 1, 1, 1, 1, 1, 1)")
     connection.execute("INSERT INTO system_access_policy (id) VALUES (2)")
     connection.execute("INSERT INTO system_access_policy_rule "
             "(policy_id, user_id, group_id, permission) "
             "VALUES (2, NULL, NULL, 'view')")
     # run migration
     upgrade_db(self.migration_metadata)
     # check that access policy 2 has been deleted
     self.assertEquals(
             self.migration_session.query(SystemAccessPolicy).filter_by(id=2).count(),
             0)
Example #19
0
 def test_delete_orphaned_system_access_policies(self):
     with self.migration_metadata.bind.connect() as connection:
         # populate empty database
         connection.execute(pkg_resources.resource_string('bkr.inttest.server',
                 'database-dumps/20.sql'))
         # access policy 1 is referenced, access policy 2 is an orphan
         connection.execute("INSERT INTO system_access_policy (id) VALUES (1)")
         connection.execute("INSERT INTO system_access_policy_rule "
                 "(policy_id, user_id, group_id, permission) "
                 "VALUES (1, NULL, NULL, 'view')")
         connection.execute("INSERT INTO system "
                 "(fqdn, date_added, owner_id, type, status, kernel_type_id, "
                 " custom_access_policy_id, active_access_policy_id) "
                 "VALUES ('test.example.invalid', '2015-01-01', 1, 1, 1, 1, 1, 1)")
         connection.execute("INSERT INTO system_access_policy (id) VALUES (2)")
         connection.execute("INSERT INTO system_access_policy_rule "
                 "(policy_id, user_id, group_id, permission) "
                 "VALUES (2, NULL, NULL, 'view')")
     # run migration
     upgrade_db(self.migration_metadata)
     # check that access policy 2 has been deleted
     self.assertEquals(
             self.migration_session.query(SystemAccessPolicy).filter_by(id=2).count(),
             0)
Example #20
0
 def test_from_017(self):
     connection = self.migration_metadata.bind.connect()
     connection.execute(pkg_resources.resource_string('bkr.inttest.server',
             'database-dumps/0.17.sql'))
     upgrade_db(self.migration_metadata)
     self.check_migrated_schema()
Example #21
0
 def test_from_23(self):
     with self.migration_engine.connect() as connection:
         connection.execute(pkg_resources.resource_string('bkr.inttest.server',
                 'database-dumps/23.sql'))
     upgrade_db(self.migration_metadata)
     self.check_migrated_schema()
Example #22
0
 def test_populate_installation_from_recipe_resource(self):
     with self.migration_metadata.bind.connect() as connection:
         # Populate empty database
         connection.execute(pkg_resources.resource_string('bkr.inttest.server',
                 'database-dumps/22.sql'))
         # Populate test data for migration
         connection.execute(pkg_resources.resource_string('bkr.inttest.server',
                 'bz991245-migration-setup.sql'))
     # Run migration
     upgrade_db(self.migration_metadata)
     # Check that installation has been populated for recipe 1 (system_resource)
     recipe = self.migration_session.query(Recipe).get(1)
     self.assertEqual(recipe.installation.distro_tree.distro.name, u'distro')
     self.assertEqual(recipe.installation.kernel_options, u'') # populated below
     self.assertEqual(recipe.installation.rendered_kickstart.kickstart, u'lol')
     self.assertEqual(recipe.installation.system.fqdn, u'test.fqdn.name')
     self.assertEqual(recipe.installation.rebooted,
             datetime.datetime(2016, 2, 16, 1, 0, 5))
     self.assertEqual(recipe.installation.install_started,
             datetime.datetime(2016, 2, 16, 1, 1, 0))
     self.assertEqual(recipe.installation.install_finished,
             datetime.datetime(2016, 2, 16, 1, 20, 0))
     self.assertEqual(recipe.installation.postinstall_finished,
             datetime.datetime(2016, 2, 16, 1, 21, 0))
     self.assertEqual(recipe.installation.created,
             datetime.datetime(2016, 2, 16, 1, 0, 0))
     self.migration_session.close()
     # Run online data migration (two batches)
     migration = DataMigration(name=u'commands-for-recipe-installations')
     finished = migration.migrate_one_batch(self.migration_metadata.bind)
     self.assertFalse(finished)
     finished = migration.migrate_one_batch(self.migration_metadata.bind)
     self.assertTrue(finished)
     # Check that commands have been associated with their installation
     recipe = self.migration_session.query(Recipe).get(1)
     self.assertEqual(recipe.installation.kernel_options, u'ks=lol')
     installation_cmd = self.migration_session.query(CommandActivity).get(1)
     self.assertEqual(installation_cmd.installation, recipe.installation)
     manual_cmd = self.migration_session.query(CommandActivity).get(2)
     self.assertEqual(manual_cmd.installation, None)
     reprovision_cmd = self.migration_session.query(CommandActivity).get(3)
     self.assertEqual(reprovision_cmd.installation, None)
     # Check that installation has been populated for recipe 2 (guest_resource)
     recipe = self.migration_session.query(Recipe).get(2)
     self.assertEqual(recipe.installation.distro_tree.distro.name, u'distro')
     self.assertEqual(recipe.installation.kernel_options, u'')
     self.assertEqual(recipe.installation.rendered_kickstart.kickstart, u'lol2')
     self.assertIsNone(recipe.installation.system)
     self.assertIsNone(recipe.installation.rebooted)
     self.assertEqual(recipe.installation.install_started,
             datetime.datetime(2016, 2, 16, 1, 31, 0))
     self.assertEqual(recipe.installation.install_finished,
             datetime.datetime(2016, 2, 16, 1, 40, 0))
     self.assertEqual(recipe.installation.postinstall_finished,
             datetime.datetime(2016, 2, 16, 1, 41, 0))
     self.assertEqual(recipe.installation.created,
             datetime.datetime(2016, 2, 16, 1, 0, 0))
     # Check that installation has been populated for recipes 3 and 4
     # (host and guest that never started)
     recipe = self.migration_session.query(Recipe).get(3)
     self.assertEqual(recipe.installation.created,
             datetime.datetime(2016, 2, 17, 0, 0, 0))
     recipe = self.migration_session.query(Recipe).get(4)
     self.assertEqual(recipe.installation.created,
             datetime.datetime(2016, 2, 17, 0, 0, 0))