PageRenderTime 53ms CodeModel.GetById 2ms app.highlight 46ms RepoModel.GetById 1ms app.codeStats 0ms

/boto-2.5.2/boto/ec2/instance.py

#
Python | 480 lines | 363 code | 9 blank | 108 comment | 15 complexity | 2d1a514d237c9deab72d44caabe95229 MD5 | raw file
  1# Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/
  2# Copyright (c) 2010, Eucalyptus Systems, Inc.
  3#
  4# Permission is hereby granted, free of charge, to any person obtaining a
  5# copy of this software and associated documentation files (the
  6# "Software"), to deal in the Software without restriction, including
  7# without limitation the rights to use, copy, modify, merge, publish, dis-
  8# tribute, sublicense, and/or sell copies of the Software, and to permit
  9# persons to whom the Software is furnished to do so, subject to the fol-
 10# lowing conditions:
 11#
 12# The above copyright notice and this permission notice shall be included
 13# in all copies or substantial portions of the Software.
 14#
 15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 16# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
 17# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
 18# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
 19# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21# IN THE SOFTWARE.
 22
 23"""
 24Represents an EC2 Instance
 25"""
 26import boto
 27from boto.ec2.ec2object import EC2Object, TaggedEC2Object
 28from boto.resultset import ResultSet
 29from boto.ec2.address import Address
 30from boto.ec2.blockdevicemapping import BlockDeviceMapping
 31from boto.ec2.image import ProductCodes
 32from boto.ec2.networkinterface import NetworkInterface
 33from boto.ec2.group import Group
 34import base64
 35
 36class Reservation(EC2Object):
 37    """
 38    Represents a Reservation response object.
 39
 40    :ivar id: The unique ID of the Reservation.
 41    :ivar owner_id: The unique ID of the owner of the Reservation.
 42    :ivar groups: A list of Group objects representing the security
 43                  groups associated with launched instances.
 44    :ivar instances: A list of Instance objects launched in this
 45                     Reservation.
 46    """
 47    
 48    def __init__(self, connection=None):
 49        EC2Object.__init__(self, connection)
 50        self.id = None
 51        self.owner_id = None
 52        self.groups = []
 53        self.instances = []
 54
 55    def __repr__(self):
 56        return 'Reservation:%s' % self.id
 57
 58    def startElement(self, name, attrs, connection):
 59        if name == 'instancesSet':
 60            self.instances = ResultSet([('item', Instance)])
 61            return self.instances
 62        elif name == 'groupSet':
 63            self.groups = ResultSet([('item', Group)])
 64            return self.groups
 65        else:
 66            return None
 67
 68    def endElement(self, name, value, connection):
 69        if name == 'reservationId':
 70            self.id = value
 71        elif name == 'ownerId':
 72            self.owner_id = value
 73        else:
 74            setattr(self, name, value)
 75
 76    def stop_all(self):
 77        for instance in self.instances:
 78            instance.stop()
 79            
 80class Instance(TaggedEC2Object):
 81    """
 82    Represents an instance.
 83
 84    :ivar id: The unique ID of the Instance.
 85    :ivar groups: A list of Group objects representing the security
 86                  groups associated with the instance.
 87    :ivar public_dns_name: The public dns name of the instance.
 88    :ivar private_dns_name: The private dns name of the instance.
 89    :ivar state: The string representation of the instances current state.
 90    :ivar state_code: An integer representation of the instances current state.
 91    :ivar key_name: The name of the SSH key associated with the instance.
 92    :ivar instance_type: The type of instance (e.g. m1.small).
 93    :ivar launch_time: The time the instance was launched.
 94    :ivar image_id: The ID of the AMI used to launch this instance.
 95    :ivar placement: The availability zone in which the instance is running.
 96    :ivar kernel: The kernel associated with the instance.
 97    :ivar ramdisk: The ramdisk associated with the instance.
 98    :ivar architecture: The architecture of the image (i386|x86_64).
 99    :ivar hypervisor: The hypervisor used.
100    :ivar virtualization_type: The type of virtualization used.
101    :ivar product_codes: A list of product codes associated with this instance.
102    :ivar ami_launch_index: This instances position within it's launch group.
103    :ivar monitored: A boolean indicating whether monitoring is enabled or not.
104    :ivar spot_instance_request_id: The ID of the spot instance request
105        if this is a spot instance.
106    :ivar subnet_id: The VPC Subnet ID, if running in VPC.
107    :ivar vpc_id: The VPC ID, if running in VPC.
108    :ivar private_ip_address: The private IP address of the instance.
109    :ivar ip_address: The public IP address of the instance.
110    :ivar platform: Platform of the instance (e.g. Windows)
111    :ivar root_device_name: The name of the root device.
112    :ivar root_device_type: The root device type (ebs|instance-store).
113    :ivar block_device_mapping: The Block Device Mapping for the instance.
114    :ivar state_reason: The reason for the most recent state transition.
115    :ivar groups: List of security Groups associated with the instance.
116    :ivar interfaces: List of Elastic Network Interfaces associated with
117        this instance.
118    """
119    
120    def __init__(self, connection=None):
121        TaggedEC2Object.__init__(self, connection)
122        self.id = None
123        self.dns_name = None
124        self.public_dns_name = None
125        self.private_dns_name = None
126        self.state = None
127        self.state_code = None
128        self.key_name = None
129        self.shutdown_state = None
130        self.previous_state = None
131        self.instance_type = None
132        self.launch_time = None
133        self.image_id = None
134        self.placement = None
135        self.kernel = None
136        self.ramdisk = None
137        self.product_codes = ProductCodes()
138        self.ami_launch_index = None
139        self.monitored = False
140        self.spot_instance_request_id = None
141        self.subnet_id = None
142        self.vpc_id = None
143        self.private_ip_address = None
144        self.ip_address = None
145        self.requester_id = None
146        self._in_monitoring_element = False
147        self.persistent = False
148        self.root_device_name = None
149        self.root_device_type = None
150        self.block_device_mapping = None
151        self.state_reason = None
152        self.group_name = None
153        self.client_token = None
154        self.eventsSet = None
155        self.groups = []
156        self.platform = None
157        self.interfaces = []
158        self.hypervisor = None
159        self.virtualization_type = None
160        self.architecture = None
161
162    def __repr__(self):
163        return 'Instance:%s' % self.id
164
165    def startElement(self, name, attrs, connection):
166        retval = TaggedEC2Object.startElement(self, name, attrs, connection)
167        if retval is not None:
168            return retval
169        if name == 'monitoring':
170            self._in_monitoring_element = True
171        elif name == 'blockDeviceMapping':
172            self.block_device_mapping = BlockDeviceMapping()
173            return self.block_device_mapping
174        elif name == 'productCodes':
175            return self.product_codes
176        elif name == 'stateReason':
177            self.state_reason = SubParse('stateReason')
178            return self.state_reason
179        elif name == 'groupSet':
180            self.groups = ResultSet([('item', Group)])
181            return self.groups
182        elif name == "eventsSet":
183            self.eventsSet = SubParse('eventsSet')
184            return self.eventsSet
185        elif name == 'networkInterfaceSet':
186            self.interfaces = ResultSet([('item', NetworkInterface)])
187        elif name == 'iamInstanceProfile':
188            self.instance_profile = SubParse('iamInstanceProfile')
189            return self.instance_profile
190        return None
191
192    def endElement(self, name, value, connection):
193        if name == 'instanceId':
194            self.id = value
195        elif name == 'imageId':
196            self.image_id = value
197        elif name == 'dnsName' or name == 'publicDnsName':
198            self.dns_name = value           # backwards compatibility
199            self.public_dns_name = value
200        elif name == 'privateDnsName':
201            self.private_dns_name = value
202        elif name == 'keyName':
203            self.key_name = value
204        elif name == 'amiLaunchIndex':
205            self.ami_launch_index = value
206        elif name == 'shutdownState':
207            self.shutdown_state = value
208        elif name == 'previousState':
209            self.previous_state = value
210        elif name == 'name':
211            self.state = value
212        elif name == 'code':
213            try:
214                self.state_code = int(value)
215            except ValueError:
216                boto.log.warning('Error converting code (%s) to int' % value)
217                self.state_code = value
218        elif name == 'instanceType':
219            self.instance_type = value
220        elif name == 'rootDeviceName':
221            self.root_device_name = value
222        elif name == 'rootDeviceType':
223            self.root_device_type = value
224        elif name == 'launchTime':
225            self.launch_time = value
226        elif name == 'availabilityZone':
227            self.placement = value
228        elif name == 'platform':
229            self.platform = value
230        elif name == 'placement':
231            pass
232        elif name == 'kernelId':
233            self.kernel = value
234        elif name == 'ramdiskId':
235            self.ramdisk = value
236        elif name == 'state':
237            if self._in_monitoring_element:
238                if value == 'enabled':
239                    self.monitored = True
240                self._in_monitoring_element = False
241        elif name == 'spotInstanceRequestId':
242            self.spot_instance_request_id = value
243        elif name == 'subnetId':
244            self.subnet_id = value
245        elif name == 'vpcId':
246            self.vpc_id = value
247        elif name == 'privateIpAddress':
248            self.private_ip_address = value
249        elif name == 'ipAddress':
250            self.ip_address = value
251        elif name == 'requesterId':
252            self.requester_id = value
253        elif name == 'persistent':
254            if value == 'true':
255                self.persistent = True
256            else:
257                self.persistent = False
258        elif name == 'groupName':
259            if self._in_monitoring_element:
260                self.group_name = value
261        elif name == 'clientToken':
262            self.client_token = value
263        elif name == "eventsSet":
264            self.events = value
265        elif name == 'hypervisor':
266            self.hypervisor = value
267        elif name == 'virtualizationType':
268            self.virtualization_type = value
269        elif name == 'architecture':
270            self.architecture = value
271        else:
272            setattr(self, name, value)
273
274    def _update(self, updated):
275        self.__dict__.update(updated.__dict__)
276
277    def update(self, validate=False):
278        """
279        Update the instance's state information by making a call to fetch
280        the current instance attributes from the service.
281
282        :type validate: bool
283        :param validate: By default, if EC2 returns no data about the
284                         instance the update method returns quietly.  If
285                         the validate param is True, however, it will
286                         raise a ValueError exception if no data is
287                         returned from EC2.
288        """
289        rs = self.connection.get_all_instances([self.id])
290        if len(rs) > 0:
291            r = rs[0]
292            for i in r.instances:
293                if i.id == self.id:
294                    self._update(i)
295        elif validate:
296            raise ValueError('%s is not a valid Instance ID' % self.id)
297        return self.state
298
299    def terminate(self):
300        """
301        Terminate the instance
302        """
303        rs = self.connection.terminate_instances([self.id])
304        if len(rs) > 0:
305            self._update(rs[0])
306
307    def stop(self, force=False):
308        """
309        Stop the instance
310
311        :type force: bool
312        :param force: Forces the instance to stop
313        
314        :rtype: list
315        :return: A list of the instances stopped
316        """
317        rs = self.connection.stop_instances([self.id], force)
318        if len(rs) > 0:
319            self._update(rs[0])
320
321    def start(self):
322        """
323        Start the instance.
324        """
325        rs = self.connection.start_instances([self.id])
326        if len(rs) > 0:
327            self._update(rs[0])
328
329    def reboot(self):
330        return self.connection.reboot_instances([self.id])
331
332    def get_console_output(self):
333        """
334        Retrieves the console output for the instance.
335
336        :rtype: :class:`boto.ec2.instance.ConsoleOutput`
337        :return: The console output as a ConsoleOutput object
338        """
339        return self.connection.get_console_output(self.id)
340
341    def confirm_product(self, product_code):
342        return self.connection.confirm_product_instance(self.id, product_code)
343
344    def use_ip(self, ip_address):
345        if isinstance(ip_address, Address):
346            ip_address = ip_address.public_ip
347        return self.connection.associate_address(self.id, ip_address)
348
349    def monitor(self):
350        return self.connection.monitor_instance(self.id)
351
352    def unmonitor(self):
353        return self.connection.unmonitor_instance(self.id)
354
355    def get_attribute(self, attribute):
356        """
357        Gets an attribute from this instance.
358
359        :type attribute: string
360        :param attribute: The attribute you need information about
361                          Valid choices are:
362                          instanceType|kernel|ramdisk|userData|
363                          disableApiTermination|
364                          instanceInitiatedShutdownBehavior|
365                          rootDeviceName|blockDeviceMapping
366                          sourceDestCheck|groupSet
367
368        :rtype: :class:`boto.ec2.image.InstanceAttribute`
369        :return: An InstanceAttribute object representing the value of the
370                 attribute requested
371        """
372        return self.connection.get_instance_attribute(self.id, attribute)
373
374    def modify_attribute(self, attribute, value):
375        """
376        Changes an attribute of this instance
377
378        :type attribute: string
379        :param attribute: The attribute you wish to change.
380
381                          * AttributeName - Expected value (default)
382                          * InstanceType - A valid instance type (m1.small)
383                          * Kernel - Kernel ID (None)
384                          * Ramdisk - Ramdisk ID (None)
385                          * UserData - Base64 encoded String (None)
386                          * DisableApiTermination - Boolean (true)
387                          * InstanceInitiatedShutdownBehavior - stop|terminate
388                          * RootDeviceName - device name (None)
389                          * SourceDestCheck - Boolean (true)
390                          * GroupSet - Set of Security Groups or IDs
391
392        :type value: string
393        :param value: The new value for the attribute
394
395        :rtype: bool
396        :return: Whether the operation succeeded or not
397        """
398        return self.connection.modify_instance_attribute(self.id, attribute,
399                                                         value)
400
401    def reset_attribute(self, attribute):
402        """
403        Resets an attribute of this instance to its default value.
404
405        :type attribute: string
406        :param attribute: The attribute to reset. Valid values are:
407                          kernel|ramdisk
408
409        :rtype: bool
410        :return: Whether the operation succeeded or not
411        """
412        return self.connection.reset_instance_attribute(self.id, attribute)
413
414class ConsoleOutput:
415
416    def __init__(self, parent=None):
417        self.parent = parent
418        self.instance_id = None
419        self.timestamp = None
420        self.output = None
421
422    def startElement(self, name, attrs, connection):
423        return None
424
425    def endElement(self, name, value, connection):
426        if name == 'instanceId':
427            self.instance_id = value
428        elif name == 'timestamp':
429            self.timestamp = value
430        elif name == 'output':
431            self.output = base64.b64decode(value)
432        else:
433            setattr(self, name, value)
434
435class InstanceAttribute(dict):
436
437    ValidValues = ['instanceType', 'kernel', 'ramdisk', 'userData',
438                   'disableApiTermination', 'instanceInitiatedShutdownBehavior',
439                   'rootDeviceName', 'blockDeviceMapping', 'sourceDestCheck',
440                   'groupSet']
441
442    def __init__(self, parent=None):
443        dict.__init__(self)
444        self.instance_id = None
445        self.request_id = None
446        self._current_value = None
447
448    def startElement(self, name, attrs, connection):
449        if name == 'blockDeviceMapping':
450            self[name] = BlockDeviceMapping()
451            return self[name]
452        elif name == 'groupSet':
453            self[name] = ResultSet([('item', Group)])
454            return self[name]
455        else:
456            return None
457
458    def endElement(self, name, value, connection):
459        if name == 'instanceId':
460            self.instance_id = value
461        elif name == 'requestId':
462            self.request_id = value
463        elif name == 'value':
464            self._current_value = value
465        elif name in self.ValidValues:
466            self[name] = self._current_value
467
468class SubParse(dict):
469
470    def __init__(self, section, parent=None):
471        dict.__init__(self)
472        self.section = section
473
474    def startElement(self, name, attrs, connection):
475        return None
476
477    def endElement(self, name, value, connection):
478        if name != self.section:
479            self[name] = value
480