Since: 5.0 (23.05.2014)
Author: Igor Vodiasov (invar@scalr.com)
Inheritance: extends Scalr\Model\AbstractEntity, implements Scalr\DataType\ScopeInterface, implements Scalr\DataType\AccessPermissionsInterface
Example #1
0
 /**
  * @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);
 }
Example #2
0
File: Ami.php Project: scalr/scalr
 /**
  * @param string $cloudLocation
  */
 public function xListAction($cloudLocation)
 {
     $aws = $this->getEnvironment()->aws($cloudLocation);
     $existedImages = [];
     foreach (Image::find([['platform' => SERVER_PLATFORMS::EC2], ['cloudLocation' => $cloudLocation], ['envId' => $this->getEnvironmentId()]]) as $i) {
         /* @var $i Image */
         $existedImages[$i->id] = $i;
     }
     $images = [];
     foreach ($aws->ec2->image->describe(null, 'self') as $im) {
         $i = ['id' => $im->imageId, 'imageName' => $im->name, 'imageState' => $im->imageState, 'imageVirt' => $im->virtualizationType, 'imageIsPublic' => $im->isPublic];
         if (isset($existedImages[$im->imageId])) {
             $i['status'] = 'sync';
             $i['name'] = $existedImages[$im->imageId]->name;
             unset($existedImages[$im->imageId]);
         } else {
             $i['status'] = 'none';
         }
         $images[] = $i;
     }
     foreach ($existedImages as $i) {
         /* @var $i Image */
         $images[] = ['name' => $i->name, 'id' => $i->id, 'status' => 'missed'];
     }
     $this->response->data(['data' => $images]);
 }
Example #3
0
 /**
  * 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;
 }
Example #4
0
 /**
  * @param $osFamily
  * @param $osVersion
  */
 public function xGetRoleImagesAction($osFamily, $osVersion)
 {
     $this->request->restrictAccess(Acl::RESOURCE_FARMS_ROLES, Acl::PERM_FARMS_ROLES_MANAGE);
     $data = [];
     foreach (Image::find([['envId' => $this->getEnvironmentId(true)], ['osFamily' => $osFamily], ['osVersion' => $osVersion]]) as $image) {
         /* @var Image $image */
         $data[] = ['platform' => $image->platform, 'cloudLocation' => $image->cloudLocation, 'id' => $image->id, 'architecture' => $image->architecture, 'source' => $image->source, 'createdByEmail' => $image->createdByEmail];
     }
     $this->response->data(['images' => $data]);
 }
 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');
 }
Example #6
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);
 }
Example #7
0
 protected function run3()
 {
     $this->console->notice('Updating images');
     $cnt = 0;
     $cntError = 0;
     $images = Image::find([['status' => 'active'], ['size' => null], ['name' => null]]);
     foreach ($images as $i) {
         /* @var Image $i */
         if ($i->checkImage()) {
             $cnt++;
         } else {
             $cntError++;
         }
         $i->save();
     }
     $this->console->notice('Proceed %d images, mark as deleted: %d', $cnt + $cntError, $cntError);
 }
Example #8
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');
 }
Example #9
0
 /**
  * {@inheritdoc}
  * @see \Scalr\System\Zmq\Cron\TaskInterface::enqueue()
  */
 public function enqueue()
 {
     foreach (Image::find([['status' => Image::STATUS_DELETE]]) as $image) {
         try {
             /* @var $image Image */
             $image->deleteCloudImage();
             $image->delete();
         } catch (Exception $e) {
             $flag = false;
             if (strpos($e->getMessage(), 'The resource could not be found') !== false || strpos($e->getMessage(), 'The requested URL / was not found on this server.') !== false || strpos($e->getMessage(), 'Not Found') !== false || strpos($e->getMessage(), 'was not found') !== false || strpos($e->getMessage(), 'OpenStack error. Image not found.') !== false) {
                 $image->delete();
             } else {
                 $image->status = Image::STATUS_FAILED;
                 $image->statusError = $e->getMessage();
                 $image->save();
             }
         }
     }
     //Workers do not need to be used
     return new ArrayObject([]);
 }
