예제 #1
0
파일: RoleImage.php 프로젝트: scalr/scalr
 /**
  * @deprecated Use method FarmRole::getImage
  *
  * @return Image|NULL
  * @throws \Exception
  */
 public function getImage()
 {
     /* @var $role Role */
     $role = Role::findPk($this->roleId);
     $criteria = [['id' => $this->imageId], ['platform' => $this->platform], ['cloudLocation' => $this->cloudLocation], ['$or' => [['accountId' => null], ['$and' => [['accountId' => $role->accountId], ['$or' => [['envId' => null], ['envId' => $role->envId]]]]]]]];
     return Image::findOne($criteria);
 }
예제 #2
0
파일: Images.php 프로젝트: scalr/scalr
 /**
  * Checks whether Image does exist in the user's scope
  *
  * @param    string     $cloudImageId   The identifier of the image on the Cloud
  * @param    string     $platform       The cloud platform
  * @param    string     $cloudLocation  The cloud location
  * @return   bool Returns TRUE if image exists in the user's scope
  * @throws   ApiErrorException
  */
 public function getImageByCloudId($cloudImageId, $platform, $cloudLocation)
 {
     $criteria = array_merge($this->getDefaultCriteria(), [['id' => $cloudImageId], ['platform' => $platform], ['cloudLocation' => $cloudLocation]]);
     $image = Entity\Image::findOne($criteria);
     if (!$image) {
         throw new ApiErrorException(404, ErrorMessage::ERR_OBJECT_NOT_FOUND, "Requested Image either does not exist or is not owned by your environment.");
     }
     return $image;
 }
예제 #3
0
 protected function run1($stage)
 {
     $this->db->Execute("CREATE TABLE `image_software` (\n              `id` int(11) unsigned NOT NULL AUTO_INCREMENT,\n              `image_hash` binary(16) NOT NULL DEFAULT '',\n              `name` varchar(45) NOT NULL DEFAULT '',\n              `version` varchar(20) DEFAULT NULL,\n              PRIMARY KEY (`id`),\n              KEY `idx_image_hash` (`image_hash`)\n            ) ENGINE=InnoDB DEFAULT CHARSET=latin1;\n        ");
     $this->db->Execute('ALTER TABLE image_software ADD CONSTRAINT `fk_images_hash_image_software` FOREIGN KEY (`image_hash`) REFERENCES `images` (`hash`) ON DELETE CASCADE ON UPDATE NO ACTION');
     foreach ($this->db->GetAll('SELECT role_images.*, roles.env_id FROM role_images LEFT JOIN roles ON roles.id = role_images.role_id') as $image) {
         $props = [];
         foreach ($this->db->GetAll('SELECT * FROM role_software WHERE role_id = ?', [$image['role_id']]) as $soft) {
             if ($soft['software_name']) {
                 $name = explode(' ', trim($soft['software_name'], '*- '));
                 $version = $soft['software_version'];
                 if (count($name) > 1) {
                     $version = $name[1];
                     $name = strtolower($name[0]);
                 } else {
                     $name = strtolower($name[0]);
                 }
                 if (preg_match('/^[a-z]+$/', $name)) {
                     $props[$name] = $version;
                 }
             }
         }
         if (empty($props)) {
             // check role behaviours
             $beh = $this->db->GetCol('SELECT behavior FROM role_behaviors WHERE role_id = ?', [$image['role_id']]);
             foreach ($beh as $b) {
                 if (in_array($b, [\ROLE_BEHAVIORS::MYSQL, \ROLE_BEHAVIORS::PERCONA, \ROLE_BEHAVIORS::TOMCAT, \ROLE_BEHAVIORS::MEMCACHED, \ROLE_BEHAVIORS::POSTGRESQL, \ROLE_BEHAVIORS::REDIS, \ROLE_BEHAVIORS::RABBITMQ, \ROLE_BEHAVIORS::MONGODB, \ROLE_BEHAVIORS::CHEF, \ROLE_BEHAVIORS::MYSQLPROXY, \ROLE_BEHAVIORS::HAPROXY, \ROLE_BEHAVIORS::MARIADB])) {
                     $props[$b] = null;
                 } else {
                     if ($b == \ROLE_BEHAVIORS::MYSQL2) {
                         $props['mysql'] = null;
                     } else {
                         if ($b == \ROLE_BEHAVIORS::NGINX) {
                             $props['nginx'] = null;
                         } else {
                             if ($b == \ROLE_BEHAVIORS::APACHE) {
                                 $props['apache'] = null;
                             }
                         }
                     }
                 }
             }
         }
         $obj = Image::findOne([['id' => $image['image_id']], ['envId' => $image['env_id'] == 0 ? NULL : $image['env_id']], ['platform' => $image['platform']], ['cloudLocation' => $image['cloud_location']]]);
         /* @var Image $obj */
         if ($obj) {
             $obj->setSoftware($props);
         } else {
             if (!Image::findOne([['id' => $image['image_id']], ['envId' => NULL], ['platform' => $image['platform']], ['cloudLocation' => $image['cloud_location']]])) {
                 $this->console->warning('Image not found: %s', $image['image_id']);
             }
         }
     }
     $this->db->Execute('RENAME TABLE role_software TO role_software_deleted');
 }
예제 #4
0
 public function xAttachAction()
 {
     $aws = $this->getEnvironment()->aws($this->getParam('cloudLocation'));
     $this->request->defineParams(array('cloudLocation', 'serverId', 'volumeId', 'mount', 'mountPoint'));
     $errmsg = null;
     try {
         $dbEbsVolume = DBEBSVolume::loadByVolumeId($this->getParam('volumeId'));
         if ($dbEbsVolume->isManual == 0) {
             $errmsg = sprintf(_("This volume was automatically created for role '%s' on farm '%s' and cannot be re-attahced manually."), $this->db->GetOne("\n                        SELECT name FROM roles\n                        JOIN farm_roles ON farm_roles.role_id = roles.id\n                        WHERE farm_roles.id=?\n                        LIMIT 1\n                    ", array($dbEbsVolume->farmRoleId)), $this->db->GetOne("SELECT name FROM farms WHERE id=? LIMIT 1", array($dbEbsVolume->farmId)));
         }
     } catch (Exception $e) {
     }
     if (!empty($errmsg)) {
         throw new Exception($errmsg);
     }
     /* @var $info VolumeData */
     $info = $aws->ec2->volume->describe($this->getParam('volumeId'))->get(0);
     $dBServer = DBServer::LoadByID($this->getParam('serverId'));
     $image = Image::findOne([['platform' => $dBServer->platform], ['id' => $dBServer->imageId], ['cloudLocation' => $dBServer->GetCloudLocation()]]);
     $device = $dBServer->GetFreeDeviceName($image->isEc2HvmImage());
     $res = $info->attach($dBServer->GetProperty(EC2_SERVER_PROPERTIES::INSTANCE_ID), $device);
     if ($this->getParam('attachOnBoot') == 'on') {
         $dbEbsVolume = new DBEBSVolume();
         $dbEbsVolume->attachmentStatus = EC2_EBS_ATTACH_STATUS::ATTACHING;
         $dbEbsVolume->isManual = true;
         $dbEbsVolume->volumeId = $info->volumeId;
         $dbEbsVolume->ec2AvailZone = $info->availabilityZone;
         $dbEbsVolume->ec2Region = $this->getParam('cloudLocation');
         $dbEbsVolume->deviceName = $device;
         $dbEbsVolume->farmId = $dBServer->farmId;
         $dbEbsVolume->farmRoleId = $dBServer->farmRoleId;
         $dbEbsVolume->serverId = $dBServer->serverId;
         $dbEbsVolume->serverIndex = $dBServer->index;
         $dbEbsVolume->size = $info->size;
         $dbEbsVolume->snapId = $info->snapshotId;
         $dbEbsVolume->mount = $this->getParam('mount') == 1;
         $dbEbsVolume->mountPoint = $this->getParam('mountPoint');
         $dbEbsVolume->mountStatus = $this->getParam('mount') == 1 ? EC2_EBS_MOUNT_STATUS::AWAITING_ATTACHMENT : EC2_EBS_MOUNT_STATUS::NOT_MOUNTED;
         $dbEbsVolume->clientId = $this->user->getAccountId();
         $dbEbsVolume->envId = $this->getEnvironmentId();
         $dbEbsVolume->Save();
     }
     $this->response->success('EBS volume has been successfully attached');
 }
예제 #5
0
 protected function run2()
 {
     $cnt = 0;
     $images = $this->db->GetAll('SELECT ri.*, r.env_id FROM role_images ri LEFT JOIN roles r ON r.id = ri.role_id');
     foreach ($images as $i) {
         /* @var Image $imObj */
         $i['env_id'] = $i['env_id'] == 0 ? NULL : $i['env_id'];
         $imObj = Image::findOne([['id' => $i['image_id']], ['$or' => [['envId' => $i['env_id']], ['envId' => null]]], ['platform' => $i['platform']], ['cloudLocation' => $i['cloud_location']]]);
         if (!$imObj) {
             $imObj = new Image();
             $imObj->id = $i['image_id'];
             $imObj->envId = $i['env_id'];
             $imObj->platform = $i['platform'];
             $imObj->cloudLocation = $i['cloud_location'];
             $imObj->architecture = $i['architecture'] ? $i['architecture'] : 'x84_64';
             $imObj->osId = $i['os_id'];
             $imObj->isDeprecated = 0;
             $imObj->dtAdded = NULL;
             $imObj->source = Image::SOURCE_MANUAL;
             if ($imObj->envId) {
                 $imObj->checkImage();
             } else {
                 $imObj->status = Image::STATUS_ACTIVE;
             }
             if (is_null($imObj->status)) {
                 $imObj->status = Image::STATUS_ACTIVE;
             }
             if (is_null($imObj->cloudLocation)) {
                 $imObj->cloudLocation = '';
             }
             $imObj->save();
             $cnt++;
         }
     }
     $this->console->notice('Added %s images', $cnt);
 }
