Revision 7eae8fce

b/snf-cyclades-app/synnefo/neutron/models.py
51 51
log = logging.getLogger(__name__)
52 52

  
53 53

  
54

  
55 54
class Network(models.Model):
56 55
    OPER_STATES = (
57 56
        ('PENDING', 'Pending'),  # Unused because of lazy networks
......
124 123
    state = models.CharField(choices=OPER_STATES, max_length=32,
125 124
                             default='PENDING')
126 125
    machines = models.ManyToManyField(VirtualMachine,
127
                                      through='NetworkInterface', related_name='neutron_machines')
126
                                      through='NetworkInterface',
127
                                      related_name='neutron_machines')
128 128
    action = models.CharField(choices=ACTIONS, max_length=32, null=True,
129 129
                              default=None)
130
    drained = models.BooleanField("Drained", default=False, null=False) # this is the opposite of admin_state_up
130
    drained = models.BooleanField("Drained", default=False, null=False)
131
    # this is the opposite of admin_state_up
131 132
    floating_ip_pool = models.BooleanField('Floating IP Pool', null=False,
132 133
                                           default=False)
133 134
    #serial = models.ForeignKey(QuotaHolderSerial, related_name='network',
......
211 212
        def __str__(self):
212 213
            return repr(str(self._action))
213 214

  
215

  
214 216
class Subnet(models.Model):
217
    subnet_id = models.CharField('ID of the subnet', max_length=128,
218
                                 null=True, db_index=True, primary_key=True)
219
    network = models.ForeignKey('Network')
215 220

  
216 221
    name = models.CharField('Network Name', max_length=128)
217
    subnet_id = models.CharField('ID of the subnet', max_length=128,
218
                              null=True, db_index=True)
219
    network_id = models.ForeignKey('Network')
220
    # subnet will be null for IPv6 only networks
221
    subnet = models.CharField('Subnet', max_length=32, null=True)
222
    ipversion = models.IntegerField('IP Version', default=4)
223
    cidr = models.CharField('Subnet', max_length=32, null=True)
224
    gateway = models.CharField('Gateway', max_length=32, null=True)
225
    #dns = models.
226
    #pools = models.
227
    #hostroutes = models.
228
    dhcp = models.BooleanField('DHCP', default=True)
229

  
230
    # Synnefo related fields
222 231
    # subnet6 will be null for IPv4 only networks
223 232
    subnet6 = models.CharField('IPv6 Subnet', max_length=64, null=True)
224
    gateway = models.CharField('Gateway', max_length=32, null=True)
225 233
    gateway6 = models.CharField('IPv6 Gateway', max_length=64, null=True)
226
    dhcp = models.BooleanField('DHCP', default=True)
234
    #dns_nameservers = models.
227 235
    #pool = models.OneToOneField('IPPoolTable', related_name='network',
228 236
    #                            default=lambda: IPPoolTable.objects.create(
229 237
    #                                                        available_map='',
......
231 239
    #                                                        size=0),
232 240
    #                           null=True)
