Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (9.5 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 import settings
44 5061546f Christos Stavrakakis
from synnefo.api import util
45 b36f78fa Giorgos Verigakis
from synnefo.api.actions import network_actions
46 b36f78fa Giorgos Verigakis
from synnefo.api.common import method_not_allowed
47 b36f78fa Giorgos Verigakis
from synnefo.api.faults import BadRequest, OverLimit, Unauthorized
48 87994836 Christos Stavrakakis
from synnefo.db.models import Network, Pool, BridgePool, MacPrefixPool
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 08b079e2 Stavros Sachtouris
        d['gateway'] = network.gateway
88 08b079e2 Stavros Sachtouris
        d['dhcp'] = network.dhcp
89 08b079e2 Stavros Sachtouris
        d['type'] = network.type
90 b36f78fa Giorgos Verigakis
        d['updated'] = util.isoformat(network.updated)
91 b36f78fa Giorgos Verigakis
        d['created'] = util.isoformat(network.created)
92 d44c236b Giorgos Verigakis
        d['status'] = network.state
93 08b079e2 Stavros Sachtouris
94 08b079e2 Stavros Sachtouris
        attachments = [util.construct_nic_id(nic) for nic in network.nics.filter(machine__userid= user_id)]
95 08b079e2 Stavros Sachtouris
        d['attachments'] = {'values':attachments}
96 0269afd6 Giorgos Verigakis
    return d
97 0269afd6 Giorgos Verigakis
98 6ef51e9f Giorgos Verigakis
99 0269afd6 Giorgos Verigakis
def render_network(request, networkdict, status=200):
100 0269afd6 Giorgos Verigakis
    if request.serialization == 'xml':
101 0269afd6 Giorgos Verigakis
        data = render_to_string('network.xml', {'network': networkdict})
102 0269afd6 Giorgos Verigakis
    else:
103 0269afd6 Giorgos Verigakis
        data = json.dumps({'network': networkdict})
104 0269afd6 Giorgos Verigakis
    return HttpResponse(data, status=status)
105 0269afd6 Giorgos Verigakis
106 0269afd6 Giorgos Verigakis
107 b36f78fa Giorgos Verigakis
@util.api_method('GET')
108 0269afd6 Giorgos Verigakis
def list_networks(request, detail=False):
109 0269afd6 Giorgos Verigakis
    # Normal Response Codes: 200, 203
110 0269afd6 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
111 0269afd6 Giorgos Verigakis
    #                       serviceUnavailable (503),
112 0269afd6 Giorgos Verigakis
    #                       unauthorized (401),
113 0269afd6 Giorgos Verigakis
    #                       badRequest (400),
114 0269afd6 Giorgos Verigakis
    #                       overLimit (413)
115 ce55f211 Kostas Papadimitriou
116 9e98ba3c Giorgos Verigakis
    log.debug('list_networks detail=%s', detail)
117 b36f78fa Giorgos Verigakis
    since = util.isoparse(request.GET.get('changes-since'))
118 6ef51e9f Giorgos Verigakis
    user_networks = Network.objects.filter(
119 4b3b8688 Giorgos Verigakis
                                Q(userid=request.user_uniq) | Q(public=True))
120 ce55f211 Kostas Papadimitriou
121 0269afd6 Giorgos Verigakis
    if since:
122 d44c236b Giorgos Verigakis
        user_networks = user_networks.filter(updated__gte=since)
123 0269afd6 Giorgos Verigakis
        if not user_networks:
124 0269afd6 Giorgos Verigakis
            return HttpResponse(status=304)
125 0269afd6 Giorgos Verigakis
    else:
126 5061546f Christos Stavrakakis
        user_networks = user_networks.filter(deleted=False)
127 ce55f211 Kostas Papadimitriou
128 4b3b8688 Giorgos Verigakis
    networks = [network_to_dict(network, request.user_uniq, detail)
129 73aed6bf Giorgos Verigakis
                for network in user_networks]
130 ce55f211 Kostas Papadimitriou
131 0269afd6 Giorgos Verigakis
    if request.serialization == 'xml':
132 b36f78fa Giorgos Verigakis
        data = render_to_string('list_networks.xml', {
133 b36f78fa Giorgos Verigakis
            'networks': networks,
134 b36f78fa Giorgos Verigakis
            'detail': detail})
135 0269afd6 Giorgos Verigakis
    else:
136 0269afd6 Giorgos Verigakis
        data = json.dumps({'networks': {'values': networks}})
137 aa197ee4 Vangelis Koukis
138 0269afd6 Giorgos Verigakis
    return HttpResponse(data, status=200)
139 0269afd6 Giorgos Verigakis
140 6ef51e9f Giorgos Verigakis
141 b36f78fa Giorgos Verigakis
@util.api_method('POST')
142 0269afd6 Giorgos Verigakis
def create_network(request):
143 0269afd6 Giorgos Verigakis
    # Normal Response Code: 202
144 0269afd6 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
145 0269afd6 Giorgos Verigakis
    #                       serviceUnavailable (503),
146 0269afd6 Giorgos Verigakis
    #                       unauthorized (401),
147 13b954b0 Giorgos Verigakis
    #                       badMediaType(415),
148 0269afd6 Giorgos Verigakis
    #                       badRequest (400),
149 0269afd6 Giorgos Verigakis
    #                       overLimit (413)
150 aa197ee4 Vangelis Koukis
151 b36f78fa Giorgos Verigakis
    req = util.get_request_dict(request)
152 9e98ba3c Giorgos Verigakis
    log.debug('create_network %s', req)
153 ce55f211 Kostas Papadimitriou
154 0269afd6 Giorgos Verigakis
    try:
155 0269afd6 Giorgos Verigakis
        d = req['network']
156 0269afd6 Giorgos Verigakis
        name = d['name']
157 5061546f Christos Stavrakakis
        # TODO: Fix this temp values:
158 b9a0b3d5 Stavros Sachtouris
        subnet = d.get('cidr', '192.168.1.0/24')
159 5061546f Christos Stavrakakis
        gateway = d.get('gateway', None)
160 04fe9a86 Christos Stavrakakis
        type = d.get('type', 'PRIVATE_VLAN')
161 5061546f Christos Stavrakakis
        dhcp = d.get('dhcp', True)
162 0269afd6 Giorgos Verigakis
    except (KeyError, ValueError):
163 0269afd6 Giorgos Verigakis
        raise BadRequest('Malformed request.')
164 ce55f211 Kostas Papadimitriou
165 5061546f Christos Stavrakakis
    if type == 'PUBLIC_ROUTED':
166 87994836 Christos Stavrakakis
        raise Unauthorized('Can not create a public network.')
167 87994836 Christos Stavrakakis
168 87994836 Christos Stavrakakis
    try:
169 87994836 Christos Stavrakakis
        if type == 'PRIVATE_FILTERED':
170 87994836 Christos Stavrakakis
            link = settings.GANETI_PRIVATE_BRIDGE
171 87994836 Christos Stavrakakis
            mac_prefix = MacPrefixPool.get_available().value
172 87994836 Christos Stavrakakis
        else:  # PRIVATE_VLAN
173 87994836 Christos Stavrakakis
            link = BridgePool.get_available().value
174 87994836 Christos Stavrakakis
            mac_prefix = None
175 87994836 Christos Stavrakakis
    except Pool.PoolExhausted:
176 87994836 Christos Stavrakakis
        raise OverLimit('Network count limit exceeded.')
177 5061546f Christos Stavrakakis
178 5061546f Christos Stavrakakis
    network = Network.objects.create(
179 5061546f Christos Stavrakakis
            name=name,
180 5061546f Christos Stavrakakis
            userid=request.user_uniq,
181 5061546f Christos Stavrakakis
            subnet=subnet,
182 5061546f Christos Stavrakakis
            gateway=gateway,
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 5061546f Christos Stavrakakis
    net.action = 'DESTROY'
254 5061546f Christos Stavrakakis
    net.save()
255 5061546f Christos Stavrakakis
256 64938cb0 Giorgos Verigakis
    backend.delete_network(net)
257 0269afd6 Giorgos Verigakis
    return HttpResponse(status=204)
258 0269afd6 Giorgos Verigakis
259 6ef51e9f Giorgos Verigakis
260 b36f78fa Giorgos Verigakis
@util.api_method('POST')
261 b19653d1 Giorgos Verigakis
def network_action(request, network_id):
262 9e98ba3c Giorgos Verigakis
    req = util.get_request_dict(request)
263 9e98ba3c Giorgos Verigakis
    log.debug('network_action %s %s', network_id, req)
264 9e98ba3c Giorgos Verigakis
    if len(req) != 1:
265 9e98ba3c Giorgos Verigakis
        raise BadRequest('Malformed request.')
266 ce55f211 Kostas Papadimitriou
267 4b3b8688 Giorgos Verigakis
    net = util.get_network(network_id, request.user_uniq)
268 207b70d5 Giorgos Verigakis
    if net.public:
269 207b70d5 Giorgos Verigakis
        raise Unauthorized('Can not modify the public network.')
270 ce55f211 Kostas Papadimitriou
271 0269afd6 Giorgos Verigakis
    key = req.keys()[0]
272 0269afd6 Giorgos Verigakis
    val = req[key]
273 aa197ee4 Vangelis Koukis
274 0269afd6 Giorgos Verigakis
    try:
275 0269afd6 Giorgos Verigakis
        assert isinstance(val, dict)
276 0269afd6 Giorgos Verigakis
        return network_actions[key](request, net, req[key])
277 0269afd6 Giorgos Verigakis
    except KeyError:
278 0269afd6 Giorgos Verigakis
        raise BadRequest('Unknown action.')
279 0269afd6 Giorgos Verigakis
    except AssertionError:
280 0269afd6 Giorgos Verigakis
        raise BadRequest('Invalid argument.')