Пример #1
0
    def enable_root(self, root_password=None):
        """Enable the root user global access and/or
           reset the root password.
        """
        user = models.MySQLUser.root(password=root_password)
        with mysql_util.SqlClient(self.mysql_app.get_engine()) as client:
            try:
                cu = sql_query.CreateUser(user.name, host=user.host)
                t = text(str(cu))
                client.execute(t, **cu.keyArgs)
            except (exc.OperationalError, exc.InternalError) as err:
                # Ignore, user is already created, just reset the password
                # TODO(rnirmal): More fine grained error checking later on
                LOG.debug(err)
        with mysql_util.SqlClient(self.mysql_app.get_engine()) as client:
            uu = sql_query.SetPassword(
                user.name, host=user.host, new_password=user.password,
                ds=CONF.datastore_manager, ds_version=CONF.datastore_version
            )
            t = text(str(uu))
            client.execute(t)

            LOG.debug("CONF.root_grant: %(grant)s CONF.root_grant_option: "
                      "%(grant_option)s.",
                      {'grant': CONF.root_grant,
                       'grant_option': CONF.root_grant_option})

            g = sql_query.Grant(permissions=CONF.root_grant,
                                user=user.name,
                                host=user.host,
                                grant_option=CONF.root_grant_option)

            t = text(str(g))
            client.execute(t)
            return user.serialize()
Пример #2
0
    def update_attributes(self, username, hostname, user_attrs):
        """Change the attributes of an existing user."""
        LOG.debug("Changing user attributes for user %s.", username)
        user = self._get_user(username, hostname)

        new_name = user_attrs.get('name')
        new_host = user_attrs.get('host')
        new_password = user_attrs.get('password')

        if new_name or new_host or new_password:
            with mysql_util.SqlClient(self.mysql_app.get_engine(),
                                      use_flush=True) as client:
                if new_password is not None:
                    uu = sql_query.SetPassword(
                        user.name,
                        host=user.host,
                        new_password=new_password,
                        ds=CONF.datastore_manager,
                        ds_version=CONF.datastore_version)
                    t = text(str(uu))
                    client.execute(t)

                if new_name or new_host:
                    uu = sql_query.RenameUser(user.name,
                                              host=user.host,
                                              new_user=new_name,
                                              new_host=new_host)
                    t = text(str(uu))
                    client.execute(t)
Пример #3
0
    def create_users(self, users):
        """Create users and grant them privileges for the
           specified databases.
        """
        with mysql_util.SqlClient(self.mysql_app.get_engine(),
                                  use_flush=True) as client:
            for item in users:
                user = models.MySQLUser.deserialize(item)
                user.check_create()

                cu = sql_query.CreateUser(user.name,
                                          host=user.host,
                                          clear=user.password)
                t = text(str(cu))
                client.execute(t, **cu.keyArgs)

                for database in user.databases:
                    mydb = models.MySQLSchema.deserialize(database)
                    g = sql_query.Grant(permissions='ALL',
                                        database=mydb.name,
                                        user=user.name,
                                        host=user.host)
                    t = text(str(g))
                    LOG.debug('Creating user, command: %s', str(g))
                    client.execute(t)
Пример #4
0
 def is_root_enabled(self):
     """Return True if root access is enabled; False otherwise."""
     with mysql_util.SqlClient(self.mysql_app.get_engine()) as client:
         t = text(sql_query.ROOT_ENABLED)
         result = client.execute(t)
         LOG.debug("Found %s with remote root access.", result.rowcount)
         return result.rowcount != 0
Пример #5
0
 def delete_user_by_name(self, name, host='%'):
     with mysql_util.SqlClient(self.mysql_app.get_engine(),
                               use_flush=True) as client:
         du = sql_query.DropUser(name, host=host)
         t = text(str(du))
         LOG.debug("delete_user_by_name: %s", t)
         client.execute(t)
Пример #6
0
    def grant_access(self, username, hostname, databases):
        """Grant a user permission to use a given database."""
        user = self._get_user(username, hostname)
        mydb = None  # cache the model as we just want name validation
        with mysql_util.SqlClient(self.mysql_app.get_engine(),
                                  use_flush=True) as client:
            for database in databases:
                try:
                    if mydb:
                        mydb.name = database
                    else:
                        mydb = models.MySQLSchema(name=database)
                        mydb.check_reserved()
                except ValueError:
                    LOG.exception("Error granting access")
                    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)
