private function GetServerAvailZone(DBServer $DBServer, OpenStack $client, \Scalr_Server_LaunchOptions $launchOptions)
{
if ($DBServer->status == \SERVER_STATUS::TEMPORARY) {
return null;
}
$serverAvailZone = $DBServer->GetProperty(\OPENSTACK_SERVER_PROPERTIES::CLOUD_LOCATION_ZONE);
if ($serverAvailZone && $serverAvailZone != 'x-scalr-diff' && !stristr($serverAvailZone, "x-scalr-custom")) {
return $serverAvailZone;
}
$roleAvailZone = $DBServer->GetFarmRoleObject()->GetSetting(Entity\FarmRoleSetting::OPENSTACK_AVAIL_ZONE);
if (!$roleAvailZone) {
return null;
}
if ($roleAvailZone == "x-scalr-diff" || stristr($roleAvailZone, "x-scalr-custom")) {
$availZones = array();
if (stristr($roleAvailZone, "x-scalr-custom")) {
$zones = explode("=", $roleAvailZone);
foreach (explode(":", $zones[1]) as $zoneName) {
if ($zoneName != "") {
$isUnavailable = $DBServer->GetEnvironmentObject()->getPlatformConfigValue("openstack.{$launchOptions->cloudLocation}.{$zoneName}.unavailable", false);
if ($isUnavailable && $isUnavailable + 3600 < time()) {
$DBServer->GetEnvironmentObject()->setPlatformConfig(array("openstack.{$launchOptions->cloudLocation}.{$zoneName}.unavailable" => false), false);
$isUnavailable = false;
}
if (!$isUnavailable) {
array_push($availZones, $zoneName);
}
}
}
} else {
// Get list of all available zones
$availZonesResp = $client->servers->listAvailabilityZones();
foreach ($availZonesResp as $zone) {
$zoneName = $zone->zoneName;
if ($zone->zoneState->available == true) {
$isUnavailable = $DBServer->GetEnvironmentObject()->getPlatformConfigValue("openstack.{$launchOptions->cloudLocation}.{$zoneName}.unavailable", false);
if ($isUnavailable && $isUnavailable + 3600 < time()) {
$DBServer->GetEnvironmentObject()->setPlatformConfig(array("openstack.{$launchOptions->cloudLocation}.{$zoneName}.unavailable" => false), false);
$isUnavailable = false;
}
if (!$isUnavailable) {
array_push($availZones, $zoneName);
}
}
}
}
rsort($availZones);
$availZone = null;
$servers = $DBServer->GetFarmRoleObject()->GetServersByFilter(array("status" => array(\SERVER_STATUS::RUNNING, \SERVER_STATUS::INIT, \SERVER_STATUS::PENDING)));
$availZoneDistribution = array();
foreach ($servers as $cDbServer) {
if ($cDbServer->serverId != $DBServer->serverId) {
$availZoneDistribution[$cDbServer->GetProperty(\OPENSTACK_SERVER_PROPERTIES::CLOUD_LOCATION_ZONE)]++;
}
}
$sCount = PHP_INT_MAX;
foreach ($availZones as $zone) {
if ((int) $availZoneDistribution[$zone] <= $sCount) {
$sCount = (int) $availZoneDistribution[$zone];
$availZone = $zone;
}
}
return $availZone;
} else {
return $roleAvailZone;
}
}