Instance.php 21 KB

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