Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / api / networks.py @ 0ed12c27

History | View | Annotate | Download (8.4 kB)

1 6ef51e9f Giorgos Verigakis
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2 adee02b8 Giorgos Verigakis
# 
3 adee02b8 Giorgos Verigakis
# Redistribution and use in source and binary forms, with or
4 adee02b8 Giorgos Verigakis
# without modification, are permitted provided that the following
5 adee02b8 Giorgos Verigakis
# conditions are met:
6 adee02b8 Giorgos Verigakis
# 
7 adee02b8 Giorgos Verigakis
#   1. Redistributions of source code must retain the above
8 adee02b8 Giorgos Verigakis
#      copyright notice, this list of conditions and the following
9 adee02b8 Giorgos Verigakis
#      disclaimer.
10 adee02b8 Giorgos Verigakis
# 
11 adee02b8 Giorgos Verigakis
#   2. Redistributions in binary form must reproduce the above
12 adee02b8 Giorgos Verigakis
#      copyright notice, this list of conditions and the following
13 adee02b8 Giorgos Verigakis
#      disclaimer in the documentation and/or other materials
14 adee02b8 Giorgos Verigakis
#      provided with the distribution.
15 adee02b8 Giorgos Verigakis
# 
16 adee02b8 Giorgos Verigakis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 adee02b8 Giorgos Verigakis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 adee02b8 Giorgos Verigakis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 adee02b8 Giorgos Verigakis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 adee02b8 Giorgos Verigakis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 adee02b8 Giorgos Verigakis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 adee02b8 Giorgos Verigakis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 adee02b8 Giorgos Verigakis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 adee02b8 Giorgos Verigakis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 adee02b8 Giorgos Verigakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 adee02b8 Giorgos Verigakis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 adee02b8 Giorgos Verigakis
# POSSIBILITY OF SUCH DAMAGE.
28 adee02b8 Giorgos Verigakis
# 
29 adee02b8 Giorgos Verigakis
# The views and conclusions contained in the software and
30 adee02b8 Giorgos Verigakis
# documentation are those of the authors and should not be
31 adee02b8 Giorgos Verigakis
# interpreted as representing official policies, either expressed
32 adee02b8 Giorgos Verigakis
# or implied, of GRNET S.A.
33 adee02b8 Giorgos Verigakis
34 2035039b Giorgos Verigakis
from logging import getLogger
35 2035039b Giorgos Verigakis
36 0269afd6 Giorgos Verigakis
from django.conf.urls.defaults import patterns
37 d44c236b Giorgos Verigakis
from django.db.models import Q
38 0269afd6 Giorgos Verigakis
from django.http import HttpResponse
39 69d6d7dd Giorgos Verigakis
from django.template.loader import render_to_string
40 0269afd6 Giorgos Verigakis
from django.utils import simplejson as json
41 0269afd6 Giorgos Verigakis
42 b36f78fa Giorgos Verigakis
from synnefo.api import util
43 b36f78fa Giorgos Verigakis
from synnefo.api.actions import network_actions
44 b36f78fa Giorgos Verigakis
from synnefo.api.common import method_not_allowed
45 b36f78fa Giorgos Verigakis
from synnefo.api.faults import BadRequest, OverLimit, Unauthorized
46 b36f78fa Giorgos Verigakis
from synnefo.db.models import Network
47 b36f78fa Giorgos Verigakis
from synnefo.logic import backend
48 9e98ba3c Giorgos Verigakis
49 9e98ba3c Giorgos Verigakis
50 9e98ba3c Giorgos Verigakis
log = getLogger('synnefo.api')
51 b36f78fa Giorgos Verigakis
52 0269afd6 Giorgos Verigakis
53 0269afd6 Giorgos Verigakis
urlpatterns = patterns('synnefo.api.networks',
54 0269afd6 Giorgos Verigakis
    (r'^(?:/|.json|.xml)?$', 'demux'),
55 0269afd6 Giorgos Verigakis
    (r'^/detail(?:.json|.xml)?$', 'list_networks', {'detail': True}),
56 f4fe8796 Giorgos Verigakis
    (r'^/(\w+)(?:.json|.xml)?$', 'network_demux'),
57 f4fe8796 Giorgos Verigakis
    (r'^/(\w+)/action(?:.json|.xml)?$', 'network_action'),
58 0269afd6 Giorgos Verigakis
)
59 0269afd6 Giorgos Verigakis
60 0269afd6 Giorgos Verigakis
61 0269afd6 Giorgos Verigakis
def demux(request):
62 0269afd6 Giorgos Verigakis
    if request.method == 'GET':
