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 Spot Instance Request
25"""
26
27from boto.ec2.ec2object import TaggedEC2Object
28from boto.ec2.launchspecification import LaunchSpecification
29
30
31class SpotInstanceStateFault(object):
32    """
33    The fault codes for the Spot Instance request, if any.
34
35    :ivar code: The reason code for the Spot Instance state change.
36    :ivar message: The message for the Spot Instance state change.
37    """
38
39    def __init__(self, code=None, message=None):
40        self.code = code
41        self.message = message
42
43    def __repr__(self):
44        return '(%s, %s)' % (self.code, self.message)
45
46    def startElement(self, name, attrs, connection):
47        return None
48
49    def endElement(self, name, value, connection):
50        if name == 'code':
51            self.code = value
52        elif name == 'message':
53            self.message = value
54        setattr(self, name, value)
55
56
57class SpotInstanceStatus(object):
58    """
59    Contains the status of a Spot Instance Request.
60
61    :ivar code: Status code of the request.
62    :ivar message: The description for the status code for the Spot request.
63    :ivar update_time: Time the status was stated.
64    """
65
66    def __init__(self, code=None, update_time=None, message=None):
67        self.code = code
68        self.update_time = update_time
69        self.message = message
70
71    def __repr__(self):
72        return '<Status: %s>' % self.code
73
74    def startElement(self, name, attrs, connection):
75        return None
76
77    def endElement(self, name, value, connection):
78        if name == 'code':
79            self.code = value
80        elif name == 'message':
81            self.message = value
82        elif name == 'updateTime':
83            self.update_time = value
84
85
86class SpotInstanceRequest(TaggedEC2Object):
87    """
88
89    :ivar id: The ID of the Spot Instance Request.
90    :ivar price: The maximum hourly price for any Spot Instance launched to
91        fulfill the request.
92    :ivar type: The Spot Instance request type.
93    :ivar state: The state of the Spot Instance request.
94    :ivar fault: The fault codes for the Spot Instance request, if any.
95    :ivar valid_from: The start date of the request. If this is a one-time
96        request, the request becomes active at this date and time and remains
97        active until all instances launch, the request expires, or the request is
98        canceled. If the request is persistent, the request becomes active at this
99        date and time and remains active until it expires or is canceled.
100    :ivar valid_until: The end date of the request. If this is a one-time
101        request, the request remains active until all instances launch, the request
102        is canceled, or this date is reached. If the request is persistent, it
103        remains active until it is canceled or this date is reached.
104    :ivar launch_group: The instance launch group. Launch groups are Spot
105        Instances that launch together and terminate together.
106    :ivar launched_availability_zone: foo
107    :ivar product_description: The Availability Zone in which the bid is
108        launched.
109    :ivar availability_zone_group: The Availability Zone group. If you specify
110        the same Availability Zone group for all Spot Instance requests, all Spot
111        Instances are launched in the same Availability Zone.
112    :ivar create_time: The time stamp when the Spot Instance request was
113        created.
114    :ivar launch_specification: Additional information for launching instances.
115    :ivar instance_id: The instance ID, if an instance has been launched to
116        fulfill the Spot Instance request.
117    :ivar status: The status code and status message describing the Spot
118        Instance request.
119
120    """
121
122    def __init__(self, connection=None):
123        super(SpotInstanceRequest, self).__init__(connection)
124        self.id = None
125        self.price = None
126        self.type = None
127        self.state = None
128        self.fault = None
129        self.valid_from = None
130        self.valid_until = None
131        self.launch_group = None
132        self.launched_availability_zone = None
133        self.product_description = None
134        self.availability_zone_group = None
135        self.create_time = None
136        self.launch_specification = None
137        self.instance_id = None
138        self.status = None
139
140    def __repr__(self):
141        return 'SpotInstanceRequest:%s' % self.id
142
143    def startElement(self, name, attrs, connection):
144        retval = super(SpotInstanceRequest, self).startElement(name, attrs,
145            connection)
146        if retval is not None:
147            return retval
148        if name == 'launchSpecification':
149            self.launch_specification = LaunchSpecification(connection)
150            return self.launch_specification
151        elif name == 'fault':
152            self.fault = SpotInstanceStateFault()
153            return self.fault
154        elif name == 'status':
155            self.status = SpotInstanceStatus()
156            return self.status
157        else:
158            return None
159
160    def endElement(self, name, value, connection):
161        if name == 'spotInstanceRequestId':
162            self.id = value
163        elif name == 'spotPrice':
164            self.price = float(value)
165        elif name == 'type':
166            self.type = value
167        elif name == 'state':
168            self.state = value
169        elif name == 'validFrom':
170            self.valid_from = value
171        elif name == 'validUntil':
172            self.valid_until = value
173        elif name == 'launchGroup':
174            self.launch_group = value
175        elif name == 'availabilityZoneGroup':
176            self.availability_zone_group = value
177        elif name == 'launchedAvailabilityZone':
178            self.launched_availability_zone = value
179        elif name == 'instanceId':
180            self.instance_id = value
181        elif name == 'createTime':
182            self.create_time = value
183        elif name == 'productDescription':
184            self.product_description = value
185        else:
186            setattr(self, name, value)
187
188    def cancel(self, dry_run=False):
189        self.connection.cancel_spot_instance_requests(
190            [self.id],
191            dry_run=dry_run
192        )
193