/** * {@inheritdoc} * @see \Scalr\System\Zmq\Cron\TaskInterface::worker() */ public function worker($request) { //Warming up static DI cache \Scalr::getContainer()->warmup(); // Reconfigure observers \Scalr::ReconfigureObservers(); try { $dbFarm = DBFarm::LoadByID($request->farmId); $curDate = new DateTime(); $tdValue = $dbFarm->GetSetting(DBFarm::SETTING_LEASE_TERMINATE_DATE); if ($tdValue) { $td = new DateTime($tdValue); if ($td < $curDate) { //Terminates farm $event = new FarmTerminatedEvent(0, 1, false, 1); SettingEntity::increase(SettingEntity::LEASE_TERMINATE_FARM); \Scalr::FireEvent($request->farmId, $event); $this->log('INFO', sprintf('Farm: %s [ID: %d] was terminated by lease manager', $dbFarm->Name, $dbFarm->ID)); } else { // only inform user $days = $td->diff($curDate)->days; $notifications = json_decode($dbFarm->GetSetting(DBFarm::SETTING_LEASE_NOTIFICATION_SEND), true); $governance = new Scalr_Governance($dbFarm->EnvID); $settings = $governance->getValue(Scalr_Governance::CATEGORY_GENERAL, Scalr_Governance::GENERAL_LEASE, 'notifications'); if (is_array($settings)) { foreach ($settings as $n) { if (!$notifications[$n['key']] && $n['period'] >= $days) { $mailer = \Scalr::getContainer()->mailer; $tdHuman = Scalr_Util_DateTime::convertDateTime($td, $dbFarm->GetSetting(DBFarm::SETTING_TIMEZONE), 'M j, Y'); if ($n['to'] == 'owner') { $user = new Scalr_Account_User(); $user->loadById($dbFarm->createdByUserId); if (\Scalr::config('scalr.auth_mode') == 'ldap') { $email = $user->getSetting(Scalr_Account_User::SETTING_LDAP_EMAIL); if (!$email) { $email = $user->getEmail(); } } else { $email = $user->getEmail(); } $mailer->addTo($email); } else { foreach (explode(',', $n['emails']) as $email) { $mailer->addTo(trim($email)); } } $mailer->sendTemplate(SCALR_TEMPLATES_PATH . '/emails/farm_lease_terminate.eml', array('{{terminate_date}}' => $tdHuman, '{{farm}}' => $dbFarm->Name, '{{envName}}' => $dbFarm->GetEnvironmentObject()->name, '{{envId}}' => $dbFarm->GetEnvironmentObject()->id)); $notifications[$n['key']] = 1; $dbFarm->SetSetting(DBFarm::SETTING_LEASE_NOTIFICATION_SEND, json_encode($notifications)); $this->log('INFO', "Notification was sent by key: %s about farm: %s [ID: %d] by lease manager", $n['key'], $dbFarm->Name, $dbFarm->ID); } } } } } } catch (Exception $e) { throw $e; } return $request; }
/** * {@inheritdoc} * @see Scalr\Tests\TestCase::tearDownAfterClass() */ public static function tearDownAfterClass() { foreach (static::$testData as $rec) { if ($rec['class'] === Farm::class) { $entry = $rec['pk']; $farm = Farm::findPk(...$entry); /* @var $farm Farm */ if (!empty($farm)) { try { \Scalr::FireEvent($farm->id, new FarmTerminatedEvent(false, false, false, false, true, static::$user->id)); foreach ($farm->servers as $server) { try { $dbServer = Server::findPk($server->serverId); /* @var $dbServer Server */ $dbServer->terminate(Server::TERMINATE_REASON_FARM_TERMINATED, true, static::$user); } catch (Exception $e) { \Scalr::logException($e); } $server->delete(); } } catch (Exception $e) { \Scalr::logException($e); } } } } parent::tearDownAfterClass(); }
public function xSaveAction() { $this->request->defineParams(array('presetId' => array('type' => 'int'), 'config' => array('type' => 'array'))); if (!$this->getParam('presetId')) { if (!in_array($this->getParam('roleBehavior'), array(ROLE_BEHAVIORS::MYSQL, ROLE_BEHAVIORS::MYSQL2, ROLE_BEHAVIORS::PERCONA, ROLE_BEHAVIORS::APACHE, ROLE_BEHAVIORS::MEMCACHED, ROLE_BEHAVIORS::NGINX, ROLE_BEHAVIORS::REDIS))) { $err['roleBehavior'] = _("Please select service name"); } if (!$this->getParam('presetName')) { $err['presetName'] = _("Preset name required"); } else { if (strlen($this->getParam('presetName')) < 5) { $err['presetName'] = _("Preset name should be 5 chars or longer"); } elseif (!preg_match("/^[A-Za-z0-9-]+\$/", $this->getParam('presetName'))) { $err['presetName'] = _("Preset name should be alpha-numeric"); } elseif (strtolower($this->getParam('presetName')) == "default") { $err['presetName'] = _("default is reserverd name"); } elseif ($this->getParam('roleBehavior') && $this->db->GetOne("SELECT id FROM service_config_presets WHERE name = ? AND role_behavior = ? AND id != ? AND env_id = ? LIMIT 1", array($this->getParam('presetName'), $this->getParam('roleBehavior'), (int) $this->getParam('presetId'), $this->getEnvironmentId()))) { $err['presetName'] = _("Preset with selected name already exists"); } } } if (count($err) == 0) { $serviceConfiguration = Scalr_ServiceConfiguration::init(); if ($this->getParam('presetId')) { $serviceConfiguration->loadById($this->getParam('presetId')); $this->user->getPermissions()->validate($serviceConfiguration); } else { $serviceConfiguration->loadBy(array('client_id' => $this->user->getAccountId(), 'env_id' => $this->getEnvironmentId(), 'name' => $this->getParam('presetName'), 'role_behavior' => $this->getParam('roleBehavior'))); } $config = $this->getParam('config'); foreach ($config as $k => $v) { $serviceConfiguration->setParameterValue($k, $v); } foreach ($serviceConfiguration->getParameters() as $param) { if ($param->getType() == 'boolean') { if (!$config[$param->getName()]) { $serviceConfiguration->setParameterValue($param->getName(), '0'); } } } $serviceConfiguration->name = $this->getParam('presetName'); $serviceConfiguration->save(); //TODO: $resetToDefaults = false; Scalr::FireEvent(null, new ServiceConfigurationPresetChangedEvent($serviceConfiguration, $resetToDefaults)); $this->response->success('Preset successfully saved'); } else { $this->response->failure(); $this->response->data(array('errors' => $err)); } }
public function FireCustomEvent($ServerID, $EventName, array $Params = array()) { $this->restrictAccess(Acl::RESOURCE_GENERAL_CUSTOM_EVENTS); $dbServer = DBServer::LoadByID($ServerID); if ($dbServer->envId != $this->Environment->id) { throw new Exception(sprintf("Server ID #%s not found", $ServerID)); } if (\Scalr\Model\Entity\EventDefinition::isExist($EventName, $this->user->getAccountId(), $this->Environment->id)) { $event = new CustomEvent($dbServer, $EventName, (array) $Params); } else { throw new Exception(sprintf("Event %s is not defined", $EventName)); } Scalr::FireEvent($dbServer->farmId, $event); $response = $this->CreateInitialResponse(); $response->EventID = $event->GetEventID(); return $response; }
public function xTroubleshootAction() { $this->request->defineParams(array('serverId')); $dbServer = DBServer::LoadByID($this->getParam('serverId')); $this->user->getPermissions()->validate($dbServer); $dbServer->status = SERVER_STATUS::TROUBLESHOOTING; $dbServer->Save(); // Send before host terminate to the server to detach all used volumes. $msg = new Scalr_Messaging_Msg_BeforeHostTerminate($dbServer); if ($dbServer->farmRoleId != 0) { foreach (Scalr_Role_Behavior::getListForFarmRole($dbServer->GetFarmRoleObject()) as $behavior) { $msg = $behavior->extendMessage($msg, $dbServer); } } $dbServer->SendMessage($msg); Scalr::FireEvent($dbServer->farmId, new HostDownEvent($dbServer)); $this->response->success(); }
public function FireCustomEvent($ServerID, $EventName, array $Params = array()) { $this->restrictAccess(Acl::RESOURCE_GENERAL_CUSTOM_EVENTS); $isEventExist = $this->DB->GetOne("\n SELECT id FROM event_definitions\n WHERE name = ? AND env_id = ?\n LIMIT 1\n ", array($EventName, $this->Environment->id)); $dbServer = DBServer::LoadByID($ServerID); if ($dbServer->envId != $this->Environment->id) { throw new Exception(sprintf("Server ID #%s not found", $ServerID)); } if ($isEventExist) { $event = new CustomEvent($dbServer, $EventName, (array) $Params); } else { throw new Exception(sprintf("Event %s is not defined", $EventName)); } Scalr::FireEvent($dbServer->farmId, $event); $response = $this->CreateInitialResponse(); $response->EventID = $event->GetEventID(); return $response; }
public static function farmUpdateRoleSettings(DBFarmRole $DBFarmRole, $oldSettings, $newSettings) { $db = Core::GetDBInstance(); $DBFarm = $DBFarmRole->GetFarmObject(); if (!$oldSettings[DBFarmRole::SETTING_AWS_USE_ELASIC_IPS] && $newSettings[DBFarmRole::SETTING_AWS_USE_ELASIC_IPS]) { $servers = $DBFarmRole->GetServersByFilter(array('status' => SERVER_STATUS::RUNNING)); if (count($servers) == 0) { return; } $AmazonEC2Client = Scalr_Service_Cloud_Aws::newEc2($DBFarmRole->CloudLocation, $DBFarm->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::PRIVATE_KEY), $DBFarm->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::CERTIFICATE)); foreach ($servers as $DBServer) { $address = $AmazonEC2Client->AllocateAddress(); $db->Execute("INSERT INTO elastic_ips SET env_id=?, farmid=?, farm_roleid=?, ipaddress=?, state='0', instance_id='', clientid=?, instance_index=?", array($DBServer->envId, $DBServer->farmId, $DBServer->farmRoleId, $address->publicIp, $DBServer->clientId, $DBServer->index)); Logger::getLogger(__CLASS__)->info(sprintf(_("Allocated new IP: %s"), $address->publicIp)); // Waiting... Logger::getLogger(__CLASS__)->debug(_("Waiting 5 seconds...")); sleep(5); $assign_retries = 1; while (true) { try { // Associate elastic ip address with instance $AmazonEC2Client->AssociateAddress($DBServer->GetProperty(EC2_SERVER_PROPERTIES::INSTANCE_ID), $address->publicIp); } catch (Exception $e) { if (!stristr($e->getMessage(), "does not belong to you") || $assign_retries == 3) { throw new Exception($e->getMessage()); } else { // Waiting... Logger::getLogger(__CLASS__)->debug(_("Waiting 2 seconds...")); sleep(2); $assign_retries++; continue; } } break; } Logger::getLogger(__CLASS__)->info(sprintf(_("IP: %s assigned to instance '%s'"), $address->publicIp, $DBServer->serverId)); // Update leastic IPs table $db->Execute("UPDATE elastic_ips SET state='1', server_id=? WHERE ipaddress=?", array($DBServer->serverId, $address->publicIp)); Scalr::FireEvent($DBFarmRole->FarmID, new IPAddressChangedEvent($DBServer, $address->publicIp)); } } }
public function handleMessage(Scalr_Messaging_Msg $message, DBServer $dbServer) { try { $dbFarmRole = $dbServer->GetFarmRoleObject(); } catch (Exception $e) { } switch (get_class($message)) { case "Scalr_Messaging_Msg_HostUp": if ($message->dbType && in_array($message->dbType, array(ROLE_BEHAVIORS::REDIS, ROLE_BEHAVIORS::POSTGRESQL, ROLE_BEHAVIORS::MYSQL2))) { $dbMsrInfo = Scalr_Db_Msr_Info::init($dbFarmRole, $dbServer, $message->dbType); $dbMsrInfo->setMsrSettings($message->{$message->dbType}); } break; case "Scalr_Messaging_Msg_DbMsr_PromoteToMasterResult": if (Scalr_Db_Msr::onPromoteToMasterResult($message, $dbServer)) { Scalr::FireEvent($dbServer->farmId, new NewDbMsrMasterUpEvent($dbServer)); } break; case "Scalr_Messaging_Msg_DbMsr_CreateDataBundleResult": if ($message->status == "ok") { Scalr_Db_Msr::onCreateDataBundleResult($message, $dbServer); } else { $dbFarmRole->SetSetting(Scalr_Db_Msr::DATA_BUNDLE_IS_RUNNING, 0); //TODO: store last error } break; case "Scalr_Messaging_Msg_DbMsr_CreateBackupResult": if ($message->status == "ok") { Scalr_Db_Msr::onCreateBackupResult($message, $dbServer); } else { $dbFarmRole->SetSetting(Scalr_Db_Msr::DATA_BACKUP_IS_RUNNING, 0); //TODO: store last error } break; } }
/** * Terminates specified farm * * @param int $farmId Unique farm identifier * @param bool $force If true skip all shutdown routines (do not process the BeforeHostTerminate event) * * @return ResultEnvelope * @throws ApiErrorException */ public function terminateAction($farmId, $force = false) { $farm = $this->getFarm($farmId, Acl::PERM_FARMS_LAUNCH_TERMINATE); try { $farm->checkLocked(); \Scalr::FireEvent($farm->id, new FarmTerminatedEvent(false, false, false, false, $force, $this->getUser()->id)); } catch (LockedException $e) { throw new ApiErrorException(409, ErrorMessage::ERR_LOCKED, $e->getMessage() . ", please unlock it first", $e->getCode(), $e); } $farmAdapter = $this->adapter('farm'); return $this->result($farmAdapter->toData($farm)); }
/** * Marks server as to be terminated. * * @param integer|array $reason The reason possibly with the format parameters. * @param bool $forcefully optional Method: forcefully (true) | gracefully (false) * @param Scalr_Account_User|int $user optional The user object or its unique identifier */ public function terminate($reason, $forcefully = null, $user = null) { if (in_array($this->status, array(SERVER_STATUS::PENDING_TERMINATE, SERVER_STATUS::TERMINATED))) { return; } $forcefully = $forcefully === null ? true : (bool) $forcefully; //Ensures handling identifier of the user instead of the object if ($user !== null && !$user instanceof \Scalr_Account_User) { try { $user = Scalr_Account_User::init()->loadById(intval($user)); } catch (\Exception $e) { } } $fnGetReason = function ($reasonId) { $args = func_get_args(); $args[0] = DBServer::getTerminateReason($reasonId); return [call_user_func_array('sprintf', $args), $reasonId]; }; list($reason, $reasonId) = is_array($reason) ? call_user_func_array($fnGetReason, $reason) : $fnGetReason($reason); //Set who does terminate the server if ($user instanceof \Scalr_Account_User) { $this->SetProperties(array(\SERVER_PROPERTIES::TERMINATED_BY_ID => $user->id, \SERVER_PROPERTIES::TERMINATED_BY_EMAIL => $user->getEmail())); } $this->SetProperties([SERVER_PROPERTIES::REBOOTING => 0]); $this->update(['status' => SERVER_STATUS::PENDING_TERMINATE, 'dateShutdownScheduled' => date("Y-m-d H:i:s", $forcefully ? time() : strtotime(Scalr::config('scalr.system.server_terminate_timeout')))]); $this->getServerHistory()->markAsTerminated($reason, $reasonId); if (isset($this->farmId)) { Scalr::FireEvent($this->farmId, new BeforeHostTerminateEvent($this, false)); // If instance was terminated outside scalr, we need manually fire HostDown if ($reasonId == self::TERMINATE_REASON_CRASHED) { Scalr::FireEvent($this->farmId, new HostDownEvent($this, false)); } } }
} $Logger->warn(new ScriptingLogMessage($req_FarmID, $event_name, $DBServer->serverId, sprintf(_("Script '%s' execution result (Execution time: %s seconds). %s %s"), $data['script_path'], $data['time_elapsed'], $stderr, $stdout))); break; case "rebundleStatus": if ($data['bundletaskid']) { try { $BundleTask = BundleTask::LoadById($data['bundletaskid']); if ($BundleTask->serverId == $DBServer->serverId) { $BundleTask->Log($data['message']); } } catch (Exception $e) { } } break; case "logEvent": $message = base64_decode($data["msg"]); $tm = date('YmdH'); $hash = md5("{$DBServer->serverId}:{$message}:{$req_FarmID}:{$data['source']}:{$tm}", true); $db->Execute("INSERT DELAYED INTO logentries SET id=?, serverid=?, message=?, `time`=?, severity=?, `source`=?, farmid=? ON DUPLICATE KEY UPDATE cnt = cnt + 1, `time` = ?", array($hash, $DBServer->serverId, $message, time(), $data["severity"], $data["source"], $req_FarmID, time())); break; } } } if ($event) { Scalr::FireEvent($DBFarm->ID, $event); } exit; } catch (Exception $e) { header("HTTP/1.0 500 Internal Server Error"); die($e->getMessage()); }
/** * @return bool * @throws Exception */ public function execute($manual = false) { $farmRoleNotFound = false; $logger = Logger::getLogger(__CLASS__); switch ($this->type) { case self::LAUNCH_FARM: try { $farmId = $this->targetId; $DBFarm = DBFarm::LoadByID($farmId); if ($DBFarm->Status == FARM_STATUS::TERMINATED) { // launch farm Scalr::FireEvent($farmId, new FarmLaunchedEvent(true)); $logger->info(sprintf("Farm #{$farmId} successfully launched")); } elseif ($DBFarm->Status == FARM_STATUS::RUNNING) { // farm is running $logger->info(sprintf("Farm #{$farmId} is already running")); } else { // farm can't be launched $logger->info(sprintf("Farm #{$farmId} can't be launched because of it's status: {$DBFarm->Status}")); } } catch (Exception $e) { $farmRoleNotFound = true; $logger->info(sprintf("Farm #{$farmId} was not found and can't be launched")); } break; case self::TERMINATE_FARM: try { // get config settings $farmId = $this->targetId; $deleteDNSZones = (int) $this->config['deleteDNSZones']; $deleteCloudObjects = (int) $this->config['deleteCloudObjects']; $keepCloudObjects = $deleteCloudObjects == 1 ? 0 : 1; $DBFarm = DBFarm::LoadByID($farmId); if ($DBFarm->Status == FARM_STATUS::RUNNING) { // terminate farm $event = new FarmTerminatedEvent($deleteDNSZones, $keepCloudObjects, false, $keepCloudObjects); Scalr::FireEvent($farmId, $event); $logger->info(sprintf("Farm successfully terminated")); } else { $logger->info(sprintf("Farm #{$farmId} can't be terminated because of it's status")); } } catch (Exception $e) { $farmRoleNotFound = true; $logger->info(sprintf("Farm #{$farmId} was not found and can't be terminated")); } break; case self::SCRIPT_EXEC: // generate event name $eventName = "Scheduler (TaskID: {$this->id})"; if ($manual) { $eventName .= ' (manual)'; } try { if (!\Scalr\Model\Entity\Script::findPk($this->config['scriptId'])) { throw new Exception('Script not found'); } // get executing object by target_type variable switch ($this->targetType) { case self::TARGET_FARM: $DBFarm = DBFarm::LoadByID($this->targetId); $farmId = $DBFarm->ID; $farmRoleId = null; $servers = $this->db->GetAll("SELECT server_id FROM servers WHERE `status` IN (?,?) AND farm_id = ?", array(SERVER_STATUS::INIT, SERVER_STATUS::RUNNING, $farmId)); break; case self::TARGET_ROLE: $farmRoleId = $this->targetId; $servers = $this->db->GetAll("SELECT server_id FROM servers WHERE `status` IN (?,?) AND farm_roleid = ?", array(SERVER_STATUS::INIT, SERVER_STATUS::RUNNING, $farmRoleId)); break; case self::TARGET_INSTANCE: $servers = $this->db->GetAll("SELECT server_id FROM servers WHERE `status` IN (?,?) AND farm_roleid = ? AND `index` = ? ", array(SERVER_STATUS::INIT, SERVER_STATUS::RUNNING, $this->targetId, $this->targetServerIndex)); break; } if ($servers) { $scriptSettings = array('version' => $this->config['scriptVersion'], 'scriptid' => $this->config['scriptId'], 'timeout' => $this->config['scriptTimeout'], 'issync' => $this->config['scriptIsSync'], 'params' => serialize($this->config['scriptOptions']), 'type' => Scalr_Scripting_Manager::ORCHESTRATION_SCRIPT_TYPE_SCALR); // send message to start executing task (starts script) foreach ($servers as $server) { $DBServer = DBServer::LoadByID($server['server_id']); $msg = new Scalr_Messaging_Msg_ExecScript($eventName); $msg->setServerMetaData($DBServer); $script = Scalr_Scripting_Manager::prepareScript($scriptSettings, $DBServer); $itm = new stdClass(); // Script $itm->asynchronous = $script['issync'] == 1 ? '0' : '1'; $itm->timeout = $script['timeout']; if ($script['body']) { $itm->name = $script['name']; $itm->body = $script['body']; } else { $itm->path = $script['path']; } $itm->executionId = $script['execution_id']; $msg->scripts = array($itm); $msg->setGlobalVariables($DBServer, true); /* if ($DBServer->IsSupported('2.5.12')) { $api = $DBServer->scalarizr->system; $api->timeout = 5; $api->executeScripts( $msg->scripts, $msg->globalVariables, $msg->eventName, $msg->roleName ); } else */ $DBServer->SendMessage($msg, false, true); } } else { $farmRoleNotFound = true; } } catch (Exception $e) { // farm or role not found. $farmRoleNotFound = true; $logger->warn(sprintf("Farm, role or instances were not found, script can't be executed")); } break; } return !$farmRoleNotFound; }
/** * Delete role from farm * @return void */ public function Delete() { foreach ($this->GetServersByFilter() as $DBServer) { /** @var DBServer $DBServer */ if ($DBServer->status != SERVER_STATUS::TERMINATED) { try { $DBServer->terminate(DBServer::TERMINATE_REASON_ROLE_REMOVED); } catch (Exception $e) { } $event = new HostDownEvent($DBServer); Scalr::FireEvent($DBServer->farmId, $event); } } // $this->DB->Execute("DELETE FROM farm_roles WHERE id=?", array($this->ID)); // Clear farm role options & scripts $this->DB->Execute("DELETE FROM farm_role_options WHERE farm_roleid=?", array($this->ID)); $this->DB->Execute("DELETE FROM farm_role_service_config_presets WHERE farm_roleid=?", array($this->ID)); $this->DB->Execute("DELETE FROM farm_role_scaling_metrics WHERE farm_roleid=?", array($this->ID)); $this->DB->Execute("DELETE FROM farm_role_scaling_times WHERE farm_roleid=?", array($this->ID)); $this->DB->Execute("DELETE FROM farm_role_service_config_presets WHERE farm_roleid=?", array($this->ID)); $this->DB->Execute("DELETE FROM farm_role_settings WHERE farm_roleid=?", array($this->ID)); $this->DB->Execute("DELETE FROM farm_role_scripting_targets WHERE `target`=? AND `target_type` = 'farmrole'", array($this->ID)); $this->DB->Execute("DELETE FROM ec2_ebs WHERE farm_roleid=?", array($this->ID)); $this->DB->Execute("DELETE FROM elastic_ips WHERE farm_roleid=?", array($this->ID)); $this->DB->Execute("DELETE FROM storage_volumes WHERE farm_roleid=?", array($this->ID)); // Clear apache vhosts and update DNS zones $this->DB->Execute("UPDATE apache_vhosts SET farm_roleid='0', farm_id='0' WHERE farm_roleid=?", array($this->ID)); $this->DB->Execute("UPDATE dns_zones SET farm_roleid='0' WHERE farm_roleid=?", array($this->ID)); // Clear scheduler tasks $this->DB->Execute("DELETE FROM scheduler WHERE target_id = ? AND target_type IN(?,?)", array($this->ID, Scalr_SchedulerTask::TARGET_ROLE, Scalr_SchedulerTask::TARGET_INSTANCE)); }
/** * {@inheritdoc} * @see \Scalr\System\Zmq\Cron\TaskInterface::worker() */ public function worker($request) { //Warming up static DI cache \Scalr::getContainer()->warmup(); // Reconfigure observers \Scalr::ReconfigureObservers(); try { $dbFarm = DBFarm::LoadByID($request->farmId); $curDate = new DateTime(); $tdValue = $dbFarm->GetSetting(Entity\FarmSetting::LEASE_TERMINATE_DATE); if ($tdValue) { $td = new DateTime($tdValue); if ($td < $curDate) { //Terminates farm SettingEntity::increase(SettingEntity::LEASE_TERMINATE_FARM); //Ajdusts both account & environment for the audit log \Scalr::getContainer()->auditlogger->setAccountId($dbFarm->ClientID)->setAccountId($dbFarm->EnvID); \Scalr::FireEvent($request->farmId, new FarmTerminatedEvent(0, 1, false, 1, true, null)); $this->log('INFO', sprintf('Farm: %s [ID: %d] was terminated by lease manager', $dbFarm->Name, $dbFarm->ID)); } else { // only inform user $days = $td->diff($curDate)->days; $notifications = json_decode($dbFarm->GetSetting(Entity\FarmSetting::LEASE_NOTIFICATION_SEND), true); $governance = new Scalr_Governance($dbFarm->EnvID); $settings = $governance->getValue(Scalr_Governance::CATEGORY_GENERAL, Scalr_Governance::GENERAL_LEASE, 'notifications'); if (is_array($settings)) { foreach ($settings as $n) { if (!$notifications[$n['key']] && $n['period'] >= $days) { $mailer = \Scalr::getContainer()->mailer; $tdHuman = Scalr_Util_DateTime::convertDateTime($td, $dbFarm->GetSetting(Entity\FarmSetting::TIMEZONE), 'M j, Y'); /* @var $user Entity\Account\User */ if ($n['to'] == 'owner') { if ($dbFarm->ownerId) { $user = Entity\Account\User::findPk($dbFarm->ownerId); } else { $user = Entity\Account\User::findOne([['accountId' => $dbFarm->ClientID], ['type' => Entity\Account\User::TYPE_ACCOUNT_OWNER]]); } if (\Scalr::config('scalr.auth_mode') == 'ldap') { $email = $user->getSetting(Entity\Account\User\UserSetting::NAME_LDAP_EMAIL); if (!$email) { $email = $user->email; } } else { $email = $user->email; } $mailer->addTo($email); } else { foreach (explode(',', $n['emails']) as $email) { $mailer->addTo(trim($email)); } } $mailer->sendTemplate(SCALR_TEMPLATES_PATH . '/emails/farm_lease_terminate.eml.php', array('terminateDate' => $tdHuman, 'farm' => $dbFarm->Name, 'envName' => $dbFarm->GetEnvironmentObject()->name, 'envId' => $dbFarm->GetEnvironmentObject()->id, 'showOwnerWarning' => !$dbFarm->ownerId)); $notifications[$n['key']] = 1; $dbFarm->SetSetting(Entity\FarmSetting::LEASE_NOTIFICATION_SEND, json_encode($notifications)); $this->log('INFO', "Notification was sent by key: %s about farm: %s [ID: %d] by lease manager", $n['key'], $dbFarm->Name, $dbFarm->ID); } } } } } } catch (Exception $e) { throw $e; } return $request; }
/** * {@inheritdoc} * @see \Scalr\System\Zmq\Cron\TaskInterface::worker() */ public function worker($request) { $serverId = $request->serverId; $logger = Logger::getLogger(__CLASS__); $this->log("INFO", "Processing messages for %s server", $serverId); try { $dbserver = DBServer::LoadByID($serverId); if ($dbserver->farmId) { if ($dbserver->GetFarmObject()->Status == FARM_STATUS::TERMINATED) { throw new ServerNotFoundException("Farm related to this server has been terminated."); } } } catch (ServerNotFoundException $e) { //By some reason server does not exist $this->db->Execute("\n DELETE m FROM messages m\n WHERE m.server_id = ? AND m.`type` = ? AND m.`status` = ?\n ", [$serverId, "in", MESSAGE_STATUS::PENDING]); return false; } //Warming up static DI cache \Scalr::getContainer()->warmup(); // Reconfigure observers \Scalr::ReconfigureObservers(); $rs = $this->db->Execute("\n SELECT m.* FROM messages m\n WHERE m.server_id = ? AND m.type = ? AND m.status = ?\n ORDER BY m.dtadded ASC\n ", [$serverId, "in", MESSAGE_STATUS::PENDING]); while ($row = $rs->FetchRow()) { try { if ($row["message_format"] == 'xml') { $message = $this->serializer->unserialize($row["message"]); } else { $message = $this->jsonSerializer->unserialize($row["message"]); $dbserver->SetProperty(SERVER_PROPERTIES::SZR_MESSAGE_FORMAT, 'json'); } $message->messageIpAddress = $row['ipaddress']; $event = null; $startTime = microtime(true); // Update scalarizr package version if ($message->meta[Scalr_Messaging_MsgMeta::SZR_VERSION]) { $dbserver->setScalarizrVersion($message->meta[Scalr_Messaging_MsgMeta::SZR_VERSION]); } if ($message->meta[Scalr_Messaging_MsgMeta::SZR_UPD_CLIENT_VERSION]) { $dbserver->SetProperty(SERVER_PROPERTIES::SZR_UPD_CLIENT_VERSION, $message->meta[Scalr_Messaging_MsgMeta::SZR_UPD_CLIENT_VERSION]); } if ($dbserver->GetProperty(SERVER_PROPERTIES::SYSTEM_IGNORE_INBOUND_MESSAGES)) { continue; } if ($message instanceof \Scalr_Messaging_Msg) { $this->log('INFO', "Handling '%s' for '%s' server", $message->getName(), $serverId); } try { if ($message instanceof Scalr_Messaging_Msg_OperationResult) { if ($message->status == 'ok' || $message->status == 'completed') { if ($message->name == 'Grow MySQL/Percona data volume' || $message->name == 'mysql.grow-volume') { $volumeConfig = $message->data ? $message->data : $message->result; $oldVolumeId = $dbserver->GetFarmRoleObject()->GetSetting(Scalr_Db_Msr::VOLUME_ID); $engine = $dbserver->GetFarmRoleObject()->GetSetting(Scalr_Db_Msr::DATA_STORAGE_ENGINE); try { $storageVolume = Scalr_Storage_Volume::init(); try { $storageVolume->loadById($volumeConfig->id); $storageVolume->setConfig($volumeConfig); $storageVolume->save(); } catch (Exception $e) { if (strpos($e->getMessage(), 'not found')) { $storageVolume->loadBy(array('id' => $volumeConfig->id, 'client_id' => $dbserver->clientId, 'env_id' => $dbserver->envId, 'name' => "'{$volumeConfig->tags->service}' data volume", 'type' => $engine, 'platform' => $dbserver->platform, 'size' => $volumeConfig->size, 'fstype' => $volumeConfig->fstype, 'purpose' => $volumeConfig->tags->service, 'farm_roleid' => $dbserver->farmRoleId, 'server_index' => $dbserver->index)); $storageVolume->setConfig($volumeConfig); $storageVolume->save(true); } else { throw $e; } } $dbserver->GetFarmRoleObject()->SetSetting(Scalr_Db_Msr::VOLUME_ID, $volumeConfig->id, DBFarmRole::TYPE_LCL); if ($engine == MYSQL_STORAGE_ENGINE::EBS) { $dbserver->GetFarmRoleObject()->SetSetting(Scalr_Db_Msr::DATA_STORAGE_EBS_SIZE, $volumeConfig->size, DBFarmRole::TYPE_CFG); } elseif ($engine == MYSQL_STORAGE_ENGINE::RAID_EBS) { $dbserver->GetFarmRoleObject()->SetSetting(Scalr_Db_Msr::DATA_STORAGE_RAID_DISK_SIZE, $volumeConfig->size, DBFarmRole::TYPE_CFG); } // Remove old $storageVolume->delete($oldVolumeId); } catch (Exception $e) { Logger::getLogger(__CLASS__)->error(new FarmLogMessage($dbserver->farmId, "Cannot save storage volume: {$e->getMessage()}")); } } } elseif ($message->status == 'error' || $message->status == 'failed') { if ($message->name == 'Initialization' || $message->name == 'system.init') { $dbserver->SetProperty(SERVER_PROPERTIES::SZR_IS_INIT_FAILED, 1); if (is_object($message->error)) { $errorText = $message->error->message; } elseif ($message->error) { $errorText = $message->error; } $dbserver->SetProperty(SERVER_PROPERTIES::SZR_IS_INIT_ERROR_MSG, $errorText); $event = new HostInitFailedEvent($dbserver, $errorText); } } } elseif ($message instanceof Scalr_Messaging_Msg_InitFailed) { $errorText = $message->reason; $dbserver->SetProperty(SERVER_PROPERTIES::SZR_IS_INIT_ERROR_MSG, $errorText); $event = new HostInitFailedEvent($dbserver, $errorText); } elseif ($message instanceof \Scalr_Messaging_Msg_RuntimeError) { $logger->fatal(new FarmLogMessage($dbserver->farmId, "Scalarizr failed to launch on server '{$dbserver->getNameByConvention()}' with runtime error: {$message->message}", $dbserver->serverId)); } elseif ($message instanceof Scalr_Messaging_Msg_UpdateControlPorts) { $apiPort = $message->api; $ctrlPort = $message->messaging; $snmpPort = $message->snmp; // Check API port; $currentApiPort = $dbserver->GetProperty(SERVER_PROPERTIES::SZR_API_PORT); if (!$currentApiPort) { $currentApiPort = 8010; } if ($apiPort && $apiPort != $currentApiPort) { $logger->warn(new FarmLogMessage($dbserver->farmId, "Scalarizr API port was changed from {$currentApiPort} to {$apiPort}", $dbserver->serverId)); $dbserver->SetProperty(SERVER_PROPERTIES::SZR_API_PORT, $apiPort); } // Check Control port $currentCtrlPort = $dbserver->GetProperty(SERVER_PROPERTIES::SZR_CTRL_PORT); if (!$currentCtrlPort) { $currentCtrlPort = 8013; } if ($ctrlPort && $ctrlPort != $currentCtrlPort) { $logger->warn(new FarmLogMessage($dbserver->farmId, "Scalarizr Control port was changed from {$currentCtrlPort} to {$ctrlPort}", $dbserver->serverId)); $dbserver->SetProperty(SERVER_PROPERTIES::SZR_CTRL_PORT, $ctrlPort); } //Check SNMP port $currentSnmpPort = $dbserver->GetProperty(SERVER_PROPERTIES::SZR_SNMP_PORT); if (!$currentSnmpPort) { $currentSnmpPort = 8014; } if ($snmpPort && $snmpPort != $currentSnmpPort) { $logger->warn(new FarmLogMessage($dbserver->farmId, "Scalarizr SNMP port was changed from {$currentSnmpPort} to {$snmpPort}", $dbserver->serverId)); $dbserver->SetProperty(SERVER_PROPERTIES::SZR_SNMP_PORT, $snmpPort); } } elseif ($message instanceof Scalr_Messaging_Msg_Win_HostDown) { $status = PlatformFactory::NewPlatform($dbserver->platform)->GetServerRealStatus($dbserver); if ($status->isRunning()) { $event = new RebootBeginEvent($dbserver); } else { if ($dbserver->platform == SERVER_PLATFORMS::EC2) { if (!$status->isTerminated()) { //Stopping $logger->error(new FarmLogMessage($dbserver->farmId, "Server is in '{$status->getName()}' state. Ignoring HostDown event.", $dbserver->serverId)); $isStopping = true; } } if ($isStopping) { $dbserver->SetProperties([SERVER_PROPERTIES::REBOOTING => 0, SERVER_PROPERTIES::RESUMING => 0]); $dbserver->remoteIp = ""; $dbserver->localIp = ""; $dbserver->status = SERVER_STATUS::SUSPENDED; $dbserver->Save(); } $event = new HostDownEvent($dbserver); $event->isSuspended = true; } } elseif ($message instanceof Scalr_Messaging_Msg_Win_PrepareBundleResult) { try { $bundleTask = BundleTask::LoadById($message->bundleTaskId); } catch (Exception $e) { } if ($bundleTask) { if ($bundleTask->status == SERVER_SNAPSHOT_CREATION_STATUS::PREPARING) { if ($message->status == 'ok') { $metaData = array('szr_version' => $message->meta[Scalr_Messaging_MsgMeta::SZR_VERSION], 'os' => $message->os, 'software' => $message->software); $bundleTask->setMetaData($metaData); $bundleTask->Save(); PlatformFactory::NewPlatform($bundleTask->platform)->CreateServerSnapshot($bundleTask); } else { $bundleTask->SnapshotCreationFailed("PrepareBundle procedure failed: {$message->lastError}"); } } } } elseif ($message instanceof Scalr_Messaging_Msg_DeployResult) { try { $deploymentTask = Scalr_Model::init(Scalr_Model::DM_DEPLOYMENT_TASK)->loadById($message->deployTaskId); } catch (Exception $e) { } if ($deploymentTask) { if ($message->status == 'error') { $deploymentTask->status = Scalr_Dm_DeploymentTask::STATUS_FAILED; $deploymentTask->lastError = $message->lastError; } else { $deploymentTask->status = Scalr_Dm_DeploymentTask::STATUS_DEPLOYED; $deploymentTask->dtDeployed = date("Y-m-d H:i:s"); } $deploymentTask->save(); } } elseif ($message instanceof Scalr_Messaging_Msg_Hello) { $event = $this->onHello($message, $dbserver); } elseif ($message instanceof Scalr_Messaging_Msg_FireEvent) { //Validate event $isEventExist = $this->db->GetOne("\n SELECT id FROM event_definitions\n WHERE name = ? AND ((env_id = ? AND account_id = ?) OR (env_id IS NULL AND account_id = ?) OR (env_id IS NULL AND account_id IS NULL))\n LIMIT 1\n ", array($message->eventName, $dbserver->envId, $dbserver->clientId, $dbserver->clientId)); if ($isEventExist) { $event = new CustomEvent($dbserver, $message->eventName, (array) $message->params); } } elseif ($message instanceof Scalr_Messaging_Msg_HostUpdate) { try { $dbFarmRole = $dbserver->GetFarmRoleObject(); } catch (Exception $e) { } if ($dbFarmRole instanceof DBFarmRole) { foreach (Scalr_Role_Behavior::getListForFarmRole($dbFarmRole) as $behavior) { $behavior->handleMessage($message, $dbserver); } } } elseif ($message instanceof Scalr_Messaging_Msg_MongoDb) { /********* MONGODB *********/ try { $dbFarmRole = $dbserver->GetFarmRoleObject(); } catch (Exception $e) { } if ($dbFarmRole instanceof DBFarmRole) { foreach (Scalr_Role_Behavior::getListForFarmRole($dbFarmRole) as $behavior) { $behavior->handleMessage($message, $dbserver); } } } elseif ($message instanceof Scalr_Messaging_Msg_DbMsr) { /********* DBMSR *********/ try { $dbFarmRole = $dbserver->GetFarmRoleObject(); } catch (Exception $e) { } if ($dbFarmRole instanceof DBFarmRole) { foreach (Scalr_Role_Behavior::getListForFarmRole($dbFarmRole) as $behavior) { $behavior->handleMessage($message, $dbserver); } } } elseif ($message instanceof Scalr_Messaging_Msg_HostInit) { $event = $this->onHostInit($message, $dbserver); try { $dbserver->updateTimelog('ts_hi', $message->secondsSinceBoot, $message->secondsSinceStart); } catch (Exception $e) { } if (!$event) { continue; } } elseif ($message instanceof Scalr_Messaging_Msg_HostUp) { $event = $this->onHostUp($message, $dbserver); try { $dbserver->updateTimelog('ts_hu'); } catch (Exception $e) { } } elseif ($message instanceof Scalr_Messaging_Msg_HostDown) { $ignoreHostDown = false; $p = PlatformFactory::NewPlatform($dbserver->platform); $status = $p->GetServerRealStatus($dbserver); if ($dbserver->isOpenstack()) { if (stristr($status->getName(), 'REBOOT') || stristr($status->getName(), 'HARD_REBOOT')) { $logger->error(new FarmLogMessage($dbserver->farmId, "Rackspace server is in " . $status->getName() . " state. Ignoring HostDown message.", $dbserver->serverId)); $isRebooting = true; } } elseif ($dbserver->platform == \SERVER_PLATFORMS::GCE) { if ($status->getName() == 'STOPPING') { // We don't know is this shutdown or stop so let's ignore HostDown // and wait for status change $doNotProcessMessage = true; $ignoreHostDown = true; } elseif ($status->getName() == 'RUNNING') { $isRebooting = true; } elseif ($status->isSuspended() && $dbserver->status != \SERVER_STATUS::PENDING_TERMINATE) { $isStopping = true; } } else { if ($p->getResumeStrategy() == 'init') { //TODO: Check is is stopping or shutting-down procedure. if (!$status->isTerminated()) { $isStopping = true; } } } if ($isStopping) { $dbserver->SetProperties([SERVER_PROPERTIES::REBOOTING => 0, SERVER_PROPERTIES::RESUMING => 0]); $dbserver->remoteIp = ""; $dbserver->localIp = ""; $dbserver->status = SERVER_STATUS::SUSPENDED; $dbserver->Save(); $event = new HostDownEvent($dbserver); $event->isSuspended = true; } elseif ($isRebooting) { $event = new RebootBeginEvent($dbserver); } elseif (!$ignoreHostDown) { if ($dbserver->farmId) { $wasHostDownFired = $this->db->GetOne("SELECT id FROM events WHERE event_server_id = ? AND type = ? AND is_suspend = '0'", array($dbserver->serverId, 'HostDown')); if (!$wasHostDownFired) { $event = new HostDownEvent($dbserver); } } } } elseif ($message instanceof Scalr_Messaging_Msg_RebootStart) { $event = new RebootBeginEvent($dbserver); } elseif ($message instanceof Scalr_Messaging_Msg_RebootFinish) { if (!$dbserver->localIp && $message->localIp) { $dbserver->localIp = $message->localIp; $dbserver->Save(); } $event = new RebootCompleteEvent($dbserver); } elseif ($message instanceof Scalr_Messaging_Msg_BeforeHostUp) { $event = new BeforeHostUpEvent($dbserver); try { $dbserver->updateTimelog('ts_bhu'); } catch (Exception $e) { } } elseif ($message instanceof Scalr_Messaging_Msg_BlockDeviceAttached) { if ($dbserver->platform == SERVER_PLATFORMS::EC2) { $aws = $dbserver->GetEnvironmentObject()->aws($dbserver->GetProperty(EC2_SERVER_PROPERTIES::REGION)); $instanceId = $dbserver->GetProperty(EC2_SERVER_PROPERTIES::INSTANCE_ID); //The main goal of using filters there is to considerably decrease the size of the response. $volumes = $aws->ec2->volume->describe(null, array(array('name' => VolumeFilterNameType::attachmentInstanceId(), 'value' => (string) $instanceId), array('name' => VolumeFilterNameType::attachmentDevice(), 'value' => (string) $message->deviceName), array('name' => VolumeFilterNameType::status(), 'value' => AMAZON_EBS_STATE::IN_USE))); foreach ($volumes as $volume) { /* @var $volume Scalr\Service\Aws\Ec2\DataType\VolumeData */ if ($volume->status == AMAZON_EBS_STATE::IN_USE && count($volume->attachmentSet) && $volume->attachmentSet[0]->instanceId == $instanceId && $volume->attachmentSet[0]->device == $message->deviceName) { $message->volumeId = $volume->volumeId; } } //Releases memory unset($volumes); $dbserver->GetEnvironmentObject()->getContainer()->release('aws'); unset($aws); } $event = new EBSVolumeAttachedEvent($dbserver, $message->deviceName, $message->volumeId); } elseif ($message instanceof Scalr_Messaging_Msg_BlockDeviceMounted) { // Single volume $ebsinfo = $this->db->GetRow("\n SELECT * FROM ec2_ebs WHERE volume_id=? LIMIT 1\n ", array($message->volumeId)); if ($ebsinfo) { $this->db->Execute("\n UPDATE ec2_ebs\n SET mount_status=?, isfsexist='1'\n WHERE id=?\n ", array(EC2_EBS_MOUNT_STATUS::MOUNTED, $ebsinfo['id'])); } $event = new EBSVolumeMountedEvent($dbserver, $message->mountpoint, $message->volumeId, $message->deviceName); } elseif ($message instanceof Scalr_Messaging_Msg_RebundleResult) { if ($message->status == Scalr_Messaging_Msg_RebundleResult::STATUS_OK) { $metaData = array('szr_version' => $message->meta[Scalr_Messaging_MsgMeta::SZR_VERSION], 'dist' => $message->dist, 'os' => $message->os, 'software' => $message->software); if ($dbserver->platform == SERVER_PLATFORMS::EC2) { if ($message->aws) { if ($message->aws->rootDeviceType == 'ebs') { $tags[] = ROLE_TAGS::EC2_EBS; } if ($message->aws->virtualizationType == 'hvm') { $tags[] = ROLE_TAGS::EC2_HVM; } } else { $aws = $dbserver->GetEnvironmentObject()->aws($dbserver); try { $info = $aws->ec2->image->describe($dbserver->GetProperty(EC2_SERVER_PROPERTIES::AMIID))->get(0); if ($info->rootDeviceType == 'ebs') { $tags[] = ROLE_TAGS::EC2_EBS; } else { try { $bundleTask = BundleTask::LoadById($message->bundleTaskId); if ($bundleTask->bundleType == SERVER_SNAPSHOT_CREATION_TYPE::EC2_EBS) { $tags[] = ROLE_TAGS::EC2_EBS; } } catch (Exception $e) { } } if ($info->virtualizationType == 'hvm') { $tags[] = ROLE_TAGS::EC2_HVM; } unset($info); } catch (Exception $e) { $metaData['tagsError'] = $e->getMessage(); try { $bundleTask = BundleTask::LoadById($message->bundleTaskId); if ($bundleTask->bundleType == SERVER_SNAPSHOT_CREATION_TYPE::EC2_EBS) { $tags[] = ROLE_TAGS::EC2_EBS; } } catch (Exception $e) { } } //Releases memory $dbserver->GetEnvironmentObject()->getContainer()->release('aws'); unset($aws); } } $metaData['tags'] = $tags; $event = new RebundleCompleteEvent($dbserver, $message->snapshotId, $message->bundleTaskId, $metaData); } else { if ($message->status == Scalr_Messaging_Msg_RebundleResult::STATUS_FAILED) { $event = new RebundleFailedEvent($dbserver, $message->bundleTaskId, $message->lastError); } } } elseif ($message instanceof Scalr_Messaging_Msg_Mysql_CreateDataBundleResult) { if ($message->status == "ok") { $event = new MysqlBackupCompleteEvent($dbserver, MYSQL_BACKUP_TYPE::BUNDLE, array('snapshotConfig' => $message->snapshotConfig, 'logFile' => $message->logFile, 'logPos' => $message->logPos, 'dataBundleSize' => $message->dataBundleSize, 'snapshotId' => $message->snapshotId)); } else { $event = new MysqlBackupFailEvent($dbserver, MYSQL_BACKUP_TYPE::BUNDLE); $event->lastError = $message->lastError; } } elseif ($message instanceof Scalr_Messaging_Msg_Mysql_CreateBackupResult) { if ($message->status == "ok") { $event = new MysqlBackupCompleteEvent($dbserver, MYSQL_BACKUP_TYPE::DUMP, array()); $event->backupParts = $message->backupParts; } else { $event = new MysqlBackupFailEvent($dbserver, MYSQL_BACKUP_TYPE::DUMP); $event->lastError = $message->lastError; } } elseif ($message instanceof Scalr_Messaging_Msg_Mysql_PromoteToMasterResult) { $event = $this->onMysql_PromoteToMasterResult($message, $dbserver); } elseif ($message instanceof Scalr_Messaging_Msg_Mysql_CreatePmaUserResult) { $farmRole = DBFarmRole::LoadByID($message->farmRoleId); if ($message->status == "ok") { $farmRole->SetSetting(DBFarmRole::SETTING_MYSQL_PMA_USER, $message->pmaUser, DBFarmRole::TYPE_LCL); $farmRole->SetSetting(DBFarmRole::SETTING_MYSQL_PMA_PASS, $message->pmaPassword, DBFarmRole::TYPE_LCL); } else { $farmRole->SetSetting(DBFarmRole::SETTING_MYSQL_PMA_REQUEST_TIME, "", DBFarmRole::TYPE_LCL); $farmRole->SetSetting(DBFarmRole::SETTING_MYSQL_PMA_REQUEST_ERROR, $message->lastError, DBFarmRole::TYPE_LCL); } } elseif ($message instanceof Scalr_Messaging_Msg_RabbitMq_SetupControlPanelResult) { $farmRole = $dbserver->GetFarmRoleObject(); if ($message->status == "ok") { $mgmtHost = $dbserver->getSzrHost(); if ($message->port) { $mgmtURL = "http://{$mgmtHost}:{$message->port}/mgmt"; } elseif ($message->cpanelUrl) { $info = parse_url($message->cpanelUrl); $mgmtURL = "http://{$mgmtHost}:{$info['port']}/mgmt"; } $farmRole->SetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_SERVER_ID, $dbserver->serverId, DBFarmRole::TYPE_LCL); $farmRole->SetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_URL, $mgmtURL, DBFarmRole::TYPE_LCL); $farmRole->SetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_REQUEST_TIME, "", DBFarmRole::TYPE_LCL); } else { $farmRole->SetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_SERVER_ID, "", DBFarmRole::TYPE_LCL); $farmRole->SetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_REQUEST_TIME, "", DBFarmRole::TYPE_LCL); $farmRole->SetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_ERROR_MSG, $message->lastError, DBFarmRole::TYPE_LCL); } } elseif ($message instanceof Scalr_Messaging_Msg_AmiScriptsMigrationResult) { try { //Open security group: if ($dbserver->platform == SERVER_PLATFORMS::EC2) { $info = PlatformFactory::NewPlatform($dbserver->platform)->GetServerExtendedInformation($dbserver); $sg = explode(", ", $info['Security groups']); foreach ($sg as $sgroup) { if ($sgroup != 'default') { // For Scalarizr $group_rules = array(array('rule' => 'tcp:8013:8013:0.0.0.0/0'), array('rule' => 'udp:8014:8014:0.0.0.0/0')); $aws = $dbserver->GetEnvironmentObject()->aws($dbserver); $ipPermissions = new \Scalr\Service\Aws\Ec2\DataType\IpPermissionList(); foreach ($group_rules as $rule) { $group_rule = explode(":", $rule["rule"]); $ipPermissions->append(new \Scalr\Service\Aws\Ec2\DataType\IpPermissionData($group_rule[0], $group_rule[1], $group_rule[2], new \Scalr\Service\Aws\Ec2\DataType\IpRangeData($group_rule[3]))); } $aws->ec2->securityGroup->authorizeIngress($ipPermissions, null, $sgroup); $dbserver->GetEnvironmentObject()->getContainer()->release('aws'); unset($aws); unset($ipPermissions); break; } } } } catch (Exception $e) { $logger->fatal($e->getMessage()); } $dbserver->SetProperty(SERVER_PROPERTIES::SZR_SNMP_PORT, 8014); $dbserver->SetProperty(SERVER_PROPERTIES::SZR_VESION, "0.7.217"); if ($message->mysql) { $event = $this->onHostUp($message, $dbserver, true); } } $handle_status = MESSAGE_STATUS::HANDLED; } catch (Exception $e) { $handle_status = MESSAGE_STATUS::FAILED; $logger->error(sprintf("Cannot handle message '%s' (message_id: %s) " . "from server '%s' (server_id: %s). %s", $message->getName(), $message->messageId, $dbserver->remoteIp ? $dbserver->remoteIp : '*no-ip*', $dbserver->serverId, $e->getMessage() . "({$e->getFile()}:{$e->getLine()})")); } if (!$doNotProcessMessage) { $totalTime = microtime(true) - $startTime; $this->db->Execute("\n UPDATE messages\n SET status = ?, processing_time = ?, dtlasthandleattempt = NOW()\n WHERE messageid = ?\n ", array($handle_status, $totalTime, $message->messageId)); } else { $logger->info(sprintf("Handle message '%s' (message_id: %s) " . "from server '%s' (server_id: %s) is postponed due to status transition", $message->getName(), $message->messageId, $dbserver->remoteIp ? $dbserver->remoteIp : '*no-ip*', $dbserver->serverId)); } if ($event) { \Scalr::FireEvent($dbserver->farmId, $event); } } catch (Exception $e) { $logger->error($e->getMessage()); } } return $request; }
/** * Launch this farm * * @param User $user optional * The user who initiates Farm launch * * @param array $auditLogExtra optional * Audit log extra fields to record * * @return Farm * * @throws Exception * @throws LockedException */ public function launch($user = null, array $auditLogExtra = null) { $this->checkLocked(); \Scalr::FireEvent($this->id, new FarmLaunchedEvent(true, !empty($user->id) ? $user->id : null, $auditLogExtra)); return $this; }
/** * @test * @functional */ public function testFarmLaunch() { $user = $this->getUser(); /* @var $farm Farm */ $farm = $this->createTestFarm('launch', ['base-ubuntu1404']); $response = $this->launchFarm($farm->id); $this->assertEquals(200, $response->status, $this->printResponseError($response)); $data = $response->getBody()->data; $this->assertEquals($farm->id, $data->id); $farm = Farm::findPk($farm->id); $this->assertEquals($farm->status, FARM_STATUS::RUNNING); $this->assertObjectEqualsEntity($data, $farm); \Scalr::FireEvent($farm->id, new FarmTerminatedEvent(false, false, false, false, true, $user->id)); }
public function FarmLaunch($FarmID) { $response = $this->CreateInitialResponse(); try { $DBFarm = DBFarm::LoadByID($FarmID); if ($DBFarm->EnvID != $this->Environment->id) { throw new Exception("N"); } } catch (Exception $e) { throw new Exception(sprintf("Farm #%s not found", $FarmID)); } $this->user->getPermissions()->validate($DBFarm); $this->restrictFarmAccess($DBFarm, Acl::PERM_FARMS_LAUNCH_TERMINATE); if ($DBFarm->Status == FARM_STATUS::RUNNING) { throw new Exception(sprintf("Farm already running", $FarmID)); } Scalr::FireEvent($FarmID, new FarmLaunchedEvent(true, $this->user->id)); $response->Result = true; return $response; }
/** * Launches server * * @param \ServerCreateInfo $ServerCreateInfo optional The server create info * @param \DBServer $DBServer optional The DBServer object * @param bool $delayed optional * @param integer|array $reason optional * @param \Scalr_Account_User|int $user optional The Scalr_Account_User object or its unique identifier * @return DBServer|null Returns the DBServer object on cussess or null otherwise */ public static function LaunchServer(ServerCreateInfo $ServerCreateInfo = null, DBServer $DBServer = null, $delayed = false, $reason = 0, $user = null) { $db = self::getDb(); $farm = null; //Ensures handling identifier of the user instead of the object if ($user !== null && !$user instanceof \Scalr_Account_User) { try { $user = Scalr_Account_User::init()->loadById(intval($user)); } catch (\Exception $e) { } } if (!$DBServer && $ServerCreateInfo) { $ServerCreateInfo->SetProperties(array(SERVER_PROPERTIES::SZR_KEY => Scalr::GenerateRandomKey(40), SERVER_PROPERTIES::SZR_KEY_TYPE => SZR_KEY_TYPE::ONE_TIME)); $DBServer = DBServer::Create($ServerCreateInfo, false, true); } elseif (!$DBServer && !$ServerCreateInfo) { // incorrect arguments Logger::getLogger(LOG_CATEGORY::FARM)->error(sprintf("Cannot create server")); return null; } $propsToSet = array(); if ($user instanceof \Scalr_Account_User) { $propsToSet[SERVER_PROPERTIES::LAUNCHED_BY_ID] = $user->id; $propsToSet[SERVER_PROPERTIES::LAUNCHED_BY_EMAIL] = $user->getEmail(); } //We should keep role_id and farm_role_id in server properties to use in cost analytics if (!empty($DBServer->farmRoleId)) { $propsToSet[SERVER_PROPERTIES::FARM_ROLE_ID] = $DBServer->farmRoleId; $propsToSet[SERVER_PROPERTIES::ROLE_ID] = $DBServer->farmRoleId ? $DBServer->GetFarmRoleObject()->RoleID : 0; } try { // Ensures the farm object will be fetched as correctly as possible $farm = $DBServer->farmId ? $DBServer->GetFarmObject() : null; $farmRole = $DBServer->farmRoleId ? $DBServer->GetFarmRoleObject() : null; if (!$farmRole instanceof DBFarmRole) { $farmRole = null; } else { if (!$farm instanceof DBFarm) { // Gets farm through FarmRole object in this case $farm = $farmRole->GetFarmObject(); } } if ($farm instanceof DBFarm) { $propsToSet[SERVER_PROPERTIES::FARM_CREATED_BY_ID] = $farm->createdByUserId; $propsToSet[SERVER_PROPERTIES::FARM_CREATED_BY_EMAIL] = $farm->createdByUserEmail; $projectId = $farm->GetSetting(DBFarm::SETTING_PROJECT_ID); if (!empty($projectId)) { try { $projectEntity = ProjectEntity::findPk($projectId); if ($projectEntity instanceof ProjectEntity) { /* @var $projectEntity ProjectEntity */ $ccId = $projectEntity->ccId; } else { $projectId = null; } } catch (Exception $e) { $projectId = null; } } $propsToSet[SERVER_PROPERTIES::FARM_PROJECT_ID] = $projectId; } if ($farmRole instanceof DBFarmRole) { $propsToSet[SERVER_PROPERTIES::INFO_INSTANCE_TYPE_NAME] = $farmRole->GetSetting(DBFarmRole::SETTING_INFO_INSTANCE_TYPE_NAME); } if (!empty($ccId)) { $propsToSet[SERVER_PROPERTIES::ENV_CC_ID] = $ccId; } elseif ($DBServer->envId && ($environment = $DBServer->GetEnvironmentObject()) instanceof Scalr_Environment) { $propsToSet[SERVER_PROPERTIES::ENV_CC_ID] = $environment->getPlatformConfigValue(Scalr_Environment::SETTING_CC_ID); } } catch (Exception $e) { Logger::getLogger(LOG_CATEGORY::FARM)->error(sprintf("Could not load related object for recently created server %s. It says: %s", $DBServer->serverId, $e->getMessage())); } if (!empty($propsToSet)) { $DBServer->SetProperties($propsToSet); } $fnGetReason = function ($reasonId) { $args = func_get_args(); $args[0] = DBServer::getLaunchReason($reasonId); return [call_user_func_array('sprintf', $args), $reasonId]; }; if ($delayed) { $DBServer->status = SERVER_STATUS::PENDING_LAUNCH; list($reasonMsg, $reasonId) = is_array($reason) ? call_user_func_array($fnGetReason, $reason) : $fnGetReason($reason); $DBServer->SetProperties([SERVER_PROPERTIES::LAUNCH_REASON => $reasonMsg, SERVER_PROPERTIES::LAUNCH_REASON_ID => $reasonId]); $DBServer->Save(); return $DBServer; } if ($ServerCreateInfo && $ServerCreateInfo->roleId) { $dbRole = DBRole::loadById($ServerCreateInfo->roleId); if ($dbRole->generation == 1) { $DBServer->status = SERVER_STATUS::PENDING_LAUNCH; $DBServer->Save(); $DBServer->SetProperties([SERVER_PROPERTIES::LAUNCH_ERROR => "ami-scripts servers no longer supported", SERVER_PROPERTIES::LAUNCH_ATTEMPT => $DBServer->GetProperty(SERVER_PROPERTIES::LAUNCH_ATTEMPT) + 1, SERVER_PROPERTIES::LAUNCH_LAST_TRY => (new DateTime())->format('Y-m-d H:i:s')]); return $DBServer; } } // Limit amount of pending servers if ($DBServer->isOpenstack()) { $config = \Scalr::getContainer()->config; if ($config->defined("scalr.{$DBServer->platform}.pending_servers_limit")) { $pendingServersLimit = $config->get("scalr.{$DBServer->platform}.pending_servers_limit"); $pendingServers = $db->GetOne("SELECT COUNT(*) FROM servers WHERE platform=? AND status=? AND server_id != ?", array($DBServer->platform, SERVER_STATUS::PENDING, $DBServer->serverId)); if ($pendingServers >= $pendingServersLimit) { Logger::getLogger("SERVER_LAUNCH")->warn("{$pendingServers} servers in PENDING state on {$DBServer->platform}. Limit is: {$pendingServersLimit}. Waiting."); $DBServer->status = SERVER_STATUS::PENDING_LAUNCH; $DBServer->Save(); $DBServer->SetProperties([SERVER_PROPERTIES::LAUNCH_ATTEMPT => $DBServer->GetProperty(SERVER_PROPERTIES::LAUNCH_ATTEMPT) + 1, SERVER_PROPERTIES::LAUNCH_LAST_TRY => (new DateTime())->format('Y-m-d H:i:s')]); return $DBServer; } else { Logger::getLogger("SERVER_LAUNCH")->warn("{$pendingServers} servers in PENDING state on {$DBServer->platform}. Limit is: {$pendingServersLimit}. Launching server."); } } } try { $account = Scalr_Account::init()->loadById($DBServer->clientId); $account->validateLimit(Scalr_Limits::ACCOUNT_SERVERS, 1); PlatformFactory::NewPlatform($DBServer->platform)->LaunchServer($DBServer); $DBServer->status = SERVER_STATUS::PENDING; $DBServer->Save(); try { if ($reason) { list($reasonMsg, $reasonId) = is_array($reason) ? call_user_func_array($fnGetReason, $reason) : $fnGetReason($reason); } else { $reasonMsg = $DBServer->GetProperty(SERVER_PROPERTIES::LAUNCH_REASON); $reasonId = $DBServer->GetProperty(SERVER_PROPERTIES::LAUNCH_REASON_ID); } $DBServer->getServerHistory()->markAsLaunched($reasonMsg, $reasonId); $DBServer->updateTimelog('ts_launched'); if ($DBServer->imageId) { //Update Image last used date $image = Image::findOne([['id' => $DBServer->imageId], ['envId' => $DBServer->envId], ['platform' => $DBServer->platform], ['cloudLocation' => $DBServer->cloudLocation]]); if (!$image) { $image = Image::findOne([['id' => $DBServer->imageId], ['envId' => NULL], ['platform' => $DBServer->platform], ['cloudLocation' => $DBServer->cloudLocation]]); } if ($image) { $image->dtLastUsed = new DateTime(); $image->save(); } //Update Role last used date if ($DBServer->farmRoleId) { $dbRole = $DBServer->GetFarmRoleObject()->GetRoleObject(); $dbRole->dtLastUsed = date("Y-m-d H:i:s"); $dbRole->save(); } } } catch (Exception $e) { Logger::getLogger('SERVER_HISTORY')->error(sprintf("Cannot update servers history: {$e->getMessage()}")); } } catch (Exception $e) { Logger::getLogger(LOG_CATEGORY::FARM)->error(new FarmLogMessage($DBServer->farmId, sprintf("Cannot launch server on '%s' platform: %s", $DBServer->platform, $e->getMessage()), $DBServer->serverId)); $existingLaunchError = $DBServer->GetProperty(SERVER_PROPERTIES::LAUNCH_ERROR); $DBServer->status = SERVER_STATUS::PENDING_LAUNCH; $DBServer->SetProperties([SERVER_PROPERTIES::LAUNCH_ERROR => $e->getMessage(), SERVER_PROPERTIES::LAUNCH_ATTEMPT => $DBServer->GetProperty(SERVER_PROPERTIES::LAUNCH_ATTEMPT) + 1, SERVER_PROPERTIES::LAUNCH_LAST_TRY => (new DateTime())->format('Y-m-d H:i:s')]); $DBServer->Save(); if ($DBServer->farmId && !$existingLaunchError) { Scalr::FireEvent($DBServer->farmId, new InstanceLaunchFailedEvent($DBServer, $e->getMessage())); } } if ($DBServer->status == SERVER_STATUS::PENDING) { Scalr::FireEvent($DBServer->farmId, new BeforeInstanceLaunchEvent($DBServer)); $DBServer->SetProperty(SERVER_PROPERTIES::LAUNCH_ERROR, ""); } return $DBServer; }
public function SetParameters(array $p_params) { if (count($p_params) > 0) { $current_role_options = $this->DB->GetAll("SELECT * FROM farm_role_options WHERE farm_roleid=?", array($this->ID)); $role_opts = array(); foreach ($current_role_options as $cro) { $role_opts[$cro['hash']] = md5($cro['value']); } $params = array(); foreach ($p_params as $name => $value) { if (preg_match("/^(.*?)\\[(.*?)\\]\$/", $name, $matches)) { $params[$matches[1]] = array(); if ($matches[2] != '' && $value == 1) { $params[$matches[1]][] = $matches[2]; } continue; } else { $params[$name] = $value; } } $saved_opts = array(); foreach ($params as $name => $value) { if ($name) { $val = is_array($value) ? implode(',', $value) : $value; $hash = preg_replace("/[^A-Za-z0-9]+/", "_", strtolower($name)); if (!$role_opts[$hash]) { $this->DB->Execute("INSERT INTO farm_role_options SET\r\n\t\t\t\t\t\t\t\tfarmid\t\t= ?,\r\n\t\t\t\t\t\t\t\tfarm_roleid\t= ?,\r\n\t\t\t\t\t\t\t\tname\t\t= ?,\r\n\t\t\t\t\t\t\t\tvalue\t\t= ?,\r\n\t\t\t\t\t\t\t\thash\t \t= ? \r\n\t\t\t\t\t\t\t\tON DUPLICATE KEY UPDATE name = ?\r\n\t\t\t\t\t\t\t", array($this->FarmID, $this->ID, $name, $val, $hash, $name)); $fire_event = true; } else { if (md5($val) != $role_opts[$hash]) { $this->DB->Execute("UPDATE farm_role_options SET value = ? WHERE\r\n\t\t\t\t\t\t\t\t\tfarm_roleid\t= ? AND hash = ?\t\r\n\t\t\t\t\t\t\t\t", array($val, $this->ID, $hash)); $fire_event = true; } } // Submit event only for existing farm. // If we create a new farm, no need to fire this event. if ($fire_event) { Scalr::FireEvent($this->FarmID, new RoleOptionChangedEvent($this, $hash)); $fire_event = false; } $saved_opts[] = $hash; } } foreach ($role_opts as $k => $v) { if (!in_array($k, array_values($saved_opts))) { $this->DB->Execute("DELETE FROM farm_role_options WHERE farm_roleid = ? AND hash = ?", array($this->ID, $k)); } } } }
public static function farmUpdateRoleSettings(DBFarmRole $dbFarmRole, $oldSettings, $newSettings) { $db = \Scalr::getDb(); $dbFarm = $dbFarmRole->GetFarmObject(); if ($newSettings[Entity\FarmRoleSetting::CLOUDSTACK_NETWORK_ID] == 'SCALR_MANUAL') { return true; } $dbFarmRole->SetSetting(Entity\FarmRoleSetting::CLOUDSTACK_STATIC_NAT_MAP, null, Entity\FarmRoleSetting::TYPE_LCL); $cs = $dbFarm->GetEnvironmentObject()->cloudstack($dbFarmRole->Platform); // Disassociate IP addresses if checkbox was unchecked if (!$newSettings[Entity\FarmRoleSetting::CLOUDSTACK_USE_STATIC_NAT] && $oldSettings[Entity\FarmRoleSetting::CLOUDSTACK_USE_STATIC_NAT]) { $eips = $db->Execute("\n SELECT * FROM elastic_ips WHERE farm_roleid = ?\n ", array($dbFarmRole->ID)); while ($eip = $eips->FetchRow()) { try { $cs->disassociateIpAddress($eip['allocation_id']); } catch (Exception $e) { } } $db->Execute("DELETE FROM elastic_ips WHERE farm_roleid = ?", array($dbFarmRole->ID)); } //TODO: Handle situation when tab was not opened, but max instances setting was changed. if ($newSettings[Entity\FarmRoleSetting::CLOUDSTACK_STATIC_NAT_MAP] && $newSettings[Entity\FarmRoleSetting::CLOUDSTACK_USE_STATIC_NAT]) { $map = explode(";", $newSettings[Entity\FarmRoleSetting::CLOUDSTACK_STATIC_NAT_MAP]); foreach ($map as $ipconfig) { list($serverIndex, $ipAddress) = explode("=", $ipconfig); if (!$serverIndex) { continue; } $dbServer = false; try { $dbServer = \DBServer::LoadByFarmRoleIDAndIndex($dbFarmRole->ID, $serverIndex); if ($dbServer->remoteIp == $ipAddress) { continue; } // Remove old association $db->Execute("\n DELETE FROM elastic_ips WHERE farm_roleid = ? AND instance_index=?\n ", array($dbFarmRole->ID, $serverIndex)); } catch (Exception $e) { } // Allocate new IP if needed if ($ipAddress == "" || $ipAddress == '0.0.0.0') { if ($dbServer) { $ipAddress = self::setStaticNatForServer($dbServer); } else { continue; } } else { //Remove old IP association $db->Execute("\n DELETE FROM elastic_ips WHERE ipaddress=?\n ", array($ipAddress)); $requestObject = new ListIpAddressesData(); $requestObject->ipaddress = $ipAddress; $info = $cs->listPublicIpAddresses($requestObject); $info = count($info > 0) ? $info[0] : null; // Associate IP with server in our db $db->Execute("INSERT INTO elastic_ips SET\n env_id=?,\n farmid=?,\n farm_roleid=?,\n ipaddress=?,\n state='0',\n instance_id='',\n clientid=?,\n instance_index=?,\n allocation_id=?\n ", array($dbFarm->EnvID, $dbFarmRole->FarmID, $dbFarmRole->ID, $ipAddress, $dbFarm->ClientID, $serverIndex, $info->id)); } $ipInfo = $db->GetRow("SELECT allocation_id FROM elastic_ips WHERE ipaddress = ? LIMIT 1", array($ipAddress)); // Associate IP on AWS with running server if ($dbServer) { try { $db->Execute("UPDATE elastic_ips SET state='1', server_id = ? WHERE ipaddress = ?", array($dbServer->serverId, $ipAddress)); if ($dbServer->remoteIp != $ipAddress) { if ($dbServer && $dbServer->status == \SERVER_STATUS::RUNNING) { $fireEvent = self::associateIpAddress($dbServer, $ipAddress, $ipInfo['allocation_id']); } } if ($fireEvent) { $event = new \IPAddressChangedEvent($dbServer, $ipAddress, $dbServer->localIp); \Scalr::FireEvent($dbServer->farmId, $event); } } catch (Exception $e) { } } } } }
/** * Release IP address when instance terminated * * @param \HostDownEvent $event */ public function OnHostDown(\HostDownEvent $event) { if (!in_array($event->DBServer->platform, array(\SERVER_PLATFORMS::CLOUDSTACK, \SERVER_PLATFORMS::IDCF))) { return; } if ($event->DBServer->IsRebooting()) { return; } try { $DBFarm = \DBFarm::LoadByID($this->FarmID); //disable static nat if ($event->DBServer->remoteIp) { $cs = $DBFarm->GetEnvironmentObject()->cloudstack($event->DBServer->platform); $requestObject = new ListIpAddressesData(); $requestObject->ipaddress = $event->DBServer->remoteIp; $ipInfo = $cs->listPublicIpAddresses($requestObject); $info = !empty($ipInfo[0]) ? $ipInfo[0] : null; if (!empty($info->isstaticnat)) { if ($info->virtualmachineid == $event->DBServer->GetCloudServerID()) { $this->Logger->warn(new \FarmLogMessage($this->FarmID, sprintf(_("Calling disableStaticNat for IP: %s"), $event->DBServer->remoteIp))); $cs->firewall->disableStaticNat($info->id); } } } if ($event->replacementDBServer) { $ip = $this->DB->GetRow("SELECT * FROM elastic_ips WHERE server_id=? LIMIT 1", array($event->DBServer->serverId)); if ($ip) { $cs = $DBFarm->GetEnvironmentObject()->cloudstack($event->replacementDBServer->platform); try { $cs->firewall->disableStaticNat($ip['allocation_id']); } catch (\Exception $e) { } try { $cs->firewall->enableStaticNat(array('ipaddressid' => $ip['allocation_id'], 'virtualmachineid' => $event->replacementDBServer->GetCloudServerID())); $this->DB->Execute("UPDATE elastic_ips SET state='1', server_id=? WHERE ipaddress=?", array($event->replacementDBServer->serverId, $ip['ipaddress'])); \Scalr::FireEvent($this->FarmID, new \IPAddressChangedEvent($event->replacementDBServer, $ip['ipaddress'], $event->replacementDBServer->localIp)); } catch (\Exception $e) { if (!stristr($e->getMessage(), "does not belong to you")) { throw new \Exception($e->getMessage()); } } } } else { $this->DB->Execute("UPDATE elastic_ips SET state='0', server_id='' WHERE server_id=?", array($event->DBServer->serverId)); } } catch (\Exception $e) { \Logger::getLogger("Cloudstack::OnHostDown")->fatal($e->getMessage()); } }
/** * {@inheritdoc} * @see Scalr_System_Cronjob_MultiProcess_DefaultWorker::handleWork() */ function handleWork($farmId) { try { $dbFarm = DBFarm::LoadByID($farmId); if ($dbFarm->Status != FARM_STATUS::RUNNING) { return; } } catch (Exception $e) { return; } foreach ($dbFarm->GetFarmRoles() as $dbFarmRole) { $instancesHealth = array(); if ($dbFarmRole->Platform == SERVER_PLATFORMS::EC2) { $env = Scalr_Environment::init()->loadById($dbFarm->EnvID); $aws = $env->aws($dbFarmRole); $statusList = $aws->ec2->instance->describeStatus(); foreach ($statusList as $sd) { /* @var $sd \Scalr\Service\Aws\Ec2\DataType\InstanceStatusData */ $instancesHealth[$sd->instanceId] = $sd; } unset($statusList); //Releases memory $env->getContainer()->release('aws'); unset($aws); } $servers = $this->db->Execute("\n SELECT server_id FROM servers\n WHERE farm_roleid = ? AND status = ?\n ", array($dbFarmRole->ID, SERVER_STATUS::RUNNING)); while ($server = $servers->FetchRow()) { $dbServer = DBServer::LoadByID($server['server_id']); // Do not support ami-scripts if (!$dbServer->IsSupported("0.5")) { continue; } // Do not support windows if ($dbServer->IsSupported("0.8") && !$dbServer->IsSupported("0.9")) { continue; } if ($dbServer->GetProperty(SERVER_PROPERTIES::REBOOTING)) { continue; } $serverAlerts = new Alerts($dbServer); //Check AWS healthchecks if ($dbServer->platform == SERVER_PLATFORMS::EC2) { try { /* @var $statusInfo \Scalr\Service\Aws\Ec2\DataType\InstanceStatusData */ $statusInfo = isset($instancesHealth[$dbServer->GetProperty(EC2_SERVER_PROPERTIES::INSTANCE_ID)]) ? $instancesHealth[$dbServer->GetProperty(EC2_SERVER_PROPERTIES::INSTANCE_ID)] : null; if ($statusInfo) { $check = Alerts::METRIC_AWS_SYSTEM_STATUS; $hasActiveAlert = $serverAlerts->hasActiveAlert($check); if ($statusInfo->systemStatus->status == 'ok' && $hasActiveAlert) { Scalr::FireEvent($dbServer->farmId, new CheckRecoveredEvent($dbServer, $check)); } elseif ($statusInfo->systemStatus->status != 'ok' && $statusInfo->systemStatus->status != 'initializing' && !$hasActiveAlert) { $txtDetails = ""; $details = $statusInfo->systemStatus->details; if ($details) { foreach ($details as $d) { /* @var $d \Scalr\Service\Aws\Ec2\DataType\InstanceStatusDetailsSetData */ $txtDetails .= " {$d->name} is {$d->status},"; } $txtDetails = trim($txtDetails, " ,"); unset($details); } Scalr::FireEvent($dbServer->farmId, new CheckFailedEvent($dbServer, $check, "{$statusInfo->systemStatus->status}: {$txtDetails}")); } $check = Alerts::METRIC_AWS_INSTANCE_STATUS; $hasActiveAlert = $serverAlerts->hasActiveAlert($check); if ($statusInfo->instanceStatus->status == 'ok' && $hasActiveAlert) { Scalr::FireEvent($dbServer->farmId, new CheckRecoveredEvent($dbServer, $check)); } else { if ($statusInfo->instanceStatus->status != 'ok' && $statusInfo->instanceStatus->status != 'initializing' && !$hasActiveAlert) { $txtDetails = ""; $details = $statusInfo->instanceStatus->details; if ($details) { foreach ($details as $d) { /* @var $d \Scalr\Service\Aws\Ec2\DataType\InstanceStatusDetailsSetData */ $txtDetails .= " {$d->name} is {$d->status},"; } $txtDetails = trim($txtDetails, " ,"); unset($details); } Scalr::FireEvent($dbServer->farmId, new CheckFailedEvent($dbServer, $check, "{$statusInfo->instanceStatus->status}: {$txtDetails}")); } } unset($statusInfo); } } catch (Exception $e) { } } //Not supported by VPC yet. if ($dbFarm->GetSetting(DBFarm::SETTING_EC2_VPC_ID)) { continue; } $ip = $dbServer->getSzrHost(); //Check scalr-upd-client status $check = Alerts::METRIC_SCALARIZR_UPD_CLIENT_CONNECTIVITY; $port = $dbServer->getPort(DBServer::PORT_UPDC); $result = $this->checkPort($ip, $port); $hasActiveAlert = $serverAlerts->hasActiveAlert($check); if (!$result['status'] && !$hasActiveAlert) { Scalr::FireEvent($dbServer->farmId, new CheckFailedEvent($dbServer, $check, $result['error'])); } elseif ($result['status'] && $hasActiveAlert) { Scalr::FireEvent($dbServer->farmId, new CheckRecoveredEvent($dbServer, $check)); } elseif ($hasActiveAlert) { $serverAlerts->updateLastCheckTime($check); } //Check scalarizr connectivity status $check = Alerts::METRIC_SCALARIZR_CONNECTIVITY; $port = $dbServer->getPort(DBServer::PORT_CTRL); $result = $this->checkPort($ip, $port); $hasActiveAlert = $serverAlerts->hasActiveAlert($check); if (!$result['status'] && !$hasActiveAlert) { Scalr::FireEvent($dbServer->farmId, new CheckFailedEvent($dbServer, $check, $result['error'])); } elseif ($result['status'] && $hasActiveAlert) { Scalr::FireEvent($dbServer->farmId, new CheckRecoveredEvent($dbServer, $check)); } elseif ($hasActiveAlert) { $serverAlerts->updateLastCheckTime($check); } } } exit; }
/** * {@inheritdoc} * @see \Scalr\System\Zmq\Cron\TaskInterface::worker() */ public function worker($request) { $dtNow = new DateTime('now'); try { $dbServer = DBServer::LoadByID($request->serverId); } catch (ServerNotFoundException $e) { $this->log('INFO', "Server:%s does not exist:%s", $request->serverId, $e->getMessage()); return false; } if (!in_array($dbServer->status, [SERVER_STATUS::PENDING_TERMINATE, SERVER_STATUS::PENDING_SUSPEND, SERVER_STATUS::TERMINATED, SERVER_STATUS::SUSPENDED])) { return false; } // Check and skip locked instances if ($dbServer->status == SERVER_STATUS::PENDING_TERMINATE && $dbServer->GetProperty(EC2_SERVER_PROPERTIES::IS_LOCKED) == 1) { if (($checkDateTime = $dbServer->GetProperty(EC2_SERVER_PROPERTIES::IS_LOCKED_LAST_CHECK_TIME)) <= time()) { if (!$dbServer->GetRealStatus(true)->isTerminated()) { $isLocked = $dbServer->GetEnvironmentObject()->aws($dbServer->GetCloudLocation())->ec2->instance->describeAttribute($dbServer->GetCloudServerID(), InstanceAttributeType::disableApiTermination()); if ($isLocked) { \Scalr::getContainer()->logger(LOG_CATEGORY::FARM)->warn(new FarmLogMessage($dbServer->GetFarmObject()->ID, sprintf("Server '%s' has disableAPITermination flag and can't be terminated (Platform: %s) (ServerTerminate).", $dbServer->serverId, $dbServer->platform), $dbServer->serverId)); $startTime = strtotime($dbServer->dateShutdownScheduled); // 1, 2, 3, 4, 5, 6, 9, 14, ... 60 $diff = round((($checkDateTime < $startTime ? $startTime : $checkDateTime) - $startTime) / 60 * 0.5) * 60; $diff = $diff == 0 ? 60 : ($diff > 3600 ? 3600 : $diff); $dbServer->SetProperty(EC2_SERVER_PROPERTIES::IS_LOCKED_LAST_CHECK_TIME, time() + $diff); return false; } else { $dbServer->SetProperty(EC2_SERVER_PROPERTIES::IS_LOCKED, $isLocked); } } } else { return false; } } //Warming up static DI cache \Scalr::getContainer()->warmup(); // Reconfigure observers \Scalr::ReconfigureObservers(); if ($dbServer->status == SERVER_STATUS::TERMINATED || $dbServer->dateShutdownScheduled <= $dtNow->format('Y-m-d H:i:s')) { try { $p = PlatformFactory::NewPlatform($dbServer->platform); $environment = $dbServer->GetEnvironmentObject(); if (!$environment->isPlatformEnabled($dbServer->platform)) { throw new Exception(sprintf("%s platform is not enabled in the '%s' (%d) environment.", $dbServer->platform, $environment->name, $environment->id)); } if ($dbServer->GetCloudServerID()) { $serverHistory = $dbServer->getServerHistory(); $isTermination = in_array($dbServer->status, [SERVER_STATUS::TERMINATED, SERVER_STATUS::PENDING_TERMINATE]); $isSuspension = in_array($dbServer->status, [SERVER_STATUS::SUSPENDED, SERVER_STATUS::PENDING_SUSPEND]); /* @var $terminationData TerminationData */ $terminationData = null; //NOTE: in any case, after call, be sure to set callback to null $this->setupClientCallback($p, function ($request, $response) use($dbServer, &$terminationData) { $terminationData = new TerminationData(); $terminationData->serverId = $dbServer->serverId; if ($request instanceof \http\Client\Request) { $terminationData->requestUrl = $request->getRequestUrl(); $terminationData->requestQuery = $request->getQuery(); $terminationData->request = $request->toString(); } if ($response instanceof \http\Client\Response) { $terminationData->response = $response->toString(); $terminationData->responseCode = $response->getResponseCode(); $terminationData->responseStatus = $response->getResponseStatus(); } }, $dbServer); try { $status = $dbServer->GetRealStatus(); } catch (Exception $e) { //eliminate callback $this->setupClientCallback($p, null, $dbServer); throw $e; } //eliminate callback $this->setupClientCallback($p, null, $dbServer); if ($dbServer->isCloudstack()) { //Workaround for when expunge flag not working and servers stuck in Destroyed state. $isTerminated = $status->isTerminated() && $status->getName() != 'Destroyed'; } else { $isTerminated = $status->isTerminated(); } if ($isTermination && !$isTerminated || $isSuspension && !$dbServer->GetRealStatus()->isSuspended()) { try { if ($dbServer->farmId != 0) { try { if ($dbServer->GetFarmRoleObject()->GetRoleObject()->hasBehavior(ROLE_BEHAVIORS::RABBITMQ)) { $serversCount = count($dbServer->GetFarmRoleObject()->GetServersByFilter([], ['status' => [SERVER_STATUS::TERMINATED, SERVER_STATUS::SUSPENDED]])); if ($dbServer->index == 1 && $serversCount > 1) { \Scalr::getContainer()->logger(LOG_CATEGORY::FARM)->warn(new FarmLogMessage($dbServer->GetFarmObject()->ID, sprintf("RabbitMQ role. Main DISK node should be terminated after all other nodes. Waiting... (Platform: %s) (ServerTerminate).", $dbServer->serverId, $dbServer->platform), $dbServer->serverId)); return false; } } } catch (Exception $e) { } \Scalr::getContainer()->logger(LOG_CATEGORY::FARM)->warn(new FarmLogMessage($dbServer->GetFarmObject()->ID, sprintf("Terminating server '%s' (Platform: %s) (ServerTerminate).", $dbServer->serverId, $dbServer->platform), $dbServer->serverId)); } } catch (Exception $e) { $this->getLogger()->warn("Server: %s caused exception: %s", $request->serverId, $e->getMessage()); } $terminationTime = $dbServer->GetProperty(SERVER_PROPERTIES::TERMINATION_REQUEST_UNIXTIME); if (!$terminationTime || time() - $terminationTime > 180) { if ($isTermination) { $p->TerminateServer($dbServer); } else { $p->SuspendServer($dbServer); } $dbServer->SetProperty(SERVER_PROPERTIES::TERMINATION_REQUEST_UNIXTIME, time()); if ($dbServer->farmId) { $wasHostDownFired = \Scalr::getDb()->GetOne("\n SELECT id FROM events WHERE event_server_id = ? AND type = ? AND is_suspend = '0'", array($request->serverId, 'HostDown')); if (!$wasHostDownFired) { $event = new HostDownEvent($dbServer); $event->isSuspended = !$isTermination; \Scalr::FireEvent($dbServer->farmId, $event); } } } } else { if ($dbServer->status == SERVER_STATUS::TERMINATED) { if (!$dbServer->dateShutdownScheduled || time() - strtotime($dbServer->dateShutdownScheduled) > 600) { $errorResolution = true; $serverHistory->setTerminated(); $dbServer->Remove(); if (isset($terminationData)) { $terminationData->save(); } } } else { if ($dbServer->status == SERVER_STATUS::PENDING_TERMINATE) { $dbServer->updateStatus(SERVER_STATUS::TERMINATED); $errorResolution = true; } else { if ($dbServer->status == SERVER_STATUS::PENDING_SUSPEND) { $dbServer->update(['status' => SERVER_STATUS::SUSPENDED, 'remoteIp' => '', 'localIp' => '']); $errorResolution = true; } } } if (!empty($errorResolution) && $request->attempts > 0 && ($ste = ServerTerminationError::findPk($request->serverId))) { //Automatic error resolution $ste->delete(); } } } else { //If there is no cloudserverID we don't need to add this server into server history. //$serverHistory->setTerminated(); $dbServer->Remove(); } } catch (InstanceNotFound $e) { if ($serverHistory) { $serverHistory->setTerminated(); } $dbServer->Remove(); if (isset($terminationData)) { $terminationData->save(); } } catch (Exception $e) { if ($request->serverId && stripos($e->getMessage(), "modify its 'disableApiTermination' instance attribute and try again") !== false && $dbServer && $dbServer->platform == \SERVER_PLATFORMS::EC2) { // server has disableApiTermination flag on cloud, update server properties $dbServer->SetProperty(EC2_SERVER_PROPERTIES::IS_LOCKED, 1); } else { if ($request->serverId && ($e instanceof InvalidCloudCredentialsException || CloudPlatformSuspensionInfo::isSuspensionException($e) || stripos($e->getMessage(), "tenant is disabled") !== false || stripos($e->getMessage(), "was not able to validate the provided access credentials") !== false || stripos($e->getMessage(), "platform is not enabled") !== false || stripos($e->getMessage(), "neither api key nor password was provided for the openstack config") !== false || stripos($e->getMessage(), "refreshing the OAuth2 token") !== false || strpos($e->getMessage(), "Cannot obtain endpoint url. Unavailable service") !== false)) { //Postpones unsuccessful task for 30 minutes. $ste = new ServerTerminationError($request->serverId, isset($request->attempts) ? $request->attempts + 1 : 1, $e->getMessage()); $minutes = rand(30, 40); $ste->retryAfter = new \DateTime('+' . $minutes . ' minutes'); if ($ste->attempts > self::MAX_ATTEMPTS && in_array($dbServer->status, [SERVER_STATUS::PENDING_TERMINATE, SERVER_STATUS::TERMINATED])) { //We are going to remove those with Pending terminate status from Scalr after 1 month of unsuccessful attempts $dbServer->Remove(); if (isset($terminationData)) { $terminationData->save(); } } $ste->save(); } else { $this->log('ERROR', "Server:%s, failed - Exeption:%s %s", $request->serverId, get_class($e), $e->getMessage()); throw $e; } } } } return $request; }
public function xRemoveReplicaSetAction() { $dbFarmRole = $this->getFarmRole(); if ($dbFarmRole->GetSetting(Scalr_Role_Behavior_MongoDB::ROLE_CLUSTER_STATUS) != Scalr_Role_Behavior_MongoDB::STATUS_ACTIVE) { throw new Exception("You cannot remove replica set from non-active cluster"); } $replicasCount = $dbFarmRole->GetSetting(Scalr_Role_Behavior_MongoDB::ROLE_REPLICAS_COUNT); if ($replicasCount == 1) { throw new Exception("You already have minimum amount of replicas. First replica set cannot be removed."); } $rReplica = $replicasCount - 1; $dbFarmRole->SetSetting(Scalr_Role_Behavior_MongoDB::ROLE_REPLICAS_COUNT, $rReplica); // Terminate instances foreach ($dbFarmRole->GetServersByFilter(array('status' => array(SERVER_STATUS::RUNNING, SERVER_STATUS::INIT, SERVER_STATUS::PENDING, SERVER_STATUS::PENDING_LAUNCH))) as $server) { if ($server->GetProperty(Scalr_Role_Behavior_MongoDB::SERVER_REPLICA_SET_INDEX) == $rReplica) { Scalr::FireEvent($server->farmId, new BeforeHostTerminateEvent($server, false)); } } Scalr_Role_Behavior::loadByName(ROLE_BEHAVIORS::MONGODB)->log($dbFarmRole, sprintf("Removing replica set #s from cluster", $rReplica)); $this->response->success('Replica removal has been initiated. It may take a few minutes before it will be removed.'); }
function handleWork($serverId) { try { $dbserver = DBServer::LoadByID($serverId); if ($dbserver->farmId) { if ($dbserver->GetFarmObject()->Status == FARM_STATUS::TERMINATED) { throw new ServerNotFoundException(""); } } } catch (Exception $e) { $this->db->Execute("DELETE FROM messages WHERE server_id=? AND `type`='in'", array($serverId)); return; } $rs = $this->db->Execute("SELECT * FROM messages \n \t\tWHERE server_id = ? AND type = ? AND status = ? \n \t\tORDER BY id ASC", array($serverId, "in", MESSAGE_STATUS::PENDING)); while ($row = $rs->FetchRow()) { try { $message = $this->serializer->unserialize($row["message"]); $event = null; // Update scalarizr package version if ($message->meta[Scalr_Messaging_MsgMeta::SZR_VERSION]) { $dbserver->SetProperty(SERVER_PROPERTIES::SZR_VESION, $message->meta[Scalr_Messaging_MsgMeta::SZR_VERSION]); } if ($message->meta[Scalr_Messaging_MsgMeta::SZR_UPD_CLIENT_VERSION]) { $dbserver->SetProperty(SERVER_PROPERTIES::SZR_UPD_CLIENT_VERSION, $message->meta[Scalr_Messaging_MsgMeta::SZR_UPD_CLIENT_VERSION]); } try { if ($message instanceof Scalr_Messaging_Msg_OperationResult) { $this->db->Execute("UPDATE server_operations SET `status` = ? WHERE id = ?", array($message->status, $message->id)); if ($message->status == 'error') { if ($message->name == 'Initialization') { $dbserver->SetProperty(SERVER_PROPERTIES::SZR_IS_INIT_FAILED, 1); } if ($message->error) { $msg = $message->error->message; $trace = $message->error->trace; $handler = $message->error->handler; } $this->db->Execute("INSERT INTO server_operation_progress SET \n\t\t\t\t\t\t\t\t\t`operation_id` = ?,\n\t\t\t\t\t\t\t\t\t`timestamp` = ?,\n\t\t\t\t\t\t\t\t\t`phase` = ?,\n\t\t\t\t\t\t\t\t\t`step` = ?,\n\t\t\t\t\t\t\t\t\t`status` = ?,\n\t\t\t\t\t\t\t\t\t`message`= ?,\n\t\t\t\t\t\t\t\t\t`trace` = ?,\n\t\t\t\t\t\t\t\t\t`handler` = ?,\n\t\t\t\t\t\t\t\t\t`progress` = ?,\n\t\t\t\t\t\t\t\t\t`stepno` = ? \n\t\t\t\t\t\t\t\t\tON DUPLICATE KEY UPDATE status = ?, progress = ?, trace = ?, handler = ?, message = ?\n\t\t\t\t\t\t\t\t", array($message->id, $message->getTimestamp(), $message->phase, $message->step, $message->status, $msg, $trace, $handler, $message->progress, $message->stepno, $message->status, $message->progress, $trace, $handler, $msg)); } } elseif ($message instanceof Scalr_Messaging_Msg_Win_HostDown) { $status = PlatformFactory::NewPlatform($dbserver->platform)->GetServerRealStatus($dbserver); if ($status->isRunning()) { $event = new RebootBeginEvent($dbserver); } else { $event = new HostDownEvent($dbserver); } } elseif ($message instanceof Scalr_Messaging_Msg_Win_PrepareBundleResult) { try { $bundleTask = BundleTask::LoadById($message->bundleTaskId); } catch (Exception $e) { } if ($bundleTask) { if ($message->status == 'ok') { $metaData = array('szr_version' => $message->meta[Scalr_Messaging_MsgMeta::SZR_VERSION], 'os' => $message->os, 'software' => $message->software); $bundleTask->setMetaData($metaData); $bundleTask->Save(); PlatformFactory::NewPlatform($bundleTask->platform)->CreateServerSnapshot($bundleTask); } else { $bundleTask->SnapshotCreationFailed("PrepareBundle procedure failed: {$message->lastError}"); } } } elseif ($message instanceof Scalr_Messaging_Msg_DeployResult) { try { $deploymentTask = Scalr_Model::init(Scalr_Model::DM_DEPLOYMENT_TASK)->loadById($message->deployTaskId); } catch (Exception $e) { } if ($deploymentTask) { if ($message->status == 'error') { $deploymentTask->status = Scalr_Dm_DeploymentTask::STATUS_FAILED; $deploymentTask->lastError = $message->lastError; } else { $deploymentTask->status = Scalr_Dm_DeploymentTask::STATUS_DEPLOYED; $deploymentTask->dtDeployed = date("Y-m-d H:i:s"); } $deploymentTask->save(); } } elseif ($message instanceof Scalr_Messaging_Msg_Hello) { $event = $this->onHello($message, $dbserver); } elseif ($message instanceof Scalr_Messaging_Msg_MongoDb) { try { $dbFarmRole = $dbserver->GetFarmRoleObject(); } catch (Exception $e) { } if ($dbFarmRole instanceof DBFarmRole) { foreach (Scalr_Role_Behavior::getListForFarmRole($dbFarmRole) as $behavior) { $behavior->handleMessage($message, $dbserver); } } } elseif ($message instanceof Scalr_Messaging_Msg_DbMsr) { try { $dbFarmRole = $dbserver->GetFarmRoleObject(); } catch (Exception $e) { } if ($dbFarmRole instanceof DBFarmRole) { foreach (Scalr_Role_Behavior::getListForFarmRole($dbFarmRole) as $behavior) { $behavior->handleMessage($message, $dbserver); } } } elseif ($message instanceof Scalr_Messaging_Msg_HostInit) { $event = $this->onHostInit($message, $dbserver); } elseif ($message instanceof Scalr_Messaging_Msg_HostUp) { $event = $this->onHostUp($message, $dbserver); } elseif ($message instanceof Scalr_Messaging_Msg_HostDown) { $isMoving = false; if ($dbserver->platform == SERVER_PLATFORMS::RACKSPACE) { $p = PlatformFactory::NewPlatform($dbserver->platform); $status = $p->GetServerRealStatus($dbserver)->getName(); if (stristr($status, 'MOVE') || stristr($status, 'REBOOT')) { $this->logger->error(new FarmLogMessage($dbserver->farmId, "Rackspace server is in MOVING state. Ignoring HostDown message.")); $isMoving = true; } } if (!$isMoving) { $event = new HostDownEvent($dbserver); } } elseif ($message instanceof Scalr_Messaging_Msg_RebootStart) { $event = new RebootBeginEvent($dbserver); } elseif ($message instanceof Scalr_Messaging_Msg_RebootFinish) { $event = new RebootCompleteEvent($dbserver); } elseif ($message instanceof Scalr_Messaging_Msg_BeforeHostUp) { $event = new BeforeHostUpEvent($dbserver); } elseif ($message instanceof Scalr_Messaging_Msg_BlockDeviceAttached) { if ($dbserver->platform == SERVER_PLATFORMS::EC2) { $ec2Client = Scalr_Service_Cloud_Aws::newEc2($dbserver->GetProperty(EC2_SERVER_PROPERTIES::REGION), $dbserver->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::PRIVATE_KEY), $dbserver->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::CERTIFICATE)); $instanceId = $dbserver->GetProperty(EC2_SERVER_PROPERTIES::INSTANCE_ID); $volumes = $ec2Client->DescribeVolumes()->volumeSet->item; if (!is_array($volumes)) { $volumes = array($volumes); } foreach ($volumes as $volume) { if ($volume->status == AMAZON_EBS_STATE::IN_USE && $volume->attachmentSet->item->instanceId == $instanceId && $volume->attachmentSet->item->device == $message->deviceName) { $message->volumeId = $volume->volumeId; } } } $event = new EBSVolumeAttachedEvent($dbserver, $message->deviceName, $message->volumeId); } elseif ($message instanceof Scalr_Messaging_Msg_BlockDeviceMounted) { // Single volume $ebsinfo = $this->db->GetRow("SELECT * FROM ec2_ebs WHERE volume_id=?", array($message->volumeId)); if ($ebsinfo) { $this->db->Execute("UPDATE ec2_ebs SET mount_status=?, isfsexist='1' WHERE id=?", array(EC2_EBS_MOUNT_STATUS::MOUNTED, $ebsinfo['id'])); } $event = new EBSVolumeMountedEvent($dbserver, $message->mountpoint, $message->volumeId, $message->deviceName); } elseif ($message instanceof Scalr_Messaging_Msg_RebundleResult) { if ($message->status == Scalr_Messaging_Msg_RebundleResult::STATUS_OK) { $metaData = array('szr_version' => $message->meta[Scalr_Messaging_MsgMeta::SZR_VERSION], 'dist' => $message->dist, 'os' => $message->os, 'software' => $message->software); if ($dbserver->platform == SERVER_PLATFORMS::EC2) { if ($message->aws) { if ($message->aws->root - device - type == 'ebs') { $tags[] = ROLE_TAGS::EC2_EBS; } if ($message->aws->virtualization - type == 'hvm') { $tags[] = ROLE_TAGS::EC2_HVM; } } else { $ec2Client = Scalr_Service_Cloud_Aws::newEc2($dbserver->GetProperty(EC2_SERVER_PROPERTIES::REGION), $dbserver->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::PRIVATE_KEY), $dbserver->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::CERTIFICATE)); try { $DescribeImagesType = new DescribeImagesType(null, array(), null); $DescribeImagesType->imagesSet = new stdClass(); $DescribeImagesType->imagesSet->item = array(); $DescribeImagesType->imagesSet->item[] = array('imageId' => $dbserver->GetProperty(EC2_SERVER_PROPERTIES::AMIID)); $info = $ec2Client->DescribeImages($DescribeImagesType); if ($info->imagesSet->item->rootDeviceType == 'ebs') { $tags[] = ROLE_TAGS::EC2_EBS; } else { try { $bundleTask = BundleTask::LoadById($message->bundleTaskId); if ($bundleTask->bundleType == SERVER_SNAPSHOT_CREATION_TYPE::EC2_EBS) { $tags[] = ROLE_TAGS::EC2_EBS; } } catch (Exception $e) { } } if ($info->imagesSet->item->virtualizationType == 'hvm') { $tags[] = ROLE_TAGS::EC2_HVM; } } catch (Exception $e) { $metaData['tagsError'] = $e->getMessage(); } } } elseif ($dbserver->platform == SERVER_PLATFORMS::NIMBULA) { $metaData['init_root_user'] = $message->sshUser; $metaData['init_root_pass'] = $message->sshPassword; } $metaData['tags'] = $tags; $event = new RebundleCompleteEvent($dbserver, $message->snapshotId, $message->bundleTaskId, $metaData); } else { if ($message->status == Scalr_Messaging_Msg_RebundleResult::STATUS_FAILED) { $event = new RebundleFailedEvent($dbserver, $message->bundleTaskId, $message->lastError); } } } elseif ($message instanceof Scalr_Messaging_Msg_Mysql_CreateDataBundleResult) { if ($message->status == "ok") { $event = new MysqlBackupCompleteEvent($dbserver, MYSQL_BACKUP_TYPE::BUNDLE, array('snapshotConfig' => $message->snapshotConfig, 'logFile' => $message->logFile, 'logPos' => $message->logPos, 'dataBundleSize' => $message->dataBundleSize, 'snapshotId' => $message->snapshotId)); } else { $event = new MysqlBackupFailEvent($dbserver, MYSQL_BACKUP_TYPE::BUNDLE); $event->lastError = $message->lastError; } } elseif ($message instanceof Scalr_Messaging_Msg_Mysql_CreateBackupResult) { if ($message->status == "ok") { $event = new MysqlBackupCompleteEvent($dbserver, MYSQL_BACKUP_TYPE::DUMP); } else { $event = new MysqlBackupFailEvent($dbserver, MYSQL_BACKUP_TYPE::DUMP); $event->lastError = $message->lastError; } } elseif ($message instanceof Scalr_Messaging_Msg_Mysql_PromoteToMasterResult) { $event = $this->onMysql_PromoteToMasterResult($message, $dbserver); } elseif ($message instanceof Scalr_Messaging_Msg_Mysql_CreatePmaUserResult) { $farmRole = DBFarmRole::LoadByID($message->farmRoleId); if ($message->status == "ok") { $farmRole->SetSetting(DbFarmRole::SETTING_MYSQL_PMA_USER, $message->pmaUser); $farmRole->SetSetting(DbFarmRole::SETTING_MYSQL_PMA_PASS, $message->pmaPassword); } else { $farmRole->SetSetting(DBFarmRole::SETTING_MYSQL_PMA_REQUEST_TIME, ""); $farmRole->SetSetting(DBFarmRole::SETTING_MYSQL_PMA_REQUEST_ERROR, $message->lastError); } } elseif ($message instanceof Scalr_Messaging_Msg_RabbitMq_SetupControlPanelResult) { $farmRole = $dbserver->GetFarmRoleObject(); if ($message->status == "ok") { $farmRole->SetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_SERVER_ID, $dbserver->serverId); $farmRole->SetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_URL, $message->cpanelUrl); $farmRole->SetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_REQUEST_TIME, ""); } else { $farmRole->SetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_SERVER_ID, ""); $farmRole->SetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_REQUEST_TIME, ""); $farmRole->SetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_ERROR_MSG, $message->lastError); } } elseif ($message instanceof Scalr_Messaging_Msg_AmiScriptsMigrationResult) { try { //Open security group: if ($dbserver->platform == SERVER_PLATFORMS::EC2) { $info = PlatformFactory::NewPlatform($dbserver->platform)->GetServerExtendedInformation($dbserver); $sg = explode(", ", $info['Security groups']); foreach ($sg as $sgroup) { if ($sgroup != 'default') { $ipPermissionSet = new IpPermissionSetType(); $group_rules = array(array('rule' => 'tcp:8013:8013:0.0.0.0/0'), array('rule' => 'udp:8014:8014:0.0.0.0/0')); foreach ($group_rules as $rule) { $group_rule = explode(":", $rule["rule"]); $ipPermissionSet->AddItem($group_rule[0], $group_rule[1], $group_rule[2], null, array($group_rule[3])); } $ec2Client = Scalr_Service_Cloud_Aws::newEc2($dbserver->GetProperty(EC2_SERVER_PROPERTIES::REGION), $dbserver->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::PRIVATE_KEY), $dbserver->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::CERTIFICATE)); // Create security group $ec2Client->AuthorizeSecurityGroupIngress($dbserver->GetEnvironmentObject()->getPlatformConfigValue(Modules_Platforms_Ec2::ACCOUNT_ID), $sgroup, $ipPermissionSet); break; } } } } catch (Exception $e) { $this->logger->fatal($e->getMessage()); } $dbserver->SetProperty(SERVER_PROPERTIES::SZR_SNMP_PORT, 8014); $dbserver->SetProperty(SERVER_PROPERTIES::SZR_VESION, "0.7.217"); if ($message->mysql) { $event = $this->onHostUp($message, $dbserver, true); } } $handle_status = MESSAGE_STATUS::HANDLED; } catch (Exception $e) { $handle_status = MESSAGE_STATUS::FAILED; $this->logger->error(sprintf("Cannot handle message '%s' (message_id: %s) " . "from server '%s' (server_id: %s). %s", $message->getName(), $message->messageId, $dbserver->remoteIp ? $dbserver->remoteIp : '*no-ip*', $dbserver->serverId, $e->getMessage() . "({$e->getFile()}:{$e->getLine()})")); } $this->db->Execute("UPDATE messages SET status = ? WHERE messageid = ?", array($handle_status, $message->messageId)); if ($event) { Scalr::FireEvent($dbserver->farmId, $event); } } catch (Exception $e) { $this->logger->error($e->getMessage(), $e); } } }
public static function farmUpdateRoleSettings(DBFarmRole $DBFarmRole, $oldSettings, $newSettings) { $db = \Scalr::getDb(); $DBFarm = $DBFarmRole->GetFarmObject(); $DBFarmRole->SetSetting(DBFarmRole::SETTING_AWS_ELASIC_IPS_MAP, null, DBFarmRole::TYPE_LCL); $isVPC = $DBFarm->GetSetting(DBFarm::SETTING_EC2_VPC_ID); $aws = $DBFarm->GetEnvironmentObject()->aws($DBFarmRole->CloudLocation); // Disassociate IP addresses if checkbox was unchecked if (!$newSettings[DBFarmRole::SETTING_AWS_USE_ELASIC_IPS] && $oldSettings[DBFarmRole::SETTING_AWS_USE_ELASIC_IPS]) { $eips = $db->Execute("\n SELECT * FROM elastic_ips WHERE farm_roleid = ?\n ", array($DBFarmRole->ID)); while ($eip = $eips->FetchRow()) { try { $aws->ec2->address->disassociate($eip['ipaddress']); } catch (\Exception $e) { } } $db->Execute("\n DELETE FROM elastic_ips\n WHERE farm_roleid = ?\n ", array($DBFarmRole->ID)); } //TODO: Handle situation when tab was not opened, but max instances setting was changed. if ($newSettings[DBFarmRole::SETTING_AWS_ELASIC_IPS_MAP] && $newSettings[DBFarmRole::SETTING_AWS_USE_ELASIC_IPS]) { $map = explode(";", $newSettings[DBFarmRole::SETTING_AWS_ELASIC_IPS_MAP]); foreach ($map as $ipconfig) { list($serverIndex, $ipAddress) = explode("=", $ipconfig); if (!$serverIndex) { continue; } $allocationId = null; try { $dbServer = DBServer::LoadByFarmRoleIDAndIndex($DBFarmRole->ID, $serverIndex); } catch (\Exception $e) { } // Allocate new IP if needed if (!$ipAddress || $ipAddress == '0.0.0.0') { if ($dbServer) { $domain = $isVPC ? 'vpc' : null; $address = $aws->ec2->address->allocate($domain); $ipAddress = $address->publicIp; $allocationId = $address->allocationId; } else { continue; } } // Remove old association $db->Execute("\n DELETE FROM elastic_ips\n WHERE farm_roleid = ? AND instance_index=?\n ", array($DBFarmRole->ID, $serverIndex)); if ($ipAddress) { //Remove old IP association $db->Execute("\n DELETE FROM elastic_ips\n WHERE ipaddress=?\n ", array($ipAddress)); if (!$allocationId && $isVPC) { $allocationId = $aws->ec2->address->describe($ipAddress)->get(0)->allocationId; } // Associate IP with server in our db $db->Execute("\n INSERT INTO elastic_ips\n SET env_id=?,\n farmid=?,\n farm_roleid=?,\n ipaddress=?,\n state='0',\n instance_id='',\n clientid=?,\n instance_index=?,\n allocation_id=?\n ", array($DBFarm->EnvID, $DBFarmRole->FarmID, $DBFarmRole->ID, $ipAddress, $DBFarm->ClientID, $serverIndex, $allocationId)); // Associate IP on AWS with running server try { $dbServer = DBServer::LoadByFarmRoleIDAndIndex($DBFarmRole->ID, $serverIndex); $db->Execute("\n UPDATE elastic_ips\n SET state='1',\n server_id = ?\n WHERE ipaddress = ?\n ", array($dbServer->serverId, $ipAddress)); $update = false; if ($dbServer->remoteIp != $ipAddress) { if ($dbServer && $dbServer->status == \SERVER_STATUS::RUNNING) { $fireEvent = self::associateIpAddress($dbServer, $ipAddress, $isVPC ? $allocationId : null); } } if ($fireEvent) { $event = new \IPAddressChangedEvent($dbServer, $ipAddress, $dbServer->localIp); \Scalr::FireEvent($dbServer->farmId, $event); } } catch (\Exception $e) { } } else { \Logger::getLogger(\LOG_CATEGORY::FARM)->fatal(sprintf(_("Cannot allocate elastic ip address for instance %s on farm %s (2)"), $dbServer->serverId, $DBFarm->Name)); } } } }
public function xLaunchAction() { $this->request->restrictAccess(Acl::RESOURCE_FARMS, Acl::PERM_FARMS_LAUNCH); $this->request->defineParams(array('farmId' => array('type' => 'int'))); $dbFarm = DBFarm::LoadByID($this->getParam('farmId')); $this->user->getPermissions()->validate($dbFarm); $dbFarm->isLocked(); Scalr::FireEvent($dbFarm->ID, new FarmLaunchedEvent(true, $this->user->id)); $this->response->success('Farm successfully launched'); }
public function handleMessage(Scalr_Messaging_Msg $message, DBServer $dbServer) { parent::handleMessage($message, $dbServer); try { $dbFarmRole = $dbServer->GetFarmRoleObject(); $storageType = $dbFarmRole->GetSetting(Scalr_Db_Msr::DATA_STORAGE_ENGINE); $storageGeneration = $storageType == 'lvm' ? 2 : 1; } catch (Exception $e) { } switch (get_class($message)) { case "Scalr_Messaging_Msg_HostUp": if ($message->dbType && in_array($message->dbType, array(ROLE_BEHAVIORS::REDIS, ROLE_BEHAVIORS::POSTGRESQL, ROLE_BEHAVIORS::MYSQL2, ROLE_BEHAVIORS::PERCONA, ROLE_BEHAVIORS::MARIADB))) { $dbMsrInfo = Scalr_Db_Msr_Info::init($dbFarmRole, $dbServer, $message->dbType); $dbMsrInfo->setMsrSettings($message->{$message->dbType}); if ($message->{$message->dbType}->snapshotConfig) { $dbFarmRole->SetSetting(self::ROLE_NO_DATA_BUNDLE_FOR_SLAVES, 0, DBFarmRole::TYPE_LCL); } if ($message->{$message->dbType}->restore) { $this->db->Execute("INSERT INTO storage_restore_configs SET farm_roleid = ?, dtadded=NOW(), manifest = ?", array($dbFarmRole->ID, $message->{$message->dbType}->restore->cloudfsSource)); $dbFarmRole->SetSetting(self::ROLE_NO_DATA_BUNDLE_FOR_SLAVES, 0, DBFarmRole::TYPE_LCL); $dbFarmRole->SetSetting(Scalr_Db_Msr::DATA_BUNDLE_LAST_TS, time(), DBFarmRole::TYPE_LCL); $dbFarmRole->SetSetting(Scalr_Db_Msr::DATA_BUNDLE_IS_RUNNING, 0, DBFarmRole::TYPE_LCL); } if ($message->{$message->dbType}->masterPassword) { $dbFarmRole->SetSetting(self::ROLE_MASTER_PASSWORD, $message->{$message->dbType}->masterPassword, DBFarmRole::TYPE_LCL); } } break; case "Scalr_Messaging_Msg_DbMsr_PromoteToMasterResult": if ($message->{$message->dbType}->restore) { $this->db->Execute("INSERT INTO storage_restore_configs SET farm_roleid = ?, dtadded=NOW(), manifest = ?", array($dbFarmRole->ID, $message->{$message->dbType}->restore->cloudfsSource)); $dbFarmRole->SetSetting(self::ROLE_NO_DATA_BUNDLE_FOR_SLAVES, 0, DBFarmRole::TYPE_LCL); } if (Scalr_Db_Msr::onPromoteToMasterResult($message, $dbServer)) { if ($message->{$this->behavior}->snapshotConfig) { $dbFarmRole->SetSetting(self::ROLE_NO_DATA_BUNDLE_FOR_SLAVES, 0, DBFarmRole::TYPE_LCL); } Scalr::FireEvent($dbServer->farmId, new NewDbMsrMasterUpEvent($dbServer)); } break; case "Scalr_Messaging_Msg_DbMsr_CreateDataBundleResult": if ($message->status == "ok") { if (isset($message->{$message->dbType}->restore) && isset($message->{$message->dbType}->restore->backupType)) { $t = $message->{$message->dbType}->restore; if ($t->backupType == 'incremental') { $parentManifest = $this->db->GetOne("\n SELECT manifest FROM storage_restore_configs WHERE farm_roleid = ? ORDER BY id DESC LIMIT 1\n ", array($dbFarmRole->ID)); } $this->db->Execute("\n INSERT INTO storage_restore_configs SET farm_roleid = ?, dtadded=NOW(), manifest = ?, type = ?, parent_manifest = ?\n ", array($dbFarmRole->ID, $t->cloudfsSource, $t->backupType, $parentManifest)); unset($t); } $dbFarmRole->SetSetting(self::ROLE_NO_DATA_BUNDLE_FOR_SLAVES, 0, DBFarmRole::TYPE_LCL); Scalr_Db_Msr::onCreateDataBundleResult($message, $dbServer); } else { $dbFarmRole->SetSetting(Scalr_Db_Msr::DATA_BUNDLE_IS_RUNNING, 0, DBFarmRole::TYPE_LCL); // TODO: store last error } $this->updateBackupHistory($dbServer, 'bundle', $message->status, $message->lastError); break; case "Scalr_Messaging_Msg_DbMsr_CreateBackupResult": if ($message->status == "ok") { Scalr_Db_Msr::onCreateBackupResult($message, $dbServer); } else { $dbFarmRole->SetSetting(Scalr_Db_Msr::DATA_BACKUP_IS_RUNNING, 0, DBFarmRole::TYPE_LCL); } $this->updateBackupHistory($dbServer, 'backup', $message->status, $message->lastError); break; } }
/** * * @param ServerCreateInfo $ServerCreateInfo * @return DBServer */ public static function LaunchServer(ServerCreateInfo $ServerCreateInfo = null, DBServer $DBServer = null, $delayed = false) { $db = Core::GetDBInstance(); if (!$DBServer && $ServerCreateInfo) { $ServerCreateInfo->SetProperties(array(SERVER_PROPERTIES::SZR_KEY => Scalr::GenerateRandomKey(40), SERVER_PROPERTIES::SZR_KEY_TYPE => SZR_KEY_TYPE::ONE_TIME)); $DBServer = DBServer::Create($ServerCreateInfo, false, true); } elseif (!$DBServer && !$ServerCreateInfo) { // incorrect arguments Logger::getLogger(LOG_CATEGORY::FARM)->error(sprintf("Cannot create server")); return null; } if ($delayed) { $DBServer->status = SERVER_STATUS::PENDING_LAUNCH; $DBServer->Save(); return $DBServer; } try { $account = Scalr_Account::init()->loadById($DBServer->clientId); $account->validateLimit(Scalr_Limits::ACCOUNT_SERVERS, 1); PlatformFactory::NewPlatform($DBServer->platform)->LaunchServer($DBServer); $DBServer->status = SERVER_STATUS::PENDING; $DBServer->Save(); } catch (Exception $e) { Logger::getLogger(LOG_CATEGORY::FARM)->error(new FarmLogMessage($DBServer->farmId, sprintf("Cannot launch server on '%s' platform: %s", $DBServer->platform, $e->getMessage()))); $DBServer->status = SERVER_STATUS::PENDING_LAUNCH; $DBServer->SetProperty(SERVER_PROPERTIES::LAUNCH_ERROR, $e->getMessage()); $DBServer->Save(); } if ($DBServer->status == SERVER_STATUS::PENDING) { Scalr::FireEvent($DBServer->farmId, new BeforeInstanceLaunchEvent($DBServer)); $DBServer->SetProperty(SERVER_PROPERTIES::LAUNCH_ERROR, ""); $db->Execute("UPDATE servers_history SET\r\n\t\t\t\t\t`dtlaunched` = NOW(),\r\n\t\t\t\t\t`cloud_server_id` = ?,\r\n\t\t\t\t\t`type` = ?\r\n\t\t\t\t\tWHERE server_id = ?\r\n\t\t\t\t", array($DBServer->GetCloudServerID(), $DBServer->GetProperty(EC2_SERVER_PROPERTIES::INSTANCE_TYPE), $DBServer->serverId)); } return $DBServer; }