def prepare(self, context, packages, databases, memory_mb, users, device_path=None, mount_point=None, backup_info=None, config_contents=None, root_password=None, overrides=None, cluster_config=None, snapshot=None): """Makes ready DBAAS on a Guest container.""" MySqlAppStatus.get().begin_install() # status end_mysql_install set with secure() app = MySqlApp(MySqlAppStatus.get()) app.install_if_needed(packages) if device_path: #stop and do not update database app.stop_db() device = volume.VolumeDevice(device_path) # unmount if device is already mounted device.unmount_device(device_path) device.format() if os.path.exists(mount_point): #rsync exiting data device.migrate_data(mount_point) #mount the volume device.mount(mount_point) LOG.debug("Mounted the volume.") app.start_mysql() if backup_info: self._perform_restore(backup_info, context, mount_point, app) LOG.debug("Securing MySQL now.") app.secure(config_contents, overrides) enable_root_on_restore = (backup_info and MySqlAdmin().is_root_enabled()) if root_password and not backup_info: app.secure_root(secure_remote_root=True) MySqlAdmin().enable_root(root_password) elif enable_root_on_restore: app.secure_root(secure_remote_root=False) MySqlAppStatus.get().report_root('root') else: app.secure_root(secure_remote_root=True) app.complete_install_or_restart() if databases: self.create_database(context, databases) if users: self.create_user(context, users) if snapshot: self.attach_replica(context, snapshot, snapshot['config']) LOG.info(_('Completed setup of MySQL database instance.'))
def prepare(self, context, databases, memory_mb, users, device_path=None, mount_point=None, backup_id=None, config_contents=None, root_password=None): """Makes ready DBAAS on a Guest container.""" MySqlAppStatus.get().begin_install() # status end_mysql_install set with secure() app = MySqlApp(MySqlAppStatus.get()) restart_mysql = False if device_path: device = volume.VolumeDevice(device_path) device.format() #if a /var/lib/mysql folder exists, back it up. if os.path.exists(CONF.mount_point): #stop and do not update database app.stop_db() #rsync exiting data if not backup_id: restart_mysql = True device.migrate_data(CONF.mount_point) #mount the volume device.mount(mount_point) LOG.debug(_("Mounted the volume.")) #check mysql was installed and stopped if restart_mysql: app.start_mysql() app.install_if_needed() if backup_id: self._perform_restore(backup_id, context, CONF.mount_point, app) LOG.info(_("Securing mysql now.")) app.secure(config_contents) enable_root_on_restore = (backup_id and MySqlAdmin().is_root_enabled()) if root_password and not backup_id: app.secure_root(secure_remote_root=True) MySqlAdmin().enable_root(root_password) MySqlAdmin().report_root_enabled(context) elif enable_root_on_restore: app.secure_root(secure_remote_root=False) MySqlAdmin().report_root_enabled(context) else: app.secure_root(secure_remote_root=True) app.complete_install_or_restart() if databases: self.create_database(context, databases) if users: self.create_user(context, users) LOG.info('"prepare" call has finished.')
def _create_replication_user(self): replication_user = None replication_password = utils.generate_random_password(16) mysql_user = None # cache the model as we just want name validation retry_count = 0 while replication_user is None: try: name = 'slave_' + str(uuid.uuid4())[:8] if mysql_user: mysql_user.name = name else: mysql_user = models.MySQLUser( name=name, password=replication_password ) mysql_user.check_create() MySqlAdmin().create_user([mysql_user.serialize()]) LOG.debug("Trying to create replication user " + mysql_user.name) replication_user = { 'name': mysql_user.name, 'password': replication_password } except Exception: retry_count += 1 if retry_count > 5: LOG.error("Replication user retry count exceeded") raise return replication_user
def _create_replication_user(self): replication_user = None replication_password = utils.generate_random_password(16) mysql_user = models.MySQLUser() mysql_user.password = replication_password retry_count = 0 while replication_user is None: try: mysql_user.name = 'slave_' + str(uuid.uuid4())[:8] MySqlAdmin().create_user([mysql_user.serialize()]) LOG.debug("Trying to create replication user " + mysql_user.name) replication_user = { 'name': mysql_user.name, 'password': replication_password } except Exception: retry_count += 1 if retry_count > 5: LOG.error(_("Replication user retry count exceeded")) raise return replication_user
def setUp(self): super(MySqlAdminTest, self).setUp() self.orig_get_engine = dbaas.get_engine self.orig_LocalSqlClient = dbaas.LocalSqlClient self.orig_LocalSqlClient_enter = dbaas.LocalSqlClient.__enter__ self.orig_LocalSqlClient_exit = dbaas.LocalSqlClient.__exit__ self.orig_LocalSqlClient_execute = dbaas.LocalSqlClient.execute self.orig_MySQLUser_is_valid_user_name = ( models.MySQLUser._is_valid_user_name) dbaas.get_engine = MagicMock(name='get_engine') dbaas.LocalSqlClient = Mock dbaas.LocalSqlClient.__enter__ = Mock() dbaas.LocalSqlClient.__exit__ = Mock() dbaas.LocalSqlClient.execute = Mock() self.mySqlAdmin = MySqlAdmin()
def test_list_databases(self): mock_conn = mock_admin_sql_connection() when(mock_conn).execute( TextClauseMatcher('schema_name as name')).thenReturn( ResultSetStub([('db1', 'utf8', 'utf8_bin'), ('db2', 'utf8', 'utf8_bin'), ('db3', 'utf8', 'utf8_bin')])) databases, next_marker = MySqlAdmin().list_databases(limit=10) self.assertThat(next_marker, Is(None)) self.assertThat(len(databases), Is(3))
def revoke_access(self, context, username, hostname, database): return MySqlAdmin().revoke_access(username, hostname, database)
def grant_access(self, context, username, hostname, databases): return MySqlAdmin().grant_access(username, hostname, databases)
def get_user(self, context, username, hostname): return MySqlAdmin().get_user(username, hostname)
def delete_user(self, context, user): MySqlAdmin().delete_user(user)
def delete_database(self, context, database): return MySqlAdmin().delete_database(database)
def test_enable_root_failed(self): when(models.MySQLUser)._is_valid_user_name(any()).thenReturn(False) self.assertRaises(ValueError, MySqlAdmin().enable_root)
def change_passwords(self, context, users): return MySqlAdmin().change_passwords(users)
def cleanup_source_on_replica_detach(self, context, replica_info): LOG.debug("Cleaning up the source on the detach of a replica.") replication = REPLICATION_STRATEGY_CLASS(context) replication.cleanup_source_on_replica_detach(MySqlAdmin(), replica_info)
def prepare(self, context, packages, databases, memory_mb, users, device_path=None, mount_point=None, backup_info=None, config_contents=None, root_password=None, overrides=None, cluster_config=None, snapshot=None): """Makes ready DBAAS on a Guest container.""" MySqlAppStatus.get().begin_install() # status end_mysql_install set with secure() app = MySqlApp(MySqlAppStatus.get()) app.install_if_needed(packages) if device_path: # stop and do not update database app.stop_db() device = volume.VolumeDevice(device_path) # unmount if device is already mounted device.unmount_device(device_path) device.format() if os.path.exists(mount_point): # rsync existing data to a "data" sub-directory # on the new volume device.migrate_data(mount_point, target_subdir="data") # mount the volume device.mount(mount_point) operating_system.chown(mount_point, 'mysql', 'mysql', recursive=False, as_root=True) LOG.debug("Mounted the volume at %s." % mount_point) # We need to temporarily update the default my.cnf so that # mysql will start after the volume is mounted. Later on it # will be changed based on the config template and restart. app.update_overrides("[mysqld]\ndatadir=%s/data\n" % mount_point) app.start_mysql() if backup_info: self._perform_restore(backup_info, context, mount_point + "/data", app) LOG.debug("Securing MySQL now.") app.secure(config_contents, overrides) enable_root_on_restore = (backup_info and MySqlAdmin().is_root_enabled()) if root_password and not backup_info: app.secure_root(secure_remote_root=True) MySqlAdmin().enable_root(root_password) elif enable_root_on_restore: app.secure_root(secure_remote_root=False) MySqlAppStatus.get().report_root(context, 'root') else: app.secure_root(secure_remote_root=True) app.complete_install_or_restart() if databases: self.create_database(context, databases) if users: self.create_user(context, users) if snapshot: self.attach_replica(context, snapshot, snapshot['config']) LOG.info(_('Completed setup of MySQL database instance.'))
def is_root_enabled(self, context): return MySqlAdmin().is_root_enabled()
def enable_root(self, context): return MySqlAdmin().enable_root()
class MySqlAdminTest(testtools.TestCase): def setUp(self): super(MySqlAdminTest, self).setUp() self.orig_get_engine = dbaas.get_engine self.orig_LocalSqlClient = dbaas.LocalSqlClient self.orig_LocalSqlClient_enter = dbaas.LocalSqlClient.__enter__ self.orig_LocalSqlClient_exit = dbaas.LocalSqlClient.__exit__ self.orig_LocalSqlClient_execute = dbaas.LocalSqlClient.execute self.orig_MySQLUser_is_valid_user_name = ( models.MySQLUser._is_valid_user_name) dbaas.get_engine = MagicMock(name='get_engine') dbaas.LocalSqlClient = Mock dbaas.LocalSqlClient.__enter__ = Mock() dbaas.LocalSqlClient.__exit__ = Mock() dbaas.LocalSqlClient.execute = Mock() self.mySqlAdmin = MySqlAdmin() def tearDown(self): super(MySqlAdminTest, self).tearDown() dbaas.get_engine = self.orig_get_engine dbaas.LocalSqlClient = self.orig_LocalSqlClient dbaas.LocalSqlClient.__enter__ = self.orig_LocalSqlClient_enter dbaas.LocalSqlClient.__exit__ = self.orig_LocalSqlClient_exit dbaas.LocalSqlClient.execute = self.orig_LocalSqlClient_execute models.MySQLUser._is_valid_user_name = ( self.orig_MySQLUser_is_valid_user_name) def test_create_database(self): databases = [] databases.append(FAKE_DB) self.mySqlAdmin.create_database(databases) args, _ = dbaas.LocalSqlClient.execute.call_args_list[0] expected = ("CREATE DATABASE IF NOT EXISTS " "`testDB` CHARACTER SET = 'latin2' " "COLLATE = 'latin2_general_ci';") self.assertEqual(args[0].text, expected, "Create database queries are not the same") self.assertEqual(1, dbaas.LocalSqlClient.execute.call_count, "The client object was not 2 times") def test_create_database_more_than_1(self): databases = [] databases.append(FAKE_DB) databases.append(FAKE_DB_2) self.mySqlAdmin.create_database(databases) args, _ = dbaas.LocalSqlClient.execute.call_args_list[0] expected = ("CREATE DATABASE IF NOT EXISTS " "`testDB` CHARACTER SET = 'latin2' " "COLLATE = 'latin2_general_ci';") self.assertEqual(args[0].text, expected, "Create database queries are not the same") args, _ = dbaas.LocalSqlClient.execute.call_args_list[1] expected = ("CREATE DATABASE IF NOT EXISTS " "`testDB2` CHARACTER SET = 'latin2' " "COLLATE = 'latin2_general_ci';") self.assertEqual(args[0].text, expected, "Create database queries are not the same") self.assertEqual(2, dbaas.LocalSqlClient.execute.call_count, "The client object was not 2 times") def test_create_database_no_db(self): databases = [] self.mySqlAdmin.create_database(databases) self.assertFalse(dbaas.LocalSqlClient.execute.called, "The client object was called when it wasn't " + "supposed to") def test_delete_database(self): database = {"_name": "testDB"} self.mySqlAdmin.delete_database(database) args, _ = dbaas.LocalSqlClient.execute.call_args expected = "DROP DATABASE `testDB`;" self.assertEqual(args[0].text, expected, "Delete database queries are not the same") self.assertTrue(dbaas.LocalSqlClient.execute.called, "The client object was not called") def test_delete_user(self): user = {"_name": "testUser"} self.mySqlAdmin.delete_user(user) # For some reason, call_args is None. call_args = dbaas.LocalSqlClient.execute.call_args if call_args is not None: args, _ = call_args expected = "DROP USER `testUser`;" self.assertEqual(args[0].text, expected, "Delete user queries are not the same") self.assertTrue(dbaas.LocalSqlClient.execute.called, "The client object was not called") def test_create_user(self): self.mySqlAdmin.create_user(FAKE_USER) expected = ("GRANT ALL PRIVILEGES ON `testDB`.* TO `random`@`%` " "IDENTIFIED BY 'guesswhat' " "WITH GRANT OPTION;") # For some reason, call_args is None. call_args = dbaas.LocalSqlClient.execute.call_args if call_args is not None: args, _ = call_args self.assertEqual(args[0].text.strip(), expected, "Create user queries are not the same") self.assertEqual(2, dbaas.LocalSqlClient.execute.call_count) def test_list_databases(self): self.mySqlAdmin.list_databases() args, _ = dbaas.LocalSqlClient.execute.call_args expected = ["SELECT schema_name as name,", "default_character_set_name as charset,", "default_collation_name as collation", "FROM information_schema.schemata", ("schema_name NOT IN (" "'mysql', 'information_schema', " "'lost+found', '#mysql50#lost+found'" ")"), "ORDER BY schema_name ASC", ] for text in expected: self.assertTrue(text in args[0].text, "%s not in query." % text) self.assertFalse("LIMIT " in args[0].text) def test_list_databases_with_limit(self): limit = 2 self.mySqlAdmin.list_databases(limit) args, _ = dbaas.LocalSqlClient.execute.call_args expected = ["SELECT schema_name as name,", "default_character_set_name as charset,", "default_collation_name as collation", "FROM information_schema.schemata", ("schema_name NOT IN (" "'mysql', 'information_schema', " "'lost+found', '#mysql50#lost+found'" ")"), "ORDER BY schema_name ASC", ] for text in expected: self.assertTrue(text in args[0].text, "%s not in query." % text) self.assertTrue("LIMIT " + str(limit + 1) in args[0].text) def test_list_databases_with_marker(self): marker = "aMarker" self.mySqlAdmin.list_databases(marker=marker) args, _ = dbaas.LocalSqlClient.execute.call_args expected = ["SELECT schema_name as name,", "default_character_set_name as charset,", "default_collation_name as collation", "FROM information_schema.schemata", ("schema_name NOT IN (" "'mysql', 'information_schema', " "'lost+found', '#mysql50#lost+found'" ")"), "ORDER BY schema_name ASC", ] for text in expected: self.assertTrue(text in args[0].text, "%s not in query." % text) self.assertFalse("LIMIT " in args[0].text) self.assertTrue("AND schema_name > '" + marker + "'" in args[0].text) def test_list_databases_with_include_marker(self): marker = "aMarker" self.mySqlAdmin.list_databases(marker=marker, include_marker=True) args, _ = dbaas.LocalSqlClient.execute.call_args expected = ["SELECT schema_name as name,", "default_character_set_name as charset,", "default_collation_name as collation", "FROM information_schema.schemata", ("schema_name NOT IN (" "'mysql', 'information_schema', " "'lost+found', '#mysql50#lost+found'" ")"), "ORDER BY schema_name ASC", ] for text in expected: self.assertTrue(text in args[0].text, "%s not in query." % text) self.assertFalse("LIMIT " in args[0].text) self.assertTrue(("AND schema_name >= '%s'" % marker) in args[0].text) def test_list_users(self): self.mySqlAdmin.list_users() args, _ = dbaas.LocalSqlClient.execute.call_args expected = ["SELECT User, Host", "FROM mysql.user", "WHERE Host != 'localhost'", "ORDER BY User", ] for text in expected: self.assertTrue(text in args[0].text, "%s not in query." % text) self.assertFalse("LIMIT " in args[0].text) self.assertFalse("AND Marker > '" in args[0].text) def test_list_users_with_limit(self): limit = 2 self.mySqlAdmin.list_users(limit) args, _ = dbaas.LocalSqlClient.execute.call_args expected = ["SELECT User, Host", "FROM mysql.user", "WHERE Host != 'localhost'", "ORDER BY User", ("LIMIT " + str(limit + 1)), ] for text in expected: self.assertTrue(text in args[0].text, "%s not in query." % text) def test_list_users_with_marker(self): marker = "aMarker" self.mySqlAdmin.list_users(marker=marker) args, _ = dbaas.LocalSqlClient.execute.call_args expected = ["SELECT User, Host, Marker", "FROM mysql.user", "WHERE Host != 'localhost'", "ORDER BY User", ] for text in expected: self.assertTrue(text in args[0].text, "%s not in query." % text) self.assertFalse("LIMIT " in args[0].text) self.assertTrue("AND Marker > '" + marker + "'" in args[0].text) def test_list_users_with_include_marker(self): marker = "aMarker" self.mySqlAdmin.list_users(marker=marker, include_marker=True) args, _ = dbaas.LocalSqlClient.execute.call_args expected = ["SELECT User, Host", "FROM mysql.user", "WHERE Host != 'localhost'", "ORDER BY User", ] for text in expected: self.assertTrue(text in args[0].text, "%s not in query." % text) self.assertFalse("LIMIT " in args[0].text) self.assertTrue("AND Marker >= '" + marker + "'" in args[0].text)
def list_access(self, context, username, hostname): return MySqlAdmin().list_access(username, hostname)
def list_users(self, context, limit=None, marker=None, include_marker=False): return MySqlAdmin().list_users(limit, marker, include_marker)
def create_database(self, context, databases): return MySqlAdmin().create_database(databases)
def update_attributes(self, context, username, hostname, user_attrs): return MySqlAdmin().update_attributes(username, hostname, user_attrs)
def create_user(self, context, users): MySqlAdmin().create_user(users)