Statistics
| Branch: | Tag: | Revision:

root / api / networks.py @ f4fe8796

History | View | Annotate | Download (7.9 kB)

1 adee02b8 Giorgos Verigakis
# Copyright 2011 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 0269afd6 Giorgos Verigakis
from django.conf.urls.defaults import patterns
35 d44c236b Giorgos Verigakis
from django.db.models import Q
36 0269afd6 Giorgos Verigakis
from django.http import HttpResponse
37 69d6d7dd Giorgos Verigakis
from django.template.loader import render_to_string
38 0269afd6 Giorgos Verigakis
from django.utils import simplejson as json
39 0269afd6 Giorgos Verigakis
40 b36f78fa Giorgos Verigakis
from synnefo.api import util
41 b36f78fa Giorgos Verigakis
from synnefo.api.actions import network_actions
42 b36f78fa Giorgos Verigakis
from synnefo.api.common import method_not_allowed
43 b36f78fa Giorgos Verigakis
from synnefo.api.faults import BadRequest, OverLimit, Unauthorized
44 b36f78fa Giorgos Verigakis
from synnefo.db.models import Network
45 b36f78fa Giorgos Verigakis
from synnefo.logic import backend
46 b36f78fa Giorgos Verigakis
47 0269afd6 Giorgos Verigakis
48 0269afd6 Giorgos Verigakis
urlpatterns = patterns('synnefo.api.networks',
49 0269afd6 Giorgos Verigakis
    (r'^(?:/|.json|.xml)?$', 'demux'),
50 0269afd6 Giorgos Verigakis
    (r'^/detail(?:.json|.xml)?$', 'list_networks', {'detail': True}),
51 f4fe8796 Giorgos Verigakis
    (r'^/(\w+)(?:.json|.xml)?$', 'network_demux'),
52 f4fe8796 Giorgos Verigakis
    (r'^/(\w+)/action(?:.json|.xml)?$', 'network_action'),
53 0269afd6 Giorgos Verigakis
)
54 0269afd6 Giorgos Verigakis
55 0269afd6 Giorgos Verigakis
56 0269afd6 Giorgos Verigakis
def demux(request):
57 0269afd6 Giorgos Verigakis
    if request.method == 'GET':
58 0269afd6 Giorgos Verigakis
        return list_networks(request)
59 0269afd6 Giorgos Verigakis
    elif request.method == 'POST':
60 0269afd6 Giorgos Verigakis
        return create_network(request)
61 0269afd6 Giorgos Verigakis
    else:
62 0269afd6 Giorgos Verigakis
        return method_not_allowed(request)
63 0269afd6 Giorgos Verigakis
64 b19653d1 Giorgos Verigakis
def network_demux(request, network_id):
65 0269afd6 Giorgos Verigakis
    if request.method == 'GET':
66 b19653d1 Giorgos Verigakis
        return get_network_details(request, network_id)
67 0269afd6 Giorgos Verigakis
    elif request.method == 'PUT':
68 b19653d1 Giorgos Verigakis
        return update_network_name(request, network_id)
69 0269afd6 Giorgos Verigakis
    elif request.method == 'DELETE':
70 b19653d1 Giorgos Verigakis
        return delete_network(request, network_id)
71 0269afd6 Giorgos Verigakis
    else:
72 0269afd6 Giorgos Verigakis
        return method_not_allowed(request)
73 0269afd6 Giorgos Verigakis
74 0269afd6 Giorgos Verigakis
75 0269afd6 Giorgos Verigakis
def network_to_dict(network, detail=True):
76 207b70d5 Giorgos Verigakis
    network_id = str(network.id) if not network.public else 'public'
77 207b70d5 Giorgos Verigakis
    d = {'id': network_id, 'name': network.name}
78 0269afd6 Giorgos Verigakis
    if detail:
79 b36f78fa Giorgos Verigakis
        d['updated'] = util.isoformat(network.updated)
80 b36f78fa Giorgos Verigakis
        d['created'] = util.isoformat(network.created)
81 0269afd6 Giorgos Verigakis
        d['servers'] = {'values': [vm.id for vm in network.machines.all()]}
82 d44c236b Giorgos Verigakis
        d['status'] = network.state
83 0269afd6 Giorgos Verigakis
    return d
84 0269afd6 Giorgos Verigakis
85 0269afd6 Giorgos Verigakis
def render_network(request, networkdict, status=200):
86 0269afd6 Giorgos Verigakis
    if request.serialization == 'xml':
87 0269afd6 Giorgos Verigakis
        data = render_to_string('network.xml', {'network': networkdict})
88 0269afd6 Giorgos Verigakis
    else:
89 0269afd6 Giorgos Verigakis
        data = json.dumps({'network': networkdict})
90 0269afd6 Giorgos Verigakis
    return HttpResponse(data, status=status)
