Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (11.8 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 4dba0480 Christos Stavrakakis
from django.db import transaction
40 0269afd6 Giorgos Verigakis
from django.http import HttpResponse
41 69d6d7dd Giorgos Verigakis
from django.template.loader import render_to_string
42 0269afd6 Giorgos Verigakis
from django.utils import simplejson as json
43 0269afd6 Giorgos Verigakis
44 bd40abfa Christos Stavrakakis
from snf_django.lib.api import faults
45 5061546f Christos Stavrakakis
from synnefo.api import util
46 b36f78fa Giorgos Verigakis
from synnefo.api.actions import network_actions
47 b36f78fa Giorgos Verigakis
from synnefo.api.common import method_not_allowed
48 77f45438 Christos Stavrakakis
from synnefo import quotas
49 03992c72 Christos Stavrakakis
from synnefo.db.models import Network
50 03992c72 Christos Stavrakakis
from synnefo.db.pools import EmptyPool
51 b36f78fa Giorgos Verigakis
from synnefo.logic import backend
52 9e98ba3c Giorgos Verigakis
53 9e98ba3c Giorgos Verigakis
54 9e98ba3c Giorgos Verigakis
log = getLogger('synnefo.api')
55 b36f78fa Giorgos Verigakis
56 e440e835 Christos Stavrakakis
urlpatterns = patterns(
57 e440e835 Christos Stavrakakis
    'synnefo.api.networks',
58 0269afd6 Giorgos Verigakis
    (r'^(?:/|.json|.xml)?$', 'demux'),
59 0269afd6 Giorgos Verigakis
    (r'^/detail(?:.json|.xml)?$', 'list_networks', {'detail': True}),
60 f4fe8796 Giorgos Verigakis
    (r'^/(\w+)(?:.json|.xml)?$', 'network_demux'),
61 f4fe8796 Giorgos Verigakis
    (r'^/(\w+)/action(?:.json|.xml)?$', 'network_action'),
62 0269afd6 Giorgos Verigakis
)
63 0269afd6 Giorgos Verigakis
64 0269afd6 Giorgos Verigakis
65 0269afd6 Giorgos Verigakis
def demux(request):
66 0269afd6 Giorgos Verigakis
    if request.method == 'GET':
67 0269afd6 Giorgos Verigakis
        return list_networks(request)
68 0269afd6 Giorgos Verigakis
    elif request.method == 'POST':
69 0269afd6 Giorgos Verigakis
        return create_network(request)
70 0269afd6 Giorgos Verigakis
    else:
71 0269afd6 Giorgos Verigakis
        return method_not_allowed(request)
72 0269afd6 Giorgos Verigakis
73 6ef51e9f Giorgos Verigakis
74 b19653d1 Giorgos Verigakis
def network_demux(request, network_id):
75 0269afd6 Giorgos Verigakis
    if request.method == 'GET':
76 b19653d1 Giorgos Verigakis
        return get_network_details(request, network_id)
77 0269afd6 Giorgos Verigakis
    elif request.method == 'PUT':
78 b19653d1 Giorgos Verigakis
        return update_network_name(request, network_id)
79 0269afd6 Giorgos Verigakis
    elif request.method == 'DELETE':
80 b19653d1 Giorgos Verigakis
        return delete_network(request, network_id)
81 0269afd6 Giorgos Verigakis
    else:
82 0269afd6 Giorgos Verigakis
        return method_not_allowed(request)
83 0269afd6 Giorgos Verigakis
84 0269afd6 Giorgos Verigakis
85 6ef51e9f Giorgos Verigakis
def network_to_dict(network, user_id, detail=True):
86 7fede91e Christos Stavrakakis
    d = {'id': str(network.id), 'name': network.name}
87 0269afd6 Giorgos Verigakis
    if detail:
88 08b079e2 Stavros Sachtouris
        d['cidr'] = network.subnet
89 cc3f266e Christos Stavrakakis
        d['cidr6'] = network.subnet6
90 08b079e2 Stavros Sachtouris
        d['gateway'] = network.gateway
91 cc3f266e Christos Stavrakakis
        d['gateway6'] = network.gateway6
92 08b079e2 Stavros Sachtouris
        d['dhcp'] = network.dhcp
93 b7d38981 Dimitris Aragiorgis
        d['type'] = network.flavor
94 b36f78fa Giorgos Verigakis
        d['updated'] = util.isoformat(network.updated)
95 b36f78fa Giorgos Verigakis
        d['created'] = util.isoformat(network.created)
96 d44c236b Giorgos Verigakis
        d['status'] = network.state
97 7fede91e Christos Stavrakakis
        d['public'] = network.public
98 08b079e2 Stavros Sachtouris
99 7fede91e Christos Stavrakakis
        attachments = [util.construct_nic_id(nic)
100 e440e835 Christos Stavrakakis
                       for nic in network.nics.filter(machine__userid=user_id)
101 939d71dd Christos Stavrakakis
                                              .filter(state="ACTIVE")
102 cd2b0bf5 Christos Stavrakakis
                                              .order_by('machine')]
103 7fede91e Christos Stavrakakis
        d['attachments'] = {'values': attachments}
104 0269afd6 Giorgos Verigakis
    return d
105 0269afd6 Giorgos Verigakis
106 6ef51e9f Giorgos Verigakis
107 0269afd6 Giorgos Verigakis
def render_network(request, networkdict, status=200):
108 0269afd6 Giorgos Verigakis
    if request.serialization == 'xml':
109 0269afd6 Giorgos Verigakis
        data = render_to_string('network.xml', {'network': networkdict})
110 0269afd6 Giorgos Verigakis
    else:
111 0269afd6 Giorgos Verigakis
        data = json.dumps({'network': networkdict})
112 0269afd6 Giorgos Verigakis
    return HttpResponse(data, status=status)
113 0269afd6 Giorgos Verigakis
114 0269afd6 Giorgos Verigakis
115 b36f78fa Giorgos Verigakis
@util.api_method('GET')
116 0269afd6 Giorgos Verigakis
def list_networks(request, detail=False):
117 0269afd6 Giorgos Verigakis
    # Normal Response Codes: 200, 203
118 0269afd6 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
119 0269afd6 Giorgos Verigakis
    #                       serviceUnavailable (503),
120 0269afd6 Giorgos Verigakis
    #                       unauthorized (401),
121 0269afd6 Giorgos Verigakis
    #                       badRequest (400),
122 0269afd6 Giorgos Verigakis
    #                       overLimit (413)
123 ce55f211 Kostas Papadimitriou
124 0c37a721 Christos Stavrakakis
    log.debug('list_networks detail=%s', detail)
125 b36f78fa Giorgos Verigakis
    since = util.isoparse(request.GET.get('changes-since'))
126 8b2515a9 Christos Stavrakakis
    user_networks = Network.objects.filter(Q(userid=request.user_uniq) |
127 3878553d Kostas Papadimitriou
                                           Q(public=True))
128 ce55f211 Kostas Papadimitriou
129 0269afd6 Giorgos Verigakis
    if since:
130 d44c236b Giorgos Verigakis
        user_networks = user_networks.filter(updated__gte=since)
131 0269afd6 Giorgos Verigakis
        if not user_networks:
132 0269afd6 Giorgos Verigakis
            return HttpResponse(status=304)
133 3878553d Kostas Papadimitriou
    else:
134 3878553d Kostas Papadimitriou
        user_networks = user_networks.filter(deleted=False)
135 ce55f211 Kostas Papadimitriou
136 4b3b8688 Giorgos Verigakis
    networks = [network_to_dict(network, request.user_uniq, detail)
137 cd2b0bf5 Christos Stavrakakis
                for network in user_networks.order_by('id')]
138 ce55f211 Kostas Papadimitriou
139 0269afd6 Giorgos Verigakis
    if request.serialization == 'xml':
140 b36f78fa Giorgos Verigakis
        data = render_to_string('list_networks.xml', {
141 b36f78fa Giorgos Verigakis
            'networks': networks,
142 b36f78fa Giorgos Verigakis
            'detail': detail})
143 0269afd6 Giorgos Verigakis
    else:
144 0269afd6 Giorgos Verigakis
        data = json.dumps({'networks': {'values': networks}})
145 aa197ee4 Vangelis Koukis
146 0269afd6 Giorgos Verigakis
    return HttpResponse(data, status=200)
147 0269afd6 Giorgos Verigakis
148 6ef51e9f Giorgos Verigakis
149 b36f78fa Giorgos Verigakis
@util.api_method('POST')
150 77f45438 Christos Stavrakakis
@quotas.uses_commission
151 d4993f77 Christos Stavrakakis
@transaction.commit_manually
152 77f45438 Christos Stavrakakis
def create_network(serials, request):
153 0269afd6 Giorgos Verigakis
    # Normal Response Code: 202
154 0269afd6 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
155 0269afd6 Giorgos Verigakis
    #                       serviceUnavailable (503),
156 0269afd6 Giorgos Verigakis
    #                       unauthorized (401),
157 13b954b0 Giorgos Verigakis
    #                       badMediaType(415),
158 0269afd6 Giorgos Verigakis
    #                       badRequest (400),
159 17c2ed57 Christos Stavrakakis
    #                       forbidden (403)
160 0269afd6 Giorgos Verigakis
    #                       overLimit (413)
161 aa197ee4 Vangelis Koukis
162 3165f027 Christos Stavrakakis
    try:
163 d4993f77 Christos Stavrakakis
        req = util.get_request_dict(request)
164 d4993f77 Christos Stavrakakis
        log.info('create_network %s', req)
165 d4993f77 Christos Stavrakakis
166 4e1133ab Christos Stavrakakis
        user_id = request.user_uniq
167 d4993f77 Christos Stavrakakis
        try:
168 d4993f77 Christos Stavrakakis
            d = req['network']
169 d4993f77 Christos Stavrakakis
            name = d['name']
170 4e1133ab Christos Stavrakakis
        except KeyError:
171 bd40abfa Christos Stavrakakis
            raise faults.BadRequest("Malformed request")
172 4e1133ab Christos Stavrakakis
173 4e1133ab Christos Stavrakakis
        # Get and validate flavor. Flavors are still exposed as 'type' in the
174 4e1133ab Christos Stavrakakis
        # API.
175 4e1133ab Christos Stavrakakis
        flavor = d.get("type", None)
176 4e1133ab Christos Stavrakakis
        if flavor is None:
177 bd40abfa Christos Stavrakakis
            raise faults.BadRequest("Missing request parameter 'type'")
178 4e1133ab Christos Stavrakakis
        elif flavor not in Network.FLAVORS.keys():
179 bd40abfa Christos Stavrakakis
            raise faults.BadRequest("Invalid network type '%s'" % flavor)
180 4e1133ab Christos Stavrakakis
        elif flavor not in settings.API_ENABLED_NETWORK_FLAVORS:
181 bd40abfa Christos Stavrakakis
            raise faults.Forbidden("Can not create network of type '%s'" % flavor)
182 4e1133ab Christos Stavrakakis
183 4e1133ab Christos Stavrakakis
        public = d.get("public", False)
184 d4993f77 Christos Stavrakakis
        if public:
185 bd40abfa Christos Stavrakakis
            raise faults.Forbidden("Can not create a public network.")
186 d4993f77 Christos Stavrakakis
187 4e1133ab Christos Stavrakakis
        dhcp = d.get('dhcp', True)
188 d4993f77 Christos Stavrakakis
189 4e1133ab Christos Stavrakakis
        # Get and validate network parameters
190 4e1133ab Christos Stavrakakis
        subnet = d.get('cidr', '192.168.1.0/24')
191 4e1133ab Christos Stavrakakis
        subnet6 = d.get('cidr6', None)
192 4e1133ab Christos Stavrakakis
        gateway = d.get('gateway', None)
193 4e1133ab Christos Stavrakakis
        gateway6 = d.get('gateway6', None)
194 d368ec0c Christos Stavrakakis
        # Check that user provided a valid subnet
195 9ae613af Christos Stavrakakis
        util.validate_network_params(subnet, gateway, subnet6, gateway6)
196 d4993f77 Christos Stavrakakis
197 4e1133ab Christos Stavrakakis
        # Issue commission
198 d4993f77 Christos Stavrakakis
        serial = quotas.issue_network_commission(user_id)
199 d4993f77 Christos Stavrakakis
        serials.append(serial)
200 d4993f77 Christos Stavrakakis
        # Make the commission accepted, since in the end of this
201 d4993f77 Christos Stavrakakis
        # transaction the Network will have been created in the DB.
202 d4993f77 Christos Stavrakakis
        serial.accepted = True
203 d4993f77 Christos Stavrakakis
        serial.save()
204 d4993f77 Christos Stavrakakis
205 d4993f77 Christos Stavrakakis
        try:
206 d4993f77 Christos Stavrakakis
            mode, link, mac_prefix, tags = util.values_from_flavor(flavor)
207 d4993f77 Christos Stavrakakis
            network = Network.objects.create(
208 e440e835 Christos Stavrakakis
                name=name,
209 e440e835 Christos Stavrakakis
                userid=user_id,
210 e440e835 Christos Stavrakakis
                subnet=subnet,
211 e440e835 Christos Stavrakakis
                subnet6=subnet6,
212 e440e835 Christos Stavrakakis
                gateway=gateway,
213 e440e835 Christos Stavrakakis
                gateway6=gateway6,
214 e440e835 Christos Stavrakakis
                dhcp=dhcp,
215 e440e835 Christos Stavrakakis
                flavor=flavor,
216 e440e835 Christos Stavrakakis
                mode=mode,
217 e440e835 Christos Stavrakakis
                link=link,
218 e440e835 Christos Stavrakakis
                mac_prefix=mac_prefix,
219 e440e835 Christos Stavrakakis
                tags=tags,
220 e440e835 Christos Stavrakakis
                action='CREATE',
221 e440e835 Christos Stavrakakis
                state='PENDING',
222 e440e835 Christos Stavrakakis
                serial=serial)
223 d4993f77 Christos Stavrakakis
        except EmptyPool:
224 d4993f77 Christos Stavrakakis
            log.error("Failed to allocate resources for network of type: %s",
225 d4993f77 Christos Stavrakakis
                      flavor)
226 bd40abfa Christos Stavrakakis
            raise faults.ServiceUnavailable("Failed to allocate network resources")
227 d4993f77 Christos Stavrakakis
228 d4993f77 Christos Stavrakakis
        # Create BackendNetwork entries for each Backend
229 d4993f77 Christos Stavrakakis
        network.create_backend_network()
230 d4993f77 Christos Stavrakakis
    except:
231 d4993f77 Christos Stavrakakis
        transaction.rollback()
232 e7a8d451 Christos Stavrakakis
        raise
233 d4993f77 Christos Stavrakakis
    else:
234 d4993f77 Christos Stavrakakis
        transaction.commit()
235 7cfbbf32 Christos Stavrakakis
236 7cfbbf32 Christos Stavrakakis
    # Create the network in the actual backends
237 87994836 Christos Stavrakakis
    backend.create_network(network)
238 ce55f211 Kostas Papadimitriou
239 4b3b8688 Giorgos Verigakis
    networkdict = network_to_dict(network, request.user_uniq)
240 77f45438 Christos Stavrakakis
    response = render_network(request, networkdict, status=202)
241 77f45438 Christos Stavrakakis
242 77f45438 Christos Stavrakakis
    return response
243 0269afd6 Giorgos Verigakis
244 6ef51e9f Giorgos Verigakis
245 b36f78fa Giorgos Verigakis
@util.api_method('GET')
246 b19653d1 Giorgos Verigakis
def get_network_details(request, network_id):
247 0269afd6 Giorgos Verigakis
    # Normal Response Codes: 200, 203
248 13b954b0 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
249 13b954b0 Giorgos Verigakis
    #                       serviceUnavailable (503),
250 13b954b0 Giorgos Verigakis
    #                       unauthorized (401),
251 13b954b0 Giorgos Verigakis
    #                       badRequest (400),
252 13b954b0 Giorgos Verigakis
    #                       itemNotFound (404),
253 13b954b0 Giorgos Verigakis
    #                       overLimit (413)
254 ce55f211 Kostas Papadimitriou
255 0c37a721 Christos Stavrakakis
    log.debug('get_network_details %s', network_id)
256 4b3b8688 Giorgos Verigakis
    net = util.get_network(network_id, request.user_uniq)
257 4b3b8688 Giorgos Verigakis
    netdict = network_to_dict(net, request.user_uniq)
258 0269afd6 Giorgos Verigakis
    return render_network(request, netdict)
259 0269afd6 Giorgos Verigakis
260 6ef51e9f Giorgos Verigakis
261 b36f78fa Giorgos Verigakis
@util.api_method('PUT')
262 b19653d1 Giorgos Verigakis
def update_network_name(request, network_id):
263 0269afd6 Giorgos Verigakis
    # Normal Response Code: 204
264 13b954b0 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
265 13b954b0 Giorgos Verigakis
    #                       serviceUnavailable (503),
266 13b954b0 Giorgos Verigakis
    #                       unauthorized (401),
267 13b954b0 Giorgos Verigakis
    #                       badRequest (400),
268 17c2ed57 Christos Stavrakakis
    #                       forbidden (403)
269 13b954b0 Giorgos Verigakis
    #                       badMediaType(415),
270 13b954b0 Giorgos Verigakis
    #                       itemNotFound (404),
271 13b954b0 Giorgos Verigakis
    #                       overLimit (413)
272 aa197ee4 Vangelis Koukis
273 b36f78fa Giorgos Verigakis
    req = util.get_request_dict(request)
274 bf5c82dc Christos Stavrakakis
    log.info('update_network_name %s', network_id)
275 ce55f211 Kostas Papadimitriou
276 0269afd6 Giorgos Verigakis
    try:
277 0269afd6 Giorgos Verigakis
        name = req['network']['name']
278 0269afd6 Giorgos Verigakis
    except (TypeError, KeyError):
279 bd40abfa Christos Stavrakakis
        raise faults.BadRequest('Malformed request.')
280 0269afd6 Giorgos Verigakis
281 4b3b8688 Giorgos Verigakis
    net = util.get_network(network_id, request.user_uniq)
282 207b70d5 Giorgos Verigakis
    if net.public:
283 bd40abfa Christos Stavrakakis
        raise faults.Forbidden('Can not rename the public network.')
284 22a9959d Christos Stavrakakis
    if net.deleted:
285 05d401cf Christos Stavrakakis
        raise faults.BadRequest("Network has been deleted.")
286 0269afd6 Giorgos Verigakis
    net.name = name
287 0269afd6 Giorgos Verigakis
    net.save()
288 0269afd6 Giorgos Verigakis
    return HttpResponse(status=204)
289 0269afd6 Giorgos Verigakis
290 6ef51e9f Giorgos Verigakis
291 b36f78fa Giorgos Verigakis
@util.api_method('DELETE')
292 4dba0480 Christos Stavrakakis
@transaction.commit_on_success
293 b19653d1 Giorgos Verigakis
def delete_network(request, network_id):
294 0269afd6 Giorgos Verigakis
    # Normal Response Code: 204
295 13b954b0 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
296 13b954b0 Giorgos Verigakis
    #                       serviceUnavailable (503),
297 13b954b0 Giorgos Verigakis
    #                       unauthorized (401),
298 17c2ed57 Christos Stavrakakis
    #                       forbidden (403)
299 13b954b0 Giorgos Verigakis
    #                       itemNotFound (404),
300 13b954b0 Giorgos Verigakis
    #                       overLimit (413)
301 ce55f211 Kostas Papadimitriou
302 bf5c82dc Christos Stavrakakis
    log.info('delete_network %s', network_id)
303 d2e73c0c Christos Stavrakakis
    net = util.get_network(network_id, request.user_uniq, for_update=True)
304 207b70d5 Giorgos Verigakis
    if net.public:
305 bd40abfa Christos Stavrakakis
        raise faults.Forbidden('Can not delete the public network.')
306 5061546f Christos Stavrakakis
307 22a9959d Christos Stavrakakis
    if net.deleted:
308 05d401cf Christos Stavrakakis
        raise faults.BadRequest("Network has been deleted.")
309 22a9959d Christos Stavrakakis
310 0196d9a3 Christos Stavrakakis
    if net.machines.all():  # Nics attached on network
311 bd40abfa Christos Stavrakakis
        raise faults.NetworkInUse('Machines are connected to network.')
312 0196d9a3 Christos Stavrakakis
313 5061546f Christos Stavrakakis
    net.action = 'DESTROY'
314 5061546f Christos Stavrakakis
    net.save()
315 5061546f Christos Stavrakakis
316 64938cb0 Giorgos Verigakis
    backend.delete_network(net)
317 0269afd6 Giorgos Verigakis
    return HttpResponse(status=204)
318 0269afd6 Giorgos Verigakis
319 6ef51e9f Giorgos Verigakis
320 b36f78fa Giorgos Verigakis
@util.api_method('POST')
321 b19653d1 Giorgos Verigakis
def network_action(request, network_id):
322 9e98ba3c Giorgos Verigakis
    req = util.get_request_dict(request)
323 0c37a721 Christos Stavrakakis
    log.debug('network_action %s %s', network_id, req)
324 9e98ba3c Giorgos Verigakis
    if len(req) != 1:
325 bd40abfa Christos Stavrakakis
        raise faults.BadRequest('Malformed request.')
326 ce55f211 Kostas Papadimitriou
327 4b3b8688 Giorgos Verigakis
    net = util.get_network(network_id, request.user_uniq)
328 207b70d5 Giorgos Verigakis
    if net.public:
329 bd40abfa Christos Stavrakakis
        raise faults.Forbidden('Can not modify the public network.')
330 22a9959d Christos Stavrakakis
    if net.deleted:
331 05d401cf Christos Stavrakakis
        raise faults.BadRequest("Network has been deleted.")
332 ce55f211 Kostas Papadimitriou
333 0269afd6 Giorgos Verigakis
    try:
334 e221ade2 Christos Stavrakakis
        key = req.keys()[0]
335 e221ade2 Christos Stavrakakis
        val = req[key]
336 0269afd6 Giorgos Verigakis
        assert isinstance(val, dict)
337 0269afd6 Giorgos Verigakis
        return network_actions[key](request, net, req[key])
338 0269afd6 Giorgos Verigakis
    except KeyError:
339 bd40abfa Christos Stavrakakis
        raise faults.BadRequest('Unknown action.')
340 0269afd6 Giorgos Verigakis
    except AssertionError:
341 bd40abfa Christos Stavrakakis
        raise faults.BadRequest('Invalid argument.')