Ottomata has submitted this change and it was merged.

Change subject: Add backup role and scripts to wikimetrics
......................................................................


Add backup role and scripts to wikimetrics

We set up a daily and hourly backups of wikimetrics database, redis
database and wikimetrics public reports directory. If the dump of the
wikimetrics database fails backup script also fails.

Backup cronjobs are setup on root's crontab

Bug: 66119
Change-Id: I5de1bd600fe20ad557372de6c514cf83a59155fb
---
A files/backup/daily_script
A files/backup/hourly_script
A manifests/backup.pp
M manifests/init.pp
4 files changed, 326 insertions(+), 1 deletion(-)

Approvals:
  Ottomata: Verified; Looks good to me, approved
  jenkins-bot: Verified



diff --git a/files/backup/daily_script b/files/backup/daily_script
new file mode 100755
index 0000000..f77aea1
--- /dev/null
+++ b/files/backup/daily_script
@@ -0,0 +1,90 @@
+#!/bin/bash
+#
+# This file is managed by puppet
+#
+
+usage()
+{
+cat << EOF
+usage: $0 -i <hourly-dir> -o <daily-dir> -k <days-to-keep>
+
+Zips and copies the last hourly backup to the daily backup destination.
+Deletes any daily backup older than -k days.
+
+REQUIRED
+    -i <hourly-dir>     input folder with hourly backups
+    -o <daily-dir>      output folder with daily backups
+    -k <days-to-keep>   how many days to keep, must be a number
+
+OPTIONS
+   -h   Show this message
+EOF
+}
+
+HOURLY_BACKUPS=
+DAILY_DESTINATION=
+KEEP_DAYS=
+
+while getopts "hi:o:k:" OPTION
+do
+     case "$OPTION" in
+         h)
+             usage
+             exit
+             ;;
+         i)
+             HOURLY_BACKUPS="$OPTARG"
+             ;;
+         o)
+             DAILY_DESTINATION="$OPTARG"
+             ;;
+         k)
+             KEEP_DAYS="$OPTARG"
+             ;;
+         *)
+             usage
+             exit 1
+             ;;
+     esac
+done
+
+error() {
+     echo "Error:" "$@" >&2
+     exit 1
+}
+
+if [[ -z "$HOURLY_BACKUPS" ]]
+then
+    error "You did not give a hourly-dir parameter, although it's required"
+fi
+
+if [[ -z "$DAILY_DESTINATION" ]]
+then
+    error "You did not give a daily-dir parameter, although it's required"
+fi
+
+if [[ ! -d "$HOURLY_BACKUPS" ]]
+then
+    error "$HOURLY_BACKUPS does not exist or is not a directory"
+fi
+
+if [[ ! -d "$DAILY_DESTINATION" ]]
+then
+    error "$DAILY_DESTINATION  does not exist or is not a directory"
+fi
+
+if [[ ! "$KEEP_DAYS" =~ ^[0-9]+$ ]]
+then
+    error "Wrong or empty value for how many days to keep, must be a number"
+fi
+
+flock --timeout 10 "$HOURLY_BACKUPS" --command "\
+cp \"$HOURLY_BACKUPS/last.hourly.snapshot.tar.gz\" 
\"$DAILY_DESTINATION/snapshot.$(date +"%Y-%m-%d").tar.gz\" \
+"
+EXITCODE=$?
+
+if [ $EXITCODE -ne 0 ] ; then
+    error "Either failed to get lock on $HOURLY_DESTINATION, or cp-ing failed."
+fi
+
+find "$DAILY_DESTINATION" -mindepth 1 -maxdepth 1 -name "snapshot.*.tar.gz" 
-mtime +"$KEEP_DAYS" -delete
diff --git a/files/backup/hourly_script b/files/backup/hourly_script
new file mode 100755
index 0000000..9cabcc3
--- /dev/null
+++ b/files/backup/hourly_script
@@ -0,0 +1,134 @@
+#!/bin/bash
+#
+# This file is managed by puppet
+#
+
+usage()
+{
+cat << EOF
+usage: $0 -o <hourly-dir> -d <db-name> -m <db-defaults-file> -r 
<redis-db-file> -f <public-files>
+
+Backs up the mysql database, redis database file, and wikimetrics public 
reports
+as last.hourly.snapshot.tar.gz into <hourly-dir>.
+Overwrites any previous backup at the destination (specified with -o)
+
+If the script encounters symlinks, behaviour is undefined.
+
+REQUIRED
+    -o <hourly-dir>        output hourly backups to this directory
+    -d <db-name>           mysql database name to back up
+    -m <db-defaults-file>  file containing mysql defaults to connect to 
<db-name>
+    -r <redis-db-file>     redis database file path to back up
+    -f <public-reports>    directory of wikimetrics public reports to back up
+
+OPTIONS
+   -h   Show this message
+EOF
+}
+
+HOURLY_DESTINATION=
+DB_NAME=
+REDIS_DB_FILE=
+PUBLIC_REPORTS=
+
+while getopts "ho:d:m:r:f:" OPTION
+do
+     case "$OPTION" in
+         h)
+             usage
+             exit
+             ;;
+         o)
+             HOURLY_DESTINATION="$OPTARG"
+             ;;
+         d)
+             DB_NAME="$OPTARG"
+             ;;
+         m)
+             DB_DEFAULTS_FILE="$OPTARG"
+             ;;
+         r)
+             REDIS_DB_FILE="$OPTARG"
+             ;;
+         f)
+             PUBLIC_REPORTS="$OPTARG"
+             ;;
+         *)
+             usage
+             exit 1
+             ;;
+     esac
+done
+
+error() {
+     echo "Error:" "$@" >&2
+     exit 1
+}
+
+if [[ -z "$HOURLY_DESTINATION" ]]
+then
+    error "You did not give a hourly-dir parameter, although it's required"
+fi
+
+if [[ -z "$PUBLIC_REPORTS" ]]
+then
+    error "You did not give a public-reports parameter, although it's required"
+fi
+
+if [[ ! -d "$HOURLY_DESTINATION" ]]
+then
+    error "'$HOURLY_DESTINATION' does not exist or is not a directory"
+fi
+
+if [[ ! -d "$PUBLIC_REPORTS" ]]
+then
+    error "'$PUBLIC_REPORTS' does not exist or is not a directory"
+fi
+
+if [[ -z "$DB_NAME" ]]
+then
+    error "Missing the name of the database to back up"
+fi
+
+if [[ ! -f "$DB_DEFAULTS_FILE" ]]
+then
+    error "'$DB_DEFAULTS_FILE' does not exist or is not a file"
+fi
+
+if [[ ! -s "$REDIS_DB_FILE" ]]
+then
+    error "$REDIS_DB_FILE is empty or not a valid file path"
+fi
+
+BACKUP_DB="$(mktemp --tmpdir "database.sql.XXXXXX")"
+
+if [[ ! -f "$BACKUP_DB" ]]
+then
+    error "Could not create temorary file for database dump"
+else
+    trap "rm -f \"$BACKUP_DB\"; exit" INT TERM EXIT
+fi
+
+# mysqldump with default parameters, just plain non-incremental full backup
+mysqldump --defaults-extra-file="$DB_DEFAULTS_FILE" "$DB_NAME" > "$BACKUP_DB"
+EXITCODE=$?
+
+# the db is the one thing we cannot live without
+if [ $EXITCODE -ne 0 ] ; then
+     error "mysqldump failed with exit code $EXITCODE"
+fi
+
+if [[ ! -s "$BACKUP_DB" ]]
+then
+    error "Mysql backup file is empty or not writtable, not proceeding with 
backup"
+fi
+
+LANGUAGE=C flock --timeout 10 "$HOURLY_DESTINATION" --command "\
+tar fcz \"$HOURLY_DESTINATION/last.hourly.snapshot.tar.gz\" \"$BACKUP_DB\" \
+\"$REDIS_DB_FILE\" \"$PUBLIC_REPORTS\" \
+" 2> >( grep -v '^tar: Removing leading `/'\'' from member names$' >&2 )
+EXITCODE=$?
+
+if [ $EXITCODE -ne 0 ] ; then
+    error "Either failed to get lock on $HOURLY_DESTINATION, or tar-ing 
failed."
+fi
diff --git a/manifests/backup.pp b/manifests/backup.pp
new file mode 100644
index 0000000..079a3ee
--- /dev/null
+++ b/manifests/backup.pp
@@ -0,0 +1,91 @@
+# == Class wikimetrics::backup
+#
+# Backs up wikimetrics files to a specified path
+#
+# == Parameters
+# $destination      - path to copy backup files to.  Should be unique within a
+#                     labs project, otherwise it might overwrite other 
backups.  Required
+# $user             - user to coordinate the backup.  Default 'root'
+# $group            - group of the coordinating user.  Default 'root'
+# $db_user          - username of wikimetrics database user.  Default 
'wikimetrics'
+# $db_pass          - password of wikimetrics database user.  Default 
'wikimetrics'
+# $db_name          - database to back up.  Default 'wikimetrics'
+# $db_host          - hostname of wikimetrics database. Default 'localhost'
+# $redis_db_file    - redis database file.  Default 
'/a/redis/wikimetrics1-6379.rdb',
+# $public_files     - directory where public files (mostly reports) are.
+#                     This directory has to exist, and it should match
+#                     the value that ::wikimetrics sets.
+#                     Default '/var/lib/wikimetrics/public'
+# $keep_days        - How many days of history to keep.  Default 10
+#
+class wikimetrics::backup(
+    $destination,
+    $user           = 'root',
+    $group          = 'root',
+    $db_user        = 'wikimetrics',
+    $db_pass        = 'wikimetrics',
+    $db_name        = 'wikimetrics',
+    $db_host        = 'localhost',
+    $redis_db_file  = "/a/redis/${hostname}-6379.rdb",
+    $public_files   = '/var/lib/wikimetrics/public',
+    $keep_days      = 10,
+)
+{
+
+    $hourly_destination = "${destination}/hourly"
+    $daily_destination  = "${destination}/daily"
+    $backup_hourly_script = "${destination}/hourly_script"
+    $backup_daily_script  = "${destination}/daily_script"
+    $mysql_defaults_file = "${destination}/my.cnf"
+
+    # These directories should be writable by $user and $group.
+    file { [$destination, $hourly_destination, $daily_destination]:
+        ensure  => 'directory',
+        owner   => $user,
+        group   => $group,
+        mode    => '0700',
+    }
+
+    file { $backup_daily_script:
+        source => 'puppet:///modules/wikimetrics/backup/daily_script',
+        owner   => $user,
+        group   => $group,
+        mode    => '0555',
+    }
+
+    file { $backup_hourly_script:
+        source => 'puppet:///modules/wikimetrics/backup/hourly_script',
+        owner   => $user,
+        group   => $group,
+        mode    => '0555',
+    }
+
+    file { $mysql_defaults_file:
+        owner   => $user,
+        group   => $group,
+        mode    => '0400',
+        content => "# This file is managed by puppet.
+
+[client]
+user=${db_user}
+password=${db_pass}
+host=${db_host}
+default-character-set=utf8
+",
+    }
+
+    # backs up wikimetrics essentials hourly, overwriting the previous backup
+    cron { 'hourly wikimetrics backup':
+        command  => "${backup_hourly_script} -o ${hourly_destination} -f 
${public_files} -d ${db_name} -m ${mysql_defaults_file} -r ${redis_db_file}",
+        user     => $user,
+        minute   => 0,
+    }
+
+    # backs up wikimetrics essentials daily, keeping the last $keep_days days
+    cron { 'daily wikimetrics backup':
+        command  => "${backup_daily_script} -i ${hourly_destination} -o 
${daily_destination} -k ${keep_days}",
+        user     => $user,
+        hour     => 22,
+        minute   => 30,
+    }
+}
diff --git a/manifests/init.pp b/manifests/init.pp
index 019ae1d..5952c97 100644
--- a/manifests/init.pp
+++ b/manifests/init.pp
@@ -65,6 +65,9 @@
 #                          Default: root
 # $service_start_on      - start on stanza for upstart jobs (queue, web 
daemon).
 #                          Default: started network-services
