/** * @return Scalr_Messaging_XmlSerializer */ static function getInstance() { if (self::$instance === null) { self::$instance = new Scalr_Messaging_JsonSerializer(); } return self::$instance; }
/** * Query Environment object and return result; */ public function Query($operation, array $args) { $this->debugObject = new stdClass(); $this->SetRequest($args); // Get Method name by operation $method_name = str_replace(" ", "", ucwords(str_replace("-", " ", $operation))); // Check method if (method_exists($this, $method_name)) { // Call method try { $this->DBServer = $this->GetCallingInstance(); $result = call_user_func(array($this, $method_name)); if ($result instanceof DOMDocument) { header("Content-Type: text/xml"); return $result->saveXML(); } else { if (is_object($result)) { header("Content-Type: application/json"); $retval = new stdClass(); $retval->result = new stdClass(); $serializer = Scalr_Messaging_JsonSerializer::getInstance(); $serializer->walkSerialize($result, $retval->result, 'underScope'); return json_encode($retval->result); } else { throw new Exception(sprintf("%s:%s() returns invalid response. DOMDocument expected.", get_class($this), $method_name)); } } } catch (\Scalr\Exception\Http\HttpException $e) { throw $e; } catch (DOMException $e) { throw $e; } catch (Exception $e) { throw new Exception(sprintf(_("Cannot retrieve environment by operation '%s': %s"), $operation, $e->getMessage())); } } else { throw new BadRequestException(sprintf("Operation '%s' is not supported", $operation)); } }
/** * Send message to instance * @param Scalr_Messaging_Msg $message * @return Scalr_Messaging_Msg */ public function SendMessage(Scalr_Messaging_Msg $message, $isEventNotice = false, $delayed = false) { $startTime = microtime(true); if ($this->farmId && $message->getName() != 'BeforeHostTerminate') { if ($this->GetFarmObject()->Status == FARM_STATUS::TERMINATED) { $this->Db->Execute("UPDATE messages SET status = ? WHERE messageid = ?", array(MESSAGE_STATUS::FAILED, $message->messageId)); return; } } // We don't need to send any messages other then it's own to the server that is not in Running state if ($message->serverId != $this->serverId && !in_array($this->status, array(SERVER_STATUS::RUNNING, SERVER_STATUS::TEMPORARY, SERVER_STATUS::IMPORTING))) { return; } // Ignore OLD messages (ami-scripts) if (!$this->IsSupported("0.5")) { return; } // Put access data and reserialize message $pl = PlatformFactory::NewPlatform($this->platform); $pl->PutAccessData($this, $message); $logger = \Scalr::getContainer()->logger('DBServer'); $serializer = Scalr_Messaging_XmlSerializer::getInstance(); $cryptoTool = \Scalr::getContainer()->srzcrypto($this->GetKey(true)); if ($this->GetProperty(\SERVER_PROPERTIES::SZR_MESSAGE_FORMAT) == 'json') { $serializer = Scalr_Messaging_JsonSerializer::getInstance(); $rawMessage = $serializer->serialize($message); $messageType = 'json'; } else { $rawMessage = $serializer->serialize($message); $messageType = 'xml'; } //$rawJsonMessage = @json_encode($message); $time = microtime(true) - $startTime; // Add message to database $this->Db->Execute("INSERT INTO messages SET\n `messageid` = ?,\n `processing_time` = ?,\n `server_id` = ?,\n `event_server_id` = ?,\n `message` = ?,\n `type` = 'out',\n `message_name` = ?,\n `handle_attempts` = ?,\n `message_version` = ?,\n `dtlasthandleattempt` = NOW(),\n `dtadded` = NOW(),\n `message_format` = ?,\n `event_id` = ?\n ON DUPLICATE KEY UPDATE handle_attempts = handle_attempts+1, dtlasthandleattempt = NOW()\n ", array($message->messageId, $time, $this->serverId, $message->serverId, $rawMessage, $message->getName(), $delayed ? '0' : '1', 2, $messageType, isset($message->eventId) ? $message->eventId : '')); if ($delayed) { return $message; } $isVPC = false; if ($this->farmId) { if (DBFarm::LoadByID($this->farmId)->GetSetting(Entity\FarmSetting::EC2_VPC_ID)) { $isVPC = true; } } if (!$this->remoteIp && !$this->localIp && !$isVPC) { return; } $cryptoTool->setCryptoKey($this->GetKey(true)); $encMessage = $cryptoTool->encrypt($rawMessage); $timestamp = date("c", time()); $signature = $cryptoTool->sign($encMessage, null, $timestamp); try { $request = new Request(); $request->setRequestMethod('POST'); $ctrlPort = $this->getPort(self::PORT_CTRL); $requestHost = $this->getSzrHost() . ":{$ctrlPort}"; if ($isVPC) { $routerFarmRoleId = $this->GetFarmRoleObject()->GetSetting(Scalr_Role_Behavior_Router::ROLE_VPC_SCALR_ROUTER_ID); if ($routerFarmRoleId) { $routerRole = DBFarmRole::LoadByID($routerFarmRoleId); } else { $routerRole = $this->GetFarmObject()->GetFarmRoleByBehavior(ROLE_BEHAVIORS::VPC_ROUTER); } if ($routerRole) { // No public IP need to use proxy if (!$this->remoteIp) { $requestHost = $routerRole->GetSetting(Scalr_Role_Behavior_Router::ROLE_VPC_IP) . ":80"; $request->addHeaders(array("X-Receiver-Host" => $this->localIp, "X-Receiver-Port" => $ctrlPort)); // There is public IP, can use it } else { $requestHost = "{$this->remoteIp}:{$ctrlPort}"; } } } //Prepare request $request->setRequestUrl("http://{$requestHost}/control"); $request->setOptions(array('timeout' => \Scalr::config('scalr.system.instances_connection_timeout'), 'connecttimeout' => \Scalr::config('scalr.system.instances_connection_timeout'))); $request->addHeaders(array("Date" => $timestamp, "X-Signature" => $signature, 'X-Server-Id' => $this->serverId)); if ($messageType == 'json') { $request->addHeaders(array('Content-type' => 'application/json')); } $request->append($encMessage); // Send request $response = \Scalr::getContainer()->srzhttp->sendRequest($request); // Process response if ($response->getResponseCode() == 201) { $logger->info(sprintf("[FarmID: %s] Sending message '%s' via REST to server '%s' (server_id: %s) completed", $this->farmId, $message->getName(), $this->remoteIp, $this->serverId)); if (in_array($message->getName(), array('ExecScript'))) { $this->Db->Execute("DELETE FROM messages WHERE messageid = ?", array($message->messageId)); } else { if ($messageType != 'json') { $this->Db->Execute("UPDATE messages SET status = ?, message = '' WHERE messageid = ?", array(MESSAGE_STATUS::HANDLED, $message->messageId)); } else { $this->Db->Execute("UPDATE messages SET status = ? WHERE messageid = ?", array(MESSAGE_STATUS::HANDLED, $message->messageId)); } if (!empty($message->eventId)) { $this->Db->Execute("UPDATE events SET msg_sent = msg_sent + 1 WHERE event_id = ?", array($message->eventId)); } } } else { $logger->warn(sprintf("[FarmID: %s] Cannot deliver message '%s' (message_id: %s) via REST" . " to server '%s' (server_id: %s). Error: %s %s", $this->farmId, $message->getName(), $message->messageId, $this->remoteIp, $this->serverId, $response->getResponseCode(), $response->getResponseStatus())); } } catch (http\Exception $e) { if (isset($e->innerException)) { $msg = $e->innerException->getMessage(); } else { $msg = $e->getMessage(); } if ($this->farmId) { $logger->warn(new FarmLogMessage($this->farmId, sprintf("Cannot deliver message '%s' (message_id: %s) via REST to server '%s' (server_id: %s). Error: %s", $message->getName(), $message->messageId, $this->remoteIp, $this->serverId, $msg), $this->serverId)); } else { $logger->fatal(sprintf("Cannot deliver message '%s' (message_id: %s) via REST" . " to server '%s' (server_id: %s). Error: %s", $message->getName(), $message->messageId, $this->remoteIp, $this->serverId, $msg)); } return false; } return $message; }
/** * @param int $farmId * @param int $farmRoleId optional * @param string $serverId optional * @param int $scriptId optional * @param string $scriptPath optional * @param int $scriptIsSync * @param int $scriptTimeout * @param int $scriptVersion * @param array $scriptParams optional * @param int $shortcutId optional * @param int $editShortcut optional * @throws Exception */ public function xExecuteAction($farmId, $farmRoleId = 0, $serverId = '', $scriptId = 0, $scriptPath = '', $scriptIsSync, $scriptTimeout, $scriptVersion, array $scriptParams = [], $shortcutId = null, $editShortcut = null) { $this->request->restrictAccess(Acl::RESOURCE_SCRIPTS_ENVIRONMENT, Acl::PERM_SCRIPTS_ENVIRONMENT_EXECUTE); if ($serverId) { $dbServer = DBServer::LoadByID($serverId); $this->user->getPermissions()->validate($dbServer); $target = Script::TARGET_INSTANCE; $serverId = $dbServer->serverId; $farmRoleId = $dbServer->farmRoleId; $farmId = $dbServer->farmId; } else { if ($farmRoleId) { $dbFarmRole = DBFarmRole::LoadByID($farmRoleId); $this->user->getPermissions()->validate($dbFarmRole); $target = Script::TARGET_ROLE; $farmRoleId = $dbFarmRole->ID; $farmId = $dbFarmRole->FarmID; } else { if (!$farmId) { $target = Script::TARGET_ALL; } else { $dbFarm = DBFarm::LoadByID($farmId); $this->user->getPermissions()->validate($dbFarm); $target = Script::TARGET_FARM; $farmId = $dbFarm->ID; } } } if ($farmId) { $this->request->checkPermissions(Entity\Farm::findPk($farmId), Acl::PERM_FARMS_SERVERS); } if ($scriptId) { $script = Script::findPk($scriptId); /* @var $script Script */ if (!$script) { throw new Scalr_UI_Exception_NotFound(); } $script->checkPermission($this->user, $this->getEnvironmentId()); } elseif (!$scriptPath) { throw new Scalr_Exception_Core('scriptId or scriptPath should be set'); } if (!$scriptTimeout) { $scriptTimeout = $scriptIsSync == 1 ? Scalr::config('scalr.script.timeout.sync') : Scalr::config('scalr.script.timeout.async'); } $executeScript = true; if ($shortcutId && ($target != Script::TARGET_INSTANCE || $target != Script::TARGET_ALL)) { if ($shortcutId == -1) { $shortcut = new ScriptShortcut(); $shortcut->farmId = $farmId; } else { $shortcut = ScriptShortcut::findPk($shortcutId); /* @var $shortcut ScriptShortcut */ if (!$shortcut) { throw new Scalr_UI_Exception_NotFound(); } if ($editShortcut == 1) { $executeScript = false; } } $shortcut->farmRoleId = $farmRoleId == 0 ? NULL : $farmRoleId; if ($scriptId) { $shortcut->scriptId = $scriptId; $shortcut->scriptPath = ''; } else { $shortcut->scriptPath = $scriptPath; $shortcut->scriptId = NULL; } $shortcut->isSync = $scriptIsSync; $shortcut->version = $scriptVersion; $shortcut->timeout = $scriptTimeout; $shortcut->params = $scriptParams; $shortcut->save(); } if ($executeScript) { switch ($target) { case Script::TARGET_FARM: $servers = $this->db->GetAll("\n SELECT server_id\n FROM servers\n WHERE is_scalarized = 1 AND status IN (?,?) AND farm_id=?", [SERVER_STATUS::INIT, SERVER_STATUS::RUNNING, $farmId]); break; case Script::TARGET_ROLE: $servers = $this->db->GetAll("\n SELECT server_id\n FROM servers\n WHERE is_scalarized = 1 AND status IN (?,?) AND farm_roleid=?", [SERVER_STATUS::INIT, SERVER_STATUS::RUNNING, $farmRoleId]); break; case Script::TARGET_INSTANCE: $servers = $this->db->GetAll("\n SELECT server_id\n FROM servers\n WHERE is_scalarized = 1 AND status IN (?,?) AND server_id=?", [SERVER_STATUS::INIT, SERVER_STATUS::RUNNING, $serverId]); break; case Script::TARGET_ALL: $sql = "\n SELECT s.server_id\n FROM servers s\n JOIN farms f ON f.id = s.farm_id\n WHERE s.is_scalarized = 1\n AND s.status IN (?,?)\n AND s.env_id = ?\n AND " . $this->request->getFarmSqlQuery(Acl::PERM_FARMS_SERVERS); $args = [SERVER_STATUS::INIT, SERVER_STATUS::RUNNING, $this->getEnvironmentId()]; $servers = $this->db->GetAll($sql, $args); break; } $scriptSettings = array('version' => $scriptVersion, 'timeout' => $scriptTimeout, 'issync' => $scriptIsSync, 'params' => serialize($scriptParams)); if ($scriptId) { $scriptSettings['scriptid'] = $scriptId; $scriptSettings['type'] = Scalr_Scripting_Manager::ORCHESTRATION_SCRIPT_TYPE_SCALR; } else { $scriptSettings['script_path'] = $scriptPath; $scriptSettings['type'] = Scalr_Scripting_Manager::ORCHESTRATION_SCRIPT_TYPE_LOCAL; } $serializer = Scalr_Messaging_JsonSerializer::getInstance(); $cryptoTool = \Scalr::getContainer()->srzcrypto; // send message to start executing task (starts script) if (count($servers) > 0) { foreach ($servers as $server) { $DBServer = DBServer::LoadByID($server['server_id']); $msg = new Scalr_Messaging_Msg_ExecScript("Manual"); $msg->setServerMetaData($DBServer); $script = Scalr_Scripting_Manager::prepareScript($scriptSettings, $DBServer); if ($script) { $DBServer->executeScript($script, $msg); $this->auditLog("script.execute", $script, $DBServer); $manualLog = new OrchestrationLogManualScript($script['execution_id'], $msg->serverId); $manualLog->userId = $this->getUser()->getId(); $manualLog->userEmail = $this->getUser()->getEmail(); $manualLog->added = new DateTime('now', new DateTimeZone('UTC')); $manualLog->save(); } } } $this->response->success('Script execution has been queued and will occur on the selected instance(s) within a couple of minutes.'); } else { $this->response->success('Script shortcut successfully saved'); } }
/** * {@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; }
/** * @param int $farmId * @param int $farmRoleId optional * @param string $serverId optional * @param int $scriptId optional * @param string $scriptPath optional * @param int $scriptIsSync * @param int $scriptTimeout * @param int $scriptVersion * @param array $scriptParams optional * @param int $shortcutId optional * @param int $editShortcut optional * @throws Exception */ public function xExecuteAction($farmId, $farmRoleId = 0, $serverId = '', $scriptId = 0, $scriptPath = '', $scriptIsSync, $scriptTimeout, $scriptVersion, array $scriptParams = [], $shortcutId = null, $editShortcut = null) { $this->request->restrictAccess(Acl::RESOURCE_ADMINISTRATION_SCRIPTS, Acl::PERM_ADMINISTRATION_SCRIPTS_EXECUTE); if ($serverId) { $dbServer = DBServer::LoadByID($serverId); $this->user->getPermissions()->validate($dbServer); $target = Script::TARGET_INSTANCE; $serverId = $dbServer->serverId; $farmRoleId = $dbServer->farmRoleId; $farmId = $dbServer->farmId; } else { if ($farmRoleId) { $dbFarmRole = DBFarmRole::LoadByID($farmRoleId); $this->user->getPermissions()->validate($dbFarmRole); $target = Script::TARGET_ROLE; $farmRoleId = $dbFarmRole->ID; $farmId = $dbFarmRole->FarmID; } else { if (!$farmId) { $target = Script::TARGET_ALL; } else { $dbFarm = DBFarm::LoadByID($this->getParam('farmId')); $this->user->getPermissions()->validate($dbFarm); $target = Script::TARGET_FARM; $farmId = $dbFarm->ID; } } } if ($scriptId) { $script = Script::findPk($scriptId); /* @var Script $script */ if (!$script) { throw new Scalr_UI_Exception_NotFound(); } $script->checkPermission($this->user, $this->getEnvironmentId()); } elseif (!$scriptPath) { throw new Scalr_Exception_Core('scriptId or scriptPath should be set'); } if (!$scriptTimeout) { $scriptTimeout = $scriptIsSync == 1 ? Scalr::config('scalr.script.timeout.sync') : Scalr::config('scalr.script.timeout.async'); } $executeScript = true; if ($shortcutId && ($target != Script::TARGET_INSTANCE || $target != Script::TARGET_ALL)) { if ($shortcutId == -1) { $shortcut = new ScriptShortcut(); $shortcut->farmId = $farmId; } else { $shortcut = ScriptShortcut::findPk($shortcutId); /* @var ScriptShortcut $shortcut */ if (!$shortcut) { throw new Scalr_UI_Exception_NotFound(); } if ($editShortcut == 1) { $executeScript = false; } } $shortcut->farmRoleId = $farmRoleId == 0 ? NULL : $farmRoleId; if ($scriptId) { $shortcut->scriptId = $scriptId; $shortcut->scriptPath = ''; } else { $shortcut->scriptPath = $scriptPath; $shortcut->scriptId = NULL; } $shortcut->isSync = $scriptIsSync; $shortcut->version = $scriptVersion; $shortcut->timeout = $scriptTimeout; $shortcut->params = $scriptParams; $shortcut->save(); } if ($executeScript) { switch ($target) { case Script::TARGET_FARM: $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 Script::TARGET_ROLE: $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 Script::TARGET_INSTANCE: $servers = $this->db->GetAll("SELECT server_id FROM servers WHERE status IN (?,?) AND server_id=?", array(SERVER_STATUS::INIT, SERVER_STATUS::RUNNING, $serverId)); break; case Script::TARGET_ALL: $servers = $this->db->GetAll("SELECT server_id FROM servers WHERE status IN (?,?) AND env_id = ?", array(SERVER_STATUS::INIT, SERVER_STATUS::RUNNING, $this->getEnvironmentId())); break; } $scriptSettings = array('version' => $scriptVersion, 'timeout' => $scriptTimeout, 'issync' => $scriptIsSync, 'params' => serialize($scriptParams)); if ($scriptId) { $scriptSettings['scriptid'] = $scriptId; $scriptSettings['type'] = Scalr_Scripting_Manager::ORCHESTRATION_SCRIPT_TYPE_SCALR; } else { $scriptSettings['script_path'] = $scriptPath; $scriptSettings['type'] = Scalr_Scripting_Manager::ORCHESTRATION_SCRIPT_TYPE_LOCAL; } $serializer = Scalr_Messaging_JsonSerializer::getInstance(); $cryptoTool = Scalr_Messaging_CryptoTool::getInstance(); // send message to start executing task (starts script) if (count($servers) > 0) { foreach ($servers as $server) { $DBServer = DBServer::LoadByID($server['server_id']); $msg = new Scalr_Messaging_Msg_ExecScript("Manual"); $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->name = "local-" . crc32($script['path']) . mt_rand(100, 999); } $itm->executionId = $script['execution_id']; $msg->scripts = array($itm); $msg->setGlobalVariables($DBServer, true); /* if ($DBServer->IsSupported('2.5.12')) { $DBServer->scalarizr->system->executeScripts( $msg->scripts, $msg->globalVariables, $msg->eventName, $msg->roleName ); } else */ $DBServer->SendMessage($msg, false, true); } } $this->response->success('Script execution has been queued and will occur on the selected instance(s) within a couple of minutes.'); } else { $this->response->success('Script shortcut successfully saved'); } }