Charmed MySQL

  • By Canonical Data Platform
  • Cloud
Channel Revision Published Runs on
8.0/stable 196 29 Sep 2023
Ubuntu 22.04
8.0/candidate 203 14 Dec 2023
Ubuntu 22.04
8.0/beta 216 18 Mar 2024
Ubuntu 22.04
8.0/edge 222 16 Apr 2024
Ubuntu 22.04
juju deploy mysql --channel 8.0/stable
Show information

Platform:

Ubuntu
22.04

charms.mysql.v0.mysql

MySQL helper class and functions.

The mysql module provides an abstraction class and methods for for managing a Group Replication enabled MySQL cluster.

The MySQLBase abstract class must be inherited and have its abstract methods implemented for each platform (vm/k8s) before being directly used in charm code.

An example of inheriting MySQLBase and implementing the abstract methods plus extending it:

from charms.mysql.v0.mysql import MySQLBase
from tenacity import retry, stop_after_delay, wait_fixed

class MySQL(MySQLBase):
    def __init__(
        self,
        instance_address: str,
        cluster_name: str,
        root_password: str,
        server_config_user: str,
        server_config_password: str,
        cluster_admin_user: str,
        cluster_admin_password: str,
        new_parameter: str
    ):
        super().__init__(
                instance_address=instance_address,
                cluster_name=cluster_name,
                root_password=root_password,
                server_config_user=server_config_user,
                server_config_password=server_config_password,
                cluster_admin_user=cluster_admin_user,
                cluster_admin_password=cluster_admin_password,
            )
        # Add new attribute
        self.new_parameter = new_parameter

    # abstract method implementation
    @retry(reraise=True, stop=stop_after_delay(30), wait=wait_fixed(5))
    def wait_until_mysql_connection(self) -> None:
        if not os.path.exists(MYSQLD_SOCK_FILE):
            raise MySQLServiceNotRunningError()

    ...

The module also provides a set of custom exceptions, used to trigger specific error handling on the subclass and in the charm code.


Index

class Error

Description

Base class for exceptions in this module. None

Methods

Error. __init__( self , message: str )

Initialize the Error class.

Arguments

message

Optional message to pass to the exception.

Error. __repr__( self )

Description

String representation of the Error class. None

Error. name( self )

Description

Return a string representation of the model plus class. None

class MySQLConfigureMySQLUsersError

Description

Exception raised when creating a user fails. None

class MySQLCheckUserExistenceError

Description

Exception raised when checking for the existence of a MySQL user. None

class MySQLConfigureRouterUserError

Description

Exception raised when configuring the MySQLRouter user. None

class MySQLCreateApplicationDatabaseAndScopedUserError

Description

Exception raised when creating application database and scoped user. None

class MySQLGetRouterUsersError

Description

Exception raised when there is an issue getting MySQL Router users. None

class MySQLDeleteUsersForUnitError

Description

Exception raised when there is an issue deleting users for a unit. None

class MySQLDeleteUsersForRelationError

Description

Exception raised when there is an issue deleting users for a relation. None

class MySQLDeleteUserError

Description

Exception raised when there is an issue deleting a user. None

class MySQLRemoveRouterFromMetadataError

Description

Exception raised when there is an issue removing MySQL Router from cluster metadata. None

class MySQLConfigureInstanceError

Description

Exception raised when there is an issue configuring a MySQL instance. None

class MySQLCreateClusterError

Description

Exception raised when there is an issue creating an InnoDB cluster. None

class MySQLCreateClusterSetError

Description

Exception raised when there is an issue creating an Cluster Set. None

class MySQLAddInstanceToClusterError

Description

Exception raised when there is an issue add an instance to the MySQL InnoDB cluster. None

class MySQLRemoveInstanceRetryError

Exception raised when there is an issue removing an instance.

Description

Utilized by tenacity to retry the method.

class MySQLRemoveInstanceError

Exception raised when there is an issue removing an instance.

