public function LaunchServer(DBServer $DBServer, Scalr_Server_LaunchOptions $launchOptions = null)
{
$environment = $DBServer->GetEnvironmentObject();
$governance = new Scalr_Governance($environment->id);
$diskOffering = null;
$size = null;
$cs = $environment->cloudstack($this->platform);
if (!$launchOptions) {
$farmRole = $DBServer->GetFarmRoleObject();
$launchOptions = new Scalr_Server_LaunchOptions();
$dbRole = $farmRole->GetRoleObject();
$launchOptions->imageId = $dbRole->__getNewRoleObject()->getImage($this->platform, $DBServer->GetFarmRoleObject()->CloudLocation)->imageId;
$launchOptions->serverType = $DBServer->GetFarmRoleObject()->GetSetting(Entity\FarmRoleSetting::INSTANCE_TYPE);
$launchOptions->cloudLocation = $DBServer->GetFarmRoleObject()->CloudLocation;
/*
* User Data
*/
$u_data = '';
foreach ($DBServer->GetCloudUserData() as $k => $v) {
$u_data .= "{$k}={$v};";
}
$launchOptions->userData = trim($u_data, ";");
$diskOffering = $farmRole->GetSetting(Entity\FarmRoleSetting::CLOUDSTACK_DISK_OFFERING_ID);
if ($diskOffering === false || $diskOffering === null) {
$diskOffering = null;
}
$sharedIp = $farmRole->GetSetting(Entity\FarmRoleSetting::CLOUDSTACK_SHARED_IP_ID);
$networkType = $farmRole->GetSetting(Entity\FarmRoleSetting::CLOUDSTACK_NETWORK_TYPE);
$networkId = $farmRole->GetSetting(Entity\FarmRoleSetting::CLOUDSTACK_NETWORK_ID);
$useStaticNat = $farmRole->GetSetting(Entity\FarmRoleSetting::CLOUDSTACK_USE_STATIC_NAT);
$roleName = $farmRole->GetRoleObject()->name;
$osType = $farmRole->GetRoleObject()->getOs()->family == 'windows' ? 'windows' : 'linux';
} else {
$launchOptions->userData = '';
$roleName = 'TemporaryScalrServer' . rand(100, 999);
$osType = 'linux';
}
$launchOptions->architecture = 'x86_64';
\Scalr::getContainer()->logger("CloudStack")->warn(new FarmLogMessage($DBServer, "[ServerLaunch] Network ID: {$networkId}, NetworkType: {$networkType}, SharedIp: {$sharedIp}"));
if (!$sharedIp && !$useStaticNat && $networkId != 'SCALR_MANUAL') {
if ($networkId && !$networkType) {
foreach ($cs->network->describe(array('id' => $networkId)) as $network) {
if ($network->id == $networkId) {
$farmRole->SetSetting(Entity\FarmRoleSetting::CLOUDSTACK_NETWORK_TYPE, $network->type, Entity\FarmRoleSetting::TYPE_LCL);
$networkType = $network->type;
\Scalr::getContainer()->logger("CloudStack")->warn(new FarmLogMessage($DBServer, "[ServerLaunch] Network found. Type: {$networkType}"));
}
}
}
if ($networkId && ($networkType == 'Virtual' || $networkType == 'Isolated') || !$networkType) {
$sharedIpId = $environment->keychain($DBServer->platform)->properties[Entity\CloudCredentialsProperty::CLOUDSTACK_SHARED_IP_ID . ".{$launchOptions->cloudLocation}"];
$sharedIpFound = false;
if ($sharedIpId) {
try {
$requestObject = new ListIpAddressesData();
$requestObject->id = $sharedIpId;
$info = $cs->listPublicIpAddresses($requestObject);
} catch (Exception $e) {
\Scalr::getContainer()->logger('CLOUDSTACK')->error("SHARED IP CHECK: {$e->getMessage()}");
}
if (!empty($info[0])) {
$sharedIpFound = true;
\Scalr::getContainer()->logger('CLOUDSTACK')->error("SHARED IP CHECK: " . json_encode($info));
}
}
$config = \Scalr::getContainer()->config;
$instancesConnectionPolicy = $config->defined("scalr.{$this->platform}.instances_connection_policy") ? $config("scalr.{$this->platform}.instances_connection_policy") : null;
if ($instancesConnectionPolicy === null) {
$instancesConnectionPolicy = $config('scalr.instances_connection_policy');
}
\Scalr::getContainer()->logger("CloudStack")->warn(new FarmLogMessage($DBServer, "[ServerLaunch] Shared IP ID: {$sharedIpId}"));
if ((!$sharedIpId || !$sharedIpFound) && $instancesConnectionPolicy != 'local') {
\Scalr::getContainer()->logger('CLOUDSTACK')->error("No shared IP. Generating new one");
$requestObject = new AssociateIpAddressData();
$requestObject->zoneid = $launchOptions->cloudLocation;
if ($networkId) {
$requestObject->networkid = $networkId;
}
$ipResult = $cs->associateIpAddress($requestObject);
$ipId = $ipResult->id;
\Scalr::getContainer()->logger('CLOUDSTACK')->error("New IP allocated: {$ipId}");
if ($ipId) {
while (true) {
$requestObject = new ListIpAddressesData();
$requestObject->id = $ipId;
$ipInfo = $cs->listPublicIpAddresses($requestObject);
$ipInfo = !empty($ipInfo[0]) ? $ipInfo[0] : null;
if (!$ipInfo) {
throw new Exception("Cannot allocate IP address: listPublicIpAddresses -> failed");
}
if ($ipInfo->state == 'Allocated') {
$environment->keychain($DBServer->platform)->properties->saveSettings([Entity\CloudCredentialsProperty::CLOUDSTACK_SHARED_IP_ID . ".{$launchOptions->cloudLocation}" => $ipId, Entity\CloudCredentialsProperty::CLOUDSTACK_SHARED_IP . ".{$launchOptions->cloudLocation}" => $ipInfo->ipaddress, Entity\CloudCredentialsProperty::CLOUDSTACK_SHARED_IP_INFO . ".{$launchOptions->cloudLocation}" => serialize($ipInfo)]);
$sharedIpId = $ipId;
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");
}
}
}
}
if ($DBServer->status == SERVER_STATUS::TEMPORARY) {
$keyName = "SCALR-ROLESBUILDER-" . SCALR_ID;
$farmId = NULL;
} else {
$keyName = "FARM-{$DBServer->farmId}-" . SCALR_ID;
$farmId = $DBServer->farmId;
}
//
$sgs = null;
try {
$zones = $cs->zone->describe(['name' => $launchOptions->cloudLocation]);
$zoneSecurityGroupsEnabled = 1;
if ($zones[0]) {
if (isset($zones[0]->securitygroupsenabled)) {
$zoneSecurityGroupsEnabled = (int) $zones[0]->securitygroupsenabled;
}
}
$features = (array) $cs->listCapabilities();
if ($features['securitygroupsenabled'] && $zoneSecurityGroupsEnabled == 1) {
$sgs = $this->GetServerSecurityGroupsList($DBServer, $cs, $governance);
}
} catch (Exception $e) {
\Scalr::getContainer()->logger("CloudStack")->error(new FarmLogMessage($DBServer, "Unable to get list of securoty groups: {$e->getMessage()}"));
}
$sshKey = new SshKey();
try {
if (!$sshKey->loadGlobalByName($DBServer->envId, $this->platform, "", $keyName)) {
$result = $cs->sshKeyPair->create(array('name' => $keyName));
if (!empty($result->privatekey)) {
$sshKey->farmId = $farmId;
$sshKey->envId = $DBServer->envId;
$sshKey->type = SshKey::TYPE_GLOBAL;
$sshKey->platform = $this->platform;
$sshKey->cloudLocation = "";
//$launchOptions->cloudLocation;
$sshKey->cloudKeyName = $keyName;
$sshKey->privateKey = $result->privatekey;
$sshKey->publicKey = $sshKey->generatePublicKey();
$sshKey->save();
}
}
} catch (Exception $e) {
\Scalr::getContainer()->logger("CloudStack")->error(new FarmLogMessage($DBServer, "Unable to generate keypair: {$e->getMessage()}"));
}
$vResult = $cs->instance->deploy(['serviceofferingid' => $launchOptions->serverType, 'templateid' => $launchOptions->imageId, 'zoneid' => $launchOptions->cloudLocation, 'diskofferingid' => $diskOffering, 'displayname' => $DBServer->serverId, 'group' => $roleName, 'keypair' => $keyName, 'networkids' => $networkId != 'SCALR_MANUAL' ? $networkId : null, 'size' => $size, 'userdata' => base64_encode($launchOptions->userData), 'securitygroupids' => !empty($sgs) ? implode(",", $sgs) : null]);
if (!empty($vResult->id)) {
$instanceTypeInfo = $this->getInstanceType($launchOptions->serverType, $environment, $launchOptions->cloudLocation);
/* @var $instanceTypeInfo CloudInstanceType */
$DBServer->SetProperties([CLOUDSTACK_SERVER_PROPERTIES::SERVER_ID => $vResult->id, CLOUDSTACK_SERVER_PROPERTIES::CLOUD_LOCATION => $launchOptions->cloudLocation, CLOUDSTACK_SERVER_PROPERTIES::LAUNCH_JOB_ID => $vResult->jobid, SERVER_PROPERTIES::ARCHITECTURE => $launchOptions->architecture, SERVER_PROPERTIES::INFO_INSTANCE_VCPUS => $instanceTypeInfo ? $instanceTypeInfo->vcpus : null]);
$DBServer->cloudLocation = $launchOptions->cloudLocation;
$DBServer->imageId = $launchOptions->imageId;
$params = ['type' => $launchOptions->serverType];
if ($instanceTypeInfo) {
$params['instanceTypeName'] = $instanceTypeInfo->name;
}
$DBServer->setOsType($osType);
$DBServer->update($params);
//We set/update server history here
$DBServer->getServerHistory()->update(['cloudServerId' => $vResult->id]);
return $DBServer;
} else {
throw new Exception(sprintf("Cannot launch new instance: %s", $vResult->errortext));
}
}