public static function setStaticNatForServer(\DBServer $dbServer)
{
$db = \Scalr::getDb();
try {
$dbFarm = DBFarm::LoadByID($dbServer->farmId);
$dbFarmRole = $dbServer->GetFarmRoleObject();
if (!$dbFarmRole->GetSetting(Entity\FarmRoleSetting::CLOUDSTACK_USE_STATIC_NAT)) {
return false;
}
$cs = $dbFarm->GetEnvironmentObject()->cloudstack($dbFarmRole->Platform);
} catch (Exception $e) {
\Scalr::getContainer()->logger(\LOG_CATEGORY::FARM)->fatal(new \FarmLogMessage($dbServer, sprintf(_("Cannot allocate elastic ip address for instance %s on farm %s (0)"), !empty($dbServer->serverId) ? $dbServer->serverId : null, !empty($dbFarm->Name) ? $dbFarm->Name : null)));
return false;
}
$ip = $db->GetRow("\n SELECT * FROM elastic_ips\n WHERE farmid=?\n AND ((farm_roleid=? AND instance_index=?) OR server_id = ?)\n LIMIT 1\n ", array($dbServer->farmId, $dbFarmRole->ID, $dbServer->index, $dbServer->serverId));
if ($ip['ipaddress']) {
if (!self::checkStaticNatIp($ip['ipaddress'], $cs)) {
\Scalr::getContainer()->logger(\LOG_CATEGORY::FARM)->warn(new \FarmLogMessage($dbServer, sprintf(_("Static NAT IP '%s' does not belong to you. Allocating new one."), !empty($ip['ipaddress']) ? $ip['ipaddress'] : null)));
$db->Execute("DELETE FROM elastic_ips WHERE ipaddress=?", array($ip['ipaddress']));
$ip = false;
}
}
if ($ip && $ip['ipaddress'] == $dbServer->remoteIp) {
return $ip['ipaddress'];
}
// If free IP not found we must allocate new IP
if (!$ip) {
$alocatedIps = $db->GetOne("SELECT COUNT(*) FROM elastic_ips WHERE farm_roleid = ?", array($dbFarmRole->ID));
// Check elastic IPs limit. We cannot allocate more than 'Max instances' option for role
if ($alocatedIps < $dbFarmRole->GetSetting(Entity\FarmRoleSetting::SCALING_MAX_INSTANCES)) {
try {
$requestObject = new AssociateIpAddressData();
$requestObject->zoneid = $dbFarmRole->CloudLocation;
$ipResult = $cs->associateIpAddress($requestObject);
$ipId = !empty($ipResult->id) ? $ipResult->id : null;
if ($ipId) {
while (true) {
$requestObject = new ListIpAddressesData();
$requestObject->id = $ipId;
$ipInfo = $cs->listPublicIpAddresses($requestObject);
$ipInfo = count($ipInfo) > 0 ? $ipInfo[0] : null;
if (!$ipInfo) {
throw new Exception("Cannot allocate IP address: listPublicIpAddresses -> failed");
}
if ($ipInfo->state == 'Allocated') {
break;
} else {
if ($ipInfo->state == 'Allocating') {
sleep(1);
} else {
throw new Exception("Cannot allocate IP address: ipAddress->state = {$ipInfo->state}");
}
}
}
} else {
throw new Exception("Cannot allocate IP address: associateIpAddress -> failed");
}
} catch (Exception $e) {
\Scalr::getContainer()->logger(\LOG_CATEGORY::FARM)->error(new \FarmLogMessage($dbServer, sprintf(_("Cannot allocate new elastic ip for instance '%s': %s"), !empty($dbServer->serverId) ? $dbServer->serverId : null, $e->getMessage())));
return false;
}
// Add allocated IP address to database
$db->Execute("INSERT INTO elastic_ips SET\n env_id=?,\n farmid=?,\n farm_roleid=?,\n ipaddress=?,\n clientid=?,\n instance_index=?,\n allocation_id=?,\n state='0', server_id=''\n ", array($dbServer->envId, $dbServer->farmId, $dbServer->farmRoleId, $ipInfo->ipaddress, $dbServer->clientId, $dbServer->index, $ipId));
$ip = array('ipaddress' => $ipInfo->ipaddress, 'allocation_id' => $ipId);
\Scalr::getContainer()->logger(\LOG_CATEGORY::FARM)->info(new \FarmLogMessage($dbServer, sprintf(_("Allocated new IP: %s"), $ip['ipaddress'])));
// Waiting...
sleep(5);
} else {
\Scalr::getContainer()->logger(__CLASS__)->fatal(_("Limit for elastic IPs reached. Check zomby records in database."));
}
}
if ($ip['ipaddress']) {
self::associateIpAddress($dbServer, $ip['ipaddress'], $ip['allocation_id']);
// Update leastic IPs table
$db->Execute("UPDATE elastic_ips SET state='1', server_id=? WHERE ipaddress=?", array($dbServer->serverId, $ip['ipaddress']));
\Scalr::FireEvent($dbServer->farmId, new \IPAddressChangedEvent($dbServer, $ip['ipaddress'], $dbServer->localIp));
} else {
\Scalr::getContainer()->logger(\LOG_CATEGORY::FARM)->fatal(new \FarmLogMessage($dbServer, sprintf(_("Cannot allocate elastic ip address for instance %s on farm %s (2)"), !empty($dbServer->serverId) ? $dbServer->serverId : null, !empty($dbFarm->Name) ? $dbFarm->Name : null)));
return false;
}
return $ip['ipaddress'];
}