Create platform instance
public static NewPlatform ( string $platform ) : Scalr\Modules\PlatformModuleInterface | ||
$platform | string | |
return | Scalr\Modules\PlatformModuleInterface |
protected function run2($stage) { $farms = $this->db->Execute("SELECT farmid, value FROM farm_settings WHERE name='ec2.vpc.id' AND value != '' AND value IS NOT NULL"); while ($farm = $farms->FetchRow()) { $dbFarm = \DBFarm::LoadByID($farm['farmid']); $roles = $dbFarm->GetFarmRoles(); foreach ($roles as $dbFarmRole) { $vpcSubnetId = $dbFarmRole->GetSetting(Entity\FarmRoleSetting::AWS_VPC_SUBNET_ID); if ($vpcSubnetId && substr($vpcSubnetId, 0, 6) != 'subnet') { $subnets = json_decode($vpcSubnetId); $vpcSubnetId = $subnets[0]; } if ($vpcSubnetId) { try { $platform = PlatformFactory::NewPlatform(\SERVER_PLATFORMS::EC2); $info = $platform->listSubnets(\Scalr_Environment::init()->loadById($dbFarm->EnvID), $dbFarmRole->CloudLocation, $farm['value'], true, $vpcSubnetId); if ($info && $info['type'] != 'public') { $routerRole = $dbFarm->GetFarmRoleByBehavior(\ROLE_BEHAVIORS::VPC_ROUTER); $dbFarmRole->SetSetting(\Scalr_Role_Behavior_Router::ROLE_VPC_SCALR_ROUTER_ID, $routerRole->ID); $this->console->out("Updating router.scalr.farm_role_id property for Farm Role: %s", $dbFarmRole->ID); } } catch (\Exception $e) { continue; } } } } }
protected function run2($stage) { $this->console->out("Populating new properties"); $platforms = $envs = []; foreach (array_keys(\SERVER_PLATFORMS::GetList()) as $platform) { $platforms[$platform] = PlatformFactory::NewPlatform($platform); } $result = $this->db->Execute("\n SELECT s.server_id, s.`platform`, s.`cloud_location`, s.env_id, s.`type`\n FROM servers AS s\n WHERE s.`status` NOT IN (?, ?) AND s.`type` IS NOT NULL\n ", [Server::STATUS_PENDING_TERMINATE, Server::STATUS_TERMINATED]); while ($row = $result->FetchRow()) { if (!empty($row["type"])) { if (!array_key_exists($row["env_id"], $envs)) { $envs[$row["env_id"]] = \Scalr_Environment::init()->loadById($row["env_id"]); } if ($this->isPlatformEnabled($envs[$row["env_id"]], $row["platform"])) { try { $instanceTypeEntity = $platforms[$row["platform"]]->getInstanceType($row["type"], $envs[$row["env_id"]], $row["cloud_location"]); /* @var $instanceTypeEntity CloudInstanceType */ if ($instanceTypeEntity && (int) $instanceTypeEntity->vcpus > 0) { $this->db->Execute("\n INSERT IGNORE INTO server_properties (`server_id`, `name`, `value`) VALUES (?, ?, ?)\n ", [$row["server_id"], Server::INFO_INSTANCE_VCPUS, $instanceTypeEntity->vcpus]); } } catch (\Exception $e) { $this->console->warning("Can't get access to %s, error: %s", $row["platform"], $e->getMessage()); } } } } }
protected function run1($stage) { $envs = []; $platform = SERVER_PLATFORMS::GCE; $platformModule = PlatformFactory::NewPlatform($platform); /* @var $platformModule GoogleCEPlatformModule*/ $result = $this->db->Execute("\n SELECT s.`server_id`, s.`cloud_location`, s.`type`, s.`env_id`, sp.`value` AS vcpus\n FROM servers AS s\n LEFT JOIN server_properties sp ON sp.`server_id`= s.`server_id` AND sp.`name` = ?\n WHERE s.`status` NOT IN (?, ?)\n AND s.`type` IS NOT NULL\n AND s.`platform` = ?\n ", [Server::INFO_INSTANCE_VCPUS, Server::STATUS_PENDING_TERMINATE, Server::STATUS_TERMINATED, $platform]); while ($row = $result->FetchRow()) { if (!empty($row["type"]) && empty($row['vcpus'])) { if (!array_key_exists($row["env_id"], $envs)) { $envs[$row["env_id"]] = \Scalr_Environment::init()->loadById($row["env_id"]); } try { $instanceTypeInfo = $platformModule->getInstanceType($row["type"], $envs[$row["env_id"]], $row["cloud_location"]); if ($instanceTypeInfo instanceof CloudInstanceType) { $vcpus = $instanceTypeInfo->vcpus; } else { trigger_error("Value of vcpus for instance type " . $row["type"] . " is missing for platform " . $platform, E_USER_WARNING); $vcpus = 0; } if ((int) $vcpus > 0) { $this->db->Execute("\n INSERT INTO server_properties (`server_id`, `name`, `value`) VALUES (?, ?, ?)\n ON DUPLICATE KEY UPDATE `value` = ?\n ", [$row["server_id"], Server::INFO_INSTANCE_VCPUS, $vcpus, $vcpus]); } } catch (\Exception $e) { $this->console->warning("Can't get access to %s, error: %s", $platform, $e->getMessage()); } } } }
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(); } }
public function xGrowStorageAction() { $dbFarmRole = DBFarmRole::LoadByID($this->getParam('farmRoleId')); $this->user->getPermissions()->validate($dbFarmRole->GetFarmObject()); $behavior = Scalr_Role_Behavior::loadByName($dbFarmRole->GetRoleObject()->getDbMsrBehavior()); $master = $behavior->getMasterServer($dbFarmRole); if ($master) { try { $volume = Scalr_Storage_Volume::init()->loadById($dbFarmRole->GetSetting(Scalr_Db_Msr::VOLUME_ID)); if ($volume->type != MYSQL_STORAGE_ENGINE::EBS && $volume->type != MYSQL_STORAGE_ENGINE::RAID_EBS && $volume->type != 'raid') { throw new Exception("Grow feature available only for EBS and RAID storage types"); } if ($volume->size >= (int) $this->getParam('newSize')) { throw new Exception("New size should be greather than current one ({$volume->size} GB)"); } $volumeConfig = $volume->getConfig(); $platformAccessData = PlatformFactory::NewPlatform($dbFarmRole->Platform)->GetPlatformAccessData($this->environment, $master); $newConfig = new stdClass(); $newConfig->size = $this->getParam('newSize'); $result = $master->scalarizr->mysql->growStorage($volumeConfig, $newConfig, $platformAccessData); // Do not remove. We need to wait a bit before operation will be registered in scalr. sleep(2); $this->response->data(array('operationId' => $result)); } catch (Exception $e) { throw new Exception("Cannot grow storage: {$e->getMessage()}"); } } else { throw new Exception("Impossible to increase storage size. No running master server."); } }
public static function getAwsLocations() { $locations = array(); foreach (PlatformFactory::NewPlatform(SERVER_PLATFORMS::EC2)->getLocations($this->environment) as $key => $loc) { $locations[] = array($key, $loc); } return $locations; }
/** * Gets AWS instance * * If cloud location is not specified it will use default cloud location for * current User's session * * @param string $cloudLocation optional A Cloud Location * @return Aws Returns AWS initialized for the specified cloud location */ protected function getAws($cloudLocation = null) { if (empty($cloudLocation)) { $p = PlatformFactory::NewPlatform(SERVER_PLATFORMS::EC2); $cloudLocations = $p->getLocations($this->environment); list($cloudLocation) = each($cloudLocations); } return $this->environment->aws($cloudLocation); }
/** * @param jsonData $platforms * @throws Exception */ public function xGetLocationsAction(JsonData $platforms) { $allPlatforms = $this->user->isScalrAdmin() ? array_keys(SERVER_PLATFORMS::GetList()) : $this->getEnvironment()->getEnabledPlatforms(); $result = array(); foreach ($platforms as $platform) { if (in_array($platform, $allPlatforms)) { $result[$platform] = !in_array($platform, array(SERVER_PLATFORMS::GCE, SERVER_PLATFORMS::ECS)) ? PlatformFactory::NewPlatform($platform)->getLocations($this->environment) : array(); } } $this->response->data(array('locations' => $result)); }
public function xGetResourceGroupsAction() { $data = array(); $azure = $this->environment->azure(); //Get Resource groups; $rGroups = $azure->resourceManager->resourceGroup->getList($this->environment->keychain(SERVER_PLATFORMS::AZURE)->properties[Entity\CloudCredentialsProperty::AZURE_SUBSCRIPTION_ID]); foreach ($rGroups as $rGroup) { $data[] = ['id' => $rGroup->name, 'name' => "{$rGroup->name} ({$rGroup->location})"]; } $p = PlatformFactory::NewPlatform(\SERVER_PLATFORMS::AZURE); $this->response->data(array('data' => ['resourceGroups' => $data, 'cloudLocations' => $p->getLocations($this->environment)])); }
public function xListIpsAction() { $this->request->defineParams(array('sort' => array('type' => 'json', 'default' => array('property' => 'ipId', 'direction' => 'ASC')), 'ipId')); $platformName = $this->getParam('platform'); if (!$platformName) { throw new Exception("Cloud should be specified"); } $platform = PlatformFactory::NewPlatform($platformName); $cs = $this->environment->cloudstack($platformName); $ccProps = $this->environment->cloudCredentials($platformName)->properties; $accountName = $ccProps[\Scalr\Model\Entity\CloudCredentialsProperty::CLOUDSTACK_ACCOUNT_NAME]; $domainId = $ccProps[\Scalr\Model\Entity\CloudCredentialsProperty::CLOUDSTACK_DOMAIN_ID]; $requestData = new ListIpAddressesData(); $requestData->account = $accountName; $requestData->domainid = $domainId; $requestData->zoneid = $this->getParam('cloudLocation'); $ipAddresses = $cs->listPublicIpAddresses($requestData); $systemIp = $ccProps[\Scalr\Model\Entity\CloudCredentialsProperty::CLOUDSTACK_SHARED_IP . ".{$this->getParam('cloudLocation')}"]; $ips = array(); if (!empty($ipAddresses)) { foreach ($ipAddresses as $pk => $pv) { if ($this->getParam('ipId') && $this->getParam('ipId') != $pv->id) { continue; } if ($pv->ipaddress == $systemIp) { $pv->purpose = 'ScalrShared'; } if ($pv->isstaticnat && !$pv->issystem) { $pv->purpose = 'ElasticIP'; } if ($pv->isstaticnat && $pv->issystem) { $pv->purpose = 'PublicIP'; } $item = array('ipId' => $pv->id, 'dtAllocated' => $pv->allocated, 'networkName' => $pv->associatednetworkname, 'purpose' => $pv->purpose ? $pv->purpose : "Not used", 'ip' => $pv->ipaddress, 'state' => $pv->state, 'instanceId' => $pv->virtualmachineid, 'fullinfo' => $pv, 'farmId' => false); if ($item['instanceId']) { try { $dbServer = DBServer::LoadByPropertyValue(CLOUDSTACK_SERVER_PROPERTIES::SERVER_ID, $item['instanceId']); $item['farmId'] = $dbServer->farmId; $item['farmRoleId'] = $dbServer->farmRoleId; $item['serverIndex'] = $dbServer->index; $item['serverId'] = $dbServer->serverId; $item['farmName'] = $dbServer->GetFarmObject()->Name; $item['roleName'] = $dbServer->GetFarmRoleObject()->GetRoleObject()->name; } catch (Exception $e) { } } $ips[] = $item; } } $response = $this->buildResponseFromData($ips, array('serverId', 'ipId', 'ip', 'farmId', 'farmRoleId')); $this->response->data($response); }
public function xSaveAction() { $this->request->defineParams(array('members' => array('type' => 'array'))); $platformObject = PlatformFactory::NewPlatform($this->platform); $request = array('pool_id' => $this->getParam('pool_id'), 'weight' => $this->getParam('weight'), 'protocol_port' => $this->getParam('protocol_port'), 'admin_state_up' => $this->getParam('admin_state_up')); foreach ($this->getParam('members') as $memberId) { $details = $this->getClient()->servers->getServerDetails($memberId); $ips = $platformObject->determineServerIps($this->getClient(), $details); $request['address'] = $ips['localIp']; $this->getClient()->network->lbMembers->create($request); } $this->response->success('Member(s) successfully created'); }
protected function run2($stage) { $envIds = $this->db->GetCol('SELECT DISTINCT env_id FROM `comments` WHERE env_id > 0'); $this->console->out("Environments to process: " . count($envIds)); foreach ($envIds as $index => $envId) { if ($this->db->GetOne('SELECT 1 FROM `security_group_rules_comments` WHERE env_id = ? LIMIT 1', array($envId))) { $this->console->out("Skip environment #{$index}(" . $envId . ")"); continue; } try { $env = \Scalr_Environment::init()->loadById($envId); } catch (\Exception $e) { continue; } $locations = PlatformFactory::NewPlatform(\SERVER_PLATFORMS::EC2)->getLocations($env); $container = \Scalr::getContainer(); $container->environment = $env; foreach ($locations as $location => $locatonName) { try { $sgList = $env->aws($location)->ec2->securityGroup->describe(); } catch (\Exception $e) { continue 2; } /* @var $sg SecurityGroupData */ foreach ($sgList as $sg) { $rules = array(); foreach ($sg->ipPermissions as $rule) { /* @var $ipRange IpRangeData */ foreach ($rule->ipRanges as $ipRange) { $rules[] = "{$rule->ipProtocol}:{$rule->fromPort}:{$rule->toPort}:{$ipRange->cidrIp}"; } /* @var $group UserIdGroupPairData */ foreach ($rule->groups as $group) { $ruleSg = $group->userId . '/' . ($group->groupName ? $group->groupName : $group->groupId); $rules[] = "{$rule->ipProtocol}:{$rule->fromPort}:{$rule->toPort}:{$ruleSg}"; } } foreach ($rules as $rule) { $comment = $this->db->GetOne('SELECT comment FROM `comments` WHERE env_id = ? AND sg_name = ? AND rule = ? LIMIT 1', array($envId, $sg->groupName, $rule)); if ($comment) { try { $this->db->Execute("\n INSERT IGNORE `security_group_rules_comments` (`env_id`, `platform`, `cloud_location`, `vpc_id`, `group_name`, `rule`, `comment`)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n ", array($env->id, \SERVER_PLATFORMS::EC2, $location, $sg->vpcId, $sg->groupName, $rule, $comment)); } catch (\Exception $e) { } } } } } $this->console->out("Environment processed: #{$index}(" . $envId . ")"); } }
public function xGetMigrateDetailsAction() { if (!$this->request->getEnvironment()->isPlatformEnabled(SERVER_PLATFORMS::EC2)) { throw new Exception('You can migrate image between regions only on EC2 cloud'); } $platform = PlatformFactory::NewPlatform(SERVER_PLATFORMS::EC2); $locationsList = $platform->getLocations($this->environment); foreach ($locationsList as $location => $name) { if ($location != $this->getParam('cloudLocation')) { $availableDestinations[] = array('cloudLocation' => $location, 'name' => $name); } } $this->response->data(array('sourceRegion' => $this->getParam('cloudLocation'), 'availableDestinations' => $availableDestinations, 'snapshotId' => $this->getParam('snapshotId'))); }
/** * @test * @dataProvider providerBlockDeviceByType * * @param string $instanceType * @param array $expectedBlockDeviceConfiguration */ public function blockDevicesTest($instanceType, array $expectedBlockDeviceConfiguration) { /* @var $pm Ec2PlatformModule */ $pm = PlatformFactory::NewPlatform('ec2'); $reflection = new ReflectionClass(get_class($pm)); $method = $reflection->getMethod('GetBlockDeviceMapping'); $method->setAccessible(true); /* @var $mapping BlockDeviceMappingData[] */ $mapping = $method->invoke($pm, $instanceType, ''); $this->assertEquals(count($expectedBlockDeviceConfiguration), count($mapping), "Wrong count"); foreach ($mapping as $num => $blockDevice) { $this->assertTrue(isset($expectedBlockDeviceConfiguration[$num]), "Invalid device position"); $this->assertEquals($expectedBlockDeviceConfiguration[$num], $blockDevice->deviceName, "Device name mismatch"); } }
protected function run1($stage) { $platform = SERVER_PLATFORMS::EC2; $platformModule = PlatformFactory::NewPlatform($platform); /* @var $platformModule Ec2PlatformModule*/ $instanceTypes = $platformModule->getInstanceTypes(null, null, true); $result = $this->db->Execute("\n SELECT s.server_id, s.`type`, sp.`value` AS vcpus\n FROM servers AS s\n LEFT JOIN server_properties sp ON sp.`server_id`= s.`server_id` AND sp.`name` = ?\n WHERE s.`status` NOT IN (?, ?)\n AND s.`type` IS NOT NULL\n AND s.`platform` = ?\n ", [Server::INFO_INSTANCE_VCPUS, Server::STATUS_PENDING_TERMINATE, Server::STATUS_TERMINATED, $platform]); while ($row = $result->FetchRow()) { if (!empty($row["type"]) && empty($row['vcpus'])) { if (isset($instanceTypes[$row['type']]['vcpus']) && $instanceTypes[$row['type']]['vcpus'] > 0) { $this->db->Execute("\n INSERT INTO server_properties (`server_id`, `name`, `value`) VALUES (?, ?, ?)\n ON DUPLICATE KEY UPDATE `value` = ?\n ", [$row["server_id"], Server::INFO_INSTANCE_VCPUS, $instanceTypes[$row['type']]['vcpus'], $instanceTypes[$row['type']]['vcpus']]); } } } }
/** * @param string $cloudLocation * @param string $diskId optional */ public function xListAction($cloudLocation, $diskId = '') { $platform = PlatformFactory::NewPlatform(SERVER_PLATFORMS::GCE); $client = $platform->getClient($this->environment, $cloudLocation); /* @var $client Google_Service_Compute */ $retval = array(); $disks = $client->disks->listDisks($this->environment->cloudCredentials(SERVER_PLATFORMS::GCE)->properties[Entity\CloudCredentialsProperty::GCE_PROJECT_ID], $cloudLocation, $diskId ? ['filter' => "name eq {$diskId}"] : []); foreach ($disks as $disk) { /* @var $disk Google_Service_Compute_Disk */ $item = array('id' => $disk->name, 'description' => $disk->description, 'createdAt' => strtotime($disk->creationTimestamp), 'size' => (int) $disk->sizeGb, 'status' => $disk->status, 'snapshotId' => $disk->sourceSnapshotId); $retval[] = $item; } $response = $this->buildResponseFromData($retval, array('id', 'name', 'description', 'snapshotId', 'createdAt', 'size')); foreach ($response['data'] as &$row) { $row['createdAt'] = Scalr_Util_DateTime::convertTz($row['createdAt']); } $this->response->data($response); }
public function xRemoveAction() { $this->request->defineParams(array('ipId' => array('type' => 'json'), 'cloudLocation')); $platformName = $this->getParam('platform'); if (!$platformName) { throw new Exception("Cloud should be specified"); } $platform = PlatformFactory::NewPlatform($platformName); $networkType = $platform->getConfigVariable(OpenstackPlatformModule::NETWORK_TYPE, $this->environment, false); $openstack = $this->environment->openstack($platformName, $this->getParam('cloudLocation')); foreach ($this->getParam('ipId') as $ipId) { if ($networkType == OpenstackPlatformModule::NETWORK_TYPE_QUANTUM) { $openstack->network->floatingIps->delete($ipId); } else { $openstack->servers->floatingIps->delete($ipId); } } $this->response->success('Floating IP(s) successfully removed'); }
public function xListSnapshotsAction() { $this->request->defineParams(array('sort' => array('type' => 'json', 'default' => array('property' => 'id', 'direction' => 'ASC')), 'snapshotId')); $platform = PlatformFactory::NewPlatform(SERVER_PLATFORMS::GCE); $client = $platform->getClient($this->environment); /* @var $client Google_Service_Compute */ $retval = array(); $snaps = $client->snapshots->listSnapshots($this->environment->getPlatformConfigValue(GoogleCEPlatformModule::PROJECT_ID)); foreach ($snaps as $snap) { /* @var $snap Google_Service_Compute_Snapshot */ if ($this->getParam('snapshotId') && $this->getParam('snapshotId') != $snap->name) { continue; } $item = array('id' => $snap->name, 'description' => $snap->description, 'createdAt' => Scalr_Util_DateTime::convertTz(strtotime($snap->creationTimestamp)), 'size' => $snap->diskSizeGb, 'status' => $snap->status); $retval[] = $item; } $response = $this->buildResponseFromData($retval, array('id', 'description')); $this->response->data($response); }
/** * List orphaned servers * * @param string $platform Cloud platform * @param string $cloudLocation optional Cloud location * @param string $query optional Filter parameter * @param string $imageId optional Filter parameter * @param string $vpcId optional Filter parameter * @param string $subnetId optional Filter paramerer */ public function xListAction($platform, $cloudLocation = null, $query = null, $imageId = null, $vpcId = null, $subnetId = null) { $lookup = []; $p = PlatformFactory::NewPlatform($platform); if (!$this->environment->isPlatformEnabled($platform)) { $this->response->failure(sprintf("Platform '%s' is not enabled", $platform)); return; } $filterFields = []; if ($query) { $filterFields[join(',', ['cloudServerId', 'privateIp', 'publicIp'])] = $query; } if ($imageId) { $filterFields['imageId'] = $imageId; } if ($vpcId) { $filterFields['vpcId'] = $vpcId; } if ($subnetId) { $filterFields['subnetId'] = $subnetId; } $orphans = $this->buildResponseFromData($p->getOrphanedServers($this->getEnvironmentEntity(), $cloudLocation), $filterFields); foreach ($orphans["data"] as $i => &$orphan) { $orphan["launchTime"] = \Scalr_Util_DateTime::convertTz($orphan["launchTime"]); $orphan["imageHash"] = null; $orphan["imageName"] = null; if (!is_array($lookup[$orphan["imageId"]])) { $lookup[$orphan["imageId"]] = []; } $lookup[$orphan["imageId"]][] = $orphan; } if (!empty($lookup)) { /* @var $image Scalr\Model\Entity\Image */ foreach (Image::find([["status" => Image::STATUS_ACTIVE], ["id" => ['$in' => array_keys($lookup)]], ['$or' => [['accountId' => null], ['$and' => [['accountId' => $this->getUser()->accountId], ['$or' => [['envId' => null], ['envId' => $this->getEnvironment()->id]]]]]]]]) as $image) { foreach ($lookup[$image->id] as &$orphan) { $orphan['imageHash'] = $image->hash; $orphan['imageName'] = $image->name; } } } $this->response->data($orphans); }
protected function run1($stage) { if (\Scalr::getContainer()->analytics->enabled) { $properties = EnvironmentProperty::find([['name' => Entity\CloudCredentialsProperty::AWS_DETAILED_BILLING_BUCKET]]); foreach ($properties as $property) { /* @var $property EnvironmentProperty */ $environment = \Scalr_Environment::init()->loadById($property->envId); $accountType = $environment->getPlatformConfigValue(Entity\CloudCredentialsProperty::AWS_ACCOUNT_TYPE); if ($accountType == Entity\CloudCredentialsProperty::AWS_ACCOUNT_TYPE_REGULAR) { $region = Aws::REGION_US_EAST_1; } else { $platformModule = PlatformFactory::NewPlatform(\SERVER_PLATFORMS::EC2); /* @var $platformModule Ec2PlatformModule */ $locations = array_keys($platformModule->getLocationsByAccountType($accountType)); $region = reset($locations); } $environment->setPlatformConfig([Entity\CloudCredentialsProperty::AWS_DETAILED_BILLING_REGION => $region]); } } }
/** * Raises onCloudAdd notification event * * @param string $platform A platform name. * @param \Scalr_Environment $environment An environment object which cloud is created in. * @param \Scalr_Account_User $user An user who has created platform. */ public function onCloudAdd($platform, $environment, $user) { $container = \Scalr::getContainer(); $analytics = $container->analytics; //Nothing to do in case analytics is disabled if (!$analytics->enabled) { return; } if (!$environment instanceof \Scalr_Environment) { $environment = \Scalr_Environment::init()->loadById($environment); } $pm = PlatformFactory::NewPlatform($platform); //Check if there are some price for this platform and endpoint url if (($endpointUrl = $pm->hasCloudPrices($environment)) === true) { return; } //Disabled or badly configured environment if ($endpointUrl === false && !in_array($platform, [\SERVER_PLATFORMS::EC2, \SERVER_PLATFORMS::GCE])) { return; } //Send a message to financial admin if there are not any price for this cloud $baseUrl = rtrim($container->config('scalr.endpoint.scheme') . "://" . $container->config('scalr.endpoint.host'), '/'); //Disable notifications for hosted Scalr if (!\Scalr::isAllowedAnalyticsOnHostedScalrAccount($environment->clientId)) { return; } $emails = $this->getFinancialAdminEmails(); //There isn't any financial admin if (empty($emails)) { return; } $emails = array_map(function ($email) { return '<' . trim($email, '<>') . '>'; }, $emails); try { $res = $container->mailer->sendTemplate(SCALR_TEMPLATES_PATH . '/emails/analytics_on_cloud_add.eml.php', ['isPublicCloud' => $platform == \SERVER_PLATFORMS::EC2, 'userEmail' => $user->getEmail(), 'cloudName' => \SERVER_PLATFORMS::GetName($platform), 'linkToPricing' => $baseUrl . '/#/analytics/pricing?platform=' . urlencode($platform) . '&url=' . urlencode($endpointUrl === false ? '' : $analytics->prices->normalizeUrl($endpointUrl))], join(',', $emails)); } catch (\Exception $e) { } }
public function OnHostInit(\HostInitEvent $event) { if ($event->DBServer->platform != \SERVER_PLATFORMS::VERIZON) { return; } try { $dbServer = $event->DBServer; $environment = $dbServer->GetEnvironmentObject(); $client = $environment->openstack($dbServer->platform, $dbServer->GetCloudLocation()); $cloudLocation = $dbServer->GetProperty(\OPENSTACK_SERVER_PROPERTIES::CLOUD_LOCATION); $serverId = $dbServer->GetProperty(\OPENSTACK_SERVER_PROPERTIES::SERVER_ID); $iinfo = $client->servers->getServerDetails($serverId); $p = PlatformFactory::NewPlatform(\SERVER_PLATFORMS::VERIZON); $ips = $p->determineServerIps($client, $iinfo); if ($iinfo->security_groups) { //TEMPORARY OPEN PORT 22 $ports = array(8008, 8010, 8013, 22); $list = array(); foreach ($iinfo->security_groups as $sg) { if ($sg->name == $ips['remoteIp']) { if (!$sg->id) { $sgs = $client->listSecurityGroups(); foreach ($sgs as $sgroup) { if ($sgroup->name == $sg->name) { $sg = $sgroup; } } } foreach ($ports as $port) { $request = ['security_group_id' => $sg->id, 'protocol' => 'tcp', "direction" => "ingress", 'port_range_min' => $port, 'port_range_max' => $port, 'remote_ip_prefix' => '0.0.0.0/0', 'remote_group_id' => null]; $client->createSecurityGroupRule($request); } } } } } catch (\Exception $e) { \Scalr::getContainer()->logger(\LOG_CATEGORY::FARM)->error(new \FarmLogMessage($event->DBServer->farmId, sprintf(_("Scalr was unable to open ports for server '%s': %s"), $event->DBServer->serverId, $e->getMessage()), $event->DBServer->serverId)); } }
/** * {@inheritdoc} * @see AbstractServerImport::importServer */ protected function importServer() { $aws = $this->farmRole->getFarm()->getEnvironment()->aws($this->farmRole->cloudLocation); try { $instance = $this->instance = $aws->ec2->instance->describe($this->orphaned->cloudServerId)->get(0)->instancesSet->get(0); $this->server->properties[EC2_SERVER_PROPERTIES::AVAIL_ZONE] = $instance->placement->availabilityZone; $this->server->properties[EC2_SERVER_PROPERTIES::ARCHITECTURE] = $instance->architecture; $this->server->cloudLocationZone = $instance->placement->availabilityZone; $this->server->setOs($instance->platform ? $instance->platform : 'linux'); $this->server->properties[EC2_SERVER_PROPERTIES::INSTANCE_ID] = $this->orphaned->cloudServerId; $this->server->properties[EC2_SERVER_PROPERTIES::VPC_ID] = $this->orphaned->vpcId; $this->server->properties[EC2_SERVER_PROPERTIES::SUBNET_ID] = $this->orphaned->subnetId; $this->server->properties[EC2_SERVER_PROPERTIES::REGION] = $this->server->cloudLocation; $this->server->properties[EC2_SERVER_PROPERTIES::AMIID] = $this->server->imageId; $this->server->instanceTypeName = $this->server->type; $p = PlatformFactory::NewPlatform(SERVER_PLATFORMS::EC2); $instanceTypeInfo = $p->getInstanceType($this->orphaned->instanceType, (new \Scalr_Environment())->loadById($this->server->envId), $this->server->cloudLocation); $this->server->properties[Entity\Server::INFO_INSTANCE_VCPUS] = isset($instanceTypeInfo['vcpus']) ? $instanceTypeInfo['vcpus'] : null; } catch (Exception $e) { throw new ServerImportException(sprintf('Scalr was unable to retrieve details for instance %s: %s', $this->orphaned->cloudServerId, $e->getMessage()), $e->getCode(), $e); } }
/** * List orphaned servers * * @param string $platform Cloud platform * @param string $cloudLocation optional Cloud location */ public function xListAction($platform, $cloudLocation = null) { $orphans = $lookup = []; $p = PlatformFactory::NewPlatform($platform); if (!$this->environment->isPlatformEnabled($platform)) { return $this->response->failure(sprintf("Platform '%s' is not enabled", $platform)); } $orphans = $this->buildResponseFromData($p->getOrphanedServers($this->environment, $cloudLocation), ["cloudServerId", "privateIp", "publicIp"]); foreach ($orphans["data"] as $i => &$orphan) { $orphan["launchTime"] = \Scalr_Util_DateTime::convertTz($orphan["launchTime"]); $orphan["imageHash"] = null; $orphan["imageName"] = null; $lookup[$orphan["imageId"]] = $i; } if (!empty($lookup)) { /* @var $image Scalr\Model\Entity\Image */ foreach (Image::find([["status" => Image::STATUS_ACTIVE], ["id" => ['$in' => array_keys($lookup)]]]) as $image) { $orphans["data"][$lookup[$image->id]]["imageHash"] = $image->hash; $orphans["data"][$lookup[$image->id]]["imageName"] = $image->name; } } $this->response->data($orphans); }
public function xListAddressesAction() { $this->request->defineParams(array('sort' => array('type' => 'json', 'default' => array('property' => 'id', 'direction' => 'ASC')), 'addressId')); $platform = PlatformFactory::NewPlatform(SERVER_PLATFORMS::GCE); $client = $platform->getClient($this->environment); /* @var $client Google_Service_Compute */ $retval = array(); $addresses = $client->addresses->listAddresses($this->environment->getPlatformConfigValue(GoogleCEPlatformModule::PROJECT_ID), $this->getParam('cloudLocation')); foreach ($addresses as $address) { /* @var $address Google_Service_Compute_Address */ if ($this->getParam('addressId') && $this->getParam('addressId') != $address->name) { continue; } $item = array('id' => $address->name, 'ip' => $address->address, 'description' => $address->description, 'createdAt' => Scalr_Util_DateTime::convertTz(strtotime($address->creationTimestamp)), 'status' => $address->status); if ($item['status'] == 'IN_USE') { $instanceURL = $address->users[0]; $instanceName = substr($instanceURL, strrpos($instanceURL, "/") + 1); $item['instanceId'] = $instanceName; try { $dbServer = DBServer::LoadByID($item['instanceId']); if ($dbServer && $dbServer->envId == $this->environment->id) { $item['farmId'] = $dbServer->farmId; $item['farmName'] = $dbServer->GetFarmObject()->Name; $item['farmRoleId'] = $dbServer->farmRoleId; $item['roleName'] = $dbServer->GetFarmRoleObject()->GetRoleObject()->name; $item['serverIndex'] = $dbServer->index; $item['serverId'] = $dbServer->serverId; } } catch (Exception $e) { } } $retval[] = $item; } $response = $this->buildResponseFromData($retval, array('id', 'ip', 'description')); $this->response->data($response); }
/** * @param string $cloudLocation * @param string $addressId optional */ public function xListAction($cloudLocation, $addressId = '') { $platform = PlatformFactory::NewPlatform(SERVER_PLATFORMS::GCE); $client = $platform->getClient($this->environment); /* @var $client Google_Service_Compute */ $retval = array(); $addresses = $client->addresses->listAddresses($this->environment->keychain(SERVER_PLATFORMS::GCE)->properties[Entity\CloudCredentialsProperty::GCE_PROJECT_ID], $cloudLocation, $addressId ? ['filter' => "name eq {$addressId}"] : []); foreach ($addresses as $address) { /* @var $address Google_Service_Compute_Address */ $item = array('id' => $address->name, 'ip' => ip2long($address->address), 'description' => $address->description, 'createdAt' => strtotime($address->creationTimestamp), 'status' => $address->status); if ($item['status'] == 'IN_USE') { $instanceURL = $address->users[0]; $instanceName = substr($instanceURL, strrpos($instanceURL, "/") + 1); $item['instanceId'] = $instanceName; try { $dbServer = DBServer::LoadByID($item['instanceId']); if ($dbServer && $dbServer->envId == $this->environment->id) { $item['farmId'] = $dbServer->farmId; $item['farmName'] = $dbServer->GetFarmObject()->Name; $item['farmRoleId'] = $dbServer->farmRoleId; $item['roleName'] = $dbServer->GetFarmRoleObject()->GetRoleObject()->name; $item['serverIndex'] = $dbServer->index; $item['serverId'] = $dbServer->serverId; } } catch (Exception $e) { } } $retval[] = $item; } $response = $this->buildResponseFromData($retval, array('id', 'ip', 'description', 'createdAt')); foreach ($response['data'] as &$row) { $row['createdAt'] = Scalr_Util_DateTime::convertTz($row['createdAt']); $row['ip'] = long2ip($row['ip']); } $this->response->data($response); }
/** * Sets floating IP for openstack server * * @param \DBServer $DBServer The server object */ public static function setServerFloatingIp(\DBServer $DBServer) { $ipPool = $DBServer->GetFarmRoleObject()->GetSetting(Entity\FarmRoleSetting::OPENSTACK_IP_POOL); if (!$DBServer->remoteIp && in_array($DBServer->status, array(\SERVER_STATUS::PENDING, \SERVER_STATUS::INIT, \SERVER_STATUS::SUSPENDED)) && $ipPool) { //$ipAddress = \Scalr\Modules\Platforms\Openstack\Helpers\OpenstackHelper::setFloatingIpForServer($DBServer); $osClient = $DBServer->GetEnvironmentObject()->openstack($DBServer->platform, $DBServer->GetProperty(\OPENSTACK_SERVER_PROPERTIES::CLOUD_LOCATION)); if ($osClient->hasService('network')) { $platform = PlatformFactory::NewPlatform($DBServer->platform); $serverIps = $platform->GetServerIPAddresses($DBServer); // USE Quantum (Neuron) NETWORK $ips = $osClient->network->floatingIps->list(); //Check free existing IP $ipAssigned = false; $ipAddress = false; $ipInfo = false; foreach ($ips as $ip) { if ($ip->floating_network_id != $ipPool) { continue; } if ($ip->fixed_ip_address == $serverIps['localIp'] && $ip->port_id) { $ipAssigned = true; $ipInfo = $ip; break; } if (!$ip->fixed_ip_address && $ip->floating_ip_address && !$ip->port_id) { // Checking that FLoating IP has the same tenant as auth user if ($ip->tenant_id && $ip->tenant_id == $osClient->getConfig()->getAuthToken()->getTenantId()) { $ipInfo = $ip; } } } if ($ipInfo && !$ipAssigned) { \Scalr::getContainer()->logger("Openstack")->warn(new FarmLogMessage($DBServer, sprintf("Found free floating IP: %s for use", !empty($ipInfo->floating_ip_address) ? $ipInfo->floating_ip_address : null))); } if (!$ipInfo || !$ipAssigned) { // Get instance port $ports = $osClient->network->ports->list(); $serverNetworkPort = []; foreach ($ports as $port) { if ($port->device_id == $DBServer->GetProperty(\OPENSTACK_SERVER_PROPERTIES::SERVER_ID)) { $serverNetworkPort[] = $port; } } if (empty($serverNetworkPort)) { \Scalr::getContainer()->logger("Openstack")->error(new FarmLogMessage($DBServer, "Unable to identify network port of instance")); } else { $publicNetworkId = $ipPool; while (!empty($serverNetworkPort)) { try { $port = array_shift($serverNetworkPort); if (!$ipInfo) { $ipInfo = $osClient->network->floatingIps->create($publicNetworkId, $port->id); \Scalr::getContainer()->logger("Openstack")->warn(new FarmLogMessage($DBServer, sprintf("Allocated new IP %s for port: %s", !empty($ipInfo->floating_ip_address) ? $ipInfo->floating_ip_address : null, !empty($port->id) ? $port->id : null))); } else { $osClient->network->floatingIps->update($ipInfo->id, $port->id); \Scalr::getContainer()->logger("Openstack")->warn(new FarmLogMessage($DBServer, sprintf("Existing floating IP %s was used for port: %s", !empty($ipInfo->floating_ip_address) ? $ipInfo->floating_ip_address : null, !empty($port->id) ? $port->id : null))); } $DBServer->SetProperties(array(\OPENSTACK_SERVER_PROPERTIES::FLOATING_IP => $ipInfo->floating_ip_address, \OPENSTACK_SERVER_PROPERTIES::FLOATING_IP_ID => $ipInfo->id)); $ipAddress = $ipInfo->floating_ip_address; break; } catch (Exception $e) { \Scalr::getContainer()->logger("OpenStackObserver")->error(sprintf("Farm: %d, Server: %s - Could not allocate/update floating IP: %s (%s, %s)", $DBServer->farmId, $DBServer->serverId, $e->getMessage(), json_encode($ipInfo), $osClient->getConfig()->getAuthToken()->getTenantId())); } } } } else { \Scalr::getContainer()->logger("Openstack")->warn(new FarmLogMessage($DBServer, sprintf("Server '%s' already has IP '%s' assigned", $DBServer->serverId, !empty($ipInfo->floating_ip_address) ? $ipInfo->floating_ip_address : null))); $ipAddress = $ipInfo->floating_ip_address; } } else { //USE NOVA NETWORK //Check free existing IP $ipAssigned = false; $ipAddress = false; $ips = $osClient->servers->floatingIps->list($ipPool); foreach ($ips as $ip) { if (!$ip->instance_id) { $ipAddress = $ip->ip; $ipAddressId = $ip->id; } if ($ip->instance_id == $DBServer->GetProperty(\OPENSTACK_SERVER_PROPERTIES::SERVER_ID)) { $ipAddress = $ip->ip; $ipAssigned = true; } } //If no free IP allocate new from pool if (!$ipAddress) { $ip = $osClient->servers->floatingIps->create($ipPool); $ipAddress = $ip->ip; $ipAddressId = $ip->id; } if (!$ipAssigned) { //Associate floating IP with Instance $osClient->servers->addFloatingIp($DBServer->GetCloudServerID(), $ipAddress); $DBServer->SetProperties(array(\OPENSTACK_SERVER_PROPERTIES::FLOATING_IP => $ipAddress, \OPENSTACK_SERVER_PROPERTIES::FLOATING_IP_ID => $ipAddressId)); } } if ($ipAddress) { $DBServer->remoteIp = $ipAddress; $DBServer->Save(); $DBServer->SetProperty(\SERVER_PROPERTIES::SYSTEM_IGNORE_INBOUND_MESSAGES, null); } } }
public function deleteCloudImage() { return PlatformFactory::NewPlatform($this->platform)->RemoveServerSnapshot($this); }
public function OnHostInit(HostInitEvent $event) { $msg = new Scalr_Messaging_Msg_HostInitResponse($event->DBServer->GetFarmObject()->GetSetting(DBFarm::SETTING_CRYPTO_KEY), $event->DBServer->index); $msg->cloudLocation = $event->DBServer->GetCloudLocation(); $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(DBFarmRole::SETTING_MYSQL_ROOT_PASSWORD), "replPassword" => $dbFarmRole->GetSetting(DBFarmRole::SETTING_MYSQL_REPL_PASSWORD), "statPassword" => $dbFarmRole->GetSetting(DBFarmRole::SETTING_MYSQL_STAT_PASSWORD), "logFile" => $dbFarmRole->GetSetting(DBFarmRole::SETTING_MYSQL_LOG_FILE), "logPos" => $dbFarmRole->GetSetting(DBFarmRole::SETTING_MYSQL_LOG_POS)); if ($event->DBServer->IsSupported("0.7")) { if ($dbFarmRole->GetSetting(DBFarmRole::SETTING_MYSQL_SCALR_VOLUME_ID) && $isMaster) { try { $volume = Scalr_Storage_Volume::init()->loadById($dbFarmRole->GetSetting(DBFarmRole::SETTING_MYSQL_SCALR_VOLUME_ID)); $msg->mysql->volumeConfig = $volume->getConfig(); } catch (Exception $e) { } } /*** * For Rackspace we ALWAYS need snapsjot_config for mysql * ***/ if ($dbFarmRole->GetSetting(DBFarmRole::SETTING_MYSQL_SCALR_SNAPSHOT_ID)) { try { $snapshotConfig = Scalr_Storage_Snapshot::init()->loadById($dbFarmRole->GetSetting(DBFarmRole::SETTING_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()}")); } } if (!$msg->mysql->snapshotConfig && $dbFarmRole->GetSetting(DBFarmRole::SETTING_MYSQL_SNAPSHOT_ID)) { $msg->mysql->snapshotConfig = new stdClass(); $msg->mysql->snapshotConfig->type = $dbFarmRole->GetSetting(DBFarmRole::SETTING_MYSQL_DATA_STORAGE_ENGINE); $msg->mysql->snapshotConfig->id = $dbFarmRole->GetSetting(DBFarmRole::SETTING_MYSQL_SNAPSHOT_ID); } if ($isMaster && !$msg->mysql->volumeConfig) { $msg->mysql->volumeConfig = new stdClass(); $msg->mysql->volumeConfig->type = $dbFarmRole->GetSetting(DBFarmRole::SETTING_MYSQL_DATA_STORAGE_ENGINE); if (!$dbFarmRole->GetSetting(DBFarmRole::SETTING_MYSQL_MASTER_EBS_VOLUME_ID)) { if (in_array($dbFarmRole->GetSetting(DBFarmRole::SETTING_MYSQL_DATA_STORAGE_ENGINE), array(MYSQL_STORAGE_ENGINE::EBS, MYSQL_STORAGE_ENGINE::CSVOL))) { $msg->mysql->volumeConfig->size = $dbFarmRole->GetSetting(DBFarmRole::SETTING_MYSQL_EBS_VOLUME_SIZE); if ($dbFarmRole->GetSetting(DBFarmRole::SETTING_MYSQL_DATA_STORAGE_ENGINE) == MYSQL_STORAGE_ENGINE::EBS) { $msg->mysql->volumeConfig->volumeType = $dbFarmRole->GetSetting(DBFarmRole::SETTING_MYSQL_EBS_TYPE); if ($msg->mysql->volumeConfig->volumeType == 'io1') { $msg->mysql->volumeConfig->iops = $dbFarmRole->GetSetting(DBFarmRole::SETTING_MYSQL_EBS_IOPS); } } } elseif ($dbFarmRole->GetSetting(DBFarmRole::SETTING_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(DBFarmRole::SETTING_MYSQL_MASTER_EBS_VOLUME_ID); } } } else { if ($isMaster) { $msg->mysql->volumeId = $dbFarmRole->GetSetting(DBFarmRole::SETTING_MYSQL_MASTER_EBS_VOLUME_ID); } $msg->mysql->snapshotId = $dbFarmRole->GetSetting(DBFarmRole::SETTING_MYSQL_SNAPSHOT_ID); } } // Create ssh keypair for rackspace if ($event->DBServer->IsSupported("0.7")) { $authSshKey = $event->DBServer->platform == SERVER_PLATFORMS::RACKSPACE || $event->DBServer->platform == SERVER_PLATFORMS::NIMBULA || $event->DBServer->isCloudstack(); if ($event->DBServer->isOpenstack()) { $platform = PlatformFactory::NewPlatform($event->DBServer->platform); $isKeyPairsSupported = $platform->getConfigVariable(OpenstackPlatformModule::EXT_KEYPAIRS_ENABLED, $event->DBServer->GetEnvironmentObject(), false); if ($isKeyPairsSupported != 1) { $authSshKey = true; } } if ($authSshKey) { $sshKey = Scalr_SshKey::init(); if (!$sshKey->loadGlobalByFarmId($event->DBServer->envId, $event->DBServer->farmId, $event->DBServer->GetFarmRoleObject()->CloudLocation, $event->DBServer->platform)) { $key_name = "FARM-{$event->DBServer->farmId}-" . SCALR_ID; $sshKey->generateKeypair(); $sshKey->farmId = $event->DBServer->farmId; $sshKey->envId = $event->DBServer->envId; $sshKey->type = Scalr_SshKey::TYPE_GLOBAL; $sshKey->platform = $event->DBServer->platform; $sshKey->cloudLocation = $event->DBServer->GetFarmRoleObject()->CloudLocation; $sshKey->cloudKeyName = $key_name; $sshKey->platform = $event->DBServer->platform; $sshKey->save(); } $sshKeysMsg = new Scalr_Messaging_Msg_UpdateSshAuthorizedKeys(array($sshKey->getPublic()), 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++; } } }
/** * {@inheritdoc} * @see \Scalr\System\Zmq\Cron\TaskInterface::worker() */ public function worker($request) { //Warming up static DI cache \Scalr::getContainer()->warmup(); // Reconfigure observers \Scalr::ReconfigureObservers(); if (!isset($request->farmRoleId)) { //This is the farm with synchronous launch of roles try { $DBFarm = DBFarm::LoadByID($request->farmId); if ($DBFarm->Status != FARM_STATUS::RUNNING) { $this->getLogger()->warn("[FarmID: %d] Farm isn't running. There is no need to scale it.", $DBFarm->ID); return false; } } catch (Exception $e) { $this->getLogger()->error("Could not load farm '%s' with ID:%d", $request->farmName, $request->farmId); throw $e; } //Gets the list of the roles $list = $DBFarm->GetFarmRoles(); } else { //This is asynchronous lauhch try { $DBFarmRole = DBFarmRole::LoadByID($request->farmRoleId); if ($DBFarmRole->getFarmStatus() != FARM_STATUS::RUNNING) { //We don't need to handle inactive farms return false; } } catch (Exception $e) { $this->getLogger()->error("Could not load FarmRole with ID:%d", $request->farmRoleId); throw $e; } $list = [$DBFarmRole]; } $this->getLogger()->debug("Processing %s FarmRoles", count($list)); foreach ($list as $DBFarmRole) { // Set Last polling time $DBFarmRole->SetSetting(Entity\FarmRoleSetting::SCALING_LAST_POLLING_TIME, time(), Entity\FarmRoleSetting::TYPE_LCL); $disabledScaling = false; if ($DBFarmRole->GetSetting(Entity\FarmRoleSetting::SCALING_ENABLED) != '1') { if ($DBFarmRole->GetRoleObject()->hasBehavior(ROLE_BEHAVIORS::RABBITMQ) || $DBFarmRole->GetRoleObject()->hasBehavior(ROLE_BEHAVIORS::VPC_ROUTER)) { // For Mongo, RabbitMQ and VPC Router we need to launch first instance (or maintain 1 instance running) // When 1 instance is already running, the rest is fully manual $roleTotalInstances = $DBFarmRole->GetRunningInstancesCount() + $DBFarmRole->GetPendingInstancesCount(); if ($roleTotalInstances != 0) { $disabledScaling = true; } } else { if (!$DBFarmRole->GetRoleObject()->hasBehavior(ROLE_BEHAVIORS::MONGODB)) { $disabledScaling = true; } } if ($disabledScaling) { $this->getLogger()->info("[FarmID: %d] Scaling is disabled for role '%s'. Skipping...", $request->farmId, $DBFarmRole->Alias); continue; } } $farmRoleName = $DBFarmRole->Alias ? $DBFarmRole->Alias : $DBFarmRole->GetRoleObject()->name; // Get current count of running and pending instances. $this->getLogger()->info(sprintf("Processing role '%s'", $farmRoleName)); $scalingManager = new Scalr_Scaling_Manager($DBFarmRole); //Replacing the logger $scalingManager->logger = $this->getLogger(); $scalingDecision = $scalingManager->makeScalingDecision(); $scalingDecisionDetails = $scalingManager->decisonInfo; $this->getLogger()->info(sprintf("Decision '%s' (%s)", $scalingDecision, $scalingDecisionDetails)); if ($scalingDecision == Scalr_Scaling_Decision::STOP_SCALING) { return; } if ($scalingDecision == Scalr_Scaling_Decision::NOOP) { continue; } else { if ($scalingDecision == Scalr_Scaling_Decision::DOWNSCALE) { /* Timeout instance's count decrease. Decreases instances count after scaling resolution the spare instances are running for selected timeout interval from scaling EditOptions */ // We have to check timeout limits before new scaling (downscaling) process will be initiated if ($DBFarmRole->GetSetting(Entity\FarmRoleSetting::SCALING_DOWNSCALE_TIMEOUT_ENABLED)) { // if the farm timeout is exceeded // checking timeout interval. $last_down_scale_data_time = $DBFarmRole->GetSetting(Entity\FarmRoleSetting::SCALING_DOWNSCALE_DATETIME); $timeout_interval = $DBFarmRole->GetSetting(Entity\FarmRoleSetting::SCALING_DOWNSCALE_TIMEOUT); // check the time interval to continue scaling or cancel it... if (time() - $last_down_scale_data_time < $timeout_interval * 60) { // if the launch time is too small to terminate smth in this role -> go to the next role in foreach() \Scalr::getContainer()->logger(LOG_CATEGORY::FARM)->info(new FarmLogMessage(!empty($request->farmId) ? $request->farmId : null, sprintf("Waiting for downscaling timeout on farm %s, role %s", !empty($request->farmName) ? $request->farmName : null, !empty($DBFarmRole->Alias) ? $DBFarmRole->Alias : null), null, null, !empty($DBFarmRole->ID) ? $DBFarmRole->ID : null)); continue; } } // end Timeout instance's count decrease $sort = $DBFarmRole->GetSetting(Entity\FarmRoleSetting::SCALING_KEEP_OLDEST) == 1 ? 'DESC' : 'ASC'; $servers = $this->db->GetAll("SELECT server_id FROM servers WHERE status = ? AND farm_roleid=? ORDER BY dtadded {$sort}", array(SERVER_STATUS::RUNNING, $DBFarmRole->ID)); $got_valid_instance = false; $ignoreFullHour = $DBFarmRole->GetSetting(Entity\FarmRoleSetting::SCALING_IGNORE_FULL_HOUR); $useSafeShutdown = $DBFarmRole->GetSetting(Entity\FarmRoleSetting::SCALING_SAFE_SHUTDOWN); $isRabbitMQ = $DBFarmRole->GetRoleObject()->hasBehavior(ROLE_BEHAVIORS::RABBITMQ); // Select instance that will be terminated // // Instances ordered by uptime (oldest wil be choosen) // Instance cannot be mysql master // Choose the one that was rebundled recently $DBServer = null; while (!$got_valid_instance && count($servers) > 0) { $item = array_shift($servers); $DBServer = DBServer::LoadByID($item['server_id']); if ($isRabbitMQ) { $serverExists = $this->db->GetOne("\n SELECT EXISTS (\n SELECT 1 FROM servers\n WHERE farm_roleid = ?\n AND status NOT IN (?, ?)\n AND `index` != ?\n )\n ", [$DBServer->farmRoleId, SERVER_STATUS::TERMINATED, SERVER_STATUS::SUSPENDED, 1]); if ($DBServer->index == 1 && $serverExists) { continue; } } if ($DBServer->GetProperty(EC2_SERVER_PROPERTIES::IS_LOCKED)) { continue; } // Exclude db master if ($DBServer->GetProperty(SERVER_PROPERTIES::DB_MYSQL_MASTER) != 1 && $DBServer->GetProperty(Scalr_Db_Msr::REPLICATION_MASTER) != 1) { $got_valid_instance = true; } //Check safe shutdown if ($useSafeShutdown == 1) { try { $res = $DBServer->scalarizr->system->callAuthShutdownHook(); } catch (Exception $e) { $res = $e->getMessage(); } if ($res != '1') { \Scalr::getContainer()->logger(LOG_CATEGORY::FARM)->info(new FarmLogMessage($DBServer->farmId, sprintf("Safe shutdown enabled. Server '%s'. Script returned '%s' skipping it.", $DBServer->serverId, $res), $DBServer->serverId, $DBServer->envId, $DBServer->farmRoleId)); $got_valid_instance = false; } } } // end while if ($DBServer !== null && $got_valid_instance) { $this->getLogger()->info(sprintf("Server '%s' selected for termination...", $DBServer->serverId)); $allow_terminate = false; if ($DBServer->platform == SERVER_PLATFORMS::EC2) { $aws = $DBServer->GetEnvironmentObject()->aws($DBServer); // Shutdown an instance just before a full hour running if (!$ignoreFullHour) { $response = $aws->ec2->instance->describe($DBServer->GetProperty(EC2_SERVER_PROPERTIES::INSTANCE_ID))->get(0); if ($response && count($response->instancesSet)) { $launch_time = $response->instancesSet->get(0)->launchTime->getTimestamp(); $time = 3600 - (time() - $launch_time) % 3600; // Terminate instance in < 10 minutes for full hour. if ($time <= 600) { $allow_terminate = true; } else { $timeout = round(($time - 600) / 60, 1); \Scalr::getContainer()->logger(LOG_CATEGORY::FARM)->info(new FarmLogMessage($request->farmId, sprintf("Role '%s' scaling down (%s). Server '%s' will be terminated in %s minutes. Launch time: %s", $DBServer->GetFarmRoleObject()->Alias, $scalingDecisionDetails, $DBServer->serverId, $timeout, $response->instancesSet->get(0)->launchTime->format('c')), $DBServer->serverId, $DBServer->envId, $DBServer->farmRoleId)); } } } else { $allow_terminate = true; } //Releases memory $DBServer->GetEnvironmentObject()->getContainer()->release('aws'); unset($aws); } else { $allow_terminate = true; } if ($allow_terminate) { $terminateStrategy = $DBFarmRole->GetSetting(Scalr_Role_Behavior::ROLE_BASE_TERMINATE_STRATEGY); if (!$terminateStrategy) { $terminateStrategy = 'terminate'; } try { if ($terminateStrategy == 'terminate') { $DBServer->terminate(DBServer::TERMINATE_REASON_SCALING_DOWN, false); $DBFarmRole->SetSetting(Entity\FarmRoleSetting::SCALING_DOWNSCALE_DATETIME, time(), Entity\FarmRoleSetting::TYPE_LCL); \Scalr::getContainer()->logger(LOG_CATEGORY::FARM)->info(new FarmLogMessage($request->farmId, sprintf("Role '%s' scaling down (%s). Server '%s' marked as 'Pending terminate' and will be fully terminated in 3 minutes.", $DBServer->GetFarmRoleObject()->Alias, $scalingDecisionDetails, $DBServer->serverId), $DBServer->serverId, $DBServer->envId, $DBServer->farmRoleId)); } else { $DBServer->suspend('SCALING_DOWN', false); $DBFarmRole->SetSetting(Entity\FarmRoleSetting::SCALING_DOWNSCALE_DATETIME, time(), Entity\FarmRoleSetting::TYPE_LCL); \Scalr::getContainer()->logger(LOG_CATEGORY::FARM)->info(new FarmLogMessage($request->farmId, sprintf("Role '%s' scaling down (%s). Server '%s' marked as 'Pending suspend' and will be fully suspended in 3 minutes.", $DBServer->GetFarmRoleObject()->Alias, $scalingDecisionDetails, $DBServer->serverId), $DBServer->serverId, $DBServer->envId, $DBServer->farmRoleId)); } } catch (Exception $e) { $this->getLogger()->fatal(sprintf("Cannot %s %s: %s", $terminateStrategy, $request->farmId, $DBServer->serverId)); } } } else { $this->getLogger()->warn(sprintf("[FarmID: %s] Scalr unable to determine what instance it should terminate (FarmRoleID: %s). Skipping...", $request->farmId, $DBFarmRole->ID)); } //break; } elseif ($scalingDecision == Scalr_Scaling_Decision::UPSCALE) { /* Timeout instance's count increase. Increases instance's count after scaling resolution 'need more instances' for selected timeout interval from scaling EditOptions */ if ($DBFarmRole->GetSetting(Entity\FarmRoleSetting::SCALING_UPSCALE_TIMEOUT_ENABLED)) { // if the farm timeout is exceeded // checking timeout interval. $last_up_scale_data_time = $DBFarmRole->GetSetting(Entity\FarmRoleSetting::SCALING_UPSCALE_DATETIME); $timeout_interval = $DBFarmRole->GetSetting(Entity\FarmRoleSetting::SCALING_UPSCALE_TIMEOUT); // check the time interval to continue scaling or cancel it... if (time() - $last_up_scale_data_time < $timeout_interval * 60) { // if the launch time is too small to terminate smth in this role -> go to the next role in foreach() \Scalr::getContainer()->logger(LOG_CATEGORY::FARM)->info(sprintf("Waiting for upscaling timeout on farm %s, role %s", $request->farmName, $DBFarmRole->Alias)); continue; } } // end Timeout instance's count increase //Check DBMsr. Do not start slave during slave2master process $isDbMsr = $DBFarmRole->GetRoleObject()->getDbMsrBehavior(); if ($isDbMsr) { if ($DBFarmRole->GetSetting(Scalr_Db_Msr::SLAVE_TO_MASTER)) { $runningServers = $DBFarmRole->GetRunningInstancesCount(); if ($runningServers > 0) { \Scalr::getContainer()->logger(LOG_CATEGORY::FARM)->warn(new FarmLogMessage($request->farmId, sprintf("Role is in slave2master promotion process. Do not launch new slaves while there is no active slaves"))); continue; } else { $DBFarmRole->SetSetting(Scalr_Db_Msr::SLAVE_TO_MASTER, 0, Entity\FarmRoleSetting::TYPE_LCL); } } } if ($DBFarmRole->GetSetting(Entity\FarmRoleSetting::SCALING_ONE_BY_ONE) == 1) { $pendingInstances = $DBFarmRole->GetPendingInstancesCount(); if ($pendingInstances > 0) { \Scalr::getContainer()->logger(LOG_CATEGORY::FARM)->info(new FarmLogMessage($request->farmId, sprintf("There are %s pending intances of %s role on % farm. Waiting...", $pendingInstances, $DBFarmRole->Alias, $request->farmName))); continue; } } $fstatus = $this->db->GetOne("SELECT status FROM farms WHERE id=? LIMIT 1", array($request->farmId)); if ($fstatus != FARM_STATUS::RUNNING) { $this->getLogger()->warn("[FarmID: {$request->farmId}] Farm terminated. There is no need to scale it."); return; } $terminateStrategy = $DBFarmRole->GetSetting(Scalr_Role_Behavior::ROLE_BASE_TERMINATE_STRATEGY); if (!$terminateStrategy) { $terminateStrategy = 'terminate'; } $suspendedServer = null; if ($terminateStrategy == 'suspend') { $suspendedServers = $DBFarmRole->GetServersByFilter(array('status' => SERVER_STATUS::SUSPENDED)); if (count($suspendedServers) > 0) { $suspendedServer = array_shift($suspendedServers); } } if ($terminateStrategy == 'suspend' && $suspendedServer) { \Scalr::getContainer()->logger(LOG_CATEGORY::FARM)->warn(new FarmLogMessage($request->farmId, sprintf("Role '%s' scaling up (%s). Found server to resume. ServerID = %s.", $suspendedServer->GetFarmRoleObject()->Alias, $scalingDecisionDetails, $suspendedServer->serverId), $suspendedServer->serverId, $suspendedServer->envId, $suspendedServer->farmRoleId)); } if ($terminateStrategy == 'terminate' || !$suspendedServer || !PlatformFactory::isOpenstack($suspendedServer->platform) && $suspendedServer->platform != SERVER_PLATFORMS::EC2 && $suspendedServer->platform != SERVER_PLATFORMS::GCE) { $ServerCreateInfo = new ServerCreateInfo($DBFarmRole->Platform, $DBFarmRole); try { $DBServer = \Scalr::LaunchServer($ServerCreateInfo, null, false, DBServer::LAUNCH_REASON_SCALING_UP); $DBFarmRole->SetSetting(Entity\FarmRoleSetting::SCALING_UPSCALE_DATETIME, time(), Entity\FarmRoleSetting::TYPE_LCL); \Scalr::getContainer()->logger(LOG_CATEGORY::FARM)->info(new FarmLogMessage($request->farmId, sprintf("Role '%s' scaling up (%s). Starting new instance. ServerID = %s.", $DBServer->GetFarmRoleObject()->Alias, $scalingDecisionDetails, $DBServer->serverId), $DBServer->serverId, $DBServer->envId, $DBServer->farmRoleId)); } catch (Exception $e) { \Scalr::getContainer()->logger(LOG_CATEGORY::SCALING)->error($e->getMessage()); } } else { $platform = PlatformFactory::NewPlatform($suspendedServer->platform); $platform->ResumeServer($suspendedServer); } } } } return true; }