public function LaunchServer(DBServer $DBServer, \Scalr_Server_LaunchOptions $launchOptions = null)
 {
     $environment = $DBServer->GetEnvironmentObject();
     if (!$launchOptions) {
         $launchOptions = new \Scalr_Server_LaunchOptions();
         $DBRole = DBRole::loadById($DBServer->roleId);
         $launchOptions->imageId = $DBRole->getImageId(\SERVER_PLATFORMS::GCE, $DBServer->GetProperty(\GCE_SERVER_PROPERTIES::CLOUD_LOCATION));
         $launchOptions->serverType = $DBServer->GetFarmRoleObject()->GetSetting(DBFarmRole::SETTING_GCE_MACHINE_TYPE);
         $launchOptions->cloudLocation = $DBServer->GetFarmRoleObject()->CloudLocation;
         $userData = $DBServer->GetCloudUserData();
         $launchOptions->architecture = 'x86_64';
         $networkName = $DBServer->GetFarmRoleObject()->GetSetting(DBFarmRole::SETTING_GCE_NETWORK);
         $onHostMaintenance = $DBServer->GetFarmRoleObject()->GetSetting(DBFarmRole::SETTING_GCE_ON_HOST_MAINTENANCE);
     } else {
         $userData = array();
         $networkName = 'default';
     }
     if (!$onHostMaintenance) {
         $onHostMaintenance = 'TERMINATE';
     }
     if ($DBServer->status == \SERVER_STATUS::TEMPORARY) {
         $keyName = "SCALR-ROLESBUILDER-" . SCALR_ID;
     } else {
         $keyName = "FARM-{$DBServer->farmId}-" . SCALR_ID;
     }
     $sshKey = \Scalr_SshKey::init();
     if (!$sshKey->loadGlobalByName($keyName, "", $DBServer->envId, \SERVER_PLATFORMS::GCE)) {
         $keys = $sshKey->generateKeypair();
         if ($keys['public']) {
             $sshKey->farmId = $DBServer->farmId;
             $sshKey->envId = $DBServer->envId;
             $sshKey->type = \Scalr_SshKey::TYPE_GLOBAL;
             $sshKey->cloudLocation = "";
             $sshKey->cloudKeyName = $keyName;
             $sshKey->platform = \SERVER_PLATFORMS::GCE;
             $sshKey->save();
             $publicKey = $keys['public'];
         } else {
             throw new \Exception("Scalr unable to generate ssh keypair");
         }
     } else {
         $publicKey = $sshKey->getPublic();
     }
     $gce = $this->getClient($environment);
     // Check firewall
     $firewalls = $gce->firewalls->listFirewalls($environment->getPlatformConfigValue(self::PROJECT_ID));
     $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', $environment->getPlatformConfigValue(self::PROJECT_ID)));
         //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($environment->getPlatformConfigValue(self::PROJECT_ID), $firewall);
     }
     $instance = new \Google_Service_Compute_Instance();
     $instance->setKind("compute#instance");
     // Set scheduling
     $scheduling = new \Google_Service_Compute_Scheduling();
     $scheduling->setAutomaticRestart(false);
     $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', $environment->getPlatformConfigValue(self::PROJECT_ID)));
     $network->setAccessConfigs(array($accessConfig));
     $instance->setNetworkInterfaces(array($network));
     $serviceAccount = new \Google_Service_Compute_ServiceAccount();
     $serviceAccount->setEmail("default");
     $serviceAccount->setScopes(array("https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/compute", "https://www.googleapis.com/auth/devstorage.full_control"));
     $instance->setServiceAccounts(array($serviceAccount));
     if ($launchOptions->cloudLocation != 'x-scalr-custom') {
         $availZone = $launchOptions->cloudLocation;
     } else {
         $location = $DBServer->GetFarmRoleObject()->GetSetting(DBFarmRole::SETTING_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})";
         }
         $DBServer->SetProperty("tmp.gce.avail_zone.algo2", "[A:{$aZones}][D:{$dZones}][S:{$availZone}]");
     }
     $instance->setZone($this->getObjectUrl($availZone, 'zones', $environment->getPlatformConfigValue(self::PROJECT_ID)));
     $instance->setMachineType($this->getObjectUrl($launchOptions->serverType, 'machineTypes', $environment->getPlatformConfigValue(self::PROJECT_ID), $availZone));
     //Create root disk
     $image = $this->getObjectUrl($launchOptions->imageId, 'images', $environment->getPlatformConfigValue(self::PROJECT_ID));
     $diskName = "root-{$DBServer->serverId}";
     /*
     try {
         $rootDisk = new \Google_Service_Compute_Disk();
         $rootDisk->setKind("compute#disk");
         $rootDisk->setZone($this->getObjectUrl(
             $availZone,
             'zones',
             $environment->getPlatformConfigValue(self::PROJECT_ID)
         ));
         $rootDisk->setName($diskName);
         $rootDisk->setDescription("Server persistent disk created from image: {$image}");
         $rootDisk->setSourceImage($image);
     
         $op = $gce->disks->insert(
             $environment->getPlatformConfigValue(self::PROJECT_ID),
             $availZone,
             $rootDisk,
             array('sourceImage' => $image)
         );
     
         $DBServer->SetProperty(\GCE_SERVER_PROPERTIES::ROOT_DEVICE_NAME, $diskName);
     } catch (\Exception $e) {
         throw new \Exception(sprintf("Cannot create root disk from image: %s", $e->getMessage()));
     }
     
     while(true) {
         //Wait for disk
         $op = $gce->zoneOperations->get(
             $environment->getPlatformConfigValue(self::PROJECT_ID),
             $availZone,
             $op->name
         );
     
         if ($op->status == 'DONE')
             break;
     
         if ($op->status == 'PENDING' || $op->status == 'RUNNING')
             sleep(1);
     }
     */
     $initializeParams = new \Google_Service_Compute_AttachedDiskInitializeParams();
     $initializeParams->sourceImage = $image;
     $initializeParams->diskName = $diskName;
     $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);
     /*
     $attachedDisk->setSource($this->getObjectUrl(
         "root-{$DBServer->serverId}",
         'disks',
         $environment->getPlatformConfigValue(self::PROJECT_ID),
         $availZone
     ));
     */
     $instance->setDisks(array($attachedDisk));
     $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
     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;
     }
     // Add SSH Key
     $item = new \Google_Service_Compute_MetadataItems();
     $item->setKey("sshKeys");
     $item->setValue("scalr:{$publicKey}");
     $items[] = $item;
     $metadata->setItems($items);
     $instance->setMetadata($metadata);
     try {
         $result = $gce->instances->insert($environment->getPlatformConfigValue(self::PROJECT_ID), $availZone, $instance);
     } catch (\Exception $e) {
         throw new \Exception(sprintf(_("Cannot launch new instance. %s (%s, %s)"), $e->getMessage(), $launchOptions->imageId, $launchOptions->serverType));
     }
     if ($result->id) {
         $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, \GCE_SERVER_PROPERTIES::MACHINE_TYPE => $launchOptions->serverType, \SERVER_PROPERTIES::ARCHITECTURE => $launchOptions->architecture]);
         //TODO: separate regions from zones.
         $DBServer->SetProperties(['debug.region' => $result->region, 'debug.zone' => $result->zone]);
         $DBServer->cloudLocation = $availZone;
         $DBServer->cloudLocationZone = $availZone;
         return $DBServer;
     } else {
         throw new \Exception(sprintf(_("Cannot launch new instance. %s (%s, %s)"), serialize($result), $launchOptions->imageId, $launchOptions->serverType));
     }
 }
