def get_virus_record_by_id(session, vid): try: q = session.query(VirusFile).filter(VirusFile.vid == vid) return q.first() except Exception as e: logger.warning('Failed to get virus record by id: %s.', e) return None
def add_virus_record(self, records): try: self.edb_session.add_all(VirusFile(repo_id, commit_id, file_path, 0) \ for repo_id, commit_id, file_path in records) self.edb_session.commit() self.edb_session.remove() return 0 except Exception as e: logger.warning('Failed to add virus records to db: %s.', e) return -1
def handle_virus_record(session, vid): try: q = session.query(VirusFile).filter(VirusFile.vid == vid) r = q.first() r.has_handle = 1 session.commit() return 0 except Exception as e: logger.warning('Failed to handle virus record: %s.', e) return -1
def run(self): while True: try: task = self.task_queue.get() if task is None: break self.do_work(task) except Exception as e: logger.warning('Failed to execute task: %s' % e) finally: self.task_queue.task_done()
def update_vscan_record(self, repo_id, scan_commit_id): try: q = self.edb_session.query(VirusScanRecord).filter( VirusScanRecord.repo_id == repo_id) r = q.first() if not r: vrecord = VirusScanRecord(repo_id, scan_commit_id) self.edb_session.add(vrecord) else: r.scan_commit_id = scan_commit_id self.edb_session.commit() self.edb_session.remove() except Exception as e: logger.warning('Failed to update virus scan record from db: %s.', e)
def get_repo_list(self): repo_list = [] try: self.sdb_cursor.execute( 'select r.repo_id, b.commit_id from Repo r, Branch b ' 'where r.repo_id = b.repo_id and b.name = "master" and ' 'r.repo_id not in (select repo_id from VirtualRepo)') rows = self.sdb_cursor.fetchall() for row in rows: repo_id, commit_id = row scan_commit_id = self.get_scan_commit_id(repo_id) repo_list.append((repo_id, commit_id, scan_commit_id)) except Exception as e: logger.warning('Failed to fetch repo list from db: %s.', e) repo_list = None return repo_list
def get_virus_record(session, repo_id, start, limit): if start < 0: logger.error('start must be non-negative') raise RuntimeError('start must be non-negative') if limit <= 0: logger.error('limit must be positive') raise RuntimeError('limit must be positive') try: q = session.query(VirusFile) if repo_id: q = q.filter(VirusFile.repo_id == repo_id) q = q.slice(start, start + limit) return q.all() except Exception as e: logger.warning('Failed to get virus record from db: %s.', e) return None
def scan_file_virus(self, repo_id, file_id, file_path): try: tfd, tpath = tempfile.mkstemp() seafile = fs_mgr.load_seafile(repo_id, 1, file_id) for blk_id in seafile.blocks: os.write(tfd, block_mgr.load_block(repo_id, 1, blk_id)) with open(os.devnull, 'w') as devnull: ret_code = subprocess.call([self.settings.scan_cmd, tpath], stdout=devnull, stderr=devnull) return self.parse_scan_result(ret_code) except Exception as e: logger.warning('Virus scan for file %s encounter error: %s.', file_path, e) return -1 finally: if tfd > 0: os.close(tfd) os.unlink(tpath)
def scan_virus(self, scan_task): try: sroot_id = None hroot_id = None if scan_task.scan_commit_id: sroot_id = commit_mgr.get_commit_root_id( scan_task.repo_id, 1, scan_task.scan_commit_id) if scan_task.head_commit_id: hroot_id = commit_mgr.get_commit_root_id( scan_task.repo_id, 1, scan_task.head_commit_id) differ = CommitDiffer(scan_task.repo_id, 1, sroot_id, hroot_id) scan_files = differ.diff() if len(scan_files) == 0: logger.debug('No change occur for repo %.8s, skip virus scan.', scan_task.repo_id) self.db_oper.update_vscan_record(scan_task.repo_id, scan_task.head_commit_id) return else: logger.info('Start to scan virus for repo %.8s.', scan_task.repo_id) vnum = 0 nvnum = 0 nfailed = 0 vrecords = [] for scan_file in scan_files: fpath, fid, fsize = scan_file if not self.should_scan_file(fpath, fsize): continue ret = self.scan_file_virus(scan_task.repo_id, fid, fpath) if ret == 0: logger.debug('File %s virus scan by %s: OK.', fpath, self.settings.scan_cmd) nvnum += 1 elif ret == 1: logger.info('File %s virus scan by %s: Found virus.', fpath, self.settings.scan_cmd) vnum += 1 fpath = fpath if isinstance( fpath, unicode) else fpath.decode('utf-8') vrecords.append( (scan_task.repo_id, scan_task.head_commit_id, fpath)) else: logger.debug('File %s virus scan by %s: Failed.', fpath, self.settings.scan_cmd) nfailed += 1 if nfailed == 0: ret = 0 if len(vrecords) > 0: ret = self.db_oper.add_virus_record(vrecords) if ret == 0 and self.settings.enable_send_mail: self.send_email(vrecords) if ret == 0: self.db_oper.update_vscan_record(scan_task.repo_id, scan_task.head_commit_id) logger.info( 'Virus scan for repo %.8s finished: %d virus, %d non virus, %d failed.', scan_task.repo_id, vnum, nvnum, nfailed) except Exception as e: logger.warning('Failed to scan virus for repo %.8s: %s.', scan_task.repo_id, e)