63 0269afd6 Giorgos Verigakis
        return list_networks(request)
64 0269afd6 Giorgos Verigakis
    elif request.method == 'POST':
65 0269afd6 Giorgos Verigakis
        return create_network(request)
66 0269afd6 Giorgos Verigakis
    else:
67 0269afd6 Giorgos Verigakis
        return method_not_allowed(request)
68 0269afd6 Giorgos Verigakis
69 6ef51e9f Giorgos Verigakis
70 b19653d1 Giorgos Verigakis
def network_demux(request, network_id):
71 0269afd6 Giorgos Verigakis
    if request.method == 'GET':
72 b19653d1 Giorgos Verigakis
        return get_network_details(request, network_id)
73 0269afd6 Giorgos Verigakis
    elif request.method == 'PUT':
74 b19653d1 Giorgos Verigakis
        return update_network_name(request, network_id)
75 0269afd6 Giorgos Verigakis
    elif request.method == 'DELETE':
76 b19653d1 Giorgos Verigakis
        return delete_network(request, network_id)
77 0269afd6 Giorgos Verigakis
    else:
78 0269afd6 Giorgos Verigakis
        return method_not_allowed(request)
79 0269afd6 Giorgos Verigakis
80 0269afd6 Giorgos Verigakis
81 6ef51e9f Giorgos Verigakis
def network_to_dict(network, user_id, detail=True):
82 207b70d5 Giorgos Verigakis
    network_id = str(network.id) if not network.public else 'public'
83 207b70d5 Giorgos Verigakis
    d = {'id': network_id, 'name': network.name}
84 0269afd6 Giorgos Verigakis
    if detail:
85 b36f78fa Giorgos Verigakis
        d['updated'] = util.isoformat(network.updated)
86 b36f78fa Giorgos Verigakis
        d['created'] = util.isoformat(network.created)
87 d44c236b Giorgos Verigakis
        d['status'] = network.state
88 6ef51e9f Giorgos Verigakis
        servers = [vm.id for vm in network.machines.filter(userid=user_id)]
89 73aed6bf Giorgos Verigakis
        d['servers'] = {'values': servers}
90 0269afd6 Giorgos Verigakis
    return d
91 0269afd6 Giorgos Verigakis
92 6ef51e9f Giorgos Verigakis
93 0269afd6 Giorgos Verigakis
def render_network(request, networkdict, status=200):
94 0269afd6 Giorgos Verigakis
    if request.serialization == 'xml':
95 0269afd6 Giorgos Verigakis
        data = render_to_string('network.xml', {'network': networkdict})
96 0269afd6 Giorgos Verigakis
    else:
97 0269afd6 Giorgos Verigakis
        data = json.dumps({'network': networkdict})
98 0269afd6 Giorgos Verigakis
    return HttpResponse(data, status=status)
99 0269afd6 Giorgos Verigakis
100 0269afd6 Giorgos Verigakis
101 b36f78fa Giorgos Verigakis
@util.api_method('GET')
102 0269afd6 Giorgos Verigakis
def list_networks(request, detail=False):
103 0269afd6 Giorgos Verigakis
    # Normal Response Codes: 200, 203
104 0269afd6 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
105 0269afd6 Giorgos Verigakis
    #                       serviceUnavailable (503),
106 0269afd6 Giorgos Verigakis
    #                       unauthorized (401),
107 0269afd6 Giorgos Verigakis
    #                       badRequest (400),
108 0269afd6 Giorgos Verigakis
    #                       overLimit (413)
109 d44c236b Giorgos Verigakis
    
110 9e98ba3c Giorgos Verigakis
    log.debug('list_networks detail=%s', detail)
111 b36f78fa Giorgos Verigakis
    since = util.isoparse(request.GET.get('changes-since'))
112 6ef51e9f Giorgos Verigakis
    user_networks = Network.objects.filter(
113 4b3b8688 Giorgos Verigakis
                                Q(userid=request.user_uniq) | Q(public=True))
114 d44c236b Giorgos Verigakis
    
115 0269afd6 Giorgos Verigakis
    if since:
116 d44c236b Giorgos Verigakis
        user_networks = user_networks.filter(updated__gte=since)
117 0269afd6 Giorgos Verigakis
        if not user_networks:
118 0269afd6 Giorgos Verigakis
            return HttpResponse(status=304)
119 0269afd6 Giorgos Verigakis
    else:
120 d44c236b Giorgos Verigakis
        user_networks = user_networks.filter(state='ACTIVE')
121 d44c236b Giorgos Verigakis
    
