web/lib/Zend/Cloud/Infrastructure/Adapter/Ec2.php
changeset 808 6b6c2214f778
child 1230 68c69c656a2c
--- /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 @@
+<?php
+/**
+ * @category   Zend
+ * @package    Zend_Cloud_Infrastructure
+ * @subpackage Adapter
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Service/Amazon/Ec2/Instance.php';
+require_once 'Zend/Service/Amazon/Ec2/Image.php';
+require_once 'Zend/Service/Amazon/Ec2/Availabilityzones.php';
+require_once 'Zend/Service/Amazon/Ec2/CloudWatch.php';
+require_once 'Zend/Cloud/Infrastructure/Instance.php';
+require_once 'Zend/Cloud/Infrastructure/InstanceList.php';
+require_once 'Zend/Cloud/Infrastructure/Image.php';
+require_once 'Zend/Cloud/Infrastructure/ImageList.php';
+require_once 'Zend/Cloud/Infrastructure/Adapter/AbstractAdapter.php';
+
+/**
+ * Amazon EC2 adapter for infrastructure service
+ *
+ * @package    Zend_Cloud_Infrastructure
+ * @subpackage Adapter
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Cloud_Infrastructure_Adapter_Ec2 extends Zend_Cloud_Infrastructure_Adapter_AbstractAdapter
+{
+    /**
+     * AWS constants
+     */
+    const AWS_ACCESS_KEY     = 'aws_accesskey';
+    const AWS_SECRET_KEY     = 'aws_secretkey';
+    const AWS_REGION         = 'aws_region';
+    const AWS_SECURITY_GROUP = 'securityGroup';
+
+    /**
+     * Ec2 Instance 
+     * 
+     * @var Ec2Instance
+     */
+    protected $ec2;
+
+    /**
+     * Ec2 Image
+     * 
+     * @var Ec2Image
+     */
+    protected $ec2Image;
+
+    /**
+     * Ec2 Zone
+     * 
+     * @var Ec2Zone
+     */
+    protected $ec2Zone;
+
+    /**
+     * Ec2 Monitor 
+     * 
+     * @var Ec2Monitor
+     */
+    protected $ec2Monitor;
+
+    /**
+     * AWS Access Key
+     * 
+     * @var string 
+     */
+    protected $accessKey;
+
+    /**
+     * AWS Access Secret
+     * 
+     * @var string 
+     */
+    protected $accessSecret;
+
+    /**
+     * Region zone 
+     * 
+     * @var string 
+     */
+    protected $region;
+
+    /**
+     * Map array between EC2 and Infrastructure status
+     * 
+     * @var array 
+     */
+    protected $mapStatus = array (
+        'running'       => 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();
+    }
+}