Merge branch 'devel' of dev.sourcefabric.org:airtime into devel

This commit is contained in:
James 2012-07-05 18:25:17 -04:00
commit 68089790ff
4 changed files with 42 additions and 52 deletions

View file

@ -77,10 +77,8 @@ class AirtimeMediaMonitorBootstrap():
dir -- pathname of the directory dir -- pathname of the directory
""" """
def sync_database_to_filesystem(self, dir_id, dir): def sync_database_to_filesystem(self, dir_id, dir):
# TODO: is this line even necessary?
dir = os.path.normpath(dir)+"/" dir = os.path.normpath(dir)+"/"
""" """
set to hold new and/or modified files. We use a set to make it ok if files are added set to hold new and/or modified files. We use a set to make it ok if files are added
twice. This is because some of the tests for new files return result sets that are not twice. This is because some of the tests for new files return result sets that are not
@ -94,24 +92,23 @@ class AirtimeMediaMonitorBootstrap():
for file in files['files']: for file in files['files']:
db_known_files_set.add(file) db_known_files_set.add(file)
all_files = self.mmc.scan_dir_for_new_files(dir) all_files = self.mmc.clean_dirty_file_paths( self.mmc.scan_dir_for_new_files(dir) )
all_files_set = set() all_files_set = set()
for file_path in all_files: for file_path in all_files:
file_path = file_path.strip(" \n") if self.config.problem_directory not in file_path:
if len(file_path) > 0 and self.config.problem_directory not in file_path:
all_files_set.add(file_path[len(dir):]) all_files_set.add(file_path[len(dir):])
# if dir doesn't exists, update db # if dir doesn't exists, update db
if not os.path.exists(dir): if not os.path.exists(dir):
self.pe.handle_watched_dir_missing(dir) self.pe.handle_stdout_files(dir)
if os.path.exists(self.mmc.timestamp_file): if os.path.exists(self.mmc.timestamp_file):
"""find files that have been modified since the last time media-monitor process started.""" """find files that have been modified since the last time media-monitor process started."""
time_diff_sec = time.time() - os.path.getmtime(self.mmc.timestamp_file) time_diff_sec = time.time() - os.path.getmtime(self.mmc.timestamp_file)
command = "find '%s' -iname '*.ogg' -o -iname '*.mp3' -type f -readable -mmin -%d" % (dir, time_diff_sec/60+1) command = self.mmc.find_command(directory=dir, extra_arguments=("-type f -readable -mmin -%d" % (time_diff_sec/60+1)))
else: else:
command = "find '%s' -iname '*.ogg' -o -iname '*.mp3' -type f -readable" % dir command = self.mmc.find_command(directory=dir, extra_arguments="-type f -readable")
self.logger.debug(command) self.logger.debug(command)
stdout = self.mmc.exec_command(command) stdout = self.mmc.exec_command(command)
@ -120,12 +117,11 @@ class AirtimeMediaMonitorBootstrap():
self.logger.error("Unrecoverable error when syncing db to filesystem.") self.logger.error("Unrecoverable error when syncing db to filesystem.")
return return
new_files = stdout.splitlines() new_files = self.mmc.clean_dirty_file_paths(stdout.splitlines())
new_and_modified_files = set() new_and_modified_files = set()
for file_path in new_files: for file_path in new_files:
file_path = file_path.strip(" \n") if self.config.problem_directory not in file_path:
if len(file_path) > 0 and self.config.problem_directory not in file_path:
new_and_modified_files.add(file_path[len(dir):]) new_and_modified_files.add(file_path[len(dir):])
""" """
@ -156,16 +152,12 @@ class AirtimeMediaMonitorBootstrap():
self.logger.debug(full_file_path) self.logger.debug(full_file_path)
self.pe.handle_removed_file(False, full_file_path) self.pe.handle_removed_file(False, full_file_path)
for file_path in new_files_set:
self.logger.debug("new file") for file_set, debug_message, handle_attribute in [(new_files_set, "new file", "handle_created_file"),
(modified_files_set, "modified file", "handle_modified_file")]:
for file_path in file_set:
self.logger.debug(debug_message)
full_file_path = os.path.join(dir, file_path) full_file_path = os.path.join(dir, file_path)
self.logger.debug(full_file_path) self.logger.debug(full_file_path)
if os.path.exists(full_file_path): if os.path.exists(full_file_path):
self.pe.handle_created_file(False, full_file_path, os.path.basename(full_file_path)) getattr(self.pe,handle_attribute)(False,full_file_path, os.path.basename(full_file_path))
for file_path in modified_files_set:
self.logger.debug("modified file")
full_file_path = "%s%s" % (dir, file_path)
self.logger.debug(full_file_path)
if os.path.exists(full_file_path):
self.pe.handle_modified_file(False, full_file_path, os.path.basename(full_file_path))

