public function SendMessage(Scalr_Messaging_Msg $message, $isEventNotice = false, $delayed = false)
{
$startTime = microtime(true);
if (!$this->isScalarized) {
return;
}
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` = UTC_TIMESTAMP(),\n `dtadded` = NOW(),\n `message_format` = ?,\n `event_id` = ?\n ON DUPLICATE KEY UPDATE handle_attempts = handle_attempts+1, dtlasthandleattempt = UTC_TIMESTAMP()\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, sprintf("Cannot deliver message '%s' (message_id: %s) via REST to server '%s' (server_id: %s). Error: %s", $message->getName(), !empty($message->messageId) ? $message->messageId : null, !empty($this->remoteIp) ? $this->remoteIp : null, !empty($this->serverId) ? $this->serverId : null, !empty($msg) ? $msg : null)));
} 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;
}