diff -r 877f952ae2bd -r 6b6c2214f778 web/lib/Zend/Cloud/Infrastructure/Adapter/Ec2.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/lib/Zend/Cloud/Infrastructure/Adapter/Ec2.php Thu Mar 21 19:52:38 2013 +0100 @@ -0,0 +1,496 @@ + Zend_Cloud_Infrastructure_Instance::STATUS_RUNNING, + 'terminated' => Zend_Cloud_Infrastructure_Instance::STATUS_TERMINATED, + 'pending' => Zend_Cloud_Infrastructure_Instance::STATUS_PENDING, + 'shutting-down' => Zend_Cloud_Infrastructure_Instance::STATUS_SHUTTING_DOWN, + 'stopping' => Zend_Cloud_Infrastructure_Instance::STATUS_PENDING, + 'stopped' => Zend_Cloud_Infrastructure_Instance::STATUS_STOPPED, + 'rebooting' => Zend_Cloud_Infrastructure_Instance::STATUS_REBOOTING, + ); + + /** + * Map monitor metrics between Infrastructure and EC2 + * + * @var array + */ + protected $mapMetrics= array ( + Zend_Cloud_Infrastructure_Instance::MONITOR_CPU => 'CPUUtilization', + Zend_Cloud_Infrastructure_Instance::MONITOR_DISK_READ => 'DiskReadBytes', + Zend_Cloud_Infrastructure_Instance::MONITOR_DISK_WRITE => 'DiskWriteBytes', + Zend_Cloud_Infrastructure_Instance::MONITOR_NETWORK_IN => 'NetworkIn', + Zend_Cloud_Infrastructure_Instance::MONITOR_NETWORK_OUT => 'NetworkOut', + ); + + /** + * Constructor + * + * @param array|Zend_Config $options + * @return void + */ + public function __construct($options = array()) + { + if (is_object($options)) { + if (method_exists($options, 'toArray')) { + $options= $options->toArray(); + } elseif ($options instanceof Traversable) { + $options = iterator_to_array($options); + } + } + + if (empty($options) || !is_array($options)) { + require_once 'Zend/Cloud/Infrastructure/Exception.php'; + throw new Zend_Cloud_Infrastructure_Exception('Invalid options provided'); + } + + if (!isset($options[self::AWS_ACCESS_KEY]) + || !isset($options[self::AWS_SECRET_KEY]) + ) { + require_once 'Zend/Cloud/Infrastructure/Exception.php'; + throw new Zend_Cloud_Infrastructure_Exception('AWS keys not specified!'); + } + + $this->accessKey = $options[self::AWS_ACCESS_KEY]; + $this->accessSecret = $options[self::AWS_SECRET_KEY]; + $this->region = ''; + + if (isset($options[self::AWS_REGION])) { + $this->region= $options[self::AWS_REGION]; + } + + try { + $this->ec2 = new Zend_Service_Amazon_Ec2_Instance($options[self::AWS_ACCESS_KEY], $options[self::AWS_SECRET_KEY], $this->region); + } catch (Exception $e) { + require_once 'Zend/Cloud/Infrastructure/Exception.php'; + throw new Zend_Cloud_Infrastructure_Exception('Error on create: ' . $e->getMessage(), $e->getCode(), $e); + } + + if (isset($options[self::HTTP_ADAPTER])) { + $this->ec2->getHttpClient()->setAdapter($options[self::HTTP_ADAPTER]); + } + } + + /** + * Convert the attributes of EC2 into attributes of Infrastructure + * + * @param array $attr + * @return array|boolean + */ + private function convertAttributes($attr) + { + $result = array(); + if (!empty($attr) && is_array($attr)) { + $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_ID] = $attr['instanceId']; + $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STATUS] = $this->mapStatus[$attr['instanceState']['name']]; + $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_IMAGEID] = $attr['imageId']; + $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_ZONE] = $attr['availabilityZone']; + $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_LAUNCHTIME] = $attr['launchTime']; + + switch ($attr['instanceType']) { + case Zend_Service_Amazon_Ec2_Instance::MICRO: + $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_CPU] = '1 virtual core'; + $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_RAM] = '613MB'; + $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STORAGE] = '0GB'; + break; + case Zend_Service_Amazon_Ec2_Instance::SMALL: + $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_CPU] = '1 virtual core'; + $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_RAM] = '1.7GB'; + $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STORAGE] = '160GB'; + break; + case Zend_Service_Amazon_Ec2_Instance::LARGE: + $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_CPU] = '2 virtual core'; + $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_RAM] = '7.5GB'; + $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STORAGE] = '850GB'; + break; + case Zend_Service_Amazon_Ec2_Instance::XLARGE: + $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_CPU] = '4 virtual core'; + $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_RAM] = '15GB'; + $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STORAGE] = '1690GB'; + break; + case Zend_Service_Amazon_Ec2_Instance::HCPU_MEDIUM: + $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_CPU] = '2 virtual core'; + $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_RAM] = '1.7GB'; + $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STORAGE] = '350GB'; + break; + case Zend_Service_Amazon_Ec2_Instance::HCPU_XLARGE: + $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_CPU] = '8 virtual core'; + $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_RAM] = '7GB'; + $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STORAGE] = '1690GB'; + break; + } + } + return $result; + } + + /** + * Return a list of the available instancies + * + * @return Zend_Cloud_Infrastructure_InstanceList + */ + public function listInstances() + { + $this->adapterResult = $this->ec2->describe(); + + $result = array(); + foreach ($this->adapterResult['instances'] as $instance) { + $result[]= $this->convertAttributes($instance); + } + return new Zend_Cloud_Infrastructure_InstanceList($this, $result); + } + + /** + * Return the status of an instance + * + * @param string + * @return string|boolean + */ + public function statusInstance($id) + { + $this->adapterResult = $this->ec2->describe($id); + if (empty($this->adapterResult['instances'])) { + return false; + } + $result = $this->adapterResult['instances'][0]; + return $this->mapStatus[$result['instanceState']['name']]; + } + + /** + * Return the public DNS name of the instance + * + * @param string $id + * @return string|boolean + */ + public function publicDnsInstance($id) + { + $this->adapterResult = $this->ec2->describe($id); + if (empty($this->adapterResult['instances'])) { + return false; + } + $result = $this->adapterResult['instances'][0]; + return $result['dnsName']; + } + + /** + * Reboot an instance + * + * @param string $id + * @return boolean + */ + public function rebootInstance($id) + { + $this->adapterResult= $this->ec2->reboot($id); + return $this->adapterResult; + } + + /** + * Create a new instance + * + * @param string $name + * @param array $options + * @return Instance|boolean + */ + public function createInstance($name, $options) + { + // @todo instance's name management? + $this->adapterResult = $this->ec2->run($options); + if (empty($this->adapterResult['instances'])) { + return false; + } + $this->error= false; + return new Zend_Cloud_Infrastructure_Instance($this, $this->convertAttributes($this->adapterResult['instances'][0])); + } + + /** + * Stop an instance + * + * @param string $id + * @return boolean + */ + public function stopInstance($id) + { + require_once 'Zend/Cloud/Infrastructure/Exception.php'; + throw new Zend_Cloud_Infrastructure_Exception('The stopInstance method is not implemented in the adapter'); + } + + /** + * Start an instance + * + * @param string $id + * @return boolean + */ + public function startInstance($id) + { + require_once 'Zend/Cloud/Infrastructure/Exception.php'; + throw new Zend_Cloud_Infrastructure_Exception('The startInstance method is not implemented in the adapter'); + } + + /** + * Destroy an instance + * + * @param string $id + * @return boolean + */ + public function destroyInstance($id) + { + $this->adapterResult = $this->ec2->terminate($id); + return (!empty($this->adapterResult)); + } + + /** + * Return a list of all the available instance images + * + * @return ImageList + */ + public function imagesInstance() + { + if (!isset($this->ec2Image)) { + $this->ec2Image = new Zend_Service_Amazon_Ec2_Image($this->accessKey, $this->accessSecret, $this->region); + } + + $this->adapterResult = $this->ec2Image->describe(); + + $images = array(); + + foreach ($this->adapterResult as $result) { + switch (strtolower($result['platform'])) { + case 'windows' : + $platform = Zend_Cloud_Infrastructure_Image::IMAGE_WINDOWS; + break; + default: + $platform = Zend_Cloud_Infrastructure_Image::IMAGE_LINUX; + break; + } + + $images[]= array ( + Zend_Cloud_Infrastructure_Image::IMAGE_ID => $result['imageId'], + Zend_Cloud_Infrastructure_Image::IMAGE_NAME => '', + Zend_Cloud_Infrastructure_Image::IMAGE_DESCRIPTION => $result['imageLocation'], + Zend_Cloud_Infrastructure_Image::IMAGE_OWNERID => $result['imageOwnerId'], + Zend_Cloud_Infrastructure_Image::IMAGE_ARCHITECTURE => $result['architecture'], + Zend_Cloud_Infrastructure_Image::IMAGE_PLATFORM => $platform, + ); + } + return new Zend_Cloud_Infrastructure_ImageList($images,$this->ec2Image); + } + + /** + * Return all the available zones + * + * @return array + */ + public function zonesInstance() + { + if (!isset($this->ec2Zone)) { + $this->ec2Zone = new Zend_Service_Amazon_Ec2_AvailabilityZones($this->accessKey,$this->accessSecret,$this->region); + } + $this->adapterResult = $this->ec2Zone->describe(); + + $zones = array(); + foreach ($this->adapterResult as $zone) { + if (strtolower($zone['zoneState']) === 'available') { + $zones[] = array ( + Zend_Cloud_Infrastructure_Instance::INSTANCE_ZONE => $zone['zoneName'], + ); + } + } + return $zones; + } + + /** + * Return the system information about the $metric of an instance + * + * @param string $id + * @param string $metric + * @param null|array $options + * @return array + */ + public function monitorInstance($id, $metric, $options = null) + { + if (empty($id) || empty($metric)) { + return false; + } + + if (!in_array($metric,$this->validMetrics)) { + require_once 'Zend/Cloud/Infrastructure/Exception.php'; + throw new Zend_Cloud_Infrastructure_Exception(sprintf( + 'The metric "%s" is not valid', + $metric + )); + } + + if (!empty($options) && !is_array($options)) { + require_once 'Zend/Cloud/Infrastructure/Exception.php'; + throw new Zend_Cloud_Infrastructure_Exception('The options must be an array'); + } + + if (!empty($options) + && (empty($options[Zend_Cloud_Infrastructure_Instance::MONITOR_START_TIME]) + || empty($options[Zend_Cloud_Infrastructure_Instance::MONITOR_END_TIME])) + ) { + require_once 'Zend/Cloud/Infrastructure/Exception.php'; + throw new Zend_Cloud_Infrastructure_Exception(sprintf( + 'The options array must contain: "%s" and "%s"', + $options[Zend_Cloud_Infrastructure_Instance::MONITOR_START_TIME], + $options[Zend_Cloud_Infrastructure_Instance::MONITOR_END_TIME] + )); + } + + if (!isset($this->ec2Monitor)) { + $this->ec2Monitor = new Zend_Service_Amazon_Ec2_CloudWatch($this->accessKey, $this->accessSecret, $this->region); + } + + $param = array( + 'MeasureName' => $this->mapMetrics[$metric], + 'Statistics' => array('Average'), + 'Dimensions' => array('InstanceId' => $id), + ); + + if (!empty($options)) { + $param['StartTime'] = $options[Zend_Cloud_Infrastructure_Instance::MONITOR_START_TIME]; + $param['EndTime'] = $options[Zend_Cloud_Infrastructure_Instance::MONITOR_END_TIME]; + } + + $this->adapterResult = $this->ec2Monitor->getMetricStatistics($param); + + $monitor = array(); + $num = 0; + $average = 0; + + if (!empty($this->adapterResult['datapoints'])) { + foreach ($this->adapterResult['datapoints'] as $result) { + $monitor['series'][] = array ( + 'timestamp' => $result['Timestamp'], + 'value' => $result['Average'], + ); + $average += $result['Average']; + $num++; + } + } + + if ($num > 0) { + $monitor['average'] = $average / $num; + } + + return $monitor; + } + + /** + * Get the adapter + * + * @return Zend_Service_Amazon_Ec2_Instance + */ + public function getAdapter() + { + return $this->ec2; + } + + /** + * Get last HTTP request + * + * @return string + */ + public function getLastHttpRequest() + { + return $this->ec2->getHttpClient()->getLastRequest(); + } + + /** + * Get the last HTTP response + * + * @return Zend_Http_Response + */ + public function getLastHttpResponse() + { + return $this->ec2->getHttpClient()->getLastResponse(); + } +}