Browse Source

new: [mariadb] added charm.

Signed-off-by: Valentin Lab <valentin.lab@kalysto.org>
dev1
Valentin Lab 4 years ago
parent
commit
e16fa1efc6
  1. 61
      mariadb/hooks/init
  2. 62
      mariadb/hooks/mysql_database-relation-joined
  3. 44
      mariadb/hooks/schedule_command-relation-joined
  4. 76
      mariadb/lib/common
  5. 18
      mariadb/metadata.yml
  6. 52
      mariadb/resources/bin/mysql-backup

61
mariadb/hooks/init

@ -0,0 +1,61 @@
#!/bin/bash
## Init is run on host
## For now it is run every time the script is launched, but
## it should be launched only once after build.
## Accessible variables are:
## - SERVICE_NAME Name of current service
## - DOCKER_BASE_IMAGE Base image from which this service might be built if any
## - SERVICE_DATASTORE Location on host of the DATASTORE of this service
## - SERVICE_CONFIGSTORE Location on host of the CONFIGSTORE of this service
. lib/common
set -e
if [ "${HOST_DATASTORE+x}" ]; then
export HOST_DB_PASSFILE="$HOST_DATASTORE/${SERVICE_NAME}$DB_DATADIR/my.cnf"
else
export HOST_DB_PASSFILE="$CLIENT_DB_PASSFILE"
fi
if ! [ -d "$HOST_DATASTORE/${SERVICE_NAME}$DB_DATADIR" ]; then
MYSQL_ROOT_PASSWORD="$(gen_password)"
debug docker run -e "MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD" \
--rm \
-v "$DATA_DIR:$DB_DATADIR" \
--entrypoint /bin/bash "$DOCKER_BASE_IMAGE"
docker run -e "MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD" \
--rm \
-v "$DATA_DIR:$DB_DATADIR" \
--entrypoint /bin/bash "$DOCKER_BASE_IMAGE" -c '
mysqld() {
echo "diverted mysqld call..." >&2;
echo "$*" | grep -E "(--help|--skip-networking)" >/dev/null 2>&1 || return;
echo " .. Allowing call." >&2;
/usr/sbin/mysqld "$@";
}
export -f mysqld;
/docker-entrypoint.sh mysqld' || true
## docker errorlevel is still 0 even if it failed.
## AND we must ignore mysqld error !
[ "$(find "$DATA_DIR" \
-maxdepth 0 -type d -empty 2>/dev/null)" ] && {
err "Docker run probably failed to do it's job."
exit 1
}
## XXXvlab: this won't help support multiple project running on the
## same host
cat <<EOF > "$HOST_DB_PASSFILE"
[client]
password=$MYSQL_ROOT_PASSWORD
EOF
chmod 600 "$HOST_DB_PASSFILE"
info "New root password for mysql. "
fi

62
mariadb/hooks/mysql_database-relation-joined

@ -0,0 +1,62 @@
#!/bin/bash
## When writing relation script, remember:
## - they should be idempotents
## - they can be launched while the dockers is already up
## - they are launched from the host
## - the target of the link is launched first, and get a chance to ``relation-set``
## - both side of the scripts get to use ``relation-get``.
DBNAME=$(relation-get dbname 2>/dev/null) || {
DBNAME="$BASE_SERVICE_NAME"
relation-set dbname "$DBNAME"
}
USER=$(relation-get user 2>/dev/null) || {
USER="$BASE_SERVICE_NAME"
relation-set user "$USER"
}
PASSWORD="$(relation-get password 2>/dev/null)"
. lib/common
set -e
## is there a previous password set for user $USER ?
NO_PREVIOUS_PASS=
PREVIOUS_PASSWORD_PATH="$state_tmpdir/$SERVICE_NAME/pwd/$USER"
PREVIOUS_PASSWORD=$(cat "$PREVIOUS_PASSWORD_PATH" 2>/dev/null) || NO_PREVIOUS_PASS=true
if PASSWORD="$(relation-get password 2>/dev/null)"; then
if [ -z "$NO_PREVIOUS_PASS" -a "$PREVIOUS_PASSWORD" != "$PASSWORD" ]; then
die "Inconsistent password specification for user '$USER' on ${DARKYELLOW}$TARGET_SERVICE_NAME$NORMAL."
fi
else
if [ "$PREVIOUS_PASSWORD" ]; then
PASSWORD="${PREVIOUS_PASSWORD}"
else
PASSWORD="$(gen_password)"
info "Generated a new password for user '$USER'."
fi
fi
ensure_db_docker_running || exit 1
if [ "$?" == 0 ] && check_access "$DBNAME" "$USER" "$PASSWORD"; then
info "Access to database '$DBNAME' from user '$USER' verified working."
exit 0
fi
db_create "$DBNAME"
db_grant_rights "$DBNAME" "$USER" "$PASSWORD"
info "Granted rights on database '$DBNAME' to user '$USER'."
relation-set password "$PASSWORD"

