Exemplo n.º 1
0
 def setUp(self):
     super(GuestAgentManagerTest, self).setUp()
     self.context = trove_testtools.TroveTestContext(self)
     self.manager = Manager()
     self.origin_MySqlAppStatus = dbaas.MySqlAppStatus
     self.origin_os_path_exists = os.path.exists
     self.origin_format = volume.VolumeDevice.format
     self.origin_migrate_data = volume.VolumeDevice.migrate_data
     self.origin_mount = volume.VolumeDevice.mount
     self.origin_unmount = volume.VolumeDevice.unmount
     self.origin_mount_points = volume.VolumeDevice.mount_points
     self.origin_stop_mysql = dbaas.MySqlApp.stop_db
     self.origin_start_mysql = dbaas.MySqlApp.start_mysql
     self.origin_update_overrides = dbaas.MySqlApp.update_overrides
     self.origin_pkg_is_installed = pkg.Package.pkg_is_installed
     self.origin_os_path_exists = os.path.exists
     self.origin_chown = operating_system.chown
     # set up common mock objects, etc. for replication testing
     self.patcher_gfvs = patch(
         'trove.guestagent.dbaas.get_filesystem_volume_stats')
     self.patcher_rs = patch(self.manager.replication_namespace + "." +
                             self.manager.replication_strategy)
     self.mock_gfvs_class = self.patcher_gfvs.start()
     self.mock_rs_class = self.patcher_rs.start()
     self.repl_datastore_manager = 'mysql'
     self.repl_replication_strategy = 'MysqlGTIDReplication'
Exemplo n.º 2
0
 def setUp(self):
     super(GuestAgentManagerTest, self).setUp()
     self.context = trove_testtools.TroveTestContext(self)
     self.replication_strategy = 'MysqlGTIDReplication'
     self.patch_rs = patch(
         'trove.guestagent.strategies.replication.get_strategy',
         return_value=self.replication_strategy)
     self.mock_rs = self.patch_rs.start()
     self.addCleanup(self.patch_rs.stop)
     self.manager = Manager()
     self.origin_MySqlAppStatus = dbaas.MySqlAppStatus.get
     self.origin_os_path_exists = os.path.exists
     self.origin_format = volume.VolumeDevice.format
     self.origin_migrate_data = volume.VolumeDevice.migrate_data
     self.origin_mount = volume.VolumeDevice.mount
     self.origin_unmount = volume.VolumeDevice.unmount
     self.origin_mount_points = volume.VolumeDevice.mount_points
     self.origin_stop_mysql = dbaas.MySqlApp.stop_db
     self.origin_start_mysql = dbaas.MySqlApp.start_mysql
     self.origin_update_overrides = dbaas.MySqlApp.update_overrides
     self.origin_install_if_needed = dbaas.MySqlApp.install_if_needed
     self.origin_secure = dbaas.MySqlApp.secure
     self.origin_secure_root = dbaas.MySqlApp.secure_root
     self.origin_pkg_is_installed = pkg.Package.pkg_is_installed
     self.origin_os_path_exists = os.path.exists
     self.origin_chown = operating_system.chown
     # set up common mock objects, etc. for replication testing
     self.patcher_gfvs = patch(
         'trove.guestagent.dbaas.get_filesystem_volume_stats')
     self.patcher_rs = patch(
         'trove.guestagent.strategies.replication.get_instance')
     self.mock_gfvs_class = self.patcher_gfvs.start()
     self.mock_rs_class = self.patcher_rs.start()
Exemplo n.º 3
0
 def setUp(self):
     super(GuestAgentManagerTest, self).setUp()
     self.context = TroveContext()
     self.manager = Manager()
     self.origin_MySqlAppStatus = dbaas.MySqlAppStatus
     self.origin_os_path_exists = os.path.exists
     self.origin_format = volume.VolumeDevice.format
     self.origin_migrate_data = volume.VolumeDevice.migrate_data
     self.origin_mount = volume.VolumeDevice.mount
     self.origin_unmount = volume.VolumeDevice.unmount
     self.origin_mount_points = volume.VolumeDevice.mount_points
     self.origin_stop_mysql = dbaas.MySqlApp.stop_db
     self.origin_start_mysql = dbaas.MySqlApp.start_mysql
     self.origin_pkg_is_installed = pkg.Package.pkg_is_installed
     self.origin_os_path_exists = os.path.exists
     # set up common mock objects, etc. for replication testing
     self.patcher_gfvs = patch(
         'trove.guestagent.dbaas.get_filesystem_volume_stats')
     self.patcher_rs = patch(
         'trove.guestagent.datastore.mysql.manager.'
         'REPLICATION_STRATEGY_CLASS')
     self.mock_gfvs_class = self.patcher_gfvs.start()
     self.mock_rs_class = self.patcher_rs.start()
     self.repl_datastore_manager = 'mysql'
     self.repl_replication_strategy = 'MysqlGTIDReplication'
Exemplo n.º 4
0
 def setUp(self):
     super(GuestAgentManagerTest, self).setUp()
     self.context = TroveContext()
     self.manager = Manager()
     self.origin_MySqlAppStatus = dbaas.MySqlAppStatus
     self.origin_os_path_exists = os.path.exists
     self.origin_format = volume.VolumeDevice.format
     self.origin_migrate_data = volume.VolumeDevice.migrate_data
     self.origin_mount = volume.VolumeDevice.mount
     self.origin_is_installed = dbaas.MySqlApp.is_installed
     self.origin_stop_mysql = dbaas.MySqlApp.stop_db
     self.origin_start_mysql = dbaas.MySqlApp.start_mysql
     self.origin_install_mysql = dbaas.MySqlApp._install_mysql
Exemplo n.º 5
0
class GuestAgentManagerTest(testtools.TestCase):

    def setUp(self):
        super(GuestAgentManagerTest, self).setUp()
        self.context = TroveContext()
        self.manager = Manager()
        self.origin_MySqlAppStatus = dbaas.MySqlAppStatus
        self.origin_os_path_exists = os.path.exists
        self.origin_format = volume.VolumeDevice.format
        self.origin_migrate_data = volume.VolumeDevice.migrate_data
        self.origin_mount = volume.VolumeDevice.mount
        self.origin_is_installed = dbaas.MySqlApp.is_installed
        self.origin_stop_mysql = dbaas.MySqlApp.stop_db
        self.origin_start_mysql = dbaas.MySqlApp.start_mysql
        self.origin_install_mysql = dbaas.MySqlApp._install_mysql

    def tearDown(self):
        super(GuestAgentManagerTest, self).tearDown()
        dbaas.MySqlAppStatus = self.origin_MySqlAppStatus
        os.path.exists = self.origin_os_path_exists
        volume.VolumeDevice.format = self.origin_format
        volume.VolumeDevice.migrate_data = self.origin_migrate_data
        volume.VolumeDevice.mount = self.origin_mount
        dbaas.MySqlApp.is_installed = self.origin_is_installed
        dbaas.MySqlApp.stop_db = self.origin_stop_mysql
        dbaas.MySqlApp.start_mysql = self.origin_start_mysql
        dbaas.MySqlApp._install_mysql = self.origin_install_mysql
        unstub()

    def test_update_status(self):
        mock_status = mock()
        when(dbaas.MySqlAppStatus).get().thenReturn(mock_status)
        self.manager.update_status(self.context)
        verify(dbaas.MySqlAppStatus).get()
        verify(mock_status).update()

    def test_create_database(self):
        when(dbaas.MySqlAdmin).create_database(['db1']).thenReturn(None)
        self.manager.create_database(self.context, ['db1'])
        verify(dbaas.MySqlAdmin).create_database(['db1'])

    def test_create_user(self):
        when(dbaas.MySqlAdmin).create_user(['user1']).thenReturn(None)
        self.manager.create_user(self.context, ['user1'])
        verify(dbaas.MySqlAdmin).create_user(['user1'])

    def test_delete_database(self):
        databases = ['db1']
        when(dbaas.MySqlAdmin).delete_database(databases).thenReturn(None)
        self.manager.delete_database(self.context, databases)
        verify(dbaas.MySqlAdmin).delete_database(databases)

    def test_delete_user(self):
        user = ['user1']
        when(dbaas.MySqlAdmin).delete_user(user).thenReturn(None)
        self.manager.delete_user(self.context, user)
        verify(dbaas.MySqlAdmin).delete_user(user)

    def test_list_databases(self):
        when(dbaas.MySqlAdmin).list_databases(None, None,
                                              False).thenReturn(['database1'])
        databases = self.manager.list_databases(self.context)
        self.assertThat(databases, Not(Is(None)))
        self.assertThat(databases, Equals(['database1']))
        verify(dbaas.MySqlAdmin).list_databases(None, None, False)

    def test_list_users(self):
        when(dbaas.MySqlAdmin).list_users(None, None,
                                          False).thenReturn(['user1'])
        users = self.manager.list_users(self.context)
        self.assertThat(users, Equals(['user1']))
        verify(dbaas.MySqlAdmin).list_users(None, None, False)

    def test_enable_root(self):
        when(dbaas.MySqlAdmin).enable_root().thenReturn('user_id_stuff')
        user_id = self.manager.enable_root(self.context)
        self.assertThat(user_id, Is('user_id_stuff'))
        verify(dbaas.MySqlAdmin).enable_root()

    def test_is_root_enabled(self):
        when(dbaas.MySqlAdmin).is_root_enabled().thenReturn(True)
        is_enabled = self.manager.is_root_enabled(self.context)
        self.assertThat(is_enabled, Is(True))
        verify(dbaas.MySqlAdmin).is_root_enabled()

    def test_create_backup(self):
        when(backup).backup(self.context, 'backup_id_123').thenReturn(None)
        # entry point
        Manager().create_backup(self.context, 'backup_id_123')
        # assertions
        verify(backup).backup(self.context, 'backup_id_123')

    def test_prepare_device_path_true(self):
        self._prepare_dynamic()

    def test_prepare_device_path_false(self):
        self._prepare_dynamic(device_path=None)

    def test_prepare_mysql_not_installed(self):
        self._prepare_dynamic(is_mysql_installed=False)

    def test_prepare_mysql_from_backup(self):
        self._prepare_dynamic(backup_id='backup_id_123abc')

    def test_prepare_mysql_from_backup_with_root(self):
        self._prepare_dynamic(backup_id='backup_id_123abc',
                              is_root_enabled=True)

    def _prepare_dynamic(self, device_path='/dev/vdb', is_mysql_installed=True,
                         backup_id=None, is_root_enabled=False):

        # covering all outcomes is starting to cause trouble here
        COUNT = 1 if device_path else 0
        SEC_COUNT = 1 if is_mysql_installed else 0
        migrate_count = 1 * COUNT if not backup_id else 0

        # TODO(juice): this should stub an instance of the MySqlAppStatus
        mock_status = mock()
        when(dbaas.MySqlAppStatus).get().thenReturn(mock_status)
        when(mock_status).begin_install().thenReturn(None)
        when(VolumeDevice).format().thenReturn(None)
        when(VolumeDevice).migrate_data(any()).thenReturn(None)
        when(VolumeDevice).mount().thenReturn(None)
        when(dbaas.MySqlApp).stop_db().thenReturn(None)
        when(dbaas.MySqlApp).start_mysql().thenReturn(None)
        when(dbaas.MySqlApp).install_if_needed().thenReturn(None)
        when(backup).restore(self.context, backup_id).thenReturn(None)
        when(dbaas.MySqlApp).secure(any()).thenReturn(None)
        when(dbaas.MySqlApp).secure_root(any()).thenReturn(None)
        when(dbaas.MySqlApp).is_installed().thenReturn(is_mysql_installed)
        when(dbaas.MySqlAdmin).is_root_enabled().thenReturn(is_root_enabled)
        when(dbaas.MySqlAdmin).create_user().thenReturn(None)
        when(dbaas.MySqlAdmin).create_database().thenReturn(None)
        when(dbaas.MySqlAdmin).report_root_enabled(self.context).thenReturn(
            None)

        when(os.path).exists(any()).thenReturn(is_mysql_installed)
        # invocation
        self.manager.prepare(context=self.context, databases=None,
                             memory_mb='2048', users=None,
                             device_path=device_path,
                             mount_point='/var/lib/mysql',
                             backup_id=backup_id)
        # verification/assertion
        verify(mock_status).begin_install()

        verify(VolumeDevice, times=COUNT).format()
        verify(dbaas.MySqlApp, times=(COUNT * SEC_COUNT)).stop_db()
        verify(VolumeDevice, times=(migrate_count * SEC_COUNT)).migrate_data(
            any())
        if backup_id:
            verify(backup).restore(self.context, backup_id, '/var/lib/mysql')
        verify(dbaas.MySqlApp).install_if_needed()
        # We dont need to make sure the exact contents are there
        verify(dbaas.MySqlApp).secure(any())
        verify(dbaas.MySqlAdmin, never).create_database()
        verify(dbaas.MySqlAdmin, never).create_user()
        times_report = 1 if is_root_enabled else 0
        verify(dbaas.MySqlApp).secure_root(secure_remote_root=any())
        verify(dbaas.MySqlAdmin, times=times_report).report_root_enabled(
            self.context)
