1# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/
2# Copyright (c) 2012 Amazon.com, Inc. or its affiliates.
3# All Rights Reserved
4#
5# Permission is hereby granted, free of charge, to any person obtaining a
6# copy of this software and associated documentation files (the
7# "Software"), to deal in the Software without restriction, including
8# without limitation the rights to use, copy, modify, merge, publish, dis-
9# tribute, sublicense, and/or sell copies of the Software, and to permit
10# persons to whom the Software is furnished to do so, subject to the fol-
11# lowing conditions:
12#
13# The above copyright notice and this permission notice shall be included
14# in all copies or substantial portions of the Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
18# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
19# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22# IN THE SOFTWARE.
23
24
25class Details(dict):
26    """
27    A dict object that contains name/value pairs which provide
28    more detailed information about the status of the system
29    or the instance.
30    """
31
32    def startElement(self, name, attrs, connection):
33        return None
34
35    def endElement(self, name, value, connection):
36        if name == 'name':
37            self._name = value
38        elif name == 'status':
39            self[self._name] = value
40        else:
41            setattr(self, name, value)
42
43
44class Event(object):
45    """
46    A status event for an instance.
47
48    :ivar code: A string indicating the event type.
49    :ivar description: A string describing the reason for the event.
50    :ivar not_before: A datestring describing the earliest time for
51        the event.
52    :ivar not_after: A datestring describing the latest time for
53        the event.
54    """
55
56    def __init__(self, code=None, description=None,
57                 not_before=None, not_after=None):
58        self.code = code
59        self.description = description
60        self.not_before = not_before
61        self.not_after = not_after
62
63    def __repr__(self):
64        return 'Event:%s' % self.code
65
66    def startElement(self, name, attrs, connection):
67        return None
68
69    def endElement(self, name, value, connection):
70        if name == 'code':
71            self.code = value
72        elif name == 'description':
73            self.description = value
74        elif name == 'notBefore':
75            self.not_before = value
76        elif name == 'notAfter':
77            self.not_after = value
78        else:
79            setattr(self, name, value)
80
81
82class Status(object):
83    """
84    A generic Status object used for system status and instance status.
85
86    :ivar status: A string indicating overall status.
87    :ivar details: A dict containing name-value pairs which provide
88        more details about the current status.
89    """
90
91    def __init__(self, status=None, details=None):
92        self.status = status
93        if not details:
94            details = Details()
95        self.details = details
96
97    def __repr__(self):
98        return 'Status:%s' % self.status
99
100    def startElement(self, name, attrs, connection):
101        if name == 'details':
102            return self.details
103        return None
104
105    def endElement(self, name, value, connection):
106        if name == 'status':
107            self.status = value
108        else:
109            setattr(self, name, value)
110
111
112class EventSet(list):
113
114    def startElement(self, name, attrs, connection):
115        if name == 'item':
116            event = Event()
117            self.append(event)
118            return event
119        else:
120            return None
121
122    def endElement(self, name, value, connection):
123        setattr(self, name, value)
124
125
126class InstanceStatus(object):
127    """
128    Represents an EC2 Instance status as reported by
129    DescribeInstanceStatus request.
130
131    :ivar id: The instance identifier.
132    :ivar zone: The availability zone of the instance.
133    :ivar events: A list of events relevant to the instance.
134    :ivar state_code: An integer representing the current state
135        of the instance.
136    :ivar state_name: A string describing the current state
137        of the instance.
138    :ivar system_status: A Status object that reports impaired
139        functionality that stems from issues related to the systems
140        that support an instance, such as such as hardware failures
141        and network connectivity problems.
142    :ivar instance_status: A Status object that reports impaired
143        functionality that arises from problems internal to the instance.
144    """
145
146    def __init__(self, id=None, zone=None, events=None,
147                 state_code=None, state_name=None):
148        self.id = id
149        self.zone = zone
150        self.events = events
151        self.state_code = state_code
152        self.state_name = state_name
153        self.system_status = Status()
154        self.instance_status = Status()
155
156    def __repr__(self):
157        return 'InstanceStatus:%s' % self.id
158
159    def startElement(self, name, attrs, connection):
160        if name == 'eventsSet':
161            self.events = EventSet()
162            return self.events
163        elif name == 'systemStatus':
164            return self.system_status
165        elif name == 'instanceStatus':
166            return self.instance_status
167        else:
168            return None
169
170    def endElement(self, name, value, connection):
171        if name == 'instanceId':
172            self.id = value
173        elif name == 'availabilityZone':
174            self.zone = value
175        elif name == 'code':
176            self.state_code = int(value)
177        elif name == 'name':
178            self.state_name = value
179        else:
180            setattr(self, name, value)
181
182
183class InstanceStatusSet(list):
184    """
185    A list object that contains the results of a call to
186    DescribeInstanceStatus request.  Each element of the
187    list will be an InstanceStatus object.
188
189    :ivar next_token: If the response was truncated by
190        the EC2 service, the next_token attribute of the
191        object will contain the string that needs to be
192        passed in to the next request to retrieve the next
193        set of results.
194    """
195
196    def __init__(self, connection=None):
197        list.__init__(self)
198        self.connection = connection
199        self.next_token = None
200
201    def startElement(self, name, attrs, connection):
202        if name == 'item':
203            status = InstanceStatus()
204            self.append(status)
205            return status
206        else:
207            return None
208
209    def endElement(self, name, value, connection):
210        if name == 'nextToken':
211            self.next_token = value
212        setattr(self, name, value)
213