44
mariadb/hooks/schedule_command-relation-joined

@ -0,0 +1,44 @@
#!/bin/bash
## When writing relation script, remember:
## - they should be idempotents
## - they can be launched while the dockers is already up
## - they are launched from the host
## - the target of the link is launched first, and get a chance to ``relation-set``
## - both side of the scripts get to use ``relation-get``.
. lib/common
set -e
## XXXvlab: should use container name here so that it could support
## multiple mysql
label=${SERVICE_NAME}-mysql-backup
DST=$CONFIGSTORE/$TARGET_SERVICE_NAME/etc/cron/$label
schedule=$(relation-get schedule)
if ! echo "$schedule" | egrep '^\s*(([0-9/,*-]+\s+){4,4}[0-9/,*-]+|@[a-z]+)\s*$' >/dev/null 2>&1; then
err "Unrecognized schedule '$schedule'."
exit 1
fi
## Warning: using '\' in heredoc will be removed in the final cron file, which
## is totally wanted: cron does not support multilines.
## Warning: 'docker -v' will use HOST directory even if launched from
## 'cron' container.
file_put "$DST" <<EOF
COMPOSE_LAUNCHER_OPTS=$COMPOSE_LAUNCHER_OPTS
$schedule root lock $label -D -p 10 -c "\
docker run --rm \
-e MYSQLHOST="${SERVICE_NAME}" \
--network ${PROJECT_NAME}_default \
-v \"$LOCAL_DB_PASSFILE\":/root/.my.cnf \
-v \"$HOST_CHARM_STORE/${CHARM_REL_PATH#${CHARM_STORE}/}/resources/bin/mysql-backup:/usr/sbin/mysql-backup\" \
-v \"$SERVICE_DATASTORE/var/backups/mysql:/var/backups/mysql\" \
--entrypoint mysql-backup \
\"$DOCKER_BASE_IMAGE\"" 2>&1 | ts '\%F \%T \%Z' >> /var/log/cron/${label}_script.log
EOF
chmod +x "$DST"

76
mariadb/lib/common

