rsync: pass command as list, moving the shlex.split to main; support `rsync -e "rsync-wrapper -C --"` style execution with the rsync command given as arguments
authorTero Marttila <terom@paivola.fi>
Fri, 02 Mar 2012 15:39:50 +0200
changeset 28 82bcde9e21c4
parent 27 689407a261c3
child 29 5abd153d78eb
rsync: pass command as list, moving the shlex.split to main; support `rsync -e "rsync-wrapper -C --"` style execution with the rsync command given as arguments
pvl/backup/rsync.py
scripts/pvlbackup-rsync-wrapper
--- a/pvl/backup/rsync.py	Fri Mar 02 14:41:19 2012 +0200
+++ b/pvl/backup/rsync.py	Fri Mar 02 15:39:50 2012 +0200
@@ -8,7 +8,6 @@
 from pvl.backup.mount import mount
 from pvl.backup import invoke
 
-import shlex
 import os.path
 
 import logging
@@ -102,11 +101,11 @@
             # cleanup
         # cleanup
  
-def parse_command (command, restrict_server=True, restrict_readonly=True) :
+def parse_command (command_parts, restrict_server=True, restrict_readonly=True) :
     """
         Parse given rsync server command into bits. 
 
-            command             - the command-string sent by rsync
+            command_parts       - the command-list sent by rsync
             restrict_server     - restrict to server-mode
             restrict_readonly   - restrict to read/send-mode
         
@@ -115,16 +114,13 @@
             (cmd, options, source, dest)
     """
 
-    # split
-    parts = shlex.split(command)
-
     cmd = None
     options = []
     source = None
     dest = None
 
     # parse
-    for part in parts :
+    for part in command_parts :
         if cmd is None :
             cmd = part
 
--- a/scripts/pvlbackup-rsync-wrapper	Fri Mar 02 14:41:19 2012 +0200
+++ b/scripts/pvlbackup-rsync-wrapper	Fri Mar 02 15:39:50 2012 +0200
@@ -2,6 +2,9 @@
 
 """
     SSH authorized_keys command="..." wrapper for rsync.
+
+    Testing goes something like:
+        sudo sh -c "PYTHONPATH=. rsync -e './scripts/pvlbackup-rsync-wrapper --debug -C --' -ax testing:lvm:asdf:test test/tmp"
 """
 
 from pvl.backup.rsync import RSyncCommandFormatError
@@ -9,6 +12,7 @@
 from pvl.backup import rsync
 
 import optparse
+import shlex
 import os
 import logging
 
@@ -22,6 +26,8 @@
         Parse command-line arguments.
     """
 
+#    import sys; sys.stderr.write("%s\n" % (argv, ))
+
     parser = optparse.OptionParser(
             prog        = argv[0],
 
@@ -42,6 +48,9 @@
     parser.add_option('-c', '--command',    metavar='CMD', default=os.environ.get('SSH_ORIGINAL_COMMAND'),
             help="rsync command to execute")
 
+    parser.add_option('-C', '--given-command', action='store_true', default=False,
+            help="use given command in `rsync -e %prog` format")
+
     parser.add_option('-R', '--readonly',   action='store_true', default=False,
             help="restrict to read/source mode")
 
@@ -112,19 +121,31 @@
     # global options + args
     options, args = parse_options(argv)
 
+    # command required
+    if options.given_command :
+        # from args (as given by `rsync -e pvlbackup-rsync-wrapper`) -> 'pvlbackup-rsync-wrapper <host> (<command> ...)'
+        host = args.pop(0)
+        command_parts = args
+
+        log.debug("using command from args: %r", command_parts)
+
     # args
-    if args :
+    elif args :
         log.error("No arguments are handled")
         return 2
 
-    # command required
-    if not options.command:
+    elif options.command:
+        # as given
+        command_parts = shlex.split(options.command)
+
+    else :
         log.error("SSH_ORIGINAL_COMMAND not given")
         return 2
 
+
+    # run
     try :
-        # handle it
-        return rsync_wrapper(options.command)
+        return rsync_wrapper(command_parts)
 
     except Exception, e:
         log.error("Internal error:", exc_info=e)