Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (10.2 kB)

1 ece5581b Christos Stavrakakis
# Copyright 2011-2013 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 ce55f211 Kostas Papadimitriou
from django.conf import settings
34 6b256427 Christos Stavrakakis
from django.conf.urls import patterns
35 a6b17d33 Christos Stavrakakis
36 b3fd98ae Christos Stavrakakis
from django.db.models import Q
37 0269afd6 Giorgos Verigakis
from django.http import HttpResponse
38 69d6d7dd Giorgos Verigakis
from django.template.loader import render_to_string
39 0269afd6 Giorgos Verigakis
from django.utils import simplejson as json
40 0269afd6 Giorgos Verigakis
41 b3fd98ae Christos Stavrakakis
from snf_django.lib import api
42 b3fd98ae Christos Stavrakakis
from snf_django.lib.api import faults, utils
43 5061546f Christos Stavrakakis
from synnefo.api import util
44 41a7fae7 Christos Stavrakakis
from synnefo.api.servers import network_actions
45 03992c72 Christos Stavrakakis
from synnefo.db.models import Network
46 ece5581b Christos Stavrakakis
from synnefo.logic import networks
47 9e98ba3c Giorgos Verigakis
48 9e98ba3c Giorgos Verigakis
49 b3fd98ae Christos Stavrakakis
from logging import getLogger
50 b3fd98ae Christos Stavrakakis
log = getLogger(__name__)
51 b36f78fa Giorgos Verigakis
52 e440e835 Christos Stavrakakis
urlpatterns = patterns(
53 e440e835 Christos Stavrakakis
    '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 ece5581b Christos Stavrakakis
    (r'^/(\w+)/action(?:.json|.xml)?$', 'demux_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 c0720b78 Kostas Papadimitriou
        return api.api_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 c0720b78 Kostas Papadimitriou
        return api.api_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 7fede91e Christos Stavrakakis
    d = {'id': str(network.id), 'name': network.name}
83 1b696c26 Christos Stavrakakis
    d['links'] = util.network_to_links(network.id)
84 0269afd6 Giorgos Verigakis
    if detail:
85 936e0be3 Christos Stavrakakis
        d['user_id'] = network.userid
86 936e0be3 Christos Stavrakakis
        d['tenant_id'] = network.userid
87 08b079e2 Stavros Sachtouris
        d['cidr'] = network.subnet
88 cc3f266e Christos Stavrakakis
        d['cidr6'] = network.subnet6
89 08b079e2 Stavros Sachtouris
        d['gateway'] = network.gateway
90 cc3f266e Christos Stavrakakis
        d['gateway6'] = network.gateway6
91 08b079e2 Stavros Sachtouris
        d['dhcp'] = network.dhcp
92 b7d38981 Dimitris Aragiorgis
        d['type'] = network.flavor
93 b3fd98ae Christos Stavrakakis
        d['updated'] = utils.isoformat(network.updated)
94 b3fd98ae Christos Stavrakakis
        d['created'] = utils.isoformat(network.created)
95 d44c236b Giorgos Verigakis
        d['status'] = network.state
96 7fede91e Christos Stavrakakis
        d['public'] = network.public
97 08b079e2 Stavros Sachtouris
98 c988fcca Christos Stavrakakis
        attachments = [nic.id
99 e440e835 Christos Stavrakakis
                       for nic in network.nics.filter(machine__userid=user_id)
100 939d71dd Christos Stavrakakis
                                              .filter(state="ACTIVE")
101 cd2b0bf5 Christos Stavrakakis
                                              .order_by('machine')]
102 5029ff36 Christos Stavrakakis
        d['attachments'] = attachments
103 0269afd6 Giorgos Verigakis
    return d
104 0269afd6 Giorgos Verigakis
105 6ef51e9f Giorgos Verigakis
106 0269afd6 Giorgos Verigakis
def render_network(request, networkdict, status=200):
107 0269afd6 Giorgos Verigakis
    if request.serialization == 'xml':
108 0269afd6 Giorgos Verigakis
        data = render_to_string('network.xml', {'network': networkdict})
109 0269afd6 Giorgos Verigakis
    else:
110 0269afd6 Giorgos Verigakis
        data = json.dumps({'network': networkdict})
111 0269afd6 Giorgos Verigakis
    return HttpResponse(data, status=status)
112 0269afd6 Giorgos Verigakis
113 0269afd6 Giorgos Verigakis
114 b3fd98ae Christos Stavrakakis
@api.api_method(http_method='GET', user_required=True, logger=log)
115 0269afd6 Giorgos Verigakis
def list_networks(request, detail=False):
116 0269afd6 Giorgos Verigakis
    # Normal Response Codes: 200, 203
117 0269afd6 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
118 0269afd6 Giorgos Verigakis
    #                       serviceUnavailable (503),
119 0269afd6 Giorgos Verigakis
    #                       unauthorized (401),
120 0269afd6 Giorgos Verigakis
    #                       badRequest (400),
121 0269afd6 Giorgos Verigakis
    #                       overLimit (413)
122 ce55f211 Kostas Papadimitriou
123 0c37a721 Christos Stavrakakis
    log.debug('list_networks detail=%s', detail)
124 8b2515a9 Christos Stavrakakis
    user_networks = Network.objects.filter(Q(userid=request.user_uniq) |
125 3878553d Kostas Papadimitriou
                                           Q(public=True))
126 b6bc4afa Christos Stavrakakis
    user_networks = utils.filter_modified_since(request, objects=user_networks)
127 ce55f211 Kostas Papadimitriou
128 ece5581b Christos Stavrakakis
    networks_dict = [network_to_dict(network, request.user_uniq, detail)
129 ece5581b Christos Stavrakakis
                     for network in user_networks.order_by('id')]
130 ce55f211 Kostas Papadimitriou
131 0269afd6 Giorgos Verigakis
    if request.serialization == 'xml':
132 b36f78fa Giorgos Verigakis
        data = render_to_string('list_networks.xml', {
133 ece5581b Christos Stavrakakis
            'networks': networks_dict,
134 b36f78fa Giorgos Verigakis
            'detail': detail})
135 0269afd6 Giorgos Verigakis
    else:
136 ece5581b Christos Stavrakakis
        data = json.dumps({'networks': networks_dict})
137 aa197ee4 Vangelis Koukis
138 0269afd6 Giorgos Verigakis
    return HttpResponse(data, status=200)
139 0269afd6 Giorgos Verigakis
140 6ef51e9f Giorgos Verigakis
141 b3fd98ae Christos Stavrakakis
@api.api_method(http_method='POST', user_required=True, logger=log)
142 2509ce17 Christos Stavrakakis
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 17c2ed57 Christos Stavrakakis
    #                       forbidden (403)
150 0269afd6 Giorgos Verigakis
    #                       overLimit (413)
151 aa197ee4 Vangelis Koukis
152 ece5581b Christos Stavrakakis
    req = utils.get_request_dict(request)
153 ece5581b Christos Stavrakakis
    log.info('create_network %s', req)
154 ece5581b Christos Stavrakakis
    user_id = request.user_uniq
155 3165f027 Christos Stavrakakis
    try:
156 ece5581b Christos Stavrakakis
        d = req['network']
157 ece5581b Christos Stavrakakis
        name = d['name']
158 ece5581b Christos Stavrakakis
    except KeyError:
159 ece5581b Christos Stavrakakis
        raise faults.BadRequest("Malformed request")
160 ece5581b Christos Stavrakakis
161 ece5581b Christos Stavrakakis
    # Get and validate flavor. Flavors are still exposed as 'type' in the
162 ece5581b Christos Stavrakakis
    # API.
163 ece5581b Christos Stavrakakis
    flavor = d.get("type", None)
164 ece5581b Christos Stavrakakis
    if flavor is None:
165 ece5581b Christos Stavrakakis
        raise faults.BadRequest("Missing request parameter 'type'")
166 ece5581b Christos Stavrakakis
    elif flavor not in Network.FLAVORS.keys():
167 ece5581b Christos Stavrakakis
        raise faults.BadRequest("Invalid network type '%s'" % flavor)
168 ece5581b Christos Stavrakakis
    elif flavor not in settings.API_ENABLED_NETWORK_FLAVORS:
169 a1d0f147 Christos Stavrakakis
        raise faults.Forbidden("Can not create network of type '%s'" %
170 a1d0f147 Christos Stavrakakis
                               flavor)
171 a1d0f147 Christos Stavrakakis
172 ece5581b Christos Stavrakakis
    public = d.get("public", False)
173 ece5581b Christos Stavrakakis
    if public:
174 ece5581b Christos Stavrakakis
        raise faults.Forbidden("Can not create a public network.")
175 4e1133ab Christos Stavrakakis
176 ece5581b Christos Stavrakakis
    dhcp = d.get('dhcp', True)
177 ece5581b Christos Stavrakakis
178 ece5581b Christos Stavrakakis
    # Get and validate network parameters
179 ece5581b Christos Stavrakakis
    subnet = d.get('cidr', '192.168.1.0/24')
180 ece5581b Christos Stavrakakis
    subnet6 = d.get('cidr6', None)
181 ece5581b Christos Stavrakakis
    gateway = d.get('gateway', None)
182 ece5581b Christos Stavrakakis
    gateway6 = d.get('gateway6', None)
183 ece5581b Christos Stavrakakis
184 ece5581b Christos Stavrakakis
    network = networks.create(user_id=user_id, name=name, flavor=flavor,
185 ece5581b Christos Stavrakakis
                              subnet=subnet, gateway=gateway, subnet6=subnet6,
186 ece5581b Christos Stavrakakis
                              gateway6=gateway6, dhcp=dhcp, public=False)
187 7cfbbf32 Christos Stavrakakis
188 4b3b8688 Giorgos Verigakis
    networkdict = network_to_dict(network, request.user_uniq)
189 77f45438 Christos Stavrakakis
    response = render_network(request, networkdict, status=202)
190 77f45438 Christos Stavrakakis
191 77f45438 Christos Stavrakakis
    return response
192 0269afd6 Giorgos Verigakis
193 6ef51e9f Giorgos Verigakis
194 b3fd98ae Christos Stavrakakis
@api.api_method(http_method='GET', user_required=True, logger=log)
195 b19653d1 Giorgos Verigakis
def get_network_details(request, network_id):
196 0269afd6 Giorgos Verigakis
    # Normal Response Codes: 200, 203
197 13b954b0 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
198 13b954b0 Giorgos Verigakis
    #                       serviceUnavailable (503),
199 13b954b0 Giorgos Verigakis
    #                       unauthorized (401),
200 13b954b0 Giorgos Verigakis
    #                       badRequest (400),
201 13b954b0 Giorgos Verigakis
    #                       itemNotFound (404),
202 13b954b0 Giorgos Verigakis
    #                       overLimit (413)
203 ce55f211 Kostas Papadimitriou
204 0c37a721 Christos Stavrakakis
    log.debug('get_network_details %s', network_id)
205 4b3b8688 Giorgos Verigakis
    net = util.get_network(network_id, request.user_uniq)
206 4b3b8688 Giorgos Verigakis
    netdict = network_to_dict(net, request.user_uniq)
207 0269afd6 Giorgos Verigakis
    return render_network(request, netdict)
208 0269afd6 Giorgos Verigakis
209 6ef51e9f Giorgos Verigakis
210 b3fd98ae Christos Stavrakakis
@api.api_method(http_method='PUT', user_required=True, logger=log)
211 b19653d1 Giorgos Verigakis
def update_network_name(request, network_id):
212 0269afd6 Giorgos Verigakis
    # Normal Response Code: 204
213 13b954b0 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
214 13b954b0 Giorgos Verigakis
    #                       serviceUnavailable (503),
215 13b954b0 Giorgos Verigakis
    #                       unauthorized (401),
216 13b954b0 Giorgos Verigakis
    #                       badRequest (400),
217 17c2ed57 Christos Stavrakakis
    #                       forbidden (403)
218 13b954b0 Giorgos Verigakis
    #                       badMediaType(415),
219 13b954b0 Giorgos Verigakis
    #                       itemNotFound (404),
220 13b954b0 Giorgos Verigakis
    #                       overLimit (413)
221 aa197ee4 Vangelis Koukis
222 b3fd98ae Christos Stavrakakis
    req = utils.get_request_dict(request)
223 bf5c82dc Christos Stavrakakis
    log.info('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 bd40abfa Christos Stavrakakis
        raise faults.BadRequest('Malformed request.')
229 0269afd6 Giorgos Verigakis
230 ece5581b Christos Stavrakakis
    network = util.get_network(network_id, request.user_uniq)
231 ece5581b Christos Stavrakakis
    if network.public:
232 bd40abfa Christos Stavrakakis
        raise faults.Forbidden('Can not rename the public network.')
233 ece5581b Christos Stavrakakis
    network = networks.rename(network, name)
234 0269afd6 Giorgos Verigakis
    return HttpResponse(status=204)
235 0269afd6 Giorgos Verigakis
236 6ef51e9f Giorgos Verigakis
237 b3fd98ae Christos Stavrakakis
@api.api_method(http_method='DELETE', user_required=True, logger=log)
238 b19653d1 Giorgos Verigakis
def delete_network(request, network_id):
239 0269afd6 Giorgos Verigakis
    # Normal Response Code: 204
240 13b954b0 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
241 13b954b0 Giorgos Verigakis
    #                       serviceUnavailable (503),
242 13b954b0 Giorgos Verigakis
    #                       unauthorized (401),
243 17c2ed57 Christos Stavrakakis
    #                       forbidden (403)
244 13b954b0 Giorgos Verigakis
    #                       itemNotFound (404),
245 13b954b0 Giorgos Verigakis
    #                       overLimit (413)
246 ce55f211 Kostas Papadimitriou
247 bf5c82dc Christos Stavrakakis
    log.info('delete_network %s', network_id)
248 ece5581b Christos Stavrakakis
    network = util.get_network(network_id, request.user_uniq, for_update=True)
249 ece5581b Christos Stavrakakis
    if network.public:
250 bd40abfa Christos Stavrakakis
        raise faults.Forbidden('Can not delete the public network.')
251 ece5581b Christos Stavrakakis
    networks.delete(network)
252 ece5581b Christos Stavrakakis
    return HttpResponse(status=204)
253 5061546f Christos Stavrakakis
254 5061546f Christos Stavrakakis
255 ece5581b Christos Stavrakakis
def key_to_action(action):
256 ece5581b Christos Stavrakakis
    return action.upper()
257 0269afd6 Giorgos Verigakis
258 6ef51e9f Giorgos Verigakis
259 b3fd98ae Christos Stavrakakis
@api.api_method(http_method='POST', user_required=True, logger=log)
260 ece5581b Christos Stavrakakis
def demux_network_action(request, network_id):
261 b3fd98ae Christos Stavrakakis
    req = utils.get_request_dict(request)
262 0c37a721 Christos Stavrakakis
    log.debug('network_action %s %s', network_id, req)
263 9e98ba3c Giorgos Verigakis
    if len(req) != 1:
264 bd40abfa Christos Stavrakakis
        raise faults.BadRequest('Malformed request.')
265 ce55f211 Kostas Papadimitriou
266 4b3b8688 Giorgos Verigakis
    net = util.get_network(network_id, request.user_uniq)
267 207b70d5 Giorgos Verigakis
    if net.public:
268 bd40abfa Christos Stavrakakis
        raise faults.Forbidden('Can not modify the public network.')
269 22a9959d Christos Stavrakakis
    if net.deleted:
270 05d401cf Christos Stavrakakis
        raise faults.BadRequest("Network has been deleted.")
271 ce55f211 Kostas Papadimitriou
272 ece5581b Christos Stavrakakis
    action = req.keys()[0]
273 ece5581b Christos Stavrakakis
    if key_to_action(action) not in [x[0] for x in Network.ACTIONS]:
274 ece5581b Christos Stavrakakis
        raise faults.BadRequest("Action %s not supported." % action)
275 ece5581b Christos Stavrakakis
    action_args = req[action]
276 ece5581b Christos Stavrakakis
    if not isinstance(action_args, dict):
277 ece5581b Christos Stavrakakis
        raise faults.BadRequest("Invalid argument.")
278 ece5581b Christos Stavrakakis
    return network_actions[action](request, net, action_args)