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 => self::GenerateRandomKey(40), SERVER_PROPERTIES::SZR_KEY_TYPE => SZR_KEY_TYPE::ONE_TIME));
$DBServer = DBServer::Create($ServerCreateInfo, false, true);
} elseif (!$DBServer && !$ServerCreateInfo) {
// incorrect arguments
self::getContainer()->logger(LOG_CATEGORY::FARM)->error(sprintf("Cannot create server"));
return null;
} else {
if ($DBServer && empty($DBServer->cloudLocation)) {
trigger_error('Cloud location is missing in DBServer', E_USER_WARNING);
}
}
$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->ownerId ?: $farm->GetSetting(Entity\FarmSetting::CREATED_BY_ID);
$propsToSet[SERVER_PROPERTIES::FARM_CREATED_BY_EMAIL] = $farm->ownerId ? Entity\Account\User::findPk($farm->ownerId)->email : $farm->GetSetting(Entity\FarmSetting::CREATED_BY_EMAIL);
$projectId = $farm->GetSetting(Entity\FarmSetting::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) {
$role = $farmRole->GetRoleObject();
$DBServer->isScalarized = $role->isScalarized;
if (!$DBServer->isScalarized) {
$propsToSet[SERVER_PROPERTIES::SZR_VESION] = '';
}
$DBServer->Save();
}
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) {
self::getContainer()->logger(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 ($reason) {
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]);
} else {
$reasonMsg = $DBServer->GetProperty(SERVER_PROPERTIES::LAUNCH_REASON);
$reasonId = $DBServer->GetProperty(SERVER_PROPERTIES::LAUNCH_REASON_ID);
}
if ($delayed) {
$DBServer->updateStatus(SERVER_STATUS::PENDING_LAUNCH);
return $DBServer;
}
if ($ServerCreateInfo && $ServerCreateInfo->roleId) {
$dbRole = DBRole::loadById($ServerCreateInfo->roleId);
if ($dbRole->generation == 1) {
$DBServer->updateStatus(SERVER_STATUS::PENDING_LAUNCH);
$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 = self::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) {
self::getContainer()->logger("SERVER_LAUNCH")->warn("{$pendingServers} servers in PENDING state on {$DBServer->platform}. Limit is: {$pendingServersLimit}. Waiting.");
$DBServer->updateStatus(SERVER_STATUS::PENDING_LAUNCH);
$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 {
self::getContainer()->logger("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 {
$DBServer->getServerHistory()->markAsLaunched($reasonMsg, $reasonId);
$DBServer->updateTimelog('ts_launched');
if ($DBServer->imageId) {
//Update Image last used date
/* @var $server Entity\Server */
$server = Entity\Server::findPk($DBServer->serverId);
$image = $server->getImage();
if ($image) {
$image->update(['dtLastUsed' => new DateTime()]);
}
if ($server->farmRoleId && empty($server->getFarmRole())) {
trigger_error(sprintf("Call to a member function getRole() on null. Server: %s, FarmRole: %d", $server->serverId, $server->farmRoleId), E_USER_WARNING);
}
if ($server->farmRoleId && !empty($server->getFarmRole()->getRole())) {
//Update Role last used date
$server->getFarmRole()->getRole()->update(['lastUsed' => new DateTime()]);
}
}
} catch (Exception $e) {
self::getContainer()->logger('SERVER_HISTORY')->error(sprintf("Cannot update servers history: {$e->getMessage()}"));
}
} catch (Exception $e) {
self::getContainer()->logger(LOG_CATEGORY::FARM)->error(new FarmLogMessage($DBServer, sprintf("Cannot launch server on '%s' platform: %s", !empty($DBServer->platform) ? $DBServer->platform : null, $e->getMessage())));
$existingLaunchError = $DBServer->GetProperty(SERVER_PROPERTIES::LAUNCH_ERROR);
$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->updateStatus(SERVER_STATUS::PENDING_LAUNCH);
if ($DBServer->farmId && !$existingLaunchError) {
self::FireEvent($DBServer->farmId, new InstanceLaunchFailedEvent($DBServer, $e->getMessage()));
}
}
if ($DBServer->status == SERVER_STATUS::PENDING) {
self::FireEvent($DBServer->farmId, new BeforeInstanceLaunchEvent($DBServer));
$DBServer->SetProperty(SERVER_PROPERTIES::LAUNCH_ERROR, "");
}
return $DBServer;
}