233 241

  
242

  
234 243
class NetworkInterface(models.Model):
235 244
    STATES = (
236 245
        ("ACTIVE", "Active"),
b/snf-cyclades-app/synnefo/neutron/subnet_views.py
1
# Copyright 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 logging import getLogger
35
from snf_django.lib import api
36
from snf_django.lib.api import faults
37

  
1 38
from django.http import HttpResponse
2 39
from django.utils import simplejson as json
3 40

  
4
from snf_django.lib import api
5 41
from snf_django.lib.api import utils
6 42

  
7
from models import Network
43
from models import Subnet
8 44

  
9
from logging import getLogger
45
log = getLogger('synnefo.neutron')
10 46

  
11
log = getLogger(__name__)
12 47

  
13 48
def demux(request):
14 49
    if request.method == 'GET':
15
        return list_networks(request)
16
        #return HttpResponse("in subnet get")
50
        return list_subnets(request)
17 51
    elif request.method == 'POST':
18 52
        #return create_network(request)
19 53
        return HttpResponse("in subnet POST")
20 54
    else:
21 55
        return api.api_method_not_allowed(request)
22 56

  
23
def subnet_demux(request,offset):
57

  
58
def subnet_demux(request, offset):
24 59
    if request.method == 'GET':
25 60
        #return get_network(request,offset)
26 61
        return HttpResponse("in subnet det get")
......
33 68
    else:
34 69
        return api.api_method_not_allowed(request)
35 70

  
71

  
36 72
@api.api_method(http_method='GET', user_required=True, logger=log)
37
def list_networks(request):
38
    user_networks = Network.objects.all()
39
    networks_dict = [network_to_dict(net)
40
                    for net in user_networks.order_by('name')]
41
    data = json.dumps({'networks': networks_dict})
73
def list_subnets(request):
74
    '''Placeholder'''
75
    log.debug('list_subnets')
76

  
77
    user_subnets = Subnet.objects.filter(network__userid=request.user_uniq)
78
    subnets_dict = [subnet_to_dict(user_subnets)
79
                    for net in user_subnets.order_by('name')]
80
    data = json.dumps({'subnets': subnets_dict})
81

  
42 82
    return HttpResponse(data, status=200)
43 83

  
84

  
44 85
@api.api_method(http_method='POST', user_required=True, logger=log)
45
def create_network(request):
86
def create_subnet(request):
87
    '''Placeholder'''
46 88
    dic = utils.get_request_dict(request)
89

  
47 90
    try:
48
    	net = dic["network"]
49
    	name = net["name"]
50
    	user_id = request.user_uniq
91
        subnet = dic['subnet']
92
        network_id = subnet['network_id']
93
        cidr = subnet['cidr']
51 94
    except KeyError:
52
        raise api.faults.BadRequest("Wrong data")
53
    # get more info from the JSON
54
    new_net = Network(name=name,user_id=user_id)
95
        raise api.faults.BadRequest("Malformed request")
96

  
97
    ipversion = subnet.get('ip_version', '4')
98
    if ipversion != 4 or ipversion != 6:
99
        raise api.faults.BadRequests("Malformed IP version type")
100
    dhcp = subnet.get('enable_dhcp', True)
101
    name = subnet.get('name', None)
102

  
103
    # Returns the first available ip in the subnet
104
    potential_gateway = ipaddr.IPv4Network(cidr).network + 1
105
    gateway = subnet.get('gateway_ip', potential_gateway)
106

  
107
    ddnew_net = Network(name=name, user_id=user_id)
55 108
    new_net.save()
56 109
    net_dic = network_to_dict(new_net)
57
    data = json.dumps({'network':net_dic})
58
    return HttpResponse("hello world")
110
    data = json.dumps({'network': net_dic})
111

  
112
    #try:
113
    #    sub = Subnet.objects.create(name=name, network_id=network_id,
114
    #                                cidr=cidr, ipversion=ipversion,
115
    #                                gateway=gateway)
116
    return HttpResponse("test world")
117
    #return 1
59 118

  
60 119

  
61 120
@api.api_method(http_method='GET', user_required=True, logger=log)
62
def get_network(request,offset):
121
def get_subnet(request, offset):
122
    '''Placeholder'''
63 123
    try:
64
        net = Network.objects.get(id=offset)
65
    except Network.DoesNotExist:
66
        raise api.faults.ItemNotFound("Network not found")
124
        subnet = Subnet.objects.get(id=offset)
125
    except Subnet.DoesNotExist:
126
        raise api.faults.ItemNotFound("Subnet not found")
127

  
128
    subnet_dic = subnet_to_dict(subnet)
129
    data = json.dumps({'subnet': subnet_dic})
130
    return HttpResponse(data, status=200)
67 131

  
68
    net_dic = network_to_dict(net)
69
    data = json.dumps({'network': net_dic})
70
    return HttpResponse(data,status=200)
71 132

  
72 133
@api.api_method(http_method='DELETE', user_required=True, logger=log)
73
def delete_network(request,offset):
74
   try:
75
        net = Network.objects.get(id=offset)
76
   except Network.DoesNotExist:
77
        raise api.faults.ItemNotFound("Network not found")
134
def delete_subnet(request, offset):
135
    '''Placeholder'''
136
    try:
137
        subnet = Subnet.objects.get(id=offset)
138
    except Subnet.DoesNotExist:
139
        raise api.faults.ItemNotFound("Subnet not found")
140
        # Add support for 409 error, subnet in use
141

  
142
    subnet.delete()
143
    return HttpResponse(status=204)
78 144

  
79
   net.delete()
80
   return HttpResponse(status=204)
81 145

  
82 146
@api.api_method(http_method='PUT', user_required=True, logger=log)
83
def update_network(request,offset):
147
def update_network(request, offset):
84 148
    try:
85 149
        net = Network.objects.get(id=offset)
86 150
    except Network.DoesNotExist:
87 151
        raise api.faults.ItemNotFound("Network not found")
88 152
    info = utils.get_request_dict(request)
89
    updatable = set(["name","driver"])
153
    updatable = set(["name", "driver"])
90 154
    try:
91
		new_vals = info["network"]
155
        new_vals = info["network"]
92 156
    except Keyerror:
93 157
        raise api.faults.BadRequest()
94 158

  
95
    for key,val in new_vals.iteritems():
159
    for key, val in new_vals.iteritems():
96 160
        if key in updatable:
97
            setattr(net,key,val)
161
            setattr(net, key, val)
98 162
        else:
99 163
            raise api.faults.BadRequest()
100
	net.save()
164
        net.save()
101 165
    net_dic = network_to_dict(net)
102
    data = json.dumps({"network":net_dic})
166
    data = json.dumps({"network": net_dic})
103 167
    return HttpResponse(data)
104 168

  
105
def network_to_dict(net):
106
    d = dict(name=net.name,driver=net.driver,driver_ops=net.driver_ops,id=net.id,user_id=net.user_id)
107
    return d
108

  
109 169

  
170
def subnet_to_dict(subnet):
171
    '''Returns a dictionary containing the info of a subnet'''
172
    dic = dict(id=subnet.subnet_id, network_id=subnet.network.id,
173
               name=subnet.name, tenant_id=subnet.network.userid,
174
               gateway_ip=subnet.gateway, ip_version=subnet.ipversion,
175
               cidr=subnet.cidr, enable_dhcp=subnet.dhcp,
176
               dns_nameservers=subnet.dns)
177
               # , allocation_pools=subnet.pools,
178
               # host_routes=subneth.ostroutes, snf-gateway6=subnet.gateway6,
179
               # snf-subnet6=subnet.subnet6)
180
    return dic
b/snf-cyclades-app/synnefo/neutron/tests/api.py
7 7

  
8 8
NEUTRON_URL = get_service_path(cyclades_services, "neutron", "v2.0")
9 9
NETWORKS_URL = join_urls(NEUTRON_URL, "networks/")
10
SUBNETS_URL = join_urls(NEUTRON_URL, "subnets/")
10 11

  
11 12

  
12 13
class NetworkTest(BaseAPITest):
......
23 24
        self.assertEqual(code, 501)
24 25

  
25 26
    def test_get_unfound_network(self):
26
        url = join_urls(NETWORKS_URL,"123")
27
        url = join_urls(NETWORKS_URL, "123")
27 28
        response = self.get(url)
28 29
        self.assertItemNotFound(response)
29 30

  
30 31
    def test_delete_unfound_network(self):
31
        url = join_urls(NETWORKS_URL,"123")
32
        url = join_urls(NETWORKS_URL, "123")
32 33
        response = self.delete(url)
33 34
        self.assertItemNotFound(response)
34 35

  
35

  
36 36
    def marios(self):
37 37
        print "hello world"
38

  
39

  
40
class SubnetTest(BaseAPITest):
41
    def test_list_subnets(self):
42
        '''Test Subnet list'''
43
        response = self.get(SUBNETS_URL)
44
        print response
45
        self.assertSuccess(response)
46
        subnets = json.loads(response.content)
47
        self.assertEqual(subnets, {'subnets': []})

Also available in: Unified diff