Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / api / networks.py @ 6dd70a5c

History | View | Annotate | Download (9.6 kB)

1 6ef51e9f Giorgos Verigakis
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2 ce55f211 Kostas Papadimitriou
#
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 ce55f211 Kostas Papadimitriou
#
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 ce55f211 Kostas Papadimitriou
#
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 ce55f211 Kostas Papadimitriou
#
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 ce55f211 Kostas Papadimitriou
#
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 ce55f211 Kostas Papadimitriou
from django.conf import settings
38 d44c236b Giorgos Verigakis
from django.db.models import Q
39 0269afd6 Giorgos Verigakis
from django.http import HttpResponse
40 69d6d7dd Giorgos Verigakis
from django.template.loader import render_to_string
41 0269afd6 Giorgos Verigakis
from django.utils import simplejson as json
42 0269afd6 Giorgos Verigakis
43 5061546f Christos Stavrakakis
from synnefo.api import util
44 b36f78fa Giorgos Verigakis
from synnefo.api.actions import network_actions
45 b36f78fa Giorgos Verigakis
from synnefo.api.common import method_not_allowed
46 6dd70a5c Christos Stavrakakis
from synnefo.api.faults import (BadRequest, Unauthorized,
47 6dd70a5c Christos Stavrakakis
                                NetworkInUse)
48 6dd70a5c Christos Stavrakakis
from synnefo.db.models import Network
49 b36f78fa Giorgos Verigakis
from synnefo.logic import backend
50 9e98ba3c Giorgos Verigakis
51 9e98ba3c Giorgos Verigakis
52 9e98ba3c Giorgos Verigakis
log = getLogger('synnefo.api')
53 b36f78fa Giorgos Verigakis
54 0269afd6 Giorgos Verigakis
urlpatterns = patterns('synnefo.api.networks',
55 0269afd6 Giorgos Verigakis
    (r'^(?:/|.json|.xml)?$', 'demux'),
56 0269afd6 Giorgos Verigakis
    (r'^/detail(?:.json|.xml)?$', 'list_networks', {'detail': True}),
57 f4fe8796 Giorgos Verigakis
    (r'^/(\w+)(?:.json|.xml)?$', 'network_demux'),
58 f4fe8796 Giorgos Verigakis
    (r'^/(\w+)/action(?:.json|.xml)?$', 'network_action'),
59 0269afd6 Giorgos Verigakis
)
60 0269afd6 Giorgos Verigakis
61 0269afd6 Giorgos Verigakis
62 0269afd6 Giorgos Verigakis
def demux(request):
63 0269afd6 Giorgos Verigakis
    if request.method == 'GET':
64 0269afd6 Giorgos Verigakis
        return list_networks(request)
65 0269afd6 Giorgos Verigakis
    elif request.method == 'POST':
66 0269afd6 Giorgos Verigakis
        return create_network(request)
67 0269afd6 Giorgos Verigakis
    else:
68 0269afd6 Giorgos Verigakis
        return method_not_allowed(request)
69 0269afd6 Giorgos Verigakis
70 6ef51e9f Giorgos Verigakis
71 b19653d1 Giorgos Verigakis
def network_demux(request, network_id):
72 0269afd6 Giorgos Verigakis
    if request.method == 'GET':
73 b19653d1 Giorgos Verigakis
        return get_network_details(request, network_id)
74 0269afd6 Giorgos Verigakis
    elif request.method == 'PUT':
75 b19653d1 Giorgos Verigakis
        return update_network_name(request, network_id)
76 0269afd6 Giorgos Verigakis
    elif request.method == 'DELETE':
77 b19653d1 Giorgos Verigakis
        return delete_network(request, network_id)
78 0269afd6 Giorgos Verigakis
    else:
79 0269afd6 Giorgos Verigakis
        return method_not_allowed(request)
80 0269afd6 Giorgos Verigakis
81 0269afd6 Giorgos Verigakis
82 6ef51e9f Giorgos Verigakis
def network_to_dict(network, user_id, detail=True):
83 207b70d5 Giorgos Verigakis
    network_id = str(network.id) if not network.public else 'public'
84 207b70d5 Giorgos Verigakis
    d = {'id': network_id, 'name': network.name}
85 0269afd6 Giorgos Verigakis
    if detail:
86 08b079e2 Stavros Sachtouris
        d['cidr'] = network.subnet
87 cc3f266e Christos Stavrakakis
        d['cidr6'] = network.subnet6
88 08b079e2 Stavros Sachtouris
        d['gateway'] = network.gateway
89 cc3f266e Christos Stavrakakis
        d['gateway6'] = network.gateway6
90 08b079e2 Stavros Sachtouris
        d['dhcp'] = network.dhcp