View file

@ -101,16 +101,12 @@ class AirtimeNotifier(Notifier):
self.bootstrap.sync_database_to_filesystem(new_storage_directory_id, new_storage_directory) self.bootstrap.sync_database_to_filesystem(new_storage_directory_id, new_storage_directory)
self.config.storage_directory = os.path.normpath(new_storage_directory) self.config.storage_directory = os.path.normpath(new_storage_directory)
self.config.imported_directory = os.path.normpath(new_storage_directory + '/imported') self.config.imported_directory = os.path.normpath(os.path.join(new_storage_directory, '/imported'))
self.config.organize_directory = os.path.normpath(new_storage_directory + '/organize') self.config.organize_directory = os.path.normpath(os.path.join(new_storage_directory, '/organize'))
self.mmc.ensure_is_dir(self.config.storage_directory) for directory in [self.config.storage_directory, self.config.imported_directory, self.config.organize_directory]:
self.mmc.ensure_is_dir(self.config.imported_directory) self.mmc.ensure_is_dir(directory)
self.mmc.ensure_is_dir(self.config.organize_directory) self.mmc.is_readable(directory, True)
self.mmc.is_readable(self.config.storage_directory, True)
self.mmc.is_readable(self.config.imported_directory, True)
self.mmc.is_readable(self.config.organize_directory, True)
self.watch_directory(new_storage_directory) self.watch_directory(new_storage_directory)
elif m['event_type'] == "file_delete": elif m['event_type'] == "file_delete":
@ -146,7 +142,7 @@ class AirtimeNotifier(Notifier):
mode = event['mode'] mode = event['mode']
md = {} md = {}
md['MDATA_KEY_FILEPATH'] = filepath md['MDATA_KEY_FILEPATH'] = os.path.normpath(filepath)
if 'data' in event: if 'data' in event:
file_md = event['data'] file_md = event['data']

View file