예제 #6
0
파일: Import.php 프로젝트: scalr/scalr
 /**
  * @param   string  $platform       Name of platform
  * @param   string  $cloudLocation  Name of location
  * @param   array   $ids            The list of the identifiers of the cloud instances
  * @param   int     $roleId         optional    Identifier of Role
  * @return  array
  * @throws  Exception
  */
 public function checkStatus($platform, $cloudLocation, $ids, $roleId = null)
 {
     if (!in_array($platform, $this->allowedPlatforms)) {
         throw new Exception(sprintf("Platform '%s' is not supported", $platform));
     }
     if (!$this->environment->isPlatformEnabled($platform)) {
         throw new Exception(sprintf("Platform '%s' is not enabled", $platform));
     }
     if (empty($ids) || empty($ids[0])) {
         throw new Exception("You should provide at least one instanceId");
     }
     $instances = PlatformFactory::NewPlatform($platform)->getOrphanedServers($this->getEnvironmentEntity(), $cloudLocation, $ids);
     $status = ['instances' => $instances];
     $imageIds = array_unique(array_map(function ($item) {
         return $item->imageId;
     }, $instances));
     if (count($imageIds) != 1) {
         $status['compatibility'] = ['success' => false];
         return $status;
     }
     /* @var $instance OrphanedServer */
     $instance = $instances[0];
     $status['compatibility'] = ['success' => true];
     // Check vpc compatibility
     if ($instance->vpcId && $instance->subnetId) {
         $gov = new Scalr_Governance($this->getEnvironmentId());
         $vpcGovernanceRegions = $gov->getValue(SERVER_PLATFORMS::EC2, Scalr_Governance::AWS_VPC, 'regions');
         if (isset($vpcGovernanceRegions)) {
             if (!array_key_exists($cloudLocation, $vpcGovernanceRegions)) {
                 $status['compatibility']['success'] = false;
                 $status['compatibility']['message'] = sprintf('Region <b>%s</b> is not allowed by the Governance.', $cloudLocation);
             } else {
                 $vpcGovernanceIds = $vpcGovernanceRegions[$cloudLocation]['ids'];
                 if (!empty($vpcGovernanceIds) && !in_array($instance->vpcId, $vpcGovernanceIds)) {
                     $status['compatibility']['success'] = false;
                     $status['compatibility']['message'] = sprintf('VPC <b>%s</b> is not allowed by the Governance.', $instance->vpcId);
                 } else {
                     $vpcGovernanceIds = $gov->getValue(SERVER_PLATFORMS::EC2, Scalr_Governance::AWS_VPC, 'ids');
                     /* @var $platformObject Ec2PlatformModule */
                     $platformObject = PlatformFactory::NewPlatform(SERVER_PLATFORMS::EC2);
                     $subnet = $platformObject->listSubnets($this->getEnvironment(), $cloudLocation, $instance->vpcId, true, $instance->subnetId);
                     if (isset($vpcGovernanceIds[$instance->vpcId])) {
                         if (!empty($vpcGovernanceIds[$instance->vpcId]) && is_array($vpcGovernanceIds[$instance->vpcId]) && !in_array($instance->subnetId, $vpcGovernanceIds[$instance->vpcId])) {
                             $status['compatibility']['success'] = false;
                             $status['compatibility']['message'] = sprintf('Subnet <b>%s</b> is prohibited by the Governance.', $instance->subnetId);
                         } else {
                             if ($vpcGovernanceIds[$instance->vpcId] == "outbound-only" && $subnet['type'] != 'private') {
                                 $status['compatibility']['success'] = false;
                                 $status['compatibility']['message'] = 'Only private subnets are allowed by the Governance.';
                             } else {
                                 if ($vpcGovernanceIds[$instance->vpcId] == "full" && $subnet['type'] != 'public') {
                                     $status['compatibility']['success'] = false;
                                     $status['compatibility']['message'] = 'Only public subnets are allowed by the Governance.';
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
     if (!$status['compatibility']['success']) {
         return $status;
     }
     $scopeCriteria = ['$or' => [['accountId' => null], ['$and' => [['accountId' => $this->getUser()->accountId], ['$or' => [['envId' => null], ['envId' => $this->getEnvironment()->id]]]]]]];
     /* @var $image Entity\Image */
     $image = Entity\Image::findOne([['platform' => $platform], ['cloudLocation' => $cloudLocation], ['id' => $instance->imageId], $scopeCriteria]);
     $status['image'] = ['success' => !!$image, 'data' => ['id' => $instance->imageId]];
     if ($image) {
         if ($image->isScalarized) {
             $status['image']['success'] = false;
             $status['image']['isScalarized'] = true;
             return $status;
         }
         $status['image']['data'] = ['hash' => $image->hash, 'name' => $image->name, 'id' => $image->id, 'scope' => $image->getScope()];
         $criteria = [['platform' => $platform], ['imageId' => $image->id]];
         if (!($platform == SERVER_PLATFORMS::GCE || $platform == SERVER_PLATFORMS::AZURE)) {
             $criteria[] = ['cloudLocation' => $cloudLocation];
         }
         $roleIds = [];
         foreach (Entity\RoleImage::find($criteria) as $ri) {
             $roleIds[] = $ri->roleId;
         }
         if (count($roleIds)) {
             $roles = Entity\Role::find([['id' => ['$in' => $roleIds]], ['isScalarized' => false], $scopeCriteria]);
             $status['role'] = ['availableRoles' => [], 'image' => Scalr_UI_Controller_Images::controller()->convertEntityToArray($image)];
             $selectedRole = null;
             if (count($roles) == 1) {
                 $selectedRole = $roles->current();
             } else {
                 if ($roleId && in_array($roleId, $roleIds)) {
                     foreach ($roles as $role) {
                         /* @var $role Entity\Role */
                         if ($role->id == $roleId) {
                             $selectedRole = $role;
                             break;
                         }
                     }
                 }
             }
             foreach ($roles as $role) {
                 /* @var $role Entity\Role */
                 $status['role']['availableRoles'][] = ['id' => $role->id, 'name' => $role->name, 'scope' => $role->getScope()];
             }
             if ($selectedRole) {
                 $status['role']['success'] = true;
                 $status['role']['data'] = ['id' => $selectedRole->id, 'name' => $selectedRole->name, 'scope' => $selectedRole->getScope()];
                 $farms = [];
                 $status['farmrole'] = ['instance' => ['instanceType' => $instance->instanceType, 'vpcId' => $instance->vpcId, 'subnetId' => $instance->subnetId, 'roleName' => $selectedRole->name]];
                 foreach (Entity\Farm::find([['envId' => $this->getEnvironment()->id], ['status' => FARM_STATUS::RUNNING]]) as $farm) {
                     /* @var $farm Entity\Farm */
                     if ($this->request->hasPermissions($farm, Acl::PERM_FARMS_UPDATE) && $this->request->hasPermissions($farm, Acl::PERM_FARMS_SERVERS)) {
                         // cloud specific (EC2)
                         if ($farm->settings[Entity\FarmSetting::EC2_VPC_ID] == $instance->vpcId) {
                             $farms[$farm->id] = ['id' => $farm->id, 'name' => $farm->name, 'farmroles' => []];
                         }
                     }
                 }
                 foreach (Entity\FarmRole::find([['farmId' => ['$in' => array_keys($farms)]], ['roleId' => $selectedRole->id]]) as $farmRole) {
                     /* @var $farmRole Entity\FarmRole */
                     if (isset($farms[$farmRole->farmId])) {
                         if (!$instance->subnetId || $instance->subnetId && in_array($instance->subnetId, json_decode($farmRole->settings[Entity\FarmRoleSetting::AWS_VPC_SUBNET_ID]))) {
                             $farms[$farmRole->farmId]['farmroles'][] = ['id' => $farmRole->id, 'name' => $farmRole->alias, 'tags' => $farmRole->getCloudTags(true)];
                         }
                     }
                 }
                 $status['farmrole']['data'] = array_values($farms);
                 $status['farmrole']['success'] = false;
             } else {
                 if (count($roles) > 1) {
                     $status['role']['success'] = false;
                 } else {
                     $status['role']['success'] = false;
                 }
             }
         } else {
             $status['role']['success'] = false;
             $status['role']['image'] = Scalr_UI_Controller_Images::controller()->convertEntityToArray($image);
         }
     }
     return $status;
 }
예제 #7
0
 protected function run4()
 {
     $this->console->notice('Fix shared images, remove duplicates');
     foreach ($this->db->GetAll('SELECT id, platform, cloud_location FROM images GROUP BY id HAVING count(*) > 1') as $im) {
         if ($this->db->GetOne('SELECT 1 FROM images WHERE id = ? and platform = ? and cloud_location = ? and env_id is null', [$im['id'], $im['platform'], $im['cloud_location']])) {
             $size = $this->db->GetRow('SELECT `size`, name, architecture FROM images WHERE id = ? and platform = ? and cloud_location = ? and size > 0', [$im['id'], $im['platform'], $im['cloud_location']]);
             if ($size) {
                 $this->db->Execute('UPDATE images SET size = ? WHERE id = ? and platform = ? and cloud_location = ? and env_id is null', [$size['size'], $im['id'], $im['platform'], $im['cloud_location']]);
                 if ($size['architecture']) {
                     $this->db->Execute('UPDATE images SET architecture = ? WHERE id = ? and platform = ? and cloud_location = ? and env_id is null', [$size['architecture'], $im['id'], $im['platform'], $im['cloud_location']]);
                 }
                 if ($size['name']) {
                     $this->db->Execute('UPDATE images SET name = ? WHERE id = ? and platform = ? and cloud_location = ? and env_id is null', [$size['name'], $im['id'], $im['platform'], $im['cloud_location']]);
                 }
             }
             // found shared image, remove others
             $this->db->Execute('DELETE FROM images WHERE id = ? and platform = ? and cloud_location = ? and env_id is not null', [$im['id'], $im['platform'], $im['cloud_location']]);
         }
     }
     $this->console->notice('Fill shared images with info');
     foreach ($this->db->GetAll('SELECT * FROM roles WHERE env_id = 0') as $role) {
         $hvm = stristr($role['name'], '-hvm-') ? 1 : 0;
         $architecture = '';
         if (stristr($role['name'], '64-')) {
             $architecture = 'x86_64';
         }
         if (stristr($role['name'], 'i386')) {
             $architecture = 'i386';
         }
         foreach ($this->db->GetAll('SELECT * FROM role_images WHERE role_id = ?', [$role['id']]) as $im) {
             /* @var Image $image */
             $image = Image::findOne([['id' => $im['image_id']], ['platform' => $im['platform']], ['cloudLocation' => $im['cloud_location']], ['envId' => null]]);
             if ($image) {
                 if ($architecture) {
                     $image->architecture = $architecture;
                 } else {
                     if (!$image->architecture) {
                         $image->architecture = 'i386';
                     }
                 }
                 $image->osId = $role['osId'];
                 if ($image->name == $image->id && $role['name']) {
                     $image->name = $role['name'];
                 }
                 if ($hvm) {
                     $image->type = 'ebs-hvm';
                 } else {
                     $image->type = 'ebs';
                 }
                 $image->save();
             } else {
                 $this->console->warning('Image not found: %s, %s, %s', $im['platform'], $im['cloud_location'], $im['image_id']);
             }
         }
     }
 }
예제 #8
0
파일: RoleImage.php 프로젝트: mheydt/scalr
 /**
  * @return Image|NULL
  * @throws \Exception
  */
 public function getImage()
 {
     /* @var $role Role */
     $role = Role::findPk($this->roleId);
     return Image::findOne([['id' => $this->imageId], ['$or' => [['envId' => $role->envId == 0 ? null : $role->envId], ['envId' => null]]], ['platform' => $this->platform], ['cloudLocation' => $this->cloudLocation]]);
 }
예제 #9
0
파일: Images.php 프로젝트: mheydt/scalr
 /**
  * @param   string   $imageId
  * @param   string   $platform
  * @param   string   $osId
  * @param   string   $name
  * @param   string   $cloudLocation
  * @param   string   $architecture
  * @param   int      $size
  * @param   string   $ec2Type
  * @param   bool     $ec2Hvm
  * @param   JsonData $software
  * @throws  Scalr_Exception_Core
  */
 public function xSaveAction($imageId, $platform, $osId, $name, $cloudLocation = '', $architecture = '', $size = null, $ec2Type = null, $ec2Hvm = null, JsonData $software = null)
 {
     $this->restrictAccess('IMAGES', 'MANAGE');
     if ($platform == SERVER_PLATFORMS::GCE || $platform == SERVER_PLATFORMS::AZURE) {
         $cloudLocation = '';
     }
     if ($accountId = $this->user->getAccountId()) {
         if ($envId = $this->getEnvironmentId(true)) {
             if (Image::findOne([['id' => $imageId], ['envId' => $envId], ['platform' => $platform], ['cloudLocation' => $cloudLocation]])) {
                 throw new Scalr_Exception_Core('This Image has already been registered in the Environment Scope.');
             }
         }
         if (Image::findOne([['id' => $imageId], ['accountId' => $this->user->getAccountId()], ['envId' => null], ['platform' => $platform], ['cloudLocation' => $cloudLocation]])) {
             throw new Scalr_Exception_Core('This Image has already been registered in the Account Scope.');
         }
     }
     if (Image::findOne([['id' => $imageId], ['accountId' => null], ['platform' => $platform], ['cloudLocation' => $cloudLocation]])) {
         $this->response->failure('This Image has already been registered in the Scalr Scope.');
         return;
     }
     if (!Role::isValidName($name)) {
         $this->response->failure('Name should start and end with letter or number and contain only letters, numbers and dashes.');
         return;
     }
     $image = new Image();
     $image->accountId = $this->user->getAccountId() ?: null;
     $image->envId = $this->getEnvironmentId(true);
     $image->id = $imageId;
     $image->platform = $platform;
     $image->cloudLocation = $cloudLocation;
     $image->architecture = 'x86_64';
     if ($this->request->getScope() == ScopeInterface::SCOPE_ENVIRONMENT) {
         if ($image->checkImage() === false) {
             $this->response->failure("This Image does not exist, or isn't usable by your account");
             return;
         }
     } else {
         $image->architecture = $architecture;
         $image->size = $size;
         if ($platform == SERVER_PLATFORMS::EC2) {
             if ($ec2Type == 'ebs' || $ec2Type == 'instance-store') {
                 $image->type = $ec2Type;
                 if ($ec2Hvm) {
                     $image->type = $image->type . '-hvm';
                 }
             }
         }
     }
     $image->name = $name;
     $image->source = Image::SOURCE_MANUAL;
     $image->osId = $osId;
     $image->createdById = $this->user->getId();
     $image->createdByEmail = $this->user->getEmail();
     $image->status = Image::STATUS_ACTIVE;
     $image->save();
     $props = [];
     foreach ($software as $value) {
         $props[$value] = null;
     }
     $image->setSoftware($props);
     $this->response->data(['hash' => $image->hash]);
     $this->response->success('Image has been added');
 }
예제 #10
0
파일: Volumes.php 프로젝트: scalr/scalr
 /**
  * Attaches volume to server
  *
  * It uses request params and can't be used without UI request
  *
  * @param    VolumeData $info AWS EBS Volume info
  * @throws   Exception
  */
 protected function attachVolumeToServer(VolumeData $info)
 {
     $dBServer = DBServer::LoadByID($this->getParam('serverId'));
     //Check access permission to specified server
     $this->request->checkPermissions($dBServer->GetFarmObject()->__getNewFarmObject(), Acl::PERM_FARMS_SERVERS);
     $errmsg = null;
     try {
         $dbEbsVolume = DBEBSVolume::loadByVolumeId($this->getParam('volumeId'));
         if ($dbEbsVolume->isManual == 0) {
             $errmsg = sprintf(_("This volume was automatically created for role '%s' on farm '%s' and cannot be re-attahced manually."), $this->db->GetOne("\n                        SELECT name FROM roles\n                        JOIN farm_roles ON farm_roles.role_id = roles.id\n                        WHERE farm_roles.id=?\n                        LIMIT 1\n                    ", array($dbEbsVolume->farmRoleId)), $this->db->GetOne("SELECT name FROM farms WHERE id=? LIMIT 1", array($dbEbsVolume->farmId)));
         }
     } catch (Exception $e) {
     }
     if (!empty($errmsg)) {
         throw new Exception($errmsg);
     }
     $image = Image::findOne([['platform' => $dBServer->platform], ['id' => $dBServer->imageId], ['cloudLocation' => $dBServer->GetCloudLocation()]]);
     $device = $dBServer->GetFreeDeviceName($image->isEc2HvmImage());
     $res = $info->attach($dBServer->GetProperty(EC2_SERVER_PROPERTIES::INSTANCE_ID), $device);
     if ($this->getParam('attachOnBoot') == 'on') {
         $dbEbsVolume = new DBEBSVolume();
         $dbEbsVolume->attachmentStatus = EC2_EBS_ATTACH_STATUS::ATTACHING;
         $dbEbsVolume->isManual = true;
         $dbEbsVolume->volumeId = $info->volumeId;
         $dbEbsVolume->ec2AvailZone = $info->availabilityZone;
         $dbEbsVolume->ec2Region = $this->getParam('cloudLocation');
         $dbEbsVolume->deviceName = $device;
         $dbEbsVolume->farmId = $dBServer->farmId;
         $dbEbsVolume->farmRoleId = $dBServer->farmRoleId;
         $dbEbsVolume->serverId = $dBServer->serverId;
         $dbEbsVolume->serverIndex = $dBServer->index;
         $dbEbsVolume->size = $info->size;
         $dbEbsVolume->snapId = $info->snapshotId;
         $dbEbsVolume->mount = $this->getParam('mount') == 1;
         $dbEbsVolume->mountPoint = $this->getParam('mountPoint');
         $dbEbsVolume->mountStatus = $this->getParam('mount') == 1 ? EC2_EBS_MOUNT_STATUS::AWAITING_ATTACHMENT : EC2_EBS_MOUNT_STATUS::NOT_MOUNTED;
         $dbEbsVolume->clientId = $this->user->getAccountId();
         $dbEbsVolume->envId = $this->getEnvironmentId();
         $dbEbsVolume->Save();
     }
     //Updates/Creates AWS Tags of Volume
     $tags = [];
     foreach ($dBServer->getAwsTags() as $k => $v) {
         $tags[] = ['key' => $k, 'value' => $v];
     }
     if (!empty($tags)) {
         $info->createTags($tags);
     }
 }
예제 #11
0
파일: Servers.php 프로젝트: scalr/scalr
 public function xSuspendServersAction()
 {
     $this->request->defineParams(array('servers' => array('type' => 'json')));
     $errorServers = array();
     foreach ($this->getParam('servers') as $serverId) {
         try {
             $dbServer = DBServer::LoadByID($serverId);
             $this->user->getPermissions()->validate($dbServer);
             if ($dbServer->platform == SERVER_PLATFORMS::AZURE || $dbServer->platform == SERVER_PLATFORMS::CLOUDSTACK || $dbServer->platform == SERVER_PLATFORMS::GCE || $dbServer->platform == SERVER_PLATFORMS::EC2 || PlatformFactory::isOpenstack($dbServer->platform)) {
                 /* @var $image Image */
                 if ($dbServer->platform == SERVER_PLATFORMS::EC2 && ($image = Image::findOne([['platform' => $dbServer->platform], ['cloudLocation' => $dbServer->cloudLocation], ['id' => $dbServer->imageId], ['$or' => [['accountId' => null], ['accountId' => $dbServer->clientId]]], ['$or' => [['envId' => null], ['envId' => $dbServer->envId]]]])) && $image->isEc2InstanceStoreImage()) {
                     $errorServers[] = "The instance does not have an 'ebs' root device type and cannot be stopped";
                     continue;
                 }
                 if ($dbServer->farmRoleId) {
                     if ($this->hasDatabaseBehavior($dbServer->GetFarmRoleObject()->GetRoleObject()->getBehaviors())) {
                         $errors[] = "Database instance cannot be stopped";
                         continue;
                     }
                     if ($dbServer->GetFarmRoleObject()->GetRoleObject()->hasBehavior(ROLE_BEHAVIORS::RABBITMQ)) {
                         $errors[] = "RabbitMQ instance cannot be stopped";
                         continue;
                     }
                 }
                 $dbServer->suspend('', false, $this->user);
             } else {
                 //NOT SUPPORTED
             }
         } catch (Exception $e) {
         }
     }
     $this->response->data(array('data' => $errorServers));
 }
예제 #12
0
 /**
  * {@inheritdoc}
  * @see \Scalr\Api\DataType\ApiEntityAdapter::validateEntity()
  */
 public function validateEntity($entity)
 {
     if (!$entity instanceof Entity\Image) {
         throw new \InvalidArgumentException(sprintf("First argument must be instance of Scalr\\Model\\Entity\\Image class"));
     }
     if ($entity->hash !== null) {
         //Checks if the image does exist
         if (!Entity\Image::findPk($entity->hash)) {
             throw new ApiErrorException(404, ErrorMessage::ERR_OBJECT_NOT_FOUND, sprintf("Could not find out the Image with ID: %d", $entity->hash));
         }
     } else {
         $image = Entity\Image::findOne([['id' => $entity->id], ['platform' => $entity->platform], ['cloudLocation' => (string) $entity->cloudLocation], ['$or' => [['accountId' => null], ['$and' => [['accountId' => $entity->accountId], ['$or' => [['envId' => null], ['envId' => $entity->envId]]]]]]]]);
         if ($image) {
             throw new ApiErrorException(409, ErrorMessage::ERR_UNICITY_VIOLATION, "This Image has already been registered in Scalr");
         }
     }
     //Is this a new Image
     if (!$entity->hash) {
         $entity->createdByEmail = $this->controller->getUser()->email;
         $entity->createdById = $this->controller->getUser()->id;
     }
     if (!Entity\Role::isValidName($entity->name)) {
         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, "Invalid name of the Image");
     }
     if (empty($entity->architecture)) {
         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_STRUCTURE, "Missed property 'architecture'");
     }
     if (!$this->controller->hasPermissions($entity, true)) {
         //Checks entity level write access permissions
         throw new ApiErrorException(403, ErrorMessage::ERR_PERMISSION_VIOLATION, "Insufficient permissions");
     }
     //We only allow to either create or modify Environment Scope Roles
     if ($entity->getScope() !== $this->controller->getScope()) {
         throw new ApiErrorException(403, ErrorMessage::ERR_SCOPE_VIOLATION, sprintf("Invalid scope"));
     }
     if (empty($entity->osId)) {
         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_STRUCTURE, "Missed property 'os.id'");
     }
     //Tries to find out the specified OS
     if (empty(Entity\Os::findPk($entity->osId))) {
         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, "OS with id '{$entity->osId}' not found.");
     }
     if (empty($entity->platform)) {
         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_STRUCTURE, "Missed property platform");
     }
     if (!isset(SERVER_PLATFORMS::GetList()[$entity->platform])) {
         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_STRUCTURE, "Unexpected platform value");
     }
 }
예제 #13
0
파일: Server.php 프로젝트: scalr/scalr
 /**
  * Get Image entity
  *
  * @return  Image|null  Return Image entity or null
  */
 public function getImage()
 {
     if (!empty($this->imageId) && empty($this->_image)) {
         $this->_image = Image::findOne([['platform' => $this->platform], ['cloudLocation' => in_array($this->platform, [SERVER_PLATFORMS::GCE, SERVER_PLATFORMS::AZURE]) ? '' : $this->cloudLocation], ['id' => $this->imageId], ['$or' => [['accountId' => null], ['$and' => [['accountId' => $this->accountId], ['$or' => [['envId' => $this->envId], ['envId' => null]]]]]]]], null, ['envId' => false]);
     }
     return $this->_image;
 }
예제 #14
0
파일: ApiFixture.php 프로젝트: scalr/scalr
 /**
  * Creates and save RoleImage entity  with data from fixtures
  *
  * @param string $name      Role category data name
  */
 protected function prepareRoleImage($name)
 {
     foreach ($this->sets[$name] as &$roleImageData) {
         if (in_array($roleImageData['platform'], [SERVER_PLATFORMS::GCE, SERVER_PLATFORMS::AZURE])) {
             $roleImageData['cloudLocation'] = '';
         }
         /* @var $image  Entity\Image */
         $image = Entity\Image::findOne([['cloudLocation' => $roleImageData['cloudLocation']], ['platform' => $roleImageData['platform']], ['$or' => [['accountId' => static::$user->getAccountId()], ['accountId' => null]]]]);
         if (empty($image)) {
             ApiTest::markTestIncomplete(sprintf('Image with cloudLocation %s and platform %s not isset', $roleImageData['cloudLocation'], $roleImageData['platform']));
         }
         $roleImageData['imageId'] = $image->id;
         ApiTest::createEntity(new Entity\RoleImage(), $roleImageData);
     }
 }
예제 #15
0
 /**
  * {@inheritdoc}
  * @see \Scalr\Api\DataType\ApiEntityAdapter::validateEntity()
  */
 public function validateEntity($entity)
 {
     if (!$entity instanceof Entity\Image) {
         throw new \InvalidArgumentException(sprintf("First argument must be instance of Scalr\\Model\\Entity\\Image class"));
     }
     if ($entity->hash !== null) {
         //Checks if the image does exist
         if (!Entity\Image::findPk($entity->hash)) {
             throw new ApiErrorException(404, ErrorMessage::ERR_OBJECT_NOT_FOUND, sprintf("Could not find out the Image with ID: %d", $entity->hash));
         }
     } else {
         $image = Entity\Image::findOne([['id' => $entity->id], ['$or' => [['envId' => $entity->envId], ['envId' => null]]], ['platform' => $entity->platform], ['cloudLocation' => $entity->cloudLocation]]);
         if ($image) {
             throw new ApiErrorException(409, ErrorMessage::ERR_UNICITY_VIOLATION, "This Image has already been registered in Scalr");
         }
     }
     //Is this a new Image
     if (!$entity->hash) {
         $entity->createdByEmail = $this->controller->getUser()->email;
         $entity->createdById = $this->controller->getUser()->id;
     }
     if (!Entity\Role::validateName($entity->name)) {
         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, "Invalid name of the Image");
     }
     $entity->architecture = $entity->architecture ?: 'x86_64';
     if (!in_array($entity->architecture, ['i386', 'x86_64'])) {
         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, "Invalid architecture of the Image.");
     }
     if (!$this->controller->hasPermissions($entity, true)) {
         //Checks entity level write access permissions
         throw new ApiErrorException(403, ErrorMessage::ERR_PERMISSION_VIOLATION, "Insufficient permissions");
     }
     //We only allow to either create or modify Environment Scope Roles
     if ($entity->getScope() !== ScopeInterface::SCOPE_ENVIRONMENT) {
         throw new ApiErrorException(403, ErrorMessage::ERR_SCOPE_VIOLATION, sprintf("Only %s scope is allowed.", ScopeInterface::SCOPE_ENVIRONMENT));
     }
     //Validates OS
     if (!empty($entity->osId)) {
         //Tries to find out the specified OS
         $os = Entity\Os::findPk($entity->osId);
         if (!$os instanceof Entity\Os) {
             throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, "Specified OS does not exist");
         }
     } else {
         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_STRUCTURE, "OS must be provided with the request.");
     }
 }
