scripts/pvlbackup-rsync-wrapper
changeset 6 302f45534b73
parent 5 23371d26fdd0
child 8 5ae35c5afc69
equal deleted inserted replaced
5:23371d26fdd0 6:302f45534b73
       
     1 #!/usr/bin/python
       
     2 
       
     3 from pvl.backup.rsync import RSyncCommandFormatError
       
     4 from pvl.backup.invoke import InvokeError
       
     5 from pvl.backup import rsync
       
     6 
       
     7 import optparse
       
     8 import os
       
     9 import logging
       
    10 
       
    11 log = logging.getLogger()
       
    12 
       
    13 # command-line options
       
    14 options = None
       
    15 
       
    16 def parse_options (argv) :
       
    17     """
       
    18         Parse command-line arguments.
       
    19     """
       
    20 
       
    21 
       
    22     parser = optparse.OptionParser()
       
    23 
       
    24     # logging
       
    25     parser.add_option('-q', '--quiet',      dest='loglevel', action='store_const', const=logging.WARNING, help="Less output")
       
    26     parser.add_option('-v', '--verbose',    dest='loglevel', action='store_const', const=logging.INFO,  help="More output")
       
    27     parser.add_option('-D', '--debug',      dest='loglevel', action='store_const', const=logging.DEBUG, help="Even more output")
       
    28 
       
    29     # 
       
    30     parser.add_option('-c', '--command',    default=os.environ.get('SSH_ORIGINAL_COMMAND'),
       
    31             help="rsync command to execute")
       
    32 
       
    33     parser.add_option('-R', '--readonly',   action='store_true', default=False,
       
    34             help="restrict to read operations")
       
    35 
       
    36     parser.add_option('-P', '--restrict-path', default=False,
       
    37             help="restrict to given path")
       
    38 
       
    39     # defaults
       
    40     parser.set_defaults(
       
    41         loglevel    = logging.WARNING,
       
    42     )
       
    43 
       
    44     # parse
       
    45     options, args = parser.parse_args(argv[1:])
       
    46 
       
    47     # configure
       
    48     logging.basicConfig(
       
    49         format  = '%(processName)s: %(name)s: %(levelname)s %(funcName)s : %(message)s',
       
    50         level   = options.loglevel,
       
    51     )
       
    52 
       
    53     return options, args
       
    54 
       
    55 def rsync_wrapper (command, restrict='lvm:') :
       
    56     """
       
    57         Wrap given rsync command.
       
    58         
       
    59         Backups the LVM LV given in the rsync command.
       
    60     """
       
    61 
       
    62     try :
       
    63         # parse
       
    64         rsync_cmd, rsync_options, source_path, dest_path = rsync.parse_command(command, 
       
    65                 restrict_readonly   = options.readonly,
       
    66             )
       
    67 
       
    68     except RSyncCommandFormatError, e:
       
    69         log.error("invalid rsync command: %r: %s", command, e)
       
    70         return 2
       
    71 
       
    72     # XXX: the real path is always given second..
       
    73     path = dest_path
       
    74 
       
    75     try :
       
    76         # parse source
       
    77         source = rsync.parse_source(path,
       
    78                 restrict_path       = options.restrict_path,
       
    79             )
       
    80 
       
    81     except RSyncCommandFormatError, e:
       
    82         log.error("invalid rsync source: %r: %s", path, e)
       
    83         return 2
       
    84 
       
    85     try :
       
    86         # run
       
    87         source.execute(rsync_options)
       
    88 
       
    89     except InvokeError, e:
       
    90         log.error("%s failed: %d", e.cmd, e.exit)
       
    91         return e.exit
       
    92 
       
    93     # ok
       
    94     return 0
       
    95 
       
    96 def main (argv) :
       
    97     """
       
    98         SSH authorized_keys command="..." wrapper for rsync.
       
    99     """
       
   100 
       
   101     global options
       
   102 
       
   103     # global options + args
       
   104     options, args = parse_options(argv)
       
   105 
       
   106     # args
       
   107     if args :
       
   108         log.error("No arguments are handled")
       
   109         return 2
       
   110 
       
   111     if not options.command:
       
   112         log.error("SSH_ORIGINAL_COMMAND not given")
       
   113         return 2
       
   114 
       
   115     try :
       
   116         # handle it
       
   117         return rsync_wrapper(options.command)
       
   118 
       
   119     except Exception, e:
       
   120         log.error("Internal error:", exc_info=e)
       
   121         return 3
       
   122 
       
   123     # ok
       
   124     return 0
       
   125 
       
   126 if __name__ == '__main__' :
       
   127     import sys
       
   128 
       
   129     sys.exit(main(sys.argv))
       
   130