Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (7.6 kB)

1 a96e84cf Christos Stavrakakis
# Copyright 2011-2013 GRNET S.A. All rights reserved.
2 a96e84cf Christos Stavrakakis
#
3 a96e84cf Christos Stavrakakis
# Redistribution and use in source and binary forms, with or
4 a96e84cf Christos Stavrakakis
# without modification, are permitted provided that the following
5 a96e84cf Christos Stavrakakis
# conditions are met:
6 a96e84cf Christos Stavrakakis
#
7 a96e84cf Christos Stavrakakis
#   1. Redistributions of source code must retain the above
8 a96e84cf Christos Stavrakakis
#      copyright notice, this list of conditions and the following
9 a96e84cf Christos Stavrakakis
#      disclaimer.
10 a96e84cf Christos Stavrakakis
#
11 a96e84cf Christos Stavrakakis
#   2. Redistributions in binary form must reproduce the above
12 a96e84cf Christos Stavrakakis
#      copyright notice, this list of conditions and the following
13 a96e84cf Christos Stavrakakis
#      disclaimer in the documentation and/or other materials
14 a96e84cf Christos Stavrakakis
#      provided with the distribution.
15 a96e84cf Christos Stavrakakis
#
16 a96e84cf Christos Stavrakakis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 a96e84cf Christos Stavrakakis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 a96e84cf Christos Stavrakakis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 a96e84cf Christos Stavrakakis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 a96e84cf Christos Stavrakakis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 a96e84cf Christos Stavrakakis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 a96e84cf Christos Stavrakakis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 a96e84cf Christos Stavrakakis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 a96e84cf Christos Stavrakakis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 a96e84cf Christos Stavrakakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 a96e84cf Christos Stavrakakis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 a96e84cf Christos Stavrakakis
# POSSIBILITY OF SUCH DAMAGE.
28 a96e84cf Christos Stavrakakis
#
29 a96e84cf Christos Stavrakakis
# The views and conclusions contained in the software and
30 a96e84cf Christos Stavrakakis
# documentation are those of the authors and should not be
31 a96e84cf Christos Stavrakakis
# interpreted as representing official policies, either expressed
32 a96e84cf Christos Stavrakakis
# or implied, of GRNET S.A.
33 a96e84cf Christos Stavrakakis
34 ce55f211 Kostas Papadimitriou
from django.conf import settings
35 6b256427 Christos Stavrakakis
from django.conf.urls import patterns
36 0269afd6 Giorgos Verigakis
from django.http import HttpResponse
37 0269afd6 Giorgos Verigakis
from django.utils import simplejson as json
38 0baa1e3d Buildbot
from django.db import transaction
39 0baa1e3d Buildbot
from django.db.models import Q
40 0baa1e3d Buildbot
from django.template.loader import render_to_string
41 a96e84cf Christos Stavrakakis
42 a96e84cf Christos Stavrakakis
from snf_django.lib import api
43 a96e84cf Christos Stavrakakis
44 5061546f Christos Stavrakakis
from synnefo.api import util
45 03992c72 Christos Stavrakakis
from synnefo.db.models import Network
46 a96e84cf Christos Stavrakakis
from synnefo.logic import networks
47 9e98ba3c Giorgos Verigakis
48 b3fd98ae Christos Stavrakakis
from logging import getLogger
49 0baa1e3d Buildbot
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 95a213d4 Christos Stavrakakis
    (r'^(?:/|.json|.xml)?$', 'demux'),
55 a96e84cf Christos Stavrakakis
    (r'^/detail(?:.json|.xml)?$', 'list_networks', {'detail': True}),
56 95a213d4 Christos Stavrakakis
    (r'^/(\w+)(?:/|.json|.xml)?$', 'network_demux'))
57 95a213d4 Christos Stavrakakis
58 0269afd6 Giorgos Verigakis
59 0269afd6 Giorgos Verigakis
def demux(request):
60 0269afd6 Giorgos Verigakis
    if request.method == 'GET':
61 0269afd6 Giorgos Verigakis
        return list_networks(request)
62 0269afd6 Giorgos Verigakis
    elif request.method == 'POST':
63 0269afd6 Giorgos Verigakis
        return create_network(request)
64 0269afd6 Giorgos Verigakis
    else:
65 2aba7764 Sofia Papagiannaki
        return api.api_method_not_allowed(request,
66 2aba7764 Sofia Papagiannaki
                                          allowed_methods=['GET', 'POST'])
67 0269afd6 Giorgos Verigakis
68 6ef51e9f Giorgos Verigakis
69 a96e84cf Christos Stavrakakis
def network_demux(request, network_id):
70 0baa1e3d Buildbot
71 0269afd6 Giorgos Verigakis
    if request.method == 'GET':
72 a96e84cf Christos Stavrakakis
        return get_network_details(request, network_id)
73 0269afd6 Giorgos Verigakis
    elif request.method == 'DELETE':
74 a96e84cf Christos Stavrakakis
        return delete_network(request, network_id)
75 0baa1e3d Buildbot
    elif request.method == 'PUT':
76 a96e84cf Christos Stavrakakis
        return update_network(request, network_id)
