Ejemplo n.º 1
0
 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));
     }
 }
Ejemplo n.º 2
0
 /**
  * {@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));
     }
 }
Ejemplo n.º 3
0
 /**
  * {@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)));
     }
 }
Ejemplo n.º 4
0
 /**
  * {@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()));
     }
 }
Ejemplo n.º 5
0
 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++;
         }
     }
 }