Description

Exempt from the retry mechanism provided by tenacity.

class MySQLInitializeJujuOperationsTableError

Description

Exception raised when there is an issue initializing the juju units operations table. None

class MySQLClientError

Exception raised when there is an issue using the mysql cli or mysqlsh.

Description

Abstract platform specific exceptions for external commands execution Errors.

class MySQLGetClusterMembersAddressesError

Description

Exception raised when there is an issue getting the cluster members addresses. None

class MySQLGetMySQLVersionError

Description

Exception raised when there is an issue getting the MySQL version. None

class MySQLGetClusterPrimaryAddressError

Description

Exception raised when there is an issue getting the primary instance. None

class MySQLSetClusterPrimaryError

Description

Exception raised when there is an issue setting the primary instance. None

class MySQLGrantPrivilegesToUserError

Description

Exception raised when there is an issue granting privileges to user. None

class MySQLGetMemberStateError

Description

Exception raised when there is an issue getting member state. None

class MySQLGetClusterEndpointsError

Description

Exception raised when there is an issue getting cluster endpoints. None

class MySQLRebootFromCompleteOutageError

Description

Exception raised when there is an issue rebooting from complete outage. None

class MySQLSetInstanceOfflineModeError

Description

Exception raised when there is an issue setting instance as offline. None

class MySQLSetInstanceOptionError

Description

Exception raised when there is an issue setting instance option. None

class MySQLOfflineModeAndHiddenInstanceExistsError

Exception raised when there is an error checking if an instance is backing up.

Description

We check if an instance is in offline_mode and hidden from mysql-router to determine this.

class MySQLGetAutoTunningParametersError

Description

Exception raised when there is an error computing the innodb buffer pool parameters. None

class MySQLExecuteBackupCommandsError

Exception raised when there is an error executing the backup commands.

Description

The backup commands are executed in the workload container using the pebble API.

class MySQLDeleteTempBackupDirectoryError

Description

Exception raised when there is an error deleting the temp backup directory. None

class MySQLRetrieveBackupWithXBCloudError

Description

Exception raised when there is an error retrieving a backup from S3 with xbcloud. None

class MySQLPrepareBackupForRestoreError

Description

Exception raised when there is an error preparing a backup for restore. None

class MySQLEmptyDataDirectoryError

Description

Exception raised when there is an error emptying the mysql data directory. None

class MySQLRestoreBackupError

Description

Exception raised when there is an error restoring a backup. None

class MySQLDeleteTempRestoreDirectoryError

Description

Exception raised when there is an error deleting the temp restore directory. None

class MySQLExecError

Description

Exception raised when there is an error executing commands on the mysql server. None

class MySQLStopMySQLDError

Description

Exception raised when there is an error stopping the MySQLD process. None

class MySQLStartMySQLDError

Description

Exception raised when there is an error starting the MySQLD process. None

class MySQLServiceNotRunningError

Description

Exception raised when the MySQL service is not running. None

class MySQLTLSSetupError

Description

Exception raised when there is an issue setting custom TLS config. None

class MySQLKillSessionError

Description

Exception raised when there is an issue killing a connection. None

class MySQLLockAcquisitionError

Description

Exception raised when a lock fails to be acquired. None

class MySQLRescanClusterError

Description

Exception raised when there is an issue rescanning the cluster. None

class MySQLSetVariableError

Description

Exception raised when there is an issue setting a variable. None

class MySQLServerNotUpgradableError

Description

Exception raised when there is an issue checking for upgradeability. None

class MySQLSecretError

Description

Exception raised when there is an issue setting/getting a secret. None

class MySQLGetAvailableMemoryError

Description

Exception raised when there is an issue getting the available memory. None

class RouterUser

Description

MySQL Router user. None

class MySQLCharmBase

Base class to encapsulate charm related functionality.

Description

Meant as a means to share common charm related code between the MySQL VM and K8s charms.

