CC-5990, CC-5991 - Python cleanup, removed need for /usr/lib/airtime
This commit is contained in:
parent
cd102b984b
commit
875a9dfd8b
115 changed files with 248 additions and 212 deletions
0
python_apps/media-monitor/mm2/media/saas/__init__.py
Normal file
0
python_apps/media-monitor/mm2/media/saas/__init__.py
Normal file
73
python_apps/media-monitor/mm2/media/saas/airtimeinstance.py
Normal file
73
python_apps/media-monitor/mm2/media/saas/airtimeinstance.py
Normal file
|
@ -0,0 +1,73 @@
|
|||
import os
|
||||
from os.path import join, basename, dirname
|
||||
|
||||
from ..monitor.exceptions import NoConfigFile
|
||||
from ..monitor.pure import LazyProperty
|
||||
from ..monitor.config import MMConfig
|
||||
from ..monitor.owners import Owner
|
||||
from ..monitor.events import EventRegistry
|
||||
from ..monitor.listeners import FileMediator
|
||||
from api_clients.api_client import AirtimeApiClient
|
||||
|
||||
# poor man's phantom types...
|
||||
class SignalString(str): pass
|
||||
|
||||
class AirtimeInstance(object):
|
||||
""" AirtimeInstance is a class that abstracts away every airtime
|
||||
instance by providing all the necessary objects required to interact
|
||||
with the instance. ApiClient, configs, root_directory """
|
||||
|
||||
@classmethod
|
||||
def root_make(cls, name, root):
|
||||
cfg = {
|
||||
'api_client' : join(root, 'etc/airtime/api_client.cfg'),
|
||||
'media_monitor' : join(root, 'etc/airtime/airtime.conf'),
|
||||
}
|
||||
return cls(name, root, cfg)
|
||||
|
||||
def __init__(self,name, root_path, config_paths):
|
||||
""" name is an internal name only """
|
||||
for cfg in ['api_client','media_monitor']:
|
||||
if cfg not in config_paths: raise NoConfigFile(config_paths)
|
||||
elif not os.path.exists(config_paths[cfg]):
|
||||
raise NoConfigFile(config_paths[cfg])
|
||||
self.name = name
|
||||
self.config_paths = config_paths
|
||||
self.root_path = root_path
|
||||
|
||||
def signal(self, sig):
|
||||
if isinstance(sig, SignalString): return sig
|
||||
else: return SignalString("%s_%s" % (self.name, sig))
|
||||
|
||||
def touch_file_path(self):
|
||||
""" Get the path of the touch file for every instance """
|
||||
touch_base_path = self.mm_config['media-monitor']['index_path']
|
||||
touch_base_name = basename(touch_base_path)
|
||||
new_base_name = self.name + touch_base_name
|
||||
return join(dirname(touch_base_path), new_base_name)
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return "%s,%s(%s)" % (self.name, self.root_path, self.config_paths)
|
||||
|
||||
@LazyProperty
|
||||
def api_client(self):
|
||||
return AirtimeApiClient(config_path=self.config_paths['api_client'])
|
||||
|
||||
@LazyProperty
|
||||
def mm_config(self):
|
||||
return MMConfig(self.config_paths['media_monitor'])
|
||||
|
||||
# I'm well aware that I'm using the service locator pattern
|
||||
# instead of normal constructor injection as I should be.
|
||||
# It's recommended to rewrite this using proper constructor injection
|
||||
|
||||
@LazyProperty
|
||||
def owner(self): return Owner()
|
||||
|
||||
@LazyProperty
|
||||
def event_registry(self): return EventRegistry()
|
||||
|
||||
@LazyProperty
|
||||
def file_mediator(self): return FileMediator()
|
||||
|
133
python_apps/media-monitor/mm2/media/saas/launcher.py
Normal file
133
python_apps/media-monitor/mm2/media/saas/launcher.py
Normal file
|
@ -0,0 +1,133 @@
|
|||
import os, sys
|
||||
import logging
|
||||
import logging.config
|
||||
|
||||
from ..monitor import pure as mmp
|
||||
|
||||
from ..monitor.exceptions import FailedToObtainLocale, FailedToSetLocale
|
||||
from ..monitor.log import get_logger, setup_logging
|
||||
from std_err_override import LogWriter
|
||||
from ..saas.thread import InstanceThread, user, apc, getsig
|
||||
from ..monitor.log import Loggable
|
||||
from ..monitor.exceptions import CouldNotCreateIndexFile
|
||||
from ..monitor.toucher import ToucherThread
|
||||
from ..monitor.airtime import AirtimeNotifier, AirtimeMessageReceiver
|
||||
from ..monitor.watchersyncer import WatchSyncer
|
||||
from ..monitor.eventdrainer import EventDrainer
|
||||
from ..monitor.manager import Manager
|
||||
from ..monitor.syncdb import AirtimeDB
|
||||
from airtimeinstance import AirtimeInstance
|
||||
|
||||
class MM2(InstanceThread, Loggable):
|
||||
|
||||
def index_create(self, index_create_attempt=False):
|
||||
config = user().mm_config
|
||||
if not index_create_attempt:
|
||||
if not os.path.exists(config['media-monitor']['index_path']):
|
||||
self.logger.info("Attempting to create index file:...")
|
||||
try:
|
||||
with open(config['media-monitor']['index_path'], 'w') as f: f.write(" ")
|
||||
except Exception as e:
|
||||
self.logger.info("Failed to create index file with exception: %s" \
|
||||
% str(e))
|
||||
else:
|
||||
self.logger.info("Created index file, reloading configuration:")
|
||||
self.index_create(index_create_attempt=True)
|
||||
else:
|
||||
self.logger.info("Already tried to create index. Will not try again ")
|
||||
|
||||
if not os.path.exists(config['media-monitor']['index_path']):
|
||||
raise CouldNotCreateIndexFile(config['media-monitor']['index_path'])
|
||||
|
||||
def run(self):
|
||||
self.index_create()
|
||||
manager = Manager()
|
||||
apiclient = apc()
|
||||
config = user().mm_config
|
||||
WatchSyncer(signal=getsig('watch'),
|
||||
chunking_number=config['media-monitor']['chunking_number'],
|
||||
timeout=config['media-monitor']['request_max_wait'])
|
||||
airtime_receiver = AirtimeMessageReceiver(config,manager)
|
||||
airtime_notifier = AirtimeNotifier(config, airtime_receiver)
|
||||
|
||||
|
||||
adb = AirtimeDB(apiclient)
|
||||
store = {
|
||||
u'stor' : adb.storage_path(),
|
||||
u'watched_dirs' : adb.list_watched(),
|
||||
}
|
||||
|
||||
self.logger.info("initializing mm with directories: %s" % str(store))
|
||||
|
||||
self.logger.info(
|
||||
"Initing with the following airtime response:%s" % str(store))
|
||||
|
||||
airtime_receiver.change_storage({ 'directory':store[u'stor'] })
|
||||
|
||||
for watch_dir in store[u'watched_dirs']:
|
||||
if not os.path.exists(watch_dir):
|
||||
# Create the watch_directory here
|
||||
try: os.makedirs(watch_dir)
|
||||
except Exception:
|
||||
self.logger.error("Could not create watch directory: '%s' \
|
||||
(given from the database)." % watch_dir)
|
||||
if os.path.exists(watch_dir):
|
||||
airtime_receiver.new_watch({ 'directory':watch_dir }, restart=True)
|
||||
else: self.logger.info("Failed to add watch on %s" % str(watch_dir))
|
||||
|
||||
EventDrainer(airtime_notifier,
|
||||
interval=float(config['media-monitor']['rmq_event_wait']))
|
||||
|
||||
# Launch the toucher that updates the last time when the script was
|
||||
# ran every n seconds.
|
||||
# TODO : verify that this does not interfere with bootstrapping because the
|
||||
# toucher thread might update the last_ran variable too fast
|
||||
ToucherThread(path=user().touch_file_path(),
|
||||
interval=int(config['media-monitor']['touch_interval']))
|
||||
|
||||
success = False
|
||||
while not success:
|
||||
try:
|
||||
apiclient.register_component('media-monitor')
|
||||
success = True
|
||||
except Exception, e:
|
||||
self.logger.error(str(e))
|
||||
import time
|
||||
time.sleep(10)
|
||||
|
||||
manager.loop()
|
||||
|
||||
def launch_instance(name, root, global_cfg):
|
||||
cfg = {
|
||||
'api_client' : global_cfg,
|
||||
'media_monitor' : global_cfg,
|
||||
}
|
||||
ai = AirtimeInstance(name, root, cfg)
|
||||
MM2(ai).start()
|
||||
|
||||
def setup_global(log):
|
||||
""" setup unicode and other stuff """
|
||||
log.info("Attempting to set the locale...")
|
||||
try: mmp.configure_locale(mmp.get_system_locale())
|
||||
except FailedToSetLocale as e:
|
||||
log.info("Failed to set the locale...")
|
||||
sys.exit(1)
|
||||
except FailedToObtainLocale as e:
|
||||
log.info("Failed to obtain the locale form the default path: \
|
||||
'/etc/default/locale'")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
log.info("Failed to set the locale for unknown reason. \
|
||||
Logging exception.")
|
||||
log.info(str(e))
|
||||
|
||||
def setup_logger(log_config, logpath):
|
||||
logging.config.fileConfig(log_config)
|
||||
#need to wait for Python 2.7 for this..
|
||||
#logging.captureWarnings(True)
|
||||
logger = logging.getLogger()
|
||||
LogWriter.override_std_err(logger)
|
||||
logfile = unicode(logpath)
|
||||
setup_logging(logfile)
|
||||
log = get_logger()
|
||||
return log
|
28
python_apps/media-monitor/mm2/media/saas/thread.py
Normal file
28
python_apps/media-monitor/mm2/media/saas/thread.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
import threading
|
||||
|
||||
class UserlessThread(Exception):
|
||||
def __str__(self):
|
||||
return "Current thread: %s is not an instance of InstanceThread \
|
||||
of InstanceInheritingThread" % str(threading.current_thread())
|
||||
|
||||
class HasUser(object):
|
||||
def user(self): return self._user
|
||||
def assign_user(self): self._user = threading.current_thread().user()
|
||||
|
||||
class InstanceThread(threading.Thread, HasUser):
|
||||
def __init__(self,user, *args, **kwargs):
|
||||
super(InstanceThread, self).__init__(*args, **kwargs)
|
||||
self._user = user
|
||||
|
||||
class InstanceInheritingThread(threading.Thread, HasUser):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.assign_user()
|
||||
super(InstanceInheritingThread, self).__init__(*args, **kwargs)
|
||||
|
||||
def user():
|
||||
try: return threading.current_thread().user()
|
||||
except AttributeError: raise UserlessThread()
|
||||
|
||||
def apc(): return user().api_client
|
||||
|
||||
def getsig(s): return user().signal(s)
|
Loading…
Add table
Add a link
Reference in a new issue