@ -16,14 +16,26 @@ import pyinotify
class MediaMonitorCommon: class MediaMonitorCommon:
timestamp_file = "/var/tmp/airtime/media-monitor/last_index" timestamp_file = "/var/tmp/airtime/media-monitor/last_index"
supported_file_formats = ['mp3', 'ogg']
def __init__(self, airtime_config, wm=None): def __init__(self, airtime_config, wm=None):
self.supported_file_formats = ['mp3', 'ogg']
self.logger = logging.getLogger() self.logger = logging.getLogger()
self.config = airtime_config self.config = airtime_config
self.md_manager = AirtimeMetadata() self.md_manager = AirtimeMetadata()
self.wm = wm self.wm = wm
def clean_dirty_file_paths(self, dirty_files):
""" clean dirty file paths by removing blanks and removing trailing/leading whitespace"""
return filter(lambda e: len(e) > 0, [ f.strip(" \n") for f in dirty_files ])
def find_command(self, directory, extra_arguments=""):
""" Builds a find command that respects supported_file_formats list
Note: Use single quotes to quote arguments """
ext_globs = [ "-iname '*.%s'" % ext for ext in self.supported_file_formats ]
find_glob = ' -o '.join(ext_globs)
return "find '%s' %s %s" % (directory, find_glob, extra_arguments)
def is_parent_directory(self, filepath, directory): def is_parent_directory(self, filepath, directory):
filepath = os.path.normpath(filepath) filepath = os.path.normpath(filepath)
directory = os.path.normpath(directory) directory = os.path.normpath(directory)
@ -31,7 +43,6 @@ class MediaMonitorCommon:
def is_temp_file(self, filename): def is_temp_file(self, filename):
info = filename.split(".") info = filename.split(".")
# if file doesn't have any extension, info[-2] throws exception # if file doesn't have any extension, info[-2] throws exception
# Hence, checking length of info before we do anything # Hence, checking length of info before we do anything
if(len(info) >= 2): if(len(info) >= 2):
@ -41,20 +52,19 @@ class MediaMonitorCommon:
def is_audio_file(self, filename): def is_audio_file(self, filename):
info = filename.split(".") info = filename.split(".")
if len(info) < 2: return false # handle cases like filename="mp3"
return info[-1].lower() in self.supported_file_formats return info[-1].lower() in self.supported_file_formats
#check if file is readable by "nobody" #check if file is readable by "nobody"
def is_user_readable(self, filepath, euid='nobody', egid='nogroup'): def is_user_readable(self, filepath, euid='nobody', egid='nogroup'):
f = None
try: try:
uid = pwd.getpwnam(euid)[2] uid = pwd.getpwnam(euid)[2]
gid = grp.getgrnam(egid)[2] gid = grp.getgrnam(egid)[2]
#drop root permissions and become "nobody" #drop root permissions and become "nobody"
os.setegid(gid) os.setegid(gid)
os.seteuid(uid) os.seteuid(uid)
f = open(filepath)
open(filepath)
readable = True readable = True
except IOError: except IOError:
self.logger.warn("File does not have correct permissions: '%s'", filepath) self.logger.warn("File does not have correct permissions: '%s'", filepath)
@ -65,16 +75,15 @@ class MediaMonitorCommon:
self.logger.error("traceback: %s", traceback.format_exc()) self.logger.error("traceback: %s", traceback.format_exc())
finally: finally:
#reset effective user to root #reset effective user to root
if f: f.close()
os.seteuid(0) os.seteuid(0)
os.setegid(0) os.setegid(0)
return readable return readable
# the function only changes the permission if its not readable by www-data # the function only changes the permission if its not readable by www-data
def is_readable(self, item, is_dir): def is_readable(self, item, is_dir):
try: try:
return self.is_user_readable(item, 'www-data', 'www-data') \ return self.is_user_readable(item, 'www-data', 'www-data')
and self.is_user_readable(item, 'pypo', 'pypo')
except Exception, e: except Exception, e:
self.logger.warn(u"Failed to check owner/group/permissions for %s", item) self.logger.warn(u"Failed to check owner/group/permissions for %s", item)
return False return False
@ -242,7 +251,7 @@ class MediaMonitorCommon:
show_name = '-'.join(title[3:]) show_name = '-'.join(title[3:])
new_md = {} new_md = {}
new_md["MDATA_KEY_FILEPATH"] = original_path new_md['MDATA_KEY_FILEPATH'] = os.path.normpath(original_path)
new_md['MDATA_KEY_TITLE'] = '%s-%s-%s:%s:%s' % (show_name, orig_md['MDATA_KEY_YEAR'], show_hour, show_min, show_sec) new_md['MDATA_KEY_TITLE'] = '%s-%s-%s:%s:%s' % (show_name, orig_md['MDATA_KEY_YEAR'], show_hour, show_min, show_sec)
self.md_manager.save_md_to_file(new_md) self.md_manager.save_md_to_file(new_md)
@ -280,7 +289,7 @@ class MediaMonitorCommon:
return stdout return stdout
def scan_dir_for_new_files(self, dir): def scan_dir_for_new_files(self, dir):
command = 'find "%s" -iname "*.ogg" -o -iname "*.mp3" -type f -readable' % dir.replace('"', '\\"') command = self.find_command(directory=dir, extra_arguments="-type f -readable")
self.logger.debug(command) self.logger.debug(command)
stdout = self.exec_command(command) stdout = self.exec_command(command)
@ -316,13 +325,10 @@ class MediaMonitorCommon:
if return_code != 0: if return_code != 0:
#print pathname for py-interpreter.log #print pathname for py-interpreter.log
print pathname print pathname
return (return_code == 0) return (return_code == 0)
def move_to_problem_dir(self, source): def move_to_problem_dir(self, source):
dest = os.path.join(self.config.problem_directory, os.path.basename(source)) dest = os.path.join(self.config.problem_directory, os.path.basename(source))
try: try:
omask = os.umask(0) omask = os.umask(0)
os.rename(source, dest) os.rename(source, dest)

View file

@ -54,14 +54,10 @@ try:
#create log dir #create log dir
create_dir(config['log_dir']) create_dir(config['log_dir'])
os.system("chown -R pypo:pypo "+config["log_dir"])
#copy python files #copy python files
copy_dir("%s/.."%current_script_dir, config["bin_dir"]) copy_dir("%s/.."%current_script_dir, config["bin_dir"])
#set executable permissions on python files
os.system("chown -R pypo:pypo "+config["bin_dir"])
#copy init.d script #copy init.d script
shutil.copy(config["bin_dir"]+"/airtime-media-monitor-init-d", "/etc/init.d/airtime-media-monitor") shutil.copy(config["bin_dir"]+"/airtime-media-monitor-init-d", "/etc/init.d/airtime-media-monitor")