Methods

MySQLCharmBase. __init__( self )

MySQLCharmBase. get_unit_hostname( self )

Description

Return unit hostname. None

MySQLCharmBase. peers( self )

Description

Retrieve the peer relation. None

MySQLCharmBase. cluster_initialized( self )

Description

Returns True if the cluster is initialized. None

MySQLCharmBase. unit_initialized( self )

Description

Return True if the unit is initialized. None

MySQLCharmBase. app_peer_data( self )

Description

Application peer relation data object. None

MySQLCharmBase. unit_peer_data( self )

Description

Unit peer relation data object. None

MySQLCharmBase. app_units( self )

Description

The peer-related units in the application. None

MySQLCharmBase. unit_label( self )

Description

Return unit label. None

MySQLCharmBase. has_cos_relation( self )

Description

Returns a bool indicating whether a relation with COS is present. None

MySQLCharmBase. peer_relation_data( self , scope: Scopes )

Description

Returns the peer relation data per scope. None

MySQLCharmBase. get_secret( self , scope: Scopes , key: str )

Get secret from the secret storage.

Description

Retrieve secret from juju secrets backend if secret exists there. Else retrieve from peer databag. This is to account for cases where secrets are stored in peer databag but the charm is then refreshed to a newer revision.

MySQLCharmBase. set_secret( self , scope: Scopes , key: str , value )

Description

Set a secret in the secret storage. None

MySQLCharmBase. remove_secret( self , scope: Scopes , key: str )

Description

Removing a secret. None

class MySQLMemberState

Description

MySQL Cluster member state. None

class MySQLTextLogs

Description

MySQL Text logs. None

class MySQLBase

Abstract class to encapsulate all operations related to the MySQL workload.

Description

This class handles the configuration of MySQL instances, and also the creation and configuration of MySQL InnoDB clusters via Group Replication. Some methods are platform specific and must be implemented in the related charm code.

Methods

MySQLBase. __init__( self , instance_address: str , cluster_name: str , cluster_set_name: str , root_password: str , server_config_user: str , server_config_password: str , cluster_admin_user: str , cluster_admin_password: str , monitoring_user: str , monitoring_password: str , backups_user: str , backups_password: str )

Initialize the MySQL class.

Arguments

instance_address

address of the targeted instance

cluster_name

cluster name

cluster_set_name

cluster set domain name

root_password

password for the 'root' user

server_config_user

user name for the server config user

server_config_password

password for the server config user

cluster_admin_user

user name for the cluster admin user

cluster_admin_password

password for the cluster admin user

monitoring_user

user name for the mysql exporter

monitoring_password

password for the monitoring user

backups_user

user name used to create backups

backups_password

password for the backups user

MySQLBase. render_mysqld_configuration( self )

Render mysqld ini configuration file.

Arguments

profile

profile to use for the configuration (testing, production)

memory_limit

memory limit to use for the configuration in bytes

snap_common

snap common directory (for log files locations in vm)

MySQLBase. configure_mysql_users( self )

Configure the MySQL users for the instance.

Description

Create <server_config>@% user with the appropriate privileges, and reconfigure root@localhost user password.

Raises MySQLConfigureMySQLUsersError if the user creation fails.

MySQLBase. does_mysql_user_exist( self , username: str , hostname: str )

Checks if a mysqlrouter user already exists.

Arguments

username

The username for the mysql user

hostname

The hostname for the mysql user

Returns

A boolean indicating whether the provided mysql user exists

MySQLBase. configure_mysqlrouter_user( self , username: str , password: str , hostname: str , unit_name: str )

Configure a mysqlrouter user and grant the appropriate permissions to the user.

Arguments

username

The username for the mysqlrouter user

password

The password for the mysqlrouter user

hostname

The hostname for the mysqlrouter user

unit_name

The name of unit from which the mysqlrouter user will be accessed

MySQLBase. create_application_database_and_scoped_user( self , database_name: str , username: str , password: str , hostname: str )

