From 516f98dfcfc1164f9b6c7621bad15e0e476474d7 Mon Sep 17 00:00:00 2001 From: Lucas Bickel Date: Sat, 1 Apr 2017 10:25:12 +0200 Subject: [PATCH 01/33] Report on airtime-celery service in status Adds celery checks to /?config and /systemstatus for completeness' sake. Fixes #138 --- .../application/configs/config-check.php | 23 ++++++++++++++++++- .../views/scripts/systemstatus/index.phtml | 21 +++++++++++++++++ airtime_mvc/build/airtime-setup/load.php | 16 ++++++++++++- 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/airtime_mvc/application/configs/config-check.php b/airtime_mvc/application/configs/config-check.php index f2b3666e5..5c6e010fd 100644 --- a/airtime_mvc/application/configs/config-check.php +++ b/airtime_mvc/application/configs/config-check.php @@ -16,7 +16,8 @@ $rabbitmq = $externalServices["rabbitmq"]; $pypo = $externalServices["pypo"]; $liquidsoap = $externalServices["liquidsoap"]; -$analyzer = $externalServices["analyzer"]; +$analyzer = $externalServices["analyzer"]; +$celery = $externalServices['celery']; $r1 = array_reduce($phpDependencies, "booleanReduce", true); $r2 = array_reduce($externalServices, "booleanReduce", true); @@ -221,6 +222,26 @@ $result = $r1 && $r2; ?> + + + Celery + + + Airtime Celery Task service + + + "> + Check that the airtime-celery service is installed correctly in /etc/init.d, + and ensure that it's running with +
initctl list | grep airtime-celery
+ If not, try running sudo service airtime-celery restart + + + diff --git a/airtime_mvc/application/views/scripts/systemstatus/index.phtml b/airtime_mvc/application/views/scripts/systemstatus/index.phtml index 9fa27d378..f86654e1e 100644 --- a/airtime_mvc/application/views/scripts/systemstatus/index.phtml +++ b/airtime_mvc/application/views/scripts/systemstatus/index.phtml @@ -13,6 +13,7 @@ $pypo = $externalServices["pypo"]; $liquidsoap = $externalServices["liquidsoap"]; $analyzer = $externalServices["analyzer"]; + $celery = $externalServices['celery']; $r1 = array_reduce($phpDependencies, "booleanReduce", true); $r2 = array_reduce($externalServices, "booleanReduce", true); @@ -149,6 +150,26 @@ ?> + + + Celery + + + LibreTime Celery Task service + + + "> + Check that the airtime-celery service is installed correctly in /etc/init, + and ensure that it's running with +
initctl list | grep airtime-celery
+ If not, try
sudo service airtime-celery restart + + + diff --git a/airtime_mvc/build/airtime-setup/load.php b/airtime_mvc/build/airtime-setup/load.php index 6b2624ce0..d255037ed 100644 --- a/airtime_mvc/build/airtime-setup/load.php +++ b/airtime_mvc/build/airtime-setup/load.php @@ -54,7 +54,8 @@ function checkExternalServices() { "analyzer" => checkAnalyzerService(), "pypo" => checkPlayoutService(), "liquidsoap" => checkLiquidsoapService(), - "rabbitmq" => checkRMQConnection() + "rabbitmq" => checkRMQConnection(), + "celery" => checkCeleryService(), ); } @@ -144,3 +145,16 @@ function checkLiquidsoapService() { } return $status == 0; } + +/** + * Check if airtime-celery is currently running + * + * @return boolean true if airtime-celery is running + */ +function checkCeleryService() { + exec("pgrep -f -u www-data airtime-celery", $out, $status); + if (array_key_exists(0, $out) && $status == 0) { + return posix_kill(rtrim($out[0]), 0); + } + return $status == 0; +} From 5fcd60415c57460529c323d3fa373be9ea33f8da Mon Sep 17 00:00:00 2001 From: Lucas Bickel Date: Fri, 7 Apr 2017 11:46:23 +0200 Subject: [PATCH 02/33] Change to check celery user instead of www-data --- airtime_mvc/build/airtime-setup/load.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airtime_mvc/build/airtime-setup/load.php b/airtime_mvc/build/airtime-setup/load.php index d255037ed..5a49630f5 100644 --- a/airtime_mvc/build/airtime-setup/load.php +++ b/airtime_mvc/build/airtime-setup/load.php @@ -152,7 +152,7 @@ function checkLiquidsoapService() { * @return boolean true if airtime-celery is running */ function checkCeleryService() { - exec("pgrep -f -u www-data airtime-celery", $out, $status); + exec("pgrep -f -u celery airtime-celery", $out, $status); if (array_key_exists(0, $out) && $status == 0) { return posix_kill(rtrim($out[0]), 0); } From fd6f3230ed9813b5c7f895f373d712abcddd41a3 Mon Sep 17 00:00:00 2001 From: Lucas Bickel Date: Mon, 17 Apr 2017 11:08:11 +0200 Subject: [PATCH 03/33] Always return proper file size Legacy upstream had a weird way of doing this that could lead to empty files being requested with a range header that did not match what was available on the server. I'm assuming this code used to work aroud some media-monitor feature that has been since refactored into analyzer which handles these cases properly. --- airtime_mvc/application/common/FileIO.php | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/airtime_mvc/application/common/FileIO.php b/airtime_mvc/application/common/FileIO.php index 96cc73878..5b789228a 100644 --- a/airtime_mvc/application/common/FileIO.php +++ b/airtime_mvc/application/common/FileIO.php @@ -26,8 +26,16 @@ class Application_Common_FileIO } //Note that $size is allowed to be zero. If that's the case, it means we don't - //know the filesize, and we just won't send the Content-Length header. - if ($size < 0) { + //know the filesize, and we need to figure one out so modern browsers don't get + //confused. This should only affect files imported by legacy upstream since + //media monitor did not always set the proper size in the database but analyzer + //seems to always have a value for this. + if ($size === 0) { + $fstats = fstat($fm); + $size = $fstats['size']; + } + + if ($size <= 0) { throw new Exception("Invalid file size returned for file at $filePath"); } @@ -56,11 +64,9 @@ class Application_Common_FileIO header('Cache-Control: public, must-revalidate, max-age=0'); header('Pragma: no-cache'); header('Accept-Ranges: bytes'); - if ($size > 0) { - header('Content-Length:' . (($end - $begin) + 1)); - if (isset($_SERVER['HTTP_RANGE'])) { - header("Content-Range: bytes $begin-$end/$size"); - } + header('Content-Length:' . (($end - $begin) + 1)); + if (isset($_SERVER['HTTP_RANGE'])) { + header("Content-Range: bytes $begin-$end/$size"); } //We can have multiple levels of output buffering. Need to @@ -77,4 +83,4 @@ class Application_Common_FileIO } fclose($fm); } -} \ No newline at end of file +} From a3fd7478d622a9ced9e78bcfe578d606fe9807f1 Mon Sep 17 00:00:00 2001 From: Robbt Date: Mon, 3 Sep 2018 19:00:13 -0400 Subject: [PATCH 04/33] decided to simply return true if it finds a celery pid running --- airtime_mvc/build/airtime-setup/load.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airtime_mvc/build/airtime-setup/load.php b/airtime_mvc/build/airtime-setup/load.php index eaf3eab9e..d926cbb25 100644 --- a/airtime_mvc/build/airtime-setup/load.php +++ b/airtime_mvc/build/airtime-setup/load.php @@ -154,7 +154,7 @@ function checkLiquidsoapService() { function checkCeleryService() { exec("pgrep -f -u celery airtime-celery", $out, $status); if (array_key_exists(0, $out) && $status == 0) { - return posix_kill(rtrim($out[0]), 0); + return 1; } return $status == 0; } From 65968ee0faa6f0d7bab507cc1acc61908a26a983 Mon Sep 17 00:00:00 2001 From: David Date: Sun, 16 Sep 2018 21:55:27 +1000 Subject: [PATCH 05/33] add DS_Stores to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index e9c9e2ff7..7e6412ac8 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ composer.phar VERSION airtime_mvc/tests/log/*.log .vagrant/ +.DS_Store From 9f15b2d3dff844841f16af832d5b6c020e0ec048 Mon Sep 17 00:00:00 2001 From: David Date: Sun, 16 Sep 2018 21:55:55 +1000 Subject: [PATCH 06/33] begin docker xenial support --- install | 117 ++++++++++-------- ...uirements-ubuntu-xenial_docker_minimal.apt | 80 ++++++++++++ 2 files changed, 147 insertions(+), 50 deletions(-) create mode 100644 installer/lib/requirements-ubuntu-xenial_docker_minimal.apt diff --git a/install b/install index 15a1f61f5..d918a1420 100755 --- a/install +++ b/install @@ -52,7 +52,13 @@ showhelp () { Install Icecast 2 and deploy a basic configuration for Airtime --selinux Run restorecon on directories and files that need tagging to - allow the WEB_USER access." + allow the WEB_USER access + --no-postgres + Skips all postgres related install tasks (Useful if you configure + postgresql as part of another script / docker builds) + --no-rabbitmq + Skips all rabbitmq related install tasks. + " exit 0 } @@ -449,6 +455,12 @@ while :; do --selinux) selinux="t" ;; + --skip-postgres) + skip_postgres=1 + ;; + --skip-rabbitmq) + skip_rabbitmq=1 + ;; --) shift break @@ -986,70 +998,75 @@ else loudCmd "a2enmod rewrite php5" fi -loud "\n-----------------------------------------------------" -loud " * Configuring PostgreSQL * " -loud "-----------------------------------------------------" +if [ $skip_postgres -ne 1 ]; then + loud "\n-----------------------------------------------------" + loud " * Configuring PostgreSQL * " + loud "-----------------------------------------------------" -# Ensure postgres is running - It isn't after you install the postgres package on Ubuntu 15.04 -systemInitCommand start postgresql + # Ensure postgres is running - It isn't after you install the postgres package on Ubuntu 15.04 + systemInitCommand start postgresql -setupAirtimePostgresUser() { - # here-doc to execute this block as postgres user - su postgres <<'EOF' - set +e - count=$(psql -d postgres -tAc "SELECT count(*) FROM pg_roles WHERE rolname='airtime';") - if [[ $count -eq 0 ]]; then - psql -d postgres -tAc "CREATE USER airtime WITH ENCRYPTED PASSWORD 'airtime'; ALTER USER airtime CREATEDB;" - [[ $? -eq 0 ]] && - echo "Created airtime user in PostgreSQL" || - echo "$0:${FUNCNAME}(): ERROR: Can't create airtime user in PostgreSQL!" - else - echo "airtime user already exists in PostgreSQL" - fi - set -e + setupAirtimePostgresUser() { + # here-doc to execute this block as postgres user + su postgres <<'EOF' + set +e + count=$(psql -d postgres -tAc "SELECT count(*) FROM pg_roles WHERE rolname='airtime';") + if [[ $count -eq 0 ]]; then + psql -d postgres -tAc "CREATE USER airtime WITH ENCRYPTED PASSWORD 'airtime'; ALTER USER airtime CREATEDB;" + [[ $? -eq 0 ]] && + echo "Created airtime user in PostgreSQL" || + echo "$0:${FUNCNAME}(): ERROR: Can't create airtime user in PostgreSQL!" + else + echo "airtime user already exists in PostgreSQL" + fi + set -e # don't indent this! EOF -} + } -if [ "$postgres" = "t" ]; then - setupAirtimePostgresUser -elif [ ${_i} -eq 1 ]; then - echo -e "Create default airtime postgres user? (Y/n): \c" - read IN - if [ "$IN" = "y" -o "$IN" = "Y" ]; then + if [ "$postgres" = "t" ]; then setupAirtimePostgresUser + elif [ ${_i} -eq 1 ]; then + echo -e "Create default airtime postgres user? (Y/n): \c" + read IN + if [ "$IN" = "y" -o "$IN" = "Y" ]; then + setupAirtimePostgresUser + fi fi fi -loud "\n-----------------------------------------------------" -loud " * Configuring RabbitMQ * " -loud "-----------------------------------------------------" +if [ $skip_rabbitmq -ne 1 ]; then -RABBITMQ_VHOST=/airtime -RABBITMQ_USER=airtime -RABBITMQ_PASSWORD=airtime -EXCHANGES="airtime-pypo|pypo-fetch|airtime-analyzer|media-monitor" + loud "\n-----------------------------------------------------" + loud " * Configuring RabbitMQ * " + loud "-----------------------------------------------------" -# Ignore errors in this check to avoid dying when vhost isn't found -set +e -rabbitmqctl list_vhosts | grep -w "^${RABBITMQ_VHOST}$" > /dev/null -RESULT="$?" -set -e + RABBITMQ_VHOST=/airtime + RABBITMQ_USER=airtime + RABBITMQ_PASSWORD=airtime + EXCHANGES="airtime-pypo|pypo-fetch|airtime-analyzer|media-monitor" -# Only run these if the vhost doesn't exist -if [ "$RESULT" != "0" ]; then - verbose "\n * Creating RabbitMQ user ${RABBITMQ_USER}..." + # Ignore errors in this check to avoid dying when vhost isn't found + set +e + rabbitmqctl list_vhosts | grep -w "^${RABBITMQ_VHOST}$" > /dev/null + RESULT="$?" + set -e - rabbitmqctl add_vhost ${RABBITMQ_VHOST} - rabbitmqctl add_user ${RABBITMQ_USER} ${RABBITMQ_PASSWORD} -else - verbose "\nRabbitMQ user already exists, skipping creation" + # Only run these if the vhost doesn't exist + if [ "$RESULT" != "0" ]; then + verbose "\n * Creating RabbitMQ user ${RABBITMQ_USER}..." + + rabbitmqctl add_vhost ${RABBITMQ_VHOST} + rabbitmqctl add_user ${RABBITMQ_USER} ${RABBITMQ_PASSWORD} + else + verbose "\nRabbitMQ user already exists, skipping creation" + fi + + verbose "\n * Setting RabbitMQ user permissions..." + #loudCmd "rabbitmqctl set_permissions -p ${RABBITMQ_VHOST} ${RABBITMQ_USER} \"$EXCHANGES\" \"$EXCHANGES\" \"$EXCHANGES\"" + loudCmd "rabbitmqctl set_permissions -p ${RABBITMQ_VHOST} ${RABBITMQ_USER} .\* .\* .\*" fi -verbose "\n * Setting RabbitMQ user permissions..." -#loudCmd "rabbitmqctl set_permissions -p ${RABBITMQ_VHOST} ${RABBITMQ_USER} \"$EXCHANGES\" \"$EXCHANGES\" \"$EXCHANGES\"" -loudCmd "rabbitmqctl set_permissions -p ${RABBITMQ_VHOST} ${RABBITMQ_USER} .\* .\* .\*" - if [ ! -d "/etc/airtime" ]; then loud "\n-----------------------------------------------------" loud " * Installing Airtime * " diff --git a/installer/lib/requirements-ubuntu-xenial_docker_minimal.apt b/installer/lib/requirements-ubuntu-xenial_docker_minimal.apt new file mode 100644 index 000000000..0238132ba --- /dev/null +++ b/installer/lib/requirements-ubuntu-xenial_docker_minimal.apt @@ -0,0 +1,80 @@ +apache2 +libapache2-mod-php7.0 +php7.0 +php-pear +php7.0-gd +php-bcmath +php-mbstring + +lsb-release + +zip +unzip + +postgresql-client +php7.0-pgsql + +python +python-virtualenv +python-pip + +libsoundtouch-ocaml +libtaglib-ocaml +libao-ocaml +libmad-ocaml +ecasound +libportaudio2 +libsamplerate0 + +python-rgain +python-gst-1.0 +gstreamer1.0-plugins-ugly +python-pika + +patch + +php7.0-curl +mpg123 +curl + +libcamomile-ocaml-data +libpulse0 +vorbis-tools +lsof +# mp3gain need to be installed over an external ppa or the use of easymp3gain +easymp3gain-gtk +vorbisgain +flac +vorbis-tools +pwgen +libfaad2 +php-apcu + +lame + +coreutils + +liquidsoap +liquidsoap-plugin-alsa +liquidsoap-plugin-ao +liquidsoap-plugin-faad +liquidsoap-plugin-flac +liquidsoap-plugin-icecast +liquidsoap-plugin-lame +liquidsoap-plugin-mad +liquidsoap-plugin-ogg +liquidsoap-plugin-portaudio +liquidsoap-plugin-pulseaudio +liquidsoap-plugin-taglib +liquidsoap-plugin-voaacenc +liquidsoap-plugin-vorbis + +silan +libopus0 + +sysvinit-utils + +build-essential +libssl-dev +libffi-dev +python-dev From 6222e56ee4b9a92e3f0abeaf4177c684ce0fccef Mon Sep 17 00:00:00 2001 From: David Date: Sun, 16 Sep 2018 22:13:30 +1000 Subject: [PATCH 07/33] add defaults for no-postgres and no-rabbitmq options --- install | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/install b/install index d918a1420..8cab1edaa 100755 --- a/install +++ b/install @@ -91,6 +91,8 @@ upgrade="f" dist="" code="" apache_bin="" +skip_postgres=0 +skip_rabbitmq=0 function verbose() { @@ -455,10 +457,10 @@ while :; do --selinux) selinux="t" ;; - --skip-postgres) + --no-postgres) skip_postgres=1 ;; - --skip-rabbitmq) + --no-rabbitmq) skip_rabbitmq=1 ;; --) @@ -998,7 +1000,7 @@ else loudCmd "a2enmod rewrite php5" fi -if [ $skip_postgres -ne 1 ]; then +if [ $skip_postgres -eq 0 ]; then loud "\n-----------------------------------------------------" loud " * Configuring PostgreSQL * " loud "-----------------------------------------------------" @@ -1035,7 +1037,7 @@ EOF fi fi -if [ $skip_rabbitmq -ne 1 ]; then +if [ $skip_rabbitmq -eq 0 ]; then loud "\n-----------------------------------------------------" loud " * Configuring RabbitMQ * " From 7ad096bd5bdf11fc6c05c75a743e29ee736ebc6b Mon Sep 17 00:00:00 2001 From: David Date: Sun, 16 Sep 2018 22:19:10 +1000 Subject: [PATCH 08/33] add xenial minimal flags --- install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install b/install index 8cab1edaa..f46ac0d70 100755 --- a/install +++ b/install @@ -598,7 +598,7 @@ code="${code:-$VERSION_ID}" code="${code,,}" verbose "Validating dist-code: ${dist}-${code}" case "${dist}-${code}" in - ubuntu-16.04|ubuntu-xenial) + ubuntu-16.04|ubuntu-xenial|ubuntu-xenial_docker_minimal) code="xenial" is_ubuntu_dist=true is_ubuntu_xenial=true From 30742cbc34c1c14e63ad786b84eb42b79284d5ec Mon Sep 17 00:00:00 2001 From: Lucas Bickel Date: Sat, 6 Oct 2018 12:09:08 +0200 Subject: [PATCH 09/33] :memo: (vagrant) update matrix of supported distros --- docs/vagrant.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/docs/vagrant.md b/docs/vagrant.md index 5e4fc6bf7..5629deae2 100644 --- a/docs/vagrant.md +++ b/docs/vagrant.md @@ -33,13 +33,12 @@ With the above instructions LibreTime is installed on Ubuntu Trusty Tahir. The V | OS | Command | Comment | | ------ | ------------------- | ------- | -| Ubuntu 14.04 | `vagrant up ubuntu-trusty` | Current default install since it was used by legacy upstream, based on Trusty Tahir. | -| Debian 8.7 | `vagrant up debian-jessie` | Recommended install on Jessie as per the docs. | -| Ubuntu 16.04 | `vagrant up ubuntu-xenial` | Experimental install on current Ubuntu Xenial Xerus. | -| Debian 7.11 | `vagrant up debian-wheezy` | Recommended install on Wheezy as per the docs. | -| CentOS | `vagrant up centos` | Experimental install on 7.3 with native systemd support and activated SELinux. | -| Ubuntu | `vagrant up ubuntu` | Deprecated Ubuntu Trusty install, replaced by `ubuntu-trusty`. Do not use for new installs! | -| Debian | `vagrant up debian` | Deprecated Debian Jessie install, replaced by `debian-jessie`. Do not use for new installs! | +| Ubuntu 14.04 | `vagrant up ubuntu-trusty` | Current default install since it was used by legacy upstream, based on Ubuntu Trusty Tahir. | +| Debian 8.7 | `vagrant up debian-jessie` | Recommended install on Debian Jessie as per the docs. | +| Debian 9.2 | `vagrant up debian-stretch` | Experimental install on current Debian Stretch. | +| Ubuntu 16.04 | `vagrant up ubuntu-xenial` | Experimental install on current Ubuntu Xenial Xerus. | +| Debian 7.11 | `vagrant up debian-wheezy` | Deprecated install on Debian Wheezy. Please switch to debian-stretch. | +| CentOS | `vagrant up centos` | Extremely experimental install on 7.3 with native systemd support and activated SELinux. Needs manual intervention due to Liquidsoap 1.3.3. | ## Troubleshooting From f7ceeedb04faa02777e212986dd6b96da3aaf362 Mon Sep 17 00:00:00 2001 From: Lucas Bickel Date: Sat, 6 Oct 2018 12:45:22 +0200 Subject: [PATCH 10/33] :heavy_minus_sign: (Amazon S3) drop broken S3 support --- .../cloud_storage/Amazon_S3StorageBackend.php | 131 ------------------ .../cloud_storage/ProxyStorageBackend.php | 10 +- airtime_mvc/application/configs/conf.php | 7 - airtime_mvc/build/airtime.example.conf | 5 - airtime_mvc/tests/conf/airtime.conf | 6 - .../airtime_analyzer/airtime_analyzer.py | 12 +- .../airtime_analyzer/analyzer_pipeline.py | 12 +- .../cloud_storage_uploader.py | 122 ---------------- .../cloud_storage_uploader_libcloud.py | 121 ---------------- .../airtime_analyzer/message_listener.py | 14 +- .../airtime_analyzer/bin/airtime_analyzer | 9 -- python_apps/airtime_analyzer/setup.py | 2 - .../tests/analyzer_pipeline_tests.py | 7 +- .../tests/cloud_storage_uploader_tests.py | 18 --- 14 files changed, 14 insertions(+), 462 deletions(-) delete mode 100644 airtime_mvc/application/cloud_storage/Amazon_S3StorageBackend.php delete mode 100644 python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader.py delete mode 100644 python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader_libcloud.py delete mode 100644 python_apps/airtime_analyzer/tests/cloud_storage_uploader_tests.py diff --git a/airtime_mvc/application/cloud_storage/Amazon_S3StorageBackend.php b/airtime_mvc/application/cloud_storage/Amazon_S3StorageBackend.php deleted file mode 100644 index 49d0ef230..000000000 --- a/airtime_mvc/application/cloud_storage/Amazon_S3StorageBackend.php +++ /dev/null @@ -1,131 +0,0 @@ -setBucket($securityCredentials['bucket']); - $this->setAccessKey($securityCredentials['api_key']); - $this->setSecretKey($securityCredentials['api_key_secret']); - - $s3Options = array( - 'key' => $securityCredentials['api_key'], - 'secret' => $securityCredentials['api_key_secret'], - 'region' => $securityCredentials['region'] - ); - if (array_key_exists("proxy_host", $securityCredentials)) { - $s3Options = array_merge($s3Options, array( - //'base_url' => "http://" . $securityCredentials['proxy_host'], - 'base_url' => "http://s3.amazonaws.com", - 'scheme' => "http", - //'force_path_style' => true, - 'signature' => 'v4' - )); - $this->proxyHost = $securityCredentials['proxy_host']; - } - - $this->s3Client = S3Client::factory($s3Options); - } - - public function getAbsoluteFilePath($resourceId) - { - return $this->s3Client->getObjectUrl($this->getBucket(), $resourceId); - } - - /** Returns a signed download URL from Amazon S3, expiring in 60 minutes */ - public function getDownloadURLs($resourceId, $contentDispositionFilename) - { - $urls = array(); - - $s3args = array('ResponseContentDisposition' => 'attachment; filename="' . urlencode($contentDispositionFilename) . '"'); - $signedS3Url = $this->s3Client->getObjectUrl($this->getBucket(), $resourceId, '+60 minutes', $s3args); - - //If we're using the proxy cache, we need to modify the request URL after it has - //been generated by the above. (The request signature must be for the amazonaws.com, - //not our proxy, since the proxy translates the host back to amazonaws.com) - if ($this->proxyHost) { - $p = parse_url($signedS3Url); - $p["host"] = $this->getBucket() . "." . $this->proxyHost; - $p["scheme"] = "http"; - //If the path contains the bucket name (which is the case with HTTPS requests to Amazon), - //we need to strip that part out, since we're forcing everything to HTTP. The Amazon S3 - //URL convention for HTTP is to prepend the bucket name to the hostname instead of having - //it in the path. - //eg. http://bucket.s3.amazonaws.com/ instead of https://s3.amazonaws.com/bucket/ - if (strpos($p["path"], $this->getBucket()) == 1) { - $p["path"] = substr($p["path"], 1 + strlen($this->getBucket())); - } - $proxyUrl = $p["scheme"] . "://" . $p["host"] . $p["path"] . "?" . $p["query"]; - //Add this proxy cache URL to the list of download URLs.s - array_push($urls, $proxyUrl); - } - - //Add the direct S3 URL to the list (as a fallback) - array_push($urls, $signedS3Url); - - //http_build_url() would be nice to use but it requires pecl_http :-( - - //Logging::info($url); - - return $urls; - } - - public function deletePhysicalFile($resourceId) - { - $bucket = $this->getBucket(); - - if ($this->s3Client->doesObjectExist($bucket, $resourceId)) { - - $result = $this->s3Client->deleteObject(array( - 'Bucket' => $bucket, - 'Key' => $resourceId, - )); - } else { - throw new Exception("ERROR: Could not locate file to delete."); - } - } - - // This should only be called for station termination. - // We are only deleting the file objects from Amazon S3. - // Records in the database will remain in case we have to restore the files. - public function deleteAllCloudFileObjects() - { - $bucket = $this->getBucket(); - $prefix = $this->getFilePrefix(); - - //Add a trailing slash in for safety - //(so that deleting /13/413 doesn't delete /13/41313 !) - $prefix = $prefix . "/"; - - //Do a bunch of safety checks to ensure we don't delete more than we intended. - //An valid prefix is like "12/4312" for instance 4312. - $slashPos = strpos($prefix, "/"); - if (($slashPos === FALSE) || //Slash must exist - ($slashPos != 2) || //Slash must be the third character - (strlen($prefix) <= $slashPos) || //String must have something after the first slash - (substr_count($prefix, "/") != 2)) //String must have two slashes - { - throw new Exception("Invalid file prefix in " . __FUNCTION__); - } - $this->s3Client->deleteMatchingObjects($bucket, $prefix); - } - - public function getFilePrefix() - { - $filePrefix = ''; - // only prefix files on S3 when billing is active since saas customers share a s3 bucket - // I'm not sure why the choice was made to put everything into one bucket - // We might refactor this to use a bucket per customer if we revisit S3 - if (LIBRETIME_ENABLE_BILLING === true) { - $hostingId = Billing::getClientInstanceId(); - $filePrefix = substr($hostingId, -2)."/".$hostingId; - } - return $filePrefix; - } -} diff --git a/airtime_mvc/application/cloud_storage/ProxyStorageBackend.php b/airtime_mvc/application/cloud_storage/ProxyStorageBackend.php index fa3e7656c..eb5cf55b3 100644 --- a/airtime_mvc/application/cloud_storage/ProxyStorageBackend.php +++ b/airtime_mvc/application/cloud_storage/ProxyStorageBackend.php @@ -18,12 +18,10 @@ class ProxyStorageBackend extends StorageBackend { $CC_CONFIG = Config::getConfig(); - //The storage backend in the airtime.conf directly corresponds to - //the name of the class that implements it (eg. Amazon_S3), so we - //can easily create the right backend object dynamically: - if ($storageBackend == "amazon_S3") { - $this->storageBackend = new Amazon_S3StorageBackend($CC_CONFIG["amazon_S3"]); - } else if ($storageBackend == "file") { + // The storage backend in the airtime.conf directly corresponds to + // the name of the class that implements it, so we can create the + // right backend object dynamically: + if ($storageBackend == "file") { $this->storageBackend = new FileStorageBackend(); } else { $this->storageBackend = new $storageBackend($CC_CONFIG[$storageBackend]); diff --git a/airtime_mvc/application/configs/conf.php b/airtime_mvc/application/configs/conf.php index a41f67f5f..964225e8c 100644 --- a/airtime_mvc/application/configs/conf.php +++ b/airtime_mvc/application/configs/conf.php @@ -49,13 +49,6 @@ class Config { $CC_CONFIG['staticBaseDir'] = '/'; } - $CC_CONFIG['amazon_S3'] = array( - 'provider' => $values['amazon_S3']['provider'], - 'bucket' => $values['amazon_S3']['bucket'], - 'api_key' => $values['amazon_S3']['api_key'], - 'api_key_secret' => $values['amazon_S3']['api_key_secret'] - ); - // Tells us where file uploads will be uploaded to. // It will either be set to a cloud storage backend or local file storage. $CC_CONFIG["current_backend"] = $values["current_backend"]["storage_backend"]; diff --git a/airtime_mvc/build/airtime.example.conf b/airtime_mvc/build/airtime.example.conf index 4001f8968..96487f3ce 100644 --- a/airtime_mvc/build/airtime.example.conf +++ b/airtime_mvc/build/airtime.example.conf @@ -127,11 +127,6 @@ vhost = /airtime [current_backend] storage_backend=file -[amazon_S3] -provider=amazon_S3 -bucket=0 -api_key=0 -api_key_secret=0 # ---------------------------------------------------------------------- # M O N I T diff --git a/airtime_mvc/tests/conf/airtime.conf b/airtime_mvc/tests/conf/airtime.conf index 5ddfd462c..e64a4b897 100644 --- a/airtime_mvc/tests/conf/airtime.conf +++ b/airtime_mvc/tests/conf/airtime.conf @@ -26,12 +26,6 @@ station_id = teststation [current_backend] storage_backend=file -[amazon_S3] -provider=amazon_S3 -bucket=0 -api_key=0 -api_key_secret=0 - [monit] monit_user = guest monit_password = airtime diff --git a/python_apps/airtime_analyzer/airtime_analyzer/airtime_analyzer.py b/python_apps/airtime_analyzer/airtime_analyzer/airtime_analyzer.py index 4cc46c8f3..eafa8f743 100644 --- a/python_apps/airtime_analyzer/airtime_analyzer/airtime_analyzer.py +++ b/python_apps/airtime_analyzer/airtime_analyzer/airtime_analyzer.py @@ -23,7 +23,7 @@ class AirtimeAnalyzerServer: # Variables _log_level = logging.INFO - def __init__(self, rmq_config_path, cloud_storage_config_path, http_retry_queue_path, debug=False): + def __init__(self, rmq_config_path, http_retry_queue_path, debug=False): # Dump a stacktrace with 'kill -SIGUSR2 ' signal.signal(signal.SIGUSR2, lambda sig, frame: AirtimeAnalyzerServer.dump_stacktrace()) @@ -34,15 +34,12 @@ class AirtimeAnalyzerServer: # Read our rmq config file rmq_config = config_file.read_config_file(rmq_config_path) - # Read the cloud storage config file - cloud_storage_config = config_file.read_config_file(cloud_storage_config_path) - # Start up the StatusReporter process StatusReporter.start_thread(http_retry_queue_path) # Start listening for RabbitMQ messages telling us about newly # uploaded files. This blocks until we recieve a shutdown signal. - self._msg_listener = MessageListener(rmq_config, cloud_storage_config) + self._msg_listener = MessageListener(rmq_config) StatusReporter.stop_thread() @@ -61,9 +58,6 @@ class AirtimeAnalyzerServer: pika_logger = logging.getLogger('pika') pika_logger.setLevel(logging.CRITICAL) - boto_logger = logging.getLogger('auth') - boto_logger.setLevel(logging.CRITICAL) - # Set up logging logFormatter = logging.Formatter("%(asctime)s [%(module)s] [%(levelname)-5.5s] %(message)s") rootLogger = logging.getLogger() @@ -89,5 +83,3 @@ class AirtimeAnalyzerServer: if line: code.append(" %s" % (line.strip())) logging.info('\n'.join(code)) - - diff --git a/python_apps/airtime_analyzer/airtime_analyzer/analyzer_pipeline.py b/python_apps/airtime_analyzer/airtime_analyzer/analyzer_pipeline.py index 65511d707..20973fdb4 100644 --- a/python_apps/airtime_analyzer/airtime_analyzer/analyzer_pipeline.py +++ b/python_apps/airtime_analyzer/airtime_analyzer/analyzer_pipeline.py @@ -7,7 +7,6 @@ import Queue import ConfigParser from metadata_analyzer import MetadataAnalyzer from filemover_analyzer import FileMoverAnalyzer -from cloud_storage_uploader import CloudStorageUploader from cuepoint_analyzer import CuePointAnalyzer from replaygain_analyzer import ReplayGainAnalyzer from playability_analyzer import * @@ -25,7 +24,7 @@ class AnalyzerPipeline: IMPORT_STATUS_FAILED = 2 @staticmethod - def run_analysis(queue, audio_file_path, import_directory, original_filename, storage_backend, file_prefix, cloud_storage_config): + def run_analysis(queue, audio_file_path, import_directory, original_filename, storage_backend, file_prefix): """Analyze and import an audio file, and put all extracted metadata into queue. Keyword arguments: @@ -40,7 +39,6 @@ class AnalyzerPipeline: to know what the original name was. storage_backend: String indicating the storage backend (amazon_s3 or file) file_prefix: - cloud_storage_config: ConfigParser object containing the cloud storage configuration settings """ # It is super critical to initialize a separate log file here so that we # don't inherit logging/locks from the parent process. Supposedly @@ -58,8 +56,6 @@ class AnalyzerPipeline: raise TypeError("original_filename must be unicode. Was of type " + type(original_filename).__name__ + " instead.") if not isinstance(file_prefix, unicode): raise TypeError("file_prefix must be unicode. Was of type " + type(file_prefix).__name__ + " instead.") - if not isinstance(cloud_storage_config, ConfigParser.SafeConfigParser): - raise TypeError("cloud_storage_config must be a SafeConfigParser. Was of type " + type(cloud_storage_config).__name__ + " instead.") # Analyze the audio file we were told to analyze: @@ -72,11 +68,7 @@ class AnalyzerPipeline: metadata = ReplayGainAnalyzer.analyze(audio_file_path, metadata) metadata = PlayabilityAnalyzer.analyze(audio_file_path, metadata) - if storage_backend.lower() == u"amazon_s3": - csu = CloudStorageUploader(cloud_storage_config) - metadata = csu.upload_obj(audio_file_path, metadata) - else: - metadata = FileMoverAnalyzer.move(audio_file_path, import_directory, original_filename, metadata) + metadata = FileMoverAnalyzer.move(audio_file_path, import_directory, original_filename, metadata) metadata["import_status"] = 0 # Successfully imported diff --git a/python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader.py b/python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader.py deleted file mode 100644 index 55e26a9d0..000000000 --- a/python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader.py +++ /dev/null @@ -1,122 +0,0 @@ -import os -import logging -import uuid -import socket -from boto.s3.connection import S3Connection -from boto.s3.key import Key - -# Fix for getaddrinfo deadlock. See these issues for details: -# https://github.com/gevent/gevent/issues/349 -# https://github.com/docker/docker-registry/issues/400 -u'fix getaddrinfo deadlock'.encode('idna') - -CLOUD_CONFIG_PATH = os.path.join(os.getenv('LIBRETIME_CONF_DIR', '/etc/airtime'), 'airtime.conf') -STORAGE_BACKEND_FILE = "file" -SOCKET_TIMEOUT = 240 - -class CloudStorageUploader: - """ A class that uses Python-Boto SDK to upload objects into Amazon S3. - - It is important to note that every file, coming from different Airtime Pro - stations, will get uploaded into the same bucket on the same Amazon S3 - account. - - Attributes: - _host: Host name for the specific region assigned to the bucket. - _bucket: Name of container on Amazon S3 where files will get uploaded into. - _api_key: Access key to objects on Amazon S3. - _api_key_secret: Secret access key to objects on Amazon S3. - """ - - def __init__(self, config): - - try: - cloud_storage_config_section = config.get("current_backend", "storage_backend") - self._storage_backend = cloud_storage_config_section - except Exception as e: - print e - print "Defaulting to file storage" - self._storage_backend = STORAGE_BACKEND_FILE - - if self._storage_backend == STORAGE_BACKEND_FILE: - self._host = "" - self._bucket = "" - self._api_key = "" - self._api_key_secret = "" - else: - self._host = config.get(cloud_storage_config_section, 'host') - self._bucket = config.get(cloud_storage_config_section, 'bucket') - self._api_key = config.get(cloud_storage_config_section, 'api_key') - self._api_key_secret = config.get(cloud_storage_config_section, 'api_key_secret') - - - def enabled(self): - if self._storage_backend == "file": - return False - else: - return True - - - def upload_obj(self, audio_file_path, metadata): - """Uploads a file into Amazon S3 object storage. - - Before a file is uploaded onto Amazon S3 we generate a unique object - name consisting of the filename and a unqiue string using the uuid4 - module. - - Keyword arguments: - audio_file_path: Path on disk to the audio file that is about to be - uploaded to Amazon S3 object storage. - metadata: ID3 tags and other metadata extracted from the audio file. - - Returns: - The metadata dictionary it received with two new keys: - filename: The file's filename. - resource_id: The unique object name used to identify the objects - on Amazon S3 - """ - - file_base_name = os.path.basename(audio_file_path) - file_name, extension = os.path.splitext(file_base_name) - - # With Amazon S3 you cannot create a signed url if there are spaces - # in the object name. URL encoding the object name doesn't solve the - # problem. As a solution we will replace spaces with dashes. - file_name = file_name.replace(" ", "-") - - unique_id = str(uuid.uuid4()) - - # We add another prefix to the resource name with the last two characters - # of the unique id so files are not all placed under the root folder. We - # do this in case we need to restore a customer's file/s; File restoration - # is done via the S3 Browser client. The client will hang if there are too - # many files under the same folder. - unique_id_prefix = unique_id[-2:] - - resource_id = "%s/%s/%s_%s%s" % (metadata['file_prefix'], unique_id_prefix, file_name, unique_id, extension) - - # Boto uses the "global default timeout" by default, which is infinite! To prevent network problems from - # turning into deadlocks, we explicitly set the global default timeout period here: - socket.setdefaulttimeout(SOCKET_TIMEOUT) - - conn = S3Connection(self._api_key, self._api_key_secret, host=self._host) - bucket = conn.get_bucket(self._bucket) - - key = Key(bucket) - key.key = resource_id - key.set_metadata('filename', file_base_name) - key.set_contents_from_filename(audio_file_path) - - # Remove file from organize directory - try: - os.remove(audio_file_path) - except OSError: - logging.info("Could not remove %s from organize directory" % audio_file_path) - - # Pass original filename to Airtime so we can store it in the db - metadata["filename"] = file_base_name - - metadata["resource_id"] = resource_id - metadata["storage_backend"] = self._storage_backend - return metadata - diff --git a/python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader_libcloud.py b/python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader_libcloud.py deleted file mode 100644 index 162493dd5..000000000 --- a/python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader_libcloud.py +++ /dev/null @@ -1,121 +0,0 @@ -import os -import logging -import uuid -import ConfigParser -from libcloud.storage.providers import get_driver -from libcloud.storage.types import Provider, ContainerDoesNotExistError, ObjectDoesNotExistError - - -CLOUD_CONFIG_PATH = os.path.join(os.getenv('LIBRETIME_CONF_DIR', '/etc/airtime'), 'airtime.conf') -STORAGE_BACKEND_FILE = "file" - -class CloudStorageUploader: - """ A class that uses Apache Libcloud's Storage API to upload objects into - a cloud storage backend. For this implementation all files will be uploaded - into a bucket on Amazon S3. - - It is important to note that every file, coming from different Airtime Pro - stations, will get uploaded into the same bucket on the same Amazon S3 - account. - - Attributes: - _provider: Storage backend. For exmaple, Amazon S3, Google Storage. - _bucket: Name of container on provider where files will get uploaded into. - _api_key: Access key to objects on the provider's storage backend. - _api_key_secret: Secret access key to objects on the provider's storage backend. - """ - - def __init__(self): - - config = ConfigParser.SafeConfigParser() - try: - config.readfp(open(CLOUD_CONFIG_PATH)) - cloud_storage_config_section = config.get("current_backend", "storage_backend") - self._storage_backend = cloud_storage_config_section - except IOError as e: - print "Failed to open config file at " + CLOUD_CONFIG_PATH + ": " + e.strerror - print "Defaulting to file storage" - self._storage_backend = STORAGE_BACKEND_FILE - except Exception as e: - print e - print "Defaulting to file storage" - self._storage_backend = STORAGE_BACKEND_FILE - - if self._storage_backend == STORAGE_BACKEND_FILE: - self._provider = "" - self._bucket = "" - self._api_key = "" - self._api_key_secret = "" - else: - self._provider = config.get(cloud_storage_config_section, 'provider') - self._bucket = config.get(cloud_storage_config_section, 'bucket') - self._api_key = config.get(cloud_storage_config_section, 'api_key') - self._api_key_secret = config.get(cloud_storage_config_section, 'api_key_secret') - - def enabled(self): - if self._storage_backend == "file": - return False - else: - return True - - - def upload_obj(self, audio_file_path, metadata): - """Uploads a file into Amazon S3 object storage. - - Before a file is uploaded onto Amazon S3 we generate a unique object - name consisting of the filename and a unqiue string using the uuid4 - module. - - Keyword arguments: - audio_file_path: Path on disk to the audio file that is about to be - uploaded to Amazon S3 object storage. - metadata: ID3 tags and other metadata extracted from the audio file. - - Returns: - The metadata dictionary it received with three new keys: - filesize: The file's filesize in bytes. - filename: The file's filename. - resource_id: The unique object name used to identify the objects - on Amazon S3 - """ - - file_base_name = os.path.basename(audio_file_path) - file_name, extension = os.path.splitext(file_base_name) - - # With Amazon S3 you cannot create a signed url if there are spaces - # in the object name. URL encoding the object name doesn't solve the - # problem. As a solution we will replace spaces with dashes. - file_name = file_name.replace(" ", "-") - object_name = "%s_%s%s" % (file_name, str(uuid.uuid4()), extension) - - provider_driver_class = get_driver(getattr(Provider, self._provider)) - driver = provider_driver_class(self._api_key, self._api_key_secret) - - try: - container = driver.get_container(self._bucket) - except ContainerDoesNotExistError: - container = driver.create_container(self._bucket) - - extra = {'meta_data': {'filename': file_base_name}} - - obj = driver.upload_object(file_path=audio_file_path, - container=container, - object_name=object_name, - verify_hash=False, - extra=extra) - - metadata["filesize"] = os.path.getsize(audio_file_path) - - # Remove file from organize directory - try: - os.remove(audio_file_path) - except OSError: - logging.info("Could not remove %s from organize directory" % audio_file_path) - - # Pass original filename to Airtime so we can store it in the db - metadata["filename"] = file_base_name - - metadata["resource_id"] = object_name - metadata["storage_backend"] = self._storage_backend - return metadata - diff --git a/python_apps/airtime_analyzer/airtime_analyzer/message_listener.py b/python_apps/airtime_analyzer/airtime_analyzer/message_listener.py index cca829ab7..c261f737b 100644 --- a/python_apps/airtime_analyzer/airtime_analyzer/message_listener.py +++ b/python_apps/airtime_analyzer/airtime_analyzer/message_listener.py @@ -9,7 +9,6 @@ import multiprocessing import Queue from analyzer_pipeline import AnalyzerPipeline from status_reporter import StatusReporter -from cloud_storage_uploader import CloudStorageUploader EXCHANGE = "airtime-uploads" EXCHANGE_TYPE = "topic" @@ -56,13 +55,12 @@ QUEUE = "airtime-uploads" """ class MessageListener: - def __init__(self, rmq_config, cloud_storage_config): + def __init__(self, rmq_config): ''' Start listening for file upload notification messages from RabbitMQ Keyword arguments: rmq_config: A ConfigParser object containing the [rabbitmq] configuration. - cloud_storage_config: A ConfigParser object containing the cloud storage configuration. ''' self._shutdown = False @@ -76,8 +74,6 @@ class MessageListener: self._password = rmq_config.get(RMQ_CONFIG_SECTION, 'password') self._vhost = rmq_config.get(RMQ_CONFIG_SECTION, 'vhost') - self.cloud_storage_config = cloud_storage_config - # Set up a signal handler so we can shutdown gracefully # For some reason, this signal handler must be set up here. I'd rather # put it in AirtimeAnalyzerServer, but it doesn't work there (something to do @@ -172,7 +168,7 @@ class MessageListener: file_prefix = msg_dict["file_prefix"] storage_backend = msg_dict["storage_backend"] - audio_metadata = MessageListener.spawn_analyzer_process(audio_file_path, import_directory, original_filename, storage_backend, file_prefix, self.cloud_storage_config) + audio_metadata = MessageListener.spawn_analyzer_process(audio_file_path, import_directory, original_filename, storage_backend, file_prefix) StatusReporter.report_success_to_callback_url(callback_url, api_key, audio_metadata) except KeyError as e: @@ -211,12 +207,12 @@ class MessageListener: channel.basic_ack(delivery_tag=method_frame.delivery_tag) @staticmethod - def spawn_analyzer_process(audio_file_path, import_directory, original_filename, storage_backend, file_prefix, cloud_storage_config): + def spawn_analyzer_process(audio_file_path, import_directory, original_filename, storage_backend, file_prefix): ''' Spawn a child process to analyze and import a new audio file. ''' ''' q = multiprocessing.Queue() p = multiprocessing.Process(target=AnalyzerPipeline.run_analysis, - args=(q, audio_file_path, import_directory, original_filename, storage_backend, file_prefix, cloud_storage_config)) + args=(q, audio_file_path, import_directory, original_filename, storage_backend, file_prefix)) p.start() p.join() if p.exitcode == 0: @@ -230,7 +226,7 @@ class MessageListener: q = Queue.Queue() try: - AnalyzerPipeline.run_analysis(q, audio_file_path, import_directory, original_filename, storage_backend, file_prefix, cloud_storage_config) + AnalyzerPipeline.run_analysis(q, audio_file_path, import_directory, original_filename, storage_backend, file_prefix) metadata = q.get() except Exception as e: logging.error("Analyzer pipeline exception: %s" % str(e)) diff --git a/python_apps/airtime_analyzer/bin/airtime_analyzer b/python_apps/airtime_analyzer/bin/airtime_analyzer index ed2c296bb..b3e4ab0aa 100755 --- a/python_apps/airtime_analyzer/bin/airtime_analyzer +++ b/python_apps/airtime_analyzer/bin/airtime_analyzer @@ -10,7 +10,6 @@ import airtime_analyzer.airtime_analyzer as aa VERSION = "1.0" LIBRETIME_CONF_DIR = os.getenv('LIBRETIME_CONF_DIR', '/etc/airtime') DEFAULT_RMQ_CONFIG_PATH = os.path.join(LIBRETIME_CONF_DIR, 'airtime.conf') -DEFAULT_CLOUD_STORAGE_CONFIG_PATH = os.path.join(LIBRETIME_CONF_DIR, 'airtime.conf') DEFAULT_HTTP_RETRY_PATH = '/tmp/airtime_analyzer_http_retries' def run(): @@ -20,7 +19,6 @@ def run(): parser.add_argument("-d", "--daemon", help="run as a daemon", action="store_true") parser.add_argument("--debug", help="log full debugging output", action="store_true") parser.add_argument("--rmq-config-file", help="specify a configuration file with RabbitMQ settings (default is %s)" % DEFAULT_RMQ_CONFIG_PATH) - parser.add_argument("--cloud-storage-config-file", help="specify a configuration file with cloud storage settings (default is %s)" % DEFAULT_CLOUD_STORAGE_CONFIG_PATH) parser.add_argument("--http-retry-queue-file", help="specify where incompleted HTTP requests will be serialized (default is %s)" % DEFAULT_HTTP_RETRY_PATH) args = parser.parse_args() @@ -28,25 +26,20 @@ def run(): #Default config file path rmq_config_path = DEFAULT_RMQ_CONFIG_PATH - cloud_storage_config_path = DEFAULT_CLOUD_STORAGE_CONFIG_PATH http_retry_queue_path = DEFAULT_HTTP_RETRY_PATH if args.rmq_config_file: rmq_config_path = args.rmq_config_file - if args.cloud_storage_config_file: - cloud_storage_config_path = args.cloud_storage_config_file if args.http_retry_queue_file: http_retry_queue_path = args.http_retry_queue_file if args.daemon: with daemon.DaemonContext(): aa.AirtimeAnalyzerServer(rmq_config_path=rmq_config_path, - cloud_storage_config_path = cloud_storage_config_path, http_retry_queue_path=http_retry_queue_path, debug=args.debug) else: # Run without daemonizing aa.AirtimeAnalyzerServer(rmq_config_path=rmq_config_path, - cloud_storage_config_path = cloud_storage_config_path, http_retry_queue_path=http_retry_queue_path, debug=args.debug) @@ -71,5 +64,3 @@ def check_if_media_monitor_is_running(): continue run() - - diff --git a/python_apps/airtime_analyzer/setup.py b/python_apps/airtime_analyzer/setup.py index f4171148c..b51d6fade 100644 --- a/python_apps/airtime_analyzer/setup.py +++ b/python_apps/airtime_analyzer/setup.py @@ -37,9 +37,7 @@ setup(name='airtime_analyzer', 'mock', 'python-daemon==1.6', 'requests>=2.7.0', - 'apache-libcloud', 'rgain', - 'boto', # These next 3 are required for requests to support SSL with SNI. Learned this the hard way... # What sucks is that GCC is required to pip install these. #'ndg-httpsclient', diff --git a/python_apps/airtime_analyzer/tests/analyzer_pipeline_tests.py b/python_apps/airtime_analyzer/tests/analyzer_pipeline_tests.py index e7f2b66e0..8e986bc11 100644 --- a/python_apps/airtime_analyzer/tests/analyzer_pipeline_tests.py +++ b/python_apps/airtime_analyzer/tests/analyzer_pipeline_tests.py @@ -22,15 +22,10 @@ def teardown(): def test_basic(): filename = os.path.basename(DEFAULT_AUDIO_FILE) q = Queue.Queue() - #cloud_storage_config_path = os.path.join(os.getenv('LIBRETIME_CONF_DIR', '/etc/airtime'), '/production/cloud_storage.conf') - #cloud_storage_config = config_file.read_config_file(cloud_storage_config_path) - cloud_storage_config = SafeConfigParser() - cloud_storage_config.add_section("current_backend") - cloud_storage_config.set("current_backend", "storage_backend", "file") file_prefix = u'' storage_backend = "file" #This actually imports the file into the "./Test Artist" directory. - AnalyzerPipeline.run_analysis(q, DEFAULT_AUDIO_FILE, u'.', filename, storage_backend, file_prefix, cloud_storage_config) + AnalyzerPipeline.run_analysis(q, DEFAULT_AUDIO_FILE, u'.', filename, storage_backend, file_prefix) metadata = q.get() assert metadata['track_title'] == u'Test Title' assert metadata['artist_name'] == u'Test Artist' diff --git a/python_apps/airtime_analyzer/tests/cloud_storage_uploader_tests.py b/python_apps/airtime_analyzer/tests/cloud_storage_uploader_tests.py deleted file mode 100644 index 2854943ef..000000000 --- a/python_apps/airtime_analyzer/tests/cloud_storage_uploader_tests.py +++ /dev/null @@ -1,18 +0,0 @@ -from nose.tools import * -from ConfigParser import SafeConfigParser -from airtime_analyzer.cloud_storage_uploader import CloudStorageUploader -from airtime_analyzer.airtime_analyzer import AirtimeAnalyzerServer -from airtime_analyzer import config_file - -def setup(): - pass - -def teardown(): - pass - -def test_analyze(): - - cloud_storage_config = SafeConfigParser() - cloud_storage_config.add_section("current_backend") - cloud_storage_config.set("current_backend", "storage_backend", "file") - cl = CloudStorageUploader(cloud_storage_config) From a82633e1cc70933b332617d944158b065cb94dd5 Mon Sep 17 00:00:00 2001 From: Lucas Bickel Date: Sat, 6 Oct 2018 12:52:07 +0200 Subject: [PATCH 11/33] :green_heart: (docs) remove deleted docs from toc --- mkdocs.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index 98583a693..ee4dd323d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -47,9 +47,6 @@ pages: - 'Installation': - 'Install': install.md - 'Preparing the Server': manual/preparing-the-server/index.md - - 'Easy Setup': manual/easy-setup/index.md - - 'Automated Installation': manual/automated-installation/index.md - - 'Manual Installation': manual/manual-installation/index.md - 'Setting the Server Time': manual/setting-the-server-time/index.md - 'Administration': - 'The airtime-log Command': manual/the-airtime-log-command/index.md From afa67eb96db4b93e118b3d5f2794c49c0b1868de Mon Sep 17 00:00:00 2001 From: Lucas Bickel Date: Sat, 6 Oct 2018 21:18:44 +0200 Subject: [PATCH 12/33] :fire: remove dead code --- .../application/controllers/ApiController.php | 22 ------------------- airtime_mvc/application/models/RabbitMq.php | 6 ----- 2 files changed, 28 deletions(-) diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php index 7188e03ae..bee424f85 100644 --- a/airtime_mvc/application/controllers/ApiController.php +++ b/airtime_mvc/application/controllers/ApiController.php @@ -927,28 +927,6 @@ class ApiController extends Zend_Controller_Action Logging::info("Registered Component: ".$component."@".$remoteAddr); Application_Model_ServiceRegister::Register($component, $remoteAddr); - - //send ip, subdomain - if ($component == "pypo"){ - $split = explode('.', $_SERVER['SERVER_NAME']); - $subdomain = array(); - foreach ($split as $value) { - if ($value == 'airtime') { - break; - } else { - $subdomain[] = $value; - } - } - if (count($subdomain) > 0){ - $subDomain = implode('.',$subdomain); - - $md = array(); - $md["sub_domain"] = $subDomain; - $md["pypo_ip"] = $remoteAddr; - - Application_Model_RabbitMq::SendMessageToHaproxyConfigDaemon($md); - } - } } public function updateLiquidsoapStatusAction() diff --git a/airtime_mvc/application/models/RabbitMq.php b/airtime_mvc/application/models/RabbitMq.php index bef33c623..8e2a2336e 100644 --- a/airtime_mvc/application/models/RabbitMq.php +++ b/airtime_mvc/application/models/RabbitMq.php @@ -129,10 +129,4 @@ class Application_Model_RabbitMq $conn->close(); } - - - public static function SendMessageToHaproxyConfigDaemon($md){ - //XXX: This function has been deprecated and is no longer needed - } - } From fb402a78d23935a73f1d4982da191587d6e55549 Mon Sep 17 00:00:00 2001 From: Lucas Bickel Date: Fri, 12 Oct 2018 20:03:07 +0200 Subject: [PATCH 13/33] :package: (ci) add PHP 7.2 to travis build matrix --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 39525a775..3a5967e19 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,7 @@ dist: trusty language: php php: # the latest and greatest, has some issues that are excluded below in matrix.allow_failures +- 7.2 - 7.1 # the 7.0 build demonstrates that everything is basically ok for 7.0, users might want to wait for 7.1 to run it - 7.0 @@ -24,6 +25,9 @@ matrix: # there are currently some testing issues with DateTime precision on 7.1 - env: PYTHON=false php: 7.1 + # there are some issues with phpunit as well as some deep in zf1 on 7.2 + - env: PYTHON=false + php: 7.2 exclude: # by excluding all of python we make way to just runu python tests in one seperate instance - env: PYTHON=true From 71ce3082c5e0611f77eb423a15b4b36267ebfda4 Mon Sep 17 00:00:00 2001 From: ryan Date: Fri, 12 Oct 2018 13:09:19 -0500 Subject: [PATCH 14/33] (docs) deprecate ubuntu 14 --- docs/install.md | 9 +++++++-- docs/manual/preparing-the-server/index.md | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/install.md b/docs/install.md index 3801898c2..48fe281f6 100644 --- a/docs/install.md +++ b/docs/install.md @@ -1,11 +1,16 @@ # Installing LibreTime -LibreTime should generally be installed on a dedicated host. By default, its installer will install and configure all its dependencies. At the moment, the installer works best on Ubuntu 16.04 LTS (Xenial Xerus), or Ubuntu 14.04.5 LTS (Trusty Tahr). +LibreTime should generally be installed on a dedicated host running Ubuntu 16.04 LTS (Xenial Xerus). + +Once you have downloaded and extracted the LibreTime repository, run the instalation script by navigating into the folder containing the LibreTime codebase, and run it's install script from the command line: :::bash sudo ./install -Instalation in Debian 9 and other Linux distributions is possible, but multiple outstanding issues have yet to be resolved. +By default, the installer will install and configure all dependencies. + +## Alternative OS installations +Instalation in Debian 9 and other Linux distributions is possible, but multiple outstanding issues have yet to be resolved. Instalation on Ubuntu 14.04.5 LTS (Trusty Tahr) is also working, but deprecated due to the fact that this version will reach its official end of life in April 2019. Plans are in the works for `.deb` and `.rpm` packages, as well as Docker and AWS images. diff --git a/docs/manual/preparing-the-server/index.md b/docs/manual/preparing-the-server/index.md index da2359045..cef67b6b1 100644 --- a/docs/manual/preparing-the-server/index.md +++ b/docs/manual/preparing-the-server/index.md @@ -1,6 +1,6 @@ The following instructions assume that you have root access (**sudo** on most distributions) to a GNU/Linux server, and are familiar with basic command line tasks. Experienced system administrators may prefer to skip to [Expert install](../expert-install/) in the appendix of manual after having prepared a server with the needed dependencies show below. -The recommended Libretime server platform is Ubuntu 16.04 LTS (Xenial Xerus), or Ubuntu 14.04.5 LTS (Trusty Tahr). +The recommended Libretime server platform is Ubuntu 16.04 LTS (Xenial Xerus). The server should have at least a 1GHz processor and 1GB of RAM, preferably 2GB RAM or more. If you are using a desktop environment and web browser directly on the server you should install at least 2GB RAM, to avoid swapping to disk. From 6898c4dc8e66b12c00e3cfda250bb25ec9c4056e Mon Sep 17 00:00:00 2001 From: Lucas Bickel Date: Fri, 12 Oct 2018 19:35:37 +0200 Subject: [PATCH 15/33] :package: (installer) add Ubuntu Bionic Beaver Vagrant box --- Vagrantfile | 6 ++ docs/vagrant.md | 15 ++-- install | 11 ++- installer/lib/requirements-debian-wheezy.apt | 66 --------------- installer/lib/requirements-ubuntu-bionic.apt | 83 +++++++++++++++++++ installer/lib/requirements-ubuntu-precise.apt | 1 - installer/lib/requirements-ubuntu-trusty.apt | 1 - installer/lib/requirements-ubuntu-xenial.apt | 2 - ...uirements-ubuntu-xenial_docker_minimal.apt | 2 - 9 files changed, 107 insertions(+), 80 deletions(-) delete mode 100644 installer/lib/requirements-debian-wheezy.apt create mode 100644 installer/lib/requirements-ubuntu-bionic.apt diff --git a/Vagrantfile b/Vagrantfile index 9ce6b01ed..f85987c79 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -38,11 +38,17 @@ Vagrant.configure("2") do |config| installer_args="--force --in-place --verbose --postgres --apache --icecast " # define all the OS boxes we support + config.vm.define "ubuntu-bionic" do |os| + os.vm.box = "bento/ubuntu-18.04" + provision_libretime(os, "ubuntu.sh", installer_args) + end config.vm.define "ubuntu-xenial" do |os| os.vm.box = "bento/ubuntu-16.04" provision_libretime(os, "ubuntu.sh", installer_args) end config.vm.define "ubuntu-trusty" do |os| + STDERR.puts 'WARNING: The "ubuntu-trusty" option is deprecated. Please migrate to "ubuntu-bionic".' + STDERR.puts os.vm.box = "bento/ubuntu-14.04" provision_libretime(os, "ubuntu.sh", installer_args) end diff --git a/docs/vagrant.md b/docs/vagrant.md index 5629deae2..8a3ba6568 100644 --- a/docs/vagrant.md +++ b/docs/vagrant.md @@ -20,24 +20,25 @@ To get started you clone the repo and run `vagrant up`. ```bash git clone https://github.com/libretime/libretime.git cd libretime -vagrant up ubuntu-trusty +vagrant up ubuntu-xenial ``` If everything works out, you will find LibreTime on [port 8080](http://localhost:8080), icecast on [port 8000](http://localhost:8000) and the docs on [port 8888](http://localhost:8888). -Once you reach the web setup GUI you can click through it using the default values. To connect to the vagrant machine you can run `vagrant ssh ubuntu-trusty` in the libretime directory. +Once you reach the web setup GUI you can click through it using the default values. To connect to the vagrant machine you can run `vagrant ssh ubuntu-xenial` in the libretime directory. ## Alternative OS installations -With the above instructions LibreTime is installed on Ubuntu Trusty Tahir. The Vagrant setup offers the option to choose a different operation system according to you needs. +With the above instructions LibreTime is installed on Ubuntu Xenial Xerus. The Vagrant setup offers the option to choose a different operation system according to you needs. | OS | Command | Comment | | ------ | ------------------- | ------- | -| Ubuntu 14.04 | `vagrant up ubuntu-trusty` | Current default install since it was used by legacy upstream, based on Ubuntu Trusty Tahir. | -| Debian 8.7 | `vagrant up debian-jessie` | Recommended install on Debian Jessie as per the docs. | -| Debian 9.2 | `vagrant up debian-stretch` | Experimental install on current Debian Stretch. | -| Ubuntu 16.04 | `vagrant up ubuntu-xenial` | Experimental install on current Ubuntu Xenial Xerus. | +| Debian 9.2 | `vagrant up debian-stretch` | Install on current Debian Stretch. | +| Debian 8.7 | `vagrant up debian-jessie` | Install on Debian Jessie. | | Debian 7.11 | `vagrant up debian-wheezy` | Deprecated install on Debian Wheezy. Please switch to debian-stretch. | +| Ubuntu 18.04 | `vagrant up ubuntu-bionic` | Experimental install on current Ubuntu Bionic Beaver. | +| Ubuntu 16.04 | `vagrant up ubuntu-xenial` | Install on Ubuntu Xenial Xerus. | +| Ubuntu 14.04 | `vagrant up ubuntu-trusty` | Deprecated install on Ubuntu Trusty Tahir. Recommended by legacy upstream. | | CentOS | `vagrant up centos` | Extremely experimental install on 7.3 with native systemd support and activated SELinux. Needs manual intervention due to Liquidsoap 1.3.3. | ## Troubleshooting diff --git a/install b/install index f46ac0d70..b2d0a2a0d 100755 --- a/install +++ b/install @@ -588,6 +588,7 @@ is_debian_stretch=false is_debian_jessie=false is_debian_wheezy=false is_ubuntu_dist=false +is_ubuntu_bionic=false is_ubuntu_xenial=false is_ubuntu_trusty=false is_centos_dist=false @@ -598,6 +599,11 @@ code="${code:-$VERSION_ID}" code="${code,,}" verbose "Validating dist-code: ${dist}-${code}" case "${dist}-${code}" in + ubuntu-18.04) + code="bionic" + is_ubuntu_dist=true + is_ubuntu_bionic=true + ;; ubuntu-16.04|ubuntu-xenial|ubuntu-xenial_docker_minimal) code="xenial" is_ubuntu_dist=true @@ -970,6 +976,7 @@ loud " * Configuring PHP in Apache * " loud "-----------------------------------------------------" # Test common locations for php conf directory php_conf_dirs=( + "/etc/php/7.2/apache2/conf.d" # Ubuntu Bionic "/etc/php/7.0/apache2/conf.d" # Ubuntu Xenial "/etc/php5/apache2/conf.d" # Debian Stretch, Debian Jessie, Ubuntu Trusty "/etc/php.d" # CentOS 7 @@ -992,7 +999,9 @@ else fi # Enable Apache modules -if $is_ubuntu_xenial || $is_debian_stretch; then +if $is_ubuntu_bionic; then + loudCmd "a2enmod rewrite php7.2" +elif $is_ubuntu_xenial || $is_debian_stretch; then loudCmd "a2enmod rewrite php7.0" elif $is_centos_dist; then verbose "TODO: enable Apache modules mod_rewrite and mod_php manually" diff --git a/installer/lib/requirements-debian-wheezy.apt b/installer/lib/requirements-debian-wheezy.apt deleted file mode 100644 index 2a96f0010..000000000 --- a/installer/lib/requirements-debian-wheezy.apt +++ /dev/null @@ -1,66 +0,0 @@ -apache2 -libapache2-mod-php5 -php5 -php-pear -php5-gd - -lsb-release - -zip -unzip - -rabbitmq-server - -postgresql -postgresql-client -php5-pgsql - -python -python-virtualenv -python-pip - -libsoundtouch-ocaml -libtaglib-ocaml -libao-ocaml -libmad-ocaml -ecasound -libportaudio2 -libsamplerate0 -libvo-aacenc0 - -python-rgain -python-gst0.10 -gstreamer0.10-plugins-ugly -gir1.2-gstreamer-0.10 - -patch - -icecast2 - -curl -php5-curl -mpg123 - -libcamomile-ocaml-data -libpulse0 -vorbis-tools -lsb-release -lsof -mp3gain -vorbisgain -flac -vorbis-tools -pwgen -libfaad2 -php-apc - -lame - -coreutils - -liquidsoap - -libopus0 - -sysvinit -sysvinit-utils diff --git a/installer/lib/requirements-ubuntu-bionic.apt b/installer/lib/requirements-ubuntu-bionic.apt new file mode 100644 index 000000000..08e6f21a6 --- /dev/null +++ b/installer/lib/requirements-ubuntu-bionic.apt @@ -0,0 +1,83 @@ +apache2 +libapache2-mod-php7.2 +php7.2 +php-pear +php7.2-gd +php-bcmath +php-mbstring + +lsb-release + +zip +unzip + +rabbitmq-server + +postgresql +postgresql-client +php7.2-pgsql + +python +python-virtualenv +python-pip + +libsoundtouch-ocaml +libtaglib-ocaml +libao-ocaml +libmad-ocaml +ecasound +libportaudio2 +libsamplerate0 + +python-rgain +python-gst-1.0 +gstreamer1.0-plugins-ugly +python-pika + +patch + +php7.2-curl +mpg123 +curl + +icecast2 + +libcamomile-ocaml-data +libpulse0 +vorbis-tools +lsof +vorbisgain +flac +vorbis-tools +pwgen +libfaad2 +php-apcu + +lame + +coreutils + +liquidsoap +liquidsoap-plugin-alsa +liquidsoap-plugin-ao +liquidsoap-plugin-faad +liquidsoap-plugin-flac +liquidsoap-plugin-icecast +liquidsoap-plugin-lame +liquidsoap-plugin-mad +liquidsoap-plugin-ogg +liquidsoap-plugin-portaudio +liquidsoap-plugin-pulseaudio +liquidsoap-plugin-taglib +liquidsoap-plugin-voaacenc +liquidsoap-plugin-vorbis + +silan +libopus0 + +sysvinit-utils + +build-essential +libssl-dev +libffi-dev +python-dev diff --git a/installer/lib/requirements-ubuntu-precise.apt b/installer/lib/requirements-ubuntu-precise.apt index 2855878e9..7c217f659 100644 --- a/installer/lib/requirements-ubuntu-precise.apt +++ b/installer/lib/requirements-ubuntu-precise.apt @@ -44,7 +44,6 @@ libpulse0 vorbis-tools lsb-release lsof -mp3gain vorbisgain flac vorbis-tools diff --git a/installer/lib/requirements-ubuntu-trusty.apt b/installer/lib/requirements-ubuntu-trusty.apt index df0fb50d2..9a93d918b 100644 --- a/installer/lib/requirements-ubuntu-trusty.apt +++ b/installer/lib/requirements-ubuntu-trusty.apt @@ -45,7 +45,6 @@ libpulse0 vorbis-tools lsb-release lsof -mp3gain vorbisgain flac vorbis-tools diff --git a/installer/lib/requirements-ubuntu-xenial.apt b/installer/lib/requirements-ubuntu-xenial.apt index 9d513657c..70336c10c 100644 --- a/installer/lib/requirements-ubuntu-xenial.apt +++ b/installer/lib/requirements-ubuntu-xenial.apt @@ -46,8 +46,6 @@ libcamomile-ocaml-data libpulse0 vorbis-tools lsof -# mp3gain need to be installed over an external ppa or the use of easymp3gain -easymp3gain-gtk vorbisgain flac vorbis-tools diff --git a/installer/lib/requirements-ubuntu-xenial_docker_minimal.apt b/installer/lib/requirements-ubuntu-xenial_docker_minimal.apt index 0238132ba..6d414ba2d 100644 --- a/installer/lib/requirements-ubuntu-xenial_docker_minimal.apt +++ b/installer/lib/requirements-ubuntu-xenial_docker_minimal.apt @@ -41,8 +41,6 @@ libcamomile-ocaml-data libpulse0 vorbis-tools lsof -# mp3gain need to be installed over an external ppa or the use of easymp3gain -easymp3gain-gtk vorbisgain flac vorbis-tools From 5347af43c156673cdc99c0c309236b049468cc70 Mon Sep 17 00:00:00 2001 From: Lucas Bickel Date: Sun, 14 Oct 2018 11:52:00 +0200 Subject: [PATCH 16/33] :bug: (installer) Add Trusty EOL warning --- install | 3 +++ 1 file changed, 3 insertions(+) diff --git a/install b/install index b2d0a2a0d..a4ad3f3b4 100755 --- a/install +++ b/install @@ -613,6 +613,9 @@ case "${dist}-${code}" in code="trusty" is_ubuntu_dist=true is_ubuntu_trusty=true + echo -e "WARNING: Ubuntu Trusty will be EOL by April 2019 and LibreTime will no longer support it at that point." >&2 + echo -e "Please upgrade to a non-EOL distro ASAP!" >&2 + sleep 6 ;; debian-9|debian-stretch) code="stretch" From 03d1215833eb78d6b351abeb1515d5d3a751d1e0 Mon Sep 17 00:00:00 2001 From: Lucas Bickel Date: Sun, 14 Oct 2018 23:09:34 +0200 Subject: [PATCH 17/33] :fire: Remove dead phone_home_stat --- .../application/helpers/AirtimeInstall.php | 9 -- utils/phone_home_stat | 34 ------ utils/phone_home_stat.php | 108 ------------------ 3 files changed, 151 deletions(-) delete mode 100755 utils/phone_home_stat delete mode 100644 utils/phone_home_stat.php diff --git a/airtime_mvc/tests/application/helpers/AirtimeInstall.php b/airtime_mvc/tests/application/helpers/AirtimeInstall.php index f9c059171..c61816856 100644 --- a/airtime_mvc/tests/application/helpers/AirtimeInstall.php +++ b/airtime_mvc/tests/application/helpers/AirtimeInstall.php @@ -310,15 +310,6 @@ class AirtimeInstall echo "* Removing logs directory ".$path.PHP_EOL; exec("rm -rf \"$path\""); } - public static function CreateCronFile(){ - echo "* Creating Cron File".PHP_EOL; - // Create CRON task to run every day. Time of day is initialized to a random time. - $hour = rand(0,23); - $minute = rand(0,59); - $fp = fopen('/etc/cron.d/airtime-crons','w'); - fwrite($fp, "$minute $hour * * * root /usr/lib/airtime/utils/phone_home_stat\n"); - fclose($fp); - } public static function removeVirtualEnvDistributeFile(){ echo "* Removing distribute-0.6.10.tar.gz".PHP_EOL; if(file_exists('/usr/share/python-virtualenv/distribute-0.6.10.tar.gz')){ diff --git a/utils/phone_home_stat b/utils/phone_home_stat deleted file mode 100755 index ff52674b2..000000000 --- a/utils/phone_home_stat +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash -#------------------------------------------------------------------------------- -# Copyright (c) 2011 Sourcefabric O.P.S. -# -# This file is part of the Airtime project. -# http://airtime.sourcefabric.org/ -# -# Airtime is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Airtime is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Airtime; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -#------------------------------------------------------------------------------- -#------------------------------------------------------------------------------- -# This script send data to data collection server -# -# Absolute path to this script -SCRIPT=`readlink -f $0` -# Absolute directory this script is in -SCRIPTPATH=`dirname $SCRIPT` - -invokePwd=$PWD -cd $SCRIPTPATH - -php -q phone_home_stat.php "$@" || exit 1 \ No newline at end of file diff --git a/utils/phone_home_stat.php b/utils/phone_home_stat.php deleted file mode 100644 index 7b0498073..000000000 --- a/utils/phone_home_stat.php +++ /dev/null @@ -1,108 +0,0 @@ -registerNamespace('Application_'); - -$resourceLoader = new Zend_Loader_Autoloader_Resource(array( - 'basePath' => $CC_CONFIG['phpDir'].'/'.'application', - 'namespace' => 'Application', - 'resourceTypes' => array( - 'model' => array( - 'path' => 'models/', - 'namespace' => 'Model', - ), - 'common' => array( - 'path' => 'common/', - 'namespace' => 'Common', - ), - ), -)); - -$infoArray = Application_Model_Preference::GetSystemInfo(true); - -if(Application_Model_Preference::GetSupportFeedback() == '1'){ - $url = 'http://stat.sourcefabric.org/index.php?p=airtime'; - //$url = 'http://localhost:9999/index.php?p=airtime'; - - $ch = curl_init(); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_POST, 1); - curl_setopt($ch, CURLOPT_URL, $url); - - $data = json_encode($infoArray); - - $dataArray = array("data" => $data ); - - curl_setopt($ch, CURLOPT_POSTFIELDS, $dataArray); - $result = curl_exec($ch); - curl_close($ch); -} - -// Get latest version from stat server and store to db -if(Application_Model_Preference::GetPlanLevel() == 'disabled'){ - $url = 'http://stat.sourcefabric.org/airtime-stats/airtime_latest_version'; - //$url = 'http://localhost:9999/index.php?p=airtime'; - - $ch = curl_init(); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_URL, $url); - $result = curl_exec($ch); - - if(curl_errno($ch)) { - echo "curl error: " . curl_error($ch) . "\n"; - } else { - $resultArray = explode("\n", $result); - if (isset($resultArray[0])) { - Application_Model_Preference::SetLatestVersion($resultArray[0]); - } - if (isset($resultArray[1])) { - Application_Model_Preference::SetLatestLink($resultArray[1]); - } - } - - curl_close($ch); -} From 8a6f992aa57016a1b952d2a3be4c6d01834374c4 Mon Sep 17 00:00:00 2001 From: Robbt Date: Sun, 21 Oct 2018 17:18:29 -0400 Subject: [PATCH 18/33] Increased podcast download timeout to 1800 seconds --- installer/systemd/airtime-celery.service | 2 +- python_apps/airtime-celery/install/conf/airtime-celery | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/installer/systemd/airtime-celery.service b/installer/systemd/airtime-celery.service index 51254e1d7..06feda985 100644 --- a/installer/systemd/airtime-celery.service +++ b/installer/systemd/airtime-celery.service @@ -7,7 +7,7 @@ User=celery Group=celery Environment=RMQ_CONFIG_FILE=/etc/airtime/airtime.conf WorkingDirectory=/srv/airtime -ExecStart=/usr/local/bin/celery worker -A airtime-celery.tasks:celery --time-limit=300 --concurrency=1 --config=celeryconfig -l INFO +ExecStart=/usr/local/bin/celery worker -A airtime-celery.tasks:celery --time-limit=1800 --concurrency=1 --config=celeryconfig -l INFO Restart=always [Install] diff --git a/python_apps/airtime-celery/install/conf/airtime-celery b/python_apps/airtime-celery/install/conf/airtime-celery index 3b1206738..cee05654b 100644 --- a/python_apps/airtime-celery/install/conf/airtime-celery +++ b/python_apps/airtime-celery/install/conf/airtime-celery @@ -8,7 +8,7 @@ CELERY_BIN="/usr/local/bin/celery" CELERY_APP="airtime-celery.tasks:celery" # Extra command-line arguments to the worker -CELERYD_OPTS="--time-limit=300 --concurrency=1 --config=celeryconfig" +CELERYD_OPTS="--time-limit=1800 --concurrency=1 --config=celeryconfig" # %N will be replaced with the first part of the nodename. CELERYD_LOG_FILE="/var/log/airtime/%N.log" From 95fbd2ccc52895df5ab2290cf95f53264c3c40b0 Mon Sep 17 00:00:00 2001 From: ryan Date: Mon, 22 Oct 2018 11:39:18 -0500 Subject: [PATCH 19/33] (docs) note bug with Butt 1.14+. Closes #160 --- docs/manual/stream-settings/index.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/manual/stream-settings/index.md b/docs/manual/stream-settings/index.md index 0e6d26ca4..452346e92 100644 --- a/docs/manual/stream-settings/index.md +++ b/docs/manual/stream-settings/index.md @@ -19,7 +19,9 @@ Click the **Save** button on the right side of the page to save any changes that Input stream settings --------------------- -On the lower left side of the Stream Settings page you can configure remote live input streams from DJ programs such as **Mixxx** or **IDJC**, or smartphone applications used by broadcast journalists. Airtime supports two types of live input stream; the **Show Source**, which enables a specific person to stream in during their own show, and the **Master Source**, which can override the Show Source if necessary. If neither type of live input is available, Airtime will fall back to **Scheduled Play** (playlists, smart blocks, remote streams and files scheduled in Airtime, in advance of or during a show). +On the lower left side of the Stream Settings page you can configure remote live input streams from DJ programs such as **Mixxx** or **IDJC**, or smartphone applications used by broadcast journalists. Note that a [bug](https://sourceforge.net/p/butt/bugs/12/) has been reported with **Butt** versions 1.14 to 1.16 that causes streams not to connect to LibreTime. Butt version 1.13 does appear to be working. + +Airtime supports two types of live input stream; the **Show Source**, which enables a specific person to stream in during their own show, and the **Master Source**, which can override the Show Source if necessary. If neither type of live input is available, Airtime will fall back to **Scheduled Play** (playlists, smart blocks, remote streams and files scheduled in Airtime, in advance of or during a show). The **Auto Switch Off** and **Auto Switch On** checkboxes enable playout to be switched automatically to the highest priority source whenever an authenticated input source disconnects from or connects to Airtime, respectively. The field **Switch Transition Fade** sets the length of the audio fade as scheduled playout is switched to a remote input source, and back. From 9bed0b79caffb6c74e16c2f722ad95cfaea60c5d Mon Sep 17 00:00:00 2001 From: ryan Date: Mon, 22 Oct 2018 18:43:49 -0500 Subject: [PATCH 20/33] Show playlist and smartblock contents on shorter screens. Fixes #574 --- airtime_mvc/public/css/dashboard.css | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/airtime_mvc/public/css/dashboard.css b/airtime_mvc/public/css/dashboard.css index 1c575ea0a..5ac64b006 100644 --- a/airtime_mvc/public/css/dashboard.css +++ b/airtime_mvc/public/css/dashboard.css @@ -585,11 +585,11 @@ li.ui-state-default { .spl_sortable { height: 100%; overflow: auto; - -webkit-flex: 1 100%; - -moz-flex: 1 100%; - -ms-flex: 1 100%; - -o-flex: 1 100%; - flex: 1 100%; + -webkit-flex: 1 0 100%; + -moz-flex: 1 0 100%; + -ms-flex: 1 0 100%; + -o-flex: 1 0 100%; + flex: 1 0 100%; margin: 4px 0; min-height: 0; From 0ae8969dd39c6a261d3c87549578e55d7da5b1f2 Mon Sep 17 00:00:00 2001 From: Robb Ebright Date: Wed, 31 Oct 2018 08:06:59 -0400 Subject: [PATCH 21/33] Modified the database to turn on the podcast album override by default --- airtime_mvc/build/sql/defaultdata.sql | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/airtime_mvc/build/sql/defaultdata.sql b/airtime_mvc/build/sql/defaultdata.sql index 466420208..818276196 100644 --- a/airtime_mvc/build/sql/defaultdata.sql +++ b/airtime_mvc/build/sql/defaultdata.sql @@ -387,4 +387,9 @@ ANALYZE cc_pref; -- this validates the new partial index --end added in 2.5.14 -- For now, just needs to be truthy - to be updated later; we should find a better way to implement this... -INSERT INTO cc_pref("keystr", "valstr") VALUES('whats_new_dialog_viewed', 1); \ No newline at end of file +INSERT INTO cc_pref("keystr", "valstr") VALUES('whats_new_dialog_viewed', 1); + +--added for LibreTime to turn on podcast album override by default 3.0.0.alpha6 +INSERT INTO cc_pref("keystr", "valstr") VALUES('podcast_album_override', 1); +INSERT INTO cc_pref("keystr", "valstr") VALUES('podcast_auto_smartblock', 1); +-- end \ No newline at end of file From 8b6c41a4c62a8162d71f22cda144674c19b63f0c Mon Sep 17 00:00:00 2001 From: Lucas Bickel Date: Sun, 4 Nov 2018 14:30:07 +0100 Subject: [PATCH 22/33] :recycle: (utils) nuke airtime-nuke.sh --- utils/airtime-nuke.sh | 45 ------------------------------------------- 1 file changed, 45 deletions(-) delete mode 100755 utils/airtime-nuke.sh diff --git a/utils/airtime-nuke.sh b/utils/airtime-nuke.sh deleted file mode 100755 index 3ed1a14b1..000000000 --- a/utils/airtime-nuke.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash - -if [[ $EUID -ne 0 ]]; then - echo "This script must be run as root." 1>&2 - exit 1 -fi - -echo "This script deletes all traces of Airtime from your system," -echo "including files uploaded through the web interface." -echo "It will delete files from all known versions of Airtime." -echo -echo "Are you sure you want to do this? Press Enter to continue..." -read - -service airtime-playout stop >/dev/null 2>&1 -service airtime-liquidsoap stop >/dev/null 2>&1 -service airtime-media-monitor stop >/dev/null 2>&1 -service airtime-show-recorder stop >/dev/null 2>&1 - -airtime-pypo-stop >/dev/null 2>&1 -airtime-show-recorder-stop >/dev/null 2>&1 - -killall liquidsoap - -rm -rf "/etc/airtime" -rm -rf "/var/log/airtime" -rm -rf "/etc/service/pypo" -rm -rf "/etc/service/pypo-liquidsoap" -rm -rf "/etc/service/recorder" -rm -rf "/usr/share/airtime" -rm -rf "/var/tmp/airtime" -rm -rf "/var/www/airtime" -rm -rf "/usr/bin/airtime-*" -rm -rf "/usr/lib/airtime" -rm -rf "/var/lib/airtime" -rm -rf "/var/tmp/airtime" -rm -rf "/opt/pypo" -rm -rf "/opt/recorder" -rm -rf "/srv/airtime" -rm -rf "/etc/monit/conf.d/airtime-monit.cfg" -rm -rf /etc/monit/conf.d/monit-airtime-* - -echo "DROP DATABASE AIRTIME;" | su postgres -c psql -echo "DROP LANGUAGE plpgsql;" | su postgres -c psql -echo "DROP USER AIRTIME;" | su postgres -c psql From beabcba99bffeae76f994b5514493aee961f9d4f Mon Sep 17 00:00:00 2001 From: Lucas Bickel Date: Sun, 4 Nov 2018 14:42:37 +0100 Subject: [PATCH 23/33] :recycle: (utils) Remove unused make_tarball.sh --- utils/make_tarball.sh | 7 ------- 1 file changed, 7 deletions(-) delete mode 100755 utils/make_tarball.sh diff --git a/utils/make_tarball.sh b/utils/make_tarball.sh deleted file mode 100755 index bad81038e..000000000 --- a/utils/make_tarball.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -if [ -z "${1}" ]; then - echo "Usage: make_tarball.sh git_tag" - exit -fi -GIT_TAG=${1} -git archive ${GIT_TAG} --prefix ${GIT_TAG}/ -o "${GIT_TAG}".tar.gz From 46483bff0cd49621d3b7bf5bfd2c65f581c72317 Mon Sep 17 00:00:00 2001 From: ryan Date: Wed, 7 Nov 2018 18:34:45 -0600 Subject: [PATCH 24/33] correct sizing for playlist and smartblock contents pane. see #574 --- airtime_mvc/public/css/dashboard.css | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/airtime_mvc/public/css/dashboard.css b/airtime_mvc/public/css/dashboard.css index 5ac64b006..05c5d18c3 100644 --- a/airtime_mvc/public/css/dashboard.css +++ b/airtime_mvc/public/css/dashboard.css @@ -583,16 +583,15 @@ li.ui-state-default { } .spl_sortable { - height: 100%; + -webkit-flex: 1 0 auto; + -moz-flex: 1 0 auto; + -ms-flex: 1 0 auto; + -o-flex: 1 0 auto; + flex: 1 0 auto; overflow: auto; - -webkit-flex: 1 0 100%; - -moz-flex: 1 0 100%; - -ms-flex: 1 0 100%; - -o-flex: 1 0 100%; - flex: 1 0 100%; - margin: 4px 0; - min-height: 0; + min-height: 6em; + max-height: 100%; padding: 5px; border: 1px solid #444; border-radius: 3px; From 6b8bf52bb3ebb4c120181d8460388eb20566ae77 Mon Sep 17 00:00:00 2001 From: ryan Date: Wed, 7 Nov 2018 18:46:05 -0600 Subject: [PATCH 25/33] don't hide buttons below playlist and smartblock contents pane --- airtime_mvc/public/css/dashboard.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airtime_mvc/public/css/dashboard.css b/airtime_mvc/public/css/dashboard.css index 05c5d18c3..d94b0f941 100644 --- a/airtime_mvc/public/css/dashboard.css +++ b/airtime_mvc/public/css/dashboard.css @@ -591,7 +591,7 @@ li.ui-state-default { overflow: auto; margin: 4px 0; min-height: 6em; - max-height: 100%; + max-height: calc(100% - 40px); padding: 5px; border: 1px solid #444; border-radius: 3px; From 05b62f92586c035a64a797929f912fb7cefa82bb Mon Sep 17 00:00:00 2001 From: jelko Date: Wed, 14 Nov 2018 01:14:53 +0100 Subject: [PATCH 26/33] Fixing failing version test Wrapping version in Array() to comply with SemVer new method signature. This should fix #487. --- .../application/views/helpers/VersionNotify.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/airtime_mvc/application/views/helpers/VersionNotify.php b/airtime_mvc/application/views/helpers/VersionNotify.php index dd6f6424b..e9b1e1421 100644 --- a/airtime_mvc/application/views/helpers/VersionNotify.php +++ b/airtime_mvc/application/views/helpers/VersionNotify.php @@ -45,16 +45,16 @@ class Airtime_View_Helper_VersionNotify extends Zend_View_Helper_Abstract { $isPreRelease = $isGitRelease || array_key_exists(4, $currentParts); // we are always interested in a major when we pre-release, hence the isPreRelease part - $majorCandidates = SemVer::satisfiedBy($latest, sprintf('>=%1$s-stable', $currentParts[0] + ($isPreRelease ? 0 : 1))); - $minorCandidates = SemVer::satisfiedBy($latest, sprintf('~%1$s.%2$s', $currentParts[0], $currentParts[1] + 1)); - $patchCandidates = SemVer::satisfiedBy($latest, sprintf('>=%1$s.%2$s.%3$s <%1$s.%3$s', $currentParts[0], $currentParts[1], $currentParts[2] + 1)); + $majorCandidates = SemVer::satisfiedBy(array($latest), sprintf('>=%1$s-stable', $currentParts[0] + ($isPreRelease ? 0 : 1))); + $minorCandidates = SemVer::satisfiedBy(array($latest), sprintf('~%1$s.%2$s', $currentParts[0], $currentParts[1] + 1)); + $patchCandidates = SemVer::satisfiedBy(array($latest), sprintf('>=%1$s.%2$s.%3$s <%1$s.%3$s', $currentParts[0], $currentParts[1], $currentParts[2] + 1)); $hasMajor = !empty($majorCandidates); $hasMinor = !empty($minorCandidates); $hasPatch = !empty($patchCandidates); $hasMultiMajor = count($majorCandidates) > 1; if ($isPreRelease) { - $stableVersions = SemVer::satisfiedBy($latest, sprintf('>=%1$s.%2$s.%3$s-stable', $currentParts[0], $currentParts[1], $currentParts[2])); + $stableVersions = SemVer::satisfiedBy(array($latest), sprintf('>=%1$s.%2$s.%3$s-stable', $currentParts[0], $currentParts[1], $currentParts[2])); // git releases are never interested in a stable version :P $hasStable = !empty($stableVersions) && !$isGitRelease; // no warning if no major release available, orange warning if you are on unreleased code @@ -71,7 +71,7 @@ class Airtime_View_Helper_VersionNotify extends Zend_View_Helper_Abstract { } else { $class = 'uptodate'; } - $latest = SemVer::rsort($latest); + $latest = SemVer::rsort(array($latest)); $highestVersion = $latest[0]; $data = (object) array( From 4b9e50b64b4304fcd5af01b514201a5d922f6a25 Mon Sep 17 00:00:00 2001 From: ryan Date: Mon, 19 Nov 2018 11:39:54 -0600 Subject: [PATCH 27/33] collapse advanced configuration sections in Schedule Dialog --- .../views/scripts/schedule/add-show-form.phtml | 8 ++++---- airtime_mvc/public/js/airtime/schedule/add-show.js | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/airtime_mvc/application/views/scripts/schedule/add-show-form.phtml b/airtime_mvc/application/views/scripts/schedule/add-show-form.phtml index 73a6591fc..918c3d2bc 100644 --- a/airtime_mvc/application/views/scripts/schedule/add-show-form.phtml +++ b/airtime_mvc/application/views/scripts/schedule/add-show-form.phtml @@ -11,10 +11,6 @@
what; ?>
-

-
- autoplaylist; ?> -

repeats; ?>
+

+
+ autoplaylist; ?> +

live; ?> diff --git a/airtime_mvc/public/js/airtime/schedule/add-show.js b/airtime_mvc/public/js/airtime/schedule/add-show.js index 921afa218..130c684a8 100644 --- a/airtime_mvc/public/js/airtime/schedule/add-show.js +++ b/airtime_mvc/public/js/airtime/schedule/add-show.js @@ -16,6 +16,14 @@ function openAddShowForm(nowOrFuture) { $("#add-show-form").show(); windowResize(); + + // collapse advanced configuration sections + $('#schedule-show-auto').hide(); + $('#live-stream-override').hide(); + $('#schedule-record-rebroadcast').hide(); + $('#schedule-show-who').hide(); + $('#schedule-show-style').hide(); + } $("#schedule-show-what").show(0, function(){ $add_show_name = $("#add_show_name"); From 11453785c0ae71b4f05d0d7804ca3d5b8b815fe7 Mon Sep 17 00:00:00 2001 From: Robb Date: Tue, 20 Nov 2018 13:31:34 -0500 Subject: [PATCH 28/33] Update install.md --- docs/install.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/install.md b/docs/install.md index 48fe281f6..9bb9efbcf 100644 --- a/docs/install.md +++ b/docs/install.md @@ -2,6 +2,8 @@ LibreTime should generally be installed on a dedicated host running Ubuntu 16.04 LTS (Xenial Xerus). +You can download LibreTime from our [github repo](https://github.com/LibreTime/libretime) In order to run the latest codebase you can click the green Clone or download button. It is recommended to type ``` git clone https://github.com/LibreTime/libretime.git ``` (if you Debian based system lacks git then you can type ``` sudo apt-get install git ```) and this will download the source code to your repository. You can also click Releases and download a tarball of our latest releases. You will then need to extract this archive into a directory on your server. It is not recommended that you install LibreTime on the same computer you are using as a desktop. So you will probably need to use wget for instance ```wget https://github.com/LibreTime/libretime/releases/download/3.0.0-alpha.6/libretime-3.0.0-alpha.6.tar.gz``` and then extract it by typing ```tar -xvzf libretime-3.0.0-alpha.6.tar.gz``` in the directory you downloaded it into. + Once you have downloaded and extracted the LibreTime repository, run the instalation script by navigating into the folder containing the LibreTime codebase, and run it's install script from the command line: :::bash From 4303a9d1e6b8d324817702c359333bd80bd65036 Mon Sep 17 00:00:00 2001 From: ryan Date: Tue, 20 Nov 2018 14:20:01 -0600 Subject: [PATCH 29/33] docs: add recomendations to instalation instructions --- docs/install.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/docs/install.md b/docs/install.md index 9bb9efbcf..8f5760e01 100644 --- a/docs/install.md +++ b/docs/install.md @@ -1,13 +1,18 @@ # Installing LibreTime -LibreTime should generally be installed on a dedicated host running Ubuntu 16.04 LTS (Xenial Xerus). +LibreTime releases can be downloaded [here](https://github.com/LibreTime/libretime/releases). -You can download LibreTime from our [github repo](https://github.com/LibreTime/libretime) In order to run the latest codebase you can click the green Clone or download button. It is recommended to type ``` git clone https://github.com/LibreTime/libretime.git ``` (if you Debian based system lacks git then you can type ``` sudo apt-get install git ```) and this will download the source code to your repository. You can also click Releases and download a tarball of our latest releases. You will then need to extract this archive into a directory on your server. It is not recommended that you install LibreTime on the same computer you are using as a desktop. So you will probably need to use wget for instance ```wget https://github.com/LibreTime/libretime/releases/download/3.0.0-alpha.6/libretime-3.0.0-alpha.6.tar.gz``` and then extract it by typing ```tar -xvzf libretime-3.0.0-alpha.6.tar.gz``` in the directory you downloaded it into. +Recommendations: +- LibreTime should generally be installed on a dedicated host running Ubuntu 16.04 LTS (Xenial Xerus). +- LibreTime is undergoing active development, and is currently in ALPHA. +- It is not recommended that you install LibreTime on the same computer you are using as a desktop. +- Please review the release notes of the version you are planning on installing. -Once you have downloaded and extracted the LibreTime repository, run the instalation script by navigating into the folder containing the LibreTime codebase, and run it's install script from the command line: +Once you have downloaded and extracted LibreTime, run the instalation script by navigating into the folder containing the LibreTime codebase, and run it's install script from the command line: - :::bash - sudo ./install +``` +sudo ./install +``` By default, the installer will install and configure all dependencies. From 410523498ddf64c75528fbc09f3883fdbd75a275 Mon Sep 17 00:00:00 2001 From: Lucas Bickel Date: Wed, 21 Nov 2018 00:50:57 +0100 Subject: [PATCH 30/33] Revert "Fixing failing version test" This reverts commit 05b62f92586c035a64a797929f912fb7cefa82bb. --- .../application/views/helpers/VersionNotify.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/airtime_mvc/application/views/helpers/VersionNotify.php b/airtime_mvc/application/views/helpers/VersionNotify.php index e9b1e1421..dd6f6424b 100644 --- a/airtime_mvc/application/views/helpers/VersionNotify.php +++ b/airtime_mvc/application/views/helpers/VersionNotify.php @@ -45,16 +45,16 @@ class Airtime_View_Helper_VersionNotify extends Zend_View_Helper_Abstract { $isPreRelease = $isGitRelease || array_key_exists(4, $currentParts); // we are always interested in a major when we pre-release, hence the isPreRelease part - $majorCandidates = SemVer::satisfiedBy(array($latest), sprintf('>=%1$s-stable', $currentParts[0] + ($isPreRelease ? 0 : 1))); - $minorCandidates = SemVer::satisfiedBy(array($latest), sprintf('~%1$s.%2$s', $currentParts[0], $currentParts[1] + 1)); - $patchCandidates = SemVer::satisfiedBy(array($latest), sprintf('>=%1$s.%2$s.%3$s <%1$s.%3$s', $currentParts[0], $currentParts[1], $currentParts[2] + 1)); + $majorCandidates = SemVer::satisfiedBy($latest, sprintf('>=%1$s-stable', $currentParts[0] + ($isPreRelease ? 0 : 1))); + $minorCandidates = SemVer::satisfiedBy($latest, sprintf('~%1$s.%2$s', $currentParts[0], $currentParts[1] + 1)); + $patchCandidates = SemVer::satisfiedBy($latest, sprintf('>=%1$s.%2$s.%3$s <%1$s.%3$s', $currentParts[0], $currentParts[1], $currentParts[2] + 1)); $hasMajor = !empty($majorCandidates); $hasMinor = !empty($minorCandidates); $hasPatch = !empty($patchCandidates); $hasMultiMajor = count($majorCandidates) > 1; if ($isPreRelease) { - $stableVersions = SemVer::satisfiedBy(array($latest), sprintf('>=%1$s.%2$s.%3$s-stable', $currentParts[0], $currentParts[1], $currentParts[2])); + $stableVersions = SemVer::satisfiedBy($latest, sprintf('>=%1$s.%2$s.%3$s-stable', $currentParts[0], $currentParts[1], $currentParts[2])); // git releases are never interested in a stable version :P $hasStable = !empty($stableVersions) && !$isGitRelease; // no warning if no major release available, orange warning if you are on unreleased code @@ -71,7 +71,7 @@ class Airtime_View_Helper_VersionNotify extends Zend_View_Helper_Abstract { } else { $class = 'uptodate'; } - $latest = SemVer::rsort(array($latest)); + $latest = SemVer::rsort($latest); $highestVersion = $latest[0]; $data = (object) array( From c0124b6245dbd17decb2b5fd3e07f1380921375d Mon Sep 17 00:00:00 2001 From: Lucas Bickel Date: Wed, 21 Nov 2018 02:21:52 +0100 Subject: [PATCH 31/33] :bug: returnn array of strings The downstream version checking code expects an array of strings and the "github is unreachable" default was returning a string. --- airtime_mvc/application/models/Preference.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airtime_mvc/application/models/Preference.php b/airtime_mvc/application/models/Preference.php index 4dee92700..3e64bde6b 100644 --- a/airtime_mvc/application/models/Preference.php +++ b/airtime_mvc/application/models/Preference.php @@ -912,7 +912,7 @@ class Application_Model_Preference self::setValue('latest_version', json_encode($latest)); self::setValue('latest_version_nextcheck', strtotime('+1 week')); if (empty($latest)) { - return $config['airtime_version']; + return array($config['airtime_version']); } else { return $latest; } From b65c04039442bc144015509c7fa280d01d0605b6 Mon Sep 17 00:00:00 2001 From: Lucas Bickel Date: Wed, 21 Nov 2018 02:25:27 +0100 Subject: [PATCH 32/33] :recycle: only store versions on success We should only overwrite latest_version if retreiving from GitHub went ok, else we should keep the old values and store "null". --- airtime_mvc/application/models/Preference.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/airtime_mvc/application/models/Preference.php b/airtime_mvc/application/models/Preference.php index 3e64bde6b..368d3e52a 100644 --- a/airtime_mvc/application/models/Preference.php +++ b/airtime_mvc/application/models/Preference.php @@ -909,13 +909,13 @@ class Application_Model_Preference $versions[] = $item->get_title(); } $latest = $versions; - self::setValue('latest_version', json_encode($latest)); self::setValue('latest_version_nextcheck', strtotime('+1 week')); if (empty($latest)) { return array($config['airtime_version']); - } else { - return $latest; } + + self::setValue('latest_version', json_encode($latest)); + return $latest; } public static function SetLatestVersion($version) From 6031d953518b1f2f87d589de262e3a4a44e70ffc Mon Sep 17 00:00:00 2001 From: frecuencialibre <36803137+frecuencialibre@users.noreply.github.com> Date: Wed, 21 Nov 2018 09:37:18 -0600 Subject: [PATCH 33/33] docs: fix bullet list formatting in install.md --- docs/install.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/install.md b/docs/install.md index 8f5760e01..cfce019bb 100644 --- a/docs/install.md +++ b/docs/install.md @@ -3,6 +3,7 @@ LibreTime releases can be downloaded [here](https://github.com/LibreTime/libretime/releases). Recommendations: + - LibreTime should generally be installed on a dedicated host running Ubuntu 16.04 LTS (Xenial Xerus). - LibreTime is undergoing active development, and is currently in ALPHA. - It is not recommended that you install LibreTime on the same computer you are using as a desktop.