Package fcp :: Module upload
[hide private]
[frames] | no frames]

Source Code for Module fcp.upload

  1  #@+leo-ver=4 
  2  #@+node:@file put.py 
  3  """ 
  4  Upload a file. 
  5   
  6  This is the guts of the command-line front-end app fcpupload. 
  7   
  8  It is adapted from put.py, just with nicer defaults and feedback. 
  9  """ 
 10   
 11  #@+others 
 12  #@+node:imports 
 13  import sys, os, getopt, traceback, mimetypes 
 14   
 15  import node 
 16   
 17  #@-node:imports 
 18  #@+node:globals 
 19  progname = sys.argv[0] 
 20   
 21  #@-node:globals 
 22  #@+node:usage 
23 -def usage(msg=None, ret=1):
24 """ 25 Prints usage message then exits 26 """ 27 if msg: 28 sys.stderr.write(msg+"\n") 29 sys.stderr.write("Usage: %s [options] key_uri [filename]\n" % progname) 30 sys.stderr.write("Type '%s -h' for help\n" % progname) 31 sys.exit(ret)
32 33 #@-node:usage 34 #@+node:help
35 -def help():
36 """ 37 print help options, then exit 38 """ 39 # TODO: Switch to argparse. That would save at least half the file. 40 print "\n".join(("%s: a simple command-line freenet key insertion command" % progname, 41 "Usage: %s [options] <filename>" % progname, 42 "", 43 "Arguments:", 44 " <key_uri>", 45 " A freenet key URI, such as 'freenet:KSK@gpl.txt'", 46 " Note that the 'freenet:' part may be omitted if you feel lazy", 47 " <filename>", 48 " The filename from which to source the key's data. If this filename", 49 " is '-', or is not given, then the data will be sourced from", 50 " standard input", 51 "", 52 "Options:", 53 " -h, -?, --help", 54 " Print this help message", 55 " -v, --verbose", 56 " Print verbose progress messages to stderr, do -v twice for more detail", 57 " -H, --fcpHost=<hostname>", 58 " Connect to FCP service at host <hostname>", 59 " -P, --fcpPort=<portnum>", 60 " Connect to FCP service at port <portnum>", 61 " -m, --mimetype=<mimetype>", 62 " The mimetype under which to insert the key. If not given, then", 63 " an attempt will be made to guess it from the filename. If no", 64 " filename is given, or if this attempt fails, the mimetype", 65 " 'text/plain' will be used as a fallback", 66 " -c, --compress", 67 " Enable compression of inserted data (default is no compression)", 68 " -d, --disk", 69 " Try to have the node access file on disk directly , it will try then a fallback is provided", 70 " nb:give the path relative to node filesystem not from where you're running this program", 71 " For the direct access to succeed, the absolute path seen by the node and by this script must be the same", 72 " -p, --persistence=", 73 " Set the persistence type, one of 'connection', 'reboot' or 'forever'", 74 " -g, --global", 75 " Do it on the FCP global queue", 76 " -w, --wait", 77 " Wait for completion", 78 " -r, --priority", 79 " Set the priority (0 highest, 6 lowest, default 3)", 80 " -e, --realtime", 81 " Use the realtime queue (fast for small files)", 82 " -t, --timeout=", 83 " Set the timeout, in seconds, for completion. Default one year", 84 " -V, --version", 85 " Print version number and exit", 86 "", 87 "Environment:", 88 " Instead of specifying -H and/or -P, you can define the environment", 89 " variables FCP_HOST and/or FCP_PORT respectively"))
90 91 92 #@-node:help 93 #@+node:main
94 -def main():
95 """ 96 Front end for fcpput utility 97 """ 98 # default job options 99 verbosity = node.ERROR 100 verbose = False 101 fcpHost = node.defaultFCPHost 102 fcpPort = node.defaultFCPPort 103 mimetype = None 104 wait = False 105 106 opts = { 107 "Verbosity" : 0, 108 "persistence" : "forever", 109 "async" : True, 110 "priority" : 3, 111 "Global": "true", 112 "MaxRetries" : -1, 113 } 114 115 # process command line switches 116 try: 117 cmdopts, args = getopt.getopt( 118 sys.argv[1:], 119 "?hvH:P:m:gcdp:wr:et:V", 120 ["help", "verbose", "fcpHost=", "fcpPort=", "mimetype=", "global","compress","disk", 121 "persistence=", "wait", 122 "priority=", "realtime", "timeout=", "version", 123 ] 124 ) 125 except getopt.GetoptError: 126 # print help information and exit: 127 usage() 128 sys.exit(2) 129 output = None 130 verbose = False 131 #print cmdopts 132 133 makeDDARequest=False 134 opts['nocompress'] = True 135 136 for o, a in cmdopts: 137 if o in ("-V", "--version"): 138 print "This is %s, version %s" % (progname, node.fcpVersion) 139 sys.exit(0) 140 141 elif o in ("-?", "-h", "--help"): 142 help() 143 sys.exit(0) 144 145 elif o in ("-v", "--verbosity"): 146 if verbosity < node.DETAIL: 147 verbosity = node.DETAIL 148 else: 149 verbosity += 1 150 opts['Verbosity'] = 1023 151 verbose = True 152 153 elif o in ("-H", "--fcpHost"): 154 fcpHost = a 155 156 elif o in ("-P", "--fcpPort"): 157 try: 158 fcpPort = int(a) 159 except: 160 usage("Invalid fcpPort argument %s" % repr(a)) 161 162 elif o in ("-m", "--mimetype"): 163 mimetype = a 164 165 elif o in ("-c", "--compress"): 166 opts['nocompress'] = False 167 168 elif o in ("-d","--disk"): 169 makeDDARequest=True 170 171 172 elif o in ("-p", "--persistence"): 173 if a not in ("connection", "reboot", "forever"): 174 usage("Persistence must be one of 'connection', 'reboot', 'forever'") 175 opts['persistence'] = a 176 177 elif o in ("-g", "--global"): 178 opts['Global'] = "true" 179 180 elif o in ("-w", "--wait"): 181 opts['async'] = False 182 wait = True 183 184 elif o in ("-r", "--priority"): 185 try: 186 pri = int(a) 187 if pri < 0 or pri > 6: 188 raise hell 189 except: 190 usage("Invalid priority '%s'" % pri) 191 opts['priority'] = int(a) 192 193 elif o in ("-e", "--realtime"): 194 opts['realtime'] = True 195 196 elif o in ("-t", "--timeout"): 197 try: 198 timeout = node.parseTime(a) 199 except: 200 usage("Invalid timeout '%s'" % a) 201 opts['timeout'] = timeout 202 203 # process args 204 nargs = len(args) 205 if nargs < 1 or nargs > 2: 206 usage("Invalid number of arguments") 207 208 keytypes = ["USK", "KSK", "SSK", "CHK"] 209 if nargs == 2: 210 infile = args[1] 211 uri = args[0] 212 if not uri.startswith("freenet:"): 213 uri = "freenet:" + uri 214 if not uri[len("freenet:"):len("freenet:")+3] in keytypes: 215 print uri, uri[len("freenet:"):len("freenet:")+4] 216 usage("The first argument must be a key. Example: CHK@/<filename>") 217 else: 218 # if no infile is given, automatically upload to a CHK key. 219 infile = args[0] 220 uri = "freenet:CHK@/" + node.toUrlsafe(infile) 221 222 # if we got an infile, but the key does not have the filename, use that filename for the uri. 223 if infile and uri[-2:] == "@/" and uri[:3] in keytypes: 224 uri += node.toUrlsafe(infile) 225 226 227 # figure out a mimetype if none present 228 if infile and not mimetype: 229 base, ext = os.path.splitext(infile) 230 if ext: 231 mimetype = mimetypes.guess_type(ext)[0] 232 233 if mimetype: 234 # mimetype explicitly specified, or implied with input file, 235 # stick it in. 236 # otherwise, let FCPNode.put try to imply it from a uri's 237 # 'file extension' suffix 238 opts['mimetype'] = mimetype 239 240 # try to create the node 241 try: 242 n = node.FCPNode(host=fcpHost, port=fcpPort, verbosity=verbosity, 243 logfile=sys.stderr) 244 except: 245 if verbose: 246 traceback.print_exc(file=sys.stderr) 247 usage("Failed to connect to FCP service at %s:%s" % (fcpHost, fcpPort)) 248 249 # FIXME: Throw out all the TestDDARequest stuff. It is not needed for putting a single file. 250 TestDDARequest=False 251 252 #: The key of the uploaded file. 253 freenet_uri = None 254 255 if makeDDARequest: 256 if infile is not None: 257 ddareq=dict() 258 ddafile = os.path.abspath(infile) 259 ddareq["Directory"]= os.path.dirname(ddafile) 260 # FIXME: This does not work. The only reason why testDDA 261 # works is because there is an alternate way of specifying 262 # a content hash, and that way works. 263 ddareq["WantReadDirectory"]="True" 264 ddareq["WantWriteDirectory"]="false" 265 print "Absolute filepath used for node direct disk access :",ddareq["Directory"] 266 print "File to insert :",os.path.basename( ddafile ) 267 TestDDARequest=n.testDDA(**ddareq) 268 269 if TestDDARequest: 270 opts["file"]=ddafile 271 putres = n.put(uri,**opts) 272 else: 273 sys.stderr.write("%s: disk access failed to insert file %s fallback to direct\n" % (progname,ddafile) ) 274 else: 275 sys.stderr.write("%s: disk access needs a disk filename\n" % progname ) 276 277 # try to insert the key using "direct" way if dda has failed 278 if not TestDDARequest: 279 # grab the data 280 if not infile: 281 data = sys.stdin.read() 282 else: 283 try: 284 data = file(infile, "rb").read() 285 except: 286 n.shutdown() 287 usage("Failed to read input from file %s" % repr(infile)) 288 289 try: 290 #print "opts=%s" % str(opts) 291 # give it the file anyway: Put is more intelligent than this script. 292 opts["data"] = data 293 if infile: 294 opts["file"] = infile 295 n.listenGlobal() 296 putres = n.put(uri, **opts) 297 if not wait: 298 opts["chkonly"] = True 299 opts["async"] = False 300 # force the node to be fast 301 opts["priority"] = 0 302 opts["realtime"] = True 303 opts["persistence"] = "connection" 304 opts["Global"] = False 305 freenet_uri = n.put(uri,**opts) 306 307 except: 308 if verbose: 309 traceback.print_exc(file=sys.stderr) 310 n.shutdown() 311 sys.stderr.write("%s: Failed to insert key %s\n" % (progname, repr(uri))) 312 sys.exit(1) 313 314 if not wait: 315 # got back a job ticket, wait till it has been sent 316 putres.waitTillReqSent() 317 else: 318 # successful, return the uri 319 sys.stdout.write(putres) 320 sys.stdout.flush() 321 322 n.shutdown() 323 324 # output the key of the file 325 if not wait: 326 print freenet_uri 327 # all done 328 sys.exit(0)
329 330 #@-node:main 331 #@-others 332 333 #@-node:@file put.py 334 #@-leo 335