Example #10
0
 protected function run1($stage)
 {
     $cntAll = 0;
     $cntError = 0;
     $cntUpdated = 0;
     foreach (Image::find([['type' => null], ['platform' => SERVER_PLATFORMS::EC2], ['envId' => ['$ne' => null]]]) as $image) {
         /* @var $image Image */
         $type = $image->type;
         $cntAll++;
         if ($image->checkImage()) {
             $image->save();
             if ($type != $image->type) {
                 $cntUpdated++;
             }
         } else {
             $cntError++;
         }
     }
     $this->console->out('Processed images: %d', $cntAll);
     $this->console->out('Updated images: %d', $cntUpdated);
     $this->console->out('Invalid images: %d', $cntError);
 }
Example #11
0
 /**
  * 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);
 }
Example #12
0
 public function run1($stage)
 {
     if ($this->hasTable('images')) {
         $this->db->Execute('DROP TABLE images');
         // drop old table if existed
     }
     $this->db->Execute("CREATE TABLE `images` (\n              `id` varchar(128) NOT NULL DEFAULT '',\n              `env_id` int(11) NULL DEFAULT NULL,\n              `bundle_task_id` int(11) NULL DEFAULT NULL,\n              `platform` varchar(25) NOT NULL DEFAULT '',\n              `cloud_location` varchar(255) NOT NULL DEFAULT '',\n              `os_family` varchar(25) NULL DEFAULT NULL,\n              `os_version` varchar(10) NULL DEFAULT NULL,\n              `os_name` varchar(255) NULL DEFAULT NULL,\n              `created_by_id` int(11) NULL DEFAULT NULL,\n              `created_by_email` varchar(100) NULL DEFAULT NULL,\n              `architecture` enum('i386','x86_64') NOT NULL DEFAULT 'x86_64',\n              `is_deprecated` tinyint(1) NOT NULL DEFAULT '0',\n              `source` enum('BundleTask','Manual') NOT NULL DEFAULT 'Manual',\n              `type` varchar(20) NULL DEFAULT NULL,\n              `status` varchar(20) NOT NULL,\n              `agent_version` varchar(20) NULL DEFAULT NULL,\n              UNIQUE KEY `id` (`env_id`, `id`, `platform`, `cloud_location`),\n              CONSTRAINT `fk_images_client_environmnets_id` FOREIGN KEY (`env_id`) REFERENCES `client_environments` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION\n            ) ENGINE=InnoDB DEFAULT CHARSET=latin1;\n        ");
     $allRecords = 0;
     $excludedCL = 0;
     $excludedMissing = 0;
     // convert
     $tasks = [];
     foreach ($this->db->GetAll('SELECT id as bundle_task_id, client_id as account_id, env_id, platform, snapshot_id as id, cloud_location, os_family, os_name,
         os_version, created_by_id, created_by_email, bundle_type as type FROM bundle_tasks WHERE status = ?', [\SERVER_SNAPSHOT_CREATION_STATUS::SUCCESS]) as $t) {
         if (!is_array($tasks[$t['env_id']])) {
             $tasks[$t['env_id']] = [];
         }
         $allRecords++;
         $tasks[$t['env_id']][] = $t;
     }
     foreach ($this->db->GetAll('SELECT r.client_id as account_id, r.env_id, ri.platform, ri.image_id as id, ri.cloud_location, ri.os_family, ri.os_name,
         ri.os_version, r.added_by_userid as created_by_id, r.added_by_email as created_by_email, ri.agent_version FROM role_images ri JOIN roles r ON r.id = ri.role_id') as $t) {
         if (!is_array($tasks[$t['env_id']])) {
             $tasks[$t['env_id']] = [];
         }
         $allRecords++;
         $tasks[$t['env_id']][] = $t;
     }
     foreach ($tasks as $id => $e) {
         if ($id == 0) {
             continue;
         }
         try {
             $env = (new \Scalr_Environment())->loadById($id);
         } catch (\Exception $e) {
             $this->console->warning('Invalid environment %d: %s', $id, $e->getMessage());
             continue;
         }
         foreach ($e as $t) {
             // check if snapshot exists
             $add = false;
             if ($this->db->GetOne('SELECT id FROM images WHERE id = ? AND env_id = ? AND platform = ? AND cloud_location = ? LIMIT 1', [$t['id'], $t['env_id'], $t['platform'], $t['cloud_location']])) {
                 continue;
             }
             if ($t['platform'] != \SERVER_PLATFORMS::GCE && !$t['cloud_location']) {
                 $excludedCL++;
                 continue;
             }
             try {
                 switch ($t['platform']) {
                     case \SERVER_PLATFORMS::EC2:
                         $snap = $env->aws($t['cloud_location'])->ec2->image->describe($t['id']);
                         if (count($snap)) {
                             $add = true;
                             $t['architecture'] = $snap->toArray()[0]['architecture'];
                         }
                         break;
                     case \SERVER_PLATFORMS::RACKSPACE:
                         $platform = PlatformFactory::NewPlatform(\SERVER_PLATFORMS::RACKSPACE);
                         /* @var $platform RackspacePlatformModule */
                         $client = \Scalr_Service_Cloud_Rackspace::newRackspaceCS($env->getPlatformConfigValue(RackspacePlatformModule::USERNAME, true, $t['cloud_location']), $env->getPlatformConfigValue(RackspacePlatformModule::API_KEY, true, $t['cloud_location']), $t['cloud_location']);
                         $snap = $client->getImageDetails($t['id']);
                         if ($snap) {
                             $add = true;
                         } else {
                             $excludedMissing++;
                         }
                         break;
                     case \SERVER_PLATFORMS::GCE:
                         $platform = PlatformFactory::NewPlatform(\SERVER_PLATFORMS::GCE);
                         /* @var $platform GoogleCEPlatformModule */
                         $client = $platform->getClient($env);
                         /* @var $client \Google_Service_Compute */
                         $projectId = $env->getPlatformConfigValue(GoogleCEPlatformModule::PROJECT_ID);
                         $snap = $client->images->get($projectId, str_replace($projectId . '/images/', '', $t['id']));
                         if ($snap) {
                             $add = true;
                             $t['architecture'] = 'x86_64';
                         } else {
                             $excludedMissing++;
                         }
                         break;
                     case \SERVER_PLATFORMS::EUCALYPTUS:
                         $snap = $env->eucalyptus($t['cloud_location'])->ec2->image->describe($t['id']);
                         if (count($snap)) {
                             $add = true;
                             $t['architecture'] = $snap->toArray()[0]['architecture'];
                         }
                         break;
                     case \SERVER_PLATFORMS::NIMBULA:
                         continue;
                     default:
                         if (PlatformFactory::isOpenstack($t['platform'])) {
                             $snap = $env->openstack($t['platform'], $t['cloud_location'])->servers->getImage($t['id']);
                             if ($snap) {
                                 $add = true;
                                 $t['architecture'] = $snap->metadata->arch == 'x84-64' ? 'x84_64' : 'i386';
                             } else {
                                 $excludedMissing++;
                             }
                         } else {
                             if (PlatformFactory::isCloudstack($t['platform'])) {
                                 $snap = $env->cloudstack($t['platform'])->template->describe(['templatefilter' => 'executable', 'id' => $t['id'], 'zoneid' => $t['cloud_location']]);
                                 if ($snap) {
                                     if (isset($snap[0])) {
                                         $add = true;
                                     }
                                 } else {
                                     $excludedMissing++;
                                 }
                             } else {
                                 $this->console->warning('Unknown platform: %s', $t['platform']);
                             }
                         }
                 }
                 if ($add) {
                     $image = new Image();
                     $image->id = $t['id'];
                     $image->envId = $t['env_id'];
                     $image->bundleTaskId = $t['bundle_task_id'];
                     $image->platform = $t['platform'];
                     $image->cloudLocation = $t['cloud_location'];
                     $image->osFamily = $t['os_family'];
                     $image->osVersion = $t['os_version'];
                     $image->osName = $t['os_name'];
                     $image->createdById = $t['created_by_id'];
                     $image->createdByEmail = $t['created_by_email'];
                     $image->architecture = $t['architecture'] ? $t['architecture'] : 'x86_64';
                     $image->isDeprecated = 0;
                     $image->source = $t['bundle_task_id'] ? 'BundleTask' : 'Manual';
                     $image->type = $t['type'];
                     $image->status = Image::STATUS_ACTIVE;
                     $image->agentVersion = $t['agent_version'];
                     $image->save();
                 } else {
                     $excludedMissing++;
                 }
             } catch (\Exception $e) {
                 if (strpos($e->getMessage(), 'The resource could not be found') !== FALSE) {
                     $excludedMissing++;
                 } else {
                     if (strpos($e->getMessage(), 'The requested URL / was not found on this server.') !== FALSE) {
                         $excludedMissing++;
                     } else {
                         if (strpos($e->getMessage(), 'Not Found') !== FALSE) {
                             $excludedMissing++;
                         } else {
                             if (strpos($e->getMessage(), 'was not found') !== FALSE) {
                                 $excludedMissing++;
                             } else {
                                 if (strpos($e->getMessage(), 'Bad username or password') !== FALSE) {
                                     $excludedMissing++;
                                 } else {
                                     if (strpos($e->getMessage(), 'unable to verify user credentials and/or request signature') !== FALSE) {
                                         $excludedMissing++;
                                     } else {
                                         if (strpos($e->getMessage(), 'OpenStack error. Image not found.') !== FALSE) {
                                             $excludedMissing++;
                                         } else {
                                             if (strpos($e->getMessage(), 'Neither api key nor password was provided for the OpenStack config.') !== FALSE) {
                                                 $excludedMissing++;
                                             } else {
                                                 $this->console->warning('SnapshotId: %s, envId: %d, error: %s', $t['id'], $t['env_id'], $e->getMessage());
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
     $this->console->notice('Found %d records', $allRecords);
     $this->console->notice('Excluded %d images because of null cloud_location', $excludedCL);
     $this->console->notice('Excluded %d missed images', $excludedMissing);
 }
Example #13
0
 /**
  * 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);
     }
 }
Example #14
0
 /**
  * {@inheritdoc}
  * @see \Scalr\Modules\PlatformModuleInterface::RemoveServerSnapshot()
  */
 public function RemoveServerSnapshot(Image $image)
 {
     if (!$image->getEnvironment()) {
         return true;
     }
     $gce = $this->getClient($image->getEnvironment());
     try {
         $projectId = $image->getEnvironment()->keychain(SERVER_PLATFORMS::GCE)->properties[Entity\CloudCredentialsProperty::GCE_PROJECT_ID];
         $imageId = str_replace("{$projectId}/images/", "", $image->id);
         $gce->images->delete($projectId, $imageId);
     } catch (Exception $e) {
         if (stristr($e->getMessage(), "was not found")) {
             return true;
         } else {
             throw $e;
         }
     }
     return true;
 }
 public function run2()
 {
     if ($this->hasTableIndex('images', 'id')) {
         $this->db->Execute('ALTER TABLE images DROP KEY id, ADD UNIQUE KEY `idx_id` (`env_id`,`id`,`platform`,`cloud_location`)');
     }
     $this->db->Execute('ALTER TABLE images ADD `hash` binary(16) NOT NULL FIRST');
     foreach ($this->db->GetAll('SELECT * FROM images') as $im) {
         if ($im['env_id']) {
             $this->db->Execute('UPDATE images SET hash = UNHEX(?) WHERE env_id = ? AND id = ? AND platform = ? AND cloud_location = ?', [str_replace('-', '', Image::calculateHash($im['env_id'], $im['id'], $im['platform'], $im['cloud_location'])), $im['env_id'], $im['id'], $im['platform'], $im['cloud_location']]);
         } else {
             $this->db->Execute('UPDATE images SET hash = UNHEX(?) WHERE ISNULL(env_id) AND id = ? AND platform = ? AND cloud_location = ?', [str_replace('-', '', Image::calculateHash($im['env_id'], $im['id'], $im['platform'], $im['cloud_location'])), $im['id'], $im['platform'], $im['cloud_location']]);
         }
     }
     // remove possible duplicates
     foreach ($this->db->GetAll('SELECT `hash`, count(*) as cnt FROM images GROUP BY hash HAVING cnt > 1') as $im) {
         $this->db->Execute('DELETE FROM images WHERE hash = ? LIMIT ?', [$im['hash'], $im['cnt'] - 1]);
     }
     $this->db->Execute('ALTER TABLE images ADD PRIMARY KEY(`hash`)');
 }
Example #16
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());
 }
 /**
  * {@inheritdoc}
  * @see \Scalr\Modules\PlatformModuleInterface::RemoveServerSnapshot()
  */
 public function RemoveServerSnapshot(Image $image)
 {
     if (!$image->getEnvironment()) {
         return true;
     }
     $cs = $image->getEnvironment()->cloudstack($this->platform);
     try {
         $cs->template->delete($image->id, $image->cloudLocation);
     } catch (\Exception $e) {
         throw $e;
     }
     return true;
 }
Example #18
0
 /**
  * @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]]);
 }
Example #19
0
 /**
  * {@inheritdoc}
  * @see \Scalr\Modules\PlatformModuleInterface::RemoveServerSnapshot()
  */
 public function RemoveServerSnapshot(Image $image)
 {
     try {
         if (!$image->getEnvironment()) {
             return true;
         }
         $aws = $image->getEnvironment()->aws($image->cloudLocation);
         try {
             $ami = $aws->ec2->image->describe($image->id)->get(0);
         } catch (Exception $e) {
             if (stristr($e->getMessage(), "is no longer available") || stristr($e->getMessage(), "does not exist")) {
                 return true;
             } else {
                 throw $e;
             }
         }
         //$ami variable is expected to be defined here
         $platform = $ami->platform;
         $rootDeviceType = $ami->rootDeviceType;
         if ($rootDeviceType == 'ebs') {
             $ami->deregister();
             //blockDeviceMapping is not mandatory option in the response as well as ebs data set.
             $snapshotId = $ami->blockDeviceMapping && count($ami->blockDeviceMapping) > 0 && $ami->blockDeviceMapping->get(0)->ebs ? $ami->blockDeviceMapping->get(0)->ebs->snapshotId : null;
             if ($snapshotId) {
                 $aws->ec2->snapshot->delete($snapshotId);
             }
         } else {
             $image_path = $ami->imageLocation;
             $chunks = explode("/", $image_path);
             $bucketName = array_shift($chunks);
             $manifestObjectName = implode('/', $chunks);
             $prefix = str_replace(".manifest.xml", "", $manifestObjectName);
             try {
                 $bucket_not_exists = false;
                 $objects = $aws->s3->bucket->listObjects($bucketName, null, null, null, $prefix);
             } catch (\Exception $e) {
                 if ($e instanceof AwsClientException && $e->getErrorData() instanceof ErrorData && $e->getErrorData()->getCode() == 404) {
                     $bucket_not_exists = true;
                 }
             }
             if ($ami) {
                 if (!$bucket_not_exists) {
                     /* @var $object ObjectData */
                     foreach ($objects as $object) {
                         $object->delete();
                     }
                     $bucket_not_exists = true;
                 }
                 if ($bucket_not_exists) {
                     $aws->ec2->image->deregister($image->id);
                 }
             }
         }
         unset($aws);
         unset($ami);
     } catch (Exception $e) {
         if (stristr($e->getMessage(), "is no longer available")) {
         } else {
             throw $e;
         }
     }
 }
Example #20
0
File: Role.php Project: 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();
 }
 /**
  * {@inheritdoc}
  * @see \Scalr\Modules\PlatformModuleInterface::RemoveServerSnapshot()
  */
 public function RemoveServerSnapshot(Image $image)
 {
     if (!$image->getEnvironment()) {
         return true;
     }
     $rsClient = $this->getRsClient($image->getEnvironment(), $image->cloudLocation);
     try {
         $rsClient->deleteImage($image->id);
     } catch (Exception $e) {
         if (stristr($e->getMessage(), "Cannot destroy a destroyed snapshot") || stristr($e->getMessage(), "com.rackspace.cloud.service.servers.ItemNotFoundFault") || stristr($e->getMessage(), "NotFoundException")) {
             return true;
         } else {
             throw $e;
         }
     }
     return true;
 }
Example #22
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']);
             }
         }
     }
 }
 /**
  * {@inheritdoc}
  * @see \Scalr\Modules\PlatformModuleInterface::RemoveServerSnapshot()
  */
 public function RemoveServerSnapshot(Image $image)
 {
     if (!$image->getEnvironment()) {
         return true;
     }
     $gce = $this->getClient($image->getEnvironment());
     try {
         $projectId = $image->getEnvironment()->getPlatformConfigValue(self::PROJECT_ID);
         $imageId = str_replace("{$projectId}/images/", "", $image->id);
         $gce->images->delete($projectId, $imageId);
     } catch (\Exception $e) {
         if (stristr($e->getMessage(), "was not found")) {
             return true;
         } else {
             throw $e;
         }
     }
     return true;
 }
 protected function run8($stage)
 {
     $knownOses = [];
     //Retrieves the list of all known OSes
     foreach (Entity\Os::all() as $os) {
         /* @var $os Entity\Os */
         $knownOses[$os->id] = $os;
     }
     $role = new Entity\Role();
     //Trying to clarify the operating system of the Roles using Images which are associated with them.
     //If all Images have the same operating system it will be considered as acceptable for the Role at latter will be updated.
     $rs = $this->db->Execute("\n            SELECT " . $role->fields('r', true) . ", GROUP_CONCAT(t.os_id) `osids`\n            FROM roles r JOIN (\n                SELECT DISTINCT ri.role_id, i.os_id\n                FROM images i\n                JOIN role_images ri ON i.id = ri.image_id\n                    AND i.platform = ri.platform\n                    AND i.cloud_location = ri.cloud_location\n            ) t ON t.role_id = r.id\n            WHERE r.os_id = ?\n            GROUP BY r.id\n            HAVING osids != r.os_id\n        ", ['unknown-os']);
     if ($rs->RecordCount()) {
         $this->console->out("Found %d Roles the OS value of which can be filled from the Images. Updating...", $rs->RecordCount());
     }
     while ($row = $rs->FetchRow()) {
         $role = new Entity\Role();
         $role->load($row, 'r');
         if (!empty($row['osids'])) {
             if (isset($knownOses[$row['osids']])) {
                 //Updating OS value of the Role
                 $role->osId = $row['osids'];
                 $role->save();
             } else {
                 $this->console->warning("Role %s (%d) is associated with the Images with either different or unknown OS: %s", $role->name, $role->id, $row['osids']);
             }
         }
     }
     $image = new Entity\Image();
     //Trying to clarify the operating sytem of the Images using Roles which are associated with them.
     $rs = $this->db->Execute("\n            SELECT " . $image->fields('i', true) . ", GROUP_CONCAT(t.os_id) `osids`\n            FROM images i JOIN (\n                SELECT DISTINCT ri.image_id, ri.platform, ri.cloud_location, r.os_id\n                FROM roles r\n                JOIN role_images ri ON ri.role_id = r.id\n            ) t ON t.image_id = i.id AND t.platform = i.platform AND t.cloud_location = i.cloud_location\n            WHERE i.os_id = ?\n            GROUP BY i.hash\n            HAVING osids != i.os_id\n        ", ['unknown-os']);
     if ($rs->RecordCount()) {
         $this->console->out("Found %d Images the OS value of which can be filled from the Roles. Updating...", $rs->RecordCount());
     }
     while ($row = $rs->FetchRow()) {
         $image = new Entity\Image();
         $image->load($row, 'i');
         if (!empty($row['osids'])) {
             if (isset($knownOses[$row['osids']])) {
                 //Updating OS value of the Image
                 $image->osId = $row['osids'];
                 $image->save();
             } else {
                 $this->console->warning("Image (%s) imageId: %s, platform: %s, cloudLocation: %s is associated with the Roles with either different or unknown OS: %s", $image->hash, $image->id, $image->platform, $image->cloudLocation, $row['osids']);
             }
         }
     }
 }
Example #25
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;
 }
