Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / neutron / subnet_views.py @ 2e0916f2

History | View | Annotate | Download (7 kB)

1 7eae8fce Dionysis Grigoropoulos
# Copyright 2013 GRNET S.A. All rights reserved.
2 7eae8fce Dionysis Grigoropoulos
#
3 7eae8fce Dionysis Grigoropoulos
# Redistribution and use in source and binary forms, with or
4 7eae8fce Dionysis Grigoropoulos
# without modification, are permitted provided that the following
5 7eae8fce Dionysis Grigoropoulos
# conditions are met:
6 7eae8fce Dionysis Grigoropoulos
#
7 7eae8fce Dionysis Grigoropoulos
#   1. Redistributions of source code must retain the above
8 7eae8fce Dionysis Grigoropoulos
#      copyright notice, this list of conditions and the following
9 7eae8fce Dionysis Grigoropoulos
#      disclaimer.
10 7eae8fce Dionysis Grigoropoulos
#
11 7eae8fce Dionysis Grigoropoulos
#   2. Redistributions in binary form must reproduce the above
12 7eae8fce Dionysis Grigoropoulos
#      copyright notice, this list of conditions and the following
13 7eae8fce Dionysis Grigoropoulos
#      disclaimer in the documentation and/or other materials
14 7eae8fce Dionysis Grigoropoulos
#      provided with the distribution.
15 7eae8fce Dionysis Grigoropoulos
#
16 7eae8fce Dionysis Grigoropoulos
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 7eae8fce Dionysis Grigoropoulos
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 7eae8fce Dionysis Grigoropoulos
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 7eae8fce Dionysis Grigoropoulos
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 7eae8fce Dionysis Grigoropoulos
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 7eae8fce Dionysis Grigoropoulos
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 7eae8fce Dionysis Grigoropoulos
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 7eae8fce Dionysis Grigoropoulos
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 7eae8fce Dionysis Grigoropoulos
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 7eae8fce Dionysis Grigoropoulos
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 7eae8fce Dionysis Grigoropoulos
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 7eae8fce Dionysis Grigoropoulos
# POSSIBILITY OF SUCH DAMAGE.
28 7eae8fce Dionysis Grigoropoulos
#
29 7eae8fce Dionysis Grigoropoulos
# The views and conclusions contained in the software and
30 7eae8fce Dionysis Grigoropoulos
# documentation are those of the authors and should not be
31 7eae8fce Dionysis Grigoropoulos
# interpreted as representing official policies, either expressed
32 7eae8fce Dionysis Grigoropoulos
# or implied, of GRNET S.A.
33 7eae8fce Dionysis Grigoropoulos
34 7eae8fce Dionysis Grigoropoulos
from logging import getLogger
35 7eae8fce Dionysis Grigoropoulos
from snf_django.lib import api
36 7eae8fce Dionysis Grigoropoulos
from snf_django.lib.api import faults
37 7eae8fce Dionysis Grigoropoulos
38 d6b24130 Marios Kogias
from django.http import HttpResponse
39 d6b24130 Marios Kogias
from django.utils import simplejson as json
40 d6b24130 Marios Kogias
41 d6b24130 Marios Kogias
from snf_django.lib.api import utils
42 0dae1b9f Dionysis Grigoropoulos
from models import Subnet, Network
43 f261896d Dionysis Grigoropoulos
from synnefo.logic import networks
44 f261896d Dionysis Grigoropoulos
45 0dae1b9f Dionysis Grigoropoulos
from ipaddr import IPv4Network, IPv6Network
46 d6b24130 Marios Kogias
47 882b662f Dionysis Grigoropoulos
log = getLogger(__name__)
48 d6b24130 Marios Kogias
49 d6b24130 Marios Kogias
50 d6b24130 Marios Kogias
def demux(request):
51 d6b24130 Marios Kogias
    if request.method == 'GET':
52 7eae8fce Dionysis Grigoropoulos
        return list_subnets(request)
53 d6b24130 Marios Kogias
    elif request.method == 'POST':
54 882b662f Dionysis Grigoropoulos
        return create_subnet(request)
55 d6b24130 Marios Kogias
    else:
56 d6b24130 Marios Kogias
        return api.api_method_not_allowed(request)
