ArielGlenn has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/390165 )

Change subject: clean up dumps web server rsync to its fallback
......................................................................


clean up dumps web server rsync to its fallback

No need for a python script any more, just rsync the relevant
directories.

Move the destination host name out to a profile.

Bug: T179942
Change-Id: I48493292def0c0630d960aaa403d2f87ff59137b
---
D modules/dumps/files/copying/rsync-dumps.py
A modules/dumps/files/copying/rsync_from_webserver.sh
M modules/dumps/manifests/copying/peers.pp
M modules/profile/manifests/dumps/web/xmldumps_active.pp
4 files changed, 71 insertions(+), 225 deletions(-)

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



diff --git a/modules/dumps/files/copying/rsync-dumps.py 
b/modules/dumps/files/copying/rsync-dumps.py
deleted file mode 100644
index 00aba76..0000000
--- a/modules/dumps/files/copying/rsync-dumps.py
+++ /dev/null
@@ -1,218 +0,0 @@
-import sys
-import subprocess
-import socket
-############################
-# This file is managed by puppet!
-# puppet:///modules/dumps/copying/rsync-dumps.py
-###########################
-
-
-class Rsyncer(object):
-    def __init__(self, max_bw, dryrun, list_only):
-        self.max_bw = str(max_bw)
-        self.dryrun = dryrun
-        self.list_only = list_only
-        self.host = socket.gethostname()
-        self.rsync_args = ["--bwlimit=" + self.max_bw, '-a', '--delete']
-        if self.list_only:
-            self.rsync_args.append("--list-only")
-        else:
-            self.rsync_args.append("-q")
-        self.excludes = ['--exclude=wikidump_*', '--exclude=md5temp.*', 
'--exclude=*.inprog']
-
-    def get_excludes_for_job(self, jobname, host_info):
-        excludes = []
-        for job in host_info:
-            # 'exclude': { 'dir': 'other', 'job': 'public' }
-            if (job != jobname and 'exclude' in host_info[job] and
-                    host_info[job]['exclude']['job'] == jobname):
-                excludes.append(host_info[job]['exclude']['dir'])
-        return excludes
-
-    def rsync_all(self, host_info):
-        for job in host_info:
-            excludes = self.get_excludes_for_job(job, host_info)
-
-            hosts = host_info[job]['hosts']
-            if self.host not in hosts:
-                # no rsync job info for this host
-                continue
-
-            targets = [h for h in hosts if h != self.host]
-            if not len(targets):
-                # no hosts to rsync to
-                continue
-
-            if 'primary' in hosts[self.host]:
-                # this host rsyncs everything except a specific list of dirs
-                dir_args = ["--exclude=/" + d.strip('/') + "/"
-                            for d in excludes]
-                for targ in targets:
-                    if 'dirs' in hosts[targ]:
-                        dir_args.extend(["--exclude=/" + d.strip('/') + "/"
-                                         for d in hosts[targ]['dirs']])
-
-            elif 'dirs' in hosts[self.host]:
-                # this host keeps data in a specific list of dirs and must
-                # rsync those everywhere else
-
-                dirs_to_include = [d.strip('/')
-                                   for d in hosts[self.host]['dirs']]
-                if not len(dirs_to_include):
-                    # no specific dirs to sync
-                    continue
-
-                dir_args = ["--include=/" + d + "/" for d in dirs_to_include]
-                dir_args.extend(["--include=/" + d + "/**"
-                                 for d in dirs_to_include])
-                dir_args.append('--exclude=*')
-
-            else:
-                # not a primary, no specific dirs to sync, do nothing
-                continue
-
-            self.do_rsync(host_info[job]['source'], host_info[job]['dest'],
-                          targets, dir_args)
-
-    def do_rsync(self, src, dest, targets, dir_args):
-        for targ in targets:
-            command = ["/usr/bin/pgrep", "-u", "root",
-                       "-f", "%s::%s" % (targ, dest)]
-            try:
-                subprocess.check_output(command)
-                # return code 0 = already running
-                if self.dryrun:
-                    print "would skip rsync to", "%s::%s" % (targ, dest)
-                continue
-            except subprocess.CalledProcessError as err:
-                if err.returncode != 1:
-                    # genuine error
-                    raise
-
-            command = (["/usr/bin/rsync"] + self.rsync_args + self.excludes +
-                       dir_args + [src, "%s::%s" % (targ, dest)])
-            if self.dryrun:
-                print "would run", " ".join(command)
-            else:
-                output = None
-                try:
-                    output = subprocess.check_output(command)
-                except subprocess.CalledProcessError:
-                    # fixme might want to do something with error output
-                    pass
-                if output:
-                    if self.list_only:
-                        print output
-                    else:
-                        command = ["/usr/bin/mail", '-E', '-s',
-                                   "DUMPS RSYNC " + self.host,
-                                   'ops-dumps' + '@' + 'wikimedia' + '.org']
-                        proc = subprocess.Popen(command, stdin=subprocess.PIPE)
-                        (out_unused, errs) = proc.communicate(input=output)
-                        if errs:
-                            # give up and hope something else sees this
-                            print errs
-
-
-def usage(message):
-    if message:
-        sys.stderr.write(message + "\n")
-        help_message = """Usage: rsync-dumps.py [dryrun] [bw=number] [list]
-    dryrun -- show commands that would be run instead of runnning them
-    bw     -- cap rsync bandwidth to this number (default: 40000)
-    list   -- only list files that would be transferred instead of sending them
-"""
-        sys.stderr.write(help_message)
-        sys.exit(1)
-
-
-def do_main():
-    dryrun = False
-    list_only = False
-    max_bandwidth = 40000
-
-    for i in range(1, len(sys.argv)):
-        if sys.argv[i] == 'dryrun':
-            dryrun = True
-        elif sys.argv[i].startswith('bw='):
-            max_bandwidth = sys.argv[i][3:]
-            if not max_bandwidth.isdigit():
-                usage("maxbw must be a number")
-        elif sys.argv[i] == 'list':
-            list_only = True
-        else:
-            usage("unknown option: " + sys.argv[i])
-
-    rsync = Rsyncer(max_bandwidth, dryrun, list_only)
-
-    # The rsync commands we would expect to see on...
-    #
-    # Primary for '/public/':
-    #   /usr/bin/rsync -v --bwlimit=40000 -a --delete
-    #          --exclude=wikidump_* --exclude=md5temp.*
-    #          --exclude=/dir-done-by-secondary/
-    #          --exclude=/another-dir-done-by-secondary/
-    #          --exclude=/other/
-    #          /data/xmldatadumps/public/
-    #          remotehost::data/xmldatadumps/public/
-    #
-    # Secondary for '/public/':
-    #   /usr/bin/rsync -v --bwlimit=40000 -a --delete
-    #          --exclude=wikidump_* --exclude=md5temp.*
-    #          --include=/dir-done-by-secondary/
-    #          --include=/another-dir-done-by-secondary/
-    #          --include=/dir-done-by-secndary/**
-    #          --include=/another-dir-done-by-secondary/**
-    #          --exclude=*
-    #          /data/xmldatadumps/public/
-    #          remotehost::data/xmldatadumps/public/
-    #
-    # primary for '/public/other/':
-    #   /usr/bin/rsync -v --bwlimit=40000 -a --delete
-    #          --exclude=wikidump_* --exclude=md5temp.*
-    #          --exclude=/subdir-done-by-secondary/
-    #          --exclude=/another-subdir-done-by-secondary/
-    #          /data/xmldatadumps/public/other/
-    #          remotehost::data/xmldatadumps/public/other/
-    #
-    # secondary for '/public/other/':
-    #   /usr/bin/rsync -v --bwlimit=40000 -a --delete
-    #          --exclude=wikidump_* --exclude=md5temp.*
-    #          --include=/subdir-done-by-secondary/
-    #          --include=/another-dir-done-by-secondary/
-    #          --include=/subdir-done-by-secondary/**
-    #          --include=/another-subdir-done-by-secondary/**
-    #          --exclude=*
-    #          /data/xmldatadumps/public/other/
-    #          remotehost::data/xmldatadumps/public/other/
-
-    host_info = {
-        'public': {  # job name
-            # source is an absolute path
-            'source': '/data/xmldatadumps/public/',
-            # dest will be prefixed by 'servername::' in rsync
-            'dest': 'data/xmldatadumps/public/',
-            'hosts': {
-                # everything but a specific list of dirs will be pushed:
-                'dataset1001': {'primary': True},
-                # only the specified list of dirs is here:
-                'ms1001': {'dirs': []}
-            }
-        },
-        'other': {   # job name
-            # don't sync this when doing the 'public' job:
-            'exclude': {'dir': 'other', 'job': 'public'},
-
-            'source': '/data/xmldatadumps/public/other/',
-            'dest': 'data/xmldatadumps/public/other/',
-            'hosts': {
-                'ms1001': {'dirs': []},
-                'dataset1001': {'primary': True}
-            }
-        }
-    }
-    rsync.rsync_all(host_info)
-
-
-if __name__ == '__main__':
-    do_main()
diff --git a/modules/dumps/files/copying/rsync_from_webserver.sh 
b/modules/dumps/files/copying/rsync_from_webserver.sh
new file mode 100644
index 0000000..e312bd8
--- /dev/null
+++ b/modules/dumps/files/copying/rsync_from_webserver.sh
@@ -0,0 +1,60 @@
+#!/bin/bash
+
+##############################
+# This file is managed by puppet!
+# puppet:///modules/dumps/copying/rsync_from_webserver.sh
+##############################
+
+# This script rsyncs xml/sql dumps to fallback web servers or other servers
+# that host a full copy of dumps and datasets.
+#
+# It expects to be run as root, since it preserves owners and permissions.
+#
+# It will not run if there is already an rsync of some sort running to/from
+# the destination host as the root user, no point in competing for
+# bandwidth. Also no point in running a second copy if this script itself
+# is already running.
+
+usage() {
+    cat<<EOF
+Usage: $0 --desthost <hostname>
+
+  --desthost   fqdn of host to which to rsync
+
+Example: $0 --desthost ms1001.wikimedia.org
+EOF
+    exit 1
+}
+
+desthost=""
+
+while [ $# -gt 0 ]; do
+    if [ $1 == "--desthost" ]; then
+        desthost="$2"
+        shift; shift
+    else
+        echo "$0: Unknown option $1" >& 2
+        usage
+    fi
+done
+
+if [ -z "$desthost" ]; then
+    echo "$0: missing argument --desthost"
+    usage && exit 1
+fi
+
+excludes="--exclude='**bad/' --exclude='**save/' --exclude='**not/' 
--exclude='**temp/' --exclude='**tmp/'--exclude='*.inprog'"
+args="--contimeout=600 --timeout=600 --bwlimit=40000 --delete"
+
+# /usr/bin/pgrep -f -x /usr/bin/rsync -rlptq $bwlimit 
${sourcehost}::${srcpath} ${destroot}/${destpath}
+isrunning=$( /usr/bin/pgrep -u root -f "/usr/bin/rsync .* ${desthost}::" )
+if [ -n "$isrunning" ]; then
+    exit 0
+fi
+
+# sample command:
+# /usr/bin/rsync --bwlimit=40000 -aq --delete --exclude='**bad/' 
--exclude='**save/' --exclude='**not/' \
+#       --exclude='**temp/' --exclude='**tmp/' --exclude='*.inprog' \
+#       /data/xmldatadumps/public/other/ 
ms1001.wikimedia.org::data/xmldatadumps/public/other/
+/usr/bin/rsync $args -aq $excludes --exclude=/other/ 
/data/xmldatadumps/public/  ${desthost}::data/xmldatadumps/public/
+/usr/bin/rsync $args -aq $excludes /data/xmldatadumps/public/other/ 
${desthost}::data/xmldatadumps/public/other/
diff --git a/modules/dumps/manifests/copying/peers.pp 
b/modules/dumps/manifests/copying/peers.pp
index cf9f80d..351e183 100644
--- a/modules/dumps/manifests/copying/peers.pp
+++ b/modules/dumps/manifests/copying/peers.pp
@@ -1,20 +1,22 @@
-class dumps::copying::peers {
-    file { '/usr/local/bin/rsync-dumps.py':
+class dumps::copying::peers(
+    $desthost = undef,
+) {
+    file { '/usr/local/bin/rsync_from_webserver.sh':
         ensure => 'present',
         mode   => '0755',
         owner  => 'root',
         group  => 'root',
-        path   => '/usr/local/bin/rsync-dumps.py',
-        source => 'puppet:///modules/dumps/copying/rsync-dumps.py',
+        path   => '/usr/local/bin/rsync_from_webserver.sh',
+        source => 'puppet:///modules/dumps/copying/rsync_from_webserver.sh'
     }
 
     cron { 'rsync-dumps':
         ensure  => 'present',
         # filter out error messages about vanishing files, we don't want email 
for that
-        command => '/usr/bin/python /usr/local/bin/rsync-dumps.py 2>&1 | grep 
-v "vanished" ',
+        command => '/bin/bash /usr/local/bin/rsync_from_webserver.sh 
--desthost $desthost 2>&1 | grep -v "vanished" ',
         user    => 'root',
         minute  => '0',
         hour    => '*/2',
-        require => File['/usr/local/bin/rsync-dumps.py'],
+        require => File['/usr/local/bin/rsync_from_webserver.sh'],
     }
 }
diff --git a/modules/profile/manifests/dumps/web/xmldumps_active.pp 
b/modules/profile/manifests/dumps/web/xmldumps_active.pp
index 2fd241d..bffa0a8 100644
--- a/modules/profile/manifests/dumps/web/xmldumps_active.pp
+++ b/modules/profile/manifests/dumps/web/xmldumps_active.pp
@@ -16,7 +16,9 @@
         webgroup         => 'datasets',
     }
     # copy dumps and other datasets to fallback host(s) and to labs
-    class {'::dumps::copying::peers':}
+    class {'::dumps::copying::peers':
+        desthost => 'ms1001.wikimedia.org',
+    }
     class {'::dumps::copying::labs':
         labhost   => 'labstore1003.eqiad.wmnet',
         publicdir => $publicdir,

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I48493292def0c0630d960aaa403d2f87ff59137b
Gerrit-PatchSet: 7
Gerrit-Project: operations/puppet
Gerrit-Branch: production
Gerrit-Owner: ArielGlenn <ar...@wikimedia.org>
Gerrit-Reviewer: ArielGlenn <ar...@wikimedia.org>
Gerrit-Reviewer: Volans <rcocci...@wikimedia.org>
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