Пример #7
0
 def _get_user(self, username, hostname):
     """Return a single user matching the criteria."""
     user = None
     try:
         # Could possibly throw a ValueError here.
         user = models.MySQLUser(name=username)
         user.check_reserved()
     except ValueError as ve:
         LOG.exception("Error Getting user information")
         err_msg = encodeutils.exception_to_unicode(ve)
         raise exception.BadRequest(
             _("Username %(user)s is not valid"
               ": %(reason)s") % {
                   'user': username,
                   'reason': err_msg
               })
     with mysql_util.SqlClient(self.mysql_app.get_engine()) as client:
         q = sql_query.Query()
         q.columns = ['User', 'Host']
         q.tables = ['mysql.user']
         q.where = [
             "Host != 'localhost'",
             "User = '******'" % username,
             "Host = '%s'" % hostname
         ]
         q.order = ['User', 'Host']
         t = text(str(q))
         result = client.execute(t).fetchall()
         LOG.debug("Getting user information %s.", result)
         if len(result) != 1:
             return None
         found_user = result[0]
         user.host = found_user['Host']
         self._associate_dbs(user)
         return user
Пример #8
0
 def delete_database(self, database):
     """Delete the specified database."""
     with mysql_util.SqlClient(self.mysql_app.get_engine()) as client:
         mydb = models.MySQLSchema.deserialize(database)
         mydb.check_delete()
         dd = sql_query.DropDatabase(mydb.name)
         t = text(str(dd))
         client.execute(t)
Пример #9
0
 def revoke_access(self, username, hostname, database):
     """Revoke a user's permission to use a given database."""
     user = self._get_user(username, hostname)
     with mysql_util.SqlClient(self.mysql_app.get_engine()) as client:
         r = sql_query.Revoke(database=database,
                              user=user.name,
                              host=user.host)
         t = text(str(r))
         client.execute(t)
Пример #10
0
    def get_service_status(self):
        try:
            with mysql_util.SqlClient(self.app.get_engine()) as client:
                cmd = "SELECT 1;"
                client.execute(cmd)

            LOG.debug("Database service check: database query is responsive")
            return service_status.ServiceStatuses.HEALTHY
        except Exception:
            return super(MySqlManager, self).get_service_status()
Пример #11
0
    def secure(self):
        LOG.info("Securing MySQL now.")

        root_pass = self.get_auth_password(file="root.cnf")
        admin_password = utils.generate_random_password()

        engine = sqlalchemy.create_engine(
            CONNECTION_STR_FORMAT % ('root', root_pass), echo=True)
        with mysql_util.SqlClient(engine, use_flush=False) as client:
            self._create_admin_user(client, admin_password)

        engine = sqlalchemy.create_engine(
            CONNECTION_STR_FORMAT % (ADMIN_USER_NAME,
                                     urllib.parse.quote(admin_password)),
            echo=True)
        with mysql_util.SqlClient(engine) as client:
            self._remove_anonymous_user(client)

        self.save_password(ADMIN_USER_NAME, admin_password)
        LOG.info("MySQL secure complete.")
Пример #12
0
    def grant_replication_privilege(self, replication_user):
        LOG.info("Granting replication slave privilege for %s",
                 replication_user['name'])

        with mysql_util.SqlClient(self.get_engine(), use_flush=True) as client:
            g = sql_query.Grant(permissions=['REPLICATION SLAVE'],
                                user=replication_user['name'],
                                clear=replication_user['password'])

            t = text(str(g))
            client.execute(t)
Пример #13
0
 def create_databases(self, databases):
     """Create the list of specified databases."""
     with mysql_util.SqlClient(self.mysql_app.get_engine()) as client:
         for item in databases:
             mydb = models.MySQLSchema.deserialize(item)
             mydb.check_create()
             cd = sql_query.CreateDatabase(mydb.name, mydb.character_set,
                                           mydb.collate)
             t = text(str(cd))
             LOG.debug('Creating database, command: %s', str(cd))
             client.execute(t)