122 4b3b8688 Giorgos Verigakis
    networks = [network_to_dict(network, request.user_uniq, detail)
123 73aed6bf Giorgos Verigakis
                for network in user_networks]
124 73aed6bf Giorgos Verigakis
    
125 0269afd6 Giorgos Verigakis
    if request.serialization == 'xml':
126 b36f78fa Giorgos Verigakis
        data = render_to_string('list_networks.xml', {
127 b36f78fa Giorgos Verigakis
            'networks': networks,
128 b36f78fa Giorgos Verigakis
            'detail': detail})
129 0269afd6 Giorgos Verigakis
    else:
130 0269afd6 Giorgos Verigakis
        data = json.dumps({'networks': {'values': networks}})
131 aa197ee4 Vangelis Koukis
132 0269afd6 Giorgos Verigakis
    return HttpResponse(data, status=200)
133 0269afd6 Giorgos Verigakis
134 6ef51e9f Giorgos Verigakis
135 b36f78fa Giorgos Verigakis
@util.api_method('POST')
136 0269afd6 Giorgos Verigakis
def create_network(request):
137 0269afd6 Giorgos Verigakis
    # Normal Response Code: 202
138 0269afd6 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
139 0269afd6 Giorgos Verigakis
    #                       serviceUnavailable (503),
140 0269afd6 Giorgos Verigakis
    #                       unauthorized (401),
141 13b954b0 Giorgos Verigakis
    #                       badMediaType(415),
142 0269afd6 Giorgos Verigakis
    #                       badRequest (400),
143 0269afd6 Giorgos Verigakis
    #                       overLimit (413)
144 aa197ee4 Vangelis Koukis
145 b36f78fa Giorgos Verigakis
    req = util.get_request_dict(request)
146 9e98ba3c Giorgos Verigakis
    log.debug('create_network %s', req)
147 9e98ba3c Giorgos Verigakis
    
148 0269afd6 Giorgos Verigakis
    try:
149 0269afd6 Giorgos Verigakis
        d = req['network']
150 0269afd6 Giorgos Verigakis
        name = d['name']
151 0269afd6 Giorgos Verigakis
    except (KeyError, ValueError):
152 0269afd6 Giorgos Verigakis
        raise BadRequest('Malformed request.')
153 b36f78fa Giorgos Verigakis
    
154 4b3b8688 Giorgos Verigakis
    network = backend.create_network(name, request.user_uniq)
155 a3992827 Giorgos Verigakis
    if not network:
156 856804af Vangelis Koukis
        raise OverLimit('Network count limit exceeded for your account.')
157 64938cb0 Giorgos Verigakis
    
158 4b3b8688 Giorgos Verigakis
    networkdict = network_to_dict(network, request.user_uniq)
159 0269afd6 Giorgos Verigakis
    return render_network(request, networkdict, status=202)
160 0269afd6 Giorgos Verigakis
161 6ef51e9f Giorgos Verigakis
162 b36f78fa Giorgos Verigakis
@util.api_method('GET')
163 b19653d1 Giorgos Verigakis
def get_network_details(request, network_id):
164 0269afd6 Giorgos Verigakis
    # Normal Response Codes: 200, 203
165 13b954b0 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
166 13b954b0 Giorgos Verigakis
    #                       serviceUnavailable (503),
167 13b954b0 Giorgos Verigakis
    #                       unauthorized (401),
168 13b954b0 Giorgos Verigakis
    #                       badRequest (400),
169 13b954b0 Giorgos Verigakis
    #                       itemNotFound (404),
170 13b954b0 Giorgos Verigakis
    #                       overLimit (413)
171 9e98ba3c Giorgos Verigakis
    
172 9e98ba3c Giorgos Verigakis
    log.debug('get_network_details %s', network_id)
173 4b3b8688 Giorgos Verigakis
    net = util.get_network(network_id, request.user_uniq)
174 4b3b8688 Giorgos Verigakis
    netdict = network_to_dict(net, request.user_uniq)
175 0269afd6 Giorgos Verigakis
    return render_network(request, netdict)
176 0269afd6 Giorgos Verigakis
177 6ef51e9f Giorgos Verigakis
178 b36f78fa Giorgos Verigakis
@util.api_method('PUT')
179 b19653d1 Giorgos Verigakis
def update_network_name(request, network_id):
180 0269afd6 Giorgos Verigakis
    # Normal Response Code: 204
181 13b954b0 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
182 13b954b0 Giorgos Verigakis
    #                       serviceUnavailable (503),
183 13b954b0 Giorgos Verigakis
    #                       unauthorized (401),
