From: Călin-Andrei Burloiu Date: Thu, 9 Feb 2012 16:28:26 +0000 (+0200) Subject: cis: bugs fixed; start / stop / remove torrents commands implemented X-Git-Url: http://p2p-next.cs.pub.ro/gitweb/?p=living-lab-site.git;a=commitdiff_plain;h=9d5e17576e133645963b8e41083baf235c5cceba cis: bugs fixed; start / stop / remove torrents commands implemented --- diff --git a/cis/api/avhandling.py b/cis/api/avhandling.py deleted file mode 100644 index 27c9a5d..0000000 --- a/cis/api/avhandling.py +++ /dev/null @@ -1,198 +0,0 @@ -#!/usr/bin/env python - - -""" -Classes derived from BaseTranscoder and BaseThumbExtractor for transcoding of -videos and thumbnail extraction from videos using FFmpeg CLI program. -""" - -import base -import api_exceptions -import subprocess -import re -import os -import math - -class FFmpegTranscoder(base.BaseTranscoder): - """ - FFmpeg CLI API for video transcoding. - """ - - prog_bin = "ffmpeg" - - log_file = 'log/FFmpegTranscoder.log' - - containers = { - "avi": "avi", - "flv": "flv", - "mp4": "mp4", - "ogg": "ogg", - "webm": "webm", - "mpegts": "mpegts" - } - a_codecs = { - "mp3": "libmp3lame", - "vorbis": "libvorbis" - } - v_codecs = { - "h264": "libx264", - "theora": "libtheora", - "vp8": "libvpx" - } - - def _transcode(self, container, a_codec=None, v_codec=None, - a_bitrate=None, a_samplingrate=None, a_channels=None, - v_bitrate=None, v_framerate=None, v_resolution=None, v_dar=None): - - args = self.prog_bin + ' -y -i "' + self.input_file + '" -f ' + container - - # Audio - if a_codec != None: - args += ' -acodec ' + a_codec - if a_bitrate != None: - args += ' -ab ' + str(a_bitrate) - if a_samplingrate != None: - args += ' -ar ' + str(a_samplingrate) - if a_channels != None: - args += ' -ac ' + str(a_channels) - - # Video - if v_codec != None: - args += ' -vcodec ' + v_codec - # Video codec specific options. - if v_codec == 'libx264': - args += ' -vpre normal' - if v_bitrate != None: - args += ' -b ' + str(v_bitrate) - if v_framerate != None: - args += ' -r ' + str(v_framerate) - if v_resolution != None: - args += ' -s ' + v_resolution - if v_dar != None: - args += ' -aspect ' + v_dar - - # Output file. - args += ' "' + self.output_file + '"' - - # READ handler for process's output. - p = subprocess.Popen(args, shell=True, - stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - pipe = p.stdout - - # WRITE handler for logging. - log = open(self.log_file, 'w') - log.write(args + '\n') - - while True: - line = pipe.readline() - if len(line) == 0: - break - log.write(line) - - exit_code = p.wait() - if exit_code > 0: - raise api_exceptions.TranscodingException( \ - 'FFmpeg exited with code ' + str(exit_code) + '.') - - log.close() - - return self.output_file - - -class FFmpegThumbExtractor(base.BaseThumbExtractor): - """ - FFmpeg CLI API for video thumbnail extraction. - """ - - prog_bin = "ffmpeg" - - log_file = 'log/FFmpegThumbExtractor.log' - - def extract_thumb(self, seek_pos, resolution="120x90", index=0): - output_file = self.get_output_file_name(index) - - args = self.prog_bin + ' -y -i "' + self.input_file \ - + '" -f rawvideo -vcodec mjpeg' + (' -ss ' + str(seek_pos)) \ - + " -vframes 1 -an -s " + resolution + ' "' \ - + output_file + '"' - - # READ handler for process's output. - p = subprocess.Popen(args, shell=True, - stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - pipe = p.stdout - - # WRITE handler for logging. - log = open(self.log_file, 'w') - log.write(args + '\n') - - while True: - line = pipe.readline() - if len(line) == 0: - break - log.write(line) - - exit_code = p.wait() - if exit_code > 0: - raise api_exceptions.ThumbExtractionException( \ - 'FFmpeg exited with code ' + str(exit_code) + '.') - - # FFmpeg bug: when no key frame is found from seek_pos to the - # end of file an empty image file is created. - if os.path.getsize(output_file) == 0L: - os.unlink(output_file) - raise api_exceptions.ThumbExtractionException( \ - 'FFmpeg created an empty file.') - - def get_video_duration(self): - return FFprobeAVInfo.get_video_duration(self.input_file) - - -class FFprobeAVInfo(base.BaseAVInfo): - - prog_bin = "ffprobe" - - log_file = 'log/FFprobeAVInfo.log' - - @staticmethod - def get_video_duration(input_file, formated=False): - args = FFprobeAVInfo.prog_bin + ' -show_format "' \ - + input_file + '"' - - # READ handler for process's output. - p = subprocess.Popen(args, shell=True, - stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - pipe = p.stdout - - # WRITE handler for logging. - log = open(FFprobeAVInfo.log_file, 'w') - log.write(args + '\n') - - # Parse ffprobe's output. - while True: - line = pipe.readline() - if len(line) == 0: - break - log.write(line) - - # Search for the line which contains duration information. - m = re.match(r"duration=([\d\.]+)", line) - if m is not None: - seconds = float(m.group(1)) - if not formated: - return seconds - else: - seconds = math.floor(seconds) - minutes = math.floor(seconds / 60) - seconds = seconds % 60 - if minutes >= 60: - hours = math.floor(minutes / 60) - minutes = minutes % 60 - - return "%02d:%02d:%02d" % (hours, minutes, seconds) - else: - return "%02d:%02d" % (minutes, seconds) - - exit_code = p.wait() - if exit_code > 0: - raise api_exceptions.AVInfoException( \ - 'ffprobe exited with code ' + str(exit_code) + '.') diff --git a/cis/api/base.py b/cis/api/base.py index 0b30bc9..500aada 100644 --- a/cis/api/base.py +++ b/cis/api/base.py @@ -137,7 +137,8 @@ class BaseTranscoder: """ Translates container API name into external program identifier.""" if not self.containers.has_key(name) or self.containers[name] is None: - raise api_exceptions.NotImplementedException("Container " + name) + raise api_exceptions.NotImplementedException("Container " + name \ + + "not implemented") return self.containers[name] @@ -158,7 +159,8 @@ class BaseTranscoder: """ Translates audio codec API name into external program identifier.""" if not self.a_codecs.has_key(name) or self.a_codecs[name] is None: - raise api_exceptions.NotImplementedException("Audio Codec " + name) + raise api_exceptions.NotImplementedException("Audio Codec " + name \ + + "not implemented") return self.a_codecs[name] @@ -166,7 +168,8 @@ class BaseTranscoder: """ Translates video codec API name into external program identifier.""" if not self.v_codecs.has_key(name) or self.v_codecs[name] is None: - raise api_exceptions.NotImplementedException("Video Codec " + name) + raise api_exceptions.NotImplementedException("Video Codec " + name \ + + "not implemented") return self.v_codecs[name] diff --git a/cis/api/ffmpeg.py b/cis/api/ffmpeg.py index e69de29..27c9a5d 100644 --- a/cis/api/ffmpeg.py +++ b/cis/api/ffmpeg.py @@ -0,0 +1,198 @@ +#!/usr/bin/env python + + +""" +Classes derived from BaseTranscoder and BaseThumbExtractor for transcoding of +videos and thumbnail extraction from videos using FFmpeg CLI program. +""" + +import base +import api_exceptions +import subprocess +import re +import os +import math + +class FFmpegTranscoder(base.BaseTranscoder): + """ + FFmpeg CLI API for video transcoding. + """ + + prog_bin = "ffmpeg" + + log_file = 'log/FFmpegTranscoder.log' + + containers = { + "avi": "avi", + "flv": "flv", + "mp4": "mp4", + "ogg": "ogg", + "webm": "webm", + "mpegts": "mpegts" + } + a_codecs = { + "mp3": "libmp3lame", + "vorbis": "libvorbis" + } + v_codecs = { + "h264": "libx264", + "theora": "libtheora", + "vp8": "libvpx" + } + + def _transcode(self, container, a_codec=None, v_codec=None, + a_bitrate=None, a_samplingrate=None, a_channels=None, + v_bitrate=None, v_framerate=None, v_resolution=None, v_dar=None): + + args = self.prog_bin + ' -y -i "' + self.input_file + '" -f ' + container + + # Audio + if a_codec != None: + args += ' -acodec ' + a_codec + if a_bitrate != None: + args += ' -ab ' + str(a_bitrate) + if a_samplingrate != None: + args += ' -ar ' + str(a_samplingrate) + if a_channels != None: + args += ' -ac ' + str(a_channels) + + # Video + if v_codec != None: + args += ' -vcodec ' + v_codec + # Video codec specific options. + if v_codec == 'libx264': + args += ' -vpre normal' + if v_bitrate != None: + args += ' -b ' + str(v_bitrate) + if v_framerate != None: + args += ' -r ' + str(v_framerate) + if v_resolution != None: + args += ' -s ' + v_resolution + if v_dar != None: + args += ' -aspect ' + v_dar + + # Output file. + args += ' "' + self.output_file + '"' + + # READ handler for process's output. + p = subprocess.Popen(args, shell=True, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + pipe = p.stdout + + # WRITE handler for logging. + log = open(self.log_file, 'w') + log.write(args + '\n') + + while True: + line = pipe.readline() + if len(line) == 0: + break + log.write(line) + + exit_code = p.wait() + if exit_code > 0: + raise api_exceptions.TranscodingException( \ + 'FFmpeg exited with code ' + str(exit_code) + '.') + + log.close() + + return self.output_file + + +class FFmpegThumbExtractor(base.BaseThumbExtractor): + """ + FFmpeg CLI API for video thumbnail extraction. + """ + + prog_bin = "ffmpeg" + + log_file = 'log/FFmpegThumbExtractor.log' + + def extract_thumb(self, seek_pos, resolution="120x90", index=0): + output_file = self.get_output_file_name(index) + + args = self.prog_bin + ' -y -i "' + self.input_file \ + + '" -f rawvideo -vcodec mjpeg' + (' -ss ' + str(seek_pos)) \ + + " -vframes 1 -an -s " + resolution + ' "' \ + + output_file + '"' + + # READ handler for process's output. + p = subprocess.Popen(args, shell=True, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + pipe = p.stdout + + # WRITE handler for logging. + log = open(self.log_file, 'w') + log.write(args + '\n') + + while True: + line = pipe.readline() + if len(line) == 0: + break + log.write(line) + + exit_code = p.wait() + if exit_code > 0: + raise api_exceptions.ThumbExtractionException( \ + 'FFmpeg exited with code ' + str(exit_code) + '.') + + # FFmpeg bug: when no key frame is found from seek_pos to the + # end of file an empty image file is created. + if os.path.getsize(output_file) == 0L: + os.unlink(output_file) + raise api_exceptions.ThumbExtractionException( \ + 'FFmpeg created an empty file.') + + def get_video_duration(self): + return FFprobeAVInfo.get_video_duration(self.input_file) + + +class FFprobeAVInfo(base.BaseAVInfo): + + prog_bin = "ffprobe" + + log_file = 'log/FFprobeAVInfo.log' + + @staticmethod + def get_video_duration(input_file, formated=False): + args = FFprobeAVInfo.prog_bin + ' -show_format "' \ + + input_file + '"' + + # READ handler for process's output. + p = subprocess.Popen(args, shell=True, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + pipe = p.stdout + + # WRITE handler for logging. + log = open(FFprobeAVInfo.log_file, 'w') + log.write(args + '\n') + + # Parse ffprobe's output. + while True: + line = pipe.readline() + if len(line) == 0: + break + log.write(line) + + # Search for the line which contains duration information. + m = re.match(r"duration=([\d\.]+)", line) + if m is not None: + seconds = float(m.group(1)) + if not formated: + return seconds + else: + seconds = math.floor(seconds) + minutes = math.floor(seconds / 60) + seconds = seconds % 60 + if minutes >= 60: + hours = math.floor(minutes / 60) + minutes = minutes % 60 + + return "%02d:%02d:%02d" % (hours, minutes, seconds) + else: + return "%02d:%02d" % (minutes, seconds) + + exit_code = p.wait() + if exit_code > 0: + raise api_exceptions.AVInfoException( \ + 'ffprobe exited with code ' + str(exit_code) + '.') diff --git a/cis/api/file_transfer.py b/cis/api/file_transfer.py deleted file mode 100644 index 2f33eac..0000000 --- a/cis/api/file_transfer.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env python - -""" -Classes that facilitate file transfer (between Web Server and CIS). - -They may extend BaseFileTransferer class. -""" - -import sys -import ftplib -import base -import ftp_config -import socket -import api_exceptions -import os - - -class FTPFileTransferer(base.BaseFileTransferer): - """ - FTPS implementation for file transfering between Web Server and CIS. - """ - - ftp = None - - def __init__(self, local_path='', remote_path=''): - base.BaseFileTransferer.__init__(self, local_path, remote_path) - - self.ftp = ftplib.FTP_TLS(ftp_config.FTP_HOST, ftp_config.FTP_USER, - ftp_config.FTP_PASSWD, ftp_config.FTP_ACCT) - self.ftp.set_pasv(True) - - def get(self, files): - try: - self.ftp.cwd(self.remote_path) - except ftplib.error_perm as e: - raise api_exceptions.FileTransferException( \ - "Could not change remote directory '%s': %s" \ - % (self.remote_path, repr(e))) - - - for crt_fn in files: - local_fn = os.path.join(self.local_path, crt_fn) - remote_fn = os.path.join(self.remote_path, crt_fn) - try: - file_local = open(local_fn, 'wb') - except IOError as e: - raise api_exceptions.FileTransferException( \ - "Could not open local file '%s' for writing: %s" \ - % (local_fn, repr(e))) - - try: - self.ftp.retrbinary('RETR %s' % crt_fn, file_local.write) - file_local.close() - except ftplib.error_perm as e: - raise api_exceptions.FileTransferException( \ - "Could not get file '%s' from Web Server: %s" \ - % (remote_fn, repr(e))) - - def put(self, files): - try: - self.ftp.cwd(self.remote_path) - except ftplib.error_perm as e: - raise api_exceptions.FileTransferException( \ - "Could not change remote directory '%s': %s" \ - % (self.remote_path, repr(e))) - - for crt_fn in files: - local_fn = os.path.join(self.local_path, crt_fn) - - try: - file_local = open(local_fn, 'rb') - except IOError as e: - raise api_exceptions.FileTransferException( \ - "Could not open local file '%s' for reading: %s" \ - % (local_fn, repr(e))) - - try: - self.ftp.storbinary('STOR %s' % crt_fn, file_local) - file_local.close() - except ftplib.error_perm as e: - raise api_exceptions.FileTransferException( \ - "Could not put file '%s' to Web Server: %s" \ - % (local_fn, repr(e))) - - def close(self): - if self.ftp is not None: - try: - self.ftp.quit() - except: - pass diff --git a/cis/api/ftp.py b/cis/api/ftp.py index e69de29..567978f 100644 --- a/cis/api/ftp.py +++ b/cis/api/ftp.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python + +""" +Classes that facilitate file transfer (between Web Server and CIS). + +They may extend BaseFileTransferer class. +""" + +import sys +import ftplib +import base +import ftp_config +import socket +import api_exceptions +import os + +import logger + + +class FTPFileTransferer(base.BaseFileTransferer): + """ + FTPS implementation for file transfering between Web Server and CIS. + """ + + ftp = None + + def __init__(self, local_path='', remote_path=''): + base.BaseFileTransferer.__init__(self, local_path, remote_path) + + self.ftp = ftplib.FTP_TLS(ftp_config.FTP_HOST, ftp_config.FTP_USER, + ftp_config.FTP_PASSWD, ftp_config.FTP_ACCT) + self.ftp.set_pasv(True) + + def get(self, files): + try: + self.ftp.cwd(self.remote_path) + except ftplib.error_perm as e: + raise api_exceptions.FileTransferException( \ + "Could not change remote directory '%s': %s" \ + % (self.remote_path, repr(e))) + + + for crt_fn in files: + local_fn = os.path.join(self.local_path, crt_fn) + remote_fn = os.path.join(self.remote_path, crt_fn) + try: + file_local = open(local_fn, 'wb') + except IOError as e: + raise api_exceptions.FileTransferException( \ + "Could not open local file '%s' for writing: %s" \ + % (local_fn, repr(e))) + + try: + self.ftp.retrbinary('RETR %s' % crt_fn, file_local.write) + file_local.close() + except ftplib.error_perm as e: + raise api_exceptions.FileTransferException( \ + "Could not get file '%s' from Web Server: %s" \ + % (remote_fn, repr(e))) + + def put(self, files): + try: + self.ftp.cwd(self.remote_path) + except ftplib.error_perm as e: + raise api_exceptions.FileTransferException( \ + "Could not change remote directory '%s': %s" \ + % (self.remote_path, repr(e))) + + for crt_fn in files: + local_fn = os.path.join(self.local_path, crt_fn) + + try: + file_local = open(local_fn, 'rb') + except IOError as e: + raise api_exceptions.FileTransferException( \ + "Could not open local file '%s' for reading: %s" \ + % (local_fn, repr(e))) + + try: + self.ftp.storbinary('STOR %s' % crt_fn, file_local) + file_local.close() + except ftplib.error_perm as e: + raise api_exceptions.FileTransferException( \ + "Could not put file '%s' to Web Server: %s" \ + % (local_fn, repr(e))) + + def close(self): + if self.ftp is not None: + try: + self.ftp.quit() + except: + pass diff --git a/cis/api/ftp_config.py b/cis/api/ftp_config.py index 551cd7d..e00e3fe 100644 --- a/cis/api/ftp_config.py +++ b/cis/api/ftp_config.py @@ -2,7 +2,7 @@ Configuration file for FTPFileTransferer class. """ -FTP_HOST = "localhost" -FTP_USER = "calinburloiu" -FTP_PASSWD = "Ps1st1h14_" +FTP_HOST = "koala.cs.pub.ro" +FTP_USER = "ftp-p2p-next" +FTP_PASSWD = "student" FTP_ACCT = "" diff --git a/cis/bt.py b/cis/bt.py index 9281876..74d43ab 100644 --- a/cis/bt.py +++ b/cis/bt.py @@ -49,9 +49,10 @@ class BitTorrent: self.session = Session(sscfg) - def start_download(self, torrent, output_dir='.'): + def start_torrent(self, torrent, output_dir='.'): """ Download (leech or seed) a file via BitTorrent. + The code is adapted from Next-Share's 'BaseLib/Tools/cmdlinedl.py'. @param torrent .torrent file or URL @@ -80,3 +81,23 @@ class BitTorrent: #else: #logger.log_msg('download of torrent "%s" already started' \ #% torrent, logger.LOG_LEVEL_DEBUG) + + def stop_torrent(self, torrent, remove_content=False): + """ + Stop leeching or seeding a file via BitTorrent. + + !!! Only tested with torrents started with .tstream files. Not tested + for torrents started with URLs. + + @param torrent .torrent file or URL + @param remove_content removes downloaded file + """ + + downloads = self.session.get_downloads() + + for dl in downloads: + tdef = dl.get_def() + if torrent.find(tdef.get_name()) == 0: + self.session.remove_download(dl, remove_content) + logger.log_msg('torrent "%s" stopped' % torrent) + break diff --git a/cis/cisd.py b/cis/cis.py similarity index 71% rename from cis/cisd.py rename to cis/cis.py index 2f39a6e..f88aad5 100755 --- a/cis/cisd.py +++ b/cis/cis.py @@ -46,7 +46,7 @@ class CIWorker(threading.Thread): logger.log_msg('#%s: transfering in...' % self.job_id) file_transfer = config.FILE_TRANSFERER_CLASS( \ - config.RAW_VIDEOS_PATH, config.WS_UPLOAD_PATH) + config.RAW_VIDEOS_PATH, config.WS_UPLOAD_PATH) file_transfer.get([raw_video]) file_transfer.close() @@ -120,7 +120,7 @@ class CIWorker(threading.Thread): output_file = output_file[(output_file.rindex('/') + 1):] # * SEED TORRENTS - Server.bit_torrent.start_download( \ + Server.bit_torrent.start_torrent( \ os.path.join(config.TORRENTS_PATH, output_file), config.MEDIA_PATH) @@ -155,16 +155,32 @@ class CIWorker(threading.Thread): self.job_id = job['id'] # * TRANSFER RAW VIDEO IN - self.transfer_in(job['raw_video']) + try: + self.transfer_in(job['raw_video']) + except Exception as e: + logger.log_msg('#%s: error while transferring in: %s' \ + % (job['id'], str(e)), logger.LOG_LEVEL_FATAL) + continue # * TRANSCODE RAW VIDEO - self.transcode(job['raw_video'], job['name'], \ - job['transcode_configs']) + try: + self.transcode(job['raw_video'], job['name'], \ + job['transcode_configs']) + except Exception as e: + logger.log_msg('#%s: error while transcoding: %s' \ + % (job['id'], str(e)), logger.LOG_LEVEL_FATAL) + continue # * EXTRACT THUMBNAIL IMAGES if job['thumbs'] != 0: - self.extract_thumbs(job['raw_video'], job['name'], \ - job['thumbs']) + try: + self.extract_thumbs(job['raw_video'], job['name'], \ + job['thumbs']) + except Exception as e: + logger.log_msg( \ + '#%s: error while extracting thumbnail images: %s' \ + % (job['id'], str(e)), logger.LOG_LEVEL_FATAL) + continue # * CREATE TORRENTS AND START SEEDING OF TRANSCODED VIDEOS self.seed(job['transcode_configs']) @@ -182,10 +198,15 @@ class CIWorker(threading.Thread): thumb_files = fnmatch.filter(files, job['name'] + "_*") # * TRANSFER TORRENTS AND THUMBNAIL IMAGES OUT - self.transfer_out(torrent_files, config.TORRENTS_PATH, \ - config.WS_TORRENTS_PATH) - self.transfer_out(thumb_files, config.THUMBS_PATH, \ - config.WS_THUMBS_PATH) + try: + self.transfer_out(torrent_files, config.TORRENTS_PATH, \ + config.WS_TORRENTS_PATH) + self.transfer_out(thumb_files, config.THUMBS_PATH, \ + config.WS_THUMBS_PATH) + except Exception as e: + logger.log_msg('#%s: error while transferring out: %s' \ + % (job['id'], str(e)), logger.LOG_LEVEL_FATAL) + continue # * CLEANUP RAW VIDEOS AND THUMBNAIL IMAGES self.remove_files([ job['raw_video'] ], config.RAW_VIDEOS_PATH) @@ -215,6 +236,8 @@ class Server: resp = {"load": Server.load} web.header('Content-Type', 'application/json') return json.dumps(resp) + #elif request == 'shutdown': + #sys.exit(0) elif request == 'test': return '' else: @@ -240,26 +263,55 @@ class Server: Server.queue.put(data) return 'Job submitted.' + elif request == 'start_torrents': + # Read JSON parameters. + json_data = web.data() + data = json.loads(json_data) + + # TODO Verify data + Server.start_torrents(data) + elif request == 'stop_torrents': + # Read JSON parameters. + json_data = web.data() + data = json.loads(json_data) + + # TODO Verify data + Server.stop_torrents(data) + elif request == 'remove_torrents': + # Read JSON parameters. + json_data = web.data() + data = json.loads(json_data) + + # TODO Verify data + Server.stop_torrents(data, True) else: web.badrequest() return "" @staticmethod - def start_downloads(): + def start_torrents(torrents=None): + """ + Scans torrent path for files in order to start download for the files + that are not already started. + """ + # All torrent files. - files = [f for f in os.listdir(config.TORRENTS_PATH) \ - if os.path.isfile(os.path.join( \ - config.TORRENTS_PATH, f))] - torrent_files = fnmatch.filter(files, "*.tstream") - - for torrent_file in torrent_files: - Server.bit_torrent.start_download( \ - torrent_file, + if torrents == None: + files = [f for f in os.listdir(config.TORRENTS_PATH) \ + if os.path.isfile(os.path.join( \ + config.TORRENTS_PATH, f))] + torrents = fnmatch.filter(files, "*.tstream") + + for torrent_file in torrents: + Server.bit_torrent.start_torrent( \ + os.path.join(config.TORRENTS_PATH, torrent_file), config.MEDIA_PATH) - - t = threading.Timer(config.START_DOWNLOADS_INTERVAL, \ - Server.start_downloads) - t.start() + + @staticmethod + def stop_torrents(torrents, remove_content=False): + for torrent_file in torrents: + Server.bit_torrent.stop_torrent( \ + torrent_file, remove_content) def authenticate(self, username, password): if not config.SECURITY: @@ -278,7 +330,11 @@ if __name__ == '__main__': Server.queue = Queue() Server.load = 0 - Server.start_downloads() + Server.start_torrents() + t = threading.Timer(config.START_DOWNLOADS_INTERVAL, \ + Server.start_torrents) + t.daemon = True + t.start() # Worker thread. ci_worker = CIWorker() diff --git a/cis/config.py b/cis/config.py index c68d05c..094e552 100644 --- a/cis/config.py +++ b/cis/config.py @@ -3,8 +3,8 @@ import logger # Make here all necessary imports required for API classes. -from api import avhandling -from api import file_transfer +from api import ffmpeg +from api import ftp # === GENERAL CONFIGURATIONS === @@ -15,34 +15,35 @@ START_DOWNLOADS_INTERVAL = 24 * 3600.0 # Once a day # === FILE TRANSFER CONFIGURATIONS === # Path from the Web Server where the raw input video file is stored. -WS_UPLOAD_PATH = 'tmp/data/upload' +WS_UPLOAD_PATH = 'devel/data/upload' # Path from the Web Server where the output torrent files will be stored. -WS_TORRENTS_PATH = 'tmp/data/torrents' +WS_TORRENTS_PATH = 'devel/data/torrents' # Path from the Web Server where the output thumbnail image files will be # stored. -WS_THUMBS_PATH = 'tmp/data/thumbs' +WS_THUMBS_PATH = 'devel/data/thumbs' # === BITTORRENT CONFIGURATIONS === #BT_TRACKER = "http://p2p-next-10.grid.pub.ro:6969/announce" -BT_TRACKER = 'http://localhost:6969/announce' +BT_TRACKER = 'http://p2p-next-10.grid.pub.ro:6969/announce' RAW_VIDEOS_PATH = 'tmp/raw' MEDIA_PATH = 'tmp/media' THUMBS_PATH = 'tmp/thumbs' -TORRENTS_PATH = 'tmp/torrents' # In a distributed file system for multi-CIS +# In a distributed file system for multi-CIS. +TORRENTS_PATH = '/home/p2p/export/p2p-tube/torrents' # === EXTERNAL PROGRAMS API CLASSES === # API class for a prgram which retrives audio/video information, like duration. -AVINFO_CLASS = avhandling.FFprobeAVInfo +AVINFO_CLASS = ffmpeg.FFprobeAVInfo # API class for a prgram which transcodes an audio/video file. -TRANSCODER_CLASS = avhandling.FFmpegTranscoder +TRANSCODER_CLASS = ffmpeg.FFmpegTranscoder # API class for a prgram which extracts thumbnail images from a file. -THUMB_EXTRACTOR_CLASS = avhandling.FFmpegThumbExtractor +THUMB_EXTRACTOR_CLASS = ffmpeg.FFmpegThumbExtractor # API class for a prgram which transfers files between Web Server and CIS. -FILE_TRANSFERER_CLASS = file_transfer.FTPFileTransferer +FILE_TRANSFERER_CLASS = ftp.FTPFileTransferer # === EXTERNAL PROGRAMS BINARY FILES === diff --git a/cis/post-json.sh b/cis/post-json.sh index eac61f7..1132520 100755 --- a/cis/post-json.sh +++ b/cis/post-json.sh @@ -6,5 +6,6 @@ if [ $# -ne 1 ]; then fi JSON_FILE="$1" +CIS_URL="http://p2p-next-02.grid.pub.ro:8080/" -curl -H application/json --data-binary @"$JSON_FILE" http://localhost:8080/ingest_content +curl -H 'Content-Type: application/json' --data-binary @"$JSON_FILE" ${CIS_URL}ingest_content