Guest User

Untitled

a guest
Jan 25th, 2017
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.47 KB | None | 0 0
  1. import logging
  2. from logging.handlers import TimedRotatingFileHandler
  3. log = logging.getLogger('')
  4. log.setLevel(logging.DEBUG)
  5.  
  6. formatter = logging.Formatter('%(asctime)s [%(threadName)10s][%(levelname)5s] %(message)s')
  7. fh = logging.FileHandler('log.txt')
  8. fh = TimedRotatingFileHandler('log.txt', when='D', interval=1, backupCount=5)
  9. fh.setFormatter(formatter)
  10. fh.setLevel(logging.DEBUG)
  11.  
  12. ch = logging.StreamHandler()
  13. ch.setFormatter(formatter)
  14. ch.setLevel(logging.DEBUG)
  15.  
  16. log.addHandler(ch)
  17. log.addHandler(fh)
  18.  
  19. import shutil
  20. import os
  21. from filecmp import dircmp
  22. import filecmp
  23.  
  24. #
  25. #Recursively compare all files & directories using comparison class (filecmp.dirmcp)
  26. # true = match, false = not matching
  27. #
  28. def verify(comparison):
  29. try:
  30. '''
  31. # comparison.diff_files reads entire file contents
  32. # not recommended for remote file comparison
  33. # disabled in this implementation.
  34. if comparison.diff_files != []:
  35. return False
  36. '''
  37. if comparison.left_only != []:
  38. #log.debug(dcmp.left_only)
  39. return False
  40. if comparison.right_only != []:
  41. #log.debug(dcmp.right_only)
  42. return False
  43. for sub_comparison in comparison.subdirs.values():
  44. if verify(sub_comparison) != True:
  45. return False
  46. return True
  47. except:
  48. return False
  49.  
  50.  
  51.  
  52. #
  53. #Recursively sync (using shutil) all files & directories using comparison class (filecmp.dirmcp)
  54. #
  55. def sync(comparison):
  56. #log.debug('compare_sync called')
  57. try:
  58. '''
  59. # comparison.diff_files reads entire file contents
  60. # not recommended for remote file comparison
  61. # disabled in this implementation.
  62.  
  63. if comparison.diff_files != []: #File size mismatch
  64. #log.debug('diff_files_issue')
  65. for item in comparison.diff_files:
  66. sub_src = comparison.left+'/'+item
  67. sub_dest = comparison.right+'/'+item
  68. if os.path.isfile(sub_dest):
  69. #log.debug('deleting: %s' % sub_dest)
  70. os.remove(sub_dest)
  71. #log.debug('copying single file: %s' % (sub_src +' -> '+ sub_dest))
  72. shutil.copy2(sub_src,sub_dest)
  73. else:
  74. #log.debug('deleting directory: %s' % sub_dest )
  75. shutil.rmtree(sub_dest)
  76. #log.debug('copying directory: %s' % (sub_src +' -> '+ sub_dest))
  77. shutil.copytree(sub_src,sub_dest, symlinks=True, ignore=None)
  78. '''
  79.  
  80. if comparison.left_only != []: #Missing in destination
  81. #log.debug('left_only_issue')
  82. for item in comparison.left_only:
  83. sub_src = comparison.left+'/'+item
  84. sub_dest = comparison.right+'/'+item
  85. if os.path.isfile(sub_src):
  86. log.debug('copying single file: %s' % (sub_src +' -> '+ sub_dest))
  87. shutil.copy2(sub_src,sub_dest)
  88. else:
  89. log.debug('copying directory: %s' % (sub_src +' -> '+ sub_dest))
  90. shutil.copytree(sub_src,sub_dest, symlinks=True, ignore=None)
  91. if comparison.right_only != []: #Destination has extra
  92. #log.debug('right_only_issue')
  93. for item in comparison.right_only:
  94. sub_src = comparison.left+'/'+item
  95. sub_dest = comparison.right+'/'+item
  96. if os.path.isfile(sub_dest):
  97. log.debug('deleting: %s' % sub_dest)
  98. os.remove(sub_dest)
  99. else:
  100. log.debug('deleting directory: %s' % sub_dest )
  101. shutil.rmtree(sub_dest)
  102. for sub_comparison in comparison.subdirs.values(): #Recursively sync subfolders
  103. result = sync(sub_comparison)
  104. if result != True: #on error escalate False
  105. return False
  106. return True
  107. except:
  108. return False
  109.  
  110.  
  111. #
  112. #Handler for inability to create a root comparison due to root directory missing.
  113. #
  114. def fix_missing_dest_directory(src, dest, e):
  115. #log.debug('fix mis dest, %s %s %s' % (src, dest, e))
  116. directory = str(e).split('The system cannot find the path specified: \'')[1]
  117. directory = directory.split('/*.*\'')[0]
  118. directory = directory.replace('\\\\', '\\') #remove unnecessary escape characters (\\) from error message
  119. if dest == directory: #don't if fix source missing
  120. if os.path.exists(directory.split('SS')[0]+'WMV'): #avoid correcting a temporary register
  121. shutil.copytree(src,dest, symlinks=True, ignore=None)
  122.  
  123. #
  124. #Task generator for threading
  125. # Creates individual tasks for each ip + source/destination combination.
  126. #
  127. def generate_sync_tasks(q, l_ip, l_src_paths, l_dest_paths, action):#str/list, list of paths
  128. for ip in l_ip:
  129. for i,dest_path in enumerate(l_dest_paths):
  130. src = l_src_paths[i]
  131. dest = r'\\' + ip + dest_path
  132. q.put((src,dest,action))
  133. return q
  134.  
  135. #
  136. #Worker thread
  137. # Grab tasks from queue until queue is empty
  138. #
  139. def worker():
  140. #log.debug('starting worker')
  141. while q.qsize() > 0:
  142. src,dest,action = q.get()
  143. comparison = dircmp(src,dest)
  144. if action == 'sync':
  145. try:
  146. result = sync(comparison)
  147. #log.debug('worker logged %s' % result)
  148. except WindowsError, e:
  149. if e.winerror == 3: #3 root src or dest directory is missing.
  150. fix_missing_dest_directory(src, dest, e)
  151. try:
  152. result = sync(comparison)
  153. except:
  154. result = False
  155. raise
  156. if e.winerror == 53: #53 network path not found
  157. result = False
  158. log.debug('WinError 53 - Network Path Not Found')
  159. ip = str(e).split('The network path was not found: \'')[1]
  160. ip = ip.split('\\\\\\\\')[1]
  161. ip = ip.split('\\\\c-drive\\')[0]
  162. action = 'sync. Store offline: %s' % ip
  163. else:
  164. action = 'verify'
  165. try:
  166. result = verify(comparison)
  167. except:
  168. result = False
  169. if result == True:
  170. log.info('Completed %s. \t %s -> %s' % (action, src, dest))
  171. q.task_done()
  172. else:
  173. log.error('Failed %s. \t %s -> %s' % (action, src, dest))
  174. q.task_done()
  175. #log.debug('closing worker')
  176.  
  177.  
  178. #
  179. #Wait for user confirmation to close window.
  180. #
  181. def closeprompt():
  182. try:
  183. input("Press enter to exit.\n")
  184. except SyntaxError:
  185. pass
  186. raise SystemExit
  187.  
  188.  
  189. #
  190. #Main Process
  191. #
  192.  
  193.  
  194. #generate ip list
  195. l_ip = []
  196.  
  197. #Use if targeting specific ips
  198. #l_ip.append(IP) #REDACTED - target IP
  199.  
  200.  
  201. #Use if targeting ips provided as list.
  202. with open('iplist.txt', 'r') as ipfile:
  203. for line in ipfile:
  204. line = line.strip()
  205. l_ip.append(line)
  206.  
  207. #list of source paths
  208. l_src_paths = []
  209. #list of destination paths
  210. l_dest_paths = []
  211.  
  212.  
  213. #Input source/destination as pairs
  214. l_src_paths.append(r'') #REDACTED - target source path pair 1
  215. l_dest_paths.append(r'') #REDACTED - target destination path pair 1
  216.  
  217. l_src_paths.append(r'') #REDACTED - target source path pair 2
  218. l_dest_paths.append(r'') #REDACTED - target destination path pair 2
  219.  
  220.  
  221. assert len(l_src_paths) == len(l_dest_paths) #verify source/dest were given as pairs
  222.  
  223.  
  224. #Identify errors without correcting, or correct immediately.
  225. try:
  226. action = input('1 for verify, 2 for sync:\n')
  227. action = int(action)
  228. if action == 2:
  229. #log.debug('sync selected')
  230. action = 'sync'
  231. else:
  232. #log.debug('verify selected')
  233. action = 'verify'
  234. except:
  235. log.error('Input not recognized, closing...')
  236. closeprompt()
  237.  
  238. #generate tasklist of source/destination pairs for threading
  239. import Queue
  240. q = Queue.Queue()
  241. q = generate_sync_tasks(q, l_ip, l_src_paths, l_dest_paths, action)
  242. log.info('Tasks queued: %i' % q.qsize())
  243.  
  244. max_threads = 20
  245.  
  246. import thread
  247. import threading
  248. import time
  249. for i in range(1,max_threads):
  250. t = threading.Thread(target=worker,name='Worker-%i' % (i))
  251. t.start()
  252.  
  253. while threading.activeCount() > 2:
  254. log.info('%i workers active.' % (len(threading.enumerate())-2) )
  255. if q.qsize() > 0:
  256. log.info('%i remaining tasks.' % q.qsize())
  257. time.sleep(30)
  258.  
  259. log.info('All tasks assigned, waiting for workers to finish.')
  260. q.join()
  261.  
  262. log.info('Program Completed. Terminating...')
  263. #exit
  264. closeprompt()
Advertisement
Add Comment
Please, Sign In to add comment