91 08b079e2 Stavros Sachtouris
        d['type'] = network.type
92 b36f78fa Giorgos Verigakis
        d['updated'] = util.isoformat(network.updated)
93 b36f78fa Giorgos Verigakis
        d['created'] = util.isoformat(network.created)
94 d44c236b Giorgos Verigakis
        d['status'] = network.state
95 08b079e2 Stavros Sachtouris
96 08b079e2 Stavros Sachtouris
        attachments = [util.construct_nic_id(nic) for nic in network.nics.filter(machine__userid= user_id)]
97 08b079e2 Stavros Sachtouris
        d['attachments'] = {'values':attachments}
98 0269afd6 Giorgos Verigakis
    return d
99 0269afd6 Giorgos Verigakis
100 6ef51e9f Giorgos Verigakis
101 0269afd6 Giorgos Verigakis
def render_network(request, networkdict, status=200):
102 0269afd6 Giorgos Verigakis
    if request.serialization == 'xml':
103 0269afd6 Giorgos Verigakis
        data = render_to_string('network.xml', {'network': networkdict})
104 0269afd6 Giorgos Verigakis
    else:
105 0269afd6 Giorgos Verigakis
        data = json.dumps({'network': networkdict})
106 0269afd6 Giorgos Verigakis
    return HttpResponse(data, status=status)
107 0269afd6 Giorgos Verigakis
108 0269afd6 Giorgos Verigakis
109 b36f78fa Giorgos Verigakis
@util.api_method('GET')
110 0269afd6 Giorgos Verigakis
def list_networks(request, detail=False):
111 0269afd6 Giorgos Verigakis
    # Normal Response Codes: 200, 203
112 0269afd6 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
113 0269afd6 Giorgos Verigakis
    #                       serviceUnavailable (503),
114 0269afd6 Giorgos Verigakis
    #                       unauthorized (401),
115 0269afd6 Giorgos Verigakis
    #                       badRequest (400),
116 0269afd6 Giorgos Verigakis
    #                       overLimit (413)
117 ce55f211 Kostas Papadimitriou
118 9e98ba3c Giorgos Verigakis
    log.debug('list_networks detail=%s', detail)
119 b36f78fa Giorgos Verigakis
    since = util.isoparse(request.GET.get('changes-since'))
120 8b2515a9 Christos Stavrakakis
    user_networks = Network.objects.filter(Q(userid=request.user_uniq) |
121 8b2515a9 Christos Stavrakakis
                                           Q(public=True),
122 8b2515a9 Christos Stavrakakis
                                           deleted=False)
123 ce55f211 Kostas Papadimitriou
124 0269afd6 Giorgos Verigakis
    if since:
125 d44c236b Giorgos Verigakis
        user_networks = user_networks.filter(updated__gte=since)
126 0269afd6 Giorgos Verigakis
        if not user_networks:
127 0269afd6 Giorgos Verigakis
            return HttpResponse(status=304)
128 ce55f211 Kostas Papadimitriou
129 4b3b8688 Giorgos Verigakis
    networks = [network_to_dict(network, request.user_uniq, detail)
130 73aed6bf Giorgos Verigakis
                for network in user_networks]
131 ce55f211 Kostas Papadimitriou
132 0269afd6 Giorgos Verigakis
    if request.serialization == 'xml':
133 b36f78fa Giorgos Verigakis
        data = render_to_string('list_networks.xml', {
134 b36f78fa Giorgos Verigakis
            'networks': networks,
135 b36f78fa Giorgos Verigakis
            'detail': detail})
136 0269afd6 Giorgos Verigakis
    else:
137 0269afd6 Giorgos Verigakis
        data = json.dumps({'networks': {'values': networks}})
138 aa197ee4 Vangelis Koukis
139 0269afd6 Giorgos Verigakis
    return HttpResponse(data, status=200)
140 0269afd6 Giorgos Verigakis
141 6ef51e9f Giorgos Verigakis
142 b36f78fa Giorgos Verigakis
@util.api_method('POST')
143 0269afd6 Giorgos Verigakis
def create_network(request):
144 0269afd6 Giorgos Verigakis
    # Normal Response Code: 202
145 0269afd6 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
146 0269afd6 Giorgos Verigakis
    #                       serviceUnavailable (503),
147 0269afd6 Giorgos Verigakis
    #                       unauthorized (401),
148 13b954b0 Giorgos Verigakis
    #                       badMediaType(415),
149 0269afd6 Giorgos Verigakis
    #                       badRequest (400),
150 0269afd6 Giorgos Verigakis
    #                       overLimit (413)
151 aa197ee4 Vangelis Koukis
152 b36f78fa Giorgos Verigakis
    req = util.get_request_dict(request)
153 9e98ba3c Giorgos Verigakis
    log.debug('create_network %s', req)
