Esempio n. 1
0
 /**
  * Runs upgrade process
  *
  * @return bool Returns true if all updates completed successfully, false otherwise
  */
 public function run()
 {
     if (!self::checkPid()) {
         $this->console->warning("Cannot start a new process because another one has already been started.");
         return false;
     }
     register_shutdown_function('Scalr\\Upgrade\\UpgradeHandler::removePid');
     //Loads updates
     $successful = $this->loadUpdates();
     if (isset($this->opt->cmd) && $this->opt->cmd == self::CMD_RUN_SPECIFIC) {
         $pending = [];
         if (!isset($this->updates[$this->opt->uuid])) {
             $this->console->warning("Could not find specified update %s", $this->opt->uuid);
             exit(1);
         }
         $pending[] = $this->updates[$this->opt->uuid];
     } else {
         $dt = new \DateTime($this->getLastDate(), new \DateTimeZone('UTC'));
         $pending = $this->updates->getPendingUpdates($dt->getTimestamp());
     }
     if (count($pending) == 0) {
         $this->console->out('Scalr is up-to-date');
         return $successful;
     }
     $this->console->success('Starting Scalr upgrade');
     //Applies updates
     foreach ($pending as $update) {
         $update->console->interactive = $this->console->interactive;
         $successful = $this->applyUpdate($update) && $successful;
     }
     $this->console->success('Done');
     return $successful;
 }