91 0269afd6 Giorgos Verigakis
92 0269afd6 Giorgos Verigakis
93 b36f78fa Giorgos Verigakis
@util.api_method('GET')
94 0269afd6 Giorgos Verigakis
def list_networks(request, detail=False):
95 0269afd6 Giorgos Verigakis
    # Normal Response Codes: 200, 203
96 0269afd6 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
97 0269afd6 Giorgos Verigakis
    #                       serviceUnavailable (503),
98 0269afd6 Giorgos Verigakis
    #                       unauthorized (401),
99 0269afd6 Giorgos Verigakis
    #                       badRequest (400),
100 0269afd6 Giorgos Verigakis
    #                       overLimit (413)
101 d44c236b Giorgos Verigakis
    
102 d44c236b Giorgos Verigakis
    owner = request.user
103 b36f78fa Giorgos Verigakis
    since = util.isoparse(request.GET.get('changes-since'))
104 d44c236b Giorgos Verigakis
    user_networks = Network.objects.filter(Q(owner=owner) | Q(public=True))
105 d44c236b Giorgos Verigakis
    
106 0269afd6 Giorgos Verigakis
    if since:
107 d44c236b Giorgos Verigakis
        user_networks = user_networks.filter(updated__gte=since)
108 0269afd6 Giorgos Verigakis
        if not user_networks:
109 0269afd6 Giorgos Verigakis
            return HttpResponse(status=304)
110 0269afd6 Giorgos Verigakis
    else:
111 d44c236b Giorgos Verigakis
        user_networks = user_networks.filter(state='ACTIVE')
112 d44c236b Giorgos Verigakis
    
113 0269afd6 Giorgos Verigakis
    networks = [network_to_dict(network, detail) for network in user_networks]
114 aa197ee4 Vangelis Koukis
115 0269afd6 Giorgos Verigakis
    if request.serialization == 'xml':
116 b36f78fa Giorgos Verigakis
        data = render_to_string('list_networks.xml', {
117 b36f78fa Giorgos Verigakis
            'networks': networks,
118 b36f78fa Giorgos Verigakis
            'detail': detail})
119 0269afd6 Giorgos Verigakis
    else:
120 0269afd6 Giorgos Verigakis
        data = json.dumps({'networks': {'values': networks}})
121 aa197ee4 Vangelis Koukis
122 0269afd6 Giorgos Verigakis
    return HttpResponse(data, status=200)
123 0269afd6 Giorgos Verigakis
124 b36f78fa Giorgos Verigakis
@util.api_method('POST')
125 0269afd6 Giorgos Verigakis
def create_network(request):
126 0269afd6 Giorgos Verigakis
    # Normal Response Code: 202
127 0269afd6 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
128 0269afd6 Giorgos Verigakis
    #                       serviceUnavailable (503),
129 0269afd6 Giorgos Verigakis
    #                       unauthorized (401),
130 13b954b0 Giorgos Verigakis
    #                       badMediaType(415),
131 0269afd6 Giorgos Verigakis
    #                       badRequest (400),
132 0269afd6 Giorgos Verigakis
    #                       overLimit (413)
133 aa197ee4 Vangelis Koukis
134 b36f78fa Giorgos Verigakis
    req = util.get_request_dict(request)
135 aa197ee4 Vangelis Koukis
136 0269afd6 Giorgos Verigakis
    try:
137 0269afd6 Giorgos Verigakis
        d = req['network']
138 0269afd6 Giorgos Verigakis
        name = d['name']
139 0269afd6 Giorgos Verigakis
    except (KeyError, ValueError):
140 0269afd6 Giorgos Verigakis
        raise BadRequest('Malformed request.')
141 b36f78fa Giorgos Verigakis
    
142 a3992827 Giorgos Verigakis
    network = backend.create_network(name, request.user)
143 a3992827 Giorgos Verigakis
    if not network:
144 64938cb0 Giorgos Verigakis
        raise OverLimit('Maximum number of networks reached.')
145 64938cb0 Giorgos Verigakis
    
146 0269afd6 Giorgos Verigakis
    networkdict = network_to_dict(network)
147 0269afd6 Giorgos Verigakis
    return render_network(request, networkdict, status=202)
148 0269afd6 Giorgos Verigakis
149 b36f78fa Giorgos Verigakis
@util.api_method('GET')
150 b19653d1 Giorgos Verigakis
def get_network_details(request, network_id):
151 0269afd6 Giorgos Verigakis
    # Normal Response Codes: 200, 203
152 13b954b0 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
153 13b954b0 Giorgos Verigakis
    #                       serviceUnavailable (503),
154 13b954b0 Giorgos Verigakis
    #                       unauthorized (401),
155 13b954b0 Giorgos Verigakis
    #                       badRequest (400),
156 13b954b0 Giorgos Verigakis
    #                       itemNotFound (404),
157 13b954b0 Giorgos Verigakis
    #                       overLimit (413)
