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

This commit is contained in:
Naomi Aro 2012-04-24 16:21:55 +02:00
commit 5d332ba5ea
40 changed files with 275 additions and 92 deletions

View File

@ -76,6 +76,14 @@ class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
$view->headScript()->appendFile($baseUrl.'/js/airtime/common/common.js?'.$CC_CONFIG['airtime_version'],'text/javascript'); $view->headScript()->appendFile($baseUrl.'/js/airtime/common/common.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
$user = Application_Model_User::GetCurrentUser();
if (!is_null($user)){
$userType = $user->getType();
} else {
$userType = "";
}
$view->headScript()->appendScript("var userType = '$userType';");
if (Application_Model_Preference::GetPlanLevel() != "disabled" if (Application_Model_Preference::GetPlanLevel() != "disabled"
&& ($_SERVER['REQUEST_URI'] != '/Dashboard/stream-player' || $_SERVER['REQUEST_URI'] != '/audiopreview/audio-preview-player')) { && ($_SERVER['REQUEST_URI'] != '/Dashboard/stream-player' || $_SERVER['REQUEST_URI'] != '/audiopreview/audio-preview-player')) {
$client_id = Application_Model_Preference::GetClientId(); $client_id = Application_Model_Preference::GetClientId();

View File

@ -8,7 +8,6 @@
* that the user can customize these. * that the user can customize these.
*/ */
global $CC_CONFIG; global $CC_CONFIG;
$dbhost = $CC_CONFIG['dsn']['hostspec']; $dbhost = $CC_CONFIG['dsn']['hostspec'];

View File

@ -0,0 +1,18 @@
<?php
/* This file is only needed during upgrades when we need the database parameters from /etc/airtime/airtime.conf.
* The reason we don't just use conf.php is because conf.php may try to load configuration parameters that aren't
* yet available because airtime.conf hasn't been updated yet. This situation ends up throwing a lot of errors to stdout.
* airtime*/
global $CC_CONFIG;
$filename = "/etc/airtime/airtime.conf";
$values = parse_ini_file($filename, true);
// Database config
$CC_CONFIG['dsn']['username'] = $values['database']['dbuser'];
$CC_CONFIG['dsn']['password'] = $values['database']['dbpass'];
$CC_CONFIG['dsn']['hostspec'] = $values['database']['host'];
$CC_CONFIG['dsn']['phptype'] = 'pgsql';
$CC_CONFIG['dsn']['database'] = $values['database']['dbname'];

View File

@ -784,6 +784,7 @@ class ApiController extends Zend_Controller_Action
$request = $this->getRequest(); $request = $this->getRequest();
$api_key = $request->getParam('api_key'); $api_key = $request->getParam('api_key');
$getDiskInfo = $request->getParam('diskinfo') == "true"; $getDiskInfo = $request->getParam('diskinfo') == "true";
if (!in_array($api_key, $CC_CONFIG["apiKey"]) && if (!in_array($api_key, $CC_CONFIG["apiKey"]) &&
is_null(Zend_Auth::getInstance()->getStorage()->read())) is_null(Zend_Auth::getInstance()->getStorage()->read()))
{ {

View File

@ -31,7 +31,6 @@ class ScheduleController extends Zend_Controller_Action
->addActionContext('set-time-interval', 'json') ->addActionContext('set-time-interval', 'json')
->addActionContext('edit-show-instance', 'json') ->addActionContext('edit-show-instance', 'json')
->addActionContext('dj-edit-show', 'json') ->addActionContext('dj-edit-show', 'json')
->addActionContext('edit-show-rebroadcast', 'json')
->initContext(); ->initContext();
$this->sched_sess = new Zend_Session_Namespace("schedule"); $this->sched_sess = new Zend_Session_Namespace("schedule");
@ -522,11 +521,6 @@ class ScheduleController extends Zend_Controller_Action
// repeating shows. It's value is either "instance","rebroadcast", or "all" // repeating shows. It's value is either "instance","rebroadcast", or "all"
$type = $this->_getParam('type'); $type = $this->_getParam('type');
/*if($type == "rebroadcast") {
//$this->view->action = "edit-show-rebroadcast";
} else {
$this->view->action = "edit-show";
}*/
$this->view->action = "edit-show"; $this->view->action = "edit-show";
try{ try{
$showInstance = new Application_Model_ShowInstance($showInstanceId); $showInstance = new Application_Model_ShowInstance($showInstanceId);
@ -695,17 +689,6 @@ class ScheduleController extends Zend_Controller_Action
$this->view->form = $this->view->render('schedule/add-show-form.phtml'); $this->view->form = $this->view->render('schedule/add-show-form.phtml');
} }
} }
public function editShowRebroadcastAction(){
$js = $this->_getParam('data');
$data = array();
//need to convert from serialized jQuery array.
foreach($js as $j){
$data[$j["name"]] = $j["value"];
}
}
public function djEditShowAction(){ public function djEditShowAction(){
$js = $this->_getParam('data'); $js = $this->_getParam('data');

View File

@ -39,16 +39,26 @@ class Application_Model_Systemstatus
"name"=>"", "name"=>"",
"process_id"=>"STARTING...", "process_id"=>"STARTING...",
"uptime_seconds"=>"-1", "uptime_seconds"=>"-1",
"status"=>true, "status"=>0,
"memory_perc"=>"0%", "memory_perc"=>"0%",
"memory_kb"=>"0", "memory_kb"=>"0",
"cpu_perc"=>"0%"); "cpu_perc"=>"0%");
$notMonitored = array(
"name"=>$p_serviceName,
"process_id"=>"NOT MONITORED",
"uptime_seconds"=>"1",
"status"=>1,
"memory_perc"=>"0%",
"memory_kb"=>"0",
"cpu_perc"=>"0%"
);
$notRunning = array( $notRunning = array(
"name"=>$p_serviceName, "name"=>$p_serviceName,
"process_id"=>"FAILED", "process_id"=>"FAILED",
"uptime_seconds"=>"-1", "uptime_seconds"=>"-1",
"status"=>false, "status"=>0,
"memory_perc"=>"0%", "memory_perc"=>"0%",
"memory_kb"=>"0", "memory_kb"=>"0",
"cpu_perc"=>"0%" "cpu_perc"=>"0%"
@ -66,8 +76,16 @@ class Application_Model_Systemstatus
$status = $monitor->item(0)->nodeValue; $status = $monitor->item(0)->nodeValue;
if ($status == "2"){ if ($status == "2"){
$data = $starting; $data = $starting;
} else if ($status == 1){
//is monitored, but is it running?
$pid = $item->getElementsByTagName("pid");
if ($pid->length == 0){
$data = $notRunning;
} else {
//running!
}
} else if ($status == 0){ } else if ($status == 0){
$data = $notRunning; $data = $notMonitored;
} }
} }
@ -79,7 +97,7 @@ class Application_Model_Systemstatus
$process_id = $item->getElementsByTagName("pid"); $process_id = $item->getElementsByTagName("pid");
if ($process_id->length > 0){ if ($process_id->length > 0){
$data["process_id"] = $process_id->item(0)->nodeValue; $data["process_id"] = $process_id->item(0)->nodeValue;
$data["status"] = true; $data["status"] = 0;
} }
$uptime = $item->getElementsByTagName("uptime"); $uptime = $item->getElementsByTagName("uptime");

View File

@ -295,7 +295,18 @@ class Application_Model_User {
public static function GetCurrentUser() { public static function GetCurrentUser() {
$userinfo = Zend_Auth::getInstance()->getStorage()->read(); $userinfo = Zend_Auth::getInstance()->getStorage()->read();
return new self($userinfo->id); if (is_null($userinfo)){
return null;
} else {
try {
return new self($userinfo->id);
} catch (Exception $e){
//we get here if $userinfo->id is defined, but doesn't exist
//in the database anymore.
Zend_Auth::getInstance()->clearIdentity();
return null;
}
}
} }
} }

View File

@ -2,7 +2,6 @@ php_value post_max_size 500M
php_value upload_max_filesize 500M php_value upload_max_filesize 500M
php_value request_order "GPC" php_value request_order "GPC"
php_value session.gc_probability 0 php_value session.gc_probability 0
php_value phar.readonly Off
php_value session.auto_start 0 php_value session.auto_start 0
RewriteEngine On RewriteEngine On
@ -22,4 +21,4 @@ AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/json AddOutputFilterByType DEFLATE application/json

View File

@ -2310,6 +2310,14 @@ tfoot tr th {
margin:0; margin:0;
display:block; display:block;
} }
.warning-icon {
width:100%;
margin:0;
background: url("images/warning-icon.png") no-repeat center center;
height:16px;
margin:0;
display:block;
}
.statustable ul { .statustable ul {
margin:4px 0; margin:4px 0;
padding:0; padding:0;
@ -2656,4 +2664,4 @@ dd .stream-status {
background-color: #727272; background-color: #727272;
outline: 0; outline: 0;
border-top-color:#333333 border-top-color:#333333
} }

View File

@ -94,7 +94,7 @@ function pad(number, length) {
function dayClick(date, allDay, jsEvent, view){ function dayClick(date, allDay, jsEvent, view){
// The show from will be preloaded if the user is admin or program manager. // The show from will be preloaded if the user is admin or program manager.
// Hence, if the user if DJ then it won't open anything. // Hence, if the user if DJ then it won't open anything.
if($.trim($("#add-show-form").html()) != ""){ if(userType == "A" || userType == "P"){
var now, today, selected, chosenDate, chosenTime; var now, today, selected, chosenDate, chosenTime;
now = adjustDateToServerDate(new Date(), serverTimezoneOffset); now = adjustDateToServerDate(new Date(), serverTimezoneOffset);
@ -212,7 +212,9 @@ function viewDisplay( view ) {
} }
if(($("#add-show-form").length == 1) && ($("#add-show-form").css('display')=='none') && ($('.fc-header-left > span').length == 5)) { if(($("#add-show-form").length == 1) && ($("#add-show-form").css('display')=='none') && ($('.fc-header-left > span').length == 5)) {
if($.trim($("#add-show-form").html()) != ""){
//userType is defined in bootstrap.php, and is derived from the currently logged in user.
if(userType == "A" || userType == "P"){
makeAddShowButton(); makeAddShowButton();
} }
} }

View File

@ -48,7 +48,15 @@ function success(data, textStatus, jqXHR){
var s = services[key]; var s = services[key];
var children = $("#"+s.name).children(); var children = $("#"+s.name).children();
$(children[0]).text(s.name); $(children[0]).text(s.name);
$($(children[1]).children()[0]).attr("class", s.status ? "checked-icon": "not-available-icon");
var status_class = "not-available-icon";
if (s.status == 0){
status_class = "checked-icon";
} else if (s.status == 1) {
status_class = "warning-icon";
}
$($(children[1]).children()[0]).attr("class", status_class);
$(children[2]).text(sprintf('%(days)sd %(hours)sh %(minutes)sm %(seconds)ss', convertSecondsToDaysHoursMinutesSeconds(s.uptime_seconds))); $(children[2]).text(sprintf('%(days)sd %(hours)sh %(minutes)sm %(seconds)ss', convertSecondsToDaysHoursMinutesSeconds(s.uptime_seconds)));
$(children[3]).text(s.cpu_perc); $(children[3]).text(s.cpu_perc);
$(children[4]).text(sprintf('%01.1fMB (%s)', parseInt(s.memory_kb)/1000, s.memory_perc)); $(children[4]).text(sprintf('%01.1fMB (%s)', parseInt(s.memory_kb)/1000, s.memory_perc));

View File

@ -0,0 +1,23 @@
Before you overwrite jquery.contextMenu.js, note that we have changed a few lines
in this file.
denise@denise-DX4860:~/airtime/airtime_mvc/public/js/contextmenu$ diff -u jquery.contextMenu_orig.js jquery.contextMenu.js
--- jquery.contextMenu_orig.js 2012-04-20 10:15:59.943215571 -0400
+++ jquery.contextMenu.js 2012-04-20 10:00:18.911178927 -0400
@@ -306,6 +306,15 @@
e.stopImmediatePropagation();
$this.remove();
root.$menu.trigger('contextmenu:hide');
+ /* (Airtime) added this to allow user to exit out of menu.
+ * if ignoreThisClick remains false, every right click
+ * thereafter continues to show the menu
+ */
+ if (ignoreRightClick) {
+ if (e.button == 2) {
+ ignoreThisClick = true;
+ }
+ }
},
// key handled :hover
keyStop: function(e, opt) {

View File

@ -310,7 +310,7 @@ var // currently active contextMenu trigger
* if ignoreThisClick remains false, every right click * if ignoreThisClick remains false, every right click
* thereafter continues to show the menu * thereafter continues to show the menu
*/ */
if (ignoreRightClick) { if (handle.ignoreRightClick) {
if (e.button == 2) { if (e.button == 2) {
ignoreThisClick = true; ignoreThisClick = true;
} }

View File

@ -247,5 +247,4 @@ php_admin_value[post_max_size] = 500M
php_admin_value[upload_max_filesize] = 500M php_admin_value[upload_max_filesize] = 500M
php_admin_value[request_order] = GPC php_admin_value[request_order] = GPC
php_admin_value[session.gc_probability] = 0 php_admin_value[session.gc_probability] = 0
php_admin_value[phar.readonly] = off
php_admin_value[upload_tmp_dir] = /tmp php_admin_value[upload_tmp_dir] = /tmp

View File

@ -39,7 +39,7 @@ php-pear php5-gd postgresql odbc-postgresql python2.6 libsoundtouch-ocaml \
libtaglib-ocaml libao-ocaml libmad-ocaml ecasound \ libtaglib-ocaml libao-ocaml libmad-ocaml ecasound \
libesd0 libportaudio2 libsamplerate0 rabbitmq-server patch \ libesd0 libportaudio2 libsamplerate0 rabbitmq-server patch \
php5-curl mpg123 monit python-virtualenv multitail libcamomile-ocaml-data \ php5-curl mpg123 monit python-virtualenv multitail libcamomile-ocaml-data \
libpulse0 vorbis-tools lsb-release libpulse0 vorbis-tools lsb-release lsof
#install packages with --force-yes option (this is useful in the case #install packages with --force-yes option (this is useful in the case
#of Debian, where these packages are unauthorized) #of Debian, where these packages are unauthorized)

View File

@ -42,7 +42,7 @@ php-pear php5-gd postgresql odbc-postgresql python2.6 libsoundtouch-ocaml \
libtaglib-ocaml libao-ocaml libmad-ocaml ecasound \ libtaglib-ocaml libao-ocaml libmad-ocaml ecasound \
libesd0 libportaudio2 libsamplerate0 rabbitmq-server patch \ libesd0 libportaudio2 libsamplerate0 rabbitmq-server patch \
php5-curl mpg123 monit python-virtualenv multitail libcamomile-ocaml-data \ php5-curl mpg123 monit python-virtualenv multitail libcamomile-ocaml-data \
libpulse0 vorbis-tools lsb-release libpulse0 vorbis-tools lsb-release lsof
#install packages with --force-yes option (this is useful in the case #install packages with --force-yes option (this is useful in the case
#of Debian, where these packages are unauthorized) #of Debian, where these packages are unauthorized)

View File

@ -61,16 +61,21 @@ class AirtimeInstall
} }
$sql = "SELECT valstr FROM cc_pref WHERE keystr = 'system_version' LIMIT 1"; $sql = "SELECT valstr FROM cc_pref WHERE keystr = 'system_version' LIMIT 1";
$version = $con->query($sql)->fetchColumn(0);
try {
if (!$version) { $version = $con->query($sql)->fetchColumn(0);
// no pref table something is wrong. } catch (PDOException $e){
// no pref table therefore Airtime is not installed.
//We only get here if airtime database exists, but the table doesn't
//This state sometimes happens if a previous Airtime uninstall couldn't remove
//the database because it was busy, so it just removed the tables instead.
return null; return null;
} }
//if version is empty string, then version is older than version 1.8.0
if ($version == '') { if ($version == '') {
try { try {
// If this table exists, then it's 1.7.0 // If this table exists, then it's version 1.7.0
$sql = "SELECT * FROM cc_show_rebroadcast LIMIT 1"; $sql = "SELECT * FROM cc_show_rebroadcast LIMIT 1";
$result = $con->query($sql)->fetchColumn(0); $result = $con->query($sql)->fetchColumn(0);
$version = "1.7.0"; $version = "1.7.0";

View File

@ -69,6 +69,7 @@ fi
mkdir -p /usr/lib/airtime mkdir -p /usr/lib/airtime
cp -R $AIRTIMEROOT/utils /usr/lib/airtime cp -R $AIRTIMEROOT/utils /usr/lib/airtime
cp -R $AIRTIMEROOT/python_apps/std_err_override /usr/lib/airtime
echo "* Creating symbolic links in /usr/bin" echo "* Creating symbolic links in /usr/bin"
#create symbolic links #create symbolic links

View File

@ -14,7 +14,7 @@ require_once(__DIR__.'/airtime-constants.php');
AirtimeInstall::ExitIfNotRoot(); AirtimeInstall::ExitIfNotRoot();
require_once(AirtimeInstall::GetAirtimeSrcDir()."/application/configs/conf.php"); require_once(AirtimeInstall::GetAirtimeSrcDir()."/application/configs/db-conf.php");
require_once('propel/runtime/lib/Propel.php'); require_once('propel/runtime/lib/Propel.php');
Propel::init(AirtimeInstall::GetAirtimeSrcDir()."/application/configs/airtime-conf-production.php"); Propel::init(AirtimeInstall::GetAirtimeSrcDir()."/application/configs/airtime-conf-production.php");

View File

@ -18,6 +18,10 @@ if (!file_exists(AirtimeIni::CONF_FILE_AIRTIME)) {
require_once(__DIR__.'/airtime-constants.php'); require_once(__DIR__.'/airtime-constants.php');
require_once(AirtimeInstall::GetAirtimeSrcDir().'/application/configs/conf.php'); require_once(AirtimeInstall::GetAirtimeSrcDir().'/application/configs/conf.php');
require_once 'propel/runtime/lib/Propel.php';
Propel::init(AirtimeInstall::GetAirtimeSrcDir()."/application/configs/airtime-conf-production.php");
echo PHP_EOL; echo PHP_EOL;
echo "* Uninstalling Airtime ".AIRTIME_VERSION.PHP_EOL; echo "* Uninstalling Airtime ".AIRTIME_VERSION.PHP_EOL;
//AirtimeInstall::UninstallPhpCode(); //AirtimeInstall::UninstallPhpCode();

View File

@ -20,6 +20,7 @@ require_once(__DIR__.'/airtime-constants.php');
require_once(__DIR__.'/AirtimeIni.php'); require_once(__DIR__.'/AirtimeIni.php');
require_once(__DIR__.'/AirtimeInstall.php'); require_once(__DIR__.'/AirtimeInstall.php');
require_once 'propel/runtime/lib/Propel.php'; require_once 'propel/runtime/lib/Propel.php';
Propel::init(AirtimeInstall::GetAirtimeSrcDir()."/application/configs/db-conf.php");
Propel::init(AirtimeInstall::GetAirtimeSrcDir()."/application/configs/airtime-conf-production.php"); Propel::init(AirtimeInstall::GetAirtimeSrcDir()."/application/configs/airtime-conf-production.php");
@ -106,9 +107,6 @@ if (strcmp($version, "2.1.0") < 0){
$sql = "DELETE FROM cc_pref WHERE keystr = 'system_version'"; $sql = "DELETE FROM cc_pref WHERE keystr = 'system_version'";
$con->exec($sql); $con->exec($sql);
$values = parse_ini_file(CONF_FILE_AIRTIME, true);
$phpDir = $values['general']['airtime_dir'];
$newVersion = AIRTIME_VERSION; $newVersion = AIRTIME_VERSION;
$sql = "INSERT INTO cc_pref (keystr, valstr) VALUES ('system_version', '$newVersion')"; $sql = "INSERT INTO cc_pref (keystr, valstr) VALUES ('system_version', '$newVersion')";
$con->exec($sql); $con->exec($sql);

View File

@ -4,8 +4,10 @@ import logging.config
import sys import sys
import os import os
import signal import signal
import traceback
from api_clients import api_client as apc from api_clients import api_client as apc
from std_err_override import LogWriter
from multiprocessing import Process, Queue as mpQueue from multiprocessing import Process, Queue as mpQueue
@ -23,12 +25,17 @@ from airtimefilemonitor.airtimemediamonitorbootstrap import AirtimeMediaMonitorB
# configure logging # configure logging
try: try:
logging.config.fileConfig("logging.cfg") logging.config.fileConfig("logging.cfg")
#need to wait for Python 2.7 for this..
#logging.captureWarnings(True)
logger = logging.getLogger()
LogWriter.override_std_err(logger)
except Exception, e: except Exception, e:
print 'Error configuring logging: ', e print 'Error configuring logging: ', e
sys.exit(1) sys.exit(1)
logger = logging.getLogger()
logger.info("\n\n*** Media Monitor bootup ***\n\n") logger.info("\n\n*** Media Monitor bootup ***\n\n")
try: try:
@ -53,7 +60,8 @@ try:
multi_queue = mpQueue() multi_queue = mpQueue()
logger.info("Initializing event processor") logger.info("Initializing event processor")
except Exception, e: except Exception, e:
logger.error('Exception: %s', e) logger.error('Exception: %s', e)
logger.error("traceback: %s", traceback.format_exc())
try: try:
@ -90,7 +98,5 @@ except KeyboardInterrupt:
notifier.stop() notifier.stop()
logger.info("Keyboard Interrupt") logger.info("Keyboard Interrupt")
except Exception, e: except Exception, e:
import traceback
top = traceback.format_exc()
logger.error('Exception: %s', e) logger.error('Exception: %s', e)
logger.error("traceback: %s", top) logger.error("traceback: %s", traceback.format_exc())

View File

@ -140,9 +140,7 @@ class AirtimeMetadata:
if key in self.mutagen2airtime and len(file_info[key]) > 0: if key in self.mutagen2airtime and len(file_info[key]) > 0:
md[self.mutagen2airtime[key]] = file_info[key][0] md[self.mutagen2airtime[key]] = file_info[key][0]
if 'MDATA_KEY_TITLE' not in md: if 'MDATA_KEY_TITLE' not in md:
#get rid of file extention from original name, name might have more than 1 '.' in it. #get rid of file extension from original name, name might have more than 1 '.' in it.
#filepath = to_unicode(filepath)
#filepath = filepath.encode('utf-8')
original_name = os.path.basename(filepath) original_name = os.path.basename(filepath)
original_name = original_name.split(".")[0:-1] original_name = original_name.split(".")[0:-1]
original_name = ''.join(original_name) original_name = ''.join(original_name)

View File

@ -2,6 +2,7 @@ import json
import time import time
import os import os
import logging import logging
import traceback
# For RabbitMQ # For RabbitMQ
from kombu.connection import BrokerConnection from kombu.connection import BrokerConnection
@ -116,7 +117,11 @@ class AirtimeNotifier(Notifier):
if m['delete']: if m['delete']:
self.logger.info("Deleting file: %s ", filepath) self.logger.info("Deleting file: %s ", filepath)
os.unlink(filepath) try:
os.unlink(filepath)
except Exception, e:
self.logger.error('Exception: %s', e)
self.logger.error("traceback: %s", traceback.format_exc())
""" """

View File

@ -4,6 +4,7 @@ import time
import os import os
import shutil import shutil
import difflib import difflib
import traceback
import pyinotify import pyinotify
from pyinotify import ProcessEvent from pyinotify import ProcessEvent
@ -142,8 +143,13 @@ class AirtimeProcessEvent(ProcessEvent):
#delete files from organize if they can not be read properly. #delete files from organize if they can not be read properly.
if pathname is None: if pathname is None:
os.remove(oldPath) try:
return self.logger.info("Deleting file because it cannot be read properly: %s", oldPath)
os.remove(oldPath)
return
except Exception, e:
self.logger.error('Exception: %s', e)
self.logger.error("traceback: %s", traceback.format_exc())
self.mmc.set_needed_file_permissions(pathname, dir) self.mmc.set_needed_file_permissions(pathname, dir)
is_recorded = self.mmc.is_parent_directory(pathname, self.config.recorded_directory) is_recorded = self.mmc.is_parent_directory(pathname, self.config.recorded_directory)
@ -245,7 +251,13 @@ class AirtimeProcessEvent(ProcessEvent):
#delete files from organize if they can not be read properly. #delete files from organize if they can not be read properly.
if filepath is None: if filepath is None:
os.remove(event.pathname) try:
self.logger.info("Deleting file because it cannot be read properly: %s", event.pathname)
os.remove(event.pathname)
return
except Exception, e:
self.logger.error('Exception: %s', e)
self.logger.error("traceback: %s", traceback.format_exc())
else: else:
filepath = event.pathname filepath = event.pathname
@ -258,7 +270,13 @@ class AirtimeProcessEvent(ProcessEvent):
#delete files from organize if they can not be read properly. #delete files from organize if they can not be read properly.
if filepath is None: if filepath is None:
os.remove(event.pathname) try:
self.logger.info("Deleting file because it cannot be read properly: %s", event.pathname)
os.remove(event.pathname)
return
except Exception, e:
self.logger.error('Exception: %s', e)
self.logger.error("traceback: %s", traceback.format_exc())
else: else:
#show dragged from unwatched folder into a watched folder. Do not "organize".:q! #show dragged from unwatched folder into a watched folder. Do not "organize".:q!
if self.mmc.is_parent_directory(event.pathname, self.config.recorded_directory): if self.mmc.is_parent_directory(event.pathname, self.config.recorded_directory):
@ -349,9 +367,15 @@ class AirtimeProcessEvent(ProcessEvent):
# handling those cases. We are manully calling handle_created_file # handling those cases. We are manully calling handle_created_file
# function. # function.
if os.path.exists(k): if os.path.exists(k):
# check if file is open # check if file is open
command = "lsof "+k try:
f = os.popen(command) command = "lsof "+k
f = os.popen(command)
except Exception, e:
self.logger.error('Exception: %s', e)
self.logger.error("traceback: %s", traceback.format_exc())
continue
if not f.readlines(): if not f.readlines():
self.logger.info("Handling file: %s", k) self.logger.info("Handling file: %s", k)
self.handle_created_file(False, k, os.path.basename(k)) self.handle_created_file(False, k, os.path.basename(k))
@ -366,9 +390,7 @@ class AirtimeProcessEvent(ProcessEvent):
except socket.timeout: except socket.timeout:
pass pass
except Exception, e: except Exception, e:
import traceback
top = traceback.format_exc()
self.logger.error('Exception: %s', e) self.logger.error('Exception: %s', e)
self.logger.error("traceback: %s", top) self.logger.error("traceback: %s", traceback.format_exc())
time.sleep(3) time.sleep(3)

View File

@ -18,7 +18,7 @@ class AirtimeMediaConfig:
self.cfg = config self.cfg = config
except Exception, e: except Exception, e:
logger.info('Error loading config: ', e) logger.info('Error loading config: ', e)
sys.exit() sys.exit(1)
self.storage_directory = None self.storage_directory = None

View File

@ -4,6 +4,7 @@ import pwd
import logging import logging
import stat import stat
import subprocess import subprocess
import traceback
from subprocess import Popen, PIPE from subprocess import Popen, PIPE
from airtimemetadata import AirtimeMetadata from airtimemetadata import AirtimeMetadata
@ -49,22 +50,25 @@ class MediaMonitorCommon:
#check if file is readable by "nobody" #check if file is readable by "nobody"
def has_correct_permissions(self, filepath, euid='nobody', egid='nogroup'): def has_correct_permissions(self, filepath, euid='nobody', egid='nogroup'):
uid = pwd.getpwnam(euid)[2]
gid = grp.getgrnam(egid)[2]
#drop root permissions and become "nobody"
os.setegid(gid)
os.seteuid(uid)
try: try:
uid = pwd.getpwnam(euid)[2]
gid = grp.getgrnam(egid)[2]
#drop root permissions and become "nobody"
os.setegid(gid)
os.seteuid(uid)
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)
readable = False readable = False
self.logger.error("traceback: %s", traceback.format_exc())
except Exception, e: except Exception, e:
self.logger.error("Unexpected exception thrown: %s", e) self.logger.error("Unexpected exception thrown: %s", e)
readable = False readable = False
self.logger.error("traceback: %s", traceback.format_exc())
finally: finally:
#reset effective user to root #reset effective user to root
os.seteuid(0) os.seteuid(0)
@ -96,10 +100,11 @@ class MediaMonitorCommon:
os.chmod(item, bitor) os.chmod(item, bitor)
except Exception, e: except Exception, e:
self.logger.error("Failed to change file's owner/group/permissions. %s", e) self.logger.error("Failed to change file's owner/group/permissions. %s", e)
return False; self.logger.error("traceback: %s", traceback.format_exc())
return False
finally: finally:
os.umask(omask) os.umask(omask)
return True; return True
#checks if path is a directory, and if it doesnt exist, then creates it. #checks if path is a directory, and if it doesnt exist, then creates it.
@ -125,6 +130,7 @@ class MediaMonitorCommon:
os.rename(source, dest) os.rename(source, dest)
except Exception, e: except Exception, e:
self.logger.error("failed to move file. %s", e) self.logger.error("failed to move file. %s", e)
self.logger.error("traceback: %s", traceback.format_exc())
finally: finally:
os.umask(omask) os.umask(omask)
@ -137,8 +143,13 @@ class MediaMonitorCommon:
def cleanup_empty_dirs(self, dir): def cleanup_empty_dirs(self, dir):
if os.path.normpath(dir) != self.config.organize_directory: if os.path.normpath(dir) != self.config.organize_directory:
if len(os.listdir(dir)) == 0: if len(os.listdir(dir)) == 0:
os.rmdir(dir) try:
os.rmdir(dir)
except Exception, e:
#non-critical exception because we probably tried to delete a non-empty dir.
#Don't need to log this, let's just "return"
return
pdir = os.path.dirname(dir) pdir = os.path.dirname(dir)
self.cleanup_empty_dirs(pdir) self.cleanup_empty_dirs(pdir)
@ -272,9 +283,13 @@ class MediaMonitorCommon:
def touch_index_file(self): def touch_index_file(self):
dirname = os.path.dirname(self.timestamp_file) dirname = os.path.dirname(self.timestamp_file)
if not os.path.exists(dirname): try:
os.makedirs(dirname) if not os.path.exists(dirname):
open(self.timestamp_file, "w") os.makedirs(dirname)
open(self.timestamp_file, "w")
except Exception, e:
self.logger.error('Exception: %s', e)
self.logger.error("traceback: %s", traceback.format_exc())
def organize_new_file(self, pathname): def organize_new_file(self, pathname):
self.logger.info("Organizing new file: %s", pathname) self.logger.info("Organizing new file: %s", pathname)

View File

@ -1,5 +1,6 @@
from mediaconfig import AirtimeMediaConfig from mediaconfig import AirtimeMediaConfig
import mediamonitorcommon import mediamonitorcommon
import traceback
class MediaMonitorWorkerProcess: class MediaMonitorWorkerProcess:
@ -20,3 +21,4 @@ class MediaMonitorWorkerProcess:
notifier.update_airtime(event) notifier.update_airtime(event)
except Exception, e: except Exception, e:
notifier.logger.error(e) notifier.logger.error(e)
notifier.logger.error("traceback: %s", traceback.format_exc())

View File

@ -1,6 +1,6 @@
def notify(m) def notify(m)
log("/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --data='#{!pypo_data}' --media-id=#{m['schedule_table_id']}") log("/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --data='#{!pypo_data}' --media-id=#{m['schedule_table_id']} &")
system("/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --data='#{!pypo_data}' --media-id=#{m['schedule_table_id']}") system("/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --data='#{!pypo_data}' --media-id=#{m['schedule_table_id']} &")
end end
# A function applied to each metadata chunk # A function applied to each metadata chunk
@ -65,14 +65,14 @@ end
def output_to(output_type, type, bitrate, host, port, pass, mount_point, url, description, genre, user, s, stream, connected) = def output_to(output_type, type, bitrate, host, port, pass, mount_point, url, description, genre, user, s, stream, connected) =
def on_error(msg) def on_error(msg)
connected := "false" connected := "false"
system("/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --error='#{msg}' --stream-id=#{stream} --time=#{!time}") system("/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --error='#{msg}' --stream-id=#{stream} --time=#{!time} &")
log("/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --error='#{msg}' --stream-id=#{stream} --time=#{!time}") log("/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --error='#{msg}' --stream-id=#{stream} --time=#{!time} &")
5. 5.
end end
def on_connect() def on_connect()
connected := "true" connected := "true"
system("/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --connect --stream-id=#{stream} --time=#{!time}") system("/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --connect --stream-id=#{stream} --time=#{!time} &")
log("/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --connect --stream-id=#{stream} --time=#{!time}") log("/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --connect --stream-id=#{stream} --time=#{!time} &")
end end
if output_type == "icecast" then if output_type == "icecast" then
user_ref = ref user user_ref = ref user

View File

@ -81,8 +81,8 @@ end
set("harbor.bind_addr", "0.0.0.0") set("harbor.bind_addr", "0.0.0.0")
def update_source_status(sourcename, status) = def update_source_status(sourcename, status) =
system("/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --source-name=#{sourcename} --source-status=#{status}") system("/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --source-name=#{sourcename} --source-status=#{status} &")
log("/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --source-name=#{sourcename} --source-status=#{status}") log("/usr/lib/airtime/pypo/bin/liquidsoap_scripts/notify.sh --source-name=#{sourcename} --source-status=#{status} &")
end end
def live_dj_connect(header) = def live_dj_connect(header) =

View File

@ -36,6 +36,7 @@ from configobj import ConfigObj
# custom imports # custom imports
#from util import * #from util import *
from api_clients import * from api_clients import *
from std_err_override import LogWriter
# Set up command-line options # Set up command-line options
parser = OptionParser() parser = OptionParser()
@ -59,13 +60,18 @@ parser.add_option("-y", "--source-status", help="source connection stauts", meta
# configure logging # configure logging
logging.config.fileConfig("logging.cfg") logging.config.fileConfig("logging.cfg")
logger = logging.getLogger()
LogWriter.override_std_err(logger)
#need to wait for Python 2.7 for this..
#logging.captureWarnings(True)
# loading config file # loading config file
try: try:
config = ConfigObj('/etc/airtime/pypo.cfg') config = ConfigObj('/etc/airtime/pypo.cfg')
except Exception, e: except Exception, e:
print 'error: ', e logger.error('Error loading config file: %s', e)
sys.exit() sys.exit()

View File

@ -23,6 +23,7 @@ from configobj import ConfigObj
# custom imports # custom imports
from api_clients import api_client from api_clients import api_client
from std_err_override import LogWriter
PYPO_VERSION = '1.1' PYPO_VERSION = '1.1'
@ -45,12 +46,16 @@ parser.add_option("-c", "--check", help="Check the cached schedule and exit", de
# configure logging # configure logging
logging.config.fileConfig("logging.cfg") logging.config.fileConfig("logging.cfg")
logger = logging.getLogger()
LogWriter.override_std_err(logger)
#need to wait for Python 2.7 for this..
#logging.captureWarnings(True)
# loading config file # loading config file
try: try:
config = ConfigObj('/etc/airtime/pypo.cfg') config = ConfigObj('/etc/airtime/pypo.cfg')
except Exception, e: except Exception, e:
logger = logging.getLogger()
logger.error('Error loading config file: %s', e) logger.error('Error loading config file: %s', e)
sys.exit() sys.exit()

View File

@ -10,11 +10,17 @@ import copy
from threading import Thread from threading import Thread
from api_clients import api_client from api_clients import api_client
from std_err_override import LogWriter
from configobj import ConfigObj from configobj import ConfigObj
# configure logging # configure logging
logging.config.fileConfig("logging.cfg") logging.config.fileConfig("logging.cfg")
logger = logging.getLogger()
LogWriter.override_std_err(logger)
#need to wait for Python 2.7 for this..
#logging.captureWarnings(True)
# loading config file # loading config file
try: try:
@ -24,7 +30,6 @@ try:
POLL_INTERVAL = int(config['poll_interval']) POLL_INTERVAL = int(config['poll_interval'])
except Exception, e: except Exception, e:
logger = logging.getLogger()
logger.error('Error loading config file: %s', e) logger.error('Error loading config file: %s', e)
sys.exit() sys.exit()

View File

@ -8,8 +8,15 @@ import shutil
import os import os
import sys import sys
from std_err_override import LogWriter
# configure logging # configure logging
logging.config.fileConfig("logging.cfg") logging.config.fileConfig("logging.cfg")
logger = logging.getLogger()
LogWriter.override_std_err(logger)
#need to wait for Python 2.7 for this..
#logging.captureWarnings(True)
# loading config file # loading config file
try: try:
@ -19,7 +26,6 @@ try:
POLL_INTERVAL = int(config['poll_interval']) POLL_INTERVAL = int(config['poll_interval'])
except Exception, e: except Exception, e:
logger = logging.getLogger()
logger.error('Error loading config file: %s', e) logger.error('Error loading config file: %s', e)
sys.exit(1) sys.exit(1)

View File

@ -10,8 +10,15 @@ from kombu.messaging import Exchange, Queue
from kombu.simple import SimpleQueue from kombu.simple import SimpleQueue
import json import json
from std_err_override import LogWriter
# configure logging # configure logging
logging.config.fileConfig("logging.cfg") logging.config.fileConfig("logging.cfg")
logger = logging.getLogger('message_h')
LogWriter.override_std_err(logger)
#need to wait for Python 2.7 for this..
#logging.captureWarnings(True)
# loading config file # loading config file
try: try:
@ -21,7 +28,6 @@ try:
POLL_INTERVAL = int(config['poll_interval']) POLL_INTERVAL = int(config['poll_interval'])
except Exception, e: except Exception, e:
logger = logging.getLogger('message_h')
logger.error('Error loading config file: %s', e) logger.error('Error loading config file: %s', e)
sys.exit() sys.exit()

View File

@ -16,11 +16,17 @@ from Queue import Empty
from threading import Thread from threading import Thread
from api_clients import api_client from api_clients import api_client
from std_err_override import LogWriter
from configobj import ConfigObj from configobj import ConfigObj
# configure logging # configure logging
logging.config.fileConfig("logging.cfg") logging.config.fileConfig("logging.cfg")
logger = logging.getLogger()
LogWriter.override_std_err(logger)
#need to wait for Python 2.7 for this..
#logging.captureWarnings(True)
# loading config file # loading config file
try: try:
@ -30,7 +36,6 @@ try:
PUSH_INTERVAL = 2 PUSH_INTERVAL = 2
MAX_LIQUIDSOAP_QUEUE_LENGTH = 2 MAX_LIQUIDSOAP_QUEUE_LENGTH = 2
except Exception, e: except Exception, e:
logger = logging.getLogger()
logger.error('Error loading config file %s', e) logger.error('Error loading config file %s', e)
sys.exit() sys.exit()

View File

@ -0,0 +1,11 @@
import sys
class LogWriter():
def __init__(self, logger):
self.logger = logger
def write(self, txt):
self.logger.error(txt)
def override_std_err(logger):
sys.stderr = LogWriter(logger)

View File

View File

@ -222,6 +222,7 @@ class AirtimeCheck {
global $showColor; global $showColor;
$RED = "[0;31m"; $RED = "[0;31m";
$ORANGE = "[0;33m";
$GREEN = "[1;32m"; $GREEN = "[1;32m";
$color = $GREEN; $color = $GREEN;
@ -229,6 +230,9 @@ class AirtimeCheck {
if ($value == "FAILED"){ if ($value == "FAILED"){
$color = $RED; $color = $RED;
self::$AIRTIME_STATUS_OK = false; self::$AIRTIME_STATUS_OK = false;
} else if ($value == "NOT MONITORED"){
$color = $ORANGE;
self::$AIRTIME_STATUS_OK = false;
} }
if ($showColor) if ($showColor)

View File

@ -42,7 +42,7 @@ def find_liquidsoap_binary():
return None return None
optlist, args = getopt.getopt(sys.argv[1:], 'hvo:H:P:u:p:') optlist, args = getopt.getopt(sys.argv[1:], 'hvo:H:P:u:p:m:')
stream_types = set(["shoutcast", "icecast"]) stream_types = set(["shoutcast", "icecast"])
verbose = False verbose = False
@ -102,6 +102,8 @@ try:
if not verbose: if not verbose:
command += " 2>/dev/null | grep \"failed\"" command += " 2>/dev/null | grep \"failed\""
else:
print command
#print command #print command
rv = subprocess.call(command, shell=True) rv = subprocess.call(command, shell=True)