Create an application database and a user scoped to the created database.

Arguments

database_name

The name of the database to create

username

The username of the scoped user

password

The password of the scoped user

hostname

The hostname of the scoped user

unit_name

The name of the unit from which the user will be accessed

create_database

Whether to create database

MySQLBase. get_mysql_router_users_for_unit( self )

Get users for related MySQL Router unit.

Description

For each user, get username & router ID attribute.

MySQLBase. delete_users_for_unit( self , unit_name: str )

Delete users for a unit.

Description

Args: unit_name: The name of the unit for which to delete mysql users for

Raises: MySQLDeleteUsersForUnitError if there is an error deleting users for the unit

MySQLBase. delete_users_for_relation( self , relation_id: int )

Delete users for a relation.

Description

Args: relation_id: The id of the relation for which to delete mysql users for

Raises: MySQLDeleteUsersForRelationError if there is an error deleting users for the relation

MySQLBase. delete_user( self , username: str )

Description

Delete user. None

MySQLBase. remove_router_from_cluster_metadata( self , router_id: str )

Description

Remove MySQL Router from InnoDB Cluster metadata. None

MySQLBase. set_dynamic_variable( self , variable: str , value: str , persist: bool , instance_address )

Set a dynamic variable value for the instance.

Description

Args: variable: The name of the variable to set value: The value to set the variable to persist: Whether to persist the variable value across restarts instance_address: instance address to set the variable, default to current

Raises: MySQLSetVariableError

MySQLBase. configure_instance( self , create_cluster_admin: bool )

Configure the instance to be used in an InnoDB cluster.

Description

Raises MySQLConfigureInstanceError if the was an error configuring the instance for use in an InnoDB cluster.

MySQLBase. create_cluster( self , unit_label: str )

Create an InnoDB cluster with Group Replication enabled.

Description

Raises MySQLCreateClusterError if there was an issue creating the cluster.

MySQLBase. create_cluster_set( self )

Create a cluster set for the cluster on cluster primary.

Description

Raises MySQLCreateClusterSetError on cluster set creation failure.

MySQLBase. initialize_juju_units_operations_table( self )

Initialize the mysql.juju_units_operations table using the serverconfig user.

Description

Raises MySQLInitializeJujuOperationsTableError if there is an issue initializing the juju_units_operations table

MySQLBase. add_instance_to_cluster( self , instance_address: str , instance_unit_label: str , from_instance , method: str )

Add an instance to the InnoDB cluster.

Arguments

instance_address

address of the instance to add to the cluster

instance_unit_label

the label/name of the unit

from_instance

address of the adding instance, e.g. primary

method

recovery method to use, either "auto" or "clone"

Description

This method is only called from the juju leader unit (thus locks are obtained locally)

Raises MySQLADDInstanceToClusterError if there was an issue adding the instance to the cluster.

MySQLBase. is_instance_configured_for_innodb( self , instance_address: str , instance_unit_label: str )

Confirm if instance is configured for use in an InnoDB cluster.

Arguments

instance_address

The instance address for which to confirm InnoDB configuration

instance_unit_label

The label of the instance unit to confirm InnoDB configuration

Returns

Boolean indicating whether the instance is configured for use in an InnoDB cluster

MySQLBase. are_locks_acquired( self , from_instance )

Report if any topology change is being executed.

Arguments

from_instance

member instance to run the command from (fallback to current one)

Description

Query the mysql.juju_units_operations table for any in-progress lock for either unit add or removal.

MySQLBase. rescan_cluster( self , from_instance , remove_instances: bool , add_instances: bool )

Rescan the cluster.

Arguments

from_instance

member instance to run the command from (fallback to current one)

remove_instances

whether to remove non-active instances from the metadata

add_instances

whether to add new instances to the metadata

MySQLBase. is_instance_in_cluster( self , unit_label: str )

Confirm if instance is in the cluster.

