Instance.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Service_Amazon
  17. * @subpackage Ec2
  18. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id$
  21. */
  22. require_once 'Zend/Service/Amazon/Ec2/Abstract.php';
  23. /**
  24. * An Amazon EC2 interface that allows yout to run, terminate, reboot and describe Amazon
  25. * Ec2 Instances.
  26. *
  27. * @category Zend
  28. * @package Zend_Service_Amazon
  29. * @subpackage Ec2
  30. * @copyright Copyright (c) 22005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  31. * @license http://framework.zend.com/license/new-bsd New BSD License
  32. */
  33. class Zend_Service_Amazon_Ec2_Instance extends Zend_Service_Amazon_Ec2_Abstract
  34. {
  35. /**
  36. * Constant for Small Instance TYpe
  37. */
  38. const SMALL = 'm1.small';
  39. /**
  40. * Constant for Large Instance TYpe
  41. */
  42. const LARGE = 'm1.large';
  43. /**
  44. * Constant for X-Large Instance TYpe
  45. */
  46. const XLARGE = 'm1.xlarge';
  47. /**
  48. * Constant for High CPU Medium Instance TYpe
  49. */
  50. const HCPU_MEDIUM = 'c1.medium';
  51. /**
  52. * Constant for High CPU X-Large Instance TYpe
  53. */
  54. const HCPU_XLARGE = 'c1.xlarge';
  55. /**
  56. * Launches a specified number of Instances.
  57. *
  58. * If Amazon EC2 cannot launch the minimum number AMIs you request, no
  59. * instances launch. If there is insufficient capacity to launch the
  60. * maximum number of AMIs you request, Amazon EC2 launches as many
  61. * as possible to satisfy the requested maximum values.
  62. *
  63. * Every instance is launched in a security group. If you do not specify
  64. * a security group at launch, the instances start in your default security group.
  65. * For more information on creating security groups, see CreateSecurityGroup.
  66. *
  67. * An optional instance type can be specified. For information
  68. * about instance types, see Instance Types.
  69. *
  70. * You can provide an optional key pair ID for each image in the launch request
  71. * (for more information, see CreateKeyPair). All instances that are created
  72. * from images that use this key pair will have access to the associated public
  73. * key at boot. You can use this key to provide secure access to an instance of an
  74. * image on a per-instance basis. Amazon EC2 public images use this feature to
  75. * provide secure access without passwords.
  76. *
  77. * Launching public images without a key pair ID will leave them inaccessible.
  78. *
  79. * @param array $options An array that contins the options to start an instance.
  80. * Required Values:
  81. * imageId string ID of the AMI with which to launch instances.
  82. * Optional Values:
  83. * minCount integer Minimum number of instances to launch.
  84. * maxCount integer Maximum number of instances to launch.
  85. * keyName string Name of the key pair with which to launch instances.
  86. * securityGruop string|array Names of the security groups with which to associate the instances.
  87. * userData string The user data available to the launched instances. This should not be Base64 encoded.
  88. * instanceType constant Specifies the instance type.
  89. * placement string Specifies the availability zone in which to launch the instance(s). By default, Amazon EC2 selects an availability zone for you.
  90. * kernelId string The ID of the kernel with which to launch the instance.
  91. * ramdiskId string The ID of the RAM disk with which to launch the instance.
  92. * blockDeviceVirtualName string Specifies the virtual name to map to the corresponding device name. For example: instancestore0
  93. * blockDeviceName string Specifies the device to which you are mapping a virtual name. For example: sdb
  94. * monitor boolean Turn on CloudWatch Monitoring for an instance.
  95. * @return array
  96. */
  97. public function run(array $options)
  98. {
  99. $_defaultOptions = array(
  100. 'minCount' => 1,
  101. 'maxCount' => 1,
  102. 'instanceType' => Zend_Service_Amazon_Ec2_Instance::SMALL
  103. );
  104. // set / override the defualt optoins if they are not passed into the array;
  105. $options = array_merge($_defaultOptions, $options);
  106. if(!isset($options['imageId'])) {
  107. require_once 'Zend/Service/Amazon/Ec2/Exception.php';
  108. throw new Zend_Service_Amazon_Ec2_Exception('No Image Id Provided');
  109. }
  110. $params = array();
  111. $params['Action'] = 'RunInstances';
  112. $params['ImageId'] = $options['imageId'];
  113. $params['MinCount'] = $options['minCount'];
  114. $params['MaxCount'] = $options['maxCount'];
  115. if(isset($options['keyName'])) {
  116. $params['KeyName'] = $options['keyName'];
  117. }
  118. if(is_array($options['securityGroup']) && !empty($options['securityGroup'])) {
  119. foreach($options['securityGroup'] as $k=>$name) {
  120. $params['SecurityGroup.' . ($k+1)] = $name;
  121. }
  122. } elseif(isset($options['securityGroup'])) {
  123. $params['SecurityGroup.1'] = $options['securityGroup'];
  124. }
  125. if(isset($options['userData'])) {
  126. $params['UserData'] = base64_encode($options['userData']);
  127. }
  128. if(isset($options['instanceType'])) {
  129. $params['InstanceType'] = $options['instanceType'];
  130. }
  131. if(isset($options['placement'])) {
  132. $params['Placement.AvailabilityZone'] = $options['placement'];
  133. }
  134. if(isset($options['kernelId'])) {
  135. $params['KernelId'] = $options['kernelId'];
  136. }
  137. if(isset($options['ramdiskId'])) {
  138. $params['RamdiskId'] = $options['ramdiskId'];
  139. }
  140. if(isset($options['blockDeviceVirtualName']) && isset($options['blockDeviceName'])) {
  141. $params['BlockDeviceMapping.n.VirtualName'] = $options['blockDeviceVirtualName'];
  142. $params['BlockDeviceMapping.n.DeviceName'] = $options['blockDeviceName'];
  143. }
  144. if(isset($options['monitor']) && $options['monitor'] === true) {
  145. $params['Monitoring.Enabled'] = true;
  146. }
  147. $response = $this->sendRequest($params);
  148. $xpath = $response->getXPath();
  149. $return = array();
  150. $return['reservationId'] = $xpath->evaluate('string(//ec2:reservationId/text())');
  151. $return['ownerId'] = $xpath->evaluate('string(//ec2:ownerId/text())');
  152. $gs = $xpath->query('//ec2:groupSet/ec2:item');
  153. foreach($gs as $gs_node) {
  154. $return['groupSet'][] = $xpath->evaluate('string(ec2:groupId/text())', $gs_node);
  155. unset($gs_node);
  156. }
  157. unset($gs);
  158. $is = $xpath->query('//ec2:instancesSet/ec2:item');
  159. foreach($is as $is_node) {
  160. $item = array();
  161. $item['instanceId'] = $xpath->evaluate('string(ec2:instanceId/text())', $is_node);
  162. $item['imageId'] = $xpath->evaluate('string(ec2:imageId/text())', $is_node);
  163. $item['instanceState']['code'] = $xpath->evaluate('string(ec2:instanceState/ec2:code/text())', $is_node);
  164. $item['instanceState']['name'] = $xpath->evaluate('string(ec2:instanceState/ec2:name/text())', $is_node);
  165. $item['privateDnsName'] = $xpath->evaluate('string(ec2:privateDnsName/text())', $is_node);
  166. $item['dnsName'] = $xpath->evaluate('string(ec2:dnsName/text())', $is_node);
  167. $item['keyName'] = $xpath->evaluate('string(ec2:keyName/text())', $is_node);
  168. $item['instanceType'] = $xpath->evaluate('string(ec2:instanceType/text())', $is_node);
  169. $item['amiLaunchIndex'] = $xpath->evaluate('string(ec2:amiLaunchIndex/text())', $is_node);
  170. $item['launchTime'] = $xpath->evaluate('string(ec2:launchTime/text())', $is_node);
  171. $item['availabilityZone'] = $xpath->evaluate('string(ec2:placement/ec2:availabilityZone/text())', $is_node);
  172. $return['instances'][] = $item;
  173. unset($item);
  174. unset($is_node);
  175. }
  176. unset($is);
  177. return $return;
  178. }
  179. /**
  180. * Returns information about instances that you own.
  181. *
  182. * If you specify one or more instance IDs, Amazon EC2 returns information
  183. * for those instances. If you do not specify instance IDs, Amazon EC2
  184. * returns information for all relevant instances. If you specify an invalid
  185. * instance ID, a fault is returned. If you specify an instance that you do
  186. * not own, it will not be included in the returned results.
  187. *
  188. * Recently terminated instances might appear in the returned results.
  189. * This interval is usually less than one hour.
  190. *
  191. * @param string|array $instaceId Set of instances IDs of which to get the status.
  192. * @param boolean Ture to ignore Terminated Instances.
  193. * @return array
  194. */
  195. public function describe($instanceId = null, $ignoreTerminated = false)
  196. {
  197. $params = array();
  198. $params['Action'] = 'DescribeInstances';
  199. if(is_array($instanceId) && !empty($instanceId)) {
  200. foreach($instanceId as $k=>$name) {
  201. $params['InstanceId.' . ($k+1)] = $name;
  202. }
  203. } elseif($instanceId) {
  204. $params['InstanceId.1'] = $instanceId;
  205. }
  206. $response = $this->sendRequest($params);
  207. $xpath = $response->getXPath();
  208. $nodes = $xpath->query('//ec2:reservationSet/ec2:item');
  209. $return = array();
  210. $return['instances'] = array();
  211. foreach($nodes as $node) {
  212. if($xpath->evaluate('string(ec2:instancesSet/ec2:item/ec2:instanceState/ec2:code/text())', $node) == 48 && $ignoreTerminated) continue;
  213. $item = array();
  214. $item['reservationId'] = $xpath->evaluate('string(ec2:reservationId/text())', $node);
  215. $item['ownerId'] = $xpath->evaluate('string(ec2:ownerId/text())', $node);
  216. $gs = $xpath->query('ec2:groupSet/ec2:item', $node);
  217. foreach($gs as $gs_node) {
  218. $item['groupSet'][] = $xpath->evaluate('string(ec2:groupId/text())', $gs_node);
  219. unset($gs_node);
  220. }
  221. unset($gs);
  222. $is = $xpath->query('ec2:instancesSet/ec2:item', $node);
  223. foreach($is as $is_node) {
  224. $item['instanceId'] = $xpath->evaluate('string(ec2:instanceId/text())', $is_node);
  225. $item['imageId'] = $xpath->evaluate('string(ec2:imageId/text())', $is_node);
  226. $item['instanceState']['code'] = $xpath->evaluate('string(ec2:instanceState/ec2:code/text())', $is_node);
  227. $item['instanceState']['name'] = $xpath->evaluate('string(ec2:instanceState/ec2:name/text())', $is_node);
  228. $item['privateDnsName'] = $xpath->evaluate('string(ec2:privateDnsName/text())', $is_node);
  229. $item['dnsName'] = $xpath->evaluate('string(ec2:dnsName/text())', $is_node);
  230. $item['keyName'] = $xpath->evaluate('string(ec2:keyName/text())', $is_node);
  231. $item['productCode'] = $xpath->evaluate('string(ec2:productCodesSet/ec2:item/ec2:productCode/text())', $is_node);
  232. $item['instanceType'] = $xpath->evaluate('string(ec2:instanceType/text())', $is_node);
  233. $item['launchTime'] = $xpath->evaluate('string(ec2:launchTime/text())', $is_node);
  234. $item['availabilityZone'] = $xpath->evaluate('string(ec2:placement/ec2:availabilityZone/text())', $is_node);
  235. $item['kernelId'] = $xpath->evaluate('string(ec2:kernelId/text())', $is_node);
  236. $item['ramediskId'] = $xpath->evaluate('string(ec2:ramediskId/text())', $is_node);
  237. $item['amiLaunchIndex'] = $xpath->evaluate('string(ec2:amiLaunchIndex/text())', $is_node);
  238. $item['monitoringState'] = $xpath->evaluate('string(ec2:monitoring/ec2:state/text())', $is_node);
  239. unset($is_node);
  240. }
  241. $return['instances'][] = $item;
  242. unset($item);
  243. unset($is);
  244. }
  245. return $return;
  246. }
  247. /**
  248. * Returns information about instances that you own that were started from
  249. * a specific imageId
  250. *
  251. * Recently terminated instances might appear in the returned results.
  252. * This interval is usually less than one hour.
  253. *
  254. * @param string $imageId The imageId used to start the Instance.
  255. * @param boolean Ture to ignore Terminated Instances.
  256. * @return array
  257. */
  258. public function describeByImageId($imageId, $ignoreTerminated = false)
  259. {
  260. $arrInstances = $this->describe(null, $ignoreTerminated);
  261. $return = array();
  262. foreach($arrInstances['instances'] as $instance) {
  263. if($instance['imageId'] !== $imageId) continue;
  264. $return[] = $instance;
  265. }
  266. return $return;
  267. }
  268. /**
  269. * Shuts down one or more instances. This operation is idempotent; if you terminate
  270. * an instance more than once, each call will succeed.
  271. *
  272. * Terminated instances will remain visible after termination (approximately one hour).
  273. *
  274. * @param string|array $instanceId One or more instance IDs returned.
  275. * @return array
  276. */
  277. public function terminate($instanceId)
  278. {
  279. $params = array();
  280. $params['Action'] = 'TerminateInstances';
  281. if(is_array($instanceId) && !empty($instanceId)) {
  282. foreach($instanceId as $k=>$name) {
  283. $params['InstanceId.' . ($k+1)] = $name;
  284. }
  285. } elseif($instanceId) {
  286. $params['InstanceId.1'] = $instanceId;
  287. }
  288. $response = $this->sendRequest($params);
  289. $xpath = $response->getXPath();
  290. $nodes = $xpath->query('//ec2:instancesSet/ec2:item');
  291. $return = array();
  292. foreach($nodes as $node) {
  293. $item = array();
  294. $item['instanceId'] = $xpath->evaluate('string(ec2:instanceId/text())', $node);
  295. $item['shutdownState']['code'] = $xpath->evaluate('string(ec2:shutdownState/ec2:code/text())', $node);
  296. $item['shutdownState']['name'] = $xpath->evaluate('string(ec2:shutdownState/ec2:name/text())', $node);
  297. $item['previousState']['code'] = $xpath->evaluate('string(ec2:previousState/ec2:code/text())', $node);
  298. $item['previousState']['name'] = $xpath->evaluate('string(ec2:previousState/ec2:name/text())', $node);
  299. $return[] = $item;
  300. unset($item);
  301. }
  302. return $return;
  303. }
  304. /**
  305. * Requests a reboot of one or more instances.
  306. *
  307. * This operation is asynchronous; it only queues a request to reboot the specified instance(s). The operation
  308. * will succeed if the instances are valid and belong to the user. Requests to reboot terminated instances are ignored.
  309. *
  310. * @param string|array $instanceId One or more instance IDs.
  311. * @return boolean
  312. */
  313. public function reboot($instanceId)
  314. {
  315. $params = array();
  316. $params['Action'] = 'RebootInstances';
  317. if(is_array($instanceId) && !empty($instanceId)) {
  318. foreach($instanceId as $k=>$name) {
  319. $params['InstanceId.' . ($k+1)] = $name;
  320. }
  321. } elseif($instanceId) {
  322. $params['InstanceId.1'] = $instanceId;
  323. }
  324. $response = $this->sendRequest($params);
  325. $xpath = $response->getXPath();
  326. $return = $xpath->evaluate('string(//ec2:return/text())');
  327. return ($return === "true");
  328. }
  329. /**
  330. * Retrieves console output for the specified instance.
  331. *
  332. * Instance console output is buffered and posted shortly after instance boot, reboot, and termination.
  333. * Amazon EC2 preserves the most recent 64 KB output which will be available for at least one hour after the most recent post.
  334. *
  335. * @param string $instanceId An instance ID
  336. * @return array
  337. */
  338. public function consoleOutput($instanceId)
  339. {
  340. $params = array();
  341. $params['Action'] = 'GetConsoleOutput';
  342. $params['InstanceId'] = $instanceId;
  343. $response = $this->sendRequest($params);
  344. $xpath = $response->getXPath();
  345. $return = array();
  346. $return['instanceId'] = $xpath->evaluate('string(//ec2:instanceId/text())');
  347. $return['timestamp'] = $xpath->evaluate('string(//ec2:timestamp/text())');
  348. $return['output'] = base64_decode($xpath->evaluate('string(//ec2:output/text())'));
  349. return $return;
  350. }
  351. /**
  352. * Returns true if the specified product code is attached to the specified instance.
  353. * The operation returns false if the product code is not attached to the instance.
  354. *
  355. * The confirmProduct operation can only be executed by the owner of the AMI.
  356. * This feature is useful when an AMI owner is providing support and wants to
  357. * verify whether a user's instance is eligible.
  358. *
  359. * @param string $productCode The product code to confirm.
  360. * @param string $instanceId The instance for which to confirm the product code.
  361. * @return array|boolean An array if the product code is attached to the instance, false if it is not.
  362. */
  363. public function confirmProduct($productCode, $instanceId)
  364. {
  365. $params = array();
  366. $params['Action'] = 'ConfirmProductInstance';
  367. $params['ProductCode'] = $productCode;
  368. $params['InstanceId'] = $instanceId;
  369. $response = $this->sendRequest($params);
  370. $xpath = $response->getXPath();
  371. $result = $xpath->evaluate('string(//ec2:result/text())');
  372. if($result === "true") {
  373. $return['result'] = true;
  374. $return['ownerId'] = $xpath->evaluate('string(//ec2:ownerId/text())');
  375. return $return;
  376. }
  377. return false;
  378. }
  379. /**
  380. * Turn on Amazon CloudWatch Monitoring for an instance or a list of instances
  381. *
  382. * @param array|string $instanceId The instance or list of instances you want to enable monitoring for
  383. * @return array
  384. */
  385. public function monitor($instanceId)
  386. {
  387. $params = array();
  388. $params['Action'] = 'MonitorInstances';
  389. if(is_array($instanceId) && !empty($instanceId)) {
  390. foreach($instanceId as $k=>$name) {
  391. $params['InstanceId.' . ($k+1)] = $name;
  392. }
  393. } elseif($instanceId) {
  394. $params['InstanceId.1'] = $instanceId;
  395. }
  396. $response = $this->sendRequest($params);
  397. $xpath = $response->getXPath();
  398. $items = $xpath->query('//ec2:instancesSet/ec2:item');
  399. $arrReturn = array();
  400. foreach($items as $item) {
  401. $i = array();
  402. $i['instanceid'] = $xpath->evaluate('string(//ec2:instanceId/text())', $item);
  403. $i['monitorstate'] = $xpath->evaluate('string(//ec2:monitoring/ec2:state/text())');
  404. $arrReturn[] = $i;
  405. unset($i);
  406. }
  407. return $arrReturn;
  408. }
  409. /**
  410. * Turn off Amazon CloudWatch Monitoring for an instance or a list of instances
  411. *
  412. * @param array|string $instanceId The instance or list of instances you want to disable monitoring for
  413. * @return array
  414. */
  415. public function unmonitor($instanceId)
  416. {
  417. $params = array();
  418. $params['Action'] = 'UnmonitorInstances';
  419. if(is_array($instanceId) && !empty($instanceId)) {
  420. foreach($instanceId as $k=>$name) {
  421. $params['InstanceId.' . ($k+1)] = $name;
  422. }
  423. } elseif($instanceId) {
  424. $params['InstanceId.1'] = $instanceId;
  425. }
  426. $response = $this->sendRequest($params);
  427. $xpath = $response->getXPath();
  428. $items = $xpath->query('//ec2:instancesSet/ec2:item');
  429. $arrReturn = array();
  430. foreach($items as $item) {
  431. $i = array();
  432. $i['instanceid'] = $xpath->evaluate('string(//ec2:instanceId/text())', $item);
  433. $i['monitorstate'] = $xpath->evaluate('string(//ec2:monitoring/ec2:state/text())');
  434. $arrReturn[] = $i;
  435. unset($i);
  436. }
  437. return $arrReturn;
  438. }
  439. }