Revision aa197ee4 api/util.py

b/api/util.py
28 28
class UTC(tzinfo):
29 29
    def utcoffset(self, dt):
30 30
        return timedelta(0)
31
    
31

  
32 32
    def tzname(self, dt):
33 33
        return 'UTC'
34
    
34

  
35 35
    def dst(self, dt):
36 36
        return timedelta(0)
37 37

  
38 38

  
39 39
def isoformat(d):
40 40
    """Return an ISO8601 date string that includes a timezone."""
41
    
41

  
42 42
    return d.replace(tzinfo=UTC()).isoformat()
43 43

  
44 44
def isoparse(s):
45 45
    """Parse an ISO8601 date string into a datetime object."""
46
    
46

  
47 47
    if not s:
48 48
        return None
49
    
49

  
50 50
    try:
51 51
        since = dateutil.parser.parse(s)
52 52
        utc_since = since.astimezone(UTC()).replace(tzinfo=None)
53 53
    except ValueError:
54 54
        raise BadRequest('Invalid changes-since parameter.')
55
    
55

  
56 56
    now = datetime.datetime.now()
57 57
    if utc_since > now:
58 58
        raise BadRequest('changes-since value set in the future.')
59
    
59

  
60 60
    if now - utc_since > timedelta(seconds=settings.POLL_LIMIT):
61 61
        raise BadRequest('Too old changes-since value.')
62
    
62

  
63 63
    return utc_since
64
    
64

  
65 65
def random_password(length=8):
66 66
    pool = ascii_letters + digits
67 67
    return ''.join(choice(pool) for i in range(length))
......
69 69

  
70 70
def get_vm(server_id, owner):
71 71
    """Return a VirtualMachine instance or raise ItemNotFound."""
72
    
72

  
73 73
    try:
74 74
        server_id = int(server_id)
75 75
        return VirtualMachine.objects.get(id=server_id, owner=owner)
......
80 80

  
81 81
def get_vm_meta(vm, key):
82 82
    """Return a VirtualMachineMetadata instance or raise ItemNotFound."""
83
    
83

  
84 84
    try:
85 85
        return VirtualMachineMetadata.objects.get(meta_key=key, vm=vm)
86 86
    except VirtualMachineMetadata.DoesNotExist:
......
88 88

  
89 89
def get_image(image_id, owner):
90 90
    """Return an Image instance or raise ItemNotFound."""
91
    
91

  
92 92
    try:
93 93
        image_id = int(image_id)
94 94
        return Image.objects.get(id=image_id, owner=owner)
......
107 107

  
108 108
def get_flavor(flavor_id):
109 109
    """Return a Flavor instance or raise ItemNotFound."""
110
    
110

  
111 111
    try:
112 112
        flavor_id = int(flavor_id)
113 113
        return Flavor.objects.get(id=flavor_id)
......
118 118

  
119 119
def get_network(network_id, owner):
120 120
    """Return a Network instance or raise ItemNotFound."""
121
    
121

  
122 122
    try:
123 123
        return Network.objects.get(id=network_id, owner=owner)
124 124
    except ValueError:
......
129 129

  
130 130
def get_request_dict(request):
131 131
    """Returns data sent by the client as a python dict."""
132
    
132

  
133 133
    data = request.raw_post_data
134 134
    if request.META.get('CONTENT_TYPE').startswith('application/json'):
135 135
        try:
......
146 146
        response['Content-Type'] = 'application/atom+xml'
147 147
    else:
148 148
        response['Content-Type'] = 'application/json'
149
    
149

  
150 150
    if settings.TEST:
151 151
        response['Date'] = format_date_time(time())
152 152

  
......
168 168
def render_fault(request, fault):
169 169
    if settings.DEBUG or settings.TEST:
170 170
        fault.details = format_exc(fault)
171
    
171

  
172 172
    if request.serialization == 'xml':
173 173
        data = render_to_string('fault.xml', {'fault': fault})
174 174
    else:
175 175
        d = {fault.name: {'code': fault.code, 'message': fault.message, 'details': fault.details}}
176 176
        data = json.dumps(d)
177
    
177

  
178 178
    resp = HttpResponse(data, status=fault.code)
179 179
    update_response_headers(request, resp)
180 180
    return resp
......
182 182

  
183 183
def request_serialization(request, atom_allowed=False):
184 184
    """Return the serialization format requested.
185
       
185

  
186 186
    Valid formats are 'json', 'xml' and 'atom' if `atom_allowed` is True.
187 187
    """
188
    
188

  
189 189
    path = request.path
190
    
190

  
191 191
    if path.endswith('.json'):
192 192
        return 'json'
193 193
    elif path.endswith('.xml'):
194 194
        return 'xml'
195 195
    elif atom_allowed and path.endswith('.atom'):
196 196
        return 'atom'
197
    
197

  
198 198
    for item in request.META.get('HTTP_ACCEPT', '').split(','):
199 199
        accept, sep, rest = item.strip().partition(';')
200 200
        if accept == 'application/json':
......
203 203
            return 'xml'
204 204
        elif atom_allowed and accept == 'application/atom+xml':
205 205
            return 'atom'
206
    
206

  
207 207
    return 'json'
208 208

  
209 209
def api_method(http_method=None, atom_allowed=False):
210 210
    """Decorator function for views that implement an API method."""
211
    
211

  
212 212
    def decorator(func):
213 213
        @wraps(func)
214 214
        def wrapper(request, *args, **kwargs):
......
218 218
                    raise Unauthorized('No user found.')
219 219
                if http_method and request.method != http_method:
220 220
                    raise BadRequest('Method not allowed.')
221
                
221

  
222 222
                resp = func(request, *args, **kwargs)
223 223
                update_response_headers(request, resp)
224 224
                return resp

Also available in: Unified diff