158 aa197ee4 Vangelis Koukis
159 b36f78fa Giorgos Verigakis
    net = util.get_network(network_id, request.user)
160 0269afd6 Giorgos Verigakis
    netdict = network_to_dict(net)
161 0269afd6 Giorgos Verigakis
    return render_network(request, netdict)
162 0269afd6 Giorgos Verigakis
163 b36f78fa Giorgos Verigakis
@util.api_method('PUT')
164 b19653d1 Giorgos Verigakis
def update_network_name(request, network_id):
165 0269afd6 Giorgos Verigakis
    # Normal Response Code: 204
166 13b954b0 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
167 13b954b0 Giorgos Verigakis
    #                       serviceUnavailable (503),
168 13b954b0 Giorgos Verigakis
    #                       unauthorized (401),
169 13b954b0 Giorgos Verigakis
    #                       badRequest (400),
170 13b954b0 Giorgos Verigakis
    #                       badMediaType(415),
171 13b954b0 Giorgos Verigakis
    #                       itemNotFound (404),
172 13b954b0 Giorgos Verigakis
    #                       overLimit (413)
173 aa197ee4 Vangelis Koukis
174 b36f78fa Giorgos Verigakis
    req = util.get_request_dict(request)
175 0269afd6 Giorgos Verigakis
176 0269afd6 Giorgos Verigakis
    try:
177 0269afd6 Giorgos Verigakis
        name = req['network']['name']
178 0269afd6 Giorgos Verigakis
    except (TypeError, KeyError):
179 0269afd6 Giorgos Verigakis
        raise BadRequest('Malformed request.')
180 0269afd6 Giorgos Verigakis
181 b36f78fa Giorgos Verigakis
    net = util.get_network(network_id, request.user)
182 207b70d5 Giorgos Verigakis
    if net.public:
183 207b70d5 Giorgos Verigakis
        raise Unauthorized('Can not rename the public network.')
184 0269afd6 Giorgos Verigakis
    net.name = name
185 0269afd6 Giorgos Verigakis
    net.save()
186 0269afd6 Giorgos Verigakis
    return HttpResponse(status=204)
187 0269afd6 Giorgos Verigakis
188 b36f78fa Giorgos Verigakis
@util.api_method('DELETE')
189 b19653d1 Giorgos Verigakis
def delete_network(request, network_id):
190 0269afd6 Giorgos Verigakis
    # Normal Response Code: 204
191 13b954b0 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
192 13b954b0 Giorgos Verigakis
    #                       serviceUnavailable (503),
193 13b954b0 Giorgos Verigakis
    #                       unauthorized (401),
194 13b954b0 Giorgos Verigakis
    #                       itemNotFound (404),
195 13b954b0 Giorgos Verigakis
    #                       unauthorized (401),
196 13b954b0 Giorgos Verigakis
    #                       overLimit (413)
197 d44c236b Giorgos Verigakis
    
198 b36f78fa Giorgos Verigakis
    net = util.get_network(network_id, request.user)
199 207b70d5 Giorgos Verigakis
    if net.public:
200 207b70d5 Giorgos Verigakis
        raise Unauthorized('Can not delete the public network.')
201 64938cb0 Giorgos Verigakis
    backend.delete_network(net)
202 0269afd6 Giorgos Verigakis
    return HttpResponse(status=204)
203 0269afd6 Giorgos Verigakis
204 b36f78fa Giorgos Verigakis
@util.api_method('POST')
205 b19653d1 Giorgos Verigakis
def network_action(request, network_id):
206 b36f78fa Giorgos Verigakis
    net = util.get_network(network_id, request.user)
207 207b70d5 Giorgos Verigakis
    if net.public:
208 207b70d5 Giorgos Verigakis
        raise Unauthorized('Can not modify the public network.')
209 207b70d5 Giorgos Verigakis
    
210 b36f78fa Giorgos Verigakis
    req = util.get_request_dict(request)
211 0269afd6 Giorgos Verigakis
    if len(req) != 1:
212 0269afd6 Giorgos Verigakis
        raise BadRequest('Malformed request.')
213 aa197ee4 Vangelis Koukis
214 0269afd6 Giorgos Verigakis
    key = req.keys()[0]
215 0269afd6 Giorgos Verigakis
    val = req[key]
216 aa197ee4 Vangelis Koukis
217 0269afd6 Giorgos Verigakis
    try:
218 0269afd6 Giorgos Verigakis
        assert isinstance(val, dict)
219 0269afd6 Giorgos Verigakis
        return network_actions[key](request, net, req[key])
220 0269afd6 Giorgos Verigakis
    except KeyError:
221 0269afd6 Giorgos Verigakis
        raise BadRequest('Unknown action.')
222 0269afd6 Giorgos Verigakis
    except AssertionError:
223 0269afd6 Giorgos Verigakis
        raise BadRequest('Invalid argument.')