@ -0,0 +1,76 @@
# -*- mode: shell-script -*-
include pretty
export DB_NAME="$SERVICE_NAME" ## general type of database (ie: postgres/mysql...)
export DB_DATADIR=/var/lib/mysql
export DATA_DIR=$SERVICE_DATASTORE$DB_DATADIR
export LOCAL_DB_PASSFILE="$DATA_DIR/my.cnf"
export CLIENT_DB_PASSFILE=/root/.my.cnf
is_db_locked() {
local host_db_volume
if [ "${HOST_DATASTORE+x}" ]; then
host_db_volume="$HOST_DATASTORE/${SERVICE_NAME}"
else
host_db_volume="$DATASTORE/${SERVICE_NAME}"
fi
## ``are_files_locked_in_dir`` doesn't work with mysql here as
## tested
is_volume_used "$host_db_volume"
}
_set_db_params() {
local docker_ip="$1" docker_network="$2"
if [ "${HOST_DATASTORE+x}" ]; then
export HOST_DB_PASSFILE="$HOST_DATASTORE/${SERVICE_NAME}$DB_DATADIR/my.cnf"
else
export HOST_DB_PASSFILE="$CLIENT_DB_PASSFILE"
fi
[ -f "$CLIENT_DB_PASSFILE" ] || touch "$CLIENT_DB_PASSFILE"
server_docker_opts+=()
db_docker_opts+=("--network" "$docker_network")
db_cmd_opts+=("-h" "$docker_ip")
check_command="SELECT 1;"
}
_set_server_db_params() {
server_docker_opts+=()
}
ddb () { dcmd mysql "$@"; }
##
## Entrypoints
##
db_create () {
local dbname="$1"
## Using this instead of pipes is important so that trap works
debug "Create if not exists '$dbname' database..."
ddb < <(echo "CREATE DATABASE IF NOT EXISTS \`$dbname\`")
}
db_grant_rights () {
local dbname="$1" user="$2" password="$3"
## Using this instead of pipes is important so that trap works
debug "Grant all on $dbname to $user"
ddb < <(echo "GRANT ALL ON \`$dbname\`.* TO '$user'@'%' IDENTIFIED BY '$password'")
}
check_access() {
local dbname="$1" user="$2" password="$3"
## Using this instead of pipes is important so that trap works
debug "Check if credentials for user '$user' can access database '$dbname'"
ddb --user="$user" --password="$password" "$dbname" < <(echo "SELECT 1")
}

18
mariadb/metadata.yml

@ -0,0 +1,18 @@
name: MariaDB
## From: mysql Ver 15.1 Distrib 10.0.21-MariaDB
docker-image: docker.0k.io/mariadb:1.0.0
maintainer: "Valentin Lab <valentin.lab@kalysto.org>"
provides:
mysql-database:
data-resources:
- /var/lib/mysql
- /var/backups/mysql
uses:
schedule-command:
constraint: optional
auto: pair
solves:
backup: "Automatic regular dumps for backuping purpose"
default-options:
schedule: "31 * * * *" ## schedule backup every hour

52
mariadb/resources/bin/mysql-backup

@ -0,0 +1,52 @@
#!/bin/bash
m() {
mysql "${mysql_opts[@]}" -Bs "$@"
}
md() {
mysqldump "${mysql_opts[@]}" "$@"
}
mysql_databases() {
echo "SHOW DATABASES" | m
}
mysql_tables() {
local db="$1"
echo "SHOW TABLES" | m "$db"
}
mysql_opts=()
if [ "$MYSQLHOST" ]; then
mysql_opts+=(-h "$MYSQLHOST")
fi
DBS=($(mysql_databases)) || exit 1
mkdir -p /var/backups/mysql
for db in "${DBS[@]}"; do
if [[ "$db" == "information_schema" || "$db" == "performance_schema" || "$db" == "mysql" ]]; then
continue
fi
echo "Dumping database $db..." >&2
# omitting all the rotation logic
dst=/"var/backups/mysql/$db"
[ -d "$dst.old" ] && rm -rf "$dst.old"
[ -d "$dst" ] && mv "$dst" "$dst.old"
mkdir -p "$dst.inprogress"
(( start = SECONDS ))
md "$db" --routines --no-data --add-drop-database --database "$db" | gzip --rsyncable > "$dst.inprogress/schema.sql.gz"
tables=$(mysql_tables "$db")
for table in $tables; do
backup_file="$dst.inprogress/${table}.sql.gz"
echo " Dumping $table into ${backup_file}"
md "$db" "$table" | gzip --rsyncable > "$backup_file" || break
done
mv "$dst.inprogress" "$dst"
[ -d "$dst.old" ] && rm -rf "$dst.old"
(( elapsed = SECONDS - start ))
echo " ..dumped $db to $dst ($(du -sh "$dst" | cut -f 1) in ${elapsed}s)" >&2
done
Loading…
Cancel
Save