Not a member of Pastebin yet?
                        Sign Up,
                        it unlocks many cool features!                    
                - import logging
- from logging.handlers import TimedRotatingFileHandler
- log = logging.getLogger('')
- log.setLevel(logging.DEBUG)
- formatter = logging.Formatter('%(asctime)s [%(threadName)10s][%(levelname)5s] %(message)s')
- fh = logging.FileHandler('log.txt')
- fh = TimedRotatingFileHandler('log.txt', when='D', interval=1, backupCount=5)
- fh.setFormatter(formatter)
- fh.setLevel(logging.DEBUG)
- ch = logging.StreamHandler()
- ch.setFormatter(formatter)
- ch.setLevel(logging.DEBUG)
- log.addHandler(ch)
- log.addHandler(fh)
- import shutil
- import os
- from filecmp import dircmp
- import filecmp
- #
- #Recursively compare all files & directories using comparison class (filecmp.dirmcp)
- # true = match, false = not matching
- #
- def verify(comparison):
- try:
- '''
- # comparison.diff_files reads entire file contents
- # not recommended for remote file comparison
- # disabled in this implementation.
- if comparison.diff_files != []:
- return False
- '''
- if comparison.left_only != []:
- #log.debug(dcmp.left_only)
- return False
- if comparison.right_only != []:
- #log.debug(dcmp.right_only)
- return False
- for sub_comparison in comparison.subdirs.values():
- if verify(sub_comparison) != True:
- return False
- return True
- except:
- return False
- #
- #Recursively sync (using shutil) all files & directories using comparison class (filecmp.dirmcp)
- #
- def sync(comparison):
- #log.debug('compare_sync called')
- try:
- '''
- # comparison.diff_files reads entire file contents
- # not recommended for remote file comparison
- # disabled in this implementation.
- if comparison.diff_files != []: #File size mismatch
- #log.debug('diff_files_issue')
- for item in comparison.diff_files:
- sub_src = comparison.left+'/'+item
- sub_dest = comparison.right+'/'+item
- if os.path.isfile(sub_dest):
- #log.debug('deleting: %s' % sub_dest)
- os.remove(sub_dest)
- #log.debug('copying single file: %s' % (sub_src +' -> '+ sub_dest))
- shutil.copy2(sub_src,sub_dest)
- else:
- #log.debug('deleting directory: %s' % sub_dest )
- shutil.rmtree(sub_dest)
- #log.debug('copying directory: %s' % (sub_src +' -> '+ sub_dest))
- shutil.copytree(sub_src,sub_dest, symlinks=True, ignore=None)
- '''
- if comparison.left_only != []: #Missing in destination
- #log.debug('left_only_issue')
- for item in comparison.left_only:
- sub_src = comparison.left+'/'+item
- sub_dest = comparison.right+'/'+item
- if os.path.isfile(sub_src):
- log.debug('copying single file: %s' % (sub_src +' -> '+ sub_dest))
- shutil.copy2(sub_src,sub_dest)
- else:
- log.debug('copying directory: %s' % (sub_src +' -> '+ sub_dest))
- shutil.copytree(sub_src,sub_dest, symlinks=True, ignore=None)
- if comparison.right_only != []: #Destination has extra
- #log.debug('right_only_issue')
- for item in comparison.right_only:
- sub_src = comparison.left+'/'+item
- sub_dest = comparison.right+'/'+item
- if os.path.isfile(sub_dest):
- log.debug('deleting: %s' % sub_dest)
- os.remove(sub_dest)
- else:
- log.debug('deleting directory: %s' % sub_dest )
- shutil.rmtree(sub_dest)
- for sub_comparison in comparison.subdirs.values(): #Recursively sync subfolders
- result = sync(sub_comparison)
- if result != True: #on error escalate False
- return False
- return True
- except:
- return False
- #
- #Handler for inability to create a root comparison due to root directory missing.
- #
- def fix_missing_dest_directory(src, dest, e):
- #log.debug('fix mis dest, %s %s %s' % (src, dest, e))
- directory = str(e).split('The system cannot find the path specified: \'')[1]
- directory = directory.split('/*.*\'')[0]
- directory = directory.replace('\\\\', '\\') #remove unnecessary escape characters (\\) from error message
- if dest == directory: #don't if fix source missing
- if os.path.exists(directory.split('SS')[0]+'WMV'): #avoid correcting a temporary register
- shutil.copytree(src,dest, symlinks=True, ignore=None)
- #
- #Task generator for threading
- # Creates individual tasks for each ip + source/destination combination.
- #
- def generate_sync_tasks(q, l_ip, l_src_paths, l_dest_paths, action):#str/list, list of paths
- for ip in l_ip:
- for i,dest_path in enumerate(l_dest_paths):
- src = l_src_paths[i]
- dest = r'\\' + ip + dest_path
- q.put((src,dest,action))
- return q
- #
- #Worker thread
- # Grab tasks from queue until queue is empty
- #
- def worker():
- #log.debug('starting worker')
- while q.qsize() > 0:
- src,dest,action = q.get()
- comparison = dircmp(src,dest)
- if action == 'sync':
- try:
- result = sync(comparison)
- #log.debug('worker logged %s' % result)
- except WindowsError, e:
- if e.winerror == 3: #3 root src or dest directory is missing.
- fix_missing_dest_directory(src, dest, e)
- try:
- result = sync(comparison)
- except:
- result = False
- raise
- if e.winerror == 53: #53 network path not found
- result = False
- log.debug('WinError 53 - Network Path Not Found')
- ip = str(e).split('The network path was not found: \'')[1]
- ip = ip.split('\\\\\\\\')[1]
- ip = ip.split('\\\\c-drive\\')[0]
- action = 'sync. Store offline: %s' % ip
- else:
- action = 'verify'
- try:
- result = verify(comparison)
- except:
- result = False
- if result == True:
- log.info('Completed %s. \t %s -> %s' % (action, src, dest))
- q.task_done()
- else:
- log.error('Failed %s. \t %s -> %s' % (action, src, dest))
- q.task_done()
- #log.debug('closing worker')
- #
- #Wait for user confirmation to close window.
- #
- def closeprompt():
- try:
- input("Press enter to exit.\n")
- except SyntaxError:
- pass
- raise SystemExit
- #
- #Main Process
- #
- #generate ip list
- l_ip = []
- #Use if targeting specific ips
- #l_ip.append(IP) #REDACTED - target IP
- #Use if targeting ips provided as list.
- with open('iplist.txt', 'r') as ipfile:
- for line in ipfile:
- line = line.strip()
- l_ip.append(line)
- #list of source paths
- l_src_paths = []
- #list of destination paths
- l_dest_paths = []
- #Input source/destination as pairs
- l_src_paths.append(r'') #REDACTED - target source path pair 1
- l_dest_paths.append(r'') #REDACTED - target destination path pair 1
- l_src_paths.append(r'') #REDACTED - target source path pair 2
- l_dest_paths.append(r'') #REDACTED - target destination path pair 2
- assert len(l_src_paths) == len(l_dest_paths) #verify source/dest were given as pairs
- #Identify errors without correcting, or correct immediately.
- try:
- action = input('1 for verify, 2 for sync:\n')
- action = int(action)
- if action == 2:
- #log.debug('sync selected')
- action = 'sync'
- else:
- #log.debug('verify selected')
- action = 'verify'
- except:
- log.error('Input not recognized, closing...')
- closeprompt()
- #generate tasklist of source/destination pairs for threading
- import Queue
- q = Queue.Queue()
- q = generate_sync_tasks(q, l_ip, l_src_paths, l_dest_paths, action)
- log.info('Tasks queued: %i' % q.qsize())
- max_threads = 20
- import thread
- import threading
- import time
- for i in range(1,max_threads):
- t = threading.Thread(target=worker,name='Worker-%i' % (i))
- t.start()
- while threading.activeCount() > 2:
- log.info('%i workers active.' % (len(threading.enumerate())-2) )
- if q.qsize() > 0:
- log.info('%i remaining tasks.' % q.qsize())
- time.sleep(30)
- log.info('All tasks assigned, waiting for workers to finish.')
- q.join()
- log.info('Program Completed. Terminating...')
- #exit
- closeprompt()
Advertisement
 
                    Add Comment                
                
                        Please, Sign In to add comment                    
                 
                    