From 45ee8a71d6ddceb7257988b7f4ccfd314bac050b Mon Sep 17 00:00:00 2001 From: Calin-Andrei Burloiu Date: Fri, 25 Nov 2011 18:08:23 +0200 Subject: [PATCH] CIS: ftp transfer API implemented --- .../api_exceptions.py} | 3 + cis/api/avhandling.py | 10 +-- cis/api/base.py | 54 ++++++++++++-- cis/api/file_transfer.py | 73 +++++++++++++++++++ cis/api/ftp_config.py | 8 ++ cis/cisd.py | 13 ++-- cis/config.py | 3 +- 7 files changed, 148 insertions(+), 16 deletions(-) rename cis/{cis_exceptions.py => api/api_exceptions.py} (87%) create mode 100644 cis/api/file_transfer.py create mode 100644 cis/api/ftp_config.py diff --git a/cis/cis_exceptions.py b/cis/api/api_exceptions.py similarity index 87% rename from cis/cis_exceptions.py rename to cis/api/api_exceptions.py index 33c314f..fa03c33 100644 --- a/cis/cis_exceptions.py +++ b/cis/api/api_exceptions.py @@ -16,3 +16,6 @@ class TranscodingException(Exception): class ThumbExtractionException(Exception): pass + +class FileTransferException(Exception): + pass diff --git a/cis/api/avhandling.py b/cis/api/avhandling.py index a64f7f2..8d04272 100644 --- a/cis/api/avhandling.py +++ b/cis/api/avhandling.py @@ -7,7 +7,7 @@ videos and thumbnail extraction from videos using FFmpeg CLI program. """ import base -import cis_exceptions +import api_exceptions import subprocess import re import os @@ -90,7 +90,7 @@ class FFmpegTranscoder(base.BaseTranscoder): exit_code = p.wait() if exit_code > 0: - raise cis_exceptions.TranscodingException( \ + raise api_exceptions.TranscodingException( \ 'FFmpeg exited with code ' + str(exit_code) + '.') log.close() @@ -131,14 +131,14 @@ class FFmpegThumbExtractor(base.BaseThumbExtractor): exit_code = p.wait() if exit_code > 0: - raise cis_exceptions.ThumbExtractionException( \ + 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 cis_exceptions.ThumbExtractionException( \ + raise api_exceptions.ThumbExtractionException( \ 'FFmpeg created an empty file.') def get_video_duration(self): @@ -163,6 +163,6 @@ class FFmpegThumbExtractor(base.BaseThumbExtractor): exit_code = p.wait() if exit_code > 0: - raise cis_exceptions.ThumbExtractionException( \ + raise api_exceptions.ThumbExtractionException( \ 'FFmpeg exited with code ' + str(exit_code) + '.') diff --git a/cis/api/base.py b/cis/api/base.py index 8ea2cd3..a57d96d 100644 --- a/cis/api/base.py +++ b/cis/api/base.py @@ -4,7 +4,7 @@ Base classes for the external programs API. """ -import cis_exceptions +import api_exceptions import re import cis_util import random @@ -131,7 +131,7 @@ class BaseTranscoder: """ Translates container API name into external program identifier.""" if not self.containers.has_key(name) or self.containers[name] is None: - raise cis_exceptions.NotImplementedException("Container " + name) + raise api_exceptions.NotImplementedException("Container " + name) return self.containers[name] @@ -152,7 +152,7 @@ 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 cis_exceptions.NotImplementedException("Audio Codec " + name) + raise api_exceptions.NotImplementedException("Audio Codec " + name) return self.a_codecs[name] @@ -160,7 +160,7 @@ 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 cis_exceptions.NotImplementedException("Video Codec " + name) + raise api_exceptions.NotImplementedException("Video Codec " + name) return self.v_codecs[name] @@ -222,7 +222,7 @@ class BaseThumbExtractor: thumb_extracted = True try: self.extract_thumb(seek_pos, resolution, index) - except cis_exceptions.ThumbExtractionException as e: + except api_exceptions.ThumbExtractionException as e: thumb_extracted = False if thumb_extracted: @@ -243,3 +243,47 @@ class BaseThumbExtractor: output_file_name = self.dest_path + self.name \ + '_t' + ("%02d" % index) + '.jpg' return output_file_name + + +class BaseFileTransferer: + """ + Ensures file transfer from the Web Server to the CIS (here). + + Several implementations can be done by extending this class for + file transfer protocol such as FTP, SCP, RSYNC, HTTP etc. + """ + + local_path = '' + remote_path = '' + + def __init__(self, local_path='', remote_path=''): + """ Initialize by setting local and remote paths for file transfer. """ + self.local_path = local_path + self.remote_path = remote_path + + def __del__(self): + self.close() + + def get(self, files): + """ + Transfers files locally from the Web Server. + + files: a list of file name strings + """ + pass + + def put(self, files): + """ + Transfers files from the Web Server locally. + + files: a list of file name strings + """ + pass + + def close(self): + """ + This method should be called when the instance is no longer required. + + Class's destructor calls this method. + """ + pass diff --git a/cis/api/file_transfer.py b/cis/api/file_transfer.py new file mode 100644 index 0000000..5a6ff01 --- /dev/null +++ b/cis/api/file_transfer.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python + +""" +Classes that facilitate file transfer (between Web Server and CIS). + +They may extend BaseFileTransferer class. +""" + +import sys +from ftplib import FTP_TLS +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 = 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): + for crt_file in files: + crt_file = os.path.join(self.local_path, crt_file) + try: + file_local = open(crt_file, 'wb') + except IOError as e: + raise api_exceptions.FileTransferException( \ + "Could not open local file '%s' for writing: %s" \ + % (crt_file, repr(e))) + + try: + self.ftp.cwd(self.remote_path) + self.ftp.retrbinary('RETR %s' % crt_file, 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" \ + % (crt_file, repr(e))) + + def put(self, files): + for crt_file in files: + crt_file = os.path.join(self.local_path, crt_file) + + try: + file_local = open(crt_file, 'rb') + except IOError as e: + raise api_exceptions.FileTransferException( \ + "Could not open local file '%s' for reading: %s" \ + % (crt_file, repr(e))) + + try: + self.ftp.cwd(self.remote_path) + self.ftp.storbinary('STOR %s' % crt_file, file_local) + file_local.close() + except ftplib.error_perm as e: + raise api_exceptions.FileTransferException( \ + "Could not get file '%s' from Web Server: %s" \ + % (crt_file, repr(e))) + + def close(self): + if self.ftp is not None: + self.ftp.quit() diff --git a/cis/api/ftp_config.py b/cis/api/ftp_config.py new file mode 100644 index 0000000..551cd7d --- /dev/null +++ b/cis/api/ftp_config.py @@ -0,0 +1,8 @@ +""" +Configuration file for FTPFileTransferer class. +""" + +FTP_HOST = "localhost" +FTP_USER = "calinburloiu" +FTP_PASSWD = "Ps1st1h14_" +FTP_ACCT = "" diff --git a/cis/cisd.py b/cis/cisd.py index cb22887..84ea512 100755 --- a/cis/cisd.py +++ b/cis/cisd.py @@ -2,14 +2,17 @@ import sys import config -import cis_exceptions if __name__ == '__main__': # transcoder = config.TRANSCODER_CLASS(sys.argv[1]) # transcoder.transcode('webm', "vorbis", "vp8", a_bitrate="128k", a_samplingrate=22050, a_channels=2, v_bitrate="256k", v_framerate=15, v_resolution="320x240", v_dar="4:3") - thumb_extractor = config.THUMB_EXTRACTOR_CLASS(sys.argv[1]) - #print thumb_extractor.get_video_duration() - #thumb_extractor.extract_random_thumb() - print thumb_extractor.extract_summary_thumbs(5) +# thumb_extractor = config.THUMB_EXTRACTOR_CLASS(sys.argv[1]) +# #print thumb_extractor.get_video_duration() +# #thumb_extractor.extract_random_thumb() +# print thumb_extractor.extract_summary_thumbs(5) + + file_transfer = config.FILE_TRANSFERER_CLASS() + file_transfer.get(['vim_config.tar.gz']) + file_transfer.close() diff --git a/cis/config.py b/cis/config.py index 7b01397..d71d4e3 100644 --- a/cis/config.py +++ b/cis/config.py @@ -2,12 +2,13 @@ # Make here all necessary imports required for API classes. from api import avhandling +from api import file_transfer # External programs API classes. TRANSCODER_CLASS = avhandling.FFmpegTranscoder THUMB_EXTRACTOR_CLASS = avhandling.FFmpegThumbExtractor BT_CLIENT_CLASS = None # TODO -FILE_TRANSFERER_CLASS = None # TODO +FILE_TRANSFERER_CLASS = file_transfer.FTPFileTransferer # External programs binary file. None means default. TRANSCODER_BIN = None -- 2.20.1