77 0269afd6 Giorgos Verigakis
    else:
78 2aba7764 Sofia Papagiannaki
        return api.api_method_not_allowed(request,
79 2aba7764 Sofia Papagiannaki
                                          allowed_methods=['GET',
80 2aba7764 Sofia Papagiannaki
                                                           'PUT',
81 2aba7764 Sofia Papagiannaki
                                                           'DELETE'])
82 0269afd6 Giorgos Verigakis
83 0269afd6 Giorgos Verigakis
84 b3fd98ae Christos Stavrakakis
@api.api_method(http_method='GET', user_required=True, logger=log)
85 bf58eed3 Dionysis Grigoropoulos
def list_networks(request, detail=True):
86 0c37a721 Christos Stavrakakis
    log.debug('list_networks detail=%s', detail)
87 0baa1e3d Buildbot
88 a96e84cf Christos Stavrakakis
    user_networks = Network.objects.filter(Q(userid=request.user_uniq) |
89 a96e84cf Christos Stavrakakis
                                           Q(public=True))\
90 883c1f94 Christos Stavrakakis
                                   .order_by('id')
91 883c1f94 Christos Stavrakakis
    if detail:
92 883c1f94 Christos Stavrakakis
        user_networks = user_networks.prefetch_related("subnets")
93 0baa1e3d Buildbot
94 a96e84cf Christos Stavrakakis
    user_networks = api.utils.filter_modified_since(request,
95 a96e84cf Christos Stavrakakis
                                                    objects=user_networks)
96 ce55f211 Kostas Papadimitriou
97 a96e84cf Christos Stavrakakis
    network_dicts = [network_to_dict(network, detail)
98 883c1f94 Christos Stavrakakis
                     for network in user_networks]
99 ce55f211 Kostas Papadimitriou
100 0269afd6 Giorgos Verigakis
    if request.serialization == 'xml':
101 b36f78fa Giorgos Verigakis
        data = render_to_string('list_networks.xml', {
102 a96e84cf Christos Stavrakakis
            "networks": network_dicts})
103 0269afd6 Giorgos Verigakis
    else:
104 a96e84cf Christos Stavrakakis
        data = json.dumps({'networks': network_dicts})
105 aa197ee4 Vangelis Koukis
106 0269afd6 Giorgos Verigakis
    return HttpResponse(data, status=200)
107 0269afd6 Giorgos Verigakis
108 6ef51e9f Giorgos Verigakis
109 b3fd98ae Christos Stavrakakis
@api.api_method(http_method='POST', user_required=True, logger=log)
110 2509ce17 Christos Stavrakakis
def create_network(request):
111 a96e84cf Christos Stavrakakis
    userid = request.user_uniq
112 a96e84cf Christos Stavrakakis
    req = api.utils.get_request_dict(request)
113 a96e84cf Christos Stavrakakis
    log.info('create_network %s', req)
114 a96e84cf Christos Stavrakakis
115 3d870b05 Dionysis Grigoropoulos
    network_dict = api.utils.get_attribute(req, "network",
116 3d870b05 Dionysis Grigoropoulos
                                           attr_type=dict)
117 3d870b05 Dionysis Grigoropoulos
    flavor = api.utils.get_attribute(network_dict, "type",
118 3d870b05 Dionysis Grigoropoulos
                                     attr_type=basestring)
119 a96e84cf Christos Stavrakakis
120 a96e84cf Christos Stavrakakis
    if flavor not in Network.FLAVORS.keys():
121 a96e84cf Christos Stavrakakis
        raise api.faults.BadRequest("Invalid network type '%s'" % flavor)
122 a96e84cf Christos Stavrakakis
    if flavor not in settings.API_ENABLED_NETWORK_FLAVORS:
123 8d5795b4 Christos Stavrakakis
        raise api.faults.Forbidden("Cannot create network of type '%s'." %
124 a96e84cf Christos Stavrakakis
                                   flavor)
125 a96e84cf Christos Stavrakakis
126 3d870b05 Dionysis Grigoropoulos
    name = api.utils.get_attribute(network_dict, "name", attr_type=basestring,
127 3d870b05 Dionysis Grigoropoulos
                                   required=False)
128 a96e84cf Christos Stavrakakis
    if name is None:
129 a96e84cf Christos Stavrakakis
        name = ""
130 a96e84cf Christos Stavrakakis
131 a96e84cf Christos Stavrakakis
    network = networks.create(userid=userid, name=name, flavor=flavor,
132 a96e84cf Christos Stavrakakis
                              public=False)
133 a96e84cf Christos Stavrakakis
    networkdict = network_to_dict(network, detail=True)
134 0baa1e3d Buildbot
    response = render_network(request, networkdict, status=201)
135 77f45438 Christos Stavrakakis
136 77f45438 Christos Stavrakakis
    return response
137 0269afd6 Giorgos Verigakis
138 6ef51e9f Giorgos Verigakis
139 b3fd98ae Christos Stavrakakis
@api.api_method(http_method='GET', user_required=True, logger=log)
140 a96e84cf Christos Stavrakakis
def get_network_details(request, network_id):
141 0c37a721 Christos Stavrakakis
    log.debug('get_network_details %s', network_id)
