protected function run1($stage) { $this->console->out("Initializing instance_type_name field in servers_history table"); $result = $this->db->Execute("\n SELECT sh.* FROM servers_history sh\n JOIN servers s USING(server_id)\n WHERE sh.instance_type_name IS NULL\n AND sh.type IS NOT NULL\n AND sh.cloud_location IS NOT NULL\n ORDER BY sh.env_id, sh.platform DESC\n "); $env = null; $platform = null; $this->db->BeginTrans(); try { $sql = "UPDATE servers_history sh SET sh.instance_type_name = ? WHERE sh.server_id = ?"; while ($record = $result->FetchRow()) { if (!isset($env) || $env->id != $record['env_id']) { $env = Scalr_Environment::init()->loadById($record['env_id']); $platform = null; } if (in_array($record['platform'], [\SERVER_PLATFORMS::EC2, \SERVER_PLATFORMS::GCE])) { $this->db->Execute($sql, [$record['type'], $record['server_id']]); continue; } if (!isset($platform) || $platform != $record['platform']) { $platform = $record['platform']; $platformModule = PlatformFactory::NewPlatform($record['platform']); $url = $platformModule->getEndpointUrl($env); } $cloudLocationId = CloudLocation::calculateCloudLocationId($record['platform'], $record['cloud_location'], $url); $instanceTypeEntity = CloudInstanceType::findPk($cloudLocationId, $record['type']); /* @var $instanceTypeEntity CloudInstanceType */ if ($instanceTypeEntity) { $this->db->Execute($sql, [$instanceTypeEntity->name, $record['server_id']]); } } $this->db->CommitTrans(); } catch (Exception $e) { $this->db->RollbackTrans(); } }
/** * Gets instance types with its prices * * @param string $cloudLocation * @param string $url * @param PlatformModuleInterface $pm * @param string $platformName * @param DateTime $effectiveDate optional The date on which prices should be applied * @param Scalr_Environment $env optional * @return array */ private function getTypesWithPrices($cloudLocation, $url, $pm, $platformName, $effectiveDate = null, Scalr_Environment $env = null) { $result = ['cloudLocation' => $cloudLocation, 'url' => $this->getContainer()->analytics->prices->normalizeUrl($url)]; try { $typeNames = $pm->getInstanceTypes($env, $cloudLocation); } catch (Exception $e) { //Has no connection to cloud provider or invalid keys $typeNames = []; //Fetches cloud location entity from the cache $cl = CloudLocation::findPk(CloudLocation::calculateCloudLocationId($platformName, $result['cloudLocation'], $result['url'])); //It is possible that it might have been already removed if ($cl instanceof CloudLocation) { foreach ($cl->getActiveInstanceTypes() as $instanceTypeEntity) { /* @var $instanceTypeEntity CloudInstanceType */ $typeNames[$instanceTypeEntity->instanceTypeId] = $instanceTypeEntity->name; } } } $result['types'] = array_keys($typeNames); $pricing = $this->getPlatformPricing($platformName, $result['cloudLocation'], $result['url'], $effectiveDate); if (!empty($pricing["prices"])) { foreach ($pricing['prices'] as $price) { if (false !== ($pos = array_search($price['type'], $result['types']))) { unset($result['types'][$pos]); } } } else { $pricing["prices"] = []; } foreach ($result['types'] as $type) { $pricing['prices'][] = ['type' => $type, 'name' => isset($typeNames[$type]) ? $typeNames[$type] : $type]; } $result = array_merge($result, $pricing); unset($result['types']); //Prices should be ordered by name if (!empty($result['prices']) && is_array($result['prices'])) { usort($result['prices'], function ($a, $b) { if ($a['type'] == $b['type']) { return 0; } return $a['type'] < $b['type'] ? -1 : 1; }); } return $result; }
/** * SCALRCORE-951 we should avoid ON DUPLICATE KEY UPDATE clause on tables with multiple unique indexes * @test * @functional */ public function testFunctionalSeveralUniqueKeys() { $db = \Scalr::getDb(); //Removes previously created records if they exist $this->cleanupCloudLocations(); $cl2Identifier = CloudLocation::calculateCloudLocationId(self::CL_PLATFORM, self::CL_NAME, self::CL_URL); $cl3Identifier = CloudLocation::calculateCloudLocationId(self::CL_PLATFORM, self::CL_NAME . '3', self::CL_URL); //Creates the first record $cl = $this->getCloudLocationEntity(); $cl->save(); unset($cl); //Checks if it has been saved properly $cl = CloudLocation::findPk(self::CL_LOC_ID); $this->assertInstanceOf('Scalr\\Model\\Entity\\CloudLocation', $cl); $this->assertEquals(self::CL_LOC_ID, $cl->cloudLocationId); $this->assertEquals(self::CL_URL, $cl->url); $this->assertEquals(self::CL_NAME, $cl->cloudLocation); $this->assertEquals(self::CL_PLATFORM, $cl->platform); $cl3 = $this->getCloudLocationEntity($cl3Identifier); $cl3->cloudLocation = self::CL_NAME . '3'; $cl3->save(); //Record with this unique key already exists $cl3->cloudLocation = self::CL_NAME; //Saving record with existing unique key $ex = false; try { $cl3->save(); $this->cleanupCloudLocations(); } catch (Exception $e) { //"Duplicate entry 'test--test' for key 'idx_unique'" $ex = true; $this->assertContains("Duplicate entry", $e->getMessage()); } $this->assertTrue($ex, "Duplicate entry 'test--test' for key 'idx_unique' must be thrown here (3)"); //Trying to create with the same unique key as $cl but different primary key $cl2 = $this->getCloudLocationEntity($cl2Identifier); //Checks they're different $this->assertNotEquals(self::CL_LOC_ID, $cl2Identifier); //unique key should cause error, and should not be just ignored $ex = false; try { $cl2->save(); $this->cleanupCloudLocations(); } catch (Exception $e) { $ex = true; $this->assertContains("Duplicate entry", $e->getMessage()); } $this->assertTrue($ex, "Duplicate entry 'test--test' for key 'idx_unique' must be thrown here (2)"); $this->assertNull(CloudLocation::findPk($cl2Identifier)); $this->cleanupCloudLocations(); }
/** * {@inheritdoc} * @see \Scalr\Modules\PlatformModuleInterface::getInstanceType() */ public function getInstanceType($instanceTypeId, \Scalr_Environment $env, $cloudLocation = null) { $cloudLocationId = CloudLocation::calculateCloudLocationId(SERVER_PLATFORMS::GCE, $cloudLocation, $this->getEndpointUrl($env)); $cit = CloudInstanceType::findPk($cloudLocationId, $instanceTypeId); if ($cit === null) { $instanceTypes = $this->getInstanceTypes($env, $cloudLocation, true); if (!empty($instanceTypes[$instanceTypeId])) { $cit = CloudInstanceType::findPk($cloudLocationId, $instanceTypeId); } } return $cit; }
/** * Gets active instance types for the specified cloud platform, url and location * from the cache * * @param string $platform A cloud platform * @param string $url A cloud endpoint url * @param string $cloudLocation A cloud location * * @return \Scalr\Model\Collections\ArrayCollection|boolean * Returns collection of the CloudInstanceType entities on success or false otherwise */ protected function getCachedInstanceTypes($platform, $url, $cloudLocation) { //Gets a lifetime of the cached data from the config $lifetime = (int) \Scalr::config('scalr.cache.instance_types.lifetime'); //If this lifetime equals zero it means we have to warm-up cache if ($lifetime === 0) { CloudLocation::warmUp(); //We have no cached instance types return false; } //Checks whether there are active instance types in the cache taking lifetime into account. if (!CloudLocation::hasInstanceTypes($platform, $url, $cloudLocation, $lifetime)) { //No cached data return false; } //Fetches cloud location entity from the cache $cl = CloudLocation::findPk(CloudLocation::calculateCloudLocationId($platform, $cloudLocation, $url)); //It is possible that it might have been already removed if (!$cl instanceof CloudLocation) { //No cached data return false; } //Retrieves an instance types for this cloud location. //We should actually return only active types. return $cl->getActiveInstanceTypes(); }
/** * Gets cloud instance type's name * * @param string $instanceTypeId Instance type identifier * @param string $envId Environment identifier * @param string $platform Platform * @param string $cloudLocation Cloud location * @return string */ public function getInstanceTypeName($instanceTypeId, $envId, $platform, $cloudLocation) { static $instanceTypeNames = []; static $urlCache = []; if ($platform == \SERVER_PLATFORMS::EC2) { return $instanceTypeId; } if (!isset($instanceTypeNames[$envId][$platform][$cloudLocation][$instanceTypeId])) { try { if (!isset($urlCache[$envId][$platform])) { $curEnv = Scalr_Environment::init()->loadById($envId); $platformObj = PlatformFactory::NewPlatform($platform); $urlCache[$envId][$platform] = $platformObj->getEndpointUrl($curEnv); } $cloudLocationId = CloudLocation::calculateCloudLocationId($platform, $cloudLocation, $urlCache[$envId][$platform]); $rows = $this->db->Execute("\n SELECT cit.instance_type_id, cit.name\n FROM cloud_instance_types cit\n WHERE cit.cloud_location_id = UNHEX(?)\n ", [str_replace('-', '', $cloudLocationId)]); while ($row = $rows->FetchRow()) { $instanceTypeNames[$envId][$platform][$cloudLocation][$row['instance_type_id']] = $row['name']; } } catch (Exception $e) { } } return !empty($instanceTypeNames[$envId][$platform][$cloudLocation][$instanceTypeId]) ? $instanceTypeNames[$envId][$platform][$cloudLocation][$instanceTypeId] : $instanceTypeId; }