Example #1
0
 /**
  * Loads updates from the implemented classes
  */
 protected function loadUpdates()
 {
     $this->fetchStatusBefore();
     foreach (new UpdatesIterator(self::getPathToUpdates()) as $fileInfo) {
         /* @var $fileInfo \SplFileInfo */
         $updateClass = __NAMESPACE__ . '\\Updates\\' . substr($fileInfo->getFilename(), 0, 20);
         try {
             /* @var $update \Scalr\Upgrade\AbstractUpdate */
             $update = new $updateClass($fileInfo, $this->stateBefore);
             $this->updates[$update->getUuidHex()] = $update;
         } catch (\Exception $e) {
             $this->console->error("Cound not load update %s. %s", $fileInfo->getPathname(), $e->getMessage());
         }
     }
 }
Example #2
0
 /**
  * Applies update
  *
  * @param   AbstractUpdate $upd Update to apply
  *
  * @return bool Returns true if update is successful, false otherwise
  *
  * @throws Exception\UpgradeException
  */
 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));
     }
     $refuseReason = $upd->isRefused();
     if (false !== $refuseReason) {
         if ($this->opt->verbosity) {
             $this->console->notice('%s is ignored. %s', $upd->getName(), (string) $refuseReason);
         }
         return true;
     }
     if ($upd->getStatus() == AbstractUpgradeEntity::STATUS_OK) {
         //Upgrade file is updated.
         $upd->updateAppears();
         if (isset($this->opt->cmd) && $this->opt->cmd == self::CMD_RUN_SPECIFIC && $this->opt->uuid == $upd->getUuidHex()) {
             //User has requested re-execution of update
             $upd->setStatus(AbstractUpgradeEntity::STATUS_PENDING);
             $upd->updateHash();
             $upd->getEntity()->save();
         } else {
             //Compare checksum
             if ($upd->getEntity()->hash == $upd->getHash()) {
                 //file modified time could be the issue
                 $upd->updateApplied();
                 $upd->getEntity()->save();
                 if (!empty($this->opt->verbosity) || isset($this->opt->cmd) && $this->opt->cmd == self::CMD_RUN_SPECIFIC && $this->opt->uuid == $upd->getUuidHex()) {
                     $this->console->warning('Ingnoring %s because of having complete status.', $upd->getName());
                 }
                 return true;
             } else {
                 //We should ignore changes in the script and update hash
                 $upd->updateHash();
                 $upd->getEntity()->save();
                 return true;
             }
         }
     }
     $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 ($upgradeEntity->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->error('Error. Stage %d of update %s could not be applied because of invalid environment! validateBefore(%d) returned false.', $stage, $upd->getName(), $stage);
             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('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;
 }
Example #3
0
    $console->out("");
    $console->out("Usage: upgrade [OPTIONS]");
    $console->out("  -h, --help          Display this help end exit.");
    $console->out("  -n, --new           Generate a new update class to implement.");
    $console->out("  -r uuid             Run only specified update. UUID is unique identifier.");
    $console->out("  -v                  Turn on verbosity.");
    $console->out("  -i                  Turn on interactive mode for upgrades which rely on it.");
    $console->out("  --force             Run forcefully ignoring pid.");
    $console->out("");
    exit;
};
$options = new \stdClass();
//validates options
if (isset($opt['r'])) {
    if (!preg_match('/^[\\da-f]{32}$/i', $opt['r']) && !preg_match('/^[\\da-f]{8}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{12}$/i', $opt['r'])) {
        $console->error("Error usage. UUID should be 32 hexadecimal digit number");
        $showusage();
    }
    $options->cmd = UpgradeHandler::CMD_RUN_SPECIFIC;
    $options->uuid = strtolower(str_replace('-', '', $opt['r']));
}
$options->verbosity = isset($opt['v']);
$options->interactive = isset($opt['i']);
if (isset($opt['help']) || isset($opt['h'])) {
    $showusage();
}
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;
 /**
  * {@inheritdoc}
  * @see \Scalr\System\Pcntl\ProcessInterface::OnStartForking()
  */
 public function OnStartForking()
 {
     $db = \Scalr::getDb();
     $sevenDaysAgo = date('Y-m-d H:i:s', strtotime('-7 days'));
     $tenDaysAgo = date('Y-m-d H:i:s', strtotime('-10 days'));
     $twentyDaysAgo = date('Y-m-d H:i:s', strtotime('-20 days'));
     $monthAgo = date('Y-m-d H:i:s', strtotime('-1 months'));
     $twoMonthAgo = date('Y-m-d H:i:s', strtotime('-2 months'));
     $twoWeeksAgo = date('Y-m-d H:i:s', strtotime('-14 days'));
     $this->console->out("%s (UTC) Start RotateLogsProcess", gmdate('Y-m-d'));
     $this->console->out("Rotating logentries table");
     $this->rotateTable("DELETE FROM `logentries` WHERE `time` < ?", [strtotime('-10 days')]);
     $this->console->out("Rotating scripting_log table");
     $this->rotateTable("DELETE FROM `scripting_log` WHERE `dtadded` < ?", array($sevenDaysAgo));
     $this->console->out("Rotating events table");
     $this->rotateTable("DELETE FROM `events` WHERE `dtadded` < ?", array($twoMonthAgo));
     $this->console->out("Rotating messages table");
     $this->rotateTable("DELETE FROM messages WHERE type='out' AND status='1' AND `dtlasthandleattempt` < ?", array($tenDaysAgo));
     $this->rotateTable("DELETE FROM messages WHERE type='out' AND status='3' AND `dtlasthandleattempt` < ?", array($tenDaysAgo));
     $this->rotateTable("DELETE FROM messages WHERE type='in' AND status='1' AND `dtlasthandleattempt` <  ?", array($tenDaysAgo));
     $this->console->out('Rotating webhook_history table');
     $this->rotateTable("DELETE FROM webhook_history WHERE `created` < ?", array($twoWeeksAgo));
     $this->console->out("Rotating farm_role_scripts table");
     $year = date('Y');
     $month = date('m', strtotime('-1 months'));
     $this->rotateTable("\n            DELETE FROM `farm_role_scripts`\n            WHERE ismenuitem='0' AND event_name LIKE 'CustomEvent-{$year}{$month}%'\n        ");
     $this->rotateTable("\n            DELETE FROM `farm_role_scripts`\n            WHERE ismenuitem='0' AND event_name LIKE 'APIEvent-{$year}{$month}%'\n        ");
     $this->console->out('Calculating number of the records in the syslog table');
     if ($db->GetOne("SELECT COUNT(*) FROM `syslog`") > 1000000) {
         $this->console->out("Rotating syslog table");
         $dtstamp = date("HdmY");
         try {
             if ($db->GetOne("SHOW TABLES LIKE ?", ['syslog_tmp'])) {
                 $db->Execute("DROP TABLE `syslog_tmp`");
             }
             $db->Execute("CREATE TABLE `syslog_tmp` LIKE `syslog`");
             $db->Execute("RENAME TABLE `syslog` TO `syslog_" . $dtstamp . "`, `syslog_tmp` TO `syslog`");
             $db->Execute("TRUNCATE TABLE syslog_metadata");
             $db->Execute("OPTIMIZE TABLE syslog");
             $db->Execute("OPTIMIZE TABLE syslog_metadata");
         } catch (Exception $e) {
             $this->console->error($e->getMessage());
         }
         $this->Logger->debug("Log rotated. New table 'syslog_{$dtstamp}' created.");
         $this->rotateBackup('^syslog_[0-9]{8,10}$');
     }
     //Rotate aws_statistics
     $this->console->out("Rotating AWS Statistics");
     StatisticsPlugin::rotate();
     //Rotate cost analytics data
     if (Scalr::getContainer()->analytics->enabled) {
         $this->console->out("Rotating analytics.poller_sessions table");
         $before = (new DateTime('-7 days', new DateTimeZone('UTC')))->format('Y-m-d H:i:s');
         $this->rotateTable("DELETE FROM `poller_sessions` WHERE `dtime` < ?", [$before], 'cadb');
         $this->console->out("Rotating analytics.usage_h table");
         $before = (new DateTime('-14 days', new DateTimeZone('UTC')))->format('Y-m-d H:i:s');
         $this->rotateTable("DELETE FROM `usage_h` WHERE `dtime` < ?", [$before], 'cadb');
         $this->console->out("Rotating analytics.nm_usage_h table");
         $this->rotateTable("DELETE FROM `nm_usage_h` WHERE `dtime` < ?", [$before], 'cadb');
     }
     $this->console->out('Done');
 }