142 a96e84cf Christos Stavrakakis
    network = util.get_network(network_id, request.user_uniq)
143 a96e84cf Christos Stavrakakis
    return render_network(request, network_to_dict(network, detail=True))
144 6ef51e9f Giorgos Verigakis
145 a96e84cf Christos Stavrakakis
146 a96e84cf Christos Stavrakakis
@api.api_method(http_method='PUT', user_required=True, logger=log)
147 a96e84cf Christos Stavrakakis
def update_network(request, network_id):
148 a96e84cf Christos Stavrakakis
    info = api.utils.get_request_dict(request)
149 a96e84cf Christos Stavrakakis
150 3d870b05 Dionysis Grigoropoulos
    network = api.utils.get_attribute(info, "network", attr_type=dict,
151 3d870b05 Dionysis Grigoropoulos
                                      required=True)
152 3d870b05 Dionysis Grigoropoulos
    new_name = api.utils.get_attribute(network, "name", attr_type=basestring)
153 a96e84cf Christos Stavrakakis
154 a96e84cf Christos Stavrakakis
    network = util.get_network(network_id, request.user_uniq, for_update=True)
155 a96e84cf Christos Stavrakakis
    if network.public:
156 8d5795b4 Christos Stavrakakis
        raise api.faults.Forbidden("Cannot rename the public network.")
157 a96e84cf Christos Stavrakakis
    network = networks.rename(network, new_name)
158 a96e84cf Christos Stavrakakis
    return render_network(request, network_to_dict(network), 200)
159 0269afd6 Giorgos Verigakis
160 6ef51e9f Giorgos Verigakis
161 b3fd98ae Christos Stavrakakis
@api.api_method(http_method='DELETE', user_required=True, logger=log)
162 0baa1e3d Buildbot
@transaction.commit_on_success
163 b19653d1 Giorgos Verigakis
def delete_network(request, network_id):
164 bf5c82dc Christos Stavrakakis
    log.info('delete_network %s', network_id)
165 a96e84cf Christos Stavrakakis
    network = util.get_network(network_id, request.user_uniq, for_update=True)
166 a96e84cf Christos Stavrakakis
    if network.public:
167 8d5795b4 Christos Stavrakakis
        raise api.faults.Forbidden("Cannot delete the public network.")
168 a96e84cf Christos Stavrakakis
    networks.delete(network)
169 ece5581b Christos Stavrakakis
    return HttpResponse(status=204)
170 5061546f Christos Stavrakakis
171 5061546f Christos Stavrakakis
172 0baa1e3d Buildbot
def network_to_dict(network, detail=True):
173 0baa1e3d Buildbot
    d = {'id': str(network.id), 'name': network.name}
174 0baa1e3d Buildbot
    d['links'] = util.network_to_links(network.id)
175 0baa1e3d Buildbot
    if detail:
176 883c1f94 Christos Stavrakakis
        # Loop over subnets. Do not perform any extra query because of prefetch
177 883c1f94 Christos Stavrakakis
        # related!
178 883c1f94 Christos Stavrakakis
        subnet_ids = []
179 883c1f94 Christos Stavrakakis
        for subnet in network.subnets.all():
180 aff81af3 Christos Stavrakakis
            subnet_ids.append(subnet.id)
181 883c1f94 Christos Stavrakakis
182 8f335041 Christos Stavrakakis
        state = "SNF:DRAINED" if network.drained else network.state
183 0baa1e3d Buildbot
        d['user_id'] = network.userid
184 0baa1e3d Buildbot
        d['tenant_id'] = network.userid
185 0baa1e3d Buildbot
        d['type'] = network.flavor
186 a96e84cf Christos Stavrakakis
        d['updated'] = api.utils.isoformat(network.updated)
187 a96e84cf Christos Stavrakakis
        d['created'] = api.utils.isoformat(network.created)
188 8f335041 Christos Stavrakakis
        d['status'] = state
189 0baa1e3d Buildbot
        d['public'] = network.public
190 64209939 Christos Stavrakakis
        d['router:external'] = network.external_router
191 0baa1e3d Buildbot
        d['admin_state_up'] = True
192 883c1f94 Christos Stavrakakis
        d['subnets'] = subnet_ids
193 7421d45e Christos Stavrakakis
        d['SNF:floating_ip_pool'] = network.floating_ip_pool
194 6faf3c78 Dionysis Grigoropoulos
        d['deleted'] = network.deleted
195 0baa1e3d Buildbot
    return d
196 0baa1e3d Buildbot
197 0baa1e3d Buildbot
198 0baa1e3d Buildbot
def render_network(request, networkdict, status=200):
199 0baa1e3d Buildbot
    if request.serialization == 'xml':
200 0baa1e3d Buildbot
        data = render_to_string('network.xml', {'network': networkdict})
201 0baa1e3d Buildbot
    else:
202 0baa1e3d Buildbot
        data = json.dumps({'network': networkdict})
203 0baa1e3d Buildbot
    return HttpResponse(data, status=status)