public static function getEventScriptList(AbstractServerEvent $event, DBServer $eventServer, DBServer $targetServer) { $db = \Scalr::getDb(); $accountScripts = $db->GetAll("\n SELECT * FROM account_scripts\n WHERE account_id = ?\n AND (event_name = ? OR event_name = '*')\n ", [$eventServer->clientId, $event->GetName()]); $roleScripts = $db->GetAll("\n SELECT * FROM role_scripts\n WHERE (event_name = ? OR event_name = '*') AND role_id = ?\n ", [$event->GetName(), $eventServer->GetFarmRoleObject()->RoleID]); $scripts = $db->GetAll("\n SELECT *, `script_type` as `type`\n FROM farm_role_scripts\n WHERE (event_name = ? OR event_name = '*') AND farmid = ?\n ", [$event->GetName(), $eventServer->farmId]); foreach ($accountScripts as $script) { $scripts[] = array("id" => "a{$script['id']}", "type" => $script['script_type'], "scriptid" => $script['script_id'], "params" => $script['params'], "event_name" => $event->GetName(), "target" => $script['target'], "version" => $script['version'], "timeout" => $script['timeout'], "issync" => $script['issync'], "order_index" => $script['order_index'], "scope" => "account", 'script_path' => $script['script_path'], 'run_as' => $script['run_as'], 'script_type' => $script['script_type']); } foreach ($roleScripts as $script) { $params = $db->GetOne("\n SELECT params\n FROM farm_role_scripting_params\n WHERE farm_role_id = ?\n AND `hash` = ?\n AND farm_role_script_id = '0'\n LIMIT 1\n ", array($eventServer->farmRoleId, $script['hash'])); if ($params) { $script['params'] = $params; } $scripts[] = array("id" => "r{$script['id']}", "scriptid" => $script['script_id'], "type" => $script['script_type'], "params" => $script['params'], "event_name" => $event->GetName(), "target" => $script['target'], "version" => $script['version'], "timeout" => $script['timeout'], "issync" => $script['issync'], "order_index" => $script['order_index'], "scope" => "role", 'script_path' => $script['script_path'], 'run_as' => $script['run_as'], 'script_type' => $script['script_type']); } $retval = []; foreach ($scripts as $scriptSettings) { $scriptSettings['order_index'] = (double) $scriptSettings['order_index']; // If target set to that instance only if ($scriptSettings['target'] == Script::TARGET_INSTANCE && $eventServer->serverId != $targetServer->serverId) { continue; } // If target set to all instances in specific role if ($scriptSettings['target'] == Script::TARGET_ROLE && $eventServer->farmRoleId != $targetServer->farmRoleId) { continue; } if (!$scriptSettings['scope']) { // Validate that event was triggered on the same farmRoleId as script if ($eventServer->farmRoleId != $scriptSettings['farm_roleid']) { continue; } // Validate that target server has the same farmRoleId as event server with target ROLE if ($scriptSettings['target'] == Script::TARGET_ROLE && $targetServer->farmRoleId != $scriptSettings['farm_roleid']) { continue; } } if ($scriptSettings['target'] == Script::TARGET_ROLES || $scriptSettings['target'] == Script::TARGET_BEHAVIORS || $scriptSettings['target'] == Script::TARGET_FARMROLES) { if ($scriptSettings['scope'] != 'role') { $targets = $db->GetAll("SELECT * FROM farm_role_scripting_targets WHERE farm_role_script_id = ?", array($scriptSettings['id'])); } else { $targets = []; } $execute = false; foreach ($targets as $target) { switch ($target['target_type']) { case "farmrole": if ($scriptSettings['target'] == Script::TARGET_ROLES && $targetServer->farmRoleId == $target['target'] || $scriptSettings['target'] == Script::TARGET_FARMROLES && $targetServer->GetFarmRoleObject()->Alias == $target['target']) { $execute = true; } break; case "behavior": if ($targetServer->GetFarmRoleObject()->GetRoleObject()->hasBehavior($target['target'])) { $execute = true; } break; } } if (!$execute) { continue; } } if ($scriptSettings['target'] == "" || $scriptSettings['id'] == "") { continue; } $script = self::prepareScript($scriptSettings, $targetServer, $event); if ($script) { while (true) { $index = (string) $scriptSettings['order_index']; if (empty($retval[$index])) { $retval[$index] = $script; break; } else { $scriptSettings['order_index'] += 0.01; } } } } if (!empty($retval) && is_array($retval)) { ksort($retval); } return $retval; }
private function sendPromoteToMasterMessage(\AbstractServerEvent $event) { if ($event->DBServer->GetProperty(\Scalr_Db_Msr::REPLICATION_MASTER) || $event->DBServer->GetFarmRoleObject()->GetSetting(\Scalr_Db_Msr::SLAVE_TO_MASTER)) { //Check if master already running: do not send promote_to_master $msg = new \Scalr_Messaging_Msg_DbMsr_PromoteToMaster(); $msg->tmpEventName = $event->GetName(); $msg->dbType = $event->DBServer->GetFarmRoleObject()->GetRoleObject()->getDbMsrBehavior(); $msg->cloudLocation = $event->DBServer->GetCloudLocation(); if (in_array($event->DBServer->platform, array(\SERVER_PLATFORMS::EC2, \SERVER_PLATFORMS::CLOUDSTACK, \SERVER_PLATFORMS::IDCF))) { try { $volume = \Scalr_Storage_Volume::init()->loadById($event->DBServer->GetFarmRoleObject()->GetSetting(\Scalr_Db_Msr::VOLUME_ID)); $msg->volumeConfig = $volume->getConfig(); } catch (\Exception $e) { $this->Logger->error(new \FarmLogMessage($event->DBServer->farmId, "Cannot create volumeConfig for PromoteToMaster message: {$e->getMessage()}", !empty($event->DBServer->serverId) ? $event->DBServer->serverId : null)); } } if ($event->DBServer->farmRoleId != 0) { foreach (\Scalr_Role_Behavior::getListForRole($event->DBServer->GetFarmRoleObject()->GetRoleObject()) as $behavior) { $msg = $behavior->extendMessage($msg, $event->DBServer); } } // Send Mysql_PromoteToMaster to the first server in the same avail zone as old master (if exists) // Otherwise send to first in role $platform = $event->DBServer->platform; if ($platform == \SERVER_PLATFORMS::EC2) { $availZone = $event->DBServer->GetProperty(\EC2_SERVER_PROPERTIES::AVAIL_ZONE); } $dbFarmRole = $event->DBServer->GetFarmRoleObject(); $servers = $dbFarmRole->GetServersByFilter(array('status' => array(\SERVER_STATUS::RUNNING))); $firstInRoleServer = false; foreach ($servers as $DBServer) { if ($DBServer->serverId == $event->DBServer->serverId) { continue; } if (!$firstInRoleServer) { $firstInRoleServer = $DBServer; } if ($platform == \SERVER_PLATFORMS::EC2 && $DBServer->GetProperty(\EC2_SERVER_PROPERTIES::AVAIL_ZONE) == $availZone || $platform != \SERVER_PLATFORMS::EC2) { $event->DBServer->SetProperty(\Scalr_Db_Msr::REPLICATION_MASTER, 0); $dbFarmRole->SetSetting(\Scalr_Db_Msr::SLAVE_TO_MASTER, 1); $DBServer->SetProperty(\Scalr_Db_Msr::REPLICATION_MASTER, 1); $DBServer->SendMessage($msg, false, true); return; } } if ($firstInRoleServer) { $dbFarmRole->SetSetting(\Scalr_Db_Msr::SLAVE_TO_MASTER, 1); $firstInRoleServer->SetProperty(\Scalr_Db_Msr::REPLICATION_MASTER, 1); $firstInRoleServer->SendMessage($msg, false, true); } } }
public static function listServerGlobalVariables(DBServer $dbServer, $includeSystem = false, AbstractServerEvent $event = null) { $retval = array(); if ($includeSystem) { $variables = $dbServer->GetScriptingVars(); if ($event) { if ($event->DBServer) { foreach ($event->DBServer->GetScriptingVars() as $k => $v) { $variables["event_{$k}"] = $v; } } foreach ($event->GetScriptingVars() as $k => $v) { $variables[$k] = $event->{$v}; } if (isset($event->params) && is_array($event->params)) { foreach ($event->params as $k => $v) { $variables[$k] = $v; } } $variables['event_name'] = $event->GetName(); } $formats = \Scalr::config("scalr.system.global_variables.format"); foreach ($variables as $name => $value) { $name = "SCALR_" . strtoupper($name); $value = trim($value); if (isset($formats[$name])) { $value = @sprintf($formats[$name], $value); } $private = strpos($name, 'SCALR_EVENT_') === 0 ? 1 : 0; $retval[] = (object) array('name' => $name, 'value' => $value, 'private' => $private, 'system' => 1); } } try { $globalVariables = new Scalr_Scripting_GlobalVariables($dbServer->GetEnvironmentObject()->clientId, $dbServer->envId, ScopeInterface::SCOPE_SERVER); $vars = $globalVariables->listVariables($dbServer->GetFarmRoleObject()->RoleID, $dbServer->farmId, $dbServer->farmRoleId, $dbServer->serverId); foreach ($vars as $v) { $retval[] = (object) $v; } } catch (Exception $e) { } return $retval; }
/** * Store event in database * * @param integer $farmid * @param string $event_name */ public static function StoreEvent($farmid, AbstractServerEvent $event, $eventTime = null) { $eventServerId = isset($event->DBServer->serverId) ? $event->DBServer->serverId : null; try { $DB = self::getDb(); // Generate event message $message = $event->getTextDetails(); $suspend = 0; if ($event instanceof HostDownEvent) { $suspend = $event->isSuspended; } elseif ($event instanceof BeforeHostTerminateEvent) { $suspend = $event->suspend; } // short_message temporary used for time tracking // Store event in database $DB->Execute("INSERT INTO events SET\n farmid\t= ?,\n type\t= ?,\n dtadded\t= NOW(),\n message\t= ?,\n event_object = ?,\n event_id\t = ?,\n event_server_id = ?,\n short_message = ?,\n msg_expected = ?,\n msg_created = ?,\n scripts_total = ?,\n is_suspend = ?", array($farmid, $event->GetName(), $message, json_encode($event->handledObservers), $event->GetEventID(), $eventServerId, $eventTime, $event->msgExpected, $event->msgCreated, $event->scriptsCount, $suspend)); } catch (Exception $e) { self::getContainer()->logger(__CLASS__)->fatal(sprintf(_("Cannot store event in database: %s"), $e->getMessage())); } try { if (isset($eventServerId)) { $dbServer = DBServer::LoadByID($eventServerId); if (!$dbServer->farmRoleId) { return true; } $dt = new DateTime('now', new DateTimeZone("UTC")); $timestamp = $dt->format("D d M Y H:i:s e"); $payload = new stdClass(); $payload->eventName = $event->GetName(); $payload->eventId = $event->GetEventID(); $payload->timestamp = $timestamp; $globalVars = Scalr_Scripting_GlobalVariables::listServerGlobalVariables($dbServer, true, $event); $webhooks = WebhookConfig::findByEvent($event->GetName(), $farmid, $dbServer->clientId, $dbServer->envId); $count = 0; foreach ($webhooks as $webhook) { /* @var $webhook \Scalr\Model\Entity\WebhookConfig */ $payload->configurationId = $webhook->webhookId; $payload->data = array(); $variables = []; foreach ($globalVars as $gv) { $variables[$gv->name] = $gv->value; if ($gv->private && $webhook->skipPrivateGv == 1 && !$gv->system) { continue; } $payload->data[$gv->name] = $gv->value; } if ($webhook->postData) { //Parse variable $keys = array_keys($variables); $keys = array_map(function ($item) { return '{' . $item . '}'; }, $keys); $values = array_values($variables); // Strip undefined variables & return value $payload->userData = preg_replace("/{[A-Za-z0-9_-]+}/", "", str_replace($keys, $values, $webhook->postData)); } else { $payload->userData = ''; } foreach ($webhook->getEndpoints() as $ce) { /* @var $ce \Scalr\Model\Entity\WebhookConfigEndpoint */ $endpoint = $ce->getEndpoint(); if (!$endpoint->isValid) { continue; } $payload->endpointId = $endpoint->endpointId; $encPayload = json_encode($payload); $history = new WebhookHistory(); $history->eventId = $event->GetEventID(); $history->eventType = $event->GetName(); $history->payload = $encPayload; $history->serverId = $event->DBServer ? $event->DBServer->serverId : null; $history->endpointId = $endpoint->endpointId; $history->webhookId = $webhook->webhookId; $history->farmId = $farmid; $history->save(); $count++; } } if ($count != 0) { $DB->Execute("UPDATE events SET wh_total = ? WHERE event_id = ?", array($count, $event->GetEventID())); } } } catch (Exception $e) { self::getContainer()->logger(__CLASS__)->fatal(sprintf(_("WebHooks: %s"), $e->getMessage())); } }