예제 #16
0
파일: Roles.php 프로젝트: mheydt/scalr
 /**
  * Associates a new Image with the Role
  *
  * @param  int      $roleId     The Identifier of the role
  * @param  string   $imageId    The Identifier of the image
  * @return \Scalr\Api\DataType\ResultEnvelope
  * @throws ApiErrorException
  */
 public function replaceImageAction($roleId, $imageId)
 {
     $this->checkScopedPermissions('ROLES', 'MANAGE');
     $role = $this->getRole($roleId, true);
     $oldImage = $this->getImage($roleId, $imageId);
     $object = $this->request->getJsonBody();
     $objectImageId = static::getBareId($object, 'image');
     $objectRoleId = static::getBareId($object, 'role');
     if (empty($objectImageId)) {
         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_STRUCTURE, "Invalid body");
     }
     if (!preg_match('/' . ApiApplication::REGEXP_UUID . '/', $objectImageId) || $oldImage->hash == $objectImageId) {
         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, "Invalid image identifier");
     }
     if (!empty($objectRoleId) && $roleId != $objectRoleId) {
         throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, "Invalid identifier of the role");
     }
     if (is_object($object->image)) {
         $imageAdapter = $this->adapter('image');
         //Pre validates the request object
         $imageAdapter->validateObject($object->image);
     }
     $criteria = $this->getScopeCriteria();
     $criteria[] = ['hash' => $objectImageId];
     /* @var $image Entity\Image */
     $image = Entity\Image::findOne($criteria);
     if (empty($image)) {
         throw new ApiErrorException(404, ErrorMessage::ERR_INVALID_VALUE, "The Image either does not exist or isn't in scope for the current Environment.");
     }
     if ($image->cloudLocation !== $oldImage->cloudLocation) {
         throw new ApiErrorException(400, ErrorMessage::ERR_BAD_REQUEST, "You can only replace images with equal cloud locations");
     }
     $this->setImage($role, $image->platform, $image->cloudLocation, $image->id, $this->getUser()->id, $this->getUser()->email);
     $this->response->setStatus(200);
     return $this->result(['image' => ['id' => $image->hash], 'role' => ['id' => $role->id]]);
 }
