HWRF  trunk@4391
hwrf_deliver.py
1 #! /usr/bin/env python
2 
3 ##@namespace ush.hwrf_deliver
4 # A test program for the produtil.fileop.deliver_file() function.
5 #
6 # This program provides access to the produtil.fileop.deliver_file()
7 # function to shell programs. It was originally used to test that
8 # function, but it can also be used in scripts for other purposes.
9 # It is called as follows:
10 # @code[.sh]
11 # hwrf_deliver.py [options] [--] fromfile tofile
12 # @endcode
13 #
14 # It will copy the fromfile to the tofile file or directory without
15 # leaving the destination file in an incomplete state. This is
16 # accomplished by copying to a temporary file in the same directory
17 # and renaming that file to the final filename. If requested, a
18 # simple move (like "mv") is done if possible.
19 #
20 # Options:
21 # * -v --- verbose; use more -v for higher verbosity
22 # * -m --- move the file instead of copying it, if possible. This
23 # may not be possible if the source and destination are in
24 # different filesystems or filesets.
25 # * -c --- verify: check to see if the temporary and original file
26 # have the same contents before renaming to the destination
27 # * -b bytes --- copy this many bytes at a time
28 # * -t template --- template to prefix to tempoarary filenames
29 # * -k --- keep the temporary file if the rename fails
30 # * -- (two hyphens) --- Terminate option processing. This is
31 # needed for "misbehaving" filenames that begin with a
32 # hyphen
33 
34 
35 from produtil.fileop import *
36 from produtil.sigsafety import *
37 import sys,logging,getopt
38 
39 ##@var minblock
40 # Minimum required block size in bytes when -b is specified.
41 minblock=4096
42 
43 def usage(s=None):
44  """!Prints a usage message to stderr
45  @param s ignored"""
46  print>>sys.stderr, '''Format: %s [options] [--] from to
47 
48 This is the test program for produtil.fileop.deliver_file. It will
49 copy or move file "from" to file or directory "to". This is similar
50 to the cp and commands, but the "to" file will never be seen in an
51 incomplete state. This is accomplished either via a "mv" or by
52 copying to a temporary file and "mv"ing that file to the destination.
53 All "mv" operations are within one filesystem, to ensure the
54 operations are unit operations. Be sure to use the -m option if you
55 do not need the original "from" file any more to allow a simple "mv".
56 
57 Options:
58  -v verbose (multiple -v for higher verbosity)
59  -m use "mv" to deliver if "from" and "to" are in the same filesystem
60  Note: if that is done, it will cause "from" to cease to exist.
61  -c verify: check to see that the temporary file has the same contents as
62  "from" before moving it to the destination
63  -b bytes copy "bytes" bytes at a time (must be >= %d)
64  -t template prefix to prepend to temporary filenames
65  Can only contain: a-z A-Z 0-9 _ . -
66  -k Keep the temporary file if the delivery fails.
67  -- Terminate option processing. Use this if you need to deliver a
68  file whose name begins with a dash (-)''' % (sys.argv[0],minblock)
69  if s is not None:
70  print>>sys.stderr,\
71  'SCRIPT IS EXITING DUE TO INCORRECT ARGUMENTS: %s'%(str(s),minblock)
72 
73 def main():
74  """!Main program. Parses arguments, delivers file."""
75  install_handlers() # raise exception on SIGTERM or SIGHUP
76 
77  dash_v_count=0
78  kwargs={}
79  try:
80  (optarg,rest) = getopt.getopt(sys.argv[1:],'kmcrvb:t:')
81  except getopt.GetoptError as e:
82  usage(str(e))
83 
84  if(len(rest)!=2):
85  usage('You must provide exactly two non-option arguments: the source and destination (you gave %d args).'%(len(rest),))
86  (infile,outfile)=rest
87 
88  for opt,arg in optarg:
89  if(opt=='-m'):
90  kwargs['keep']=False
91  elif(opt=='-c'):
92  kwargs['verify']=True
93  elif(opt=='-b'):
94  try:
95  bs=float(arg)
96  if not (bs>=minblock):
97  usage('Minimum allowed block size is %d'%(minblock,))
98  kwargs['blocksize']=bs
99  except ValueError as e:
100  usage(str(e))
101  elif(opt=='-v'):
102  dash_v_count+=1
103  elif(opt=='-t'):
104  if(re.search('[^a-zA-Z0-9_-.]',arg)):
105  usage('The temp prefix must only contain alphanumerics, underscore (_), dash (-) and period (.).')
106  kwargs['tempprefix']=arg
107  elif(opt=='-k'):
108  kwargs['removefailed']=False
109  else:
110  usage('Unknown option %s'%(opt,))
111 
112  level=logging.WARNING
113  if dash_v_count>1:
114  level=logging.DEBUG
115  elif dash_v_count>0:
116  level=logging.INFO
117  logging.basicConfig(level=level)
118 
119  try:
120  deliver_file(infile,outfile,logger=logging.getLogger(),**kwargs)
121  sys.exit(0)
122  except DeliveryFailed as d:
123  logging.critical(str(d))
124  sys.exit(1)
125  except (IOError,OSError) as e:
126  logging.critical('%s delivery: %s' % (infile,str(e)))
127  sys.exit(1)
128  except (KeyboardInterrupt,CaughtSignal) as e:
129  logging.critical('%s delivery: abort due to signal: %s'%(infile,str(e)))
130  sys.exit(1)
131 
132 if __name__=='__main__': main()
This module provides a set of utility functions to do filesystem operations.
Definition: fileop.py:1
Sets up signal handlers to ensure a clean exit.
Definition: sigsafety.py:1