Esempio n. 2
0
}
if (isset($opt['n']) || isset($opt['new'])) {
    $template = UpgradeHandler::getPathToUpdates() . '/Template.php';
    if (!is_readable($template)) {
        $console->error('Could not open template file for reading ' . $template);
        exit;
    }
    $released = gmdate('YmdHis');
    $pathname = UpgradeHandler::getPathToUpdates() . '/Update' . $released . '.php';
    $tpl = PhpTemplate::load($template, array('upd_released' => $released, 'upd_uuid' => \Scalr::GenerateUID()));
    if ($console->confirm("Are you sure you want to create a new upgrade class?")) {
        if (file_put_contents($pathname, $tpl) === false) {
            $console->error('Could not write to file "%s"', $pathname);
            exit;
        }
        $console->success('Upgrade class "%s" has been successfully created.', realpath($pathname));
    }
    exit;
}
if (isset($opt['force'])) {
    UpgradeHandler::removePid();
}
$upgrade = new UpgradeHandler($options);
if (!$upgrade->run()) {
    exit(1);
}
$scalrInfo = Scalr::getContainer()->version();
try {
    Scalr::getDb()->Execute("\n        REPLACE `scalr_hosts`\n        SET `host` = ?, `version` = ?, `edition` = ?, `git_commit` = ?, `git_commit_added` = ?\n    ", [php_uname("n"), $scalrInfo['version'], $scalrInfo['edition'], empty($scalrInfo['gitRevision']) ? null : $scalrInfo['gitRevision'], empty($scalrInfo['gitDate']) || ($gts = strtotime($scalrInfo['gitDate'])) === false ? null : date("Y-m-d H:i:s", $gts)]);
} catch (Exception $e) {
    Scalr::logException($e);
Esempio n. 3
0
 /**
  * Applies update
  *
  * @param   AbstractUpdate   $upd   Update to apply
  */
 protected function applyUpdate(AbstractUpdate $upd)
 {
     if (!isset($this->attempts[$upd->getUuidHex()])) {
         $this->attempts[$upd->getUuidHex()] = 1;
     } else {
         $this->attempts[$upd->getUuidHex()]++;
     }
     if ($this->attempts[$upd->getUuidHex()] > self::MAX_ATTEMPTS) {
         throw new Exception\UpgradeException(sprintf('"%s" Failed due to infinity loop. Max number of attempts (%d) reached!', $upd->getName(), self::MAX_ATTEMPTS));
     }
     if ($upd->getStatus() == AbstractUpgradeEntity::STATUS_OK) {
         //Upgrade file is updated.
         $upd->updateAppears();
         //Compare checksum
         if ($upd->getEntity()->hash == $upd->getHash()) {
             if (isset($this->opt->cmd) && $this->opt->cmd == self::CMD_RUN_SPECIFIC && $this->opt->uuid == $upd->getUuidHex()) {
                 $this->console->warning('Nothing to do. %s has complete status.', $upd->getName());
             }
             return true;
         } else {
             //Update script has been changed and needs to be re-executed
             $upd->setStatus(AbstractUpgradeEntity::STATUS_PENDING);
             $upd->updateHash();
             $upd->getEntity()->save();
         }
     }
     $this->console->success('%s...', $upd->description ?: $upd->getName());
     //Checks updates this upgrade depends upon
     if (!empty($upd->depends)) {
         foreach ($upd->depends as $uuid) {
             $uuidhex = AbstractUpdate::castUuid($uuid);
             if (!empty($this->updates[$uuidhex])) {
                 $update = $this->updates[$uuidhex];
                 if ($update->getStatus() == AbstractUpgradeEntity::STATUS_OK) {
                     //Relative update has already been successfully applied.
                     continue;
                 }
             } else {
                 if (isset($this->stateBefore[$uuidhex])) {
                     /* @var $upgradeEntity \Scalr\Upgrade\Entity\AbstractUpgradeEntity */
                     $upgradeEntity = $this->stateBefore[$uuidhex];
                     if ($updateEntity->status == AbstractUpgradeEntity::STATUS_OK) {
                         //Relative update has already been applied
                         continue;
                     } else {
                         //Relative update needs to be applied before dependant.
                         $this->console->warning('"%s" has been declined as it depends on incomplete update "%s" which has status "%s". ' . 'Desired class "%s" does not exist in the expected folder.', $upd->getName(), $uuid, $upgradeEntity->getStatusName(), $upgradeEntity->getUpdateClassName());
                         return false;
                     }
                 } else {
                     //Relative update has not been delivered yet.
                     $this->console->warning('"%s" has been postponed as it depends on "%s" which has not been delivered yet.', $upd->getName(), $uuid);
                     return false;
                 }
             }
             if ($update->getStatus() == AbstractUpgradeEntity::STATUS_FAILED && isset($this->recurrences[$update->getUuidHex()])) {
                 //Recurrence of the failed status. We don't need to report about it again.
                 $this->console->warning('"%s" has been declined because of failure dependent update "%s".', $upd->getName(), $uuid);
                 return false;
             }
             //Relative update has not been applied or it has incomplete status.
             //We need to apply it first.
             if ($this->applyUpdate($update) === false) {
                 $this->console->warning('"%s" has been declined. Could not apply related update "%s".', $upd->getName(), $update->getName());
                 return false;
             }
         }
     }
     //Checks if update class implements SequenceInterface
     $stages = $upd instanceof SequenceInterface ? range(1, $upd->getNumberStages()) : array(1);
     $skip = 0;
     foreach ($stages as $stage) {
         //Checks if update is applied
         if ($upd->isApplied($stage)) {
             $upd->console->warning('Skips over the stage %d of update %s because it has already been applied.', $stage, $upd->getName());
             $skip++;
             continue;
         }
         //Validates environment before applying
         if (!$upd->validateBefore($stage)) {
             $this->console->warning('Stage %d of update %s could not be applied because of invalid environment!', $stage, $upd->getName());
             return false;
         }
         //Applies the update
         try {
             $upd->run($stage);
         } catch (\Exception $e) {
             //We should avoid repetition when another update depends on failed.
             $this->recurrences[$upd->getUuidHex()] = true;
             $upd->setStatus(AbstractUpgradeEntity::STATUS_FAILED);
             $upd->console->error('Stage %d of update %s failed! %s', $stage, $upd->getName(), $e->getMessage());
             $upd->getEntity()->save();
             $upd->getEntity()->createFailureMessage($upd->console->getLog());
             return false;
         }
     }
     $this->console->success("%s - OK", $upd->description ?: $upd->getName());
     $upd->setStatus(AbstractUpgradeEntity::STATUS_OK);
     $upd->updateHash();
     $upd->updateApplied();
     $upd->getEntity()->save();
     return true;
 }