Exemplo n.º 6
0
class GuestAgentManagerTest(testtools.TestCase):
    def setUp(self):
        super(GuestAgentManagerTest, self).setUp()
        self.context = TroveContext()
        self.manager = Manager()
        self.origin_MySqlAppStatus = dbaas.MySqlAppStatus
        self.origin_os_path_exists = os.path.exists
        self.origin_format = volume.VolumeDevice.format
        self.origin_migrate_data = volume.VolumeDevice.migrate_data
        self.origin_mount = volume.VolumeDevice.mount
        self.origin_unmount = volume.VolumeDevice.unmount
        self.origin_mount_points = volume.VolumeDevice.mount_points
        self.origin_stop_mysql = dbaas.MySqlApp.stop_db
        self.origin_start_mysql = dbaas.MySqlApp.start_mysql
        self.origin_update_overrides = dbaas.MySqlApp.update_overrides
        self.origin_pkg_is_installed = pkg.Package.pkg_is_installed
        self.origin_os_path_exists = os.path.exists
        self.origin_chown = operating_system.chown
        # set up common mock objects, etc. for replication testing
        self.patcher_gfvs = patch(
            'trove.guestagent.dbaas.get_filesystem_volume_stats')
        self.patcher_rs = patch(self.manager.replication_namespace + "." +
                                self.manager.replication_strategy)
        self.mock_gfvs_class = self.patcher_gfvs.start()
        self.mock_rs_class = self.patcher_rs.start()
        self.repl_datastore_manager = 'mysql'
        self.repl_replication_strategy = 'MysqlGTIDReplication'

    def tearDown(self):
        super(GuestAgentManagerTest, self).tearDown()
        dbaas.MySqlAppStatus = self.origin_MySqlAppStatus
        os.path.exists = self.origin_os_path_exists
        volume.VolumeDevice.format = self.origin_format
        volume.VolumeDevice.migrate_data = self.origin_migrate_data
        volume.VolumeDevice.mount = self.origin_mount
        volume.VolumeDevice.unmount = self.origin_unmount
        volume.VolumeDevice.mount_points = self.origin_mount_points
        dbaas.MySqlApp.stop_db = self.origin_stop_mysql
        dbaas.MySqlApp.start_mysql = self.origin_start_mysql
        dbaas.MySqlApp.update_overrides = self.origin_update_overrides
        operating_system.chown = self.origin_chown
        pkg.Package.pkg_is_installed = self.origin_pkg_is_installed
        os.path.exists = self.origin_os_path_exists
        # teardown the replication mock objects
        self.patcher_gfvs.stop()
        self.patcher_rs.stop()

    def test_update_status(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        self.manager.update_status(self.context)
        dbaas.MySqlAppStatus.get.assert_any_call()
        mock_status.update.assert_any_call()

    def test_create_database(self):
        dbaas.MySqlAdmin.create_database = MagicMock(return_value=None)
        self.manager.create_database(self.context, ['db1'])
        dbaas.MySqlAdmin.create_database.assert_any_call(['db1'])

    def test_create_user(self):
        dbaas.MySqlAdmin.create_user = MagicMock(return_value=None)
        self.manager.create_user(self.context, ['user1'])
        dbaas.MySqlAdmin.create_user.assert_any_call(['user1'])

    def test_delete_database(self):
        databases = ['db1']
        dbaas.MySqlAdmin.delete_database = MagicMock(return_value=None)
        self.manager.delete_database(self.context, databases)
        dbaas.MySqlAdmin.delete_database.assert_any_call(databases)

    def test_delete_user(self):
        user = ['user1']
        dbaas.MySqlAdmin.delete_user = MagicMock(return_value=None)
        self.manager.delete_user(self.context, user)
        dbaas.MySqlAdmin.delete_user.assert_any_call(user)

    def test_grant_access(self):
        username = "******"
        hostname = "test_host"
        databases = ["test_database"]
        dbaas.MySqlAdmin.grant_access = MagicMock(return_value=None)
        self.manager.grant_access(self.context,
                                  username,
                                  hostname,
                                  databases)

        dbaas.MySqlAdmin.grant_access.assert_any_call(username,
                                                      hostname,
                                                      databases)

    def test_list_databases(self):
        dbaas.MySqlAdmin.list_databases = MagicMock(return_value=['database1'])
        databases = self.manager.list_databases(self.context)
        self.assertThat(databases, Not(Is(None)))
        self.assertThat(databases, Equals(['database1']))
        dbaas.MySqlAdmin.list_databases.assert_any_call(None, None, False)

    def test_list_users(self):
        dbaas.MySqlAdmin.list_users = MagicMock(return_value=['user1'])
        users = self.manager.list_users(self.context)
        self.assertThat(users, Equals(['user1']))
        dbaas.MySqlAdmin.list_users.assert_any_call(None, None, False)

    def test_get_users(self):
        username = ['user1']
        hostname = ['host']
        dbaas.MySqlAdmin.get_user = MagicMock(return_value=['user1'])
        users = self.manager.get_user(self.context, username, hostname)
        self.assertThat(users, Equals(['user1']))
        dbaas.MySqlAdmin.get_user.assert_any_call(username, hostname)

    def test_enable_root(self):
        dbaas.MySqlAdmin.enable_root = MagicMock(return_value='user_id_stuff')
        user_id = self.manager.enable_root(self.context)
        self.assertThat(user_id, Is('user_id_stuff'))
        dbaas.MySqlAdmin.enable_root.assert_any_call()

    def test_is_root_enabled(self):
        dbaas.MySqlAdmin.is_root_enabled = MagicMock(return_value=True)
        is_enabled = self.manager.is_root_enabled(self.context)
        self.assertThat(is_enabled, Is(True))
        dbaas.MySqlAdmin.is_root_enabled.assert_any_call()

    def test_create_backup(self):
        backup.backup = MagicMock(return_value=None)
        # entry point
        Manager().create_backup(self.context, 'backup_id_123')
        # assertions
        backup.backup.assert_any_call(self.context, 'backup_id_123')

    def test_prepare_device_path_true(self):
        self._prepare_dynamic()

    def test_prepare_device_path_false(self):
        self._prepare_dynamic(device_path=None)

    def test_prepare_device_path_mounted(self):
        self._prepare_dynamic(is_mounted=True)

    def test_prepare_mysql_not_installed(self):
        self._prepare_dynamic(is_mysql_installed=False)

    def test_prepare_mysql_from_backup(self):
        self._prepare_dynamic(backup_id='backup_id_123abc')

    def test_prepare_mysql_from_backup_with_root(self):
        self._prepare_dynamic(backup_id='backup_id_123abc',
                              is_root_enabled=True)

    def test_prepare_mysql_with_root_password(self):
        self._prepare_dynamic(root_password='******')

    def test_prepare_mysql_with_users_and_databases(self):
        self._prepare_dynamic(databases=['db1'], users=['user1'])

    def test_prepare_mysql_with_snapshot(self):
        snapshot = {'replication_strategy': self.repl_replication_strategy,
                    'dataset': {'dataset_size': 1.0},
                    'config': None}
        self._prepare_dynamic(snapshot=snapshot)

    def _prepare_dynamic(self, device_path='/dev/vdb', is_mysql_installed=True,
                         backup_id=None, is_root_enabled=False,
                         root_password=None, overrides=None, is_mounted=False,
                         databases=None, users=None, snapshot=None):
        # covering all outcomes is starting to cause trouble here
        COUNT = 1 if device_path else 0
        backup_info = None
        if backup_id is not None:
            backup_info = {'id': backup_id,
                           'location': 'fake-location',
                           'type': 'InnoBackupEx',
                           'checksum': 'fake-checksum',
                           }

        # TODO(juice): this should stub an instance of the MySqlAppStatus
        mock_status = MagicMock()

        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        mock_status.begin_install = MagicMock(return_value=None)
        VolumeDevice.format = MagicMock(return_value=None)
        VolumeDevice.migrate_data = MagicMock(return_value=None)
        VolumeDevice.mount = MagicMock(return_value=None)
        mount_points = []
        if is_mounted:
            mount_points = ['/mnt']
        VolumeDevice.mount_points = MagicMock(return_value=mount_points)
        VolumeDevice.unmount = MagicMock(return_value=None)
        set_data_dir_patcher = patch.object(dbaas.MySqlApp, 'set_data_dir',
                                            return_value='/var/lib/mysql')
        self.addCleanup(set_data_dir_patcher.stop)
        set_data_dir_patcher.start()
        dbaas.MySqlApp.stop_db = MagicMock(return_value=None)
        dbaas.MySqlApp.start_mysql = MagicMock(return_value=None)
        dbaas.MySqlApp.update_overrides = MagicMock(return_value=None)
        dbaas.MySqlApp.install_if_needed = MagicMock(return_value=None)
        backup.restore = MagicMock(return_value=None)
        dbaas.MySqlApp.secure = MagicMock(return_value=None)
        dbaas.MySqlApp.secure_root = MagicMock(return_value=None)
        pkg.Package.pkg_is_installed = MagicMock(
            return_value=is_mysql_installed)
        dbaas.MySqlAdmin.is_root_enabled = MagicMock(
            return_value=is_root_enabled)
        dbaas.MySqlAdmin.create_user = MagicMock(return_value=None)
        dbaas.MySqlAdmin.create_database = MagicMock(return_value=None)
        dbaas.MySqlAdmin.enable_root = MagicMock(return_value=None)
        operating_system.chown = MagicMock(return_value=None)
        os.path.exists = MagicMock(return_value=True)
        mock_replication = MagicMock()
        mock_replication.enable_as_slave = MagicMock()
        self.mock_rs_class.return_value = mock_replication
        # invocation
        self.manager.prepare(context=self.context,
                             packages=None,
                             memory_mb='2048',
                             databases=databases,
                             users=users,
                             device_path=device_path,
                             mount_point='/var/lib/mysql',
                             backup_info=backup_info,
                             root_password=root_password,
                             overrides=overrides,
                             cluster_config=None,
                             snapshot=snapshot)

        # verification/assertion
        mock_status.begin_install.assert_any_call()

        self.assertEqual(COUNT, VolumeDevice.format.call_count)
        self.assertEqual(COUNT, VolumeDevice.migrate_data.call_count)
        self.assertEqual(COUNT, VolumeDevice.mount_points.call_count)
        self.assertEqual(COUNT, dbaas.MySqlApp.stop_db.call_count)
        if is_mounted:
            self.assertEqual(1, VolumeDevice.unmount.call_count)
        else:
            self.assertEqual(0, VolumeDevice.unmount.call_count)
        if backup_info:
            backup.restore.assert_any_call(self.context,
                                           backup_info,
                                           '/var/lib/mysql/data')
        dbaas.MySqlApp.install_if_needed.assert_any_call(None)
        # We don't need to make sure the exact contents are there
        dbaas.MySqlApp.secure.assert_any_call(None, None)
        dbaas.MySqlApp.secure_root.assert_any_call(
            secure_remote_root=not is_root_enabled)

        if root_password:
            dbaas.MySqlAdmin.enable_root.assert_any_call(root_password)
        if databases:
            dbaas.MySqlAdmin.create_database.assert_any_call(databases)
        else:
            self.assertFalse(dbaas.MySqlAdmin.create_database.called)

        if users:
            dbaas.MySqlAdmin.create_user.assert_any_call(users)
        else:
            self.assertFalse(dbaas.MySqlAdmin.create_user.called)

        if snapshot:
            self.assertEqual(1, mock_replication.enable_as_slave.call_count)
        else:
            self.assertEqual(0, mock_replication.enable_as_slave.call_count)

    def test_get_replication_snapshot(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        snapshot_id = 'my_snapshot_id'
        log_position = 123456789
        master_ref = 'my_master'
        used_size = 1.0
        total_size = 2.0

        mock_replication = MagicMock()
        mock_replication.enable_as_master = MagicMock()
        mock_replication.snapshot_for_replication = MagicMock(
            return_value=(snapshot_id, log_position))
        mock_replication.get_master_ref = MagicMock(
            return_value=master_ref)
        self.mock_rs_class.return_value = mock_replication
        self.mock_gfvs_class.return_value = (
            {'used': used_size, 'total': total_size})

        expected_replication_snapshot = {
            'dataset': {
                'datastore_manager': self.repl_datastore_manager,
                'dataset_size': used_size,
                'volume_size': total_size,
                'snapshot_id': snapshot_id
            },
            'replication_strategy': self.repl_replication_strategy,
            'master': master_ref,
            'log_position': log_position
        }

        snapshot_info = None
        replica_source_config = None
        # entry point
        replication_snapshot = (
            self.manager.get_replication_snapshot(self.context, snapshot_info,
                                                  replica_source_config))
        # assertions
        self.assertEqual(expected_replication_snapshot, replication_snapshot)
        self.assertEqual(1, mock_replication.enable_as_master.call_count)
        self.assertEqual(
            1, mock_replication.snapshot_for_replication.call_count)
        self.assertEqual(1, mock_replication.get_master_ref.call_count)

    def test_attach_replication_slave_valid(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        total_size = 2.0
        dataset_size = 1.0

        mock_replication = MagicMock()
        mock_replication.enable_as_slave = MagicMock()
        self.mock_rs_class.return_value = mock_replication
        self.mock_gfvs_class.return_value = {'total': total_size}

        snapshot = {'replication_strategy': self.repl_replication_strategy,
                    'dataset': {'dataset_size': dataset_size}}

        # entry point
        self.manager.attach_replica(self.context, snapshot, None)
        # assertions
        self.assertEqual(1, mock_replication.enable_as_slave.call_count)

    def test_attach_replication_slave_invalid(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        total_size = 2.0
        dataset_size = 3.0

        mock_replication = MagicMock()
        mock_replication.enable_as_slave = MagicMock()
        self.mock_rs_class.return_value = mock_replication
        self.mock_gfvs_class.return_value = {'total': total_size}

        snapshot = {'replication_strategy': self.repl_replication_strategy,
                    'dataset': {'dataset_size': dataset_size}}

        # entry point
        self.assertRaises(InsufficientSpaceForReplica,
                          self.manager.attach_replica,
                          self.context, snapshot, None)
        # assertions
        self.assertEqual(0, mock_replication.enable_as_slave.call_count)

    def test_detach_replica(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        mock_replication = MagicMock()
        mock_replication.detach_slave = MagicMock()
        self.mock_rs_class.return_value = mock_replication

        # entry point
        self.manager.detach_replica(self.context)
        # assertions
        self.assertEqual(1, mock_replication.detach_slave.call_count)

    def test_demote_replication_master(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        mock_replication = MagicMock()
        mock_replication.demote_master = MagicMock()
        self.mock_rs_class.return_value = mock_replication

        # entry point
        self.manager.demote_replication_master(self.context)
        # assertions
        self.assertEqual(1, mock_replication.demote_master.call_count)

    def test_get_master_UUID(self):
        app = dbaas.MySqlApp(None)

        def test_case(slave_status, expected_value):
            with patch.object(dbaas.MySqlApp, '_get_slave_status',
                              return_value=slave_status):
                assert_equal(app._get_master_UUID(), expected_value)

        test_case({'Master_UUID': '2a5b-2064-32fb'}, '2a5b-2064-32fb')
        test_case({'Master_UUID': ''}, None)
        test_case({}, None)

    def test_get_last_txn(self):

        def test_case(gtid_list, expected_value):
            with patch.object(dbaas.MySqlApp, '_get_gtid_executed',
                              return_value=gtid_list):
                txn = self.manager.get_last_txn(self.context)
                assert_equal(txn, expected_value)

        with patch.object(dbaas.MySqlApp, '_get_slave_status',
                          return_value={'Master_UUID': '2a5b-2064-32fb'}):
            test_case('2a5b-2064-32fb:1', ('2a5b-2064-32fb', 1))
            test_case('2a5b-2064-32fb:1-5', ('2a5b-2064-32fb', 5))
            test_case('2a5b-2064-32fb:1,4b4-23:5', ('2a5b-2064-32fb', 1))
            test_case('4b4-23:5,2a5b-2064-32fb:1', ('2a5b-2064-32fb', 1))
            test_case('4b-23:5,2a5b-2064-32fb:1,25:3-4', ('2a5b-2064-32fb', 1))
            test_case('4b4-23:1-5,2a5b-2064-32fb:1-10', ('2a5b-2064-32fb', 10))

        with patch.object(dbaas.MySqlApp, '_get_slave_status',
                          return_value={'Master_UUID': ''}):
            test_case('2a5b-2064-32fb:1', (None, 0))

        with patch.object(dbaas.MySqlApp, '_get_slave_status',
                          return_value={}):
            test_case('2a5b-2064-32fb:1', (None, 0))

    def test_rpc_ping(self):
        self.assertTrue(self.manager.rpc_ping(self.context))

    def test_change_passwords(self):
        dbaas.MySqlAdmin.change_passwords = MagicMock(return_value=None)
        self.manager.change_passwords(
            self.context, [{'name': 'test_user', 'password': '******'}])
        dbaas.MySqlAdmin.change_passwords.assert_any_call(
            [{'name': 'test_user', 'password': '******'}])

    def test_update_attributes(self):
        dbaas.MySqlAdmin.update_attributes = MagicMock(return_value=None)
        self.manager.update_attributes(self.context, 'test_user', '%',
                                       {'password': '******'})
        dbaas.MySqlAdmin.update_attributes.assert_any_call('test_user', '%',
                                                           {'password':
                                                            '******'})

    def test_reset_configuration(self):
        dbaas.MySqlAppStatus.get = MagicMock(return_value=MagicMock())
        dbaas.MySqlApp.reset_configuration = MagicMock(return_value=None)
        configuration = {'config_contents': 'some junk'}
        self.manager.reset_configuration(self.context, configuration)
        dbaas.MySqlAppStatus.get.assert_any_call()
        dbaas.MySqlApp.reset_configuration.assert_any_call({'config_contents':
                                                            'some junk'})

    def test_revoke_access(self):
        dbaas.MySqlAdmin.revoke_access = MagicMock(return_value=None)
        self.manager.revoke_access(self.context, 'test_user', '%', 'test_db')
        dbaas.MySqlAdmin.revoke_access.assert_any_call('test_user', '%',
                                                       'test_db')

    def test_list_access(self):
        dbaas.MySqlAdmin.list_access = MagicMock(return_value=['database1'])
        access = self.manager.list_access(self.context, 'test_user', '%')
        self.assertEqual(['database1'], access)
        dbaas.MySqlAdmin.list_access.assert_any_call('test_user', '%')

    def test_restart(self):
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        dbaas.MySqlApp.restart = MagicMock(return_value=None)
        self.manager.restart(self.context)
        dbaas.MySqlAppStatus.get.assert_any_call()
        dbaas.MySqlApp.restart.assert_any_call()

    def test_start_db_with_conf_changes(self):
        mock_status = MagicMock()
        configuration = {'config_contents': 'some junk'}
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        dbaas.MySqlApp.start_db_with_conf_changes = MagicMock(
            return_value=None)
        self.manager.start_db_with_conf_changes(self.context, configuration)
        dbaas.MySqlAppStatus.get.assert_any_call()
        dbaas.MySqlApp.start_db_with_conf_changes.assert_any_call(
            {'config_contents': 'some junk'})

    def test_stop_db(self):
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        dbaas.MySqlApp.stop_db = MagicMock(return_value=None)
        self.manager.stop_db(self.context)
        dbaas.MySqlAppStatus.get.assert_any_call()
        dbaas.MySqlApp.stop_db.assert_any_call(do_not_start_on_reboot=False)

    def test_get_filesystem_stats(self):
        with patch.object(base_dbaas, 'get_filesystem_volume_stats'):
            self.manager.get_filesystem_stats(self.context, '/var/lib/mysql')
            base_dbaas.get_filesystem_volume_stats.assert_any_call(
                '/var/lib/mysql')

    def test_mount_volume(self):
        with patch.object(volume.VolumeDevice, 'mount', return_value=None):
            self.manager.mount_volume(self.context,
                                      device_path='/dev/vdb',
                                      mount_point='/var/lib/mysql')
            test_mount = volume.VolumeDevice.mount.call_args_list[0]
            test_mount.assert_called_with('/var/lib/mysql', False)

    def test_unmount_volume(self):
        with patch.object(volume.VolumeDevice, 'unmount', return_value=None):
            self.manager.unmount_volume(self.context, device_path='/dev/vdb')
            test_unmount = volume.VolumeDevice.unmount.call_args_list[0]
            test_unmount.assert_called_with('/var/lib/mysql')

    def test_resize_fs(self):
        with patch.object(volume.VolumeDevice, 'resize_fs', return_value=None):
            self.manager.resize_fs(self.context, device_path='/dev/vdb')
            test_resize_fs = volume.VolumeDevice.resize_fs.call_args_list[0]
            test_resize_fs.assert_called_with('/var/lib/mysql')

    def test_update_overrides(self):
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        dbaas.MySqlApp.remove_overrides = MagicMock(return_value=None)
        dbaas.MySqlApp.update_overrides = MagicMock(return_value=None)
        self.manager.update_overrides(self.context, 'something_overrides')
        dbaas.MySqlAppStatus.get.assert_any_call()
        dbaas.MySqlApp.remove_overrides.assert_not_called()
        dbaas.MySqlApp.update_overrides.assert_any_call('something_overrides')

    def test_update_overrides_with_remove(self):
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        dbaas.MySqlApp.remove_overrides = MagicMock(return_value=None)
        dbaas.MySqlApp.update_overrides = MagicMock(return_value=None)
        self.manager.update_overrides(self.context, 'something_overrides',
                                      True)
        dbaas.MySqlAppStatus.get.assert_any_call()
        dbaas.MySqlApp.remove_overrides.assert_any_call()
        dbaas.MySqlApp.update_overrides.assert_any_call('something_overrides')

    def test_apply_overrides(self):
        mock_status = MagicMock()
        override = {'some_key': 'some value'}
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        dbaas.MySqlApp.apply_overrides = MagicMock(return_value=None)
        self.manager.apply_overrides(self.context, override)
        dbaas.MySqlAppStatus.get.assert_any_call()
        dbaas.MySqlApp.apply_overrides.assert_any_call({'some_key':
                                                        'some value'})

    def test_get_txn_count(self):
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        dbaas.MySqlApp.get_txn_count = MagicMock(return_value=(9879))
        txn_count = self.manager.get_txn_count(self.context)
        self.assertEqual(9879, txn_count)
        dbaas.MySqlAppStatus.get.assert_any_call()
        dbaas.MySqlApp.get_txn_count.assert_any_call()

    def test_get_latest_txn_id(self):
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        dbaas.MySqlApp.get_latest_txn_id = MagicMock(
            return_value=('2a5b-2064-32fb:1'))
        latest_txn_id = self.manager.get_latest_txn_id(self.context)
        self.assertEqual('2a5b-2064-32fb:1', latest_txn_id)
        dbaas.MySqlAppStatus.get.assert_any_call()
        dbaas.MySqlApp.get_latest_txn_id.assert_any_call()

    def test_wait_for_txn(self):
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        dbaas.MySqlApp.wait_for_txn = MagicMock(return_value=None)
        self.manager.wait_for_txn(self.context, '4b4-23:5,2a5b-2064-32fb:1')
        dbaas.MySqlAppStatus.get.assert_any_call()
        dbaas.MySqlApp.wait_for_txn.assert_any_call('4b4-23:5,2a5b-2064-32fb:1'
                                                    )

    def test_make_read_only(self):
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        dbaas.MySqlApp.make_read_only = MagicMock(return_value=None)
        self.manager.make_read_only(self.context, 'ON')
        dbaas.MySqlAppStatus.get.assert_any_call()
        dbaas.MySqlApp.make_read_only.assert_any_call('ON')

    def test_cleanup_source_on_replica_detach(self):
        mock_replication = MagicMock()
        mock_replication.cleanup_source_on_replica_detach = MagicMock()
        self.mock_rs_class.return_value = mock_replication
        snapshot = {'replication_strategy': self.repl_replication_strategy,
                    'dataset': {'dataset_size': '1.0'}}

        # entry point
        self.manager.cleanup_source_on_replica_detach(self.context, snapshot)
        # assertions
        self.assertEqual(
            1, mock_replication.cleanup_source_on_replica_detach.call_count)

    def test_get_replica_context(self):
        replication_user = {
            'name': 'repl_user',
            'password': '******'
        }
        master_ref = {
            'host': '1.2.3.4',
            'port': 3306
        }
        rep_info = {
            'master': master_ref,
            'log_position': {
                'replication_user': replication_user
            }
        }
        mock_replication = MagicMock()
        mock_replication.get_replica_context = MagicMock(return_value=rep_info)
        self.mock_rs_class.return_value = mock_replication

        # entry point
        replica_info = self.manager.get_replica_context(self.context)
        # assertions
        self.assertEqual(1, mock_replication.get_replica_context.call_count)
        self.assertEqual(rep_info, replica_info)

    def test_enable_as_master(self):
        mock_replication = MagicMock()
        mock_replication.enable_as_master = MagicMock()
        self.mock_rs_class.return_value = mock_replication

        # entry point
        self.manager.enable_as_master(self.context, None)
        # assertions
        self.assertEqual(mock_replication.enable_as_master.call_count, 1)

    def test__perform_restore(self):
        backup_info = {'id': 'backup_id_123abc',
                       'location': 'fake-location',
                       'type': 'InnoBackupEx',
                       'checksum': 'fake-checksum',
                       }
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        app = dbaas.MySqlApp(dbaas.MySqlAppStatus.get())
        backup.restore = MagicMock(side_effect=ProcessExecutionError)
        self.assertRaises(ProcessExecutionError,
                          self.manager._perform_restore, backup_info,
                          self.context, '/var/lib/mysql', app)
        app.status.set_status.assert_called_with(
            rd_instance.ServiceStatuses.FAILED)
Exemplo n.º 7
0
class GuestAgentManagerTest(testtools.TestCase):

    def setUp(self):
        super(GuestAgentManagerTest, self).setUp()
        self.context = TroveContext()
        self.manager = Manager()
        self.origin_MySqlAppStatus = dbaas.MySqlAppStatus
        self.origin_os_path_exists = os.path.exists
        self.origin_format = volume.VolumeDevice.format
        self.origin_migrate_data = volume.VolumeDevice.migrate_data
        self.origin_mount = volume.VolumeDevice.mount
        self.origin_stop_mysql = dbaas.MySqlApp.stop_db
        self.origin_start_mysql = dbaas.MySqlApp.start_mysql
        self.origin_pkg_is_installed = pkg.Package.pkg_is_installed
        self.origin_os_path_exists = os.path.exists

    def tearDown(self):
        super(GuestAgentManagerTest, self).tearDown()
        dbaas.MySqlAppStatus = self.origin_MySqlAppStatus
        os.path.exists = self.origin_os_path_exists
        volume.VolumeDevice.format = self.origin_format
        volume.VolumeDevice.migrate_data = self.origin_migrate_data
        volume.VolumeDevice.mount = self.origin_mount
        dbaas.MySqlApp.stop_db = self.origin_stop_mysql
        dbaas.MySqlApp.start_mysql = self.origin_start_mysql
        pkg.Package.pkg_is_installed = self.origin_pkg_is_installed
        os.path.exists = self.origin_os_path_exists
        unstub()

    def test_update_status(self):
        mock_status = mock()
        when(dbaas.MySqlAppStatus).get().thenReturn(mock_status)
        self.manager.update_status(self.context)
        verify(dbaas.MySqlAppStatus).get()
        verify(mock_status).update()

    def test_create_database(self):
        when(dbaas.MySqlAdmin).create_database(['db1']).thenReturn(None)
        self.manager.create_database(self.context, ['db1'])
        verify(dbaas.MySqlAdmin).create_database(['db1'])

    def test_create_user(self):
        when(dbaas.MySqlAdmin).create_user(['user1']).thenReturn(None)
        self.manager.create_user(self.context, ['user1'])
        verify(dbaas.MySqlAdmin).create_user(['user1'])

    def test_delete_database(self):
        databases = ['db1']
        when(dbaas.MySqlAdmin).delete_database(databases).thenReturn(None)
        self.manager.delete_database(self.context, databases)
        verify(dbaas.MySqlAdmin).delete_database(databases)

    def test_delete_user(self):
        user = ['user1']
        when(dbaas.MySqlAdmin).delete_user(user).thenReturn(None)
        self.manager.delete_user(self.context, user)
        verify(dbaas.MySqlAdmin).delete_user(user)

    def test_grant_access(self):
        username = "******"
        hostname = "test_host"
        databases = ["test_database"]
        when(dbaas.MySqlAdmin).grant_access(username,
                                            hostname,
                                            databases).thenReturn(None)

        self.manager.grant_access(self.context,
                                  username,
                                  hostname,
                                  databases)

        verify(dbaas.MySqlAdmin).grant_access(username, hostname, databases)

    def test_list_databases(self):
        when(dbaas.MySqlAdmin).list_databases(None, None,
                                              False).thenReturn(['database1'])
        databases = self.manager.list_databases(self.context)
        self.assertThat(databases, Not(Is(None)))
        self.assertThat(databases, Equals(['database1']))
        verify(dbaas.MySqlAdmin).list_databases(None, None, False)

    def test_list_users(self):
        when(dbaas.MySqlAdmin).list_users(None, None,
                                          False).thenReturn(['user1'])
        users = self.manager.list_users(self.context)
        self.assertThat(users, Equals(['user1']))
        verify(dbaas.MySqlAdmin).list_users(None, None, False)

    def test_get_users(self):
        username = ['user1']
        hostname = ['host']
        when(dbaas.MySqlAdmin).get_user(username,
                                        hostname).thenReturn(['user1'])
        users = self.manager.get_user(self.context, username, hostname)
        self.assertThat(users, Equals(['user1']))
        verify(dbaas.MySqlAdmin).get_user(username, hostname)

    def test_enable_root(self):
        when(dbaas.MySqlAdmin).enable_root().thenReturn('user_id_stuff')
        user_id = self.manager.enable_root(self.context)
        self.assertThat(user_id, Is('user_id_stuff'))
        verify(dbaas.MySqlAdmin).enable_root()

    def test_is_root_enabled(self):
        when(dbaas.MySqlAdmin).is_root_enabled().thenReturn(True)
        is_enabled = self.manager.is_root_enabled(self.context)
        self.assertThat(is_enabled, Is(True))
        verify(dbaas.MySqlAdmin).is_root_enabled()

    def test_create_backup(self):
        when(backup).backup(self.context, 'backup_id_123').thenReturn(None)
        # entry point
        Manager().create_backup(self.context, 'backup_id_123')
        # assertions
        verify(backup).backup(self.context, 'backup_id_123')

    def test_prepare_device_path_true(self):
        self._prepare_dynamic()

    def test_prepare_device_path_false(self):
        self._prepare_dynamic(device_path=None)

    def test_prepare_mysql_not_installed(self):
        self._prepare_dynamic(is_mysql_installed=False)

    def test_prepare_mysql_from_backup(self):
        self._prepare_dynamic(backup_id='backup_id_123abc')

    def test_prepare_mysql_from_backup_with_root(self):
        self._prepare_dynamic(backup_id='backup_id_123abc',
                              is_root_enabled=True)

    def _prepare_dynamic(self, device_path='/dev/vdb', is_mysql_installed=True,
                         backup_id=None, is_root_enabled=False):

        # covering all outcomes is starting to cause trouble here
        COUNT = 1 if device_path else 0
        backup_info = None
        if backup_id is not None:
            backup_info = {'id': backup_id,
                           'location': 'fake-location',
                           'type': 'InnoBackupEx',
                           'checksum': 'fake-checksum',
                           }

        # TODO(juice): this should stub an instance of the MySqlAppStatus
        mock_status = mock()
        when(dbaas.MySqlAppStatus).get().thenReturn(mock_status)
        when(mock_status).begin_install().thenReturn(None)
        when(VolumeDevice).format().thenReturn(None)
        when(VolumeDevice).migrate_data(any()).thenReturn(None)
        when(VolumeDevice).mount().thenReturn(None)
        when(dbaas.MySqlApp).stop_db().thenReturn(None)
        when(dbaas.MySqlApp).start_mysql().thenReturn(None)
        when(dbaas.MySqlApp).install_if_needed(any()).thenReturn(None)
        when(backup).restore(self.context,
                             backup_info,
                             '/var/lib/mysql').thenReturn(None)
        when(dbaas.MySqlApp).secure(any()).thenReturn(None)
        when(dbaas.MySqlApp).secure_root(any()).thenReturn(None)
        (when(pkg.Package).pkg_is_installed(any()).
         thenReturn(is_mysql_installed))
        when(dbaas.MySqlAdmin).is_root_enabled().thenReturn(is_root_enabled)
        when(dbaas.MySqlAdmin).create_user().thenReturn(None)
        when(dbaas.MySqlAdmin).create_database().thenReturn(None)

        when(os.path).exists(any()).thenReturn(True)
        # invocation
        self.manager.prepare(context=self.context,
                             packages=None,
                             memory_mb='2048',
                             databases=None,
                             users=None,
                             device_path=device_path,
                             mount_point='/var/lib/mysql',
                             backup_info=backup_info)
        # verification/assertion
        verify(mock_status).begin_install()

        verify(VolumeDevice, times=COUNT).format()
        verify(dbaas.MySqlApp, times=COUNT).stop_db()
        verify(VolumeDevice, times=COUNT).migrate_data(
            any())
        if backup_info:
            verify(backup).restore(self.context, backup_info, '/var/lib/mysql')
        verify(dbaas.MySqlApp).install_if_needed(any())
        # We dont need to make sure the exact contents are there
        verify(dbaas.MySqlApp).secure(any())
        verify(dbaas.MySqlAdmin, never).create_database()
        verify(dbaas.MySqlAdmin, never).create_user()
        verify(dbaas.MySqlApp).secure_root(secure_remote_root=any())
 def test_create_backup(self):
     backup.backup = MagicMock(return_value=None)
     # entry point
     Manager().create_backup(self.context, 'backup_id_123')
     # assertions
     backup.backup.assert_any_call(self.context, 'backup_id_123')
Exemplo n.º 9
0
 def test_create_backup(self):
     when(backup).backup(self.context, 'backup_id_123').thenReturn(None)
     # entry point
     Manager().create_backup(self.context, 'backup_id_123')
     # assertions
     verify(backup).backup(self.context, 'backup_id_123')
Exemplo n.º 10
0
class GuestAgentManagerTest(testtools.TestCase):
    def setUp(self):
        super(GuestAgentManagerTest, self).setUp()
        self.context = TroveContext()
        self.manager = Manager()
        self.origin_MySqlAppStatus = dbaas.MySqlAppStatus
        self.origin_os_path_exists = os.path.exists
        self.origin_format = volume.VolumeDevice.format
        self.origin_migrate_data = volume.VolumeDevice.migrate_data
        self.origin_mount = volume.VolumeDevice.mount
        self.origin_stop_mysql = dbaas.MySqlApp.stop_db
        self.origin_start_mysql = dbaas.MySqlApp.start_mysql
        self.origin_pkg_is_installed = pkg.Package.pkg_is_installed
        self.origin_os_path_exists = os.path.exists

    def tearDown(self):
        super(GuestAgentManagerTest, self).tearDown()
        dbaas.MySqlAppStatus = self.origin_MySqlAppStatus
        os.path.exists = self.origin_os_path_exists
        volume.VolumeDevice.format = self.origin_format
        volume.VolumeDevice.migrate_data = self.origin_migrate_data
        volume.VolumeDevice.mount = self.origin_mount
        dbaas.MySqlApp.stop_db = self.origin_stop_mysql
        dbaas.MySqlApp.start_mysql = self.origin_start_mysql
        pkg.Package.pkg_is_installed = self.origin_pkg_is_installed
        os.path.exists = self.origin_os_path_exists
        unstub()

    def test_update_status(self):
        mock_status = mock()
        when(dbaas.MySqlAppStatus).get().thenReturn(mock_status)
        self.manager.update_status(self.context)
        verify(dbaas.MySqlAppStatus).get()
        verify(mock_status).update()

    def test_create_database(self):
        when(dbaas.MySqlAdmin).create_database(['db1']).thenReturn(None)
        self.manager.create_database(self.context, ['db1'])
        verify(dbaas.MySqlAdmin).create_database(['db1'])

    def test_create_user(self):
        when(dbaas.MySqlAdmin).create_user(['user1']).thenReturn(None)
        self.manager.create_user(self.context, ['user1'])
        verify(dbaas.MySqlAdmin).create_user(['user1'])

    def test_delete_database(self):
        databases = ['db1']
        when(dbaas.MySqlAdmin).delete_database(databases).thenReturn(None)
        self.manager.delete_database(self.context, databases)
        verify(dbaas.MySqlAdmin).delete_database(databases)

    def test_delete_user(self):
        user = ['user1']
        when(dbaas.MySqlAdmin).delete_user(user).thenReturn(None)
        self.manager.delete_user(self.context, user)
        verify(dbaas.MySqlAdmin).delete_user(user)

    def test_grant_access(self):
        username = "******"
        hostname = "test_host"
        databases = ["test_database"]
        when(dbaas.MySqlAdmin).grant_access(username,
                                            hostname,
                                            databases).thenReturn(None)

        self.manager.grant_access(self.context,
                                  username,
                                  hostname,
                                  databases)

        verify(dbaas.MySqlAdmin).grant_access(username, hostname, databases)

    def test_list_databases(self):
        when(dbaas.MySqlAdmin).list_databases(None, None,
                                              False).thenReturn(['database1'])
        databases = self.manager.list_databases(self.context)
        self.assertThat(databases, Not(Is(None)))
        self.assertThat(databases, Equals(['database1']))
        verify(dbaas.MySqlAdmin).list_databases(None, None, False)

    def test_list_users(self):
        when(dbaas.MySqlAdmin).list_users(None, None,
                                          False).thenReturn(['user1'])
        users = self.manager.list_users(self.context)
        self.assertThat(users, Equals(['user1']))
        verify(dbaas.MySqlAdmin).list_users(None, None, False)

    def test_get_users(self):
        username = ['user1']
        hostname = ['host']
        when(dbaas.MySqlAdmin).get_user(username,
                                        hostname).thenReturn(['user1'])
        users = self.manager.get_user(self.context, username, hostname)
        self.assertThat(users, Equals(['user1']))
        verify(dbaas.MySqlAdmin).get_user(username, hostname)

    def test_enable_root(self):
        when(dbaas.MySqlAdmin).enable_root().thenReturn('user_id_stuff')
        user_id = self.manager.enable_root(self.context)
        self.assertThat(user_id, Is('user_id_stuff'))
        verify(dbaas.MySqlAdmin).enable_root()

    def test_is_root_enabled(self):
        when(dbaas.MySqlAdmin).is_root_enabled().thenReturn(True)
        is_enabled = self.manager.is_root_enabled(self.context)
        self.assertThat(is_enabled, Is(True))
        verify(dbaas.MySqlAdmin).is_root_enabled()

    def test_create_backup(self):
        when(backup).backup(self.context, 'backup_id_123').thenReturn(None)
        # entry point
        Manager().create_backup(self.context, 'backup_id_123')
        # assertions
        verify(backup).backup(self.context, 'backup_id_123')

    def test_prepare_device_path_true(self):
        self._prepare_dynamic()

    def test_prepare_device_path_false(self):
        self._prepare_dynamic(device_path=None)

    def test_prepare_mysql_not_installed(self):
        self._prepare_dynamic(is_mysql_installed=False)

    def test_prepare_mysql_from_backup(self):
        self._prepare_dynamic(backup_id='backup_id_123abc')

    def test_prepare_mysql_from_backup_with_root(self):
        self._prepare_dynamic(backup_id='backup_id_123abc',
                              is_root_enabled=True)

    def _prepare_dynamic(self, device_path='/dev/vdb', is_mysql_installed=True,
                         backup_id=None, is_root_enabled=False,
                         overrides=None):
        # covering all outcomes is starting to cause trouble here
        COUNT = 1 if device_path else 0
        backup_info = None
        if backup_id is not None:
            backup_info = {'id': backup_id,
                           'location': 'fake-location',
                           'type': 'InnoBackupEx',
                           'checksum': 'fake-checksum',
                           }

        # TODO(juice): this should stub an instance of the MySqlAppStatus
        mock_status = mock()
        when(dbaas.MySqlAppStatus).get().thenReturn(mock_status)
        when(mock_status).begin_install().thenReturn(None)
        when(VolumeDevice).format().thenReturn(None)
        when(VolumeDevice).migrate_data(any()).thenReturn(None)
        when(VolumeDevice).mount().thenReturn(None)
        when(dbaas.MySqlApp).stop_db().thenReturn(None)
        when(dbaas.MySqlApp).start_mysql().thenReturn(None)
        when(dbaas.MySqlApp).install_if_needed(any()).thenReturn(None)
        when(backup).restore(self.context,
                             backup_info,
                             '/var/lib/mysql').thenReturn(None)
        when(dbaas.MySqlApp).secure(any()).thenReturn(None)
        when(dbaas.MySqlApp).secure_root(any()).thenReturn(None)
        (when(pkg.Package).pkg_is_installed(any()).
         thenReturn(is_mysql_installed))
        when(dbaas.MySqlAdmin).is_root_enabled().thenReturn(is_root_enabled)
        when(dbaas.MySqlAdmin).create_user().thenReturn(None)
        when(dbaas.MySqlAdmin).create_database().thenReturn(None)

        when(os.path).exists(any()).thenReturn(True)
        # invocation
        self.manager.prepare(context=self.context,
                             packages=None,
                             memory_mb='2048',
                             databases=None,
                             users=None,
                             device_path=device_path,
                             mount_point='/var/lib/mysql',
                             backup_info=backup_info,
                             overrides=overrides)
        # verification/assertion
        verify(mock_status).begin_install()

        verify(VolumeDevice, times=COUNT).format()
        verify(dbaas.MySqlApp, times=COUNT).stop_db()
        verify(VolumeDevice, times=COUNT).migrate_data(
            any())
        if backup_info:
            verify(backup).restore(self.context, backup_info, '/var/lib/mysql')
        verify(dbaas.MySqlApp).install_if_needed(any())
        # We dont need to make sure the exact contents are there
        verify(dbaas.MySqlApp).secure(any(), overrides)
        verify(dbaas.MySqlAdmin, never).create_database()
        verify(dbaas.MySqlAdmin, never).create_user()
        verify(dbaas.MySqlApp).secure_root(secure_remote_root=any())
Exemplo n.º 11
0
class GuestAgentManagerTest(testtools.TestCase):
    def setUp(self):
        super(GuestAgentManagerTest, self).setUp()
        self.context = TroveContext()
        self.manager = Manager()
        self.origin_MySqlAppStatus = dbaas.MySqlAppStatus
        self.origin_os_path_exists = os.path.exists
        self.origin_format = volume.VolumeDevice.format
        self.origin_migrate_data = volume.VolumeDevice.migrate_data
        self.origin_mount = volume.VolumeDevice.mount
        self.origin_unmount = volume.VolumeDevice.unmount
        self.origin_mount_points = volume.VolumeDevice.mount_points
        self.origin_stop_mysql = dbaas.MySqlApp.stop_db
        self.origin_start_mysql = dbaas.MySqlApp.start_mysql
        self.origin_update_overrides = dbaas.MySqlApp.update_overrides
        self.origin_pkg_is_installed = pkg.Package.pkg_is_installed
        self.origin_os_path_exists = os.path.exists
        self.origin_chown = operating_system.chown
        # set up common mock objects, etc. for replication testing
        self.patcher_gfvs = patch(
            'trove.guestagent.dbaas.get_filesystem_volume_stats')
        self.patcher_rs = patch(self.manager.replication_namespace + "." +
                                self.manager.replication_strategy)
        self.mock_gfvs_class = self.patcher_gfvs.start()
        self.mock_rs_class = self.patcher_rs.start()
        self.repl_datastore_manager = 'mysql'
        self.repl_replication_strategy = 'MysqlGTIDReplication'

    def tearDown(self):
        super(GuestAgentManagerTest, self).tearDown()
        dbaas.MySqlAppStatus = self.origin_MySqlAppStatus
        os.path.exists = self.origin_os_path_exists
        volume.VolumeDevice.format = self.origin_format
        volume.VolumeDevice.migrate_data = self.origin_migrate_data
        volume.VolumeDevice.mount = self.origin_mount
        volume.VolumeDevice.unmount = self.origin_unmount
        volume.VolumeDevice.mount_points = self.origin_mount_points
        dbaas.MySqlApp.stop_db = self.origin_stop_mysql
        dbaas.MySqlApp.start_mysql = self.origin_start_mysql
        dbaas.MySqlApp.update_overrides = self.origin_update_overrides
        operating_system.chown = self.origin_chown
        pkg.Package.pkg_is_installed = self.origin_pkg_is_installed
        os.path.exists = self.origin_os_path_exists
        # teardown the replication mock objects
        self.patcher_gfvs.stop()
        self.patcher_rs.stop()

    def test_update_status(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        self.manager.update_status(self.context)
        dbaas.MySqlAppStatus.get.assert_any_call()
        mock_status.update.assert_any_call()

    def test_create_database(self):
        dbaas.MySqlAdmin.create_database = MagicMock(return_value=None)
        self.manager.create_database(self.context, ['db1'])
        dbaas.MySqlAdmin.create_database.assert_any_call(['db1'])

    def test_create_user(self):
        dbaas.MySqlAdmin.create_user = MagicMock(return_value=None)
        self.manager.create_user(self.context, ['user1'])
        dbaas.MySqlAdmin.create_user.assert_any_call(['user1'])

    def test_delete_database(self):
        databases = ['db1']
        dbaas.MySqlAdmin.delete_database = MagicMock(return_value=None)
        self.manager.delete_database(self.context, databases)
        dbaas.MySqlAdmin.delete_database.assert_any_call(databases)

    def test_delete_user(self):
        user = ['user1']
        dbaas.MySqlAdmin.delete_user = MagicMock(return_value=None)
        self.manager.delete_user(self.context, user)
        dbaas.MySqlAdmin.delete_user.assert_any_call(user)

    def test_grant_access(self):
        username = "******"
        hostname = "test_host"
        databases = ["test_database"]
        dbaas.MySqlAdmin.grant_access = MagicMock(return_value=None)
        self.manager.grant_access(self.context, username, hostname, databases)

        dbaas.MySqlAdmin.grant_access.assert_any_call(username, hostname,
                                                      databases)

    def test_list_databases(self):
        dbaas.MySqlAdmin.list_databases = MagicMock(return_value=['database1'])
        databases = self.manager.list_databases(self.context)
        self.assertThat(databases, Not(Is(None)))
        self.assertThat(databases, Equals(['database1']))
        dbaas.MySqlAdmin.list_databases.assert_any_call(None, None, False)

    def test_list_users(self):
        dbaas.MySqlAdmin.list_users = MagicMock(return_value=['user1'])
        users = self.manager.list_users(self.context)
        self.assertThat(users, Equals(['user1']))
        dbaas.MySqlAdmin.list_users.assert_any_call(None, None, False)

    def test_get_users(self):
        username = ['user1']
        hostname = ['host']
        dbaas.MySqlAdmin.get_user = MagicMock(return_value=['user1'])
        users = self.manager.get_user(self.context, username, hostname)
        self.assertThat(users, Equals(['user1']))
        dbaas.MySqlAdmin.get_user.assert_any_call(username, hostname)

    def test_enable_root(self):
        dbaas.MySqlAdmin.enable_root = MagicMock(return_value='user_id_stuff')
        user_id = self.manager.enable_root(self.context)
        self.assertThat(user_id, Is('user_id_stuff'))
        dbaas.MySqlAdmin.enable_root.assert_any_call()

    def test_is_root_enabled(self):
        dbaas.MySqlAdmin.is_root_enabled = MagicMock(return_value=True)
        is_enabled = self.manager.is_root_enabled(self.context)
        self.assertThat(is_enabled, Is(True))
        dbaas.MySqlAdmin.is_root_enabled.assert_any_call()

    def test_create_backup(self):
        backup.backup = MagicMock(return_value=None)
        # entry point
        Manager().create_backup(self.context, 'backup_id_123')
        # assertions
        backup.backup.assert_any_call(self.context, 'backup_id_123')

    def test_prepare_device_path_true(self):
        self._prepare_dynamic()

    def test_prepare_device_path_false(self):
        self._prepare_dynamic(device_path=None)

    def test_prepare_device_path_mounted(self):
        self._prepare_dynamic(is_mounted=True)

    def test_prepare_mysql_not_installed(self):
        self._prepare_dynamic(is_mysql_installed=False)

    def test_prepare_mysql_from_backup(self):
        self._prepare_dynamic(backup_id='backup_id_123abc')

    def test_prepare_mysql_from_backup_with_root(self):
        self._prepare_dynamic(backup_id='backup_id_123abc',
                              is_root_enabled=True)

    def test_prepare_mysql_with_root_password(self):
        self._prepare_dynamic(root_password='******')

    def test_prepare_mysql_with_users_and_databases(self):
        self._prepare_dynamic(databases=['db1'], users=['user1'])

    def test_prepare_mysql_with_snapshot(self):
        snapshot = {
            'replication_strategy': self.repl_replication_strategy,
            'dataset': {
                'dataset_size': 1.0
            },
            'config': None
        }
        self._prepare_dynamic(snapshot=snapshot)

    def _prepare_dynamic(self,
                         device_path='/dev/vdb',
                         is_mysql_installed=True,
                         backup_id=None,
                         is_root_enabled=False,
                         root_password=None,
                         overrides=None,
                         is_mounted=False,
                         databases=None,
                         users=None,
                         snapshot=None):
        # covering all outcomes is starting to cause trouble here
        COUNT = 1 if device_path else 0
        backup_info = None
        if backup_id is not None:
            backup_info = {
                'id': backup_id,
                'location': 'fake-location',
                'type': 'InnoBackupEx',
                'checksum': 'fake-checksum',
            }

        # TODO(juice): this should stub an instance of the MySqlAppStatus
        mock_status = MagicMock()

        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        mock_status.begin_install = MagicMock(return_value=None)
        VolumeDevice.format = MagicMock(return_value=None)
        VolumeDevice.migrate_data = MagicMock(return_value=None)
        VolumeDevice.mount = MagicMock(return_value=None)
        mount_points = []
        if is_mounted:
            mount_points = ['/mnt']
        VolumeDevice.mount_points = MagicMock(return_value=mount_points)
        VolumeDevice.unmount = MagicMock(return_value=None)
        set_data_dir_patcher = patch.object(dbaas.MySqlApp,
                                            'set_data_dir',
                                            return_value='/var/lib/mysql')
        self.addCleanup(set_data_dir_patcher.stop)
        set_data_dir_patcher.start()
        dbaas.MySqlApp.stop_db = MagicMock(return_value=None)
        dbaas.MySqlApp.start_mysql = MagicMock(return_value=None)
        dbaas.MySqlApp.update_overrides = MagicMock(return_value=None)
        dbaas.MySqlApp.install_if_needed = MagicMock(return_value=None)
        backup.restore = MagicMock(return_value=None)
        dbaas.MySqlApp.secure = MagicMock(return_value=None)
        dbaas.MySqlApp.secure_root = MagicMock(return_value=None)
        pkg.Package.pkg_is_installed = MagicMock(
            return_value=is_mysql_installed)
        dbaas.MySqlAdmin.is_root_enabled = MagicMock(
            return_value=is_root_enabled)
        dbaas.MySqlAdmin.create_user = MagicMock(return_value=None)
        dbaas.MySqlAdmin.create_database = MagicMock(return_value=None)
        dbaas.MySqlAdmin.enable_root = MagicMock(return_value=None)
        operating_system.chown = MagicMock(return_value=None)
        os.path.exists = MagicMock(return_value=True)
        mock_replication = MagicMock()
        mock_replication.enable_as_slave = MagicMock()
        self.mock_rs_class.return_value = mock_replication
        # invocation
        self.manager.prepare(context=self.context,
                             packages=None,
                             memory_mb='2048',
                             databases=databases,
                             users=users,
                             device_path=device_path,
                             mount_point='/var/lib/mysql',
                             backup_info=backup_info,
                             root_password=root_password,
                             overrides=overrides,
                             cluster_config=None,
                             snapshot=snapshot)

        # verification/assertion
        mock_status.begin_install.assert_any_call()

        self.assertEqual(COUNT, VolumeDevice.format.call_count)
        self.assertEqual(COUNT, VolumeDevice.migrate_data.call_count)
        self.assertEqual(COUNT, VolumeDevice.mount_points.call_count)
        self.assertEqual(COUNT, dbaas.MySqlApp.stop_db.call_count)
        if is_mounted:
            self.assertEqual(1, VolumeDevice.unmount.call_count)
        else:
            self.assertEqual(0, VolumeDevice.unmount.call_count)
        if backup_info:
            backup.restore.assert_any_call(self.context, backup_info,
                                           '/var/lib/mysql/data')
        dbaas.MySqlApp.install_if_needed.assert_any_call(None)
        # We don't need to make sure the exact contents are there
        dbaas.MySqlApp.secure.assert_any_call(None, None)
        dbaas.MySqlApp.secure_root.assert_any_call(
            secure_remote_root=not is_root_enabled)

        if root_password:
            dbaas.MySqlAdmin.enable_root.assert_any_call(root_password)
        if databases:
            dbaas.MySqlAdmin.create_database.assert_any_call(databases)
        else:
            self.assertFalse(dbaas.MySqlAdmin.create_database.called)

        if users:
            dbaas.MySqlAdmin.create_user.assert_any_call(users)
        else:
            self.assertFalse(dbaas.MySqlAdmin.create_user.called)

        if snapshot:
            self.assertEqual(1, mock_replication.enable_as_slave.call_count)
        else:
            self.assertEqual(0, mock_replication.enable_as_slave.call_count)

    def test_get_replication_snapshot(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        snapshot_id = 'my_snapshot_id'
        log_position = 123456789
        master_ref = 'my_master'
        used_size = 1.0
        total_size = 2.0

        mock_replication = MagicMock()
        mock_replication.enable_as_master = MagicMock()
        mock_replication.snapshot_for_replication = MagicMock(
            return_value=(snapshot_id, log_position))
        mock_replication.get_master_ref = MagicMock(return_value=master_ref)
        self.mock_rs_class.return_value = mock_replication
        self.mock_gfvs_class.return_value = ({
            'used': used_size,
            'total': total_size
        })

        expected_replication_snapshot = {
            'dataset': {
                'datastore_manager': self.repl_datastore_manager,
                'dataset_size': used_size,
                'volume_size': total_size,
                'snapshot_id': snapshot_id
            },
            'replication_strategy': self.repl_replication_strategy,
            'master': master_ref,
            'log_position': log_position
        }

        snapshot_info = None
        replica_source_config = None
        # entry point
        replication_snapshot = (self.manager.get_replication_snapshot(
            self.context, snapshot_info, replica_source_config))
        # assertions
        self.assertEqual(expected_replication_snapshot, replication_snapshot)
        self.assertEqual(1, mock_replication.enable_as_master.call_count)
        self.assertEqual(1,
                         mock_replication.snapshot_for_replication.call_count)
        self.assertEqual(1, mock_replication.get_master_ref.call_count)

    def test_attach_replication_slave_valid(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        total_size = 2.0
        dataset_size = 1.0

        mock_replication = MagicMock()
        mock_replication.enable_as_slave = MagicMock()
        self.mock_rs_class.return_value = mock_replication
        self.mock_gfvs_class.return_value = {'total': total_size}

        snapshot = {
            'replication_strategy': self.repl_replication_strategy,
            'dataset': {
                'dataset_size': dataset_size
            }
        }

        # entry point
        self.manager.attach_replica(self.context, snapshot, None)
        # assertions
        self.assertEqual(1, mock_replication.enable_as_slave.call_count)

    def test_attach_replication_slave_invalid(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        total_size = 2.0
        dataset_size = 3.0

        mock_replication = MagicMock()
        mock_replication.enable_as_slave = MagicMock()
        self.mock_rs_class.return_value = mock_replication
        self.mock_gfvs_class.return_value = {'total': total_size}

        snapshot = {
            'replication_strategy': self.repl_replication_strategy,
            'dataset': {
                'dataset_size': dataset_size
            }
        }

        # entry point
        self.assertRaises(InsufficientSpaceForReplica,
                          self.manager.attach_replica, self.context, snapshot,
                          None)
        # assertions
        self.assertEqual(0, mock_replication.enable_as_slave.call_count)

    def test_detach_replica(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        mock_replication = MagicMock()
        mock_replication.detach_slave = MagicMock()
        self.mock_rs_class.return_value = mock_replication

        # entry point
        self.manager.detach_replica(self.context)
        # assertions
        self.assertEqual(1, mock_replication.detach_slave.call_count)

    def test_demote_replication_master(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        mock_replication = MagicMock()
        mock_replication.demote_master = MagicMock()
        self.mock_rs_class.return_value = mock_replication

        # entry point
        self.manager.demote_replication_master(self.context)
        # assertions
        self.assertEqual(1, mock_replication.demote_master.call_count)

    def test_get_master_UUID(self):
        app = dbaas.MySqlApp(None)

        def test_case(slave_status, expected_value):
            with patch.object(dbaas.MySqlApp,
                              '_get_slave_status',
                              return_value=slave_status):
                assert_equal(app._get_master_UUID(), expected_value)

        test_case({'Master_UUID': '2a5b-2064-32fb'}, '2a5b-2064-32fb')
        test_case({'Master_UUID': ''}, None)
        test_case({}, None)

    def test_get_last_txn(self):
        def test_case(gtid_list, expected_value):
            with patch.object(dbaas.MySqlApp,
                              '_get_gtid_executed',
                              return_value=gtid_list):
                txn = self.manager.get_last_txn(self.context)
                assert_equal(txn, expected_value)

        with patch.object(dbaas.MySqlApp,
                          '_get_slave_status',
                          return_value={'Master_UUID': '2a5b-2064-32fb'}):
            test_case('2a5b-2064-32fb:1', ('2a5b-2064-32fb', 1))
            test_case('2a5b-2064-32fb:1-5', ('2a5b-2064-32fb', 5))
            test_case('2a5b-2064-32fb:1,4b4-23:5', ('2a5b-2064-32fb', 1))
            test_case('4b4-23:5,2a5b-2064-32fb:1', ('2a5b-2064-32fb', 1))
            test_case('4b-23:5,2a5b-2064-32fb:1,25:3-4', ('2a5b-2064-32fb', 1))
            test_case('4b4-23:1-5,2a5b-2064-32fb:1-10', ('2a5b-2064-32fb', 10))

        with patch.object(dbaas.MySqlApp,
                          '_get_slave_status',
                          return_value={'Master_UUID': ''}):
            test_case('2a5b-2064-32fb:1', (None, 0))

        with patch.object(dbaas.MySqlApp, '_get_slave_status',
                          return_value={}):
            test_case('2a5b-2064-32fb:1', (None, 0))

    def test_rpc_ping(self):
        self.assertTrue(self.manager.rpc_ping(self.context))

    def test_change_passwords(self):
        dbaas.MySqlAdmin.change_passwords = MagicMock(return_value=None)
        self.manager.change_passwords(self.context, [{
            'name': 'test_user',
            'password': '******'
        }])
        dbaas.MySqlAdmin.change_passwords.assert_any_call([{
            'name':
            'test_user',
            'password':
            '******'
        }])

    def test_update_attributes(self):
        dbaas.MySqlAdmin.update_attributes = MagicMock(return_value=None)
        self.manager.update_attributes(self.context, 'test_user', '%',
                                       {'password': '******'})
        dbaas.MySqlAdmin.update_attributes.assert_any_call(
            'test_user', '%', {'password': '******'})

    def test_reset_configuration(self):
        dbaas.MySqlAppStatus.get = MagicMock(return_value=MagicMock())
        dbaas.MySqlApp.reset_configuration = MagicMock(return_value=None)
        configuration = {'config_contents': 'some junk'}
        self.manager.reset_configuration(self.context, configuration)
        dbaas.MySqlAppStatus.get.assert_any_call()
        dbaas.MySqlApp.reset_configuration.assert_any_call(
            {'config_contents': 'some junk'})

    def test_revoke_access(self):
        dbaas.MySqlAdmin.revoke_access = MagicMock(return_value=None)
        self.manager.revoke_access(self.context, 'test_user', '%', 'test_db')
        dbaas.MySqlAdmin.revoke_access.assert_any_call('test_user', '%',
                                                       'test_db')

    def test_list_access(self):
        dbaas.MySqlAdmin.list_access = MagicMock(return_value=['database1'])
        access = self.manager.list_access(self.context, 'test_user', '%')
        self.assertEqual(['database1'], access)
        dbaas.MySqlAdmin.list_access.assert_any_call('test_user', '%')

    def test_restart(self):
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        dbaas.MySqlApp.restart = MagicMock(return_value=None)
        self.manager.restart(self.context)
        dbaas.MySqlAppStatus.get.assert_any_call()
        dbaas.MySqlApp.restart.assert_any_call()

    def test_start_db_with_conf_changes(self):
        mock_status = MagicMock()
        configuration = {'config_contents': 'some junk'}
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        dbaas.MySqlApp.start_db_with_conf_changes = MagicMock(
            return_value=None)
        self.manager.start_db_with_conf_changes(self.context, configuration)
        dbaas.MySqlAppStatus.get.assert_any_call()
        dbaas.MySqlApp.start_db_with_conf_changes.assert_any_call(
            {'config_contents': 'some junk'})

    def test_stop_db(self):
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        dbaas.MySqlApp.stop_db = MagicMock(return_value=None)
        self.manager.stop_db(self.context)
        dbaas.MySqlAppStatus.get.assert_any_call()
        dbaas.MySqlApp.stop_db.assert_any_call(do_not_start_on_reboot=False)

    def test_get_filesystem_stats(self):
        with patch.object(base_dbaas, 'get_filesystem_volume_stats'):
            self.manager.get_filesystem_stats(self.context, '/var/lib/mysql')
            base_dbaas.get_filesystem_volume_stats.assert_any_call(
                '/var/lib/mysql')

    def test_mount_volume(self):
        with patch.object(volume.VolumeDevice, 'mount', return_value=None):
            self.manager.mount_volume(self.context,
                                      device_path='/dev/vdb',
                                      mount_point='/var/lib/mysql')
            test_mount = volume.VolumeDevice.mount.call_args_list[0]
            test_mount.assert_called_with('/var/lib/mysql', False)

    def test_unmount_volume(self):
        with patch.object(volume.VolumeDevice, 'unmount', return_value=None):
            self.manager.unmount_volume(self.context, device_path='/dev/vdb')
            test_unmount = volume.VolumeDevice.unmount.call_args_list[0]
            test_unmount.assert_called_with('/var/lib/mysql')

    def test_resize_fs(self):
        with patch.object(volume.VolumeDevice, 'resize_fs', return_value=None):
            self.manager.resize_fs(self.context, device_path='/dev/vdb')
            test_resize_fs = volume.VolumeDevice.resize_fs.call_args_list[0]
            test_resize_fs.assert_called_with('/var/lib/mysql')

    def test_update_overrides(self):
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        dbaas.MySqlApp.remove_overrides = MagicMock(return_value=None)
        dbaas.MySqlApp.update_overrides = MagicMock(return_value=None)
        self.manager.update_overrides(self.context, 'something_overrides')
        dbaas.MySqlAppStatus.get.assert_any_call()
        dbaas.MySqlApp.remove_overrides.assert_not_called()
        dbaas.MySqlApp.update_overrides.assert_any_call('something_overrides')

    def test_update_overrides_with_remove(self):
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        dbaas.MySqlApp.remove_overrides = MagicMock(return_value=None)
        dbaas.MySqlApp.update_overrides = MagicMock(return_value=None)
        self.manager.update_overrides(self.context, 'something_overrides',
                                      True)
        dbaas.MySqlAppStatus.get.assert_any_call()
        dbaas.MySqlApp.remove_overrides.assert_any_call()
        dbaas.MySqlApp.update_overrides.assert_any_call('something_overrides')

    def test_apply_overrides(self):
        mock_status = MagicMock()
        override = {'some_key': 'some value'}
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        dbaas.MySqlApp.apply_overrides = MagicMock(return_value=None)
        self.manager.apply_overrides(self.context, override)
        dbaas.MySqlAppStatus.get.assert_any_call()
        dbaas.MySqlApp.apply_overrides.assert_any_call(
            {'some_key': 'some value'})

    def test_get_txn_count(self):
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        dbaas.MySqlApp.get_txn_count = MagicMock(return_value=(9879))
        txn_count = self.manager.get_txn_count(self.context)
        self.assertEqual(9879, txn_count)
        dbaas.MySqlAppStatus.get.assert_any_call()
        dbaas.MySqlApp.get_txn_count.assert_any_call()

    def test_get_latest_txn_id(self):
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        dbaas.MySqlApp.get_latest_txn_id = MagicMock(
            return_value=('2a5b-2064-32fb:1'))
        latest_txn_id = self.manager.get_latest_txn_id(self.context)
        self.assertEqual('2a5b-2064-32fb:1', latest_txn_id)
        dbaas.MySqlAppStatus.get.assert_any_call()
        dbaas.MySqlApp.get_latest_txn_id.assert_any_call()

    def test_wait_for_txn(self):
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        dbaas.MySqlApp.wait_for_txn = MagicMock(return_value=None)
        self.manager.wait_for_txn(self.context, '4b4-23:5,2a5b-2064-32fb:1')
        dbaas.MySqlAppStatus.get.assert_any_call()
        dbaas.MySqlApp.wait_for_txn.assert_any_call(
            '4b4-23:5,2a5b-2064-32fb:1')

    def test_make_read_only(self):
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        dbaas.MySqlApp.make_read_only = MagicMock(return_value=None)
        self.manager.make_read_only(self.context, 'ON')
        dbaas.MySqlAppStatus.get.assert_any_call()
        dbaas.MySqlApp.make_read_only.assert_any_call('ON')

    def test_cleanup_source_on_replica_detach(self):
        mock_replication = MagicMock()
        mock_replication.cleanup_source_on_replica_detach = MagicMock()
        self.mock_rs_class.return_value = mock_replication
        snapshot = {
            'replication_strategy': self.repl_replication_strategy,
            'dataset': {
                'dataset_size': '1.0'
            }
        }

        # entry point
        self.manager.cleanup_source_on_replica_detach(self.context, snapshot)
        # assertions
        self.assertEqual(
            1, mock_replication.cleanup_source_on_replica_detach.call_count)

    def test_get_replica_context(self):
        replication_user = {'name': 'repl_user', 'password': '******'}
        master_ref = {'host': '1.2.3.4', 'port': 3306}
        rep_info = {
            'master': master_ref,
            'log_position': {
                'replication_user': replication_user
            }
        }
        mock_replication = MagicMock()
        mock_replication.get_replica_context = MagicMock(return_value=rep_info)
        self.mock_rs_class.return_value = mock_replication

        # entry point
        replica_info = self.manager.get_replica_context(self.context)
        # assertions
        self.assertEqual(1, mock_replication.get_replica_context.call_count)
        self.assertEqual(rep_info, replica_info)

    def test_enable_as_master(self):
        mock_replication = MagicMock()
        mock_replication.enable_as_master = MagicMock()
        self.mock_rs_class.return_value = mock_replication

        # entry point
        self.manager.enable_as_master(self.context, None)
        # assertions
        self.assertEqual(mock_replication.enable_as_master.call_count, 1)

    def test__perform_restore(self):
        backup_info = {
            'id': 'backup_id_123abc',
            'location': 'fake-location',
            'type': 'InnoBackupEx',
            'checksum': 'fake-checksum',
        }
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        app = dbaas.MySqlApp(dbaas.MySqlAppStatus.get())
        backup.restore = MagicMock(side_effect=ProcessExecutionError)
        self.assertRaises(ProcessExecutionError, self.manager._perform_restore,
                          backup_info, self.context, '/var/lib/mysql', app)
        app.status.set_status.assert_called_with(
            rd_instance.ServiceStatuses.FAILED)
Exemplo n.º 12
0
class GuestAgentManagerTest(trove_testtools.TestCase):
    def setUp(self):
        super(GuestAgentManagerTest, self).setUp()
        self.context = TroveContext()
        self.replication_strategy = "MysqlGTIDReplication"
        self.patch_rs = patch(
            "trove.guestagent.strategies.replication.get_strategy", return_value=self.replication_strategy
        )
        self.mock_rs = self.patch_rs.start()
        self.addCleanup(self.patch_rs.stop)
        self.manager = Manager()
        self.origin_MySqlAppStatus = dbaas.MySqlAppStatus.get
        self.origin_os_path_exists = os.path.exists
        self.origin_format = volume.VolumeDevice.format
        self.origin_migrate_data = volume.VolumeDevice.migrate_data
        self.origin_mount = volume.VolumeDevice.mount
        self.origin_unmount = volume.VolumeDevice.unmount
        self.origin_mount_points = volume.VolumeDevice.mount_points
        self.origin_stop_mysql = dbaas.MySqlApp.stop_db
        self.origin_start_mysql = dbaas.MySqlApp.start_mysql
        self.origin_update_overrides = dbaas.MySqlApp.update_overrides
        self.origin_install_if_needed = dbaas.MySqlApp.install_if_needed
        self.origin_secure = dbaas.MySqlApp.secure
        self.origin_secure_root = dbaas.MySqlApp.secure_root
        self.origin_pkg_is_installed = pkg.Package.pkg_is_installed
        self.origin_os_path_exists = os.path.exists
        self.origin_chown = operating_system.chown
        # set up common mock objects, etc. for replication testing
        self.patcher_gfvs = patch("trove.guestagent.dbaas.get_filesystem_volume_stats")
        self.patcher_rs = patch("trove.guestagent.strategies.replication.get_instance")
        self.mock_gfvs_class = self.patcher_gfvs.start()
        self.mock_rs_class = self.patcher_rs.start()

    def tearDown(self):
        super(GuestAgentManagerTest, self).tearDown()
        dbaas.MySqlAppStatus.get = self.origin_MySqlAppStatus
        os.path.exists = self.origin_os_path_exists
        volume.VolumeDevice.format = self.origin_format
        volume.VolumeDevice.migrate_data = self.origin_migrate_data
        volume.VolumeDevice.mount = self.origin_mount
        volume.VolumeDevice.unmount = self.origin_unmount
        volume.VolumeDevice.mount_points = self.origin_mount_points
        dbaas.MySqlApp.stop_db = self.origin_stop_mysql
        dbaas.MySqlApp.start_mysql = self.origin_start_mysql
        dbaas.MySqlApp.update_overrides = self.origin_update_overrides
        dbaas.MySqlApp.install_if_needed = self.origin_install_if_needed
        dbaas.MySqlApp.secure = self.origin_secure
        dbaas.MySqlApp.secure_root = self.origin_secure_root
        operating_system.chown = self.origin_chown
        pkg.Package.pkg_is_installed = self.origin_pkg_is_installed
        os.path.exists = self.origin_os_path_exists
        # teardown the replication mock objects
        self.patcher_gfvs.stop()
        self.patcher_rs.stop()

    def test_update_status(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        self.manager.update_status(self.context)
        dbaas.MySqlAppStatus.get.assert_any_call()
        mock_status.update.assert_any_call()

    @patch.object(dbaas.MySqlAdmin, "create_database")
    def test_create_database(self, create_db_mock):
        self.manager.create_database(self.context, ["db1"])
        create_db_mock.assert_any_call(["db1"])

    @patch.object(dbaas.MySqlAdmin, "create_user")
    def test_create_user(self, create_user_mock):
        self.manager.create_user(self.context, ["user1"])
        create_user_mock.assert_any_call(["user1"])

    @patch.object(dbaas.MySqlAdmin, "delete_database")
    def test_delete_database(self, delete_database_mock):
        databases = ["db1"]
        self.manager.delete_database(self.context, databases)
        delete_database_mock.assert_any_call(databases)

    @patch.object(dbaas.MySqlAdmin, "delete_user")
    def test_delete_user(self, delete_user_mock):
        user = ["user1"]
        self.manager.delete_user(self.context, user)
        delete_user_mock.assert_any_call(user)

    @patch.object(dbaas.MySqlAdmin, "grant_access")
    def test_grant_access(self, grant_access_mock):
        username = "******"
        hostname = "test_host"
        databases = ["test_database"]
        self.manager.grant_access(self.context, username, hostname, databases)

        grant_access_mock.assert_any_call(username, hostname, databases)

    @patch.object(dbaas.MySqlAdmin, "list_databases", return_value=["database1"])
    def test_list_databases(self, list_databases_mock):
        databases = self.manager.list_databases(self.context)
        self.assertThat(databases, Not(Is(None)))
        self.assertThat(databases, Equals(list_databases_mock.return_value))
        list_databases_mock.assert_any_call(None, None, False)

    @patch.object(dbaas.MySqlAdmin, "list_users", return_value=["user1"])
    def test_list_users(self, list_users_mock):
        users = self.manager.list_users(self.context)
        self.assertThat(users, Equals(list_users_mock.return_value))
        dbaas.MySqlAdmin.list_users.assert_any_call(None, None, False)

    @patch.object(dbaas.MySqlAdmin, "get_user", return_value=["user1"])
    def test_get_users(self, get_user_mock):
        username = ["user1"]
        hostname = ["host"]
        users = self.manager.get_user(self.context, username, hostname)
        self.assertThat(users, Equals(get_user_mock.return_value))
        get_user_mock.assert_any_call(username, hostname)

    @patch.object(dbaas.MySqlAdmin, "enable_root", return_value="user_id_stuff")
    def test_enable_root(self, enable_root_mock):
        user_id = self.manager.enable_root(self.context)
        self.assertThat(user_id, Is(enable_root_mock.return_value))
        enable_root_mock.assert_any_call()

    @patch.object(dbaas.MySqlAdmin, "disable_root")
    def test_disable_root(self, disable_root_mock):
        self.manager.disable_root(self.context)
        disable_root_mock.assert_any_call()

    @patch.object(dbaas.MySqlAdmin, "is_root_enabled", return_value=True)
    def test_is_root_enabled(self, is_root_enabled_mock):
        is_enabled = self.manager.is_root_enabled(self.context)
        self.assertThat(is_enabled, Is(is_root_enabled_mock.return_value))
        is_root_enabled_mock.assert_any_call()

    @patch.object(backup, "backup")
    def test_create_backup(self, backup_mock):
        # entry point
        Manager().create_backup(self.context, "backup_id_123")
        # assertions
        backup_mock.assert_any_call(self.context, "backup_id_123")

    def test_prepare_device_path_true(self):
        self._prepare_dynamic()

    def test_prepare_device_path_false(self):
        self._prepare_dynamic(device_path=None)

    def test_prepare_device_path_mounted(self):
        self._prepare_dynamic(is_mounted=True)

    def test_prepare_mysql_not_installed(self):
        self._prepare_dynamic(is_mysql_installed=False)

    def test_prepare_mysql_from_backup(self):
        self._prepare_dynamic(backup_id="backup_id_123abc")

    def test_prepare_mysql_from_backup_with_root(self):
        self._prepare_dynamic(backup_id="backup_id_123abc", is_root_enabled=True)

    def test_prepare_mysql_with_root_password(self):
        self._prepare_dynamic(root_password="******")

    def test_prepare_mysql_with_users_and_databases(self):
        self._prepare_dynamic(databases=["db1"], users=["user1"])

    def test_prepare_mysql_with_snapshot(self):
        snapshot = {"replication_strategy": self.replication_strategy, "dataset": {"dataset_size": 1.0}, "config": None}
        total_size = snapshot["dataset"]["dataset_size"] + 1
        self.mock_gfvs_class.return_value = {"total": total_size}
        self._prepare_dynamic(snapshot=snapshot)

    @patch.multiple(dbaas.MySqlAdmin, create_user=DEFAULT, create_database=DEFAULT, enable_root=DEFAULT)
    @patch.object(backup, "restore")
    def _prepare_dynamic(
        self,
        restore_mock,
        create_user,
        create_database,
        enable_root,
        device_path="/dev/vdb",
        is_mysql_installed=True,
        backup_id=None,
        is_root_enabled=False,
        root_password=None,
        overrides=None,
        is_mounted=False,
        databases=None,
        users=None,
        snapshot=None,
    ):
        # covering all outcomes is starting to cause trouble here
        COUNT = 1 if device_path else 0
        backup_info = None
        if backup_id is not None:
            backup_info = {
                "id": backup_id,
                "location": "fake-location",
                "type": "InnoBackupEx",
                "checksum": "fake-checksum",
            }

        # TODO(juice): this should stub an instance of the MySqlAppStatus
        mock_status = MagicMock()

        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        mock_status.begin_install = MagicMock(return_value=None)
        VolumeDevice.format = MagicMock(return_value=None)
        VolumeDevice.migrate_data = MagicMock(return_value=None)
        VolumeDevice.mount = MagicMock(return_value=None)
        mount_points = []
        if is_mounted:
            mount_points = ["/mnt"]
        VolumeDevice.mount_points = MagicMock(return_value=mount_points)
        VolumeDevice.unmount = MagicMock(return_value=None)
        set_data_dir_patcher = patch.object(dbaas.MySqlApp, "set_data_dir", return_value="/var/lib/mysql")
        self.addCleanup(set_data_dir_patcher.stop)
        set_data_dir_patcher.start()
        dbaas.MySqlApp.stop_db = MagicMock(return_value=None)
        dbaas.MySqlApp.start_mysql = MagicMock(return_value=None)
        dbaas.MySqlApp.update_overrides = MagicMock(return_value=None)
        dbaas.MySqlApp.install_if_needed = MagicMock(return_value=None)
        dbaas.MySqlApp.secure = MagicMock(return_value=None)
        dbaas.MySqlApp.secure_root = MagicMock(return_value=None)
        pkg.Package.pkg_is_installed = MagicMock(return_value=is_mysql_installed)
        operating_system.chown = MagicMock(return_value=None)
        os.path.exists = MagicMock(return_value=True)
        mock_replication = MagicMock()
        mock_replication.enable_as_slave = MagicMock()
        self.mock_rs_class.return_value = mock_replication

        with patch.object(dbaas.MySqlAdmin, "is_root_enabled", return_value=is_root_enabled):
            self.manager.prepare(
                context=self.context,
                packages=None,
                memory_mb="2048",
                databases=databases,
                users=users,
                device_path=device_path,
                mount_point="/var/lib/mysql",
                backup_info=backup_info,
                root_password=root_password,
                overrides=overrides,
                cluster_config=None,
                snapshot=snapshot,
            )

        # verification/assertion
        mock_status.begin_install.assert_any_call()

        self.assertEqual(COUNT, VolumeDevice.format.call_count)
        self.assertEqual(COUNT, VolumeDevice.migrate_data.call_count)
        self.assertEqual(COUNT, VolumeDevice.mount_points.call_count)
        self.assertEqual(COUNT, dbaas.MySqlApp.stop_db.call_count)
        if is_mounted:
            self.assertEqual(1, VolumeDevice.unmount.call_count)
        else:
            self.assertEqual(0, VolumeDevice.unmount.call_count)
        if backup_info:
            restore_mock.assert_any_call(self.context, backup_info, "/var/lib/mysql/data")
        dbaas.MySqlApp.install_if_needed.assert_any_call(None)
        # We don't need to make sure the exact contents are there
        dbaas.MySqlApp.secure.assert_any_call(None)
        dbaas.MySqlApp.secure_root.assert_any_call(secure_remote_root=not is_root_enabled)

        if root_password:
            dbaas.MySqlAdmin.enable_root.assert_any_call(root_password)
        if databases:
            dbaas.MySqlAdmin.create_database.assert_any_call(databases)
        else:
            self.assertFalse(dbaas.MySqlAdmin.create_database.called)

        if users:
            dbaas.MySqlAdmin.create_user.assert_any_call(users)
        else:
            self.assertFalse(dbaas.MySqlAdmin.create_user.called)

        if snapshot:
            self.assertEqual(1, mock_replication.enable_as_slave.call_count)
        else:
            self.assertEqual(0, mock_replication.enable_as_slave.call_count)

    def test_get_replication_snapshot(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        snapshot_id = "my_snapshot_id"
        log_position = 123456789
        master_ref = "my_master"
        used_size = 1.0
        total_size = 2.0

        mock_replication = MagicMock()
        mock_replication.enable_as_master = MagicMock()
        mock_replication.snapshot_for_replication = MagicMock(return_value=(snapshot_id, log_position))
        mock_replication.get_master_ref = MagicMock(return_value=master_ref)
        self.mock_rs_class.return_value = mock_replication
        self.mock_gfvs_class.return_value = {"used": used_size, "total": total_size}

        expected_replication_snapshot = {
            "dataset": {
                "datastore_manager": self.manager.manager,
                "dataset_size": used_size,
                "volume_size": total_size,
                "snapshot_id": snapshot_id,
            },
            "replication_strategy": self.replication_strategy,
            "master": master_ref,
            "log_position": log_position,
        }

        snapshot_info = None
        replica_source_config = None
        # entry point
        replication_snapshot = self.manager.get_replication_snapshot(self.context, snapshot_info, replica_source_config)
        # assertions
        self.assertEqual(expected_replication_snapshot, replication_snapshot)
        self.assertEqual(1, mock_replication.enable_as_master.call_count)
        self.assertEqual(1, mock_replication.snapshot_for_replication.call_count)
        self.assertEqual(1, mock_replication.get_master_ref.call_count)

    def test_attach_replication_slave_valid(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        total_size = 2.0
        dataset_size = 1.0

        mock_replication = MagicMock()
        mock_replication.enable_as_slave = MagicMock()
        self.mock_rs_class.return_value = mock_replication
        self.mock_gfvs_class.return_value = {"total": total_size}

        snapshot = {"replication_strategy": self.replication_strategy, "dataset": {"dataset_size": dataset_size}}

        # entry point
        self.manager.attach_replica(self.context, snapshot, None)
        # assertions
        self.assertEqual(1, mock_replication.enable_as_slave.call_count)

    @patch("trove.guestagent.datastore.mysql_common.manager.LOG")
    def test_attach_replication_slave_invalid(self, *args):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        total_size = 2.0
        dataset_size = 3.0

        mock_replication = MagicMock()
        mock_replication.enable_as_slave = MagicMock()
        self.mock_rs_class.return_value = mock_replication
        self.mock_gfvs_class.return_value = {"total": total_size}

        snapshot = {"replication_strategy": self.replication_strategy, "dataset": {"dataset_size": dataset_size}}

        # entry point
        self.assertRaises(InsufficientSpaceForReplica, self.manager.attach_replica, self.context, snapshot, None)
        # assertions
        self.assertEqual(0, mock_replication.enable_as_slave.call_count)

    def test_detach_replica(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        mock_replication = MagicMock()
        mock_replication.detach_slave = MagicMock()
        self.mock_rs_class.return_value = mock_replication

        # entry point
        self.manager.detach_replica(self.context)
        # assertions
        self.assertEqual(1, mock_replication.detach_slave.call_count)

    def test_demote_replication_master(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        mock_replication = MagicMock()
        mock_replication.demote_master = MagicMock()
        self.mock_rs_class.return_value = mock_replication

        # entry point
        self.manager.demote_replication_master(self.context)
        # assertions
        self.assertEqual(1, mock_replication.demote_master.call_count)

    def test_get_master_UUID(self):
        app = dbaas.MySqlApp(None)

        def test_case(slave_status, expected_value):
            with patch.object(dbaas.MySqlApp, "_get_slave_status", return_value=slave_status):
                assert_equal(app._get_master_UUID(), expected_value)

        test_case({"Master_UUID": "2a5b-2064-32fb"}, "2a5b-2064-32fb")
        test_case({"Master_UUID": ""}, None)
        test_case({}, None)

    def test_get_last_txn(self):
        def test_case(gtid_list, expected_value):
            with patch.object(dbaas.MySqlApp, "_get_gtid_executed", return_value=gtid_list):
                txn = self.manager.get_last_txn(self.context)
                assert_equal(txn, expected_value)

        with patch.object(dbaas.MySqlApp, "_get_slave_status", return_value={"Master_UUID": "2a5b-2064-32fb"}):
            test_case("2a5b-2064-32fb:1", ("2a5b-2064-32fb", 1))
            test_case("2a5b-2064-32fb:1-5", ("2a5b-2064-32fb", 5))
            test_case("2a5b-2064-32fb:1,4b4-23:5", ("2a5b-2064-32fb", 1))
            test_case("4b4-23:5,2a5b-2064-32fb:1", ("2a5b-2064-32fb", 1))
            test_case("4b-23:5,2a5b-2064-32fb:1,25:3-4", ("2a5b-2064-32fb", 1))
            test_case("4b4-23:1-5,2a5b-2064-32fb:1-10", ("2a5b-2064-32fb", 10))

        with patch.object(dbaas.MySqlApp, "_get_slave_status", return_value={"Master_UUID": ""}):
            test_case("2a5b-2064-32fb:1", (None, 0))

        with patch.object(dbaas.MySqlApp, "_get_slave_status", return_value={}):
            test_case("2a5b-2064-32fb:1", (None, 0))

    def test_rpc_ping(self):
        self.assertTrue(self.manager.rpc_ping(self.context))

    @patch.object(dbaas.MySqlAdmin, "change_passwords")
    def test_change_passwords(self, change_passwords_mock):
        self.manager.change_passwords(self.context, [{"name": "test_user", "password": "******"}])
        change_passwords_mock.assert_any_call([{"name": "test_user", "password": "******"}])

    @patch.object(dbaas.MySqlAdmin, "update_attributes")
    def test_update_attributes(self, update_attr_mock):
        self.manager.update_attributes(self.context, "test_user", "%", {"password": "******"})
        update_attr_mock.assert_any_call("test_user", "%", {"password": "******"})

    @patch.object(dbaas.MySqlApp, "reset_configuration")
    def test_reset_configuration(self, reset_config_mock):
        dbaas.MySqlAppStatus.get = MagicMock(return_value=MagicMock())
        configuration = {"config_contents": "some junk"}
        self.manager.reset_configuration(self.context, configuration)
        dbaas.MySqlAppStatus.get.assert_any_call()
        reset_config_mock.assert_any_call({"config_contents": "some junk"})

    @patch.object(dbaas.MySqlAdmin, "revoke_access")
    def test_revoke_access(self, revoke_access_mock):
        self.manager.revoke_access(self.context, "test_user", "%", "test_db")
        revoke_access_mock.assert_any_call("test_user", "%", "test_db")

    @patch.object(dbaas.MySqlAdmin, "list_access", return_value=["database1"])
    def test_list_access(self, list_access_mock):
        access = self.manager.list_access(self.context, "test_user", "%")
        self.assertEqual(list_access_mock.return_value, access)
        list_access_mock.assert_any_call("test_user", "%")

    @patch.object(dbaas.MySqlApp, "restart")
    def test_restart(self, restart_mock):
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        self.manager.restart(self.context)
        dbaas.MySqlAppStatus.get.assert_any_call()
        restart_mock.assert_any_call()

    @patch.object(dbaas.MySqlApp, "start_db_with_conf_changes")
    def test_start_db_with_conf_changes(self, start_db_mock):
        mock_status = MagicMock()
        configuration = {"config_contents": "some junk"}
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        self.manager.start_db_with_conf_changes(self.context, configuration)
        dbaas.MySqlAppStatus.get.assert_any_call()
        start_db_mock.assert_any_call({"config_contents": "some junk"})

    def test_stop_db(self):
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        dbaas.MySqlApp.stop_db = MagicMock(return_value=None)
        self.manager.stop_db(self.context)
        dbaas.MySqlAppStatus.get.assert_any_call()
        dbaas.MySqlApp.stop_db.assert_any_call(do_not_start_on_reboot=False)

    def test_get_filesystem_stats(self):
        with patch.object(base_dbaas, "get_filesystem_volume_stats"):
            self.manager.get_filesystem_stats(self.context, "/var/lib/mysql")
            base_dbaas.get_filesystem_volume_stats.assert_any_call("/var/lib/mysql")

    def test_mount_volume(self):
        with patch.object(volume.VolumeDevice, "mount", return_value=None):
            self.manager.mount_volume(self.context, device_path="/dev/vdb", mount_point="/var/lib/mysql")
            test_mount = volume.VolumeDevice.mount.call_args_list[0]
            test_mount.assert_called_with("/var/lib/mysql", False)

    def test_unmount_volume(self):
        with patch.object(volume.VolumeDevice, "unmount", return_value=None):
            self.manager.unmount_volume(self.context, device_path="/dev/vdb")
            test_unmount = volume.VolumeDevice.unmount.call_args_list[0]
            test_unmount.assert_called_with("/var/lib/mysql")

    def test_resize_fs(self):
        with patch.object(volume.VolumeDevice, "resize_fs", return_value=None):
            self.manager.resize_fs(self.context, device_path="/dev/vdb")
            test_resize_fs = volume.VolumeDevice.resize_fs.call_args_list[0]
            test_resize_fs.assert_called_with("/var/lib/mysql")

    @patch.object(dbaas.MySqlApp, "remove_overrides")
    def test_update_overrides(self, remove_config_mock):
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        dbaas.MySqlApp.update_overrides = MagicMock(return_value=None)
        self.manager.update_overrides(self.context, "something_overrides")
        dbaas.MySqlAppStatus.get.assert_any_call()
        remove_config_mock.assert_not_called()
        dbaas.MySqlApp.update_overrides.assert_any_call("something_overrides")

    @patch.object(dbaas.MySqlApp, "remove_overrides")
    def test_update_overrides_with_remove(self, remove_overrides_mock):
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        dbaas.MySqlApp.update_overrides = MagicMock(return_value=None)
        self.manager.update_overrides(self.context, "something_overrides", True)
        dbaas.MySqlAppStatus.get.assert_any_call()
        remove_overrides_mock.assert_any_call()
        dbaas.MySqlApp.update_overrides.assert_any_call("something_overrides")

    @patch.object(dbaas.MySqlApp, "apply_overrides")
    def test_apply_overrides(self, apply_overrides_mock):
        mock_status = MagicMock()
        override = {"some_key": "some value"}
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        self.manager.apply_overrides(self.context, override)
        dbaas.MySqlAppStatus.get.assert_any_call()
        apply_overrides_mock.assert_any_call({"some_key": "some value"})

    @patch.object(dbaas.MySqlApp, "get_txn_count", return_value=(9879))
    def test_get_txn_count(self, get_txn_count_mock):
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        txn_count = self.manager.get_txn_count(self.context)
        self.assertEqual(get_txn_count_mock.return_value, txn_count)
        dbaas.MySqlAppStatus.get.assert_any_call()
        get_txn_count_mock.assert_any_call()

    @patch.object(dbaas.MySqlApp, "get_latest_txn_id", return_value=("2a5b-2064-32fb:1"))
    def test_get_latest_txn_id(self, get_latest_txn_id_mock):
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        latest_txn_id = self.manager.get_latest_txn_id(self.context)
        self.assertEqual(get_latest_txn_id_mock.return_value, latest_txn_id)
        dbaas.MySqlAppStatus.get.assert_any_call()
        get_latest_txn_id_mock.assert_any_call()

    @patch.object(dbaas.MySqlApp, "wait_for_txn")
    def test_wait_for_txn(self, wait_for_txn_mock):
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        self.manager.wait_for_txn(self.context, "4b4-23:5,2a5b-2064-32fb:1")
        dbaas.MySqlAppStatus.get.assert_any_call()
        wait_for_txn_mock.assert_any_call("4b4-23:5,2a5b-2064-32fb:1")

    @patch.object(dbaas.MySqlApp, "make_read_only")
    def test_make_read_only(self, make_read_only_mock):
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        self.manager.make_read_only(self.context, "ON")
        dbaas.MySqlAppStatus.get.assert_any_call()
        make_read_only_mock.assert_any_call("ON")

    def test_cleanup_source_on_replica_detach(self):
        mock_replication = MagicMock()
        mock_replication.cleanup_source_on_replica_detach = MagicMock()
        self.mock_rs_class.return_value = mock_replication
        snapshot = {"replication_strategy": self.replication_strategy, "dataset": {"dataset_size": "1.0"}}

        # entry point
        self.manager.cleanup_source_on_replica_detach(self.context, snapshot)
        # assertions
        self.assertEqual(1, mock_replication.cleanup_source_on_replica_detach.call_count)

    def test_get_replica_context(self):
        replication_user = {"name": "repl_user", "password": "******"}
        master_ref = {"host": "1.2.3.4", "port": 3306}
        rep_info = {"master": master_ref, "log_position": {"replication_user": replication_user}}
        mock_replication = MagicMock()
        mock_replication.get_replica_context = MagicMock(return_value=rep_info)
        self.mock_rs_class.return_value = mock_replication

        # entry point
        replica_info = self.manager.get_replica_context(self.context)
        # assertions
        self.assertEqual(1, mock_replication.get_replica_context.call_count)
        self.assertEqual(rep_info, replica_info)

    def test_enable_as_master(self):
        mock_replication = MagicMock()
        mock_replication.enable_as_master = MagicMock()
        self.mock_rs_class.return_value = mock_replication

        # entry point
        self.manager.enable_as_master(self.context, None)
        # assertions
        self.assertEqual(mock_replication.enable_as_master.call_count, 1)

    @patch("trove.guestagent.datastore.mysql_common.manager.LOG")
    def test__perform_restore(self, *args):
        backup_info = {
            "id": "backup_id_123abc",
            "location": "fake-location",
            "type": "InnoBackupEx",
            "checksum": "fake-checksum",
        }
        mock_status = MagicMock()
        self.manager.appStatus = mock_status
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        app = dbaas.MySqlApp(dbaas.MySqlAppStatus.get())
        with patch.object(backup, "restore", side_effect=ProcessExecutionError):
            self.assertRaises(
                ProcessExecutionError, self.manager._perform_restore, backup_info, self.context, "/var/lib/mysql", app
            )
            app.status.set_status.assert_called_with(rd_instance.ServiceStatuses.FAILED)
Exemplo n.º 13
0
 def test_create_backup(self, backup_mock):
     # entry point
     Manager().create_backup(self.context, 'backup_id_123')
     # assertions
     backup_mock.assert_any_call(self.context, 'backup_id_123')
Exemplo n.º 14
0
class GuestAgentManagerTest(testtools.TestCase):
    def setUp(self):
        super(GuestAgentManagerTest, self).setUp()
        self.context = TroveContext()
        self.manager = Manager()
        self.origin_MySqlAppStatus = dbaas.MySqlAppStatus
        self.origin_os_path_exists = os.path.exists
        self.origin_format = volume.VolumeDevice.format
        self.origin_migrate_data = volume.VolumeDevice.migrate_data
        self.origin_mount = volume.VolumeDevice.mount
        self.origin_unmount = volume.VolumeDevice.unmount
        self.origin_mount_points = volume.VolumeDevice.mount_points
        self.origin_stop_mysql = dbaas.MySqlApp.stop_db
        self.origin_start_mysql = dbaas.MySqlApp.start_mysql
        self.origin_pkg_is_installed = pkg.Package.pkg_is_installed
        self.origin_os_path_exists = os.path.exists

    def tearDown(self):
        super(GuestAgentManagerTest, self).tearDown()
        dbaas.MySqlAppStatus = self.origin_MySqlAppStatus
        os.path.exists = self.origin_os_path_exists
        volume.VolumeDevice.format = self.origin_format
        volume.VolumeDevice.migrate_data = self.origin_migrate_data
        volume.VolumeDevice.mount = self.origin_mount
        volume.VolumeDevice.unmount = self.origin_unmount
        volume.VolumeDevice.mount_points = self.origin_mount_points
        dbaas.MySqlApp.stop_db = self.origin_stop_mysql
        dbaas.MySqlApp.start_mysql = self.origin_start_mysql
        pkg.Package.pkg_is_installed = self.origin_pkg_is_installed
        os.path.exists = self.origin_os_path_exists

    def test_update_status(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        self.manager.update_status(self.context)
        dbaas.MySqlAppStatus.get.assert_any_call()
        mock_status.update.assert_any_call()

    def test_create_database(self):
        dbaas.MySqlAdmin.create_database = MagicMock(return_value=None)
        self.manager.create_database(self.context, ['db1'])
        dbaas.MySqlAdmin.create_database.assert_any_call(['db1'])

    def test_create_user(self):
        dbaas.MySqlAdmin.create_user = MagicMock(return_value=None)
        self.manager.create_user(self.context, ['user1'])
        dbaas.MySqlAdmin.create_user.assert_any_call(['user1'])

    def test_delete_database(self):
        databases = ['db1']
        dbaas.MySqlAdmin.delete_database = MagicMock(return_value=None)
        self.manager.delete_database(self.context, databases)
        dbaas.MySqlAdmin.delete_database.assert_any_call(databases)

    def test_delete_user(self):
        user = ['user1']
        dbaas.MySqlAdmin.delete_user = MagicMock(return_value=None)
        self.manager.delete_user(self.context, user)
        dbaas.MySqlAdmin.delete_user.assert_any_call(user)

    def test_grant_access(self):
        username = "******"
        hostname = "test_host"
        databases = ["test_database"]
        dbaas.MySqlAdmin.grant_access = MagicMock(return_value=None)
        self.manager.grant_access(self.context, username, hostname, databases)

        dbaas.MySqlAdmin.grant_access.assert_any_call(username, hostname,
                                                      databases)

    def test_list_databases(self):
        dbaas.MySqlAdmin.list_databases = MagicMock(return_value=['database1'])
        databases = self.manager.list_databases(self.context)
        self.assertThat(databases, Not(Is(None)))
        self.assertThat(databases, Equals(['database1']))
        dbaas.MySqlAdmin.list_databases.assert_any_call(None, None, False)

    def test_list_users(self):
        dbaas.MySqlAdmin.list_users = MagicMock(return_value=['user1'])
        users = self.manager.list_users(self.context)
        self.assertThat(users, Equals(['user1']))
        dbaas.MySqlAdmin.list_users.assert_any_call(None, None, False)

    def test_get_users(self):
        username = ['user1']
        hostname = ['host']
        dbaas.MySqlAdmin.get_user = MagicMock(return_value=['user1'])
        users = self.manager.get_user(self.context, username, hostname)
        self.assertThat(users, Equals(['user1']))
        dbaas.MySqlAdmin.get_user.assert_any_call(username, hostname)

    def test_enable_root(self):
        dbaas.MySqlAdmin.enable_root = MagicMock(return_value='user_id_stuff')
        user_id = self.manager.enable_root(self.context)
        self.assertThat(user_id, Is('user_id_stuff'))
        dbaas.MySqlAdmin.enable_root.assert_any_call()

    def test_is_root_enabled(self):
        dbaas.MySqlAdmin.is_root_enabled = MagicMock(return_value=True)
        is_enabled = self.manager.is_root_enabled(self.context)
        self.assertThat(is_enabled, Is(True))
        dbaas.MySqlAdmin.is_root_enabled.assert_any_call()

    def test_create_backup(self):
        backup.backup = MagicMock(return_value=None)
        # entry point
        Manager().create_backup(self.context, 'backup_id_123')
        # assertions
        backup.backup.assert_any_call(self.context, 'backup_id_123')

    def test_prepare_device_path_true(self):
        self._prepare_dynamic()

    def test_prepare_device_path_false(self):
        self._prepare_dynamic(device_path=None)

    def test_prepare_device_path_mounted(self):
        self._prepare_dynamic(is_mounted=True)

    def test_prepare_mysql_not_installed(self):
        self._prepare_dynamic(is_mysql_installed=False)

    def test_prepare_mysql_from_backup(self):
        self._prepare_dynamic(backup_id='backup_id_123abc')

    def test_prepare_mysql_from_backup_with_root(self):
        self._prepare_dynamic(backup_id='backup_id_123abc',
                              is_root_enabled=True)

    def _prepare_dynamic(self,
                         device_path='/dev/vdb',
                         is_mysql_installed=True,
                         backup_id=None,
                         is_root_enabled=False,
                         overrides=None,
                         is_mounted=False):
        # covering all outcomes is starting to cause trouble here
        COUNT = 1 if device_path else 0
        backup_info = None
        if backup_id is not None:
            backup_info = {
                'id': backup_id,
                'location': 'fake-location',
                'type': 'InnoBackupEx',
                'checksum': 'fake-checksum',
            }

        # TODO(juice): this should stub an instance of the MySqlAppStatus
        mock_status = MagicMock()

        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        mock_status.begin_install = MagicMock(return_value=None)
        VolumeDevice.format = MagicMock(return_value=None)
        VolumeDevice.migrate_data = MagicMock(return_value=None)
        VolumeDevice.mount = MagicMock(return_value=None)
        mount_points = []
        if is_mounted:
            mount_points = ['/mnt']
        VolumeDevice.mount_points = MagicMock(return_value=mount_points)
        VolumeDevice.unmount = MagicMock(return_value=None)
        dbaas.MySqlApp.stop_db = MagicMock(return_value=None)
        dbaas.MySqlApp.start_mysql = MagicMock(return_value=None)
        dbaas.MySqlApp.install_if_needed = MagicMock(return_value=None)
        backup.restore = MagicMock(return_value=None)
        dbaas.MySqlApp.secure = MagicMock(return_value=None)
        dbaas.MySqlApp.secure_root = MagicMock(return_value=None)
        pkg.Package.pkg_is_installed = MagicMock(
            return_value=is_mysql_installed)
        dbaas.MySqlAdmin.is_root_enabled = MagicMock(
            return_value=is_root_enabled)
        dbaas.MySqlAdmin.create_user = MagicMock(return_value=None)
        dbaas.MySqlAdmin.create_database = MagicMock(return_value=None)

        os.path.exists = MagicMock(return_value=True)
        # invocation
        self.manager.prepare(context=self.context,
                             packages=None,
                             memory_mb='2048',
                             databases=None,
                             users=None,
                             device_path=device_path,
                             mount_point='/var/lib/mysql',
                             backup_info=backup_info,
                             overrides=overrides)

        # verification/assertion
        mock_status.begin_install.assert_any_call()

        self.assertEqual(VolumeDevice.format.call_count, COUNT)
        self.assertEqual(VolumeDevice.migrate_data.call_count, COUNT)
        self.assertEqual(VolumeDevice.mount_points.call_count, COUNT)
        self.assertEqual(dbaas.MySqlApp.stop_db.call_count, COUNT)
        if is_mounted:
            self.assertEqual(VolumeDevice.unmount.call_count, 1)
        else:
            self.assertEqual(VolumeDevice.unmount.call_count, 0)
        if backup_info:
            backup.restore.assert_any_call(self.context, backup_info,
                                           '/var/lib/mysql')
        dbaas.MySqlApp.install_if_needed.assert_any_call(None)
        # We dont need to make sure the exact contents are there
        dbaas.MySqlApp.secure.assert_any_call(None, None)
        self.assertFalse(dbaas.MySqlAdmin.create_database.called)
        self.assertFalse(dbaas.MySqlAdmin.create_user.called)
        dbaas.MySqlApp.secure_root.assert_any_call(
            secure_remote_root=not is_root_enabled)
Exemplo n.º 15
0
class GuestAgentManagerTest(testtools.TestCase):
    def setUp(self):
        super(GuestAgentManagerTest, self).setUp()
        self.context = TroveContext()
        self.manager = Manager()
        self.origin_MySqlAppStatus = dbaas.MySqlAppStatus
        self.origin_os_path_exists = os.path.exists
        self.origin_format = volume.VolumeDevice.format
        self.origin_migrate_data = volume.VolumeDevice.migrate_data
        self.origin_mount = volume.VolumeDevice.mount
        self.origin_stop_mysql = dbaas.MySqlApp.stop_db
        self.origin_start_mysql = dbaas.MySqlApp.start_mysql
        self.origin_pkg_is_installed = pkg.Package.pkg_is_installed
        self.origin_os_path_exists = os.path.exists

    def tearDown(self):
        super(GuestAgentManagerTest, self).tearDown()
        dbaas.MySqlAppStatus = self.origin_MySqlAppStatus
        os.path.exists = self.origin_os_path_exists
        volume.VolumeDevice.format = self.origin_format
        volume.VolumeDevice.migrate_data = self.origin_migrate_data
        volume.VolumeDevice.mount = self.origin_mount
        dbaas.MySqlApp.stop_db = self.origin_stop_mysql
        dbaas.MySqlApp.start_mysql = self.origin_start_mysql
        pkg.Package.pkg_is_installed = self.origin_pkg_is_installed
        os.path.exists = self.origin_os_path_exists

    def test_update_status(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        self.manager.update_status(self.context)
        dbaas.MySqlAppStatus.get.assert_any_call()
        mock_status.update.assert_any_call()

    def test_create_database(self):
        dbaas.MySqlAdmin.create_database = MagicMock(return_value=None)
        self.manager.create_database(self.context, ['db1'])
        dbaas.MySqlAdmin.create_database.assert_any_call(['db1'])

    def test_create_user(self):
        dbaas.MySqlAdmin.create_user = MagicMock(return_value=None)
        self.manager.create_user(self.context, ['user1'])
        dbaas.MySqlAdmin.create_user.assert_any_call(['user1'])

    def test_delete_database(self):
        databases = ['db1']
        dbaas.MySqlAdmin.delete_database = MagicMock(return_value=None)
        self.manager.delete_database(self.context, databases)
        dbaas.MySqlAdmin.delete_database.assert_any_call(databases)

    def test_delete_user(self):
        user = ['user1']
        dbaas.MySqlAdmin.delete_user = MagicMock(return_value=None)
        self.manager.delete_user(self.context, user)
        dbaas.MySqlAdmin.delete_user.assert_any_call(user)

    def test_grant_access(self):
        username = "******"
        hostname = "test_host"
        databases = ["test_database"]
        dbaas.MySqlAdmin.grant_access = MagicMock(return_value=None)
        self.manager.grant_access(self.context,
                                  username,
                                  hostname,
                                  databases)

        dbaas.MySqlAdmin.grant_access.assert_any_call(username,
                                                      hostname,
                                                      databases)

    def test_list_databases(self):
        dbaas.MySqlAdmin.list_databases = MagicMock(return_value=['database1'])
        databases = self.manager.list_databases(self.context)
        self.assertThat(databases, Not(Is(None)))
        self.assertThat(databases, Equals(['database1']))
        dbaas.MySqlAdmin.list_databases.assert_any_call(None, None, False)

    def test_list_users(self):
        dbaas.MySqlAdmin.list_users = MagicMock(return_value=['user1'])
        users = self.manager.list_users(self.context)
        self.assertThat(users, Equals(['user1']))
        dbaas.MySqlAdmin.list_users.assert_any_call(None, None, False)

    def test_get_users(self):
        username = ['user1']
        hostname = ['host']
        dbaas.MySqlAdmin.get_user = MagicMock(return_value=['user1'])
        users = self.manager.get_user(self.context, username, hostname)
        self.assertThat(users, Equals(['user1']))
        dbaas.MySqlAdmin.get_user.assert_any_call(username, hostname)

    def test_enable_root(self):
        dbaas.MySqlAdmin.enable_root = MagicMock(return_value='user_id_stuff')
        user_id = self.manager.enable_root(self.context)
        self.assertThat(user_id, Is('user_id_stuff'))
        dbaas.MySqlAdmin.enable_root.assert_any_call()

    def test_is_root_enabled(self):
        dbaas.MySqlAdmin.is_root_enabled = MagicMock(return_value=True)
        is_enabled = self.manager.is_root_enabled(self.context)
        self.assertThat(is_enabled, Is(True))
        dbaas.MySqlAdmin.is_root_enabled.assert_any_call()

    def test_create_backup(self):
        backup.backup = MagicMock(return_value=None)
        # entry point
        Manager().create_backup(self.context, 'backup_id_123')
        # assertions
        backup.backup.assert_any_call(self.context, 'backup_id_123')

    def test_prepare_device_path_true(self):
        self._prepare_dynamic()

    def test_prepare_device_path_false(self):
        self._prepare_dynamic(device_path=None)

    def test_prepare_mysql_not_installed(self):
        self._prepare_dynamic(is_mysql_installed=False)

    def test_prepare_mysql_from_backup(self):
        self._prepare_dynamic(backup_id='backup_id_123abc')

    def test_prepare_mysql_from_backup_with_root(self):
        self._prepare_dynamic(backup_id='backup_id_123abc',
                              is_root_enabled=True)

    def _prepare_dynamic(self, device_path='/dev/vdb', is_mysql_installed=True,
                         backup_id=None, is_root_enabled=False,
                         overrides=None):
        # covering all outcomes is starting to cause trouble here
        COUNT = 1 if device_path else 0
        backup_info = None
        if backup_id is not None:
            backup_info = {'id': backup_id,
                           'location': 'fake-location',
                           'type': 'InnoBackupEx',
                           'checksum': 'fake-checksum',
                           }

        # TODO(juice): this should stub an instance of the MySqlAppStatus
        mock_status = MagicMock()

        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        mock_status.begin_install = MagicMock(return_value=None)
        VolumeDevice.format = MagicMock(return_value=None)
        VolumeDevice.migrate_data = MagicMock(return_value=None)
        VolumeDevice.mount = MagicMock(return_value=None)
        dbaas.MySqlApp.stop_db = MagicMock(return_value=None)
        dbaas.MySqlApp.start_mysql = MagicMock(return_value=None)
        dbaas.MySqlApp.install_if_needed = MagicMock(return_value=None)
        backup.restore = MagicMock(return_value=None)
        dbaas.MySqlApp.secure = MagicMock(return_value=None)
        dbaas.MySqlApp.secure_root = MagicMock(return_value=None)
        pkg.Package.pkg_is_installed = MagicMock(
            return_value=is_mysql_installed)
        dbaas.MySqlAdmin.is_root_enabled = MagicMock(
            return_value=is_root_enabled)
        dbaas.MySqlAdmin.create_user = MagicMock(return_value=None)
        dbaas.MySqlAdmin.create_database = MagicMock(return_value=None)

        os.path.exists = MagicMock(return_value=True)
        # invocation
        self.manager.prepare(context=self.context,
                             packages=None,
                             memory_mb='2048',
                             databases=None,
                             users=None,
                             device_path=device_path,
                             mount_point='/var/lib/mysql',
                             backup_info=backup_info,
                             overrides=overrides)

        # verification/assertion
        mock_status.begin_install.assert_any_call()

        self.assertEqual(VolumeDevice.format.call_count, COUNT)
        self.assertEqual(VolumeDevice.migrate_data.call_count, COUNT)
        self.assertEqual(dbaas.MySqlApp.stop_db.call_count, COUNT)
        if backup_info:
            backup.restore.assert_any_call(self.context,
                                           backup_info,
                                           '/var/lib/mysql')
        dbaas.MySqlApp.install_if_needed.assert_any_call(None)
        # We dont need to make sure the exact contents are there
        dbaas.MySqlApp.secure.assert_any_call(None, None)
        self.assertFalse(dbaas.MySqlAdmin.create_database.called)
        self.assertFalse(dbaas.MySqlAdmin.create_user.called)
        dbaas.MySqlApp.secure_root.assert_any_call(
            secure_remote_root=not is_root_enabled)
Exemplo n.º 16
0
class GuestAgentManagerTest(testtools.TestCase):
    def setUp(self):
        super(GuestAgentManagerTest, self).setUp()
        self.context = TroveContext()
        self.manager = Manager()
        self.origin_MySqlAppStatus = dbaas.MySqlAppStatus
        self.origin_os_path_exists = os.path.exists
        self.origin_format = volume.VolumeDevice.format
        self.origin_migrate_data = volume.VolumeDevice.migrate_data
        self.origin_mount = volume.VolumeDevice.mount
        self.origin_unmount = volume.VolumeDevice.unmount
        self.origin_mount_points = volume.VolumeDevice.mount_points
        self.origin_stop_mysql = dbaas.MySqlApp.stop_db
        self.origin_start_mysql = dbaas.MySqlApp.start_mysql
        self.origin_pkg_is_installed = pkg.Package.pkg_is_installed
        self.origin_os_path_exists = os.path.exists
        # set up common mock objects, etc. for replication testing
        self.patcher_gfvs = patch(
            'trove.guestagent.dbaas.get_filesystem_volume_stats')
        self.patcher_rs = patch(
            'trove.guestagent.datastore.mysql.manager.'
            'REPLICATION_STRATEGY_CLASS')
        self.mock_gfvs_class = self.patcher_gfvs.start()
        self.mock_rs_class = self.patcher_rs.start()
        self.repl_datastore_manager = 'mysql'
        self.repl_replication_strategy = 'MysqlGTIDReplication'

    def tearDown(self):
        super(GuestAgentManagerTest, self).tearDown()
        dbaas.MySqlAppStatus = self.origin_MySqlAppStatus
        os.path.exists = self.origin_os_path_exists
        volume.VolumeDevice.format = self.origin_format
        volume.VolumeDevice.migrate_data = self.origin_migrate_data
        volume.VolumeDevice.mount = self.origin_mount
        volume.VolumeDevice.unmount = self.origin_unmount
        volume.VolumeDevice.mount_points = self.origin_mount_points
        dbaas.MySqlApp.stop_db = self.origin_stop_mysql
        dbaas.MySqlApp.start_mysql = self.origin_start_mysql
        pkg.Package.pkg_is_installed = self.origin_pkg_is_installed
        os.path.exists = self.origin_os_path_exists
        # teardown the replication mock objects
        self.patcher_gfvs.stop()
        self.patcher_rs.stop()

    def test_update_status(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        self.manager.update_status(self.context)
        dbaas.MySqlAppStatus.get.assert_any_call()
        mock_status.update.assert_any_call()

    def test_create_database(self):
        dbaas.MySqlAdmin.create_database = MagicMock(return_value=None)
        self.manager.create_database(self.context, ['db1'])
        dbaas.MySqlAdmin.create_database.assert_any_call(['db1'])

    def test_create_user(self):
        dbaas.MySqlAdmin.create_user = MagicMock(return_value=None)
        self.manager.create_user(self.context, ['user1'])
        dbaas.MySqlAdmin.create_user.assert_any_call(['user1'])

    def test_delete_database(self):
        databases = ['db1']
        dbaas.MySqlAdmin.delete_database = MagicMock(return_value=None)
        self.manager.delete_database(self.context, databases)
        dbaas.MySqlAdmin.delete_database.assert_any_call(databases)

    def test_delete_user(self):
        user = ['user1']
        dbaas.MySqlAdmin.delete_user = MagicMock(return_value=None)
        self.manager.delete_user(self.context, user)
        dbaas.MySqlAdmin.delete_user.assert_any_call(user)

    def test_grant_access(self):
        username = "******"
        hostname = "test_host"
        databases = ["test_database"]
        dbaas.MySqlAdmin.grant_access = MagicMock(return_value=None)
        self.manager.grant_access(self.context,
                                  username,
                                  hostname,
                                  databases)

        dbaas.MySqlAdmin.grant_access.assert_any_call(username,
                                                      hostname,
                                                      databases)

    def test_list_databases(self):
        dbaas.MySqlAdmin.list_databases = MagicMock(return_value=['database1'])
        databases = self.manager.list_databases(self.context)
        self.assertThat(databases, Not(Is(None)))
        self.assertThat(databases, Equals(['database1']))
        dbaas.MySqlAdmin.list_databases.assert_any_call(None, None, False)

    def test_list_users(self):
        dbaas.MySqlAdmin.list_users = MagicMock(return_value=['user1'])
        users = self.manager.list_users(self.context)
        self.assertThat(users, Equals(['user1']))
        dbaas.MySqlAdmin.list_users.assert_any_call(None, None, False)

    def test_get_users(self):
        username = ['user1']
        hostname = ['host']
        dbaas.MySqlAdmin.get_user = MagicMock(return_value=['user1'])
        users = self.manager.get_user(self.context, username, hostname)
        self.assertThat(users, Equals(['user1']))
        dbaas.MySqlAdmin.get_user.assert_any_call(username, hostname)

    def test_enable_root(self):
        dbaas.MySqlAdmin.enable_root = MagicMock(return_value='user_id_stuff')
        user_id = self.manager.enable_root(self.context)
        self.assertThat(user_id, Is('user_id_stuff'))
        dbaas.MySqlAdmin.enable_root.assert_any_call()

    def test_is_root_enabled(self):
        dbaas.MySqlAdmin.is_root_enabled = MagicMock(return_value=True)
        is_enabled = self.manager.is_root_enabled(self.context)
        self.assertThat(is_enabled, Is(True))
        dbaas.MySqlAdmin.is_root_enabled.assert_any_call()

    def test_create_backup(self):
        backup.backup = MagicMock(return_value=None)
        # entry point
        Manager().create_backup(self.context, 'backup_id_123')
        # assertions
        backup.backup.assert_any_call(self.context, 'backup_id_123')

    def test_prepare_device_path_true(self):
        self._prepare_dynamic()

    def test_prepare_device_path_false(self):
        self._prepare_dynamic(device_path=None)

    def test_prepare_device_path_mounted(self):
        self._prepare_dynamic(is_mounted=True)

    def test_prepare_mysql_not_installed(self):
        self._prepare_dynamic(is_mysql_installed=False)

    def test_prepare_mysql_from_backup(self):
        self._prepare_dynamic(backup_id='backup_id_123abc')

    def test_prepare_mysql_from_backup_with_root(self):
        self._prepare_dynamic(backup_id='backup_id_123abc',
                              is_root_enabled=True)

    def _prepare_dynamic(self, device_path='/dev/vdb', is_mysql_installed=True,
                         backup_id=None, is_root_enabled=False,
                         overrides=None, is_mounted=False):
        # covering all outcomes is starting to cause trouble here
        COUNT = 1 if device_path else 0
        backup_info = None
        if backup_id is not None:
            backup_info = {'id': backup_id,
                           'location': 'fake-location',
                           'type': 'InnoBackupEx',
                           'checksum': 'fake-checksum',
                           }

        # TODO(juice): this should stub an instance of the MySqlAppStatus
        mock_status = MagicMock()

        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        mock_status.begin_install = MagicMock(return_value=None)
        VolumeDevice.format = MagicMock(return_value=None)
        VolumeDevice.migrate_data = MagicMock(return_value=None)
        VolumeDevice.mount = MagicMock(return_value=None)
        mount_points = []
        if is_mounted:
            mount_points = ['/mnt']
        VolumeDevice.mount_points = MagicMock(return_value=mount_points)
        VolumeDevice.unmount = MagicMock(return_value=None)
        dbaas.MySqlApp.stop_db = MagicMock(return_value=None)
        dbaas.MySqlApp.start_mysql = MagicMock(return_value=None)
        dbaas.MySqlApp.install_if_needed = MagicMock(return_value=None)
        backup.restore = MagicMock(return_value=None)
        dbaas.MySqlApp.secure = MagicMock(return_value=None)
        dbaas.MySqlApp.secure_root = MagicMock(return_value=None)
        pkg.Package.pkg_is_installed = MagicMock(
            return_value=is_mysql_installed)
        dbaas.MySqlAdmin.is_root_enabled = MagicMock(
            return_value=is_root_enabled)
        dbaas.MySqlAdmin.create_user = MagicMock(return_value=None)
        dbaas.MySqlAdmin.create_database = MagicMock(return_value=None)

        os.path.exists = MagicMock(return_value=True)
        # invocation
        self.manager.prepare(context=self.context,
                             packages=None,
                             memory_mb='2048',
                             databases=None,
                             users=None,
                             device_path=device_path,
                             mount_point='/var/lib/mysql',
                             backup_info=backup_info,
                             overrides=overrides,
                             cluster_config=None)

        # verification/assertion
        mock_status.begin_install.assert_any_call()

        self.assertEqual(VolumeDevice.format.call_count, COUNT)
        self.assertEqual(VolumeDevice.migrate_data.call_count, COUNT)
        self.assertEqual(VolumeDevice.mount_points.call_count, COUNT)
        self.assertEqual(dbaas.MySqlApp.stop_db.call_count, COUNT)
        if is_mounted:
            self.assertEqual(VolumeDevice.unmount.call_count, 1)
        else:
            self.assertEqual(VolumeDevice.unmount.call_count, 0)
        if backup_info:
            backup.restore.assert_any_call(self.context,
                                           backup_info,
                                           '/var/lib/mysql')
        dbaas.MySqlApp.install_if_needed.assert_any_call(None)
        # We don't need to make sure the exact contents are there
        dbaas.MySqlApp.secure.assert_any_call(None, None)
        self.assertFalse(dbaas.MySqlAdmin.create_database.called)
        self.assertFalse(dbaas.MySqlAdmin.create_user.called)
        dbaas.MySqlApp.secure_root.assert_any_call(
            secure_remote_root=not is_root_enabled)

    def test_get_replication_snapshot(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        snapshot_id = 'my_snapshot_id'
        log_position = 123456789
        master_ref = 'my_master'
        used_size = 1.0
        total_size = 2.0

        mock_replication = MagicMock()
        mock_replication.enable_as_master = MagicMock()
        mock_replication.snapshot_for_replication = MagicMock(
            return_value=(snapshot_id, log_position))
        mock_replication.get_master_ref = MagicMock(
            return_value=master_ref)
        self.mock_rs_class.return_value = mock_replication
        self.mock_gfvs_class.return_value = (
            {'used': used_size, 'total': total_size})

        expected_replication_snapshot = {
            'dataset': {
                'datastore_manager': self.repl_datastore_manager,
                'dataset_size': used_size,
                'volume_size': total_size,
                'snapshot_id': snapshot_id
            },
            'replication_strategy': self.repl_replication_strategy,
            'master': master_ref,
            'log_position': log_position
        }

        snapshot_info = None
        replica_source_config = None
        # entry point
        replication_snapshot = (
            self.manager.get_replication_snapshot(self.context, snapshot_info,
                                                  replica_source_config))
        # assertions
        self.assertEqual(expected_replication_snapshot, replication_snapshot)
        self.assertEqual(mock_replication.enable_as_master.call_count, 1)
        self.assertEqual(
            mock_replication.snapshot_for_replication.call_count, 1)
        self.assertEqual(mock_replication.get_master_ref.call_count, 1)

    def test_attach_replication_slave_valid(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        total_size = 2.0
        dataset_size = 1.0

        mock_replication = MagicMock()
        mock_replication.enable_as_slave = MagicMock()
        self.mock_rs_class.return_value = mock_replication
        self.mock_gfvs_class.return_value = {'total': total_size}

        snapshot = {'replication_strategy': self.repl_replication_strategy,
                    'dataset': {'dataset_size': dataset_size}}

        # entry point
        self.manager.attach_replica(self.context, snapshot, None)
        # assertions
        self.assertEqual(mock_replication.enable_as_slave.call_count, 1)

    def test_attach_replication_slave_invalid(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        total_size = 2.0
        dataset_size = 3.0

        mock_replication = MagicMock()
        mock_replication.enable_as_slave = MagicMock()
        self.mock_rs_class.return_value = mock_replication
        self.mock_gfvs_class.return_value = {'total': total_size}

        snapshot = {'replication_strategy': self.repl_replication_strategy,
                    'dataset': {'dataset_size': dataset_size}}

        # entry point
        self.assertRaises(InsufficientSpaceForReplica,
                          self.manager.attach_replica,
                          self.context, snapshot, None)
        # assertions
        self.assertEqual(mock_replication.enable_as_slave.call_count, 0)

    def test_detach_replica(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        mock_replication = MagicMock()
        mock_replication.detach_slave = MagicMock()
        self.mock_rs_class.return_value = mock_replication

        # entry point
        self.manager.detach_replica(self.context)
        # assertions
        self.assertEqual(mock_replication.detach_slave.call_count, 1)

    def test_demote_replication_master(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        mock_replication = MagicMock()
        mock_replication.demote_master = MagicMock()
        self.mock_rs_class.return_value = mock_replication

        # entry point
        self.manager.demote_replication_master(self.context)
        # assertions
        self.assertEqual(mock_replication.demote_master.call_count, 1)

    def test_get_master_UUID(self):
        app = dbaas.MySqlApp(None)

        def test_case(slave_status, expected_value):
            with patch.object(dbaas.MySqlApp, '_get_slave_status',
                              return_value=slave_status):
                assert_equal(app._get_master_UUID(), expected_value)

        test_case({'Master_UUID': '2a5b-2064-32fb'}, '2a5b-2064-32fb')
        test_case({'Master_UUID': ''}, None)
        test_case({}, None)

    def test_get_last_txn(self):

        def test_case(gtid_list, expected_value):
            with patch.object(dbaas.MySqlApp, '_get_gtid_executed',
                              return_value=gtid_list):
                txn = self.manager.get_last_txn(self.context)
                assert_equal(txn, expected_value)

        with patch.object(dbaas.MySqlApp, '_get_slave_status',
                          return_value={'Master_UUID': '2a5b-2064-32fb'}):
            test_case('2a5b-2064-32fb:1', ('2a5b-2064-32fb', 1))
            test_case('2a5b-2064-32fb:1-5', ('2a5b-2064-32fb', 5))
            test_case('2a5b-2064-32fb:1,4b4-23:5', ('2a5b-2064-32fb', 1))
            test_case('4b4-23:5,2a5b-2064-32fb:1', ('2a5b-2064-32fb', 1))
            test_case('4b-23:5,2a5b-2064-32fb:1,25:3-4', ('2a5b-2064-32fb', 1))
            test_case('4b4-23:1-5,2a5b-2064-32fb:1-10', ('2a5b-2064-32fb', 10))

        with patch.object(dbaas.MySqlApp, '_get_slave_status',
                          return_value={'Master_UUID': ''}):
            test_case('2a5b-2064-32fb:1', (None, 0))

        with patch.object(dbaas.MySqlApp, '_get_slave_status',
                          return_value={}):
            test_case('2a5b-2064-32fb:1', (None, 0))
Exemplo n.º 17
0
class GuestAgentManagerTest(testtools.TestCase):
    def setUp(self):
        super(GuestAgentManagerTest, self).setUp()
        self.context = TroveContext()
        self.manager = Manager()
        self.origin_MySqlAppStatus = dbaas.MySqlAppStatus
        self.origin_os_path_exists = os.path.exists
        self.origin_format = volume.VolumeDevice.format
        self.origin_migrate_data = volume.VolumeDevice.migrate_data
        self.origin_mount = volume.VolumeDevice.mount
        self.origin_is_installed = dbaas.MySqlApp.is_installed
        self.origin_stop_mysql = dbaas.MySqlApp.stop_db
        self.origin_start_mysql = dbaas.MySqlApp.start_mysql
        self.origin_install_mysql = dbaas.MySqlApp._install_mysql

    def tearDown(self):
        super(GuestAgentManagerTest, self).tearDown()
        dbaas.MySqlAppStatus = self.origin_MySqlAppStatus
        os.path.exists = self.origin_os_path_exists
        volume.VolumeDevice.format = self.origin_format
        volume.VolumeDevice.migrate_data = self.origin_migrate_data
        volume.VolumeDevice.mount = self.origin_mount
        dbaas.MySqlApp.is_installed = self.origin_is_installed
        dbaas.MySqlApp.stop_db = self.origin_stop_mysql
        dbaas.MySqlApp.start_mysql = self.origin_start_mysql
        dbaas.MySqlApp._install_mysql = self.origin_install_mysql
        unstub()

    def test_update_status(self):
        mock_status = mock()
        when(dbaas.MySqlAppStatus).get().thenReturn(mock_status)
        self.manager.update_status(self.context)
        verify(dbaas.MySqlAppStatus).get()
        verify(mock_status).update()

    def test_create_database(self):
        when(dbaas.MySqlAdmin).create_database(['db1']).thenReturn(None)
        self.manager.create_database(self.context, ['db1'])
        verify(dbaas.MySqlAdmin).create_database(['db1'])

    def test_create_user(self):
        when(dbaas.MySqlAdmin).create_user(['user1']).thenReturn(None)
        self.manager.create_user(self.context, ['user1'])
        verify(dbaas.MySqlAdmin).create_user(['user1'])

    def test_delete_database(self):
        databases = ['db1']
        when(dbaas.MySqlAdmin).delete_database(databases).thenReturn(None)
        self.manager.delete_database(self.context, databases)
        verify(dbaas.MySqlAdmin).delete_database(databases)

    def test_delete_user(self):
        user = ['user1']
        when(dbaas.MySqlAdmin).delete_user(user).thenReturn(None)
        self.manager.delete_user(self.context, user)
        verify(dbaas.MySqlAdmin).delete_user(user)

    def test_list_databases(self):
        when(dbaas.MySqlAdmin).list_databases(None, None,
                                              False).thenReturn(['database1'])
        databases = self.manager.list_databases(self.context)
        self.assertThat(databases, Not(Is(None)))
        self.assertThat(databases, Equals(['database1']))
        verify(dbaas.MySqlAdmin).list_databases(None, None, False)

    def test_list_users(self):
        when(dbaas.MySqlAdmin).list_users(None, None,
                                          False).thenReturn(['user1'])
        users = self.manager.list_users(self.context)
        self.assertThat(users, Equals(['user1']))
        verify(dbaas.MySqlAdmin).list_users(None, None, False)

    def test_enable_root(self):
        when(dbaas.MySqlAdmin).enable_root().thenReturn('user_id_stuff')
        user_id = self.manager.enable_root(self.context)
        self.assertThat(user_id, Is('user_id_stuff'))
        verify(dbaas.MySqlAdmin).enable_root()

    def test_is_root_enabled(self):
        when(dbaas.MySqlAdmin).is_root_enabled().thenReturn(True)
        is_enabled = self.manager.is_root_enabled(self.context)
        self.assertThat(is_enabled, Is(True))
        verify(dbaas.MySqlAdmin).is_root_enabled()

    def test_create_backup(self):
        when(backup).backup(self.context, 'backup_id_123').thenReturn(None)
        # entry point
        Manager().create_backup(self.context, 'backup_id_123')
        # assertions
        verify(backup).backup(self.context, 'backup_id_123')

    def test_prepare_device_path_true(self):
        self._prepare_dynamic()

    def test_prepare_device_path_false(self):
        self._prepare_dynamic(device_path=None)

    def test_prepare_mysql_not_installed(self):
        self._prepare_dynamic(is_mysql_installed=False)

    def test_prepare_mysql_from_backup(self):
        self._prepare_dynamic(backup_id='backup_id_123abc')

    def test_prepare_mysql_from_backup_with_root(self):
        self._prepare_dynamic(backup_id='backup_id_123abc',
                              is_root_enabled=True)

    def _prepare_dynamic(self,
                         device_path='/dev/vdb',
                         is_mysql_installed=True,
                         backup_id=None,
                         is_root_enabled=False):

        # covering all outcomes is starting to cause trouble here
        COUNT = 1 if device_path else 0
        SEC_COUNT = 1 if is_mysql_installed else 0
        migrate_count = 1 * COUNT if not backup_id else 0

        # TODO(juice): this should stub an instance of the MySqlAppStatus
        mock_status = mock()
        when(dbaas.MySqlAppStatus).get().thenReturn(mock_status)
        when(mock_status).begin_install().thenReturn(None)
        when(VolumeDevice).format().thenReturn(None)
        when(VolumeDevice).migrate_data(any()).thenReturn(None)
        when(VolumeDevice).mount().thenReturn(None)
        when(dbaas.MySqlApp).stop_db().thenReturn(None)
        when(dbaas.MySqlApp).start_mysql().thenReturn(None)
        when(dbaas.MySqlApp).install_if_needed().thenReturn(None)
        when(backup).restore(self.context, backup_id).thenReturn(None)
        when(dbaas.MySqlApp).secure(any()).thenReturn(None)
        when(dbaas.MySqlApp).secure_root(any()).thenReturn(None)
        when(dbaas.MySqlApp).is_installed().thenReturn(is_mysql_installed)
        when(dbaas.MySqlAdmin).is_root_enabled().thenReturn(is_root_enabled)
        when(dbaas.MySqlAdmin).create_user().thenReturn(None)
        when(dbaas.MySqlAdmin).create_database().thenReturn(None)
        when(dbaas.MySqlAdmin).report_root_enabled(
            self.context).thenReturn(None)

        when(os.path).exists(any()).thenReturn(is_mysql_installed)
        # invocation
        self.manager.prepare(context=self.context,
                             databases=None,
                             memory_mb='2048',
                             users=None,
                             device_path=device_path,
                             mount_point='/var/lib/mysql',
                             backup_id=backup_id)
        # verification/assertion
        verify(mock_status).begin_install()

        verify(VolumeDevice, times=COUNT).format()
        verify(dbaas.MySqlApp, times=(COUNT * SEC_COUNT)).stop_db()
        verify(VolumeDevice,
               times=(migrate_count * SEC_COUNT)).migrate_data(any())
        if backup_id:
            verify(backup).restore(self.context, backup_id, '/var/lib/mysql')
        verify(dbaas.MySqlApp).install_if_needed()
        # We dont need to make sure the exact contents are there
        verify(dbaas.MySqlApp).secure(any())
        verify(dbaas.MySqlAdmin, never).create_database()
        verify(dbaas.MySqlAdmin, never).create_user()
        times_report = 1 if is_root_enabled else 0
        verify(dbaas.MySqlApp).secure_root(secure_remote_root=any())
        verify(dbaas.MySqlAdmin,
               times=times_report).report_root_enabled(self.context)
Exemplo n.º 18
0
class GuestAgentManagerTest(testtools.TestCase):
    def setUp(self):
        super(GuestAgentManagerTest, self).setUp()
        self.context = TroveContext()
        self.manager = Manager()
        self.origin_MySqlAppStatus = dbaas.MySqlAppStatus
        self.origin_os_path_exists = os.path.exists
        self.origin_format = volume.VolumeDevice.format
        self.origin_migrate_data = volume.VolumeDevice.migrate_data
        self.origin_mount = volume.VolumeDevice.mount
        self.origin_unmount = volume.VolumeDevice.unmount
        self.origin_mount_points = volume.VolumeDevice.mount_points
        self.origin_stop_mysql = dbaas.MySqlApp.stop_db
        self.origin_start_mysql = dbaas.MySqlApp.start_mysql
        self.origin_pkg_is_installed = pkg.Package.pkg_is_installed
        self.origin_os_path_exists = os.path.exists
        # set up common mock objects, etc. for replication testing
        self.patcher_gfvs = patch(
            'trove.guestagent.dbaas.get_filesystem_volume_stats')
        self.patcher_rs = patch('trove.guestagent.datastore.mysql.manager.'
                                'REPLICATION_STRATEGY_CLASS')
        self.mock_gfvs_class = self.patcher_gfvs.start()
        self.mock_rs_class = self.patcher_rs.start()
        self.repl_datastore_manager = 'mysql'
        self.repl_replication_strategy = 'MysqlGTIDReplication'

    def tearDown(self):
        super(GuestAgentManagerTest, self).tearDown()
        dbaas.MySqlAppStatus = self.origin_MySqlAppStatus
        os.path.exists = self.origin_os_path_exists
        volume.VolumeDevice.format = self.origin_format
        volume.VolumeDevice.migrate_data = self.origin_migrate_data
        volume.VolumeDevice.mount = self.origin_mount
        volume.VolumeDevice.unmount = self.origin_unmount
        volume.VolumeDevice.mount_points = self.origin_mount_points
        dbaas.MySqlApp.stop_db = self.origin_stop_mysql
        dbaas.MySqlApp.start_mysql = self.origin_start_mysql
        pkg.Package.pkg_is_installed = self.origin_pkg_is_installed
        os.path.exists = self.origin_os_path_exists
        # teardown the replication mock objects
        self.patcher_gfvs.stop()
        self.patcher_rs.stop()

    def test_update_status(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        self.manager.update_status(self.context)
        dbaas.MySqlAppStatus.get.assert_any_call()
        mock_status.update.assert_any_call()

    def test_create_database(self):
        dbaas.MySqlAdmin.create_database = MagicMock(return_value=None)
        self.manager.create_database(self.context, ['db1'])
        dbaas.MySqlAdmin.create_database.assert_any_call(['db1'])

    def test_create_user(self):
        dbaas.MySqlAdmin.create_user = MagicMock(return_value=None)
        self.manager.create_user(self.context, ['user1'])
        dbaas.MySqlAdmin.create_user.assert_any_call(['user1'])

    def test_delete_database(self):
        databases = ['db1']
        dbaas.MySqlAdmin.delete_database = MagicMock(return_value=None)
        self.manager.delete_database(self.context, databases)
        dbaas.MySqlAdmin.delete_database.assert_any_call(databases)

    def test_delete_user(self):
        user = ['user1']
        dbaas.MySqlAdmin.delete_user = MagicMock(return_value=None)
        self.manager.delete_user(self.context, user)
        dbaas.MySqlAdmin.delete_user.assert_any_call(user)

    def test_grant_access(self):
        username = "******"
        hostname = "test_host"
        databases = ["test_database"]
        dbaas.MySqlAdmin.grant_access = MagicMock(return_value=None)
        self.manager.grant_access(self.context, username, hostname, databases)

        dbaas.MySqlAdmin.grant_access.assert_any_call(username, hostname,
                                                      databases)

    def test_list_databases(self):
        dbaas.MySqlAdmin.list_databases = MagicMock(return_value=['database1'])
        databases = self.manager.list_databases(self.context)
        self.assertThat(databases, Not(Is(None)))
        self.assertThat(databases, Equals(['database1']))
        dbaas.MySqlAdmin.list_databases.assert_any_call(None, None, False)

    def test_list_users(self):
        dbaas.MySqlAdmin.list_users = MagicMock(return_value=['user1'])
        users = self.manager.list_users(self.context)
        self.assertThat(users, Equals(['user1']))
        dbaas.MySqlAdmin.list_users.assert_any_call(None, None, False)

    def test_get_users(self):
        username = ['user1']
        hostname = ['host']
        dbaas.MySqlAdmin.get_user = MagicMock(return_value=['user1'])
        users = self.manager.get_user(self.context, username, hostname)
        self.assertThat(users, Equals(['user1']))
        dbaas.MySqlAdmin.get_user.assert_any_call(username, hostname)

    def test_enable_root(self):
        dbaas.MySqlAdmin.enable_root = MagicMock(return_value='user_id_stuff')
        user_id = self.manager.enable_root(self.context)
        self.assertThat(user_id, Is('user_id_stuff'))
        dbaas.MySqlAdmin.enable_root.assert_any_call()

    def test_is_root_enabled(self):
        dbaas.MySqlAdmin.is_root_enabled = MagicMock(return_value=True)
        is_enabled = self.manager.is_root_enabled(self.context)
        self.assertThat(is_enabled, Is(True))
        dbaas.MySqlAdmin.is_root_enabled.assert_any_call()

    def test_create_backup(self):
        backup.backup = MagicMock(return_value=None)
        # entry point
        Manager().create_backup(self.context, 'backup_id_123')
        # assertions
        backup.backup.assert_any_call(self.context, 'backup_id_123')

    def test_prepare_device_path_true(self):
        self._prepare_dynamic()

    def test_prepare_device_path_false(self):
        self._prepare_dynamic(device_path=None)

    def test_prepare_device_path_mounted(self):
        self._prepare_dynamic(is_mounted=True)

    def test_prepare_mysql_not_installed(self):
        self._prepare_dynamic(is_mysql_installed=False)

    def test_prepare_mysql_from_backup(self):
        self._prepare_dynamic(backup_id='backup_id_123abc')

    def test_prepare_mysql_from_backup_with_root(self):
        self._prepare_dynamic(backup_id='backup_id_123abc',
                              is_root_enabled=True)

    def _prepare_dynamic(self,
                         device_path='/dev/vdb',
                         is_mysql_installed=True,
                         backup_id=None,
                         is_root_enabled=False,
                         overrides=None,
                         is_mounted=False):
        # covering all outcomes is starting to cause trouble here
        COUNT = 1 if device_path else 0
        backup_info = None
        if backup_id is not None:
            backup_info = {
                'id': backup_id,
                'location': 'fake-location',
                'type': 'InnoBackupEx',
                'checksum': 'fake-checksum',
            }

        # TODO(juice): this should stub an instance of the MySqlAppStatus
        mock_status = MagicMock()

        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)
        mock_status.begin_install = MagicMock(return_value=None)
        VolumeDevice.format = MagicMock(return_value=None)
        VolumeDevice.migrate_data = MagicMock(return_value=None)
        VolumeDevice.mount = MagicMock(return_value=None)
        mount_points = []
        if is_mounted:
            mount_points = ['/mnt']
        VolumeDevice.mount_points = MagicMock(return_value=mount_points)
        VolumeDevice.unmount = MagicMock(return_value=None)
        dbaas.MySqlApp.stop_db = MagicMock(return_value=None)
        dbaas.MySqlApp.start_mysql = MagicMock(return_value=None)
        dbaas.MySqlApp.install_if_needed = MagicMock(return_value=None)
        backup.restore = MagicMock(return_value=None)
        dbaas.MySqlApp.secure = MagicMock(return_value=None)
        dbaas.MySqlApp.secure_root = MagicMock(return_value=None)
        pkg.Package.pkg_is_installed = MagicMock(
            return_value=is_mysql_installed)
        dbaas.MySqlAdmin.is_root_enabled = MagicMock(
            return_value=is_root_enabled)
        dbaas.MySqlAdmin.create_user = MagicMock(return_value=None)
        dbaas.MySqlAdmin.create_database = MagicMock(return_value=None)

        os.path.exists = MagicMock(return_value=True)
        # invocation
        self.manager.prepare(context=self.context,
                             packages=None,
                             memory_mb='2048',
                             databases=None,
                             users=None,
                             device_path=device_path,
                             mount_point='/var/lib/mysql',
                             backup_info=backup_info,
                             overrides=overrides,
                             cluster_config=None)

        # verification/assertion
        mock_status.begin_install.assert_any_call()

        self.assertEqual(VolumeDevice.format.call_count, COUNT)
        self.assertEqual(VolumeDevice.migrate_data.call_count, COUNT)
        self.assertEqual(VolumeDevice.mount_points.call_count, COUNT)
        self.assertEqual(dbaas.MySqlApp.stop_db.call_count, COUNT)
        if is_mounted:
            self.assertEqual(VolumeDevice.unmount.call_count, 1)
        else:
            self.assertEqual(VolumeDevice.unmount.call_count, 0)
        if backup_info:
            backup.restore.assert_any_call(self.context, backup_info,
                                           '/var/lib/mysql')
        dbaas.MySqlApp.install_if_needed.assert_any_call(None)
        # We don't need to make sure the exact contents are there
        dbaas.MySqlApp.secure.assert_any_call(None, None)
        self.assertFalse(dbaas.MySqlAdmin.create_database.called)
        self.assertFalse(dbaas.MySqlAdmin.create_user.called)
        dbaas.MySqlApp.secure_root.assert_any_call(
            secure_remote_root=not is_root_enabled)

    def test_get_replication_snapshot(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        snapshot_id = 'my_snapshot_id'
        log_position = 123456789
        master_ref = 'my_master'
        used_size = 1.0
        total_size = 2.0

        mock_replication = MagicMock()
        mock_replication.enable_as_master = MagicMock()
        mock_replication.snapshot_for_replication = MagicMock(
            return_value=(snapshot_id, log_position))
        mock_replication.get_master_ref = MagicMock(return_value=master_ref)
        self.mock_rs_class.return_value = mock_replication
        self.mock_gfvs_class.return_value = ({
            'used': used_size,
            'total': total_size
        })

        expected_replication_snapshot = {
            'dataset': {
                'datastore_manager': self.repl_datastore_manager,
                'dataset_size': used_size,
                'volume_size': total_size,
                'snapshot_id': snapshot_id
            },
            'replication_strategy': self.repl_replication_strategy,
            'master': master_ref,
            'log_position': log_position
        }

        snapshot_info = None
        replica_source_config = None
        # entry point
        replication_snapshot = (self.manager.get_replication_snapshot(
            self.context, snapshot_info, replica_source_config))
        # assertions
        self.assertEqual(expected_replication_snapshot, replication_snapshot)
        self.assertEqual(mock_replication.enable_as_master.call_count, 1)
        self.assertEqual(mock_replication.snapshot_for_replication.call_count,
                         1)
        self.assertEqual(mock_replication.get_master_ref.call_count, 1)

    def test_attach_replication_slave_valid(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        total_size = 2.0
        dataset_size = 1.0

        mock_replication = MagicMock()
        mock_replication.enable_as_slave = MagicMock()
        self.mock_rs_class.return_value = mock_replication
        self.mock_gfvs_class.return_value = {'total': total_size}

        snapshot = {
            'replication_strategy': self.repl_replication_strategy,
            'dataset': {
                'dataset_size': dataset_size
            }
        }

        # entry point
        self.manager.attach_replica(self.context, snapshot, None)
        # assertions
        self.assertEqual(mock_replication.enable_as_slave.call_count, 1)

    def test_attach_replication_slave_invalid(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        total_size = 2.0
        dataset_size = 3.0

        mock_replication = MagicMock()
        mock_replication.enable_as_slave = MagicMock()
        self.mock_rs_class.return_value = mock_replication
        self.mock_gfvs_class.return_value = {'total': total_size}

        snapshot = {
            'replication_strategy': self.repl_replication_strategy,
            'dataset': {
                'dataset_size': dataset_size
            }
        }

        # entry point
        self.assertRaises(InsufficientSpaceForReplica,
                          self.manager.attach_replica, self.context, snapshot,
                          None)
        # assertions
        self.assertEqual(mock_replication.enable_as_slave.call_count, 0)

    def test_detach_replica(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        mock_replication = MagicMock()
        mock_replication.detach_slave = MagicMock()
        self.mock_rs_class.return_value = mock_replication

        # entry point
        self.manager.detach_replica(self.context)
        # assertions
        self.assertEqual(mock_replication.detach_slave.call_count, 1)

    def test_demote_replication_master(self):
        mock_status = MagicMock()
        dbaas.MySqlAppStatus.get = MagicMock(return_value=mock_status)

        mock_replication = MagicMock()
        mock_replication.demote_master = MagicMock()
        self.mock_rs_class.return_value = mock_replication

        # entry point
        self.manager.demote_replication_master(self.context)
        # assertions
        self.assertEqual(mock_replication.demote_master.call_count, 1)

    def test_get_master_UUID(self):
        app = dbaas.MySqlApp(None)

        def test_case(slave_status, expected_value):
            with patch.object(dbaas.MySqlApp,
                              '_get_slave_status',
                              return_value=slave_status):
                assert_equal(app._get_master_UUID(), expected_value)

        test_case({'Master_UUID': '2a5b-2064-32fb'}, '2a5b-2064-32fb')
        test_case({'Master_UUID': ''}, None)
        test_case({}, None)

    def test_get_last_txn(self):
        def test_case(gtid_list, expected_value):
            with patch.object(dbaas.MySqlApp,
                              '_get_gtid_executed',
                              return_value=gtid_list):
                txn = self.manager.get_last_txn(self.context)
                assert_equal(txn, expected_value)

        with patch.object(dbaas.MySqlApp,
                          '_get_slave_status',
                          return_value={'Master_UUID': '2a5b-2064-32fb'}):
            test_case('2a5b-2064-32fb:1', ('2a5b-2064-32fb', 1))
            test_case('2a5b-2064-32fb:1-5', ('2a5b-2064-32fb', 5))
            test_case('2a5b-2064-32fb:1,4b4-23:5', ('2a5b-2064-32fb', 1))
            test_case('4b4-23:5,2a5b-2064-32fb:1', ('2a5b-2064-32fb', 1))
            test_case('4b-23:5,2a5b-2064-32fb:1,25:3-4', ('2a5b-2064-32fb', 1))
            test_case('4b4-23:1-5,2a5b-2064-32fb:1-10', ('2a5b-2064-32fb', 10))

        with patch.object(dbaas.MySqlApp,
                          '_get_slave_status',
                          return_value={'Master_UUID': ''}):
            test_case('2a5b-2064-32fb:1', (None, 0))

        with patch.object(dbaas.MySqlApp, '_get_slave_status',
                          return_value={}):
            test_case('2a5b-2064-32fb:1', (None, 0))