154 ce55f211 Kostas Papadimitriou
155 0269afd6 Giorgos Verigakis
    try:
156 0269afd6 Giorgos Verigakis
        d = req['network']
157 0269afd6 Giorgos Verigakis
        name = d['name']
158 5061546f Christos Stavrakakis
        # TODO: Fix this temp values:
159 b9a0b3d5 Stavros Sachtouris
        subnet = d.get('cidr', '192.168.1.0/24')
160 cc3f266e Christos Stavrakakis
        subnet6 = d.get('cidr6', None)
161 5061546f Christos Stavrakakis
        gateway = d.get('gateway', None)
162 cc3f266e Christos Stavrakakis
        gateway6 = d.get('gateway6', None)
163 839e2bd0 Christos Stavrakakis
        type = d.get('type', 'PRIVATE_MAC_FILTERED')
164 5061546f Christos Stavrakakis
        dhcp = d.get('dhcp', True)
165 0269afd6 Giorgos Verigakis
    except (KeyError, ValueError):
166 0269afd6 Giorgos Verigakis
        raise BadRequest('Malformed request.')
167 ce55f211 Kostas Papadimitriou
168 5061546f Christos Stavrakakis
    if type == 'PUBLIC_ROUTED':
169 87994836 Christos Stavrakakis
        raise Unauthorized('Can not create a public network.')
170 87994836 Christos Stavrakakis
171 6dd70a5c Christos Stavrakakis
172 6dd70a5c Christos Stavrakakis
    link, mac_prefix = util.network_specs_from_type(type)
173 6dd70a5c Christos Stavrakakis
    if not link:
174 6dd70a5c Christos Stavrakakis
        raise Exception("Can not create network. No connectivity link.")
175 5061546f Christos Stavrakakis
176 5061546f Christos Stavrakakis
    network = Network.objects.create(
177 5061546f Christos Stavrakakis
            name=name,
178 5061546f Christos Stavrakakis
            userid=request.user_uniq,
179 5061546f Christos Stavrakakis
            subnet=subnet,
180 cc3f266e Christos Stavrakakis
            subnet6=subnet6,
181 5061546f Christos Stavrakakis
            gateway=gateway,
182 cc3f266e Christos Stavrakakis
            gateway6=gateway6,
183 5061546f Christos Stavrakakis
            dhcp=dhcp,
184 5061546f Christos Stavrakakis
            type=type,
185 5061546f Christos Stavrakakis
            link=link,
186 5061546f Christos Stavrakakis
            mac_prefix=mac_prefix,
187 87994836 Christos Stavrakakis
            state='PENDING')
188 5061546f Christos Stavrakakis
189 87994836 Christos Stavrakakis
    backend.create_network(network)
190 ce55f211 Kostas Papadimitriou
191 4b3b8688 Giorgos Verigakis
    networkdict = network_to_dict(network, request.user_uniq)
192 0269afd6 Giorgos Verigakis
    return render_network(request, networkdict, status=202)
193 0269afd6 Giorgos Verigakis
194 6ef51e9f Giorgos Verigakis
195 b36f78fa Giorgos Verigakis
@util.api_method('GET')
196 b19653d1 Giorgos Verigakis
def get_network_details(request, network_id):
197 0269afd6 Giorgos Verigakis
    # Normal Response Codes: 200, 203
198 13b954b0 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
199 13b954b0 Giorgos Verigakis
    #                       serviceUnavailable (503),
200 13b954b0 Giorgos Verigakis
    #                       unauthorized (401),
201 13b954b0 Giorgos Verigakis
    #                       badRequest (400),
202 13b954b0 Giorgos Verigakis
    #                       itemNotFound (404),
203 13b954b0 Giorgos Verigakis
    #                       overLimit (413)
204 ce55f211 Kostas Papadimitriou
205 9e98ba3c Giorgos Verigakis
    log.debug('get_network_details %s', network_id)
206 4b3b8688 Giorgos Verigakis
    net = util.get_network(network_id, request.user_uniq)
207 4b3b8688 Giorgos Verigakis
    netdict = network_to_dict(net, request.user_uniq)
208 0269afd6 Giorgos Verigakis
    return render_network(request, netdict)
209 0269afd6 Giorgos Verigakis
210 6ef51e9f Giorgos Verigakis
211 b36f78fa Giorgos Verigakis
@util.api_method('PUT')
212 b19653d1 Giorgos Verigakis
def update_network_name(request, network_id):
213 0269afd6 Giorgos Verigakis
    # Normal Response Code: 204
214 13b954b0 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
215 13b954b0 Giorgos Verigakis
    #                       serviceUnavailable (503),
216 13b954b0 Giorgos Verigakis
    #                       unauthorized (401),
