Instance.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  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. * @return array
  95. */
  96. public function run(array $options)
  97. {
  98. $_defaultOptions = array(
  99. 'minCount' => 1,
  100. 'maxCount' => 1,
  101. 'instanceType' => Zend_Service_Amazon_Ec2_Instance::SMALL
  102. );
  103. // set / override the defualt optoins if they are not passed into the array;
  104. $options = array_merge($_defaultOptions, $options);
  105. if(!isset($options['imageId'])) {
  106. require_once 'Zend/Service/Amazon/Ec2/Exception.php';
  107. throw new Zend_Service_Amazon_Ec2_Exception('No Image Id Provided');
  108. }
  109. $params = array();
  110. $params['Action'] = 'RunInstances';
  111. $params['ImageId'] = $options['imageId'];
  112. $params['MinCount'] = $options['minCount'];
  113. $params['MaxCount'] = $options['maxCount'];
  114. if(isset($options['keyName'])) {
  115. $params['KeyName'] = $options['keyName'];
  116. }
  117. if(is_array($options['securityGroup']) && !empty($options['securityGroup'])) {
  118. foreach($options['securityGroup'] as $k=>$name) {
  119. $params['SecurityGroup.' . ($k+1)] = $name;
  120. }
  121. } elseif(isset($options['securityGroup'])) {
  122. $params['SecurityGroup.1'] = $options['securityGroup'];
  123. }
  124. if(isset($options['userData'])) {
  125. $params['UserData'] = base64_encode($options['userData']);
  126. }
  127. if(isset($options['instanceType'])) {
  128. $params['InstanceType'] = $options['instanceType'];
  129. }
  130. if(isset($options['placement'])) {
  131. $params['Placement.AvailabilityZone'] = $options['placement'];
  132. }
  133. if(isset($options['kernelId'])) {
  134. $params['KernelId'] = $options['kernelId'];
  135. }
  136. if(isset($options['ramdiskId'])) {
  137. $params['RamdiskId'] = $options['ramdiskId'];
  138. }
  139. if(isset($options['blockDeviceVirtualName']) && isset($options['blockDeviceName'])) {
  140. $params['BlockDeviceMapping.n.VirtualName'] = $options['blockDeviceVirtualName'];
  141. $params['BlockDeviceMapping.n.DeviceName'] = $options['blockDeviceName'];
  142. }
  143. $response = $this->sendRequest($params);
  144. $xpath = $response->getXPath();
  145. $return = array();
  146. $return['reservationId'] = $xpath->evaluate('string(//ec2:reservationId/text())');
  147. $return['ownerId'] = $xpath->evaluate('string(//ec2:ownerId/text())');
  148. $gs = $xpath->query('//ec2:groupSet/ec2:item');
  149. foreach($gs as $gs_node) {
  150. $return['groupSet'][] = $xpath->evaluate('string(ec2:groupId/text())', $gs_node);
  151. unset($gs_node);
  152. }
  153. unset($gs);
  154. $is = $xpath->query('//ec2:instancesSet/ec2:item');
  155. foreach($is as $is_node) {
  156. $item = array();
  157. $item['instanceId'] = $xpath->evaluate('string(ec2:instanceId/text())', $is_node);
  158. $item['imageId'] = $xpath->evaluate('string(ec2:imageId/text())', $is_node);
  159. $item['instanceState']['code'] = $xpath->evaluate('string(ec2:instanceState/ec2:code/text())', $is_node);
  160. $item['instanceState']['name'] = $xpath->evaluate('string(ec2:instanceState/ec2:name/text())', $is_node);
  161. $item['privateDnsName'] = $xpath->evaluate('string(ec2:privateDnsName/text())', $is_node);
  162. $item['dnsName'] = $xpath->evaluate('string(ec2:dnsName/text())', $is_node);
  163. $item['keyName'] = $xpath->evaluate('string(ec2:keyName/text())', $is_node);
  164. $item['instanceType'] = $xpath->evaluate('string(ec2:instanceType/text())', $is_node);
  165. $item['amiLaunchIndex'] = $xpath->evaluate('string(ec2:amiLaunchIndex/text())', $is_node);
  166. $item['launchTime'] = $xpath->evaluate('string(ec2:launchTime/text())', $is_node);
  167. $item['availabilityZone'] = $xpath->evaluate('string(ec2:placement/ec2:availabilityZone/text())', $is_node);
  168. $return['instances'][] = $item;
  169. unset($item);
  170. unset($is_node);
  171. }
  172. unset($is);
  173. return $return;
  174. }
  175. /**
  176. * Returns information about instances that you own.
  177. *
  178. * If you specify one or more instance IDs, Amazon EC2 returns information
  179. * for those instances. If you do not specify instance IDs, Amazon EC2
  180. * returns information for all relevant instances. If you specify an invalid
  181. * instance ID, a fault is returned. If you specify an instance that you do
  182. * not own, it will not be included in the returned results.
  183. *
  184. * Recently terminated instances might appear in the returned results.
  185. * This interval is usually less than one hour.
  186. *
  187. * @param string|array $instaceId Set of instances IDs of which to get the status.
  188. * @param boolean Ture to ignore Terminated Instances.
  189. * @return array
  190. */
  191. public function describe($instanceId = null, $ignoreTerminated = false)
  192. {
  193. $params = array();
  194. $params['Action'] = 'DescribeInstances';
  195. if(is_array($instanceId) && !empty($instanceId)) {
  196. foreach($instanceId as $k=>$name) {
  197. $params['InstanceId.' . ($k+1)] = $name;
  198. }
  199. } elseif($instanceId) {
  200. $params['InstanceId.1'] = $instanceId;
  201. }
  202. $response = $this->sendRequest($params);
  203. $xpath = $response->getXPath();
  204. $nodes = $xpath->query('//ec2:reservationSet/ec2:item');
  205. $return = array();
  206. foreach($nodes as $node) {
  207. $return['reservationId'] = $xpath->evaluate('string(ec2:reservationId/text())', $node);
  208. $return['ownerId'] = $xpath->evaluate('string(ec2:ownerId/text())', $node);
  209. $gs = $xpath->query('ec2:groupSet/ec2:item', $node);
  210. foreach($gs as $gs_node) {
  211. $return['groupSet'][] = $xpath->evaluate('string(ec2:groupId/text())', $gs_node);
  212. unset($gs_node);
  213. }
  214. unset($gs);
  215. $is = $xpath->query('ec2:instancesSet/ec2:item', $node);
  216. $return['instances'] = array();
  217. foreach($is as $is_node) {
  218. if($xpath->evaluate('string(ec2:instanceState/ec2:code/text())', $is_node) == 48 && $ignoreTerminated) continue;
  219. $item = array();
  220. $item['instanceId'] = $xpath->evaluate('string(ec2:instanceId/text())', $is_node);
  221. $item['imageId'] = $xpath->evaluate('string(ec2:imageId/text())', $is_node);
  222. $item['instanceState']['code'] = $xpath->evaluate('string(ec2:instanceState/ec2:code/text())', $is_node);
  223. $item['instanceState']['name'] = $xpath->evaluate('string(ec2:instanceState/ec2:name/text())', $is_node);
  224. $item['privateDnsName'] = $xpath->evaluate('string(ec2:privateDnsName/text())', $is_node);
  225. $item['dnsName'] = $xpath->evaluate('string(ec2:dnsName/text())', $is_node);
  226. $item['keyName'] = $xpath->evaluate('string(ec2:keyName/text())', $is_node);
  227. $item['productCode'] = $xpath->evaluate('string(ec2:productCodesSet/ec2:item/ec2:productCode/text())', $is_node);
  228. $item['instanceType'] = $xpath->evaluate('string(ec2:instanceType/text())', $is_node);
  229. $item['launchTime'] = $xpath->evaluate('string(ec2:launchTime/text())', $is_node);
  230. $item['availabilityZone'] = $xpath->evaluate('string(ec2:placement/ec2:availabilityZone/text())', $is_node);
  231. $item['kernelId'] = $xpath->evaluate('string(ec2:kernelId/text())', $is_node);
  232. $item['ramediskId'] = $xpath->evaluate('string(ec2:ramediskId/text())', $is_node);
  233. $return['instances'][] = $item;
  234. unset($item);
  235. unset($is_node);
  236. }
  237. unset($is);
  238. }
  239. return $return;
  240. }
  241. /**
  242. * Returns information about instances that you own that were started from
  243. * a specific imageId
  244. *
  245. * Recently terminated instances might appear in the returned results.
  246. * This interval is usually less than one hour.
  247. *
  248. * @param string $imageId The imageId used to start the Instance.
  249. * @param boolean Ture to ignore Terminated Instances.
  250. * @return array
  251. */
  252. public function describeByImageId($imageId, $ignoreTerminated = false)
  253. {
  254. $arrInstances = $this->describe(null, $ignoreTerminated);
  255. $return = array();
  256. foreach($arrInstances['instances'] as $k => $instance) {
  257. if($instance['imageId'] !== $imageId) continue;
  258. $instance['groupSet'] = $arrInstances['groupSet'][$k];
  259. $return[] = $instance;
  260. }
  261. return $return;
  262. }
  263. /**
  264. * Shuts down one or more instances. This operation is idempotent; if you terminate
  265. * an instance more than once, each call will succeed.
  266. *
  267. * Terminated instances will remain visible after termination (approximately one hour).
  268. *
  269. * @param string|array $instanceId One or more instance IDs returned.
  270. * @return array
  271. */
  272. public function terminate($instanceId)
  273. {
  274. $params = array();
  275. $params['Action'] = 'TerminateInstances';
  276. if(is_array($instanceId) && !empty($instanceId)) {
  277. foreach($instanceId as $k=>$name) {
  278. $params['InstanceId.' . ($k+1)] = $name;
  279. }
  280. } elseif($instanceId) {
  281. $params['InstanceId.1'] = $instanceId;
  282. }
  283. $response = $this->sendRequest($params);
  284. $xpath = $response->getXPath();
  285. $nodes = $xpath->query('//ec2:instancesSet/ec2:item');
  286. $return = array();
  287. foreach($nodes as $node) {
  288. $item = array();
  289. $item['instanceId'] = $xpath->evaluate('string(ec2:instanceId/text())', $node);
  290. $item['shutdownState']['code'] = $xpath->evaluate('string(ec2:shutdownState/ec2:code/text())', $node);
  291. $item['shutdownState']['name'] = $xpath->evaluate('string(ec2:shutdownState/ec2:name/text())', $node);
  292. $item['previousState']['code'] = $xpath->evaluate('string(ec2:previousState/ec2:code/text())', $node);
  293. $item['previousState']['name'] = $xpath->evaluate('string(ec2:previousState/ec2:name/text())', $node);
  294. $return[] = $item;
  295. unset($item);
  296. }
  297. return $return;
  298. }
  299. /**
  300. * Requests a reboot of one or more instances.
  301. *
  302. * This operation is asynchronous; it only queues a request to reboot the specified instance(s). The operation
  303. * will succeed if the instances are valid and belong to the user. Requests to reboot terminated instances are ignored.
  304. *
  305. * @param string|array $instanceId One or more instance IDs.
  306. * @return boolean
  307. */
  308. public function reboot($instanceId)
  309. {
  310. $params = array();
  311. $params['Action'] = 'RebootInstances';
  312. if(is_array($instanceId) && !empty($instanceId)) {
  313. foreach($instanceId as $k=>$name) {
  314. $params['InstanceId.' . ($k+1)] = $name;
  315. }
  316. } elseif($instanceId) {
  317. $params['InstanceId.1'] = $instanceId;
  318. }
  319. $response = $this->sendRequest($params);
  320. $xpath = $response->getXPath();
  321. $return = $xpath->evaluate('string(//ec2:return/text())');
  322. return ($return === "true");
  323. }
  324. /**
  325. * Retrieves console output for the specified instance.
  326. *
  327. * Instance console output is buffered and posted shortly after instance boot, reboot, and termination.
  328. * Amazon EC2 preserves the most recent 64 KB output which will be available for at least one hour after the most recent post.
  329. *
  330. * @param string $instanceId An instance ID
  331. * @return array
  332. */
  333. public function consoleOutput($instanceId)
  334. {
  335. $params = array();
  336. $params['Action'] = 'GetConsoleOutput';
  337. $params['InstanceId'] = $instanceId;
  338. $response = $this->sendRequest($params);
  339. $xpath = $response->getXPath();
  340. $return = array();
  341. $return['instanceId'] = $xpath->evaluate('string(//ec2:instanceId/text())');
  342. $return['timestamp'] = $xpath->evaluate('string(//ec2:timestamp/text())');
  343. $return['output'] = base64_decode($xpath->evaluate('string(//ec2:output/text())'));
  344. return $return;
  345. }
  346. /**
  347. * Returns true if the specified product code is attached to the specified instance.
  348. * The operation returns false if the product code is not attached to the instance.
  349. *
  350. * The confirmProduct operation can only be executed by the owner of the AMI.
  351. * This feature is useful when an AMI owner is providing support and wants to
  352. * verify whether a user's instance is eligible.
  353. *
  354. * @param string $productCode The product code to confirm.
  355. * @param string $instanceId The instance for which to confirm the product code.
  356. * @return array|boolean An array if the product code is attached to the instance, false if it is not.
  357. */
  358. public function confirmProduct($productCode, $instanceId)
  359. {
  360. $params = array();
  361. $params['Action'] = 'ConfirmProductInstance';
  362. $params['ProductCode'] = $productCode;
  363. $params['InstanceId'] = $instanceId;
  364. $response = $this->sendRequest($params);
  365. $xpath = $response->getXPath();
  366. $result = $xpath->evaluate('string(//ec2:result/text())');
  367. if($result === "true") {
  368. $return['result'] = true;
  369. $return['ownerId'] = $xpath->evaluate('string(//ec2:ownerId/text())');
  370. return $return;
  371. }
  372. return false;
  373. }
  374. }