184 13b954b0 Giorgos Verigakis
    #                       badRequest (400),
185 13b954b0 Giorgos Verigakis
    #                       badMediaType(415),
186 13b954b0 Giorgos Verigakis
    #                       itemNotFound (404),
187 13b954b0 Giorgos Verigakis
    #                       overLimit (413)
188 aa197ee4 Vangelis Koukis
189 b36f78fa Giorgos Verigakis
    req = util.get_request_dict(request)
190 9e98ba3c Giorgos Verigakis
    log.debug('update_network_name %s', network_id)
191 9e98ba3c Giorgos Verigakis
    
192 0269afd6 Giorgos Verigakis
    try:
193 0269afd6 Giorgos Verigakis
        name = req['network']['name']
194 0269afd6 Giorgos Verigakis
    except (TypeError, KeyError):
195 0269afd6 Giorgos Verigakis
        raise BadRequest('Malformed request.')
196 0269afd6 Giorgos Verigakis
197 4b3b8688 Giorgos Verigakis
    net = util.get_network(network_id, request.user_uniq)
198 207b70d5 Giorgos Verigakis
    if net.public:
199 207b70d5 Giorgos Verigakis
        raise Unauthorized('Can not rename the public network.')
200 0269afd6 Giorgos Verigakis
    net.name = name
201 0269afd6 Giorgos Verigakis
    net.save()
202 0269afd6 Giorgos Verigakis
    return HttpResponse(status=204)
203 0269afd6 Giorgos Verigakis
204 6ef51e9f Giorgos Verigakis
205 b36f78fa Giorgos Verigakis
@util.api_method('DELETE')
206 b19653d1 Giorgos Verigakis
def delete_network(request, network_id):
207 0269afd6 Giorgos Verigakis
    # Normal Response Code: 204
208 13b954b0 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
209 13b954b0 Giorgos Verigakis
    #                       serviceUnavailable (503),
210 13b954b0 Giorgos Verigakis
    #                       unauthorized (401),
211 13b954b0 Giorgos Verigakis
    #                       itemNotFound (404),
212 13b954b0 Giorgos Verigakis
    #                       unauthorized (401),
213 13b954b0 Giorgos Verigakis
    #                       overLimit (413)
214 d44c236b Giorgos Verigakis
    
215 9e98ba3c Giorgos Verigakis
    log.debug('delete_network %s', network_id)
216 4b3b8688 Giorgos Verigakis
    net = util.get_network(network_id, request.user_uniq)
217 207b70d5 Giorgos Verigakis
    if net.public:
218 207b70d5 Giorgos Verigakis
        raise Unauthorized('Can not delete the public network.')
219 64938cb0 Giorgos Verigakis
    backend.delete_network(net)
220 0269afd6 Giorgos Verigakis
    return HttpResponse(status=204)
221 0269afd6 Giorgos Verigakis
222 6ef51e9f Giorgos Verigakis
223 b36f78fa Giorgos Verigakis
@util.api_method('POST')
224 b19653d1 Giorgos Verigakis
def network_action(request, network_id):
225 9e98ba3c Giorgos Verigakis
    req = util.get_request_dict(request)
226 9e98ba3c Giorgos Verigakis
    log.debug('network_action %s %s', network_id, req)
227 9e98ba3c Giorgos Verigakis
    if len(req) != 1:
228 9e98ba3c Giorgos Verigakis
        raise BadRequest('Malformed request.')
229 9e98ba3c Giorgos Verigakis
    
230 4b3b8688 Giorgos Verigakis
    net = util.get_network(network_id, request.user_uniq)
231 207b70d5 Giorgos Verigakis
    if net.public:
232 207b70d5 Giorgos Verigakis
        raise Unauthorized('Can not modify the public network.')
233 207b70d5 Giorgos Verigakis
    
234 0269afd6 Giorgos Verigakis
    key = req.keys()[0]
235 0269afd6 Giorgos Verigakis
    val = req[key]
236 aa197ee4 Vangelis Koukis
237 0269afd6 Giorgos Verigakis
    try:
238 0269afd6 Giorgos Verigakis
        assert isinstance(val, dict)
239 0269afd6 Giorgos Verigakis
        return network_actions[key](request, net, req[key])
240 0269afd6 Giorgos Verigakis
    except KeyError:
241 0269afd6 Giorgos Verigakis
        raise BadRequest('Unknown action.')
242 0269afd6 Giorgos Verigakis
    except AssertionError:
243 0269afd6 Giorgos Verigakis
        raise BadRequest('Invalid argument.')