public function LaunchServer(DBServer $DBServer, \Scalr_Server_LaunchOptions $launchOptions = null)
{
$config = \Scalr::getContainer()->config;
$environment = $DBServer->GetEnvironmentObject();
$governance = new \Scalr_Governance($environment->id);
if (!$launchOptions) {
$launchOptions = new \Scalr_Server_LaunchOptions();
$DBRole = $DBServer->GetFarmRoleObject()->GetRoleObject();
$launchOptions->imageId = $DBRole->__getNewRoleObject()->getImage($this->platform, $DBServer->GetCloudLocation())->imageId;
$launchOptions->serverType = $DBServer->GetFarmRoleObject()->GetSetting(Entity\FarmRoleSetting::INSTANCE_TYPE);
$launchOptions->cloudLocation = $DBServer->GetFarmRoleObject()->CloudLocation;
$launchOptions->userData = $DBServer->GetCloudUserData();
$launchOptions->userData['region'] = $launchOptions->cloudLocation;
$launchOptions->userData['platform'] = 'openstack';
$networks = json_decode($DBServer->GetFarmRoleObject()->GetSetting(Entity\FarmRoleSetting::OPENSTACK_NETWORKS));
$gevernanceNetworks = $governance->getValue($this->platform, 'openstack.networks');
if (count($networks) == 0 && !empty($gevernanceNetworks)) {
$networks = $gevernanceNetworks[$launchOptions->cloudLocation];
}
foreach ($launchOptions->userData as $k => $v) {
if (!$v) {
unset($launchOptions->userData[$k]);
}
}
$launchOptions->architecture = 'x86_64';
$isWindows = $DBServer->osType == 'windows' || $DBRole->getOs()->family == 'windows';
if ($DBServer->GetFarmRoleObject()->GetSetting('openstack.boot_from_volume') == 1) {
$deviceMapping = new \stdClass();
$deviceMapping->device_name = 'vda';
$deviceMapping->source_type = 'image';
$deviceMapping->destination_type = 'volume';
$deviceMapping->delete_on_termination = true;
$deviceMapping->guest_format = null;
$deviceMapping->volume_size = 10;
$deviceMapping->uuid = $launchOptions->imageId;
$deviceMapping->boot_index = 0;
}
$customUserData = $DBServer->GetFarmRoleObject()->GetSetting('base.custom_user_data');
$serverNameFormat = $governance->getValue($DBServer->platform, \Scalr_Governance::OPENSTACK_INSTANCE_NAME_FORMAT);
if (!$serverNameFormat) {
$serverNameFormat = $DBServer->GetFarmRoleObject()->GetSetting(\Scalr_Role_Behavior::ROLE_INSTANCE_NAME_FORMAT);
}
// Availability zone
$launchOptions->availZone = $this->GetServerAvailZone($DBServer, $this->getOsClient($environment, $launchOptions->cloudLocation), $launchOptions);
} else {
$launchOptions->availZone = null;
$launchOptions->userData = array();
$customUserData = false;
$networks = array();
$isWindows = $DBServer->osType == 'windows';
$deviceMapping = null;
$serverNameFormat = null;
}
$extProperties = array();
$client = $this->getOsClient($environment, $launchOptions->cloudLocation);
// Prepare user data
$u_data = "";
foreach ($launchOptions->userData as $k => $v) {
$u_data .= "{$k}={$v};";
}
$u_data = trim($u_data, ";");
if ($customUserData) {
$repos = $DBServer->getScalarizrRepository();
$extProperties["user_data"] = base64_encode(str_replace(array('{SCALR_USER_DATA}', '{RPM_REPO_URL}', '{DEB_REPO_URL}'), array($u_data, $repos['rpm_repo_url'], $repos['deb_repo_url']), $customUserData));
}
$personality = new PersonalityList();
if ($isWindows) {
$personality->append(new Personality('C:\\Program Files\\Scalarizr\\etc\\private.d\\.user-data', base64_encode($u_data)));
} else {
$personality->append(new Personality('/etc/scalr/private.d/.user-data', base64_encode($u_data)));
}
/* @var $ccProps SettingsCollection */
$ccProps = $environment->keychain($this->platform)->properties;
//Check SecurityGroups
$securityGroupsEnabled = $ccProps[Entity\CloudCredentialsProperty::OPENSTACK_EXT_SECURITYGROUPS_ENABLED];
$extProperties['security_groups'] = array();
if ($securityGroupsEnabled) {
$securityGroups = $this->GetServerSecurityGroupsList($DBServer, $client, $governance);
foreach ($securityGroups as $sg) {
$itm = new \stdClass();
$itm->name = $sg;
$extProperties['security_groups'][] = $itm;
}
}
if ($launchOptions->availZone) {
$extProperties['availability_zone'] = $launchOptions->availZone;
}
if ($deviceMapping) {
$extProperties['block_device_mapping_v2'][] = $deviceMapping;
}
//Check key-pairs
$keyPairsEnabled = $ccProps[Entity\CloudCredentialsProperty::OPENSTACK_EXT_KEYPAIRS_ENABLED];
if ($keyPairsEnabled === null || $keyPairsEnabled === false) {
if ($client->servers->isExtensionSupported(ServersExtension::EXT_KEYPAIRS)) {
$keyPairsEnabled = 1;
} else {
$keyPairsEnabled = 0;
}
$ccProps->saveSettings([Entity\CloudCredentialsProperty::OPENSTACK_EXT_KEYPAIRS_ENABLED => $keyPairsEnabled]);
}
//Check config-drive
$configDriveEnabled = $ccProps[Entity\CloudCredentialsProperty::OPENSTACK_EXT_CONFIG_DRIVE_ENABLED];
if ($configDriveEnabled === null || $configDriveEnabled === false) {
if ($client->servers->isExtensionSupported(ServersExtension::EXT_CONFIG_DRIVE)) {
$configDriveEnabled = 1;
} else {
$configDriveEnabled = 0;
}
$ccProps->saveSettings([Entity\CloudCredentialsProperty::OPENSTACK_EXT_CONFIG_DRIVE_ENABLED => $configDriveEnabled]);
}
$extProperties['config_drive'] = $configDriveEnabled;
if ($keyPairsEnabled) {
if ($DBServer->status == \SERVER_STATUS::TEMPORARY) {
$keyName = "SCALR-ROLESBUILDER-" . SCALR_ID;
$farmId = NULL;
} else {
$keyName = "FARM-{$DBServer->farmId}-" . SCALR_ID;
$farmId = $DBServer->farmId;
}
$sshKey = (new SshKey())->loadGlobalByName($DBServer->envId, \SERVER_PLATFORMS::OPENSTACK, $launchOptions->cloudLocation, $keyName);
if (!$sshKey && !($sshKey = (new SshKey())->loadGlobalByName($DBServer->envId, $DBServer->platform, $launchOptions->cloudLocation, $keyName))) {
$result = $client->servers->createKeypair($keyName);
if ($result->private_key) {
$sshKey = new SshKey();
$sshKey->farmId = $farmId;
$sshKey->envId = $DBServer->envId;
$sshKey->type = SshKey::TYPE_GLOBAL;
$sshKey->platform = $DBServer->platform;
$sshKey->cloudLocation = $launchOptions->cloudLocation;
$sshKey->cloudKeyName = $keyName;
$sshKey->privateKey = $result->private_key;
$sshKey->publicKey = $result->public_key;
$sshKey->save();
}
}
$extProperties['key_name'] = $keyName;
}
//TODO: newtorks
$networksList = new NetworkList();
foreach ((array) $networks as $network) {
if ($network) {
$networksList->append(new Network($network));
}
}
$osUserData = null;
$osPersonality = null;
$userDataMethod = $config->defined("scalr.{$this->platform}.user_data_method") ? $config("scalr.{$this->platform}.user_data_method") : null;
if (!$userDataMethod || $userDataMethod == 'both' || $userDataMethod == 'personality') {
$osPersonality = $personality;
}
if (!$userDataMethod || $userDataMethod == 'both' || $userDataMethod == 'meta-data' || $isWindows) {
$osUserData = $launchOptions->userData;
}
$serverName = $serverNameFormat ? $DBServer->applyGlobalVarsToValue($serverNameFormat) : $DBServer->serverId;
try {
$result = $client->servers->createServer($serverName, $launchOptions->serverType, $launchOptions->imageId, null, $osUserData, $osPersonality, $networksList, $extProperties);
$instanceTypeInfo = $this->getInstanceType($launchOptions->serverType, $environment, $launchOptions->cloudLocation);
/* @var $instanceTypeInfo CloudInstanceType */
$DBServer->SetProperties([\OPENSTACK_SERVER_PROPERTIES::SERVER_ID => $result->id, \OPENSTACK_SERVER_PROPERTIES::IMAGE_ID => $launchOptions->imageId, \OPENSTACK_SERVER_PROPERTIES::ADMIN_PASS => $launchOptions->userData['vzc.adminpassword'] ? $launchOptions->userData['vzc.adminpassword'] : $result->adminPass, \OPENSTACK_SERVER_PROPERTIES::NAME => $DBServer->serverId, \SERVER_PROPERTIES::ARCHITECTURE => $launchOptions->architecture, \OPENSTACK_SERVER_PROPERTIES::CLOUD_LOCATION => $launchOptions->cloudLocation, \OPENSTACK_SERVER_PROPERTIES::CLOUD_LOCATION_ZONE => $launchOptions->availZone, \SERVER_PROPERTIES::SYSTEM_USER_DATA_METHOD => $userDataMethod, \SERVER_PROPERTIES::INFO_INSTANCE_VCPUS => $instanceTypeInfo ? $instanceTypeInfo->vcpus : null]);
if ($DBServer->farmRoleId) {
$ipPool = $DBServer->GetFarmRoleObject()->GetSetting(Entity\FarmRoleSetting::OPENSTACK_IP_POOL);
if ($ipPool) {
$DBServer->SetProperty(\SERVER_PROPERTIES::SYSTEM_IGNORE_INBOUND_MESSAGES, 1);
}
}
$params = ['type' => $launchOptions->serverType];
if ($instanceTypeInfo) {
$params['instanceTypeName'] = $instanceTypeInfo->name;
}
$DBServer->setOsType($isWindows ? 'windows' : 'linux');
$DBServer->cloudLocation = $launchOptions->cloudLocation;
$DBServer->cloudLocationZone = $launchOptions->availZone;
$DBServer->update($params);
$DBServer->imageId = $launchOptions->imageId;
// we set server history here
$DBServer->getServerHistory()->update(['cloudServerId' => $result->id]);
return $DBServer;
} catch (\Exception $e) {
if (stripos($e->getMessage(), 'Invalid key_name provided')) {
if (isset($sshKey)) {
$sshKey->delete();
}
throw new \Exception(sprintf(_("Cannot launch new instance: KeyPair was removed from cloud. Re-generating it."), $e->getMessage()));
}
throw new \Exception(sprintf(_("Cannot launch new instance. %s"), $e->getMessage()));
}
}