예제 #17
0
 /**
  * @test
  */
 public function testImagesFunctional()
 {
     $testName = str_replace('-', '', $this->getTestName());
     $images = null;
     $uri = self::getUserApiUrl('/images');
     do {
         $query = [];
         if (isset($images->pagination->next)) {
             $parts = parse_url($images->pagination->next);
             parse_str($parts['query'], $query);
         }
         $describe = $this->request($uri, Request::METHOD_GET, $query);
         $this->assertDescribeResponseNotEmpty($describe);
         $images = $describe->getBody();
         foreach ($images->data as $image) {
             $this->assertImageObjectNotEmpty($image);
             if (strpos($image->name, $testName) !== false) {
                 $delete = $this->request($uri . '/' . $image->id, Request::METHOD_DELETE);
                 $this->assertEquals(200, $delete->response->getStatus());
             }
         }
     } while (!empty($images->pagination->next));
     // test create action
     $create = $this->request($uri, Request::METHOD_POST, [], ['scope' => 'invalid']);
     $this->assertErrorMessageContains($create, 400, ErrorMessage::ERR_INVALID_VALUE, 'Invalid scope');
     $create = $this->request($uri, Request::METHOD_POST);
     $this->assertErrorMessageContains($create, 400, ErrorMessage::ERR_INVALID_STRUCTURE, 'Invalid body');
     $create = $this->request($uri, Request::METHOD_POST, [], ['invalid' => 'value']);
     $this->assertErrorMessageContains($create, 400, ErrorMessage::ERR_INVALID_STRUCTURE, 'You are trying to set');
     $create = $this->request($uri, Request::METHOD_POST, [], ['scope' => ScopeInterface::SCOPE_ENVIRONMENT, 'name' => 'invalidName^$&&']);
     $this->assertErrorMessageContains($create, 400, ErrorMessage::ERR_INVALID_VALUE, 'Invalid name of the Image');
     $create = $this->request($uri, Request::METHOD_POST, [], ['scope' => ScopeInterface::SCOPE_ENVIRONMENT, 'architecture' => 'invalid', 'name' => $testName]);
     $this->assertErrorMessageContains($create, 400, ErrorMessage::ERR_INVALID_VALUE, 'Invalid architecture of the Image');
     $create = $this->request($uri, Request::METHOD_POST, [], ['scope' => ScopeInterface::SCOPE_ENVIRONMENT, 'name' => $testName]);
     $this->assertErrorMessageContains($create, 400, ErrorMessage::ERR_INVALID_STRUCTURE, 'OS must be provided with the request');
     $create = $this->request($uri, Request::METHOD_POST, [], ['scope' => ScopeInterface::SCOPE_ENVIRONMENT, 'name' => $testName, 'os' => ['id' => 'invalidOsId']]);
     $this->assertErrorMessageContains($create, 400, ErrorMessage::ERR_INVALID_VALUE, 'Specified OS does not exist');
     $os = Os::findOne([['status' => Os::STATUS_ACTIVE]]);
     /* @var $os Os */
     $env = \Scalr_Environment::init()->loadById(static::$testEnvId);
     $platform = \SERVER_PLATFORMS::EC2;
     if ($env->isPlatformEnabled($platform)) {
         $env->setPlatformConfig([$platform . '.is_enabled' => 0]);
     }
     $create = $this->request($uri, Request::METHOD_POST, [], ['scope' => ScopeInterface::SCOPE_ENVIRONMENT, 'name' => $testName, 'os' => ['id' => $os->id], 'cloudPlatform' => $platform]);
     $this->assertErrorMessageErrorEquals(ErrorMessage::ERR_INVALID_VALUE, $create);
     $this->assertErrorMessageStatusEquals(400, $create);
     $env->setPlatformConfig([$platform . '.is_enabled' => 1]);
     $create = $this->request($uri, Request::METHOD_POST, [], ['scope' => ScopeInterface::SCOPE_ENVIRONMENT, 'name' => $testName, 'os' => ['invalid'], 'cloudPlatform' => $platform]);
     $this->assertErrorMessageContains($create, 400, ErrorMessage::ERR_INVALID_VALUE, 'Invalid identifier of the OS');
     $create = $this->request($uri, Request::METHOD_POST, [], ['scope' => ScopeInterface::SCOPE_ENVIRONMENT, 'name' => $testName, 'os' => ['id' => $os->id], 'cloudPlatform' => $platform]);
     $this->assertErrorMessageContains($create, 400, ErrorMessage::ERR_INVALID_VALUE, 'Unable to find the requested image on the cloud');
     $region = null;
     $cloudImageId = null;
     foreach (Aws::getCloudLocations() as $cloudLocation) {
         $cloudImageId = $this->getNewImageId($env, $cloudLocation);
         if (!empty($cloudImageId)) {
             $region = $cloudLocation;
             break;
         }
     }
     $this->assertNotNull($cloudImageId);
     $this->assertNotNull($cloudLocation);
     $create = $this->request($uri, Request::METHOD_POST, [], ['scope' => ScopeInterface::SCOPE_ENVIRONMENT, 'name' => $testName, 'os' => $os->id, 'cloudPlatform' => $platform, 'cloudLocation' => $region, 'cloudImageId' => $cloudImageId]);
     $this->assertFetchResponseNotEmpty($create);
     $imageBody = $create->getBody();
     $this->assertImageObjectNotEmpty($imageBody->data);
     $this->assertEquals(201, $create->response->getStatus());
     $this->assertNotEmpty($imageBody->data->id);
     $this->assertEquals(ScopeInterface::SCOPE_ENVIRONMENT, $imageBody->data->scope);
     $this->assertEquals($testName, $imageBody->data->name);
     $this->assertEquals($os->id, $imageBody->data->os->id);
     $this->assertEquals($platform, $imageBody->data->cloudPlatform);
     $this->assertEquals($region, $imageBody->data->cloudLocation);
     $this->assertEquals($cloudImageId, $imageBody->data->cloudImageId);
     $create = $this->request($uri, Request::METHOD_POST, [], ['scope' => ScopeInterface::SCOPE_ENVIRONMENT, 'name' => $testName, 'os' => ['id' => $os->id], 'cloudPlatform' => $platform, 'cloudLocation' => $region, 'cloudImageId' => $cloudImageId]);
     $this->assertErrorMessageErrorEquals(ErrorMessage::ERR_UNICITY_VIOLATION, $create);
     $this->assertErrorMessageStatusEquals(409, $create);
     // test filtering
     $describe = $this->request($uri, Request::METHOD_GET, ['scope' => ScopeInterface::SCOPE_ENVIRONMENT]);
     $this->assertDescribeResponseNotEmpty($describe);
     foreach ($describe->getBody()->data as $data) {
         $this->assertImageObjectNotEmpty($data);
         $this->assertEquals(ScopeInterface::SCOPE_ENVIRONMENT, $data->scope);
     }
     $describe = $this->request($uri, Request::METHOD_GET, ['name' => $testName]);
     $this->assertDescribeResponseNotEmpty($describe);
     foreach ($describe->getBody()->data as $data) {
         $this->assertImageObjectNotEmpty($data);
         $this->assertEquals($testName, $data->name);
     }
     $describe = $this->request($uri, Request::METHOD_GET, ['id' => $imageBody->data->id]);
     $this->assertDescribeResponseNotEmpty($describe);
     foreach ($describe->getBody()->data as $data) {
         $this->assertImageObjectNotEmpty($data);
         $this->assertEquals($imageBody->data->id, $data->id);
     }
     $describe = $this->request($uri, Request::METHOD_GET, ['os' => $os->id]);
     $this->assertDescribeResponseNotEmpty($describe);
     foreach ($describe->getBody()->data as $data) {
         $this->assertImageObjectNotEmpty($data);
         $this->assertEquals($os->id, $data->os->id);
     }
     $describe = $this->request($uri, Request::METHOD_GET, ['os' => 'invalid*&^^%']);
     $this->assertErrorMessageContains($describe, 400, ErrorMessage::ERR_INVALID_VALUE, "Invalid identifier of the OS");
     $describe = $this->request($uri, Request::METHOD_GET, ['cloudPlatform' => $platform, 'cloudLocation' => $region]);
     $this->assertDescribeResponseNotEmpty($describe);
     foreach ($describe->getBody()->data as $data) {
         $this->assertImageObjectNotEmpty($data);
         $this->assertEquals($platform, $data->cloudPlatform);
         $this->assertEquals($region, $data->cloudLocation);
     }
     $describe = $this->request($uri, Request::METHOD_GET, ['cloudLocation' => $region]);
     $this->assertErrorMessageErrorEquals(ErrorMessage::ERR_INVALID_STRUCTURE, $describe);
     $this->assertErrorMessageStatusEquals(400, $describe);
     $describe = $this->request($uri, Request::METHOD_GET, ['cloudImageId' => $cloudImageId]);
     $this->assertDescribeResponseNotEmpty($describe);
     foreach ($describe->getBody()->data as $data) {
         $this->assertImageObjectNotEmpty($data);
         $this->assertEquals($cloudImageId, $data->cloudImageId);
     }
     // test modify action
     $modify = $this->request($uri, Request::METHOD_PATCH, [], ['name' => $testName . 'modify']);
     $this->assertErrorMessageErrorEquals(ErrorMessage::ERR_ENDPOINT_NOT_FOUND, $modify);
     $this->assertErrorMessageStatusEquals(404, $modify);
     $modify = $this->request($uri . '/' . $imageBody->data->id, Request::METHOD_PATCH, [], ['invalid' => $testName . 'modify']);
     $this->assertErrorMessageErrorEquals(ErrorMessage::ERR_INVALID_STRUCTURE, $modify);
     $this->assertErrorMessageStatusEquals(400, $modify);
     $modify = $this->request($uri . '/' . $imageBody->data->id, Request::METHOD_PATCH, [], ['id' => $testName . 'modify']);
     $this->assertErrorMessageErrorEquals(ErrorMessage::ERR_INVALID_STRUCTURE, $modify);
     $this->assertErrorMessageStatusEquals(400, $modify);
     $modify = $this->request($uri . '/' . $imageBody->data->id, Request::METHOD_PATCH, [], ['scope' => $testName . 'modify']);
     $this->assertErrorMessageErrorEquals(ErrorMessage::ERR_INVALID_VALUE, $modify);
     $this->assertErrorMessageStatusEquals(400, $modify);
     $notFoundId = '11111111-1111-1111-1111-111111111111';
     $modify = $this->request($uri . '/' . $notFoundId, Request::METHOD_PATCH, [], ['name' => $testName . 'modify']);
     $this->assertErrorMessageErrorEquals(ErrorMessage::ERR_OBJECT_NOT_FOUND, $modify);
     $this->assertErrorMessageStatusEquals(404, $modify);
     $entity = Image::findOne([['envId' => null], ['status' => Image::STATUS_ACTIVE]]);
     /* @var $entity Image */
     $this->assertNotEmpty($entity);
     $notAccessibleId = $entity->hash;
     $modify = $this->request($uri . '/' . $notAccessibleId, Request::METHOD_PATCH, [], ['name' => $testName . 'modify']);
     $this->assertErrorMessageErrorEquals(ErrorMessage::ERR_SCOPE_VIOLATION, $modify);
     $this->assertErrorMessageStatusEquals(403, $modify);
     $create = $this->request($uri, Request::METHOD_POST, [], ['scope' => ScopeInterface::SCOPE_ENVIRONMENT, 'name' => $testName, 'os' => ['id' => $entity->osId], 'cloudPlatform' => $entity->platform, 'cloudLocation' => $entity->cloudLocation, 'cloudImageId' => $entity->id]);
     $this->assertErrorMessageErrorEquals(ErrorMessage::ERR_UNICITY_VIOLATION, $create);
     $this->assertErrorMessageStatusEquals(409, $create);
     // test fetch action
     $fetch = $this->request($uri . '/' . $notFoundId, Request::METHOD_GET);
     $this->assertErrorMessageErrorEquals(ErrorMessage::ERR_OBJECT_NOT_FOUND, $fetch);
     $this->assertErrorMessageStatusEquals(404, $fetch);
     $fetch = $this->request($uri . '/' . $imageBody->data->id, Request::METHOD_GET);
     $this->assertFetchResponseNotEmpty($fetch);
     $fetchBody = $fetch->getBody();
     $this->assertImageObjectNotEmpty($fetchBody->data);
     $this->assertEquals($imageBody->data->id, $fetchBody->data->id);
     $fetch = $this->request($uri . '/' . $entity->hash, Request::METHOD_GET);
     $this->assertFetchResponseNotEmpty($fetch);
     $fetchBody = $fetch->getBody();
     $this->assertImageObjectNotEmpty($fetchBody->data);
     $this->assertEquals($entity->hash, $fetchBody->data->id);
     $modify = $this->request($uri . '/' . $imageBody->data->id, Request::METHOD_PATCH, [], ['name' => $testName . 'modify']);
     $this->assertEquals(200, $modify->response->getStatus());
     $this->assertImageObjectNotEmpty($modify->getBody()->data);
     $this->assertEquals($testName . 'modify', $modify->getBody()->data->name);
     // test copy action
     $copy = $this->request($uri . '/' . $imageBody->data->id . '/actions/copy', Request::METHOD_POST);
     $this->assertErrorMessageErrorEquals(ErrorMessage::ERR_INVALID_STRUCTURE, $copy);
     $this->assertErrorMessageStatusEquals(400, $copy);
     $copy = $this->request($uri . '/' . $imageBody->data->id . '/actions/copy', Request::METHOD_POST, [], ['cloudLocation' => 'invalid', 'cloudPlatform' => 'ec2']);
     $this->assertErrorMessageErrorEquals(ErrorMessage::ERR_INVALID_VALUE, $copy);
     $this->assertErrorMessageStatusEquals(400, $copy);
     $copy = $this->request($uri . '/' . $imageBody->data->id . '/actions/copy', Request::METHOD_POST, [], ['cloudLocation' => Aws::REGION_US_EAST_1, 'cloudPlatform' => 'gce']);
     $this->assertErrorMessageErrorEquals(ErrorMessage::ERR_INVALID_VALUE, $copy);
     $this->assertErrorMessageStatusEquals(400, $copy);
     $copy = $this->request($uri . '/' . $imageBody->data->id . '/actions/copy', Request::METHOD_POST, [], ['cloudLocation' => $region, 'cloudPlatform' => 'ec2']);
     $this->assertErrorMessageErrorEquals(ErrorMessage::ERR_BAD_REQUEST, $copy);
     $this->assertErrorMessageStatusEquals(400, $copy);
     $awsRegions = Aws::getCloudLocations();
     $copyTo = null;
     foreach ($awsRegions as $awsRegion) {
         if ($awsRegion != $region) {
             $copyTo = $awsRegion;
             break;
         }
     }
     $this->assertNotNull($copyTo);
     $copy = $this->request($uri . '/' . $notAccessibleId . '/actions/copy', Request::METHOD_POST, [], ['cloudLocation' => $copyTo, 'cloudPlatform' => \SERVER_PLATFORMS::EC2]);
     $this->assertErrorMessageErrorEquals(ErrorMessage::ERR_SCOPE_VIOLATION, $copy);
     $this->assertErrorMessageStatusEquals(403, $copy);
     $copy = $this->request($uri . '/' . $imageBody->data->id . '/actions/copy', Request::METHOD_POST, [], ['cloudLocation' => $copyTo, 'cloudPlatform' => \SERVER_PLATFORMS::EC2]);
     $copyBody = $copy->getBody();
     $this->assertEquals(202, $copy->response->getStatus());
     $this->assertFetchResponseNotEmpty($copy);
     $this->assertImageObjectNotEmpty($copyBody->data);
     $this->assertEquals(\SERVER_PLATFORMS::EC2, $copyBody->data->cloudPlatform);
     $this->assertEquals($copyTo, $copyBody->data->cloudLocation);
     // test delete action
     $delete = $this->request($uri . '/' . $notFoundId, Request::METHOD_DELETE);
     $this->assertErrorMessageErrorEquals(ErrorMessage::ERR_OBJECT_NOT_FOUND, $delete);
     $this->assertErrorMessageStatusEquals(404, $delete);
     $delete = $this->request($uri . '/' . $entity->hash, Request::METHOD_DELETE);
     $this->assertErrorMessageErrorEquals(ErrorMessage::ERR_SCOPE_VIOLATION, $delete);
     $this->assertErrorMessageStatusEquals(403, $delete);
     $delete = $this->request($uri . '/' . $copyBody->data->id, Request::METHOD_DELETE);
     $this->assertEquals(200, $delete->response->getStatus());
     $delete = $this->request($uri . '/' . $imageBody->data->id, Request::METHOD_DELETE);
     $this->assertEquals(200, $delete->response->getStatus());
 }