Arguments

unit_label

The label of unit to check existence in cluster for

Returns

Boolean indicating whether the unit is a member of the cluster

MySQLBase. get_cluster_status( self , extended )

Get the cluster status.

Returns

Cluster status as a dictionary, or None if running the status script fails.

Description

Executes script to retrieve cluster status. Won't raise errors.

MySQLBase. get_cluster_node_count( self , from_instance )

Retrieve current count of cluster nodes.

Returns

Amount of cluster nodes.

MySQLBase. get_cluster_endpoints( self , get_ips: bool )

Use get_cluster_status to return endpoints tuple.

Arguments

get_ips

Whether to return IP addresses or hostnames, default to IP

Returns

A tuple of strings with endpoints, read-only-endpoints and offline endpoints

MySQLBase. remove_instance( self , unit_label: str )

Remove instance from the cluster.

Description

This method is called from each unit being torn down, thus we must obtain locks on the cluster primary. There is a retry mechanism for any issues obtaining the lock, removing instances/dissolving the cluster, or releasing the lock.

Raises: MySQLRemoveInstanceRetryError - to retry this method if there was an issue obtaining a lock or removing the instance MySQLRemoveInstanceError - if there is an issue releasing the lock after the instance is removed from the cluster (avoids retries)

Args: unit_label: The label for this unit's instance (to be torn down)

MySQLBase. get_cluster_primary_address( self , connect_instance_address )

Get the cluster primary's address.

Returns

The address of the cluster's primary

Description