57 d6b24130 Marios Kogias
58 7eae8fce Dionysis Grigoropoulos
59 0dae1b9f Dionysis Grigoropoulos
def subnet_demux(request, sub_id):
60 d6b24130 Marios Kogias
    if request.method == 'GET':
61 0dae1b9f Dionysis Grigoropoulos
        return get_subnet(request, sub_id)
62 d6b24130 Marios Kogias
    elif request.method == 'DELETE':
63 0dae1b9f Dionysis Grigoropoulos
        return delete_subnet(request, sub_id)
64 d6b24130 Marios Kogias
    elif request.method == 'PUT':
65 0dae1b9f Dionysis Grigoropoulos
        return update_subnet(request, sub_id)
66 d6b24130 Marios Kogias
    else:
67 d6b24130 Marios Kogias
        return api.api_method_not_allowed(request)
68 d6b24130 Marios Kogias
69 7eae8fce Dionysis Grigoropoulos
70 d6b24130 Marios Kogias
@api.api_method(http_method='GET', user_required=True, logger=log)
71 7eae8fce Dionysis Grigoropoulos
def list_subnets(request):
72 6de57f9c Dionysis Grigoropoulos
    '''List all subnets of a user'''
73 7eae8fce Dionysis Grigoropoulos
    log.debug('list_subnets')
74 7eae8fce Dionysis Grigoropoulos
75 7eae8fce Dionysis Grigoropoulos
    user_subnets = Subnet.objects.filter(network__userid=request.user_uniq)
76 0dae1b9f Dionysis Grigoropoulos
    subnets_dict = [subnet_to_dict(sub)
77 0dae1b9f Dionysis Grigoropoulos
                    for sub in user_subnets.order_by('id')]
78 7eae8fce Dionysis Grigoropoulos
    data = json.dumps({'subnets': subnets_dict})
79 7eae8fce Dionysis Grigoropoulos
80 d6b24130 Marios Kogias
    return HttpResponse(data, status=200)
81 d6b24130 Marios Kogias
82 7eae8fce Dionysis Grigoropoulos
83 d6b24130 Marios Kogias
@api.api_method(http_method='POST', user_required=True, logger=log)
84 7eae8fce Dionysis Grigoropoulos
def create_subnet(request):
85 f261896d Dionysis Grigoropoulos
    '''Create a subnet'''
86 882b662f Dionysis Grigoropoulos
87 0dae1b9f Dionysis Grigoropoulos
    dictionary = utils.get_request_dict(request)
88 0dae1b9f Dionysis Grigoropoulos
    log.info('create subnet %s', dictionary)
89 f261896d Dionysis Grigoropoulos
    user_id = request.user_uniq
90 7eae8fce Dionysis Grigoropoulos
91 d6b24130 Marios Kogias
    try:
92 0dae1b9f Dionysis Grigoropoulos
        subnet = dictionary['subnet']
93 7eae8fce Dionysis Grigoropoulos
        network_id = subnet['network_id']
94 7eae8fce Dionysis Grigoropoulos
        cidr = subnet['cidr']
95 d6b24130 Marios Kogias
    except KeyError:
96 7eae8fce Dionysis Grigoropoulos
        raise api.faults.BadRequest("Malformed request")
97 7eae8fce Dionysis Grigoropoulos
98 0dae1b9f Dionysis Grigoropoulos
    try:
99 0dae1b9f Dionysis Grigoropoulos
        network = Network.objects.get(id=network_id)
100 0dae1b9f Dionysis Grigoropoulos
    except Network.DoesNotExist:
101 0dae1b9f Dionysis Grigoropoulos
        raise api.faults.ItemNotFound("No networks found with that id")
102 0dae1b9f Dionysis Grigoropoulos
103 0dae1b9f Dionysis Grigoropoulos
    if user_id != network.userid:
104 0dae1b9f Dionysis Grigoropoulos
        raise api.faults.Unauthorized("Unauthorized operation")
105 0dae1b9f Dionysis Grigoropoulos
106 f261896d Dionysis Grigoropoulos
    ipversion = subnet.get('ip_version', 4)
107 f261896d Dionysis Grigoropoulos
    if ipversion not in [4, 6]:
108 882b662f Dionysis Grigoropoulos
        raise api.faults.BadRequest("Malformed IP version type")
