def create_user(self, users): LOG.debug("Creating user(s) for accessing DB2 database(s).") try: for item in users: user = models.MySQLUser() user.deserialize(item) try: LOG.debug("Creating OS user: %s." % user.name) utils.execute_with_timeout( system.CREATE_USER_COMMAND % { 'login': user.name, 'login': user.name, 'passwd': user.password}, shell=True) except exception.ProcessExecutionError as pe: LOG.exception(_("Error creating user: %s.") % user.name) continue for database in user.databases: mydb = models.ValidatedMySQLDatabase() mydb.deserialize(database) try: LOG.debug("Granting user: %s access to database: %s." % (user.name, mydb.name)) run_command(system.GRANT_USER_ACCESS % { 'dbname': mydb.name, 'login': user.name}) except exception.ProcessExecutionError as pe: LOG.debug( "Error granting user: %s access to database: %s." % (user.name, mydb.name)) LOG.debug(pe) pass except exception.ProcessExecutionError as pe: LOG.exception(_("An error occured creating users: %s.") % pe.message) pass
def create_user(self, users): """Create users and grant them privileges for the specified databases. """ with self.local_sql_client(self.mysql_app.get_engine()) as client: for item in users: user = models.MySQLUser() user.deserialize(item) # TODO(cp16net):Should users be allowed to create users # 'os_admin' or 'debian-sys-maint' g = sql_query.Grant(user=user.name, host=user.host, clear=user.password) t = text(str(g)) client.execute(t) for database in user.databases: mydb = models.ValidatedMySQLDatabase() mydb.deserialize(database) g = sql_query.Grant(permissions='ALL', database=mydb.name, user=user.name, host=user.host, clear=user.password) t = text(str(g)) client.execute(t)
def delete_database(self, database): """Delete the specified database.""" with LocalSqlClient(get_engine()) as client: mydb = models.ValidatedMySQLDatabase() mydb.deserialize(database) dd = sql_query.DropDatabase(mydb.name) t = text(str(dd)) client.execute(t)
def do_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): """This is called from prepare in the base class.""" if device_path: device = volume.VolumeDevice(device_path) device.unmount_device(device_path) device.format() device.mount(mount_point) operating_system.chown(mount_point, service.OracleVMApp.instance_owner, service.OracleVMApp.instance_owner_group, recursive=False, as_root=True) LOG.debug('Mounted the volume.') if snapshot: self.attach_replica(context, snapshot, snapshot['config']) else: if backup_info: self._perform_restore(backup_info, context, mount_point, self.app) else: self.app.configure_listener() if databases: # only create 1 database database = databases[:1] else: # using ValidatedMySQLDatabase here for to simulate the # object that would normally be passed in via --databases, # and to bookmark this for when per-datastore validation is # added db = models.ValidatedMySQLDatabase() # no database name provided so default to first 8 valid # characters of instance name (alphanumeric, no '_') db.name = re.sub(r'[\W_]', '', CONF.guest_name[:8]) database = [db.serialize()] self.admin.create_database(database) self.app.set_db_start_flag_in_oratab() self.refresh_guest_log_defs() self.app.prep_pfile_management() if root_password: self.admin.enable_root(root_password)
def create_database(self, databases): """Create the list of specified databases.""" with self.local_sql_client(self.mysql_app.get_engine()) as client: for item in databases: mydb = models.ValidatedMySQLDatabase() mydb.deserialize(item) cd = sql_query.CreateDatabase(mydb.name, mydb.character_set, mydb.collate) t = text(str(cd)) client.execute(t)
def delete(self, req, tenant_id, instance_id, id): LOG.info(_("Deleting schema for instance '%s'") % instance_id) LOG.info(_("req : '%s'\n\n") % req) context = req.environ[wsgi.CONTEXT_KEY] try: schema = guest_models.ValidatedMySQLDatabase() schema.name = id models.Schema.delete(context, instance_id, schema.serialize()) except (ValueError, AttributeError) as e: raise exception.BadRequest(msg=str(e)) return wsgi.Result(None, 202)
def test_prepare(self): CONF.guest_name = 'testdb' schema = models.ValidatedMySQLDatabase() schema.name = 'testdb' with mock.patch.multiple(self.manager, admin=DEFAULT, app=DEFAULT, refresh_guest_log_defs=DEFAULT): self.manager.do_prepare(self.context, None, None, None, None) self.manager.refresh_guest_log_defs.assert_any_call() self.manager.app.prep_pfile_management.assert_any_call() self.manager.admin.create_database.assert_called_with( [schema.serialize()])
def delete_database(self, database): """Delete the specified database.""" dbName = None try: mydb = models.ValidatedMySQLDatabase() mydb.deserialize(database) dbName = mydb.name LOG.debug("Deleting DB2 database: %s." % dbName) run_command(system.DELETE_DB_COMMAND % {'dbname': dbName}) except exception.ProcessExecutionError: LOG.exception( _("There was an error while deleting database:%s.") % dbName) raise exception.GuestError( _("Unable to delete database: %s.") % dbName)
def do_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): """This is called from prepare in the base class.""" if device_path: device = volume.VolumeDevice(device_path) device.unmount_device(device_path) device.format() device.mount(mount_point) LOG.debug('Mounted the volume.') self.app.change_ownership(mount_point) if snapshot: self.attach_replica(context, snapshot, snapshot['config']) else: if backup_info: self._perform_restore(backup_info, context, mount_point, self.app) else: # using ValidatedMySQLDatabase here for to simulate the object # that would normally be passed in via --databases, and to bookmark # this for when per-datastore validation is added db = models.ValidatedMySQLDatabase() db.name = CONF.guest_name self.admin.create_database([db.serialize()]) self.refresh_guest_log_defs() self.app.prep_pfile_management() if users: self.create_user(context, users) if root_password: self.admin.enable_root(root_password)
def grant_access(self, username, hostname, databases): """Grant a user permission to use a given database.""" user = self._get_user(username, hostname) mydb = models.ValidatedMySQLDatabase() with LocalSqlClient(get_engine()) as client: for database in databases: try: mydb.name = database except ValueError: raise exception.BadRequest(_( "Grant access to %s is not allowed") % database) g = sql_query.Grant(permissions='ALL', database=mydb.name, user=user.name, host=user.host, hashed=user.password) t = text(str(g)) client.execute(t)
def delete(self, req, tenant_id, instance_id, id): LOG.info( _("Deleting schema for instance '%(id)s'\n" "req : '%(req)s'\n\n") % { "id": instance_id, "req": req }) context = req.environ[wsgi.CONTEXT_KEY] context.notification = notification.DBaaSDatabaseDelete(context, request=req) with StartNotification(context, instance_id=instance_id, dbname=id): try: schema = guest_models.ValidatedMySQLDatabase() schema.name = id models.Schema.delete(context, instance_id, schema.serialize()) except (ValueError, AttributeError) as e: raise exception.BadRequest(msg=str(e)) return wsgi.Result(None, 202)
def populate_validated_databases(dbs): """ Create a serializable request with user provided data for creating new databases. """ try: databases = [] for database in dbs: mydb = guest_models.ValidatedMySQLDatabase() mydb.name = database.get('name', '') mydb.character_set = database.get('character_set', '') mydb.collate = database.get('collate', '') databases.append(mydb.serialize()) return databases except ValueError as ve: # str(ve) contains user input and may include '%' which can cause a # format str vulnerability. Escape the '%' to avoid this. This is # okay to do since we're not using dict args here in any case. safe_string = str(ve).replace('%', '%%') raise exception.BadRequest(safe_string)
def create_database(self, databases): """Create the given database(s).""" dbName = None db_create_failed = [] LOG.debug("Creating DB2 databases.") for item in databases: mydb = models.ValidatedMySQLDatabase() mydb.deserialize(item) dbName = mydb.name LOG.debug("Creating DB2 database: %s." % dbName) try: run_command(system.CREATE_DB_COMMAND % {'dbname': dbName}) except exception.ProcessExecutionError: LOG.exception(_( "There was an error creating database: %s.") % dbName) db_create_failed.append(dbName) pass if len(db_create_failed) > 0: LOG.exception(_("Creating the following databases failed: %s.") % db_create_failed)
def create_database(self, databases): """Create the given database(s).""" dbName = None db_create_failed = [] LOG.debug("Creating DB2 databases.") for item in databases: mydb = models.ValidatedMySQLDatabase() mydb.deserialize(item) dbName = mydb.name LOG.debug("Creating DB2 database: %s." % dbName) try: run_command(system.CREATE_DB_COMMAND % {'dbname': dbName}) except exception.ProcessExecutionError: LOG.exception( _("There was an error creating database: %s.") % dbName) db_create_failed.append(dbName) pass ''' Configure each database to do archive logging for online backups. Once the database is configured, it will go in to a BACKUP PENDING state. In this state, the database will not be accessible for any operations. To get the database back to normal mode, we have to do a full offline backup as soon as we configure it for archive logging. ''' try: if CONF.db2.backup_strategy == 'DB2OnlineBackup': run_command(system.UPDATE_DB_LOG_CONFIGURATION % {'dbname': dbName}) run_command(system.RECOVER_FROM_BACKUP_PENDING_MODE % {'dbname': dbName}) except exception.ProcessExecutionError: LOG.exception( _("There was an error while configuring the database for " "online backup: %s.") % dbName) if len(db_create_failed) > 0: LOG.exception( _("Creating the following databases failed: %s.") % db_create_failed)
def delete_user(self, user): LOG.debug("Delete a given user.") db2_user = models.MySQLUser() db2_user.deserialize(user) userName = db2_user.name user_dbs = db2_user.databases LOG.debug("For user %s, databases to be deleted = %r." % (userName, user_dbs)) if len(user_dbs) == 0: databases = self.list_access(db2_user.name, None) else: databases = user_dbs LOG.debug("databases for user = %r." % databases) for database in databases: mydb = models.ValidatedMySQLDatabase() mydb.deserialize(database) try: run_command(system.REVOKE_USER_ACCESS % { 'dbname': mydb.name, 'login': userName }) LOG.debug("Revoked access for user:%s on database:%s." % (userName, mydb.name)) except exception.ProcessExecutionError as pe: LOG.debug("Error occurred while revoking access to %s." % mydb.name) pass try: utils.execute_with_timeout(system.DELETE_USER_COMMAND % {'login': db2_user.name.lower()}, shell=True) except exception.ProcessExecutionError as pe: LOG.exception( _("There was an error while deleting user: %s.") % pe) raise exception.GuestError( original_message=_("Unable to delete user: %s.") % userName)
def test_prepare_create_database(self): self.manager.refresh_guest_log_defs = mock.MagicMock() create_db_mock = mock.MagicMock() self.manager.admin.create_database = create_db_mock def check_test(test_tag, db_name): self.assertEqual(db_name, create_db_mock.call_args[0][0][0]['_name'], message="Test %s failed") create_db_mock.reset_mock() self.manager.do_prepare(None, None, None, None, None) check_test('short_instance_name', self.test_instance_name) self.patch_conf_property('guest_name', 'ora1toolong') self.manager.do_prepare(None, None, None, None, None) check_test('long_instance_name', 'ora1tool') test_db_name = 'testdb' database = models.ValidatedMySQLDatabase() database.name = test_db_name self.manager.do_prepare(None, None, [database.serialize()], None, None) check_test('given_db_name', test_db_name)
def setUp(self): super(MySQLDatabaseTest, self).setUp() self.mysqlDb = dbmodels.ValidatedMySQLDatabase() self.origin_ignore_db = self.mysqlDb._ignore_dbs self.mysqlDb._ignore_dbs = ['mysql']