Example #26
0
 /**
  * @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;
 }
Example #27
0
 /**
  * Detach configured cloud configuration from specified environment
  *
  * @param   int     $envId  Environment ID
  * @param   string  $cloud  Cloud platform name
  *
  * @return  ResultEnvelope
  *
  * @throws  ApiErrorException
  * @throws  ModelException
  */
 public function detachCredentialsAction($envId, $cloud)
 {
     if (!$this->getUser()->canManageAcl()) {
         $this->checkPermissions(Acl::RESOURCE_ENV_CLOUDS_ENVIRONMENT);
     }
     $env = $this->getEnv($envId);
     $cloudCredentials = $env->keychain($cloud);
     if (empty($cloudCredentials->id)) {
         throw new ApiErrorException(404, ErrorMessage::ERR_OBJECT_NOT_FOUND, "Cloud '{$cloud}' not configured for this environment");
     }
     if (in_array($cloudCredentials->cloud, [SERVER_PLATFORMS::EC2, SERVER_PLATFORMS::GCE]) && (count(Entity\Server::find([['envId' => $envId], ['platform' => $cloudCredentials->cloud]])) || count(Entity\Image::find([['envId' => $envId], ['platform' => $cloudCredentials->cloud]])))) {
         throw new ApiErrorException(409, ErrorMessage::ERR_OBJECT_IN_USE, "Cloud Credentials are used");
     }
     $cloudCredentials->environments[$envId]->delete();
     return $this->result(null);
 }