109 f261896d Dionysis Grigoropoulos
110 7eae8fce Dionysis Grigoropoulos
    dhcp = subnet.get('enable_dhcp', True)
111 882b662f Dionysis Grigoropoulos
    if dhcp not in [True, False]:
112 0dae1b9f Dionysis Grigoropoulos
        raise api.faults.BadRequest("Malformed request, enable_dhcp must be "
113 0dae1b9f Dionysis Grigoropoulos
                                    "True or False")
114 7eae8fce Dionysis Grigoropoulos
    name = subnet.get('name', None)
115 882b662f Dionysis Grigoropoulos
    if len(str(name)) > Subnet.SUBNET_NAME_LENGTH:
116 882b662f Dionysis Grigoropoulos
        raise api.faults.BadRequest("Subnet name too long")
117 7eae8fce Dionysis Grigoropoulos
118 882b662f Dionysis Grigoropoulos
    # Returns the first available IP in the subnet
119 0dae1b9f Dionysis Grigoropoulos
    if ipversion == 6:
120 0dae1b9f Dionysis Grigoropoulos
        potential_gateway = IPv6Network(cidr).network + 1
121 0dae1b9f Dionysis Grigoropoulos
        check_number_of_subnets(network, 6)
122 0dae1b9f Dionysis Grigoropoulos
    else:
123 0dae1b9f Dionysis Grigoropoulos
        potential_gateway = IPv4Network(cidr).network + 1
124 0dae1b9f Dionysis Grigoropoulos
        check_number_of_subnets(network, 4)
125 7eae8fce Dionysis Grigoropoulos
126 0dae1b9f Dionysis Grigoropoulos
    gateway = subnet.get('gateway_ip', potential_gateway)
127 0dae1b9f Dionysis Grigoropoulos
    networks.validate_network_params(cidr, gateway)
128 f261896d Dionysis Grigoropoulos
129 882b662f Dionysis Grigoropoulos
    # FIX ME
130 f261896d Dionysis Grigoropoulos
    try:
131 0dae1b9f Dionysis Grigoropoulos
        sub = Subnet.objects.create(name=name, network=network, cidr=cidr,
132 0dae1b9f Dionysis Grigoropoulos
                                    ipversion=ipversion, gateway=gateway,
133 0dae1b9f Dionysis Grigoropoulos
                                    dhcp=dhcp)
134 f261896d Dionysis Grigoropoulos
    except:
135 0dae1b9f Dionysis Grigoropoulos
        return "Error"
136 7eae8fce Dionysis Grigoropoulos
137 0dae1b9f Dionysis Grigoropoulos
    return HttpResponse(sub, status=200)
138 d6b24130 Marios Kogias
139 d6b24130 Marios Kogias
140 d6b24130 Marios Kogias
@api.api_method(http_method='GET', user_required=True, logger=log)
141 0dae1b9f Dionysis Grigoropoulos
def get_subnet(request, sub_id):
142 6de57f9c Dionysis Grigoropoulos
    '''Show info of a specific subnet'''
143 0dae1b9f Dionysis Grigoropoulos
    log.debug('get_subnet %s', sub_id)
144 0dae1b9f Dionysis Grigoropoulos
    user_id = request.user_uniq
145 0dae1b9f Dionysis Grigoropoulos
146 d6b24130 Marios Kogias
    try:
147 0dae1b9f Dionysis Grigoropoulos
        subnet = Subnet.objects.get(id=sub_id)
148 7eae8fce Dionysis Grigoropoulos
    except Subnet.DoesNotExist:
149 7eae8fce Dionysis Grigoropoulos
        raise api.faults.ItemNotFound("Subnet not found")
150 7eae8fce Dionysis Grigoropoulos
151 0dae1b9f Dionysis Grigoropoulos
    if subnet.network.userid != user_id:
152 0dae1b9f Dionysis Grigoropoulos
        raise api.failts.Unauthorized("You're not allowed to view this subnet")
153 0dae1b9f Dionysis Grigoropoulos
154 0dae1b9f Dionysis Grigoropoulos
    subnet_dict = subnet_to_dict(subnet)
155 0dae1b9f Dionysis Grigoropoulos
    data = json.dumps({'subnet': subnet_dict})