예제 #18
0
 /**
  * @return Image
  */
 public function getImageEntity()
 {
     return Image::findOne([['id' => $this->snapshotId], ['envId' => $this->envId], ['platform' => $this->platform], ['cloudLocation' => $this->cloudLocation]]);
 }
예제 #19
0
 /**
  * Launches server
  *
  * @param   \ServerCreateInfo       $ServerCreateInfo optional The server create info
  * @param   \DBServer               $DBServer         optional The DBServer object
  * @param   bool                    $delayed          optional
  * @param   integer|array            $reason           optional
  * @param   \Scalr_Account_User|int $user             optional The Scalr_Account_User object or its unique identifier
  * @return  DBServer|null           Returns the DBServer object on cussess or null otherwise
  */
 public static function LaunchServer(ServerCreateInfo $ServerCreateInfo = null, DBServer $DBServer = null, $delayed = false, $reason = 0, $user = null)
 {
     $db = self::getDb();
     $farm = null;
     //Ensures handling identifier of the user instead of the object
     if ($user !== null && !$user instanceof \Scalr_Account_User) {
         try {
             $user = Scalr_Account_User::init()->loadById(intval($user));
         } catch (\Exception $e) {
         }
     }
     if (!$DBServer && $ServerCreateInfo) {
         $ServerCreateInfo->SetProperties(array(SERVER_PROPERTIES::SZR_KEY => Scalr::GenerateRandomKey(40), SERVER_PROPERTIES::SZR_KEY_TYPE => SZR_KEY_TYPE::ONE_TIME));
         $DBServer = DBServer::Create($ServerCreateInfo, false, true);
     } elseif (!$DBServer && !$ServerCreateInfo) {
         // incorrect arguments
         Logger::getLogger(LOG_CATEGORY::FARM)->error(sprintf("Cannot create server"));
         return null;
     }
     $propsToSet = array();
     if ($user instanceof \Scalr_Account_User) {
         $propsToSet[SERVER_PROPERTIES::LAUNCHED_BY_ID] = $user->id;
         $propsToSet[SERVER_PROPERTIES::LAUNCHED_BY_EMAIL] = $user->getEmail();
     }
     //We should keep role_id and farm_role_id in server properties to use in cost analytics
     if (!empty($DBServer->farmRoleId)) {
         $propsToSet[SERVER_PROPERTIES::FARM_ROLE_ID] = $DBServer->farmRoleId;
         $propsToSet[SERVER_PROPERTIES::ROLE_ID] = $DBServer->farmRoleId ? $DBServer->GetFarmRoleObject()->RoleID : 0;
     }
     try {
         // Ensures the farm object will be fetched as correctly as possible
         $farm = $DBServer->farmId ? $DBServer->GetFarmObject() : null;
         $farmRole = $DBServer->farmRoleId ? $DBServer->GetFarmRoleObject() : null;
         if (!$farmRole instanceof DBFarmRole) {
             $farmRole = null;
         } else {
             if (!$farm instanceof DBFarm) {
                 // Gets farm through FarmRole object in this case
                 $farm = $farmRole->GetFarmObject();
             }
         }
         if ($farm instanceof DBFarm) {
             $propsToSet[SERVER_PROPERTIES::FARM_CREATED_BY_ID] = $farm->createdByUserId;
             $propsToSet[SERVER_PROPERTIES::FARM_CREATED_BY_EMAIL] = $farm->createdByUserEmail;
             $projectId = $farm->GetSetting(DBFarm::SETTING_PROJECT_ID);
             if (!empty($projectId)) {
                 try {
                     $projectEntity = ProjectEntity::findPk($projectId);
                     if ($projectEntity instanceof ProjectEntity) {
                         /* @var $projectEntity ProjectEntity */
                         $ccId = $projectEntity->ccId;
                     } else {
                         $projectId = null;
                     }
                 } catch (Exception $e) {
                     $projectId = null;
                 }
             }
             $propsToSet[SERVER_PROPERTIES::FARM_PROJECT_ID] = $projectId;
         }
         if ($farmRole instanceof DBFarmRole) {
             $propsToSet[SERVER_PROPERTIES::INFO_INSTANCE_TYPE_NAME] = $farmRole->GetSetting(DBFarmRole::SETTING_INFO_INSTANCE_TYPE_NAME);
         }
         if (!empty($ccId)) {
             $propsToSet[SERVER_PROPERTIES::ENV_CC_ID] = $ccId;
         } elseif ($DBServer->envId && ($environment = $DBServer->GetEnvironmentObject()) instanceof Scalr_Environment) {
             $propsToSet[SERVER_PROPERTIES::ENV_CC_ID] = $environment->getPlatformConfigValue(Scalr_Environment::SETTING_CC_ID);
         }
     } catch (Exception $e) {
         Logger::getLogger(LOG_CATEGORY::FARM)->error(sprintf("Could not load related object for recently created server %s. It says: %s", $DBServer->serverId, $e->getMessage()));
     }
     if (!empty($propsToSet)) {
         $DBServer->SetProperties($propsToSet);
     }
     $fnGetReason = function ($reasonId) {
         $args = func_get_args();
         $args[0] = DBServer::getLaunchReason($reasonId);
         return [call_user_func_array('sprintf', $args), $reasonId];
     };
     if ($delayed) {
         $DBServer->status = SERVER_STATUS::PENDING_LAUNCH;
         list($reasonMsg, $reasonId) = is_array($reason) ? call_user_func_array($fnGetReason, $reason) : $fnGetReason($reason);
         $DBServer->SetProperties([SERVER_PROPERTIES::LAUNCH_REASON => $reasonMsg, SERVER_PROPERTIES::LAUNCH_REASON_ID => $reasonId]);
         $DBServer->Save();
         return $DBServer;
     }
     if ($ServerCreateInfo && $ServerCreateInfo->roleId) {
         $dbRole = DBRole::loadById($ServerCreateInfo->roleId);
         if ($dbRole->generation == 1) {
             $DBServer->status = SERVER_STATUS::PENDING_LAUNCH;
             $DBServer->Save();
             $DBServer->SetProperties([SERVER_PROPERTIES::LAUNCH_ERROR => "ami-scripts servers no longer supported", SERVER_PROPERTIES::LAUNCH_ATTEMPT => $DBServer->GetProperty(SERVER_PROPERTIES::LAUNCH_ATTEMPT) + 1, SERVER_PROPERTIES::LAUNCH_LAST_TRY => (new DateTime())->format('Y-m-d H:i:s')]);
             return $DBServer;
         }
     }
     // Limit amount of pending servers
     if ($DBServer->isOpenstack()) {
         $config = \Scalr::getContainer()->config;
         if ($config->defined("scalr.{$DBServer->platform}.pending_servers_limit")) {
             $pendingServersLimit = $config->get("scalr.{$DBServer->platform}.pending_servers_limit");
             $pendingServers = $db->GetOne("SELECT COUNT(*) FROM servers WHERE platform=? AND status=? AND server_id != ?", array($DBServer->platform, SERVER_STATUS::PENDING, $DBServer->serverId));
             if ($pendingServers >= $pendingServersLimit) {
                 Logger::getLogger("SERVER_LAUNCH")->warn("{$pendingServers} servers in PENDING state on {$DBServer->platform}. Limit is: {$pendingServersLimit}. Waiting.");
                 $DBServer->status = SERVER_STATUS::PENDING_LAUNCH;
                 $DBServer->Save();
                 $DBServer->SetProperties([SERVER_PROPERTIES::LAUNCH_ATTEMPT => $DBServer->GetProperty(SERVER_PROPERTIES::LAUNCH_ATTEMPT) + 1, SERVER_PROPERTIES::LAUNCH_LAST_TRY => (new DateTime())->format('Y-m-d H:i:s')]);
                 return $DBServer;
             } else {
                 Logger::getLogger("SERVER_LAUNCH")->warn("{$pendingServers} servers in PENDING state on {$DBServer->platform}. Limit is: {$pendingServersLimit}. Launching server.");
             }
         }
     }
     try {
         $account = Scalr_Account::init()->loadById($DBServer->clientId);
         $account->validateLimit(Scalr_Limits::ACCOUNT_SERVERS, 1);
         PlatformFactory::NewPlatform($DBServer->platform)->LaunchServer($DBServer);
         $DBServer->status = SERVER_STATUS::PENDING;
         $DBServer->Save();
         try {
             if ($reason) {
                 list($reasonMsg, $reasonId) = is_array($reason) ? call_user_func_array($fnGetReason, $reason) : $fnGetReason($reason);
             } else {
                 $reasonMsg = $DBServer->GetProperty(SERVER_PROPERTIES::LAUNCH_REASON);
                 $reasonId = $DBServer->GetProperty(SERVER_PROPERTIES::LAUNCH_REASON_ID);
             }
             $DBServer->getServerHistory()->markAsLaunched($reasonMsg, $reasonId);
             $DBServer->updateTimelog('ts_launched');
             if ($DBServer->imageId) {
                 //Update Image last used date
                 $image = Image::findOne([['id' => $DBServer->imageId], ['envId' => $DBServer->envId], ['platform' => $DBServer->platform], ['cloudLocation' => $DBServer->cloudLocation]]);
                 if (!$image) {
                     $image = Image::findOne([['id' => $DBServer->imageId], ['envId' => NULL], ['platform' => $DBServer->platform], ['cloudLocation' => $DBServer->cloudLocation]]);
                 }
                 if ($image) {
                     $image->dtLastUsed = new DateTime();
                     $image->save();
                 }
                 //Update Role last used date
                 if ($DBServer->farmRoleId) {
                     $dbRole = $DBServer->GetFarmRoleObject()->GetRoleObject();
                     $dbRole->dtLastUsed = date("Y-m-d H:i:s");
                     $dbRole->save();
                 }
             }
         } catch (Exception $e) {
             Logger::getLogger('SERVER_HISTORY')->error(sprintf("Cannot update servers history: {$e->getMessage()}"));
         }
     } catch (Exception $e) {
         Logger::getLogger(LOG_CATEGORY::FARM)->error(new FarmLogMessage($DBServer->farmId, sprintf("Cannot launch server on '%s' platform: %s", $DBServer->platform, $e->getMessage()), $DBServer->serverId));
         $existingLaunchError = $DBServer->GetProperty(SERVER_PROPERTIES::LAUNCH_ERROR);
         $DBServer->status = SERVER_STATUS::PENDING_LAUNCH;
         $DBServer->SetProperties([SERVER_PROPERTIES::LAUNCH_ERROR => $e->getMessage(), SERVER_PROPERTIES::LAUNCH_ATTEMPT => $DBServer->GetProperty(SERVER_PROPERTIES::LAUNCH_ATTEMPT) + 1, SERVER_PROPERTIES::LAUNCH_LAST_TRY => (new DateTime())->format('Y-m-d H:i:s')]);
         $DBServer->Save();
         if ($DBServer->farmId && !$existingLaunchError) {
             Scalr::FireEvent($DBServer->farmId, new InstanceLaunchFailedEvent($DBServer, $e->getMessage()));
         }
     }
     if ($DBServer->status == SERVER_STATUS::PENDING) {
         Scalr::FireEvent($DBServer->farmId, new BeforeInstanceLaunchEvent($DBServer));
         $DBServer->SetProperty(SERVER_PROPERTIES::LAUNCH_ERROR, "");
     }
     return $DBServer;
 }