Example #2
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));
     }
 }
Example #3
0
 /**
  * Retrieve password for a Windows machine
  *
  * @param  string $serverId
  * @throws Exception
  */
 public function xGetWindowsPasswordAction($serverId)
 {
     $this->request->restrictAccess(Acl::RESOURCE_SECURITY_RETRIEVE_WINDOWS_PASSWORDS);
     $password = $encPassword = null;
     $dbServer = DBServer::LoadByID($serverId);
     $this->user->getPermissions()->validate($dbServer);
     if ($dbServer->platform == SERVER_PLATFORMS::EC2) {
         $env = Scalr_Environment::init()->loadById($dbServer->envId);
         $ec2 = $env->aws($dbServer->GetCloudLocation())->ec2;
         $encPassword = $ec2->instance->getPasswordData($dbServer->GetCloudServerID());
         $encPassword = str_replace('\\/', '/', trim($encPassword->passwordData));
     } elseif ($dbServer->platform == SERVER_PLATFORMS::AZURE) {
         $password = $dbServer->GetProperty(AZURE_SERVER_PROPERTIES::ADMIN_PASSWORD);
     } elseif ($dbServer->platform == SERVER_PLATFORMS::GCE) {
         $platform = PlatformFactory::NewPlatform(SERVER_PLATFORMS::GCE);
         /* @var $client Google_Service_Compute */
         $client = $platform->getClient($this->environment);
         $ccProps = $this->environment->keychain(SERVER_PLATFORMS::GCE)->properties;
         /* @var $info Google_Service_Compute_Instance */
         $info = $client->instances->get($ccProps[Entity\CloudCredentialsProperty::GCE_PROJECT_ID], $dbServer->cloudLocation, $dbServer->serverId);
         // More info about following code is available here:
         // https://cloud.google.com/compute/docs/instances/windows-old-auth
         //
         // Check GCE agent version
         $serialPort = $client->instances->getSerialPortOutput($ccProps[Entity\CloudCredentialsProperty::GCE_PROJECT_ID], $dbServer->cloudLocation, $dbServer->serverId);
         $serialPortContents = $serialPort->getContents();
         preg_match("/GCE Agent started( \\(version ([0-9\\.]+)\\))?\\./", $serialPortContents, $matches);
         $agentVersion = count($matches) > 1 ? (int) str_replace('.', '', $matches[2]) : 0;
         // New stuff is supported from version 3.0.0.0
         if ($agentVersion > 3000) {
             // NEW GCE AGENT
             // Get SSH key
             $config = array("digest_alg" => "sha512", "private_key_bits" => 2048, "private_key_type" => OPENSSL_KEYTYPE_RSA);
             $key = openssl_pkey_new($config);
             $details = openssl_pkey_get_details($key);
             $userObject = ['userName' => 'scalr', 'modulus' => base64_encode($details['rsa']['n']), 'exponent' => base64_encode($details['rsa']['e']), 'email' => $ccProps[Entity\CloudCredentialsProperty::GCE_SERVICE_ACCOUNT_NAME], 'expireOn' => date("c", strtotime("+10 minute"))];
             /* @var $meta Google_Service_Compute_Metadata */
             $meta = $info->getMetadata();
             $found = false;
             /* @var $item \Google_Service_Compute_MetadataItems */
             foreach ($meta as $item) {
                 if ($item->getKey() === "windows-keys") {
                     $item->setValue(json_encode($userObject, JSON_FORCE_OBJECT));
                     $found = true;
                     break;
                 }
             }
             if (!$found) {
                 $item = new \Google_Service_Compute_MetadataItems();
                 $item->setKey("windows-keys");
                 $item->setValue(json_encode($userObject, JSON_FORCE_OBJECT));
                 $meta[count($meta)] = $item;
             }
             $client->instances->setMetadata($ccProps[Entity\CloudCredentialsProperty::GCE_PROJECT_ID], $dbServer->cloudLocation, $dbServer->serverId, $meta);
             //Monitor serial port #4
             for ($i = 0; $i < 10; $i++) {
                 $serialPortInfo = $client->instances->getSerialPortOutput($ccProps[Entity\CloudCredentialsProperty::GCE_PROJECT_ID], $dbServer->cloudLocation, $dbServer->serverId, ['port' => 4]);
                 $lines = explode("\n", $serialPortInfo->getContents());
                 foreach ($lines as $line) {
                     $obj = json_decode(trim($line));
                     if (isset($obj->modulus) && $obj->modulus == $userObject['modulus']) {
                         $encPassword = base64_decode($obj->encryptedPassword);
                         break;
                     }
                 }
                 if ($encPassword) {
                     break;
                 }
                 sleep(2);
             }
             if ($encPassword) {
                 openssl_private_decrypt($encPassword, $password, $key, OPENSSL_PKCS1_OAEP_PADDING);
                 $encPassword = null;
             } else {
                 throw new Exception("Windows password is not available yet. Please try again in couple minutes.");
             }
         } else {
             // OLD GCE AGENT
             foreach ($info->getMetadata() as $meta) {
                 /* @var $meta Google_Service_Compute_MetadataItems */
                 if ($meta->getKey() == 'gce-initial-windows-password') {
                     $password = $meta->getValue();
                     break;
                 }
             }
         }
     } elseif (PlatformFactory::isOpenstack($dbServer->platform)) {
         if (in_array($dbServer->platform, array(SERVER_PLATFORMS::RACKSPACENG_UK, SERVER_PLATFORMS::RACKSPACENG_US))) {
             $password = $dbServer->GetProperty(OPENSTACK_SERVER_PROPERTIES::ADMIN_PASS);
         } else {
             $env = Scalr_Environment::init()->loadById($dbServer->envId);
             $os = $env->openstack($dbServer->platform, $dbServer->GetCloudLocation());
             //TODO: Check is extension supported
             $encPassword = trim($os->servers->getEncryptedAdminPassword($dbServer->GetCloudServerID()));
         }
     } else {
         throw new Exception("Requested operation is supported by '{$dbServer->platform}' cloud");
     }
     if ($encPassword) {
         try {
             $sshKey = (new SshKey())->loadGlobalByFarmId($dbServer->envId, $dbServer->platform, $dbServer->GetCloudLocation(), $dbServer->farmId);
             $password = CryptoTool::opensslDecrypt(base64_decode($encPassword), $sshKey->privateKey);
         } catch (Exception $e) {
             //Do nothing. Error already handled in UI (If no password returned)
         }
     }
     $this->response->data(array('password' => $password, 'encodedPassword' => $encPassword));
 }