File indexing completed on 2024-12-29 05:27:29
0001 <?php 0002 /** 0003 * @category Zend 0004 * @package Zend_Cloud_Infrastructure 0005 * @subpackage Adapter 0006 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0007 * @license http://framework.zend.com/license/new-bsd New BSD License 0008 */ 0009 0010 // require_once 'Zend/Service/Amazon/Ec2/Instance.php'; 0011 // require_once 'Zend/Service/Amazon/Ec2/Image.php'; 0012 // require_once 'Zend/Service/Amazon/Ec2/Availabilityzones.php'; 0013 // require_once 'Zend/Service/Amazon/Ec2/CloudWatch.php'; 0014 // require_once 'Zend/Cloud/Infrastructure/Instance.php'; 0015 // require_once 'Zend/Cloud/Infrastructure/InstanceList.php'; 0016 // require_once 'Zend/Cloud/Infrastructure/Image.php'; 0017 // require_once 'Zend/Cloud/Infrastructure/ImageList.php'; 0018 // require_once 'Zend/Cloud/Infrastructure/Adapter/AbstractAdapter.php'; 0019 0020 /** 0021 * Amazon EC2 adapter for infrastructure service 0022 * 0023 * @package Zend_Cloud_Infrastructure 0024 * @subpackage Adapter 0025 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0026 * @license http://framework.zend.com/license/new-bsd New BSD License 0027 */ 0028 class Zend_Cloud_Infrastructure_Adapter_Ec2 extends Zend_Cloud_Infrastructure_Adapter_AbstractAdapter 0029 { 0030 /** 0031 * AWS constants 0032 */ 0033 const AWS_ACCESS_KEY = 'aws_accesskey'; 0034 const AWS_SECRET_KEY = 'aws_secretkey'; 0035 const AWS_REGION = 'aws_region'; 0036 const AWS_SECURITY_GROUP = 'securityGroup'; 0037 0038 /** 0039 * Ec2 Instance 0040 * 0041 * @var Ec2Instance 0042 */ 0043 protected $ec2; 0044 0045 /** 0046 * Ec2 Image 0047 * 0048 * @var Ec2Image 0049 */ 0050 protected $ec2Image; 0051 0052 /** 0053 * Ec2 Zone 0054 * 0055 * @var Ec2Zone 0056 */ 0057 protected $ec2Zone; 0058 0059 /** 0060 * Ec2 Monitor 0061 * 0062 * @var Ec2Monitor 0063 */ 0064 protected $ec2Monitor; 0065 0066 /** 0067 * AWS Access Key 0068 * 0069 * @var string 0070 */ 0071 protected $accessKey; 0072 0073 /** 0074 * AWS Access Secret 0075 * 0076 * @var string 0077 */ 0078 protected $accessSecret; 0079 0080 /** 0081 * Region zone 0082 * 0083 * @var string 0084 */ 0085 protected $region; 0086 0087 /** 0088 * Map array between EC2 and Infrastructure status 0089 * 0090 * @var array 0091 */ 0092 protected $mapStatus = array ( 0093 'running' => Zend_Cloud_Infrastructure_Instance::STATUS_RUNNING, 0094 'terminated' => Zend_Cloud_Infrastructure_Instance::STATUS_TERMINATED, 0095 'pending' => Zend_Cloud_Infrastructure_Instance::STATUS_PENDING, 0096 'shutting-down' => Zend_Cloud_Infrastructure_Instance::STATUS_SHUTTING_DOWN, 0097 'stopping' => Zend_Cloud_Infrastructure_Instance::STATUS_PENDING, 0098 'stopped' => Zend_Cloud_Infrastructure_Instance::STATUS_STOPPED, 0099 'rebooting' => Zend_Cloud_Infrastructure_Instance::STATUS_REBOOTING, 0100 ); 0101 0102 /** 0103 * Map monitor metrics between Infrastructure and EC2 0104 * 0105 * @var array 0106 */ 0107 protected $mapMetrics= array ( 0108 Zend_Cloud_Infrastructure_Instance::MONITOR_CPU => 'CPUUtilization', 0109 Zend_Cloud_Infrastructure_Instance::MONITOR_DISK_READ => 'DiskReadBytes', 0110 Zend_Cloud_Infrastructure_Instance::MONITOR_DISK_WRITE => 'DiskWriteBytes', 0111 Zend_Cloud_Infrastructure_Instance::MONITOR_NETWORK_IN => 'NetworkIn', 0112 Zend_Cloud_Infrastructure_Instance::MONITOR_NETWORK_OUT => 'NetworkOut', 0113 ); 0114 0115 /** 0116 * Constructor 0117 * 0118 * @param array|Zend_Config $options 0119 * @return void 0120 */ 0121 public function __construct($options = array()) 0122 { 0123 if (is_object($options)) { 0124 if (method_exists($options, 'toArray')) { 0125 $options= $options->toArray(); 0126 } elseif ($options instanceof Traversable) { 0127 $options = iterator_to_array($options); 0128 } 0129 } 0130 0131 if (empty($options) || !is_array($options)) { 0132 // require_once 'Zend/Cloud/Infrastructure/Exception.php'; 0133 throw new Zend_Cloud_Infrastructure_Exception('Invalid options provided'); 0134 } 0135 0136 if (!isset($options[self::AWS_ACCESS_KEY]) 0137 || !isset($options[self::AWS_SECRET_KEY]) 0138 ) { 0139 // require_once 'Zend/Cloud/Infrastructure/Exception.php'; 0140 throw new Zend_Cloud_Infrastructure_Exception('AWS keys not specified!'); 0141 } 0142 0143 $this->accessKey = $options[self::AWS_ACCESS_KEY]; 0144 $this->accessSecret = $options[self::AWS_SECRET_KEY]; 0145 $this->region = ''; 0146 0147 if (isset($options[self::AWS_REGION])) { 0148 $this->region= $options[self::AWS_REGION]; 0149 } 0150 0151 try { 0152 $this->ec2 = new Zend_Service_Amazon_Ec2_Instance($options[self::AWS_ACCESS_KEY], $options[self::AWS_SECRET_KEY], $this->region); 0153 } catch (Exception $e) { 0154 // require_once 'Zend/Cloud/Infrastructure/Exception.php'; 0155 throw new Zend_Cloud_Infrastructure_Exception('Error on create: ' . $e->getMessage(), $e->getCode(), $e); 0156 } 0157 0158 if (isset($options[self::HTTP_ADAPTER])) { 0159 $this->ec2->getHttpClient()->setAdapter($options[self::HTTP_ADAPTER]); 0160 } 0161 } 0162 0163 /** 0164 * Convert the attributes of EC2 into attributes of Infrastructure 0165 * 0166 * @param array $attr 0167 * @return array|boolean 0168 */ 0169 private function convertAttributes($attr) 0170 { 0171 $result = array(); 0172 if (!empty($attr) && is_array($attr)) { 0173 $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_ID] = $attr['instanceId']; 0174 $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STATUS] = $this->mapStatus[$attr['instanceState']['name']]; 0175 $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_IMAGEID] = $attr['imageId']; 0176 $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_ZONE] = $attr['availabilityZone']; 0177 $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_LAUNCHTIME] = $attr['launchTime']; 0178 0179 switch ($attr['instanceType']) { 0180 case Zend_Service_Amazon_Ec2_Instance::MICRO: 0181 $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_CPU] = '1 virtual core'; 0182 $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_RAM] = '613MB'; 0183 $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STORAGE] = '0GB'; 0184 break; 0185 case Zend_Service_Amazon_Ec2_Instance::SMALL: 0186 $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_CPU] = '1 virtual core'; 0187 $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_RAM] = '1.7GB'; 0188 $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STORAGE] = '160GB'; 0189 break; 0190 case Zend_Service_Amazon_Ec2_Instance::LARGE: 0191 $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_CPU] = '2 virtual core'; 0192 $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_RAM] = '7.5GB'; 0193 $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STORAGE] = '850GB'; 0194 break; 0195 case Zend_Service_Amazon_Ec2_Instance::XLARGE: 0196 $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_CPU] = '4 virtual core'; 0197 $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_RAM] = '15GB'; 0198 $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STORAGE] = '1690GB'; 0199 break; 0200 case Zend_Service_Amazon_Ec2_Instance::HCPU_MEDIUM: 0201 $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_CPU] = '2 virtual core'; 0202 $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_RAM] = '1.7GB'; 0203 $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STORAGE] = '350GB'; 0204 break; 0205 case Zend_Service_Amazon_Ec2_Instance::HCPU_XLARGE: 0206 $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_CPU] = '8 virtual core'; 0207 $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_RAM] = '7GB'; 0208 $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STORAGE] = '1690GB'; 0209 break; 0210 } 0211 } 0212 return $result; 0213 } 0214 0215 /** 0216 * Return a list of the available instancies 0217 * 0218 * @return Zend_Cloud_Infrastructure_InstanceList 0219 */ 0220 public function listInstances() 0221 { 0222 $this->adapterResult = $this->ec2->describe(); 0223 0224 $result = array(); 0225 foreach ($this->adapterResult['instances'] as $instance) { 0226 $result[]= $this->convertAttributes($instance); 0227 } 0228 return new Zend_Cloud_Infrastructure_InstanceList($this, $result); 0229 } 0230 0231 /** 0232 * Return the status of an instance 0233 * 0234 * @param string 0235 * @return string|boolean 0236 */ 0237 public function statusInstance($id) 0238 { 0239 $this->adapterResult = $this->ec2->describe($id); 0240 if (empty($this->adapterResult['instances'])) { 0241 return false; 0242 } 0243 $result = $this->adapterResult['instances'][0]; 0244 return $this->mapStatus[$result['instanceState']['name']]; 0245 } 0246 0247 /** 0248 * Return the public DNS name of the instance 0249 * 0250 * @param string $id 0251 * @return string|boolean 0252 */ 0253 public function publicDnsInstance($id) 0254 { 0255 $this->adapterResult = $this->ec2->describe($id); 0256 if (empty($this->adapterResult['instances'])) { 0257 return false; 0258 } 0259 $result = $this->adapterResult['instances'][0]; 0260 return $result['dnsName']; 0261 } 0262 0263 /** 0264 * Reboot an instance 0265 * 0266 * @param string $id 0267 * @return boolean 0268 */ 0269 public function rebootInstance($id) 0270 { 0271 $this->adapterResult= $this->ec2->reboot($id); 0272 return $this->adapterResult; 0273 } 0274 0275 /** 0276 * Create a new instance 0277 * 0278 * @param string $name 0279 * @param array $options 0280 * @return Instance|boolean 0281 */ 0282 public function createInstance($name, $options) 0283 { 0284 // @todo instance's name management? 0285 $this->adapterResult = $this->ec2->run($options); 0286 if (empty($this->adapterResult['instances'])) { 0287 return false; 0288 } 0289 $this->error= false; 0290 return new Zend_Cloud_Infrastructure_Instance($this, $this->convertAttributes($this->adapterResult['instances'][0])); 0291 } 0292 0293 /** 0294 * Stop an instance 0295 * 0296 * @param string $id 0297 * @return boolean 0298 */ 0299 public function stopInstance($id) 0300 { 0301 // require_once 'Zend/Cloud/Infrastructure/Exception.php'; 0302 throw new Zend_Cloud_Infrastructure_Exception('The stopInstance method is not implemented in the adapter'); 0303 } 0304 0305 /** 0306 * Start an instance 0307 * 0308 * @param string $id 0309 * @return boolean 0310 */ 0311 public function startInstance($id) 0312 { 0313 // require_once 'Zend/Cloud/Infrastructure/Exception.php'; 0314 throw new Zend_Cloud_Infrastructure_Exception('The startInstance method is not implemented in the adapter'); 0315 } 0316 0317 /** 0318 * Destroy an instance 0319 * 0320 * @param string $id 0321 * @return boolean 0322 */ 0323 public function destroyInstance($id) 0324 { 0325 $this->adapterResult = $this->ec2->terminate($id); 0326 return (!empty($this->adapterResult)); 0327 } 0328 0329 /** 0330 * Return a list of all the available instance images 0331 * 0332 * @return ImageList 0333 */ 0334 public function imagesInstance() 0335 { 0336 if (!isset($this->ec2Image)) { 0337 $this->ec2Image = new Zend_Service_Amazon_Ec2_Image($this->accessKey, $this->accessSecret, $this->region); 0338 } 0339 0340 $this->adapterResult = $this->ec2Image->describe(); 0341 0342 $images = array(); 0343 0344 foreach ($this->adapterResult as $result) { 0345 switch (strtolower($result['platform'])) { 0346 case 'windows' : 0347 $platform = Zend_Cloud_Infrastructure_Image::IMAGE_WINDOWS; 0348 break; 0349 default: 0350 $platform = Zend_Cloud_Infrastructure_Image::IMAGE_LINUX; 0351 break; 0352 } 0353 0354 $images[]= array ( 0355 Zend_Cloud_Infrastructure_Image::IMAGE_ID => $result['imageId'], 0356 Zend_Cloud_Infrastructure_Image::IMAGE_NAME => '', 0357 Zend_Cloud_Infrastructure_Image::IMAGE_DESCRIPTION => $result['imageLocation'], 0358 Zend_Cloud_Infrastructure_Image::IMAGE_OWNERID => $result['imageOwnerId'], 0359 Zend_Cloud_Infrastructure_Image::IMAGE_ARCHITECTURE => $result['architecture'], 0360 Zend_Cloud_Infrastructure_Image::IMAGE_PLATFORM => $platform, 0361 ); 0362 } 0363 return new Zend_Cloud_Infrastructure_ImageList($images,$this->ec2Image); 0364 } 0365 0366 /** 0367 * Return all the available zones 0368 * 0369 * @return array 0370 */ 0371 public function zonesInstance() 0372 { 0373 if (!isset($this->ec2Zone)) { 0374 $this->ec2Zone = new Zend_Service_Amazon_Ec2_AvailabilityZones($this->accessKey,$this->accessSecret,$this->region); 0375 } 0376 $this->adapterResult = $this->ec2Zone->describe(); 0377 0378 $zones = array(); 0379 foreach ($this->adapterResult as $zone) { 0380 if (strtolower($zone['zoneState']) === 'available') { 0381 $zones[] = array ( 0382 Zend_Cloud_Infrastructure_Instance::INSTANCE_ZONE => $zone['zoneName'], 0383 ); 0384 } 0385 } 0386 return $zones; 0387 } 0388 0389 /** 0390 * Return the system information about the $metric of an instance 0391 * 0392 * @param string $id 0393 * @param string $metric 0394 * @param null|array $options 0395 * @return array 0396 */ 0397 public function monitorInstance($id, $metric, $options = null) 0398 { 0399 if (empty($id) || empty($metric)) { 0400 return false; 0401 } 0402 0403 if (!in_array($metric,$this->validMetrics)) { 0404 // require_once 'Zend/Cloud/Infrastructure/Exception.php'; 0405 throw new Zend_Cloud_Infrastructure_Exception(sprintf( 0406 'The metric "%s" is not valid', 0407 $metric 0408 )); 0409 } 0410 0411 if (!empty($options) && !is_array($options)) { 0412 // require_once 'Zend/Cloud/Infrastructure/Exception.php'; 0413 throw new Zend_Cloud_Infrastructure_Exception('The options must be an array'); 0414 } 0415 0416 if (!empty($options) 0417 && (empty($options[Zend_Cloud_Infrastructure_Instance::MONITOR_START_TIME]) 0418 || empty($options[Zend_Cloud_Infrastructure_Instance::MONITOR_END_TIME])) 0419 ) { 0420 // require_once 'Zend/Cloud/Infrastructure/Exception.php'; 0421 throw new Zend_Cloud_Infrastructure_Exception(sprintf( 0422 'The options array must contain: "%s" and "%s"', 0423 $options[Zend_Cloud_Infrastructure_Instance::MONITOR_START_TIME], 0424 $options[Zend_Cloud_Infrastructure_Instance::MONITOR_END_TIME] 0425 )); 0426 } 0427 0428 if (!isset($this->ec2Monitor)) { 0429 $this->ec2Monitor = new Zend_Service_Amazon_Ec2_CloudWatch($this->accessKey, $this->accessSecret, $this->region); 0430 } 0431 0432 $param = array( 0433 'MeasureName' => $this->mapMetrics[$metric], 0434 'Statistics' => array('Average'), 0435 'Dimensions' => array('InstanceId' => $id), 0436 ); 0437 0438 if (!empty($options)) { 0439 $param['StartTime'] = $options[Zend_Cloud_Infrastructure_Instance::MONITOR_START_TIME]; 0440 $param['EndTime'] = $options[Zend_Cloud_Infrastructure_Instance::MONITOR_END_TIME]; 0441 } 0442 0443 $this->adapterResult = $this->ec2Monitor->getMetricStatistics($param); 0444 0445 $monitor = array(); 0446 $num = 0; 0447 $average = 0; 0448 0449 if (!empty($this->adapterResult['datapoints'])) { 0450 foreach ($this->adapterResult['datapoints'] as $result) { 0451 $monitor['series'][] = array ( 0452 'timestamp' => $result['Timestamp'], 0453 'value' => $result['Average'], 0454 ); 0455 $average += $result['Average']; 0456 $num++; 0457 } 0458 } 0459 0460 if ($num > 0) { 0461 $monitor['average'] = $average / $num; 0462 } 0463 0464 return $monitor; 0465 } 0466 0467 /** 0468 * Get the adapter 0469 * 0470 * @return Zend_Service_Amazon_Ec2_Instance 0471 */ 0472 public function getAdapter() 0473 { 0474 return $this->ec2; 0475 } 0476 0477 /** 0478 * Get last HTTP request 0479 * 0480 * @return string 0481 */ 0482 public function getLastHttpRequest() 0483 { 0484 return $this->ec2->getHttpClient()->getLastRequest(); 0485 } 0486 0487 /** 0488 * Get the last HTTP response 0489 * 0490 * @return Zend_Http_Response 0491 */ 0492 public function getLastHttpResponse() 0493 { 0494 return $this->ec2->getHttpClient()->getLastResponse(); 0495 } 0496 }