Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (7.3 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 a96e84cf Christos Stavrakakis
    network_dict = api.utils.get_attribute(req, "network")
116 a96e84cf Christos Stavrakakis
    flavor = api.utils.get_attribute(network_dict, "type")
117 a96e84cf Christos Stavrakakis
118 a96e84cf Christos Stavrakakis
    if flavor not in Network.FLAVORS.keys():
119 a96e84cf Christos Stavrakakis
        raise api.faults.BadRequest("Invalid network type '%s'" % flavor)
120 a96e84cf Christos Stavrakakis
    if flavor not in settings.API_ENABLED_NETWORK_FLAVORS:
121 8d5795b4 Christos Stavrakakis
        raise api.faults.Forbidden("Cannot create network of type '%s'." %
122 a96e84cf Christos Stavrakakis
                                   flavor)
123 a96e84cf Christos Stavrakakis
124 a96e84cf Christos Stavrakakis
    name = api.utils.get_attribute(network_dict, "name", required=False)
125 a96e84cf Christos Stavrakakis
    if name is None:
126 a96e84cf Christos Stavrakakis
        name = ""
127 a96e84cf Christos Stavrakakis
128 a96e84cf Christos Stavrakakis
    network = networks.create(userid=userid, name=name, flavor=flavor,
129 a96e84cf Christos Stavrakakis
                              public=False)
130 a96e84cf Christos Stavrakakis
    networkdict = network_to_dict(network, detail=True)
131 0baa1e3d Buildbot
    response = render_network(request, networkdict, status=201)
132 77f45438 Christos Stavrakakis
133 77f45438 Christos Stavrakakis
    return response
134 0269afd6 Giorgos Verigakis
135 6ef51e9f Giorgos Verigakis
136 b3fd98ae Christos Stavrakakis
@api.api_method(http_method='GET', user_required=True, logger=log)
137 a96e84cf Christos Stavrakakis
def get_network_details(request, network_id):
138 0c37a721 Christos Stavrakakis
    log.debug('get_network_details %s', network_id)
139 a96e84cf Christos Stavrakakis
    network = util.get_network(network_id, request.user_uniq)
140 a96e84cf Christos Stavrakakis
    return render_network(request, network_to_dict(network, detail=True))
141 6ef51e9f Giorgos Verigakis
142 a96e84cf Christos Stavrakakis
143 a96e84cf Christos Stavrakakis
@api.api_method(http_method='PUT', user_required=True, logger=log)
144 a96e84cf Christos Stavrakakis
def update_network(request, network_id):
145 a96e84cf Christos Stavrakakis
    info = api.utils.get_request_dict(request)
146 a96e84cf Christos Stavrakakis
147 a96e84cf Christos Stavrakakis
    network = api.utils.get_attribute(info, "network", required=True)
148 a96e84cf Christos Stavrakakis
    new_name = api.utils.get_attribute(network, "name")
149 a96e84cf Christos Stavrakakis
150 a96e84cf Christos Stavrakakis
    network = util.get_network(network_id, request.user_uniq, for_update=True)
151 a96e84cf Christos Stavrakakis
    if network.public:
152 8d5795b4 Christos Stavrakakis
        raise api.faults.Forbidden("Cannot rename the public network.")
153 a96e84cf Christos Stavrakakis
    network = networks.rename(network, new_name)
154 a96e84cf Christos Stavrakakis
    return render_network(request, network_to_dict(network), 200)
155 0269afd6 Giorgos Verigakis
156 6ef51e9f Giorgos Verigakis
157 b3fd98ae Christos Stavrakakis
@api.api_method(http_method='DELETE', user_required=True, logger=log)
158 0baa1e3d Buildbot
@transaction.commit_on_success
159 b19653d1 Giorgos Verigakis
def delete_network(request, network_id):
160 bf5c82dc Christos Stavrakakis
    log.info('delete_network %s', network_id)
161 a96e84cf Christos Stavrakakis
    network = util.get_network(network_id, request.user_uniq, for_update=True)
162 a96e84cf Christos Stavrakakis
    if network.public:
163 8d5795b4 Christos Stavrakakis
        raise api.faults.Forbidden("Cannot delete the public network.")
164 a96e84cf Christos Stavrakakis
    networks.delete(network)
165 ece5581b Christos Stavrakakis
    return HttpResponse(status=204)
166 5061546f Christos Stavrakakis
167 5061546f Christos Stavrakakis
168 0baa1e3d Buildbot
def network_to_dict(network, detail=True):
169 0baa1e3d Buildbot
    d = {'id': str(network.id), 'name': network.name}
170 0baa1e3d Buildbot
    d['links'] = util.network_to_links(network.id)
171 0baa1e3d Buildbot
    if detail:
172 883c1f94 Christos Stavrakakis
        # Loop over subnets. Do not perform any extra query because of prefetch
173 883c1f94 Christos Stavrakakis
        # related!
174 883c1f94 Christos Stavrakakis
        subnet_ids = []
175 883c1f94 Christos Stavrakakis
        for subnet in network.subnets.all():
176 aff81af3 Christos Stavrakakis
            subnet_ids.append(subnet.id)
177 883c1f94 Christos Stavrakakis
178 8f335041 Christos Stavrakakis
        state = "SNF:DRAINED" if network.drained else network.state
179 0baa1e3d Buildbot
        d['user_id'] = network.userid
180 0baa1e3d Buildbot
        d['tenant_id'] = network.userid
181 0baa1e3d Buildbot
        d['type'] = network.flavor
182 a96e84cf Christos Stavrakakis
        d['updated'] = api.utils.isoformat(network.updated)
183 a96e84cf Christos Stavrakakis
        d['created'] = api.utils.isoformat(network.created)
184 8f335041 Christos Stavrakakis
        d['status'] = state
185 0baa1e3d Buildbot
        d['public'] = network.public
186 64209939 Christos Stavrakakis
        d['router:external'] = network.external_router
187 0baa1e3d Buildbot
        d['admin_state_up'] = True
188 883c1f94 Christos Stavrakakis
        d['subnets'] = subnet_ids
189 7421d45e Christos Stavrakakis
        d['SNF:floating_ip_pool'] = network.floating_ip_pool
190 0baa1e3d Buildbot
    return d
191 0baa1e3d Buildbot
192 0baa1e3d Buildbot
193 0baa1e3d Buildbot
def render_network(request, networkdict, status=200):
194 0baa1e3d Buildbot
    if request.serialization == 'xml':
195 0baa1e3d Buildbot
        data = render_to_string('network.xml', {'network': networkdict})
196 0baa1e3d Buildbot
    else:
197 0baa1e3d Buildbot
        data = json.dumps({'network': networkdict})
198 0baa1e3d Buildbot
    return HttpResponse(data, status=status)