Пример #14
0
 def apply_overrides(self, overrides):
     with mysql_util.SqlClient(self.get_engine()) as client:
         for k, v in overrides.items():
             byte_value = guestagent_utils.to_bytes(v)
             q = sql_query.SetServerVariable(key=k, value=byte_value)
             t = text(str(q))
             try:
                 client.execute(t)
             except exc.OperationalError:
                 output = {'key': k, 'value': byte_value}
                 LOG.error("Unable to set %(key)s with value %(value)s.",
                           output)
Пример #15
0
    def stop_slave(self, for_failover):
        LOG.info("Stopping slave replication.")

        replication_user = None
        with mysql_util.SqlClient(self.get_engine()) as client:
            result = client.execute('SHOW SLAVE STATUS')
            replication_user = result.first()['Master_User']
            client.execute('STOP SLAVE')
            client.execute('RESET SLAVE ALL')
            self.wait_for_slave_status('OFF', client, 180)
            if not for_failover:
                client.execute('DROP USER IF EXISTS ' + replication_user)

        return {'replication_user': replication_user}
Пример #16
0
 def _associate_dbs(self, user):
     """Internal. Given a MySQLUser, populate its databases attribute."""
     LOG.debug("Associating dbs to user %(name)s at %(host)s.",
               {'name': user.name, 'host': user.host})
     with mysql_util.SqlClient(self.mysql_app.get_engine()) as client:
         q = sql_query.Query()
         q.columns = ["grantee", "table_schema"]
         q.tables = ["information_schema.SCHEMA_PRIVILEGES"]
         q.group = ["grantee", "table_schema"]
         q.where = ["privilege_type != 'USAGE'"]
         t = text(str(q))
         db_result = client.execute(t)
         for db in db_result:
             LOG.debug("\t db: %s.", db)
             if db['grantee'] == "'%s'@'%s'" % (user.name, user.host):
                 user.databases = db['table_schema']
Пример #17
0
 def change_passwords(self, users):
     """Change the passwords of one or more existing users."""
     LOG.debug("Changing the password of some users.")
     with mysql_util.SqlClient(self.mysql_app.get_engine()) as client:
         for item in users:
             LOG.debug("Changing password for user %s.", item)
             user_dict = {'_name': item['name'],
                          '_host': item['host'],
                          '_password': item['password']}
             user = models.MySQLUser.deserialize(user_dict)
             uu = sql_query.SetPassword(user.name, host=user.host,
                                        new_password=user.password,
                                        ds=CONF.datastore_manager,
                                        ds_version=CONF.datastore_version)
             t = text(str(uu))
             client.execute(t)
Пример #18
0
    def list_databases(self, limit=None, marker=None, include_marker=False):
        """List databases on this mysql instance."""
        LOG.info("Listing Databases")
        ignored_database_names = "'%s'" % "', '".join(cfg.get_ignored_dbs())
        LOG.debug(
            "The following database names are on ignore list and will "
            "be omitted from the listing: %s", ignored_database_names)
        databases = []
        with mysql_util.SqlClient(self.mysql_app.get_engine()) as client:
            # If you have an external volume mounted at /var/lib/mysql
            # the lost+found directory will show up in mysql as a database
            # which will create errors if you try to do any database ops
            # on it.  So we remove it here if it exists.
            q = sql_query.Query()
            q.columns = [
                'schema_name as name',
                'default_character_set_name as charset',
                'default_collation_name as collation',
            ]
            q.tables = ['information_schema.schemata']
            q.where = ["schema_name NOT IN (" + ignored_database_names + ")"]
            q.order = ['schema_name ASC']
            if limit:
                q.limit = limit + 1
            if marker:
                q.where.append(
                    "schema_name %s '%s'" %
                    (INCLUDE_MARKER_OPERATORS[include_marker], marker))
            t = text(str(q))
            database_names = client.execute(t)
            next_marker = None
            for count, database in enumerate(database_names):
                if limit is not None and count >= limit:
                    break
                mysql_db = models.MySQLSchema(name=database[0],
                                              character_set=database[1],
                                              collate=database[2])
                next_marker = mysql_db.name
                databases.append(mysql_db.serialize())

        LOG.info("databases = %s", str(databases))
        if limit is not None and database_names.rowcount <= limit:
            next_marker = None
        return databases, next_marker
