#! /usr/bin/python #+ # NAME: # burnfiles # PURPOSE: # Burn DVD from L1A files # CATEGORY: # gen/python # CALLING SEQUENCE: # burnfiles [] # INPUTS: # fully-qualified directory # source directory with files to be put on CD/DVD # fully-qualified directory # directory where files are moved after # the CD/DVD has been burned. # If omitted then this is the same as . # Files are moved to only if the CD/DVD # burned succesfully. If -test is set then files # stay in ; if burning fails or -img is set # then files are moved back to . # OPTIONAL INPUTS: # -pattern=pattern file name wildcard # default: * # -sort sort files before selecting files # -dvd burn a DVD (instead of a CD) # -img make the CD image file, but don't burn CD/DVD # -nosudo launch cdrecord without using sudo # -remove remove the files after burning the CD/DVD # (ignored if -test or -img is set) # -verbose display messages # -temp=temp location where CD image is created # default: $temp # -count=count number of CD/DVD copies # -speed=speed write speed (default is different for CD and DVD # and is set in burndisk.py) # -dev=dev SCSI dev id for the CD/DVD writer; default: 0,0,0 # -email=email comma-separated list of email addresses to which # to send an email upon completion. # -test test run # -before number of days # if a file is found with a modification time # more than 'before' days before the current time # than file selection is terminated. # # Size can be specified with postfix G or GB for gigabyte, M or MB for # megabyte, k or kB for kilobyte or just bytes with no postfix. # # -max_disk_size=max_disk_size # files are selected until the combined # file size is upto max_disk_size bytes. # DVD default: 4500MB # CD default: 650MB # (these values still need tuning) # -min_disk_size=min_disk_size # the combined file size must be at least # this many bytes or no disk is burned. # DVD default: 4200MB # CD default: 600MB # -min_file_size=min_file_size # default: 500kB # see PROCEDURE # -logfile=logfile log file where content of CD/DVD is logged. # A list of file names is appened to # only if burning of CD/DVD was succesfull. # -timestamp add timestamp to file name in logfile # -unblock skips test for running instances of l1a.py in ftp mode. # OUTPUTS: # CD/DVD (maybe) # CALLS: # burndisk # SEE ALSO: # EXAMPLE: # burnfiles.py -dvd -count=2 /storage/temp # PROCEDURE: # Selected files are moved to a temporary subdirectory of # # # If -remove IS set then the temporary directory and its content are # deleted after burning the CD/DVD. # If -remove is NOT set then the files are moved back # # The CD img file is created in $temp and is also deleted after # processing (see href=burndisk=). # MODIFICATION HISTORY: # FEB-2004, Paul Hick (UCSD/CASS) # MAR-2004, Paul Hick (UCSD/CASS; pphick@ucsd.edu) # Added -speed, -verbose, -dev, -clean keywords. # Changed to dictionary for list of args for burndisk # Lowered max_disk_size for DVDs. # Fixed bug for non-existent log file. # APR-2004, Paul Hick (UCSD/CASS) # Changed min_file_size default from 100kB to 500kB. # MAY-2004, Paul Hick (UCSD/CASS; pphick@ucsd.edu) # Added -before keyword # JUN-2004, Paul Hick (UCSD/CASS) # Added -noblock keyword # AUG-2004, Paul Hick (UCSD/CASS; pphick@ucsd.edu) # Replace -sudo by -nosudo. #- import sys, os, tempfile, glob from datetime import datetime from tiny import hide_env, args, start, is_there, count_instances, tomb from burndisk import burndisk datetime.now() def burnfiles_remove( burndir, verbose ): # Delete files and burndir for file in os.listdir(burndir): tmp = os.path.join(burndir, file) if verbose: print 'remove', hide_env(tmp) os.remove( tmp ) os.rmdir( burndir ) if verbose: print 'remove', hide_env(burndir) return def burnfiles_move( burndir, source, verbose ): for file in os.listdir(burndir): tmp = os.path.join(burndir, file) if verbose: print ' ', hide_env(tmp) os.rename( tmp, os.path.join(source, file) ) if verbose: print '-->', hide_env(source) os.rmdir( burndir ) if verbose: print 'remove', hide_env(burndir) return def burnfiles_log( logfile, burndir, verbose, timestamp ): t = datetime.now() t = '%d'%t.year+'/%02d'%t.month+'/%02d'%t.day+' %02d'%t.hour+':%02d'%t.minute+':%02d'%t.second if logfile != '': if os.path.exists(logfile): content = (open(logfile,'r')).read() content = content.split('\n') else: content = [] # Determine next sequence number from log file # Check for / in time stamp ndvd = 0 for tmp in content: if tmp.find('/') != -1: ndvd = (tmp.split(' '))[0] ndvd = int(ndvd)+1 print 'ID', ndvd, ' Time', t # Update logfile with info for new dvd content = ( ['', '%d'%ndvd+' '+t, ''] ) lst = os.listdir(burndir) if timestamp: for i in range( len(lst) ): lst[i] = lst[i]+' %d'%((os.stat(os.path.join(burndir, lst[i]))).st_mtime) content.extend( lst ) if os.path.exists(logfile): (open(logfile,'a')).write( '\n'.join(content)+'\n') else: (open(logfile,'w')).write( '\n'.join(content)+'\n') return #=========== if __name__ == '__main__': arg = args( sys.argv ) narg = len(arg) sort = is_there( '-sort' , sys.argv ) remove = is_there( '-remove' , sys.argv ) test = is_there( '-test' , sys.argv ) clean = is_there( '-clean' , sys.argv ) logfile = start ( '-logfile=', sys.argv ) before = start ( '-before=' , sys.argv ) unblock = is_there( '-unblock' , sys.argv ) if not unblock: if count_instances( 'l1a.py coreftp.plh.af.mil', 1 ) >= 1: sys.exit() check_time = before != '' if check_time: import time cutoff_time = time.time()-int(before)*86400 pattern = start ( '-pattern=', sys.argv ) if pattern == '': pattern = '*' make_dvd = is_there( '-dvd' , sys.argv ) make_img = is_there( '-img' , sys.argv ) verbose = is_there( '-verbose' , sys.argv ) timestamp = is_there( '-timestamp', sys.argv ) burn_args = dict \ ( [ \ ( 'make_tar', is_there( '-tar' , sys.argv ) ), \ ( 'make_dvd', is_there( '-dvd' , sys.argv ) ), \ ( 'make_img', is_there( '-img' , sys.argv ) ), \ ( 'nosudo' , is_there( '-nosudo', sys.argv ) ), \ ( 'verbose' , is_there( '-verbose',sys.argv ) ), \ ( 'tempdir' , start ( '-temp=' , sys.argv ) ), \ ( 'count' , start ( '-count=', sys.argv ) ), \ ( 'speed' , start ( '-speed=', sys.argv ) ), \ ( 'dev' , start ( '-dev=' , sys.argv ) ), \ ( 'mode' , start ( '-mode=' , sys.argv ) ), \ ( 'email' , start ( '-email=', sys.argv ) ), \ ( 'exe' , start ( '-exe=' , sys.argv ) ) ] ) max_disk_size = start( '-max_disk_size=', sys.argv ) min_disk_size = start( '-min_disk_size=', sys.argv ) min_file_size = start( '-min_file_size=', sys.argv ) if narg > 1: source = arg[1] if source == '.': source = os.getcwd() if narg > 2: destination = arg[2] if destination == '.': destination = os.getcwd() else: destination = source else: source = raw_input('Directory: ') source = os.path.expandvars( source ) destination = source if not os.path.isdir(source): print 'source is not a directory: ', source sys.exit(1) if not os.path.isdir(destination): print 'destination is not a directory: ', destination sys.exit(1) # Pick up list of *.buf files in source until the next file pushes # the total file above l1a_size_max. # l1a: list of file names (no path) # 650MB CD: max # 681443328 (OK) # 682491904 (too big) # 4.5GB DVD: 4707186688 (OK) # 4707608576 (too big) if max_disk_size == '': if make_dvd: max_disk_size = '4489MB' # 4500MB else: max_disk_size = '650MB' # 650 MB if min_disk_size == '': if make_dvd: min_disk_size = '4200MB' else: min_disk_size = '600MB' if min_file_size == '': min_file_size = '500kB' # Convert to MB as floating point numbers max_disk_size = tomb( max_disk_size ) min_disk_size = tomb( min_disk_size ) min_file_size = tomb( min_file_size ) pattern = os.path.join( source, pattern ) file_list = glob.glob( pattern ) if len(file_list) == 0: print 'no files found matching', pattern sys.exit() if sort: file_list.sort() # Name for temporary directory to put the files. tempfile.tempdir = source burndir = tempfile.mktemp() size = 0.0 max_flag = 0 if not test: # Create temp directory to be put on DVD os.mkdir( burndir ) # Put a copy of the logfile on the CD/DVD. This is the old copy # of the logfile (the current CD/DVD has not yet been entered). if logfile != '': if os.path.exists( logfile ): os.spawnlp( os.P_WAIT, 'cp', 'cp', logfile, burndir ) size = size+tomb( '%d'%(os.stat(logfile)).st_size ) for file in file_list: if check_time: if (os.stat(file)).st_mtime > cutoff_time: print ' Too recent:', hide_env(file) print ' Release in:', ((os.stat(file)).st_mtime - cutoff_time)/3600, 'hours' break file_size = tomb( '%d'%(os.stat(file)).st_size ) # Keep adding files until max_disk_size is reached # The selected files are moved into the temporary subdirectory # 'burndir' of 'source' # Initially (max_flag = False) files are added until max_disk_size is # reached. Once a file is encountered that pushed the total size # above max_disk_size (max_flag = True) files are only added if they # are larger than min_file_size. new_size = size+file_size if new_size > max_disk_size: if clean: break max_flag = 1 elif not max_flag or file_size > min_file_size: print ' ', hide_env(file), round(file_size,6), 'MB' if not test: os.rename( file, os.path.join(burndir, (os.path.split(file))[1]) ) size = new_size if not test: print '-->', hide_env(burndir) if size < min_disk_size: print '\nTotal size is', round(size,3), '/', max_disk_size, 'MB\n',\ 'Total size is less than', min_disk_size, 'MB\n', \ 'No disk was burned. Override with -min_disk_size=.\n' if not test: burnfiles_move( burndir, source, verbose ) elif test: print '\nTotal size is', round(size,3), '/', max_disk_size, 'MB\n' else: # Burn the disk. print '\nTotal size is', round(size,3), '/', max_disk_size, 'MB\n' try: status = burndisk([burndir], burn_args) except: # If something goes wrong, put the files back burnfiles_move( burndir, source, verbose ) print 'burnfiles, problem in burndisk. cdrecord key expired ???' status = 1 else: if make_img: # Create CD-image only burnfiles_move( burndir, source, verbose ) elif status != 0: # Burndisk returned error status burnfiles_move( burndir, source, verbose ) else: burnfiles_log( logfile, burndir, verbose, timestamp ) if remove: # Remove files and burndir burnfiles_remove ( burndir, verbose ) else: # Move files to destination burnfiles_move( burndir, destination, verbose ) sys.exit()