156 7eae8fce Dionysis Grigoropoulos
    return HttpResponse(data, status=200)
157 d6b24130 Marios Kogias
158 d6b24130 Marios Kogias
159 d6b24130 Marios Kogias
@api.api_method(http_method='DELETE', user_required=True, logger=log)
160 0dae1b9f Dionysis Grigoropoulos
def delete_subnet(request, sub_id):
161 0dae1b9f Dionysis Grigoropoulos
    '''Delete a subnet -- Operation not allowed'''
162 882b662f Dionysis Grigoropoulos
    raise api.faults.BadRequest("Deletion of a subnet is not supported")
163 d6b24130 Marios Kogias
164 d6b24130 Marios Kogias
165 2e0916f2 Marios Kogias
166 0dae1b9f Dionysis Grigoropoulos
@api.api_method(http_method='PUT', user_required=True, logger=log)
167 0dae1b9f Dionysis Grigoropoulos
def update_subnet(request, sub_id):
168 0dae1b9f Dionysis Grigoropoulos
    '''Update info of a subnet'''
169 0dae1b9f Dionysis Grigoropoulos
170 0dae1b9f Dionysis Grigoropoulos
171 2e0916f2 Marios Kogias
# util functions
172 2e0916f2 Marios Kogias
173 2e0916f2 Marios Kogias
174 7eae8fce Dionysis Grigoropoulos
def subnet_to_dict(subnet):
175 7eae8fce Dionysis Grigoropoulos
    '''Returns a dictionary containing the info of a subnet'''
176 f261896d Dionysis Grigoropoulos
    # FIX ME, allocation pools
177 0dae1b9f Dionysis Grigoropoulos
    dictionary = dict({'id': subnet.id, 'network_id': subnet.network.id,
178 0dae1b9f Dionysis Grigoropoulos
                       'name': subnet.name, 'tenant_id': subnet.network.userid,
179 0dae1b9f Dionysis Grigoropoulos
                       'gateway_ip': subnet.gateway,
180 0dae1b9f Dionysis Grigoropoulos
                       'ip_version': subnet.ipversion, 'cidr': subnet.cidr,
181 0dae1b9f Dionysis Grigoropoulos
                       'enable_dhcp': subnet.dhcp, 'dns_nameservers': [],
182 0dae1b9f Dionysis Grigoropoulos
                       'host_routes': [], 'allocation_pools': []})
183 0dae1b9f Dionysis Grigoropoulos
    return dictionary
184 0dae1b9f Dionysis Grigoropoulos
185 0dae1b9f Dionysis Grigoropoulos
186 0dae1b9f Dionysis Grigoropoulos
def check_number_of_subnets(network, version):
187 0dae1b9f Dionysis Grigoropoulos
    '''Checks if a user can add a subnet in a network'''
188 0dae1b9f Dionysis Grigoropoulos
    if network.subnet_set.filter(ipversion=version):
189 0dae1b9f Dionysis Grigoropoulos
        raise api.faults.BadRequest("Only one subnet of IPv4/IPv6 per "
190 0dae1b9f Dionysis Grigoropoulos
                                    "network is allowed")
191 2e0916f2 Marios Kogias
192 2e0916f2 Marios Kogias
def get_subnet_fromdb(subnet_id, user_id, for_update=False):
193 2e0916f2 Marios Kogias
    """
194 2e0916f2 Marios Kogias
    Return a Subnet instance or raise ItemNotFound.
195 2e0916f2 Marios Kogias
    This is the same as util.get_network
196 2e0916f2 Marios Kogias
    """
197 2e0916f2 Marios Kogias
    try:
198 2e0916f2 Marios Kogias
        subnet_id = int(subnet_id)
199 2e0916f2 Marios Kogias
        objects = Subnet.objects
200 2e0916f2 Marios Kogias
        if for_update:
201 2e0916f2 Marios Kogias
            objects = objects.select_for_update()
202 2e0916f2 Marios Kogias
        return objects.get(userid=user_id, id=subnet_id)
203 2e0916f2 Marios Kogias
    except (ValueError, Subnet.DoesNotExist):
204 2e0916f2 Marios Kogias
        raise api.faults.ItemNotFound('Network not found.')