2013-10-24 17:59:39 +00:00
< ? php
/**
2015-03-26 10:44:34 +00:00
* @ author Andreas Fischer < bantu @ owncloud . com >
2015-10-05 18:54:56 +00:00
* @ author Joas Schilling < nickvergessen @ owncloud . com >
2015-03-26 10:44:34 +00:00
* @ author Morris Jobke < hey @ morrisjobke . de >
* @ author Owen Winkler < a_github @ midnightcircus . com >
2015-06-25 09:43:55 +00:00
* @ author Steffen Lindner < mail @ steffen - lindner . de >
2015-03-26 10:44:34 +00:00
* @ author Thomas Müller < thomas . mueller @ tmit . eu >
* @ author Vincent Petry < pvince81 @ owncloud . com >
*
* @ copyright Copyright ( c ) 2015 , ownCloud , Inc .
* @ license AGPL - 3.0
*
* This code is free software : you can redistribute it and / or modify
* it under the terms of the GNU Affero General Public License , version 3 ,
* as published by the Free Software Foundation .
*
* This program 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 Affero General Public License for more details .
*
* You should have received a copy of the GNU Affero General Public License , version 3 ,
* along with this program . If not , see < http :// www . gnu . org / licenses />
*
2013-10-24 17:59:39 +00:00
*/
2015-02-26 10:37:37 +00:00
2013-10-24 17:59:39 +00:00
namespace OC\Core\Command ;
2015-06-23 15:07:28 +00:00
use OC\Console\TimestampFormatter ;
2013-10-28 14:15:56 +00:00
use OC\Updater ;
2014-09-22 10:04:48 +00:00
use OCP\IConfig ;
2015-10-09 12:08:22 +00:00
use OCP\ILogger ;
2013-10-24 17:59:39 +00:00
use Symfony\Component\Console\Command\Command ;
use Symfony\Component\Console\Input\InputInterface ;
use Symfony\Component\Console\Output\OutputInterface ;
2014-06-05 14:19:24 +00:00
use Symfony\Component\Console\Input\InputOption ;
2013-10-24 17:59:39 +00:00
class Upgrade extends Command {
2013-10-28 20:50:28 +00:00
const ERROR_SUCCESS = 0 ;
const ERROR_NOT_INSTALLED = 1 ;
const ERROR_MAINTENANCE_MODE = 2 ;
const ERROR_UP_TO_DATE = 3 ;
2014-06-05 14:19:24 +00:00
const ERROR_INVALID_ARGUMENTS = 4 ;
2015-06-23 08:03:27 +00:00
const ERROR_FAILURE = 5 ;
2014-09-22 09:59:13 +00:00
2015-10-09 12:08:22 +00:00
/** @var IConfig */
2014-09-22 10:04:48 +00:00
private $config ;
2015-10-09 12:08:22 +00:00
/** @var ILogger */
private $logger ;
2014-09-22 10:04:48 +00:00
/**
* @ param IConfig $config
*/
2015-10-09 12:08:22 +00:00
public function __construct ( IConfig $config , ILogger $logger ) {
2014-11-03 12:53:59 +00:00
parent :: __construct ();
2014-09-22 10:04:48 +00:00
$this -> config = $config ;
2015-10-09 12:08:22 +00:00
$this -> logger = $logger ;
2014-09-22 10:04:48 +00:00
}
2013-10-24 17:59:39 +00:00
protected function configure () {
$this
-> setName ( 'upgrade' )
2015-03-26 21:30:35 +00:00
-> setDescription ( 'run upgrade routines after installation of a new release. The release has to be installed before.' )
2014-06-05 14:19:24 +00:00
-> addOption (
'--skip-migration-test' ,
null ,
InputOption :: VALUE_NONE ,
'skips the database schema migration simulation and update directly'
)
-> addOption (
'--dry-run' ,
null ,
InputOption :: VALUE_NONE ,
'only runs the database schema migration simulation, do not actually update'
2015-05-20 15:06:00 +00:00
)
-> addOption (
'--no-app-disable' ,
null ,
InputOption :: VALUE_NONE ,
'skips the disable of third party apps'
2014-06-05 14:19:24 +00:00
);
2013-10-24 17:59:39 +00:00
}
2014-03-14 09:48:07 +00:00
/**
* Execute the upgrade command
*
* @ param InputInterface $input input interface
* @ param OutputInterface $output output interface
*/
2013-10-24 17:59:39 +00:00
protected function execute ( InputInterface $input , OutputInterface $output ) {
2013-10-28 14:15:56 +00:00
2014-06-05 14:19:24 +00:00
$simulateStepEnabled = true ;
$updateStepEnabled = true ;
2015-05-20 15:06:00 +00:00
$skip3rdPartyAppsDisable = false ;
2014-06-05 14:19:24 +00:00
if ( $input -> getOption ( 'skip-migration-test' )) {
$simulateStepEnabled = false ;
}
if ( $input -> getOption ( 'dry-run' )) {
$updateStepEnabled = false ;
}
2015-05-20 15:06:00 +00:00
if ( $input -> getOption ( 'no-app-disable' )) {
$skip3rdPartyAppsDisable = true ;
}
2014-06-05 14:19:24 +00:00
if ( ! $simulateStepEnabled && ! $updateStepEnabled ) {
$output -> writeln (
'<error>Only one of "--skip-migration-test" or "--dry-run" ' .
'can be specified at a time.</error>'
);
return self :: ERROR_INVALID_ARGUMENTS ;
}
2013-10-28 14:15:56 +00:00
if ( \OC :: checkUpgrade ( false )) {
2015-06-23 15:07:28 +00:00
if ( OutputInterface :: VERBOSITY_NORMAL < $output -> getVerbosity ()) {
// Prepend each line with a little timestamp
$timestampFormatter = new TimestampFormatter ( $this -> config , $output -> getFormatter ());
$output -> setFormatter ( $timestampFormatter );
}
2014-09-22 09:59:13 +00:00
$self = $this ;
2015-02-17 11:00:39 +00:00
$updater = new Updater ( \OC :: $server -> getHTTPHelper (),
2015-10-09 12:08:22 +00:00
$this -> config ,
$this -> logger );
2013-10-28 14:15:56 +00:00
2014-06-05 14:19:24 +00:00
$updater -> setSimulateStepEnabled ( $simulateStepEnabled );
$updater -> setUpdateStepEnabled ( $updateStepEnabled );
2015-05-20 15:06:00 +00:00
$updater -> setSkip3rdPartyAppsDisable ( $skip3rdPartyAppsDisable );
2014-06-05 14:19:24 +00:00
2015-05-19 08:27:53 +00:00
$updater -> listen ( '\OC\Updater' , 'maintenanceEnabled' , function () use ( $output ) {
2013-10-28 21:26:44 +00:00
$output -> writeln ( '<info>Turned on maintenance mode</info>' );
2013-10-28 14:15:56 +00:00
});
2015-05-19 08:27:53 +00:00
$updater -> listen ( '\OC\Updater' , 'maintenanceDisabled' , function () use ( $output ) {
$output -> writeln ( '<info>Turned off maintenance mode</info>' );
});
$updater -> listen ( '\OC\Updater' , 'maintenanceActive' , function () use ( $output ) {
$output -> writeln ( '<info>Maintenance mode is kept active</info>' );
});
$updater -> listen ( '\OC\Updater' , 'updateEnd' ,
2015-06-23 08:03:27 +00:00
function ( $success ) use ( $output , $updateStepEnabled , $self ) {
2014-09-22 09:59:13 +00:00
$mode = $updateStepEnabled ? 'Update' : 'Update simulation' ;
2015-06-23 15:07:28 +00:00
if ( $success ) {
$message = " <info> $mode successful</info> " ;
} else {
$message = " <error> $mode failed</error> " ;
}
2014-09-22 09:59:13 +00:00
$output -> writeln ( $message );
});
2015-10-21 07:17:38 +00:00
$updater -> listen ( '\OC\Updater' , 'dbUpgradeBefore' , function () use ( $output ) {
$output -> writeln ( '<info>Updating database schema</info>' );
});
2013-10-28 20:50:28 +00:00
$updater -> listen ( '\OC\Updater' , 'dbUpgrade' , function () use ( $output ) {
2013-10-28 21:26:44 +00:00
$output -> writeln ( '<info>Updated database</info>' );
2013-10-28 14:15:56 +00:00
});
2015-10-21 07:17:38 +00:00
$updater -> listen ( '\OC\Updater' , 'dbSimulateUpgradeBefore' , function () use ( $output ) {
$output -> writeln ( '<info>Checking whether the database schema can be updated (this can take a long time depending on the database size)</info>' );
});
2014-06-04 14:40:53 +00:00
$updater -> listen ( '\OC\Updater' , 'dbSimulateUpgrade' , function () use ( $output ) {
$output -> writeln ( '<info>Checked database schema update</info>' );
});
2015-02-17 11:00:39 +00:00
$updater -> listen ( '\OC\Updater' , 'incompatibleAppDisabled' , function ( $app ) use ( $output ) {
$output -> writeln ( '<info>Disabled incompatible app: ' . $app . '</info>' );
});
2015-05-20 15:06:00 +00:00
$updater -> listen ( '\OC\Updater' , 'thirdPartyAppDisabled' , function ( $app ) use ( $output ) {
2015-02-17 11:00:39 +00:00
$output -> writeln ( '<info>Disabled 3rd-party app: ' . $app . '</info>' );
2014-05-27 13:20:33 +00:00
});
2015-05-12 16:02:31 +00:00
$updater -> listen ( '\OC\Updater' , 'upgradeAppStoreApp' , function ( $app ) use ( $output ) {
$output -> writeln ( '<info>Update 3rd-party app: ' . $app . '</info>' );
});
2015-02-27 11:44:04 +00:00
$updater -> listen ( '\OC\Updater' , 'repairWarning' , function ( $app ) use ( $output ) {
$output -> writeln ( '<error>Repair warning: ' . $app . '</error>' );
});
$updater -> listen ( '\OC\Updater' , 'repairError' , function ( $app ) use ( $output ) {
$output -> writeln ( '<error>Repair error: ' . $app . '</error>' );
});
2015-10-21 07:17:38 +00:00
$updater -> listen ( '\OC\Updater' , 'appUpgradeCheckBefore' , function () use ( $output ) {
$output -> writeln ( '<info>Checking updates of apps</info>' );
});
$updater -> listen ( '\OC\Updater' , 'appSimulateUpdate' , function ( $app ) use ( $output ) {
$output -> writeln ( " <info>Checking whether the database schema for < $app > can be updated (this can take a long time depending on the database size)</info> " );
});
2015-02-24 11:52:16 +00:00
$updater -> listen ( '\OC\Updater' , 'appUpgradeCheck' , function () use ( $output ) {
$output -> writeln ( '<info>Checked database schema update for apps</info>' );
});
2015-06-23 08:43:45 +00:00
$updater -> listen ( '\OC\Updater' , 'appUpgradeStarted' , function ( $app , $version ) use ( $output ) {
$output -> writeln ( " <info>Updating < $app > ...</info> " );
});
2015-02-24 11:52:16 +00:00
$updater -> listen ( '\OC\Updater' , 'appUpgrade' , function ( $app , $version ) use ( $output ) {
$output -> writeln ( " <info>Updated < $app > to $version </info> " );
});
2014-09-22 09:59:13 +00:00
$updater -> listen ( '\OC\Updater' , 'failure' , function ( $message ) use ( $output , $self ) {
$output -> writeln ( " <error> $message </error> " );
2013-10-28 14:15:56 +00:00
});
2015-09-29 12:35:32 +00:00
$updater -> listen ( '\OC\Updater' , 'setDebugLogLevel' , function ( $logLevel , $logLevelName ) use ( $output ) {
$output -> writeln ( " <info>Set log level to debug - current level: ' $logLevelName '</info> " );
});
$updater -> listen ( '\OC\Updater' , 'resetLogLevel' , function ( $logLevel , $logLevelName ) use ( $output ) {
$output -> writeln ( " <info>Reset log level to ' $logLevelName '</info> " );
});
2013-10-28 14:15:56 +00:00
2015-06-23 08:22:24 +00:00
if ( OutputInterface :: VERBOSITY_NORMAL < $output -> getVerbosity ()) {
$updater -> listen ( '\OC\Updater' , 'repairInfo' , function ( $message ) use ( $output ) {
$output -> writeln ( '<info>Repair info: ' . $message . '</info>' );
});
$updater -> listen ( '\OC\Updater' , 'repairStep' , function ( $message ) use ( $output ) {
$output -> writeln ( '<info>Repair step: ' . $message . '</info>' );
});
}
2015-06-23 08:03:27 +00:00
$success = $updater -> upgrade ();
2014-03-14 09:48:07 +00:00
$this -> postUpgradeCheck ( $input , $output );
2015-06-23 08:03:27 +00:00
if ( ! $success ) {
return self :: ERROR_FAILURE ;
}
2013-10-28 20:50:28 +00:00
return self :: ERROR_SUCCESS ;
2014-09-22 10:04:48 +00:00
} else if ( $this -> config -> getSystemValue ( 'maintenance' , false )) {
2013-10-28 21:19:15 +00:00
//Possible scenario: ownCloud core is updated but an app failed
2013-10-28 21:26:44 +00:00
$output -> writeln ( '<warning>ownCloud is in maintenance mode</warning>' );
$output -> write ( '<comment>Maybe an upgrade is already in process. Please check the '
2013-10-28 21:19:15 +00:00
. 'logfile (data/owncloud.log). If you want to re-run the '
. 'upgrade procedure, remove the "maintenance mode" from '
2013-10-28 21:26:44 +00:00
. 'config.php and call this script again.</comment>'
2013-10-28 21:19:15 +00:00
, true );
return self :: ERROR_MAINTENANCE_MODE ;
2013-10-28 14:15:56 +00:00
} else {
2013-10-28 21:26:44 +00:00
$output -> writeln ( '<info>ownCloud is already latest version</info>' );
2013-10-28 21:19:15 +00:00
return self :: ERROR_UP_TO_DATE ;
2013-10-28 14:15:56 +00:00
}
2013-10-24 17:59:39 +00:00
}
2014-03-14 09:48:07 +00:00
/**
* Perform a post upgrade check ( specific to the command line tool )
*
* @ param InputInterface $input input interface
* @ param OutputInterface $output output interface
*/
protected function postUpgradeCheck ( InputInterface $input , OutputInterface $output ) {
2014-09-22 10:04:48 +00:00
$trustedDomains = $this -> config -> getSystemValue ( 'trusted_domains' , array ());
2014-03-14 09:48:07 +00:00
if ( empty ( $trustedDomains )) {
$output -> write (
'<warning>The setting "trusted_domains" could not be ' .
'set automatically by the upgrade script, ' .
'please set it manually</warning>'
);
}
}
2013-10-24 17:59:39 +00:00
}