/** * Makes api request * * @param string $qid The id of the query. * @param array $options optional Query options for the request. * @param string $path optional Uri path for the request (/user by default) * @param string $method optional Http method (GET by default) * @return object Returns object that is an response data. * @throws CloudynException */ public function call($qid, array $options = array(), $path = '/user', $method = 'GET') { $options['qid'] = (string) $qid; $options['out'] = self::OUT_JSON; if (!isset($options['rqid'])) { $options['rqid'] = $this->getRequestId(); } if (!isset($options['apiversion'])) { $options['apiversion'] = '0.4'; } $this->request = $this->createNewRequest(); $this->request->setRequestUrl($this->getUrl() . $path); $this->request->setRequestMethod($method); $this->request->setOptions(array('redirect' => 10, 'cookiesession' => true)); $this->request->addQuery($options); $this->response = $this->tryCall($this->request); $json = $this->response->getBody()->toString(); $json = preg_replace('#^[^\\{\\[]+|[^\\}\\]]+$#', '', trim($json)); $obj = json_decode($json); if (isset($obj->status) && $obj->status != 'ok' && isset($obj->message)) { throw new CloudynException('Cloudyn error. ' . $obj->message); } return $obj; }
/** * 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; }
/** * Returns page with RabbitMQ role status * * @param int $farmId Identifier of the Farm * @param int $farmRoleId optional Identifier of the FarmRole */ public function statusAction($farmId, $farmRoleId = null) { $dbFarm = DBFarm::LoadByID($farmId); $this->user->getPermissions()->validate($dbFarm); $list = []; foreach ($dbFarm->GetFarmRoles() as $dbFarmRole) { if (!$dbFarmRole->GetRoleObject()->hasBehavior(ROLE_BEHAVIORS::RABBITMQ)) { continue; } $farmRole = ['id' => $dbFarmRole->ID, 'alias' => $dbFarmRole->Alias]; if (empty($farmRoleId) && empty($list) || $dbFarmRole->ID == $farmRoleId) { $rabbitmq = []; $rabbitmq['status'] = ''; $rabbitmq['showSetup'] = false; $rabbitmq['showStatusLabel'] = true; $cpUrl = $dbFarmRole->GetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_URL); if ($cpUrl) { $serverId = $dbFarmRole->GetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_SERVER_ID); try { $dbServer = DBServer::LoadByID($serverId); if ($dbServer->status == SERVER_STATUS::RUNNING) { $rabbitmq['username'] = '******'; $rabbitmq['password'] = $dbFarmRole->GetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_PASSWORD); $rabbitmq['url'] = $cpUrl; $url = str_replace('/mgmt/', '/api/overview', $rabbitmq['url']); $httpRequest = new Request(); $httpRequest->setRequestMethod('GET'); $httpRequest->setRequestUrl($url); $httpRequest->setOptions(['redirect' => 5, 'timeout' => 30, 'connecttimeout' => 10]); $httpRequest->setHeaders(array('Authorization' => 'Basic ' . base64_encode($rabbitmq['username'] . ':' . $rabbitmq['password']))); $response = \Scalr::getContainer()->http->sendRequest($httpRequest); $data = $response->getBody()->toString(); $result = json_decode($data, true); if ($result) { $rabbitmq['overview'] = $result; } } else { throw new \Scalr\Exception\ServerNotFoundException(); } } catch (\Scalr\Exception\ServerNotFoundException $e) { $rabbitmq['status'] = "Control panel was installed, however server wasn't found"; $rabbitmq['showSetup'] = true; $dbFarmRole->ClearSettings('rabbitmq.cp'); } catch (Exception $e) { if (isset($e->innerException)) { $msg = $e->innerException->getMessage(); } else { $msg = $e->getMessage(); } $rabbitmq['status'] = "Error retrieving information about control panel: \"{$msg}\""; } } else { if ($dbFarmRole->GetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_REQUESTED) == '1') { if ($dbFarmRole->GetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_ERROR_MSG)) { $rabbitmq['showSetup'] = true; $rabbitmq['status'] = 'Server returned error: "' . $dbFarmRole->GetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_ERROR_MSG) . '"'; } else { if ($dbFarmRole->GetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_REQUEST_TIME) > time() - self::REQUEST_TIMEOUT) { $rabbitmq['status'] = "Request was sent at " . Scalr_Util_DateTime::convertTz((int) $dbFarmRole->GetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_REQUEST_TIME)) . ". Please wait..."; } else { $rabbitmq['showSetup'] = true; $rabbitmq['status'] = "Request timeout exceeded. Request was sent at " . Scalr_Util_DateTime::convertTz((int) $dbFarmRole->GetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_CP_REQUEST_TIME)); } } } else { if ($dbFarmRole->GetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_PASSWORD)) { $rabbitmq['showSetup'] = true; } else { $rabbitmq['status'] = 'Rabbitmq cluster not initialized yet. Please wait ...'; $rabbitmq['showStatusLabel'] = false; } } } $rabbitmq['password'] = $dbFarmRole->GetSetting(Scalr_Role_Behavior_RabbitMQ::ROLE_PASSWORD); $farmRole['data'] = $rabbitmq; } $list[] = $farmRole; } $this->response->page('ui/services/rabbitmq/status.js', ['list' => $list]); }
private function request($path, $method, $data = "") { $data = trim($data); $httpRequest = new Request(); $httpRequest->setSslOptions(['verifypeer' => false, 'verifyhost' => false]); $fullUrl = "{$this->chefServerUrl}{$path}"; $chunks = parse_url($fullUrl); if (in_array($method, ["POST", "PUT"]) && $data) { $httpRequest->append($data); } $httpRequest->setRequestUrl($fullUrl); $httpRequest->setRequestMethod($method); $tz = @date_default_timezone_get(); date_default_timezone_set("UTC"); $timestamp = date("Y-m-d\\TH:i:s\\Z"); date_default_timezone_set($tz); $chunks['path'] = str_replace('//', '/', $chunks['path']); $hashedPath = base64_encode(sha1($chunks['path'], true)); $hashedBody = base64_encode(sha1($data, true)); $userId = $this->username; $str = "Method:{$method}\n" . "Hashed Path:{$hashedPath}\n" . "X-Ops-Content-Hash:{$hashedBody}\n" . "X-Ops-Timestamp:{$timestamp}\n" . "X-Ops-UserId:{$userId}"; $headers = array('x-ops-sign' => "algorithm=sha1;version=1.0", 'x-chef-version' => "0.10.8", 'x-ops-userid' => $userId, 'x-ops-timestamp' => $timestamp, 'x-ops-content-hash' => $hashedBody, 'content-type' => 'application/json', 'accept' => 'application/json'); $r = array_merge($headers, $this->sign($str)); $httpRequest->addHeaders($r); $response = \Scalr::getContainer()->http->sendRequest($httpRequest); if ($response->getResponseCode() == 401) { throw new Exception("Failed to authenticate as {$userId}. Ensure that your node_name and client key are correct."); } if ($response->getResponseCode() == 404) { throw new Exception("Client not found or parameters are not valid"); } else { if ($response->getResponseCode() <= 205) { $data = $response->getBody()->toString(); $retval = empty($data) ? true : json_decode($data); } else { if ($response->getResponseCode() >= 300 && $response->getResponseCode() < 400) { throw new Exception("Request to chef server failed. Chef server returned code {$response->getResponseCode()}. Redirect URL: {$response->getHeader("Location")}"); } else { if ($response->getResponseCode() > 400) { $data = $response->getBody()->toString(); $msg = empty($data) ? "" : json_decode($data); if (is_array($msg->error)) { $msg = $msg->error[0]; } elseif ($msg->error) { $msg = $msg->error; } else { $msg = "Unknown error. Error code: {$response->getResponseCode()}"; } throw new Exception("Request to chef server failed with error: {$msg} ({$method} {$path})"); } else { throw new Exception("Unexpected situation. Response code {$response->getResponseCode()}"); } } } } return $retval; }
/** * {@inheritdoc} * @see Scalr\Service\CloudStack\Client.ClientInterface::call() */ public function call($command, array $args = null, $verb = 'GET') { $attempts = 3; if ($args === null) { $args = array(); } foreach ($args as $key => $value) { if (is_null($value)) { unset($args[$key]); } // Workaround for zones. if ($key == 'zoneid' && !is_null($value)) { if (empty($this->zonesCache)) { foreach ($this->cloudstack->zone->describe() as $zone) { $this->zonesCache[$zone->name] = $zone->id; } } if (!empty($this->zonesCache[$value])) { $args[$key] = $this->zonesCache[$value]; } else { throw new RestClientException("Availability zone '{$value}' no longer supported"); } } } $args['apikey'] = $this->apiKey; $args['command'] = $command; $args['response'] = 'json'; ksort($args); $query = http_build_query($args, null, '&', PHP_QUERY_RFC3986); if ('GET' == $verb) { $query .= "&signature=" . $this->getSignature(strtolower($query)); } else { $args['signature'] = $this->getSignature(strtolower($query)); } $httpRequest = new Request(); $httpRequest->setRequestMethod($verb); $url = 'GET' == $verb ? $this->endpoint . "?" . $query : $this->endpoint; $httpRequest->setRequestUrl($url); if ('POST' == $verb) { $httpRequest->append($args); } $message = $this->tryCall($httpRequest, $attempts); $response = new QueryClientResponse($message, $command); $response->setRawRequestMessage($httpRequest->toString()); if ($this->debug) { echo "\nURL: " . $httpRequest->getRequestUrl() . "\n", "{$httpRequest}\n", "{$response->getResponse()}\n"; } return $response; }