Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (7.1 kB)

1
# Copyright 2011-2013 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
from django.conf import settings
35
from django.conf.urls import patterns
36
from django.http import HttpResponse
37
from django.utils import simplejson as json
38
from django.db import transaction
39
from django.db.models import Q
40
from django.template.loader import render_to_string
41

    
42
from snf_django.lib import api
43

    
44
from synnefo.api import util
45
from synnefo.db.models import Network
46
from synnefo.logic import networks
47

    
48
from logging import getLogger
49

    
50
log = getLogger(__name__)
51

    
52
urlpatterns = patterns(
53
    'synnefo.api.networks',
54
    (r'^(?:/|.json|.xml)?$', 'demux'),
55
    (r'^/detail(?:.json|.xml)?$', 'list_networks', {'detail': True}),
56
    (r'^/(\w+)(?:/|.json|.xml)?$', 'network_demux'))
57

    
58

    
59
def demux(request):
60
    if request.method == 'GET':
61
        return list_networks(request)
62
    elif request.method == 'POST':
63
        return create_network(request)
64
    else:
65
        return api.api_method_not_allowed(request,
66
                                          allowed_methods=['GET', 'POST'])
67

    
68

    
69
def network_demux(request, network_id):
70

    
71
    if request.method == 'GET':
72
        return get_network_details(request, network_id)
73
    elif request.method == 'DELETE':
74
        return delete_network(request, network_id)
75
    elif request.method == 'PUT':
76
        return update_network(request, network_id)
77
    else:
78
        return api.api_method_not_allowed(request,
79
                                          allowed_methods=['GET',
80
                                                           'PUT',
81
                                                           'DELETE'])
82

    
83

    
84
@api.api_method(http_method='GET', user_required=True, logger=log)
85
def list_networks(request, detail=False):
86
    log.debug('list_networks detail=%s', detail)
87

    
88
    user_networks = Network.objects.filter(Q(userid=request.user_uniq) |
89
                                           Q(public=True))\
90
                                   .prefetch_related("subnets")
91

    
92
    user_networks = api.utils.filter_modified_since(request,
93
                                                    objects=user_networks)
94

    
95
    network_dicts = [network_to_dict(network, detail)
96
                     for network in user_networks.order_by('id')]
97

    
98
    if request.serialization == 'xml':
99
        data = render_to_string('list_networks.xml', {
100
            "networks": network_dicts})
101
    else:
102
        data = json.dumps({'networks': network_dicts})
103

    
104
    return HttpResponse(data, status=200)
105

    
106

    
107
@api.api_method(http_method='POST', user_required=True, logger=log)
108
def create_network(request):
109
    userid = request.user_uniq
110
    req = api.utils.get_request_dict(request)
111
    log.info('create_network %s', req)
112

    
113
    network_dict = api.utils.get_attribute(req, "network")
114
    flavor = api.utils.get_attribute(network_dict, "type")
115

    
116
    if flavor not in Network.FLAVORS.keys():
117
        raise api.faults.BadRequest("Invalid network type '%s'" % flavor)
118
    if flavor not in settings.API_ENABLED_NETWORK_FLAVORS:
119
        raise api.faults.Forbidden("Cannot create network of type '%s'." %
120
                                   flavor)
121

    
122
    name = api.utils.get_attribute(network_dict, "name", required=False)
123
    if name is None:
124
        name = ""
125

    
126
    network = networks.create(userid=userid, name=name, flavor=flavor,
127
                              public=False)
128
    networkdict = network_to_dict(network, detail=True)
129
    response = render_network(request, networkdict, status=201)
130

    
131
    return response
132

    
133

    
134
@api.api_method(http_method='GET', user_required=True, logger=log)
135
def get_network_details(request, network_id):
136
    log.debug('get_network_details %s', network_id)
137
    network = util.get_network(network_id, request.user_uniq)
138
    return render_network(request, network_to_dict(network, detail=True))
139

    
140

    
141
@api.api_method(http_method='PUT', user_required=True, logger=log)
142
def update_network(request, network_id):
143
    info = api.utils.get_request_dict(request)
144

    
145
    network = api.utils.get_attribute(info, "network", required=True)
146
    new_name = api.utils.get_attribute(network, "name")
147

    
148
    network = util.get_network(network_id, request.user_uniq, for_update=True)
149
    if network.public:
150
        raise api.faults.Forbidden("Cannot rename the public network.")
151
    network = networks.rename(network, new_name)
152
    return render_network(request, network_to_dict(network), 200)
153

    
154

    
155
@api.api_method(http_method='DELETE', user_required=True, logger=log)
156
@transaction.commit_on_success
157
def delete_network(request, network_id):
158
    log.info('delete_network %s', network_id)
159
    network = util.get_network(network_id, request.user_uniq, for_update=True)
160
    if network.public:
161
        raise api.faults.Forbidden("Cannot delete the public network.")
162
    networks.delete(network)
163
    return HttpResponse(status=204)
164

    
165

    
166
def network_to_dict(network, detail=True):
167
    d = {'id': str(network.id), 'name': network.name}
168
    d['links'] = util.network_to_links(network.id)
169
    if detail:
170
        state = "SNF:DRAINED" if network.drained else network.state
171
        d['user_id'] = network.userid
172
        d['tenant_id'] = network.userid
173
        d['type'] = network.flavor
174
        d['updated'] = api.utils.isoformat(network.updated)
175
        d['created'] = api.utils.isoformat(network.created)
176
        d['status'] = state
177
        d['public'] = network.public
178
        d['router:external'] = network.external_router
179
        d['admin_state_up'] = True
180
        d['subnets'] = list(network.subnets.values_list('id', flat=True))
181
        d['SNF:floating_ip_pool'] = network.floating_ip_pool
182
    return d
183

    
184

    
185
def render_network(request, networkdict, status=200):
186
    if request.serialization == 'xml':
187
        data = render_to_string('network.xml', {'network': networkdict})
188
    else:
189
        data = json.dumps({'network': networkdict})
190
    return HttpResponse(data, status=status)