Пример #19
0
 def _get_gtid_executed(self):
     with mysql_util.SqlClient(self.get_engine()) as client:
         return client.execute('SELECT @@global.gtid_binlog_pos').first()[0]
Пример #20
0
 def wait_for_txn(self, txn):
     cmd = "SELECT MASTER_GTID_WAIT('%s')" % txn
     with mysql_util.SqlClient(self.get_engine()) as client:
         client.execute(cmd)
Пример #21
0
 def wait_for_txn(self, txn):
     with mysql_util.SqlClient(self.get_engine()) as client:
         client.execute("SELECT WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS('%s')" %
                        txn)
Пример #22
0
 def _get_slave_status(self):
     with mysql_util.SqlClient(self.get_engine()) as client:
         return client.execute('SHOW SLAVE STATUS').first()
Пример #23
0
 def stop_master(self):
     LOG.info("Stopping replication master.")
     with mysql_util.SqlClient(self.get_engine()) as client:
         client.execute('RESET MASTER')
Пример #24
0
 def make_read_only(self, read_only):
     with mysql_util.SqlClient(self.get_engine()) as client:
         q = "set global read_only = %s" % read_only
         client.execute(text(str(q)))
Пример #25
0
    def list_users(self, limit=None, marker=None, include_marker=False):
        """List users that have access to the database."""
        '''
        SELECT
            User,
            Host,
            Marker
        FROM
            (SELECT
                User,
                Host,
                CONCAT(User, '@', Host) as Marker
            FROM mysql.user
            ORDER BY 1, 2) as innerquery
        WHERE
            Marker > :marker
        ORDER BY
            Marker
        LIMIT :limit;
        '''
        LOG.info("Listing Users")
        ignored_user_names = "'%s'" % "', '".join(cfg.get_ignored_users())
        LOG.debug(
            "The following user names are on ignore list and will "
            "be omitted from the listing: %s", ignored_user_names)
        users = []
        with mysql_util.SqlClient(self.mysql_app.get_engine(),
                                  use_flush=True) as client:
            iq = sql_query.Query()  # Inner query.
            iq.columns = ['User', 'Host', "CONCAT(User, '@', Host) as Marker"]
            iq.tables = ['mysql.user']
            iq.order = ['User', 'Host']
            innerquery = str(iq).rstrip(';')

            oq = sql_query.Query()  # Outer query.
            oq.columns = ['User', 'Host', 'Marker']
            oq.tables = ['(%s) as innerquery' % innerquery]
            oq.where = [
                "Host != 'localhost'",
                "User NOT IN (" + ignored_user_names + ")"
            ]
            oq.order = ['Marker']
            if marker:
                oq.where.append(
                    "Marker %s '%s'" %
                    (INCLUDE_MARKER_OPERATORS[include_marker], marker))
            if limit:
                oq.limit = limit + 1
            t = text(str(oq))
            result = client.execute(t)
            next_marker = None
            for count, row in enumerate(result):
                if limit is not None and count >= limit:
                    break
                LOG.debug("user = %s", str(row))
                mysql_user = models.MySQLUser(name=row['User'],
                                              host=row['Host'])
                mysql_user.check_reserved()
                self._associate_dbs(mysql_user)
                next_marker = row['Marker']
                users.append(mysql_user.serialize())
        if limit is not None and result.rowcount <= limit:
            next_marker = None
        LOG.info("users = %s", str(users))

        return users, next_marker
Пример #26
0
 def start_slave(self):
     LOG.info("Starting slave replication.")
     with mysql_util.SqlClient(self.get_engine()) as client:
         client.execute('START SLAVE')
         self.wait_for_slave_status("ON", client, 180)
Пример #27
0
 def get_port(self):
     with mysql_util.SqlClient(self.get_engine()) as client:
         result = client.execute('SELECT @@port').first()
         return result[0]
Пример #28
0
 def execute_sql(self, sql_statement, use_flush=False):
     LOG.debug("Executing SQL: %s", sql_statement)
     with mysql_util.SqlClient(self.get_engine(),
                               use_flush=use_flush) as client:
         return client.execute(sql_statement)
Пример #29
0
 def secure_root(self):
     with mysql_util.SqlClient(self.get_engine(), use_flush=True) as client:
         self._remove_remote_root_access(client)