+# $public_subdirectory   - Directory for public reports in $var_directory.
+#                          Must not contain slashes.
+#                          Default: public
 class wikimetrics(
     # path in which to install wikimetrics
     $path                  = '/srv/wikimetrics',
@@ -116,9 +119,16 @@
     $config_file_group     = 'root',
 
     $service_start_on      = 'started network-services',
+
+    $public_subdirectory   = 'public',
 )
 {
-    $public_directory  = "${var_directory}/public"
+    # Although we could inline $public_directory as it is used only
+    # once in this file, other wikimetrics modules
+    # (e.g. wikimetrics::web::apache) directly access
+    # $public_directory from here, so we cannot remove it :-(
+    $public_directory = "$var_directory/$public_subdirectory"
+
     $celery_beat_datafile  = "${run_directory}/celerybeat_scheduled_tasks"
     $celery_beat_pidfile   = "${run_directory}/celerybeat.pid"
 

-- 
To view, visit https://gerrit.wikimedia.org/r/139557
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I5de1bd600fe20ad557372de6c514cf83a59155fb
Gerrit-PatchSet: 17
Gerrit-Project: operations/puppet/wikimetrics
Gerrit-Branch: master
Gerrit-Owner: Milimetric <dandree...@wikimedia.org>
Gerrit-Reviewer: Milimetric <dandree...@wikimedia.org>
Gerrit-Reviewer: Nuria <nu...@wikimedia.org>
Gerrit-Reviewer: Ottomata <o...@wikimedia.org>
Gerrit-Reviewer: QChris <christ...@quelltextlich.at>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to