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)); } }
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)); } }