예제 #20
0
 /**
  * @return Image
  */
 public function getImageEntity()
 {
     return Image::findOne([['id' => $this->snapshotId], ['envId' => $this->envId], ['platform' => $this->platform], ['cloudLocation' => in_array($this->platform, [SERVER_PLATFORMS::GCE, SERVER_PLATFORMS::AZURE]) ? '' : $this->cloudLocation]]);
 }
예제 #21
0
파일: Role.php 프로젝트: scalr/scalr
 /**
  * Add, replace or remove image in role
  *
  * @param   string  $platform      The cloud platform
  * @param   string  $cloudLocation The cloud location
  * @param   string  $imageId       optional Either Identifier of the Image to add or NULL to remove
  * @param   integer $userId        The identifier of the User who adds the Image
  * @param   string  $userEmail     The email address of the User who adds the Image
  *
  * @throws ImageInUseException
  * @throws ImageNotFoundException
  * @throws NotAcceptableImageStatusException
  * @throws OsMismatchException
  * @throws \Scalr\Exception\ModelException
  */
 public function setImage($platform, $cloudLocation, $imageId, $userId, $userEmail)
 {
     if (in_array($platform, [\SERVER_PLATFORMS::GCE, \SERVER_PLATFORMS::AZURE])) {
         $cloudLocation = '';
     }
     $history = new ImageHistory();
     $history->roleId = $this->id;
     $history->platform = $platform;
     $history->cloudLocation = $cloudLocation;
     $history->addedById = $userId;
     $history->addedByEmail = $userEmail;
     $oldImage = null;
     try {
         $oldImage = $this->getImage($platform, $cloudLocation);
         $history->oldImageId = $oldImage->imageId;
         if ($imageId) {
             if ($oldImage->imageId == $imageId) {
                 return;
             }
         }
     } catch (\Exception $e) {
     }
     if ($imageId) {
         /* @var $newImage Image */
         $newImage = Image::findOne([['id' => $imageId], ['platform' => $platform], ['cloudLocation' => $cloudLocation], ['$or' => [['accountId' => null], ['$and' => [['accountId' => $this->accountId], ['$or' => [['envId' => null], ['envId' => $this->envId]]]]]]]]);
         if (!$newImage) {
             throw new ImageNotFoundException(sprintf("The Image does not exist, or isn't owned by your account: %s, %s, %s", $platform, $cloudLocation, $imageId));
         }
         if ($newImage->status !== Image::STATUS_ACTIVE) {
             throw new NotAcceptableImageStatusException(sprintf("You can't add image %s because of its status: %s", $newImage->id, $newImage->status));
         }
         if ($newImage->getOs()->family && $newImage->getOs()->generation) {
             // check only if they are set
             if ($this->getOs()->family != $newImage->getOs()->family || $this->getOs()->generation != $newImage->getOs()->generation) {
                 throw new OsMismatchException(sprintf("OS mismatch between Image: %s, family: %s and Role: %d, family: %s", $newImage->id, $newImage->getOs()->family, $this->id, $this->getOs()->family));
             }
         }
         if ($this->isScalarized && !($newImage->isScalarized || $newImage->hasCloudInit)) {
             throw new ImageNotScalarizedException("You can not add the Image {$newImage->id} because neither it is not use Scalr Agent nor cloud-init");
         }
         $history->imageId = $newImage->id;
         if ($oldImage) {
             $oldImage->delete();
         }
         $newRoleImage = new RoleImage();
         $newRoleImage->roleId = $this->id;
         $newRoleImage->imageId = $newImage->id;
         $newRoleImage->platform = $newImage->platform;
         $newRoleImage->cloudLocation = $newImage->cloudLocation;
         $newRoleImage->save();
     } else {
         if ($oldImage) {
             if ($oldImage->isUsed()) {
                 throw new ImageInUseException(sprintf("The Image for roleId: %d, platform: %s, cloudLocation: %s is used by some FarmRole", $oldImage->roleId, $oldImage->platform, $oldImage->cloudLocation));
             }
             $oldImage->delete();
         }
     }
     $history->save();
 }
