/** * @return Scalr_Net_Ssh2_Client * Enter description here ... */ public function GetSsh2Client() { $ssh2Client = new Scalr_Net_Ssh2_Client(); switch ($this->platform) { case SERVER_PLATFORMS::RACKSPACENG_UK: case SERVER_PLATFORMS::RACKSPACENG_US: $ssh2Client->addPassword('root', $this->GetProperty(OPENSTACK_SERVER_PROPERTIES::ADMIN_PASS)); break; case SERVER_PLATFORMS::RACKSPACE: $ssh2Client->addPassword('root', $this->GetProperty(RACKSPACE_SERVER_PROPERTIES::ADMIN_PASS)); break; case SERVER_PLATFORMS::GCE: $userName = '******'; if ($this->status == SERVER_STATUS::TEMPORARY) { $keyName = 'SCALR-ROLESBUILDER-' . SCALR_ID; } else { $keyName = "FARM-{$this->farmId}-" . SCALR_ID; } try { $key = (new SshKey())->loadGlobalByName($this->envId, SERVER_PLATFORMS::GCE, "", $keyName); if (!$key) { throw new Exception(_("There is no SSH key for server: {$this->serverId}")); } } catch (Exception $e) { throw new Exception("Cannot init SshKey object: {$e->getMessage()}"); } $priv_key_file = tempnam("/tmp", "GCEPK"); @file_put_contents($priv_key_file, $key->privateKey); $this->tmpFiles[] = $priv_key_file; $pub_key_file = tempnam("/tmp", "GCEK"); @file_put_contents($pub_key_file, $key->publicKey); $this->tmpFiles[] = $pub_key_file; $ssh2Client->addPubkey($userName, $pub_key_file, $priv_key_file); break; case SERVER_PLATFORMS::IDCF: case SERVER_PLATFORMS::EC2: $userName = '******'; $skipKeyValidation = false; // Temporary server for role builder $sshKey = new SshKey(); if ($this->status == SERVER_STATUS::TEMPORARY) { $keyName = "SCALR-ROLESBUILDER-" . SCALR_ID . "-{$this->envId}"; if (!$sshKey->loadGlobalByName($this->envId, $this->platform, $this->GetCloudLocation(), $keyName)) { $keyName = "SCALR-ROLESBUILDER-" . SCALR_ID; } try { $bundleTaskId = $this->GetProperty(\SERVER_PROPERTIES::SZR_IMPORTING_BUNDLE_TASK_ID); $bundleTask = BundleTask::LoadById($bundleTaskId); if ($bundleTask->osFamily == 'amazon') { $userName = '******'; } } catch (Exception $e) { } } else { $keyName = "FARM-{$this->farmId}-" . SCALR_ID; $oldKeyName = "FARM-{$this->farmId}"; $key = $sshKey->loadGlobalByName($this->envId, $this->platform, $this->GetCloudLocation(), $oldKeyName); if ($key) { $keyName = $oldKeyName; $skipKeyValidation = true; } } if (!$skipKeyValidation) { try { $key = $sshKey->loadGlobalByName($this->envId, $this->platform, $this->GetCloudLocation(), $keyName); if (!$key) { throw new Exception(sprintf('Could not find SSH Key for server "%s" with name:"%s", cloud-location:"%s", platform:"%s", environment:"%d".', $this->serverId, $keyName, $this->GetCloudLocation(), $this->platform, $this->envId)); } } catch (Exception $e) { throw new Exception("Cannot init SshKey object: {$e->getMessage()}"); } } $priv_key_file = tempnam("/tmp", "AWSK"); @file_put_contents($priv_key_file, $key->privateKey); $this->tmpFiles[] = $priv_key_file; $pub_key_file = tempnam("/tmp", "AWSK"); $this->tmpFiles[] = $pub_key_file; $pubKey = $key->publicKey; if (!stristr($pubKey, $keyName)) { $pubKey .= " {$keyName}"; } @file_put_contents($pub_key_file, $pubKey); $ssh2Client->addPubkey($userName, $pub_key_file, $priv_key_file); break; } return $ssh2Client; }
/** * @param string $query * @param string $sshKeyId * @param int $farmId * @param string $platform * @param string $cloudLocation * @param JsonData $sort * @param int $start * @param int $limit */ public function xListAction($query = null, $sshKeyId = null, $farmId = null, $platform = null, $cloudLocation = null, JsonData $sort, $start = 0, $limit = 20) { $criteria = [['envId' => $this->getEnvironmentId()]]; if ($this->request->isAllowed(Acl::RESOURCE_FARMS, Acl::PERM_FARMS_SERVERS)) { if (!$this->request->isAllowed(Acl::RESOURCE_IMAGES_ENVIRONMENT, Acl::PERM_IMAGES_ENVIRONMENT_MANAGE)) { $criteria[] = ['farmId' => ['$ne' => NULL]]; } } else { $farmSql = "SELECT id FROM farms WHERE env_id = ?"; $farmArgs = [$this->getEnvironmentId()]; list($farmSql, $farmArgs) = $this->request->prepareFarmSqlQuery($farmSql, $farmArgs, '', Acl::PERM_FARMS_SERVERS); $farms = $this->db->GetCol($farmSql, $farmArgs); if ($this->request->isAllowed(Acl::RESOURCE_IMAGES_ENVIRONMENT, Acl::PERM_IMAGES_ENVIRONMENT_MANAGE)) { $criteria[] = ['$or' => [['farmId' => NULL], ['farmId' => ['$in' => $farms]]]]; } else { if (count($farms)) { $criteria[] = ['farmId' => ['$in' => $farms]]; } else { // user doesn't have access to any farm. try to find better solution $criteria[] = ['farmId' => -1]; } } } if ($sshKeyId) { $criteria[] = ['id' => $sshKeyId]; } if ($farmId) { $criteria[] = ['farmId' => $farmId]; } if ($query) { $querySql = '%' . $query . '%'; $criteria[] = ['$or' => [['cloudKeyName' => ['$like' => $querySql]]]]; } if ($platform) { $criteria[] = ['platform' => $platform]; if ($cloudLocation) { $criteria[] = ['cloudLocation' => $cloudLocation]; } } $result = SshKey::find($criteria, null, \Scalr\UI\Utils::convertOrder($sort, ['id' => true], ['id', 'cloudKeyName', 'platform', 'cloudLocation']), $limit, $start, true); $data = []; foreach ($result as $key) { /* @var SshKey $key */ $data[] = $this->getSshKeyObject($key); } $this->response->data(['total' => $result->totalNumber, 'data' => $data]); }
public function LaunchServer(DBServer $DBServer, \Scalr_Server_LaunchOptions $launchOptions = null) { $environment = $DBServer->GetEnvironmentObject(); $ccProps = $environment->keychain(SERVER_PLATFORMS::GCE)->properties; $governance = new \Scalr_Governance($environment->id); $rootDeviceSettings = null; $ssdDisks = array(); $scopes = ["https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/compute", "https://www.googleapis.com/auth/devstorage.full_control"]; if (!$launchOptions) { $launchOptions = new \Scalr_Server_LaunchOptions(); $DBRole = $DBServer->GetFarmRoleObject()->GetRoleObject(); $launchOptions->imageId = $DBRole->__getNewRoleObject()->getImage(\SERVER_PLATFORMS::GCE, $DBServer->GetProperty(\GCE_SERVER_PROPERTIES::CLOUD_LOCATION))->imageId; $launchOptions->serverType = $DBServer->GetFarmRoleObject()->GetSetting(Entity\FarmRoleSetting::INSTANCE_TYPE); $launchOptions->cloudLocation = $DBServer->GetFarmRoleObject()->CloudLocation; $userData = $DBServer->GetCloudUserData(); $launchOptions->architecture = 'x86_64'; $networkName = $DBServer->GetFarmRoleObject()->GetSetting(Entity\FarmRoleSetting::GCE_NETWORK); $subnet = $DBServer->GetFarmRoleObject()->GetSetting(Entity\FarmRoleSetting::GCE_SUBNET); $onHostMaintenance = $DBServer->GetFarmRoleObject()->GetSetting(Entity\FarmRoleSetting::GCE_ON_HOST_MAINTENANCE); $osType = $DBRole->getOs()->family == 'windows' ? 'windows' : 'linux'; $rootDevice = json_decode($DBServer->GetFarmRoleObject()->GetSetting(\Scalr_Role_Behavior::ROLE_BASE_ROOT_DEVICE_CONFIG), true); if ($rootDevice && $rootDevice['settings']) { $rootDeviceSettings = $rootDevice['settings']; } $storage = new FarmRoleStorage($DBServer->GetFarmRoleObject()); $volumes = $storage->getVolumesConfigs($DBServer); if (!empty($volumes)) { foreach ($volumes as $volume) { if ($volume->type == FarmRoleStorageConfig::TYPE_GCE_EPHEMERAL) { array_push($ssdDisks, $volume); } } } if ($governance->isEnabled(\Scalr_Governance::CATEGORY_GENERAL, \Scalr_Governance::GENERAL_HOSTNAME_FORMAT)) { $hostNameFormat = $governance->getValue(\Scalr_Governance::CATEGORY_GENERAL, \Scalr_Governance::GENERAL_HOSTNAME_FORMAT); } else { $hostNameFormat = $DBServer->GetFarmRoleObject()->GetSetting(\Scalr_Role_Behavior::ROLE_BASE_HOSTNAME_FORMAT); } $hostname = !empty($hostNameFormat) ? $DBServer->applyGlobalVarsToValue($hostNameFormat) : ''; if ($hostname != '') { $DBServer->SetProperty(\Scalr_Role_Behavior::SERVER_BASE_HOSTNAME, $hostname); } $userScopes = json_decode($DBServer->GetFarmRoleObject()->GetSetting(Entity\FarmRoleSetting::GCE_INSTANCE_PERMISSIONS)); if (!empty($userScopes) && is_array($userScopes)) { $scopes = array_merge($scopes, $userScopes); } } else { $userData = array(); $networkName = 'default'; $osType = 'linux'; $hostname = ''; } if (!$onHostMaintenance) { $onHostMaintenance = 'MIGRATE'; } if ($DBServer->status == \SERVER_STATUS::TEMPORARY) { $keyName = "SCALR-ROLESBUILDER-" . SCALR_ID; } else { $keyName = "FARM-{$DBServer->farmId}-" . SCALR_ID; } $sshKey = (new SshKey())->loadGlobalByName($DBServer->envId, \SERVER_PLATFORMS::GCE, "", $keyName); if (!$sshKey) { $sshKey = new SshKey(); $keys = $sshKey->generateKeypair(); if ($keys['public']) { $sshKey->farmId = $DBServer->farmId; $sshKey->envId = $DBServer->envId; $sshKey->type = SshKey::TYPE_GLOBAL; $sshKey->platform = \SERVER_PLATFORMS::GCE; $sshKey->cloudLocation = ""; $sshKey->cloudKeyName = $keyName; $sshKey->save(); $publicKey = $keys['public']; } else { throw new Exception("Scalr unable to generate ssh keypair"); } } else { $publicKey = $sshKey->publicKey; } $gce = $this->getClient($environment); $projectId = $ccProps[Entity\CloudCredentialsProperty::GCE_PROJECT_ID]; // Check firewall $firewalls = $gce->firewalls->listFirewalls($projectId); $firewallFound = false; foreach ($firewalls->getItems() as $f) { if ($f->getName() == 'scalr-system') { $firewallFound = true; break; } } // Create scalr firewall if (!$firewallFound) { $firewall = new \Google_Service_Compute_Firewall(); $firewall->setName('scalr-system'); $firewall->setNetwork($this->getObjectUrl($networkName, 'networks', $projectId)); //Get scalr IP-pool IP list and set source ranges $firewall->setSourceRanges(\Scalr::config('scalr.aws.ip_pool')); // Set ports $tcp = new \Google_Service_Compute_FirewallAllowed(); $tcp->setIPProtocol('tcp'); $tcp->setPorts(array('1-65535')); $udp = new \Google_Service_Compute_FirewallAllowed(); $udp->setIPProtocol('udp'); $udp->setPorts(array('1-65535')); $firewall->setAllowed(array($tcp, $udp)); // Set target tags $firewall->setTargetTags(array('scalr')); $gce->firewalls->insert($projectId, $firewall); } $instance = new \Google_Service_Compute_Instance(); $instance->setKind("compute#instance"); // Set scheduling $scheduling = new \Google_Service_Compute_Scheduling(); $scheduling->setAutomaticRestart(true); $scheduling->setOnHostMaintenance($onHostMaintenance); $instance->setScheduling($scheduling); $accessConfig = new \Google_Service_Compute_AccessConfig(); $accessConfig->setName("External NAT"); $accessConfig->setType("ONE_TO_ONE_NAT"); $network = new \Google_Service_Compute_NetworkInterface(); $network->setNetwork($this->getObjectUrl($networkName, 'networks', $projectId)); if (!empty($subnet)) { $network->setSubnetwork($this->getObjectUrl($subnet, 'subnetworks', $projectId, $DBServer->GetFarmRoleObject()->GetSetting(Entity\FarmRoleSetting::GCE_REGION))); } $network->setAccessConfigs(array($accessConfig)); $instance->setNetworkInterfaces(array($network)); $serviceAccount = new \Google_Service_Compute_ServiceAccount(); $serviceAccount->setEmail("default"); $serviceAccount->setScopes($scopes); $instance->setServiceAccounts(array($serviceAccount)); if ($launchOptions->cloudLocation != 'x-scalr-custom') { $availZone = $launchOptions->cloudLocation; } else { $location = $DBServer->GetFarmRoleObject()->GetSetting(Entity\FarmRoleSetting::GCE_CLOUD_LOCATION); $availZones = array(); if (stristr($location, "x-scalr-custom")) { $zones = explode("=", $location); foreach (explode(":", $zones[1]) as $zone) { if ($zone != "") { array_push($availZones, $zone); } } } sort($availZones); $availZones = array_reverse($availZones); $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(\GCE_SERVER_PROPERTIES::CLOUD_LOCATION)]++; } } $sCount = 1000000; foreach ($availZones as $zone) { if ((int) $availZoneDistribution[$zone] <= $sCount) { $sCount = (int) $availZoneDistribution[$zone]; $availZone = $zone; } } $aZones = implode(",", $availZones); // Available zones $dZones = ""; // Zones distribution foreach ($availZoneDistribution as $zone => $num) { $dZones .= "({$zone}:{$num})"; } } $instance->setZone($this->getObjectUrl($availZone, 'zones', $projectId)); $instance->setMachineType($this->getObjectUrl($launchOptions->serverType, 'machineTypes', $projectId, $availZone)); //Create root disk $image = $this->getObjectUrl($launchOptions->imageId, 'images', $projectId); $disks = array(); $diskName = "root-{$DBServer->serverId}"; $initializeParams = new \Google_Service_Compute_AttachedDiskInitializeParams(); $initializeParams->sourceImage = $image; $initializeParams->diskName = $diskName; if ($rootDeviceSettings) { $initializeParams->diskType = $this->getObjectUrl($rootDeviceSettings[FarmRoleStorageConfig::SETTING_GCE_PD_TYPE] ? $rootDeviceSettings[FarmRoleStorageConfig::SETTING_GCE_PD_TYPE] : 'pd-standard', 'diskTypes', $projectId, $availZone); $initializeParams->diskSizeGb = $rootDeviceSettings[FarmRoleStorageConfig::SETTING_GCE_PD_SIZE]; } $attachedDisk = new \Google_Service_Compute_AttachedDisk(); $attachedDisk->setKind("compute#attachedDisk"); $attachedDisk->setBoot(true); $attachedDisk->setMode("READ_WRITE"); $attachedDisk->setType("PERSISTENT"); $attachedDisk->setDeviceName("root"); $attachedDisk->setAutoDelete(true); $attachedDisk->setInitializeParams($initializeParams); array_push($disks, $attachedDisk); if (count($ssdDisks) > 0) { foreach ($ssdDisks as $disk) { $attachedDisk = new \Google_Service_Compute_AttachedDisk(); $attachedDisk->setKind("compute#attachedDisk"); $attachedDisk->setBoot(false); $attachedDisk->setMode("READ_WRITE"); $attachedDisk->setType("SCRATCH"); $attachedDisk->setDeviceName(str_replace("google-", "", $disk->name)); $attachedDisk->setInterface('SCSI'); $attachedDisk->setAutoDelete(true); $initializeParams = new \Google_Service_Compute_AttachedDiskInitializeParams(); $initializeParams->diskType = $this->getObjectUrl('local-ssd', 'diskTypes', $projectId, $availZone); $attachedDisk->setInitializeParams($initializeParams); array_push($disks, $attachedDisk); } } $instance->setDisks($disks); $instance->setName($DBServer->serverId); $tags = array('scalr', "env-{$DBServer->envId}"); if ($DBServer->farmId) { $tags[] = "farm-{$DBServer->farmId}"; } if ($DBServer->farmRoleId) { $tags[] = "farmrole-{$DBServer->farmRoleId}"; } $gTags = new \Google_Service_Compute_Tags(); $gTags->setItems($tags); $instance->setTags($gTags); $metadata = new \Google_Service_Compute_Metadata(); $items = array(); // Set user data $uData = ''; foreach ($userData as $k => $v) { $uData .= "{$k}={$v};"; } $uData = trim($uData, ";"); if ($uData) { $item = new \Google_Service_Compute_MetadataItems(); $item->setKey('scalr'); $item->setValue($uData); $items[] = $item; } if ($osType == 'windows') { // Add Windows credentials $item = new \Google_Service_Compute_MetadataItems(); $item->setKey("gce-initial-windows-user"); $item->setValue("scalr"); $items[] = $item; $item = new \Google_Service_Compute_MetadataItems(); $item->setKey("gce-initial-windows-password"); $item->setValue(\Scalr::GenerateRandomKey(16) . rand(0, 9)); $items[] = $item; } else { // Add SSH Key $item = new \Google_Service_Compute_MetadataItems(); $item->setKey("sshKeys"); $item->setValue("scalr:{$publicKey}"); $items[] = $item; } //Set hostname if ($hostname != '') { $item = new \Google_Service_Compute_MetadataItems(); $item->setKey("hostname"); $item->setValue($hostname); $items[] = $item; } $metadata->setItems($items); $instance->setMetadata($metadata); try { $result = $gce->instances->insert($projectId, $availZone, $instance); } catch (Exception $e) { $json = json_decode($e->getMessage()); if (!empty($json->error->message)) { $message = $json->error->message; } else { $message = $e->getMessage(); } throw new Exception(sprintf(_("Cannot launch new instance. %s (%s, %s)"), $message, $image, $launchOptions->serverType)); } if ($result->id) { $instanceTypeInfo = $this->getInstanceType($launchOptions->serverType, $environment, $availZone); /* @var $instanceTypeInfo CloudInstanceType */ $DBServer->SetProperties([\GCE_SERVER_PROPERTIES::PROVISIONING_OP_ID => $result->name, \GCE_SERVER_PROPERTIES::SERVER_NAME => $DBServer->serverId, \GCE_SERVER_PROPERTIES::CLOUD_LOCATION => $availZone, \GCE_SERVER_PROPERTIES::CLOUD_LOCATION_ZONE => $availZone, \SERVER_PROPERTIES::ARCHITECTURE => $launchOptions->architecture, 'debug.region' => $result->region, 'debug.zone' => $result->zone, \SERVER_PROPERTIES::INFO_INSTANCE_VCPUS => $instanceTypeInfo ? $instanceTypeInfo->vcpus : null]); $DBServer->setOsType($osType); $DBServer->cloudLocation = $availZone; $DBServer->cloudLocationZone = $availZone; $DBServer->imageId = $launchOptions->imageId; $DBServer->update(['type' => $launchOptions->serverType, 'instanceTypeName' => $launchOptions->serverType]); // we set server history here $DBServer->getServerHistory()->update(['cloudServerId' => $DBServer->serverId]); return $DBServer; } else { throw new Exception(sprintf(_("Cannot launch new instance. %s (%s, %s)"), serialize($result), $launchOptions->imageId, $launchOptions->serverType)); } }
/** * {@inheritdoc} * @see \Scalr\Modules\PlatformModuleInterface::LaunchServer() */ 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::CLOUDSTACK_SERVICE_OFFERING_ID); $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->farmId, "[ServerLaunch] Network ID: {$networkId}, NetworkType: {$networkType}, SharedIp: {$sharedIp}", $DBServer->serverId)); 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->farmId, "[ServerLaunch] Network found. Type: {$networkType}", $DBServer->serverId)); } } } if ($networkId && ($networkType == 'Virtual' || $networkType == 'Isolated') || !$networkType) { $sharedIpId = $environment->cloudCredentials($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->farmId, "[ServerLaunch] Shared IP ID: {$sharedIpId}", $DBServer->serverId)); 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->cloudCredentials($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->farmId, "Unable to get list of securoty groups: {$e->getMessage()}", $DBServer->serverId)); } $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->farmId, "Unable to generate keypair: {$e->getMessage()}", $DBServer->serverId)); } $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(); return $DBServer; } else { throw new \Exception(sprintf("Cannot launch new instance: %s", $vResult->errortext)); } }
/** * {@inheritdoc} * @see \Scalr\Modules\PlatformModuleInterface::LaunchServer() */ 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::OPENSTACK_FLAVOR_ID); $launchOptions->cloudLocation = $DBServer->GetFarmRoleObject()->CloudLocation; $launchOptions->userData = $DBServer->GetCloudUserData(); $launchOptions->userData['region'] = $launchOptions->cloudLocation; $launchOptions->userData['platform'] = 'openstack'; $launchOptions->networks = @json_decode($DBServer->GetFarmRoleObject()->GetSetting(Entity\FarmRoleSetting::OPENSTACK_NETWORKS)); $gevernanceNetworks = $governance->getValue($this->platform, 'openstack.networks'); if (count($launchOptions->networks) == 0 && $gevernanceNetworks) { $launchOptions->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; if (!$launchOptions->networks) { $launchOptions->networks = array(); } $isWindows = $DBServer->osType == 'windows'; } $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->cloudCredentials($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 $networks = new NetworkList(); foreach ((array) $launchOptions->networks as $network) { if ($network) { $networks->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, $networks, $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(); return $DBServer; } catch (\Exception $e) { if (stripos($e->getMessage(), 'Invalid key_name provided')) { $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())); } }
/** * {@inheritdoc} * @see \Scalr\Modules\PlatformModuleInterface::LaunchServer() */ public function LaunchServer(DBServer $DBServer, Scalr_Server_LaunchOptions $launchOptions = null) { $runInstanceRequest = new RunInstancesRequestData(isset($launchOptions->imageId) ? $launchOptions->imageId : null, 1, 1); $environment = $DBServer->GetEnvironmentObject(); $governance = new \Scalr_Governance($DBServer->envId); $placementData = null; $noSecurityGroups = false; if (!$launchOptions) { $launchOptions = new Scalr_Server_LaunchOptions(); $dbFarmRole = $DBServer->GetFarmRoleObject(); $DBRole = $dbFarmRole->GetRoleObject(); $runInstanceRequest->setMonitoring($dbFarmRole->GetSetting(Entity\FarmRoleSetting::AWS_ENABLE_CW_MONITORING)); $image = $DBRole->__getNewRoleObject()->getImage(SERVER_PLATFORMS::EC2, $dbFarmRole->CloudLocation); $launchOptions->imageId = $image->imageId; if ($DBRole->isScalarized) { if (!$image->getImage()->isScalarized && $image->getImage()->hasCloudInit) { $useCloudInit = true; } } // Need OS Family to get block device mapping for OEL roles $launchOptions->osFamily = $image->getImage()->getOs()->family; $launchOptions->cloudLocation = $dbFarmRole->CloudLocation; $akiId = $DBServer->GetProperty(EC2_SERVER_PROPERTIES::AKIID); if (!$akiId) { $akiId = $dbFarmRole->GetSetting(Entity\FarmRoleSetting::AWS_AKI_ID); } if ($akiId) { $runInstanceRequest->kernelId = $akiId; } $ariId = $DBServer->GetProperty(EC2_SERVER_PROPERTIES::ARIID); if (!$ariId) { $ariId = $dbFarmRole->GetSetting(Entity\FarmRoleSetting::AWS_ARI_ID); } if ($ariId) { $runInstanceRequest->ramdiskId = $ariId; } $iType = $dbFarmRole->GetSetting(Entity\FarmRoleSetting::INSTANCE_TYPE); $launchOptions->serverType = $iType; // Check governance of instance types $types = $governance->getValue('ec2', Scalr_Governance::INSTANCE_TYPE); if (count($types) > 0) { if (!in_array($iType, $types)) { throw new Exception(sprintf("Instance type '%s' was prohibited to use by scalr account owner", $iType)); } } $iamProfileArn = $dbFarmRole->GetSetting(Entity\FarmRoleSetting::AWS_IAM_INSTANCE_PROFILE_ARN); if ($iamProfileArn) { $iamInstanceProfile = new IamInstanceProfileRequestData($iamProfileArn); $runInstanceRequest->setIamInstanceProfile($iamInstanceProfile); } if ($dbFarmRole->GetSetting(Entity\FarmRoleSetting::AWS_EBS_OPTIMIZED) == 1) { $runInstanceRequest->ebsOptimized = true; } else { $runInstanceRequest->ebsOptimized = false; } // Custom user-data (base.custom_user_data) $u_data = ''; foreach ($DBServer->GetCloudUserData() as $k => $v) { $u_data .= "{$k}={$v};"; } $u_data = trim($u_data, ";"); if (!empty($useCloudInit)) { $customUserData = file_get_contents(APPPATH . "/templates/services/cloud_init/config.tpl"); } else { $customUserData = $dbFarmRole->GetSetting('base.custom_user_data'); } if ($customUserData) { $repos = $DBServer->getScalarizrRepository(); $userData = str_replace(array('{SCALR_USER_DATA}', '{RPM_REPO_URL}', '{DEB_REPO_URL}'), array($u_data, $repos['rpm_repo_url'], $repos['deb_repo_url']), $customUserData); } else { $userData = $u_data; } if ($DBRole->isScalarized) { $runInstanceRequest->userData = base64_encode($userData); } $vpcId = $dbFarmRole->GetFarmObject()->GetSetting(Entity\FarmSetting::EC2_VPC_ID); if ($vpcId) { if ($DBRole->hasBehavior(ROLE_BEHAVIORS::VPC_ROUTER)) { $networkInterface = new InstanceNetworkInterfaceSetRequestData(); $networkInterface->networkInterfaceId = $dbFarmRole->GetSetting(Scalr_Role_Behavior_Router::ROLE_VPC_NID); $networkInterface->deviceIndex = 0; $networkInterface->deleteOnTermination = false; $runInstanceRequest->setNetworkInterface($networkInterface); $noSecurityGroups = true; } else { $vpcSubnetId = $dbFarmRole->GetSetting(Entity\FarmRoleSetting::AWS_VPC_SUBNET_ID); // VPC Support v2 if ($vpcSubnetId && substr($vpcSubnetId, 0, 6) != 'subnet') { $subnets = json_decode($vpcSubnetId); $servers = $DBServer->GetFarmRoleObject()->GetServersByFilter(array("status" => array(SERVER_STATUS::RUNNING, SERVER_STATUS::INIT, SERVER_STATUS::PENDING))); $subnetsDistribution = array(); foreach ($servers as $cDbServer) { if ($cDbServer->serverId != $DBServer->serverId) { $subnetsDistribution[$cDbServer->GetProperty(EC2_SERVER_PROPERTIES::SUBNET_ID)]++; } } $sCount = 1000000; foreach ($subnets as $subnet) { if ((int) $subnetsDistribution[$subnet] <= $sCount) { $sCount = (int) $subnetsDistribution[$subnet]; $selectedSubnetId = $subnet; } } } else { $vpcInternetAccess = $dbFarmRole->GetSetting(Entity\FarmRoleSetting::AWS_VPC_INTERNET_ACCESS); if (!$vpcSubnetId) { $aws = $environment->aws($launchOptions->cloudLocation); $subnet = $this->AllocateNewSubnet($aws->ec2, $vpcId, $dbFarmRole->GetSetting(Entity\FarmRoleSetting::AWS_VPC_AVAIL_ZONE), 24); try { $subnet->createTags(array(array('key' => "scalr-id", 'value' => SCALR_ID), array('key' => "scalr-sn-type", 'value' => $vpcInternetAccess), array('key' => "Name", 'value' => 'Scalr System Subnet'))); } catch (Exception $e) { } try { $routeTableId = $dbFarmRole->GetSetting(Entity\FarmRoleSetting::AWS_VPC_ROUTING_TABLE_ID); \Scalr::getContainer()->logger('VPC')->warn(new FarmLogMessage($DBServer, "Internet access: {$vpcInternetAccess}")); if (!$routeTableId) { if ($vpcInternetAccess == Scalr_Role_Behavior_Router::INTERNET_ACCESS_OUTBOUND) { $routerRole = $DBServer->GetFarmObject()->GetFarmRoleByBehavior(ROLE_BEHAVIORS::VPC_ROUTER); if (!$routerRole) { if (\Scalr::config('scalr.instances_connection_policy') != 'local') { throw new Exception("Outbound access require VPC router role in farm"); } } $networkInterfaceId = $routerRole->GetSetting(Scalr_Role_Behavior_Router::ROLE_VPC_NID); \Scalr::getContainer()->logger('EC2')->warn(new FarmLogMessage($DBServer, "Requesting outbound routing table. NID: {$networkInterfaceId}")); $routeTableId = $this->getRoutingTable($vpcInternetAccess, $aws, $networkInterfaceId, $vpcId); \Scalr::getContainer()->logger('EC2')->warn(new FarmLogMessage($DBServer, "Routing table ID: {$routeTableId}")); } elseif ($vpcInternetAccess == Scalr_Role_Behavior_Router::INTERNET_ACCESS_FULL) { $routeTableId = $this->getRoutingTable($vpcInternetAccess, $aws, null, $vpcId); } } $aws->ec2->routeTable->associate($routeTableId, $subnet->subnetId); } catch (Exception $e) { \Scalr::getContainer()->logger('EC2')->warn(new FarmLogMessage($DBServer, "Removing allocated subnet, due to routing table issues")); $aws->ec2->subnet->delete($subnet->subnetId); throw $e; } $selectedSubnetId = $subnet->subnetId; $dbFarmRole->SetSetting(Entity\FarmRoleSetting::AWS_VPC_SUBNET_ID, $selectedSubnetId, Entity\FarmRoleSetting::TYPE_LCL); } else { $selectedSubnetId = $vpcSubnetId; } } if ($selectedSubnetId) { $networkInterface = new InstanceNetworkInterfaceSetRequestData(); $networkInterface->deviceIndex = 0; $networkInterface->deleteOnTermination = true; // //Check network private or public // // We don't need public IP for private subnets $info = $this->listSubnets($environment, $launchOptions->cloudLocation, $vpcId, true, $selectedSubnetId); if ($info && $info['type'] == 'public') { $networkInterface->associatePublicIpAddress = true; } $networkInterface->subnetId = $selectedSubnetId; $staticPrivateIpsMap = $dbFarmRole->GetSetting(Entity\FarmRoleSetting::AWS_PRIVATE_IPS_MAP); if (!empty($staticPrivateIpsMap)) { $map = @json_decode($staticPrivateIpsMap, true); if (array_key_exists((int) $DBServer->index, $map)) { $networkInterface->privateIpAddress = $map[$DBServer->index]; } } $aws = $environment->aws($launchOptions->cloudLocation); $sgroups = $this->GetServerSecurityGroupsList($DBServer, $aws->ec2, $vpcId, $governance, $launchOptions->osFamily); $networkInterface->setSecurityGroupId($sgroups); $runInstanceRequest->setNetworkInterface($networkInterface); $noSecurityGroups = true; //$runInstanceRequest->subnetId = $selectedSubnetId; } else { throw new Exception("Unable to define subnetId for role in VPC"); } } } $rootDevice = json_decode($DBServer->GetFarmRoleObject()->GetSetting(\Scalr_Role_Behavior::ROLE_BASE_ROOT_DEVICE_CONFIG), true); if ($rootDevice && $rootDevice['settings']) { $rootDeviceSettings = $rootDevice['settings']; } $instanceInitiatedShutdownBehavior = $dbFarmRole->GetSetting(Entity\FarmRoleSetting::AWS_SHUTDOWN_BEHAVIOR); } else { $instanceInitiatedShutdownBehavior = null; $runInstanceRequest->userData = base64_encode(trim($launchOptions->userData)); } $aws = $environment->aws($launchOptions->cloudLocation); if (!$vpcId) { $vpcId = $this->getDefaultVpc($environment, $launchOptions->cloudLocation); } // Set AMI, AKI and ARI ids $runInstanceRequest->imageId = $launchOptions->imageId; $runInstanceRequest->instanceInitiatedShutdownBehavior = $instanceInitiatedShutdownBehavior ?: 'terminate'; if (!$noSecurityGroups) { foreach ($this->GetServerSecurityGroupsList($DBServer, $aws->ec2, $vpcId, $governance, $launchOptions->osFamily) as $sgroup) { $runInstanceRequest->appendSecurityGroupId($sgroup); } if (!$runInstanceRequest->subnetId) { // Set availability zone if (!$launchOptions->availZone) { $avail_zone = $this->GetServerAvailZone($DBServer, $aws->ec2, $launchOptions); if ($avail_zone) { $placementData = new PlacementResponseData($avail_zone); } } else { $placementData = new PlacementResponseData($launchOptions->availZone); } } } $runInstanceRequest->minCount = 1; $runInstanceRequest->maxCount = 1; // Set instance type $runInstanceRequest->instanceType = $launchOptions->serverType; if ($rootDeviceSettings) { $ebs = new EbsBlockDeviceData(array_key_exists(FarmRoleStorageConfig::SETTING_EBS_SIZE, $rootDeviceSettings) ? $rootDeviceSettings[FarmRoleStorageConfig::SETTING_EBS_SIZE] : null, null, array_key_exists(FarmRoleStorageConfig::SETTING_EBS_TYPE, $rootDeviceSettings) ? $rootDeviceSettings[FarmRoleStorageConfig::SETTING_EBS_TYPE] : null, array_key_exists(FarmRoleStorageConfig::SETTING_EBS_IOPS, $rootDeviceSettings) ? $rootDeviceSettings[FarmRoleStorageConfig::SETTING_EBS_IOPS] : null, true, null); $deviceName = !empty($rootDeviceSettings[FarmRoleStorageConfig::SETTING_EBS_DEVICE_NAME]) ? $rootDeviceSettings[FarmRoleStorageConfig::SETTING_EBS_DEVICE_NAME] : '/dev/sda1'; $rootBlockDevice = new BlockDeviceMappingData($deviceName, null, null, $ebs); $runInstanceRequest->appendBlockDeviceMapping($rootBlockDevice); } foreach ($this->GetBlockDeviceMapping($launchOptions->serverType) as $bdm) { $runInstanceRequest->appendBlockDeviceMapping($bdm); } $placementData = $this->GetPlacementGroupData($launchOptions->serverType, $DBServer, $placementData); if ($placementData !== null) { $runInstanceRequest->setPlacement($placementData); } $skipKeyValidation = false; $sshKey = new SshKey(); $farmId = NULL; if ($DBServer->status == SERVER_STATUS::TEMPORARY) { $keyName = "SCALR-ROLESBUILDER-" . SCALR_ID; if (!$sshKey->loadGlobalByName($DBServer->envId, SERVER_PLATFORMS::EC2, $launchOptions->cloudLocation, $keyName)) { $keyName = "SCALR-ROLESBUILDER-" . SCALR_ID . "-{$DBServer->envId}"; } } else { $keyName = $governance->getValue(SERVER_PLATFORMS::EC2, \Scalr_Governance::AWS_KEYPAIR); if ($keyName) { $skipKeyValidation = true; } else { $keyName = "FARM-{$DBServer->farmId}-" . SCALR_ID; $farmId = $DBServer->farmId; $oldKeyName = "FARM-{$DBServer->farmId}"; if ($sshKey->loadGlobalByName($DBServer->envId, SERVER_PLATFORMS::EC2, $launchOptions->cloudLocation, $oldKeyName)) { $keyName = $oldKeyName; $skipKeyValidation = true; } } } if (!$skipKeyValidation && !$sshKey->loadGlobalByName($DBServer->envId, SERVER_PLATFORMS::EC2, $launchOptions->cloudLocation, $keyName)) { $result = $aws->ec2->keyPair->create($keyName); if ($result->keyMaterial) { $sshKey->farmId = $farmId; $sshKey->envId = $DBServer->envId; $sshKey->type = SshKey::TYPE_GLOBAL; $sshKey->platform = SERVER_PLATFORMS::EC2; $sshKey->cloudLocation = $launchOptions->cloudLocation; $sshKey->cloudKeyName = $keyName; $sshKey->privateKey = $result->keyMaterial; $sshKey->generatePublicKey(); $sshKey->save(); } } $runInstanceRequest->keyName = $keyName; try { $result = $aws->ec2->instance->run($runInstanceRequest); } catch (Exception $e) { if (stristr($e->getMessage(), "The key pair") && stristr($e->getMessage(), "does not exist")) { $sshKey->delete(); throw $e; } if (stristr($e->getMessage(), "The requested configuration is currently not supported for this AMI")) { \Scalr::getContainer()->logger(__CLASS__)->fatal(sprintf("Unsupported configuration: %s", json_encode($runInstanceRequest))); } if (stristr($e->getMessage(), "The requested Availability Zone is no longer supported") || stristr($e->getMessage(), "is not supported in your requested Availability Zone") || stristr($e->getMessage(), "capacity in the Availability Zone you requested") || stristr($e->getMessage(), "Our system will be working on provisioning additional capacity") || stristr($e->getMessage(), "is currently constrained and we are no longer accepting new customer requests")) { $availZone = $runInstanceRequest->getPlacement() ? $runInstanceRequest->getPlacement()->availabilityZone : null; if ($availZone) { $DBServer->GetEnvironmentObject()->setPlatformConfig(array("aws.{$launchOptions->cloudLocation}.{$availZone}.unavailable" => time())); } throw $e; } else { throw $e; } } if ($result->instancesSet->get(0)->instanceId) { $instanceTypeInfo = $this->getInstanceType($runInstanceRequest->instanceType, $environment, $launchOptions->cloudLocation); /* @var $instanceTypeInfo CloudInstanceType */ $DBServer->SetProperties([\EC2_SERVER_PROPERTIES::REGION => $launchOptions->cloudLocation, \EC2_SERVER_PROPERTIES::AVAIL_ZONE => $result->instancesSet->get(0)->placement->availabilityZone, \EC2_SERVER_PROPERTIES::INSTANCE_ID => $result->instancesSet->get(0)->instanceId, \EC2_SERVER_PROPERTIES::AMIID => $runInstanceRequest->imageId, \EC2_SERVER_PROPERTIES::VPC_ID => $result->instancesSet->get(0)->vpcId, \EC2_SERVER_PROPERTIES::SUBNET_ID => $result->instancesSet->get(0)->subnetId, \EC2_SERVER_PROPERTIES::ARCHITECTURE => $result->instancesSet->get(0)->architecture, \SERVER_PROPERTIES::INFO_INSTANCE_VCPUS => isset($instanceTypeInfo['vcpus']) ? $instanceTypeInfo['vcpus'] : null]); $DBServer->setOsType($result->instancesSet->get(0)->platform ? $result->instancesSet->get(0)->platform : 'linux'); $DBServer->cloudLocation = $launchOptions->cloudLocation; $DBServer->cloudLocationZone = $result->instancesSet->get(0)->placement->availabilityZone; $DBServer->update(['type' => $runInstanceRequest->instanceType, 'instanceTypeName' => $runInstanceRequest->instanceType]); $DBServer->imageId = $launchOptions->imageId; // we set server history here $DBServer->getServerHistory()->update(['cloudServerId' => $result->instancesSet->get(0)->instanceId]); return $DBServer; } else { throw new Exception(sprintf(_("Cannot launch new instance. %s"), serialize($result))); } }
public function OnHostInit(\HostInitEvent $event) { $msg = new \Scalr_Messaging_Msg_HostInitResponse($event->DBServer->GetFarmObject()->GetSetting(Entity\FarmSetting::CRYPTO_KEY), $event->DBServer->index); $msg->cloudLocation = $event->DBServer->GetCloudLocation(); $msg->eventId = $event->GetEventID(); $msg->serverId = $event->DBServer->serverId; $dbServer = $event->DBServer; $dbFarmRole = $dbServer->GetFarmRoleObject(); if ($dbFarmRole) { foreach (\Scalr_Role_Behavior::getListForFarmRole($dbFarmRole) as $behavior) { $msg = $behavior->extendMessage($msg, $dbServer); } } $msg->setGlobalVariables($dbServer, true, $event); /** * TODO: Move everything to\\Scalr_Db_Msr_* */ if ($dbFarmRole->GetRoleObject()->hasBehavior(\ROLE_BEHAVIORS::MYSQL)) { $isMaster = (int) $dbServer->GetProperty(\SERVER_PROPERTIES::DB_MYSQL_MASTER); $msg->mysql = (object) array("replicationMaster" => $isMaster, "rootPassword" => $dbFarmRole->GetSetting(Entity\FarmRoleSetting::MYSQL_ROOT_PASSWORD), "replPassword" => $dbFarmRole->GetSetting(Entity\FarmRoleSetting::MYSQL_REPL_PASSWORD), "statPassword" => $dbFarmRole->GetSetting(Entity\FarmRoleSetting::MYSQL_STAT_PASSWORD), "logFile" => $dbFarmRole->GetSetting(Entity\FarmRoleSetting::MYSQL_LOG_FILE), "logPos" => $dbFarmRole->GetSetting(Entity\FarmRoleSetting::MYSQL_LOG_POS)); if ($event->DBServer->IsSupported("0.7")) { if ($dbFarmRole->GetSetting(Entity\FarmRoleSetting::MYSQL_SCALR_VOLUME_ID) && $isMaster) { try { $volume = \Scalr_Storage_Volume::init()->loadById($dbFarmRole->GetSetting(Entity\FarmRoleSetting::MYSQL_SCALR_VOLUME_ID)); $msg->mysql->volumeConfig = $volume->getConfig(); } catch (\Exception $e) { } } /*** * For Rackspace we ALWAYS need snapsjot_config for mysql * ***/ if ($dbFarmRole->GetSetting(Entity\FarmRoleSetting::MYSQL_SCALR_SNAPSHOT_ID)) { try { $snapshotConfig = \Scalr_Storage_Snapshot::init()->loadById($dbFarmRole->GetSetting(Entity\FarmRoleSetting::MYSQL_SCALR_SNAPSHOT_ID)); $msg->mysql->snapshotConfig = $snapshotConfig->getConfig(); } catch (\Exception $e) { $this->Logger->error(new \FarmLogMessage($event->DBServer->farmId, "Cannot get snaphotConfig for hostInit message: {$e->getMessage()}", !empty($event->DBServer->serverId) ? $event->DBServer->serverId : null)); } } if (!$msg->mysql->snapshotConfig && $dbFarmRole->GetSetting(Entity\FarmRoleSetting::MYSQL_SNAPSHOT_ID)) { $msg->mysql->snapshotConfig = new \stdClass(); $msg->mysql->snapshotConfig->type = $dbFarmRole->GetSetting(Entity\FarmRoleSetting::MYSQL_DATA_STORAGE_ENGINE); $msg->mysql->snapshotConfig->id = $dbFarmRole->GetSetting(Entity\FarmRoleSetting::MYSQL_SNAPSHOT_ID); } if ($isMaster && !$msg->mysql->volumeConfig) { $msg->mysql->volumeConfig = new \stdClass(); $msg->mysql->volumeConfig->type = $dbFarmRole->GetSetting(Entity\FarmRoleSetting::MYSQL_DATA_STORAGE_ENGINE); if (!$dbFarmRole->GetSetting(Entity\FarmRoleSetting::MYSQL_MASTER_EBS_VOLUME_ID)) { if (in_array($dbFarmRole->GetSetting(Entity\FarmRoleSetting::MYSQL_DATA_STORAGE_ENGINE), array(\MYSQL_STORAGE_ENGINE::EBS, \MYSQL_STORAGE_ENGINE::CSVOL))) { $msg->mysql->volumeConfig->size = $dbFarmRole->GetSetting(Entity\FarmRoleSetting::MYSQL_EBS_VOLUME_SIZE); if ($dbFarmRole->GetSetting(Entity\FarmRoleSetting::MYSQL_DATA_STORAGE_ENGINE) == \MYSQL_STORAGE_ENGINE::EBS) { $msg->mysql->volumeConfig->volumeType = $dbFarmRole->GetSetting(Entity\FarmRoleSetting::MYSQL_EBS_TYPE); if ($msg->mysql->volumeConfig->volumeType == 'io1') { $msg->mysql->volumeConfig->iops = $dbFarmRole->GetSetting(Entity\FarmRoleSetting::MYSQL_EBS_IOPS); } } } elseif ($dbFarmRole->GetSetting(Entity\FarmRoleSetting::MYSQL_DATA_STORAGE_ENGINE) == \MYSQL_STORAGE_ENGINE::EPH) { //$msg->mysql->volumeConfig->snap_backend = "cf://mysql-data-bundle/scalr-{$dbFarmRole->GetFarmObject()->Hash}"; $msg->mysql->volumeConfig->snap_backend = sprintf("cf://scalr-%s-%s/data-bundles/%s/mysql/", $event->DBServer->envId, $event->DBServer->GetCloudLocation(), $event->DBServer->farmId); $msg->mysql->volumeConfig->vg = 'mysql'; $msg->mysql->volumeConfig->disk = new \stdClass(); $msg->mysql->volumeConfig->disk->type = 'loop'; $msg->mysql->volumeConfig->disk->size = '75%root'; } } else { $msg->mysql->volumeConfig->id = $dbFarmRole->GetSetting(Entity\FarmRoleSetting::MYSQL_MASTER_EBS_VOLUME_ID); } } } else { if ($isMaster) { $msg->mysql->volumeId = $dbFarmRole->GetSetting(Entity\FarmRoleSetting::MYSQL_MASTER_EBS_VOLUME_ID); } $msg->mysql->snapshotId = $dbFarmRole->GetSetting(Entity\FarmRoleSetting::MYSQL_SNAPSHOT_ID); } } // Create ssh keypair for rackspace if ($event->DBServer->IsSupported("0.7")) { $authSshKey = $event->DBServer->platform == \SERVER_PLATFORMS::AZURE || $event->DBServer->isCloudstack(); if ($event->DBServer->isOpenstack()) { $isKeyPairsSupported = $event->DBServer->GetEnvironmentObject()->cloudCredentials($event->DBServer->platform)->properties[Entity\CloudCredentialsProperty::OPENSTACK_EXT_KEYPAIRS_ENABLED]; if ($isKeyPairsSupported != 1) { $authSshKey = true; } } if ($authSshKey && $dbServer->osType == 'linux') { $sshKey = (new SshKey())->loadGlobalByFarmId($event->DBServer->envId, $event->DBServer->platform, $event->DBServer->GetFarmRoleObject()->CloudLocation, $event->DBServer->farmId); if (!$sshKey) { $keyName = "FARM-{$event->DBServer->farmId}-" . SCALR_ID; $sshKey = new SshKey(); $sshKey->generateKeypair(); $sshKey->farmId = $event->DBServer->farmId; $sshKey->envId = $event->DBServer->envId; $sshKey->type = SshKey::TYPE_GLOBAL; $sshKey->platform = $event->DBServer->platform; $sshKey->cloudLocation = $event->DBServer->isCloudstack() || $event->DBServer->platform == \SERVER_PLATFORMS::AZURE || $event->DBServer->platform == \SERVER_PLATFORMS::GCE ? "" : $event->DBServer->GetFarmRoleObject()->CloudLocation; $sshKey->cloudKeyName = $keyName; $sshKey->save(); } $sshKeysMsg = new \Scalr_Messaging_Msg_UpdateSshAuthorizedKeys(array($sshKey->publicKey), array()); $event->DBServer->SendMessage($sshKeysMsg, false, true); } } // Send HostInitResponse to target server $event->DBServer->SendMessage($msg); // Send broadcast HostInit $servers = \DBFarm::LoadByID($this->FarmID)->GetServersByFilter(array('status' => array(\SERVER_STATUS::INIT, \SERVER_STATUS::RUNNING))); $event->msgExpected = count($servers); foreach ((array) $servers as $DBServer) { if (!$DBServer->IsSupported('0.5')) { $event->msgExpected--; continue; } if ($DBServer->status == \SERVER_STATUS::INIT && $DBServer->serverId != $event->DBServer->serverId) { $event->msgExpected--; continue; } $hiMsg = new \Scalr_Messaging_Msg_HostInit(); $hiMsg->setServerMetaData($event->DBServer); $hiMsg = \Scalr_Scripting_Manager::extendMessage($hiMsg, $event, $event->DBServer, $DBServer); if ($event->DBServer->farmRoleId != 0) { foreach (\Scalr_Role_Behavior::getListForFarmRole($event->DBServer->GetFarmRoleObject()) as $behavior) { $hiMsg = $behavior->extendMessage($hiMsg, $event->DBServer); } } $hiMsg = $DBServer->SendMessage($hiMsg, false, true); if ($hiMsg->dbMessageId) { $event->msgCreated++; } } }