Keyword args: connect_instance_address: The address for the cluster primary (default to this instance's address)

MySQLBase. get_primary_label( self )

Description

Get the label of the cluster's primary. None

MySQLBase. is_unit_primary( self , unit_label: str )

Test if a given unit is the cluster primary.

Arguments

unit_label

The label of the unit to test

MySQLBase. set_cluster_primary( self , new_primary_address: str )

Set the cluster primary.

Arguments

new_primary_address

Address of node to set as cluster's primary

MySQLBase. get_cluster_members_addresses( self )

Get the addresses of the cluster's members.

Returns

Iterable of members addresses

MySQLBase. verify_server_upgradable( self , instance )

Wrapper for API check_for_server_upgrade.

MySQLBase. get_mysql_version( self )

Get the MySQL version.

Returns

The MySQL full version

MySQLBase. grant_privileges_to_user( self , username , hostname , privileges , with_grant_option )

Grants specified privileges to the provided user.

Description

Args: username: The username of user to grant privileges to hostname: The hostname of user to grant privileges to privileges: A list of privileges to grant to the user with_grant_option: Indicating whether to provide with grant option to user

Raises: MySQLGrantPrivilegesToUserError if there is an issue granting privileges to a user

MySQLBase. update_user_password( self , username: str , new_password: str , host: str )

Updates user password in MySQL database.

Description

Args: username: The username of user to update the password for new_password: The new password to be set for the user mentioned in username arg

Raises: MySQLCheckUserExistenceError if there is an issue updating the user's password

MySQLBase. get_member_state( self )

Get member status in cluster.

Returns

A tuple(str) with the MEMBER_STATE and MEMBER_ROLE within the cluster.

MySQLBase. reboot_from_complete_outage( self )

Description

Wrapper for reboot_cluster_from_complete_outage command. None

MySQLBase. hold_if_recovering( self )

Description

Hold execution if member is recovering. None

MySQLBase. set_instance_offline_mode( self , offline_mode: bool )

Sets the instance offline_mode.

Description

Args: offline_mode: Value of offline_mode to set

Raises: MySQLSetInstanceOfflineModeError - if issue setting instance offline_mode.

MySQLBase. set_instance_option( self , option: str , value: Any )

Sets an instance option.

Description

Args: option: The option to set for the instance value: The option value to set

Raises: MySQLSetInstanceOptionError - if there is an error setting instance option

MySQLBase. offline_mode_and_hidden_instance_exists( self )

Indicates whether an instance exists in offline_mode and hidden from router.

Description

The pre_backup operations switch an instance to offline_mode and hide it from the mysql-router.

MySQLBase. get_innodb_buffer_pool_parameters( self , available_memory: int )

Get innodb buffer pool parameters for the instance.

Arguments

available_memory

The amount (bytes) of memory available to the instance

Returns

a tuple of (innodb_buffer_pool_size, optional(innodb_buffer_pool_chunk_size), optional(group_replication_message_cache)) in bytes

MySQLBase. get_max_connections( self , available_memory: int )

Calculate max_connections parameter for the instance.

Arguments

available_memory

The available memory for mysql-server.

MySQLBase. get_available_memory( self )

Platform dependent method to get the available memory for mysql-server.

MySQLBase. execute_backup_commands( self , s3_path: str , s3_parameters , xtrabackup_location: str , xbcloud_location: str , xtrabackup_plugin_dir: str , mysqld_socket_file: str , tmp_base_directory: str , defaults_config_file: str , user , group )

Description

Executes commands to create a backup with the given args. None

MySQLBase. delete_temp_backup_directory( self , tmp_base_directory: str , user , group )

Description

Delete the temp backup directory. None

MySQLBase. retrieve_backup_with_xbcloud( self , backup_id: str , s3_parameters , temp_restore_directory: str , xbcloud_location: str , xbstream_location: str , user , group )

Retrieve the specified backup from S3.

Description

The backup is retrieved using xbcloud and stored in a temp dir in the mysql container. This temp dir is supposed to be on the same volume as the mysql data directory to reduce latency for IOPS.

MySQLBase. prepare_backup_for_restore( self , backup_location: str , xtrabackup_location: str , xtrabackup_plugin_dir: str , user , group )

Description

Prepare the backup in the provided dir for restore. None

MySQLBase. empty_data_files( self , mysql_data_directory: str , user , group )

Description

Empty the mysql data directory in preparation of backup restore. None

MySQLBase. restore_backup( self , backup_location: str , xtrabackup_location: str , defaults_config_file: str , mysql_data_directory: str , xtrabackup_plugin_directory: str , user , group )

Description

Restore the provided prepared backup. None

MySQLBase. delete_temp_restore_directory( self , temp_restore_directory: str , user , group )

Description

Delete the temp restore directory from the mysql data directory. None

MySQLBase. tls_setup( self , ca_path: str , key_path: str , cert_path: str , require_tls: bool )

Setup TLS files and requirement mode.

Arguments

ca_path

Path to the CA certificate

key_path

Path to the server key_path

cert_path

Path to the server certificate

require_tls

Require encryption

Description

When no arguments, restore to default configuration, i.e. SSL not required.

MySQLBase. kill_unencrypted_sessions( self )

Description

Kill non local, non system open unencrypted connections. None

MySQLBase. check_mysqlsh_connection( self )

Description

Checks if it is possible to connect to the server with mysqlsh. None

MySQLBase. get_pid_of_port_3306( self )

Description

Retrieves the PID of the process that is bound to port 3306. None

MySQLBase. flush_mysql_logs( self , logs_type )

Description

Flushes the specified logs_type logs. None

MySQLBase. is_mysqld_running( self )

Description

Returns whether mysqld is running. None

MySQLBase. is_server_connectable( self )

Description

Returns whether the server is connectable. None

MySQLBase. stop_mysqld( self )

Description

Stops the mysqld process. None

MySQLBase. start_mysqld( self )

Description

Starts the mysqld process. None

MySQLBase. restart_mysql_exporter( self )

Description

Restart the mysqld exporter. None

MySQLBase. wait_until_mysql_connection( self , check_port: bool )

Wait until a connection to MySQL has been obtained.

Description

Implemented in subclasses, test for socket file existence.

MySQLBase. reset_data_dir( self )

Description

Reset the data directory. None