217 13b954b0 Giorgos Verigakis
    #                       badRequest (400),
218 13b954b0 Giorgos Verigakis
    #                       badMediaType(415),
219 13b954b0 Giorgos Verigakis
    #                       itemNotFound (404),
220 13b954b0 Giorgos Verigakis
    #                       overLimit (413)
221 aa197ee4 Vangelis Koukis
222 b36f78fa Giorgos Verigakis
    req = util.get_request_dict(request)
223 9e98ba3c Giorgos Verigakis
    log.debug('update_network_name %s', network_id)
224 ce55f211 Kostas Papadimitriou
225 0269afd6 Giorgos Verigakis
    try:
226 0269afd6 Giorgos Verigakis
        name = req['network']['name']
227 0269afd6 Giorgos Verigakis
    except (TypeError, KeyError):
228 0269afd6 Giorgos Verigakis
        raise BadRequest('Malformed request.')
229 0269afd6 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 rename the public network.')
233 0269afd6 Giorgos Verigakis
    net.name = name
234 0269afd6 Giorgos Verigakis
    net.save()
235 0269afd6 Giorgos Verigakis
    return HttpResponse(status=204)
236 0269afd6 Giorgos Verigakis
237 6ef51e9f Giorgos Verigakis
238 b36f78fa Giorgos Verigakis
@util.api_method('DELETE')
239 b19653d1 Giorgos Verigakis
def delete_network(request, network_id):
240 0269afd6 Giorgos Verigakis
    # Normal Response Code: 204
241 13b954b0 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
242 13b954b0 Giorgos Verigakis
    #                       serviceUnavailable (503),
243 13b954b0 Giorgos Verigakis
    #                       unauthorized (401),
244 13b954b0 Giorgos Verigakis
    #                       itemNotFound (404),
245 13b954b0 Giorgos Verigakis
    #                       unauthorized (401),
246 13b954b0 Giorgos Verigakis
    #                       overLimit (413)
247 ce55f211 Kostas Papadimitriou
248 9e98ba3c Giorgos Verigakis
    log.debug('delete_network %s', network_id)
249 4b3b8688 Giorgos Verigakis
    net = util.get_network(network_id, request.user_uniq)
250 207b70d5 Giorgos Verigakis
    if net.public:
251 207b70d5 Giorgos Verigakis
        raise Unauthorized('Can not delete the public network.')
252 5061546f Christos Stavrakakis
253 0196d9a3 Christos Stavrakakis
    if net.machines.all():  # Nics attached on network
254 0196d9a3 Christos Stavrakakis
        raise NetworkInUse('Machines are connected to network.')
255 0196d9a3 Christos Stavrakakis
256 5061546f Christos Stavrakakis
    net.action = 'DESTROY'
257 5061546f Christos Stavrakakis
    net.save()
258 5061546f Christos Stavrakakis
259 64938cb0 Giorgos Verigakis
    backend.delete_network(net)
260 0269afd6 Giorgos Verigakis
    return HttpResponse(status=204)
261 0269afd6 Giorgos Verigakis
262 6ef51e9f Giorgos Verigakis
263 b36f78fa Giorgos Verigakis
@util.api_method('POST')
264 b19653d1 Giorgos Verigakis
def network_action(request, network_id):
265 9e98ba3c Giorgos Verigakis
    req = util.get_request_dict(request)
266 9e98ba3c Giorgos Verigakis
    log.debug('network_action %s %s', network_id, req)
267 9e98ba3c Giorgos Verigakis
    if len(req) != 1:
268 9e98ba3c Giorgos Verigakis
        raise BadRequest('Malformed request.')
269 ce55f211 Kostas Papadimitriou
270 4b3b8688 Giorgos Verigakis
    net = util.get_network(network_id, request.user_uniq)
271 207b70d5 Giorgos Verigakis
    if net.public:
272 207b70d5 Giorgos Verigakis
        raise Unauthorized('Can not modify the public network.')
273 ce55f211 Kostas Papadimitriou
274 0269afd6 Giorgos Verigakis
    key = req.keys()[0]
275 0269afd6 Giorgos Verigakis
    val = req[key]
276 aa197ee4 Vangelis Koukis
277 0269afd6 Giorgos Verigakis
    try:
278 0269afd6 Giorgos Verigakis
        assert isinstance(val, dict)
279 0269afd6 Giorgos Verigakis
        return network_actions[key](request, net, req[key])
280 0269afd6 Giorgos Verigakis
    except KeyError:
281 0269afd6 Giorgos Verigakis
        raise BadRequest('Unknown action.')
282 0269afd6 Giorgos Verigakis
    except AssertionError:
283 0269afd6 Giorgos Verigakis
        raise BadRequest('Invalid argument.')