Example #28
0
 /**
  * {@inheritdoc}
  * @see \Scalr\Modules\PlatformModuleInterface::RemoveServerSnapshot()
  */
 public function RemoveServerSnapshot(Image $image)
 {
     if (!$image->getEnvironment()) {
         return true;
     }
     try {
         $cloudLocation = $image->cloudLocation;
         if ($image->cloudLocation == '') {
             $locations = $this->getLocations($image->getEnvironment());
             $cloudLocation = array_keys($locations)[0];
         }
         $osClient = $image->getEnvironment()->openstack($image->platform, $cloudLocation);
         $osClient->servers->images->delete($image->id);
     } catch (\Exception $e) {
         if (stristr($e->getMessage(), "Image not found") || stristr($e->getMessage(), "Cannot destroy a destroyed snapshot")) {
             //DO NOTHING
         } else {
             throw $e;
         }
     }
     return true;
 }
Example #29
0
 /**
  * Migrates an Image to another Cloud Location
  *
  * @param  string $cloudLocation The cloud location
  * @param  \Scalr_Account_User|\Scalr\Model\Entity\Account\User $user The user object
  * @return Image
  * @throws Exception
  * @throws NotEnabledPlatformException
  * @throws DomainException
  */
 public function migrateEc2Location($cloudLocation, $user)
 {
     if (!$this->getEnvironment()->isPlatformEnabled(SERVER_PLATFORMS::EC2)) {
         throw new NotEnabledPlatformException("You can migrate image between regions only on EC2 cloud");
     }
     if ($this->cloudLocation == $cloudLocation) {
         throw new DomainException('Destination region is the same as source one');
     }
     $snap = $this->getEnvironment()->aws($this->cloudLocation)->ec2->image->describe($this->id);
     if ($snap->count() == 0) {
         throw new Exception("Image haven't been found on cloud.");
     }
     if ($snap->get(0)->toArray()['imageState'] != 'available') {
         throw new Exception('Image is not in "available" status on cloud and cannot be copied.');
     }
     $this->checkImage();
     // re-check properties
     $aws = $this->getEnvironment()->aws($cloudLocation);
     $newImageId = $aws->ec2->image->copy($this->cloudLocation, $this->id, $this->name, "Image was copied by Scalr from image: {$this->name}, cloudLocation: {$this->cloudLocation}, id: {$this->id}", null, $cloudLocation);
     $newImage = new Image();
     $newImage->platform = $this->platform;
     $newImage->cloudLocation = $cloudLocation;
     $newImage->id = $newImageId;
     $newImage->name = $this->name;
     $newImage->architecture = $this->architecture;
     $newImage->size = $this->size;
     $newImage->accountId = $this->accountId;
     $newImage->envId = $this->envId;
     $newImage->osId = $this->osId;
     $newImage->source = Image::SOURCE_MANUAL;
     $newImage->type = $this->type;
     $newImage->agentVersion = $this->agentVersion;
     $newImage->createdById = $user->getId();
     $newImage->createdByEmail = $user->getEmail();
     $newImage->status = Image::STATUS_ACTIVE;
     $newImage->isScalarized = $this->isScalarized;
     $newImage->hasCloudInit = $this->hasCloudInit;
     $newImage->save();
     $newImage->setSoftware($this->getSoftware());
     return $newImage;
 }
Example #30
0
 /**
  * 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]]);
 }