| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483 |
- <?php
- /**
- * @category Zend
- * @package Zend_Cloud_Infrastructure
- * @subpackage Adapter
- * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- */
- require_once 'Zend/Service/Rackspace/Servers.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';
- /**
- * Rackspace servers adapter for infrastructure service
- *
- * @package Zend_Cloud_Infrastructure
- * @subpackage Adapter
- * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- */
- class Zend_Cloud_Infrastructure_Adapter_Rackspace extends Zend_Cloud_Infrastructure_Adapter_AbstractAdapter
- {
- /**
- * RACKSPACE constants
- */
- const RACKSPACE_USER = 'rackspace_user';
- const RACKSPACE_KEY = 'rackspace_key';
- const RACKSPACE_REGION = 'rackspace_region';
- const RACKSPACE_ZONE_USA = 'USA';
- const RACKSPACE_ZONE_UK = 'UK';
- const MONITOR_CPU_SAMPLES = 3;
- /**
- * Rackspace Servers Instance
- *
- * @var Zend_Service_Rackspace_Servers
- */
- protected $rackspace;
- /**
- * Rackspace access user
- *
- * @var string
- */
- protected $accessUser;
- /**
- * Rackspace access key
- *
- * @var string
- */
- protected $accessKey;
- /**
- * Rackspace Region
- *
- * @var string
- */
- protected $region;
- /**
- * Flavors
- *
- * @var array
- */
- protected $flavors;
- /**
- * Map array between Rackspace and Infrastructure status
- *
- * @var array
- */
- protected $mapStatus = array (
- 'ACTIVE' => Zend_Cloud_Infrastructure_Instance::STATUS_RUNNING,
- 'SUSPENDED' => Zend_Cloud_Infrastructure_Instance::STATUS_STOPPED,
- 'BUILD' => Zend_Cloud_Infrastructure_Instance::STATUS_REBUILD,
- 'REBUILD' => Zend_Cloud_Infrastructure_Instance::STATUS_REBUILD,
- 'QUEUE_RESIZE' => Zend_Cloud_Infrastructure_Instance::STATUS_PENDING,
- 'PREP_RESIZE' => Zend_Cloud_Infrastructure_Instance::STATUS_PENDING,
- 'RESIZE' => Zend_Cloud_Infrastructure_Instance::STATUS_REBUILD,
- 'VERIFY_RESIZE' => Zend_Cloud_Infrastructure_Instance::STATUS_REBUILD,
- 'PASSWORD' => Zend_Cloud_Infrastructure_Instance::STATUS_PENDING,
- 'RESCUE' => Zend_Cloud_Infrastructure_Instance::STATUS_PENDING,
- 'REBOOT' => Zend_Cloud_Infrastructure_Instance::STATUS_REBOOTING,
- 'HARD_REBOOT' => Zend_Cloud_Infrastructure_Instance::STATUS_REBOOTING,
- 'SHARE_IP' => Zend_Cloud_Infrastructure_Instance::STATUS_PENDING,
- 'SHARE_IP_NO_CONFIG' => Zend_Cloud_Infrastructure_Instance::STATUS_PENDING,
- 'DELETE_IP' => Zend_Cloud_Infrastructure_Instance::STATUS_PENDING,
- 'UNKNOWN' => Zend_Cloud_Infrastructure_Instance::STATUS_PENDING
- );
- /**
- * 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::RACKSPACE_USER])) {
- require_once 'Zend/Cloud/Infrastructure/Exception.php';
- throw new Zend_Cloud_Infrastructure_Exception('Rackspace access user not specified!');
- }
- if (!isset($options[self::RACKSPACE_KEY])) {
- require_once 'Zend/Cloud/Infrastructure/Exception.php';
- throw new Zend_Cloud_Infrastructure_Exception('Rackspace access key not specified!');
- }
-
- $this->accessUser = $options[self::RACKSPACE_USER];
- $this->accessKey = $options[self::RACKSPACE_KEY];
-
- if (isset($options[self::RACKSPACE_REGION])) {
- switch ($options[self::RACKSPACE_REGION]) {
- case self::RACKSPACE_ZONE_UK:
- $this->region= Zend_Service_Rackspace_Servers::UK_AUTH_URL;
- break;
- case self::RACKSPACE_ZONE_USA:
- $this->region = Zend_Service_Rackspace_Servers::US_AUTH_URL;
- break;
- default:
- require_once 'Zend/Cloud/Infrastructure/Exception.php';
- throw new Zend_Cloud_Infrastructure_Exception('The region is not valid');
- }
- } else {
- $this->region = Zend_Service_Rackspace_Servers::US_AUTH_URL;
- }
- try {
- $this->rackspace = new Zend_Service_Rackspace_Servers($this->accessUser,$this->accessKey, $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->rackspace->getHttpClient()->setAdapter($options[self::HTTP_ADAPTER]);
- }
-
- }
- /**
- * Convert the attributes of Rackspace server into attributes of Infrastructure
- *
- * @param array $attr
- * @return array|boolean
- */
- protected function convertAttributes($attr)
- {
- $result = array();
- if (!empty($attr) && is_array($attr)) {
- $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_ID] = $attr['id'];
- $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_NAME] = $attr['name'];
- $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STATUS] = $this->mapStatus[$attr['status']];
- $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_IMAGEID] = $attr['imageId'];
- if ($this->region==Zend_Service_Rackspace_Servers::US_AUTH_URL) {
- $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_ZONE] = self::RACKSPACE_ZONE_USA;
- } else {
- $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_ZONE] = self::RACKSPACE_ZONE_UK;
- }
- $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_RAM] = $this->flavors[$attr['flavorId']]['ram'];
- $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STORAGE] = $this->flavors[$attr['flavorId']]['disk'];
- }
- return $result;
- }
- /**
- * Return a list of the available instancies
- *
- * @return InstanceList|boolean
- */
- public function listInstances()
- {
- $this->adapterResult = $this->rackspace->listServers(true);
- if ($this->adapterResult===false) {
- return false;
- }
- $array= $this->adapterResult->toArray();
- $result = array();
- foreach ($array 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->rackspace->getServer($id);
- if ($this->adapterResult===false) {
- return false;
- }
- $array= $this->adapterResult->toArray();
- return $this->mapStatus[$array['status']];
- }
- /**
- * Return the public DNS name/Ip address of the instance
- *
- * @param string $id
- * @return string|boolean
- */
- public function publicDnsInstance($id)
- {
- $this->adapterResult = $this->rackspace->getServerPublicIp($id);
- if (empty($this->adapterResult)) {
- return false;
- }
- return $this->adapterResult[0];
- }
- /**
- * Reboot an instance
- *
- * @param string $id
- * @return boolean
- */
- public function rebootInstance($id)
- {
- return $this->rackspace->rebootServer($id,true);
- }
- /**
- * Create a new instance
- *
- * @param string $name
- * @param array $options
- * @return Instance|boolean
- */
- public function createInstance($name, $options)
- {
- if (empty($name)) {
- require_once 'Zend/Cloud/Infrastructure/Exception.php';
- throw new Zend_Cloud_Infrastructure_Exception('You must specify the name of the instance');
- }
- 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');
- }
- // @todo create an generic abstract definition for an instance?
- $metadata= array();
- if (isset($options['metadata'])) {
- $metadata= $options['metadata'];
- unset($options['metadata']);
- }
- $files= array();
- if (isset($options['files'])) {
- $files= $options['files'];
- unset($options['files']);
- }
- $options['name']= $name;
- $this->adapterResult = $this->rackspace->createServer($options,$metadata,$files);
- if ($this->adapterResult===false) {
- return false;
- }
- return new Zend_Cloud_Infrastructure_Instance($this, $this->convertAttributes($this->adapterResult->toArray()));
- }
- /**
- * 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->rackspace->deleteServer($id);
- return $this->adapterResult;
- }
- /**
- * Return a list of all the available instance images
- *
- * @return ImageList|boolean
- */
- public function imagesInstance()
- {
- $this->adapterResult = $this->rackspace->listImages(true);
- if ($this->adapterResult===false) {
- return false;
- }
-
- $images= $this->adapterResult->toArray();
- $result= array();
-
- foreach ($images as $image) {
- if (strtolower($image['status'])==='active') {
- if (strpos($image['name'],'Windows')!==false) {
- $platform = Zend_Cloud_Infrastructure_Image::IMAGE_WINDOWS;
- } else {
- $platform = Zend_Cloud_Infrastructure_Image::IMAGE_LINUX;
- }
- if (strpos($image['name'],'x64')!==false) {
- $arch = Zend_Cloud_Infrastructure_Image::ARCH_64BIT;
- } else {
- $arch = Zend_Cloud_Infrastructure_Image::ARCH_32BIT;
- }
- $result[]= array (
- Zend_Cloud_Infrastructure_Image::IMAGE_ID => $image['id'],
- Zend_Cloud_Infrastructure_Image::IMAGE_NAME => $image['name'],
- Zend_Cloud_Infrastructure_Image::IMAGE_DESCRIPTION => $image['name'],
- Zend_Cloud_Infrastructure_Image::IMAGE_ARCHITECTURE => $arch,
- Zend_Cloud_Infrastructure_Image::IMAGE_PLATFORM => $platform,
- );
- }
- }
- return new Zend_Cloud_Infrastructure_ImageList($result,$this->adapterResult);
- }
- /**
- * Return all the available zones
- *
- * @return array
- */
- public function zonesInstance()
- {
- return array(self::RACKSPACE_ZONE_USA,self::RACKSPACE_ZONE_UK);
- }
- /**
- * Return the system information about the $metric of an instance
- * NOTE: it works only for Linux servers
- *
- * @param string $id
- * @param string $metric
- * @param null|array $options
- * @return array|boolean
- */
- public function monitorInstance($id, $metric, $options = null)
- {
- if (!function_exists("ssh2_connect")) {
- require_once 'Zend/Cloud/Infrastructure/Exception.php';
- throw new Zend_Cloud_Infrastructure_Exception('Monitor requires the PHP "SSH" extension (ext/ssh2)');
- }
- if (empty($id)) {
- require_once 'Zend/Cloud/Infrastructure/Exception.php';
- throw new Zend_Cloud_Infrastructure_Exception('You must specify the id of the instance to monitor');
- }
- if (empty($metric)) {
- require_once 'Zend/Cloud/Infrastructure/Exception.php';
- throw new Zend_Cloud_Infrastructure_Exception('You must specify the metric to monitor');
- }
- 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');
- }
-
- switch ($metric) {
- case Zend_Cloud_Infrastructure_Instance::MONITOR_CPU:
- $cmd= 'top -b -n '.self::MONITOR_CPU_SAMPLES.' | grep \'Cpu\'';
- break;
- case Zend_Cloud_Infrastructure_Instance::MONITOR_RAM:
- $cmd= 'top -b -n 1 | grep \'Mem\'';
- break;
- case Zend_Cloud_Infrastructure_Instance::MONITOR_DISK:
- $cmd= 'df --total | grep total';
- break;
- }
- if (empty($cmd)) {
- require_once 'Zend/Cloud/Infrastructure/Exception.php';
- throw new Zend_Cloud_Infrastructure_Exception('The metric specified is not supported by the adapter');
- }
-
- $params= array(
- Zend_Cloud_Infrastructure_Instance::SSH_USERNAME => $options['username'],
- Zend_Cloud_Infrastructure_Instance::SSH_PASSWORD => $options['password']
- );
- $exec_time= time();
- $result= $this->deployInstance($id,$params,$cmd);
-
- if (empty($result)) {
- return false;
- }
- $monitor = array();
- $num = 0;
- $average = 0;
- $outputs= explode("\n",$result);
- foreach ($outputs as $output) {
- if (!empty($output)) {
- switch ($metric) {
- case Zend_Cloud_Infrastructure_Instance::MONITOR_CPU:
- if (preg_match('/(\d+\.\d)%us/', $output,$match)) {
- $usage = (float) $match[1];
- }
- break;
- case Zend_Cloud_Infrastructure_Instance::MONITOR_RAM:
- if (preg_match('/(\d+)k total/', $output,$match)) {
- $total = (integer) $match[1];
- }
- if (preg_match('/(\d+)k used/', $output,$match)) {
- $used = (integer) $match[1];
- }
- if ($total>0) {
- $usage= (float) $used/$total;
- }
- break;
- case Zend_Cloud_Infrastructure_Instance::MONITOR_DISK:
- if (preg_match('/(\d+)%/', $output,$match)) {
- $usage = (float) $match[1];
- }
- break;
- }
-
- $monitor['series'][] = array (
- 'timestamp' => $exec_time,
- 'value' => number_format($usage,2).'%'
- );
-
- $average += $usage;
- $exec_time+= 60; // seconds
- $num++;
- }
- }
-
- if ($num>0) {
- $monitor['average'] = number_format($average/$num,2).'%';
- }
- return $monitor;
- }
- /**
- * Get the adapter
- *
- * @return Zend_Service_Rackspace_Servers
- */
- public function getAdapter()
- {
- return $this->rackspace;
- }
- /**
- * Get last HTTP request
- *
- * @return string
- */
- public function getLastHttpRequest()
- {
- return $this->rackspace->getHttpClient()->getLastRequest();
- }
- /**
- * Get the last HTTP response
- *
- * @return Zend_Http_Response
- */
- public function getLastHttpResponse()
- {
- return $this->rackspace->getHttpClient()->getLastResponse();
- }
- }
|