예제 #22
0
 /**
  * @param JsonData $images
  * @param bool $removeFromCloud
  * @throws Scalr_Exception_Core
  * @throws \Scalr\Exception\ModelException
  */
 public function xRemoveAction(JsonData $images, $removeFromCloud = false)
 {
     $this->request->restrictAccess(Acl::RESOURCE_FARMS_IMAGES, Acl::PERM_FARMS_IMAGES_MANAGE);
     $errors = [];
     $processed = [];
     $pending = [];
     foreach ($images as $i) {
         try {
             /* @var $im Image */
             $im = Image::findOne([['id' => $i['id']], ['envId' => $this->getEnvironmentId(true)], ['platform' => $i['platform']], ['cloudLocation' => $i['cloudLocation']]]);
             if ($im) {
                 if (!$im->getUsed()) {
                     if ($removeFromCloud && $this->user->isUser()) {
                         if ($im->isUsedGlobal()) {
                             throw new Exception(sprintf("Unable to delete %s, this Image may be:\n- Still registered in another Environment or Account\n- Currently in-use by a Server in another Environment", $im->id));
                         }
                         $im->status = Image::STATUS_DELETE;
                         $im->save();
                     } else {
                         if ($this->user->isScalrAdmin() && $im->isUsedGlobal()) {
                             throw new Exception(sprintf("Unable to delete %s, this Image may be:\n- Still registered in another Environment or Account\n- Currently in-use by a Server in another Environment", $im->id));
                         }
                         $im->delete();
                         $processed[] = $im->hash;
                     }
                 }
             }
         } catch (Exception $e) {
             $errors[] = $e->getMessage();
         }
     }
     $this->response->data(['processed' => $processed, 'pending' => $pending]);
     if (count($errors)) {
         $this->response->warning("Images(s) successfully removed, but some errors occurred:\n" . implode("\n", $errors));
     } else {
         $this->response->success('Images(s) successfully removed');
     }
 }