Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / neutron / router_views.py @ 5cf968ab

History | View | Annotate | Download (10.1 kB)

1
from django.http import HttpResponse
2
from django.utils import simplejson as json
3
from django.db import transaction
4
from django.db.models import Q
5
from synnefo.db.pools import EmptyPool
6
from synnefo.db.utils import validate_mac
7
from django.conf import settings
8
from snf_django.lib import api
9
from snf_django.lib.api import utils
10
from synnefo.logic import backend
11
from django.template.loader import render_to_string
12
from synnefo.api import util
13

    
14
from synnefo.db.models import VirtualMachine
15
import models
16
import subnet_views
17
from logging import getLogger
18

    
19
import network_views as nv
20
#from synnefo.logic import servers
21

    
22
log = getLogger(__name__)
23

    
24

    
25
def demux(request):
26
    if request.method == 'GET':
27
        #return HttpResponse("list routers")
28
        return list_routers(request)
29
    elif request.method == 'POST':
30
        return create_router(request)
31
        #return HttpResponse("create router")
32
    else:
33
        return api.api_method_not_allowed(request)
34

    
35

    
36
def router_demux(request, offset):
37
    if request.method == 'GET':
38
        #return HttpResponse("get single router")
39
        return get_router(request,  offset)
40
    elif request.method == 'DELETE':
41
        #return HttpResponse("delete router")
42
        return delete_router(request, offset)
43
    elif request.method == 'PUT':
44
        #return HttpResponse("put router")
45
        return update_router(request, offset)
46
    else:
47
        return api.api_method_not_allowed(request)
48

    
49

    
50
def rinterface_demux(request, offset1, offset2):
51
    if request.method == 'PUT':
52
        if offset2 == "add_router_interface":
53
            #return HttpResponse("add interface")
54
            return add_interface(request, offset1)
55
        elif offset2 == "remove_router_interface":
56
            #return HttpResponse("remove interface")
57
            return remove_interface(request, offset1)
58
    else:
59
        return api.api_method_not_allowed(request)
60

    
61

    
62
@api.api_method(http_method='GET', user_required=True, logger=log)
63
def list_routers(request):
64
    log.debug('list_routers')
65

    
66
    user_routers = VirtualMachine.objects.filter(userid=request.user_uniq,
67
                                                 router=True)
68

    
69
    user_routers = utils.filter_modified_since(request, objects=user_routers)
70

    
71
    routers = [router_to_dict(router)
72
               for router in user_routers.order_by('id')]
73

    
74
    if request.serialization == 'xml':
75
        data = render_to_string('list_routers.xml', {
76
            'routers': routers})
77
    else:
78
        data = json.dumps({"routers": routers})
79

    
80
    return HttpResponse(data, status=200)
81

    
82

    
83
@api.api_method(http_method='POST', user_required=True, logger=log)
84
@transaction.commit_manually
85
def create_router(request):
86
    user_id = request.user_uniq
87
    req = utils.get_request_dict(request)
88

    
89
    try:
90
        server = req['router']
91
        name = server['name']
92
    except (KeyError, AssertionError):
93
        raise api.faults.BadRequest("Malformed request")
94

    
95
    try:
96
        netid = server[external_gateway_info]["network_id"]
97
        net = nv.get_network_fromdb(netid, request.user_uniq)
98
    except (KeyError, AssertionError):
99
        pass
100

    
101
    '''
102
    vm = servers.create(user_id,
103
                        name,
104
                        #password,
105
                        #flavor,
106
                        #image,
107
                        #metadata=metadata,
108
                        #personality=personality,
109
                        #private_networks=private_networks,
110
                        #floating_ips=floating_ips
111
                        )
112
    '''
113

    
114
    try:
115
        net
116
        mock_connect(vm, net)
117
    except NameError:
118
        pass
119
        #mock_connect(vm, random_public_net)
120

    
121
    server = router_to_dict(vm, detail=True)
122

    
123
    response = render_router(request, server, status=202)
124

    
125
    return response
126

    
127

    
128
@api.api_method(http_method='GET', user_required=True, logger=log)
129
def get_router(request, router_id):
130
    log.debug('get_router_details %s', router_id)
131
    router = util.get_vm(router_id, request.user_uniq)
132

    
133
    router_dict = router_to_dict(router)
134
    return render_router(request, router_dict)
135

    
136

    
137
@api.api_method(http_method='DELETE', user_required=True, logger=log)
138
@transaction.commit_on_success
139
def delete_router(request, router_id):
140
    log.debug('delete router  %s', router_id)
141
    router = util.get_vm(router_id, request.user_uniq)
142

    
143
    if router.neutron_networks.filter(public=False):
144
        return HttpResponse("There are internal interfaces on the router",
145
                            status=409)
146

    
147
    #servers.destroy(router)
148

    
149
    router.deleted = True
150
    router.save()
151
    return HttpResponse(status=204)
152

    
153

    
154
@api.api_method(http_method='PUT', user_required=True, logger=log)
155
def update_router(request, router_id):
156
    log.debug('update router %s', router_id)
157
    router = util.get_vm(router_id, request.user_uniq)
158

    
159
    req = utils.get_request_dict(request)
160
    try:
161
        server = req['router']
162
    except (KeyError, AssertionError):
163
        raise api.faults.BadRequest("Malformed request")
164

    
165
    try:
166
        name = server['name']
167
        router.name = name
168
    except KeyError:
169
        pass
170

    
171
    try:
172
        net = server['external_gateway_info']['network_id']
173

    
174
        #find the new network
175
        new_net = nv.get_network_fromdb(net, request.user_uniq)
176

    
177
        #disconnect from the old net
178
        external_net = router.neutron_networks.filter(public=True)
179
        if external_net:
180
            #servers.disconnect(router, external_net[0])
181
            mock_disconnect(router, external_net[0])
182

    
183
        #connect to the new net
184
        #servers.connect(router, new_net)
185
        mock_connect(router, new_net)
186
    except KeyError:
187
        pass
188

    
189
    router.save()
190
    routerdict = router_to_dict(router)
191
    return render_router(request, routerdict, 200)
192

    
193

    
194
@api.api_method(http_method='PUT', user_required=True, logger=log)
195
def add_interface(request, router_id):
196
    log.debug('add interface to router %s', router_id)
197
    info = utils.get_request_dict(request)
198
    router = util.get_vm(router_id, request.user_uniq)
199

    
200
    subnet = False
201
    try:
202
        subnet_id = info["subnet_id"]
203
        subnet = True
204
        subnet_obj = subnet_views.get_subnet_fromdb(subnet_id,
205
                                                    request.user_uniq)
206
    except KeyError:
207
        pass
208

    
209
    try:
210
        port_id = info['port_id']
211
        if subnet:
212
            raise api.faults.BadRequest("Both subnet and port provided")
213
        try:
214
            nic_obj = models.NetworkInterface.objects.get(id=port_id)
215
        except (ValueError, models.NetworkInterface.DoesNotExist):
216
            raise api.faults.ItemNotFound('Port not found')
217
        if not nic_obj.ipv4:
218
            raise api.faults.BadRequest("No ip-address")
219
        if nic_obj.machine:
220
            return HttpResponse(status=409)
221
    except KeyError:
222
        if not subnet:
223
            raise api.faults.BadRequest("Malformed request")
224

    
225
    if subnet:
226
        #create nic with the subnet and add to the vm
227
        nic_obj = models.NetworkInterface(machine=router,
228
                                          subnet=subnet_obj,
229
                                          network=subnet_obj.network,
230
                                          ipv4=subnet_obj.gateway)
231
        nic_obj.save()
232

    
233
    else:
234
        #connect the nic
235
        nic_obj.machine = router
236
        nic_obj.save()
237
    #FIX ME : do backend connection
238

    
239
    res = {"port_id": nic_obj.id,
240
           "subnet_id": nic_obj.subnet.id}
241

    
242
    data = json.dumps(res)
243
    return HttpResponse(data, status=200)
244

    
245

    
246
@api.api_method(http_method='PUT', user_required=True, logger=log)
247
def remove_interface(request, router_id):
248

    
249
    log.debug('remove interface from router %s', router_id)
250

    
251
    info = utils.get_request_dict(request)
252

    
253
    router = util.get_vm(router_id, request.user_uniq)
254
    subnet = False
255
    try:
256
        subnet_id = info["subnet_id"]
257
        subnet = True
258
        subnet_db = subnet_views.get_subnet_fromdb(subnet_id,
259
                                                   request.user_uniq)
260
    except KeyError:
261
        pass
262

    
263
    port = False
264
    try:
265
        port_id = info['port_id']
266
        port = True
267
        try:
268
            port_db = models.NetworkInterface.objects.get(id=port_id)
269
        except (ValueError, models.NetworkInterface.DoesNotExist):
270
            raise api.faults.ItemNotFound('Port not found')
271
    except KeyError:
272
        pass
273

    
274
    if (port and subnet):
275
        #validate port-subnet combination else return 409
276
        #subnet must be the first of the port
277
        if not (port_db.subnet.id == subnet_db.id):
278
            return HttpResponse(status=409)
279

    
280
    if subnet:
281
        #get the port
282
        try:
283
            port_db
284
        except NameError:
285
            try:
286
                port_db = subnet_db.neutron_nics.get(machine=router)
287
            except (ValueError, models.NetworkInterface.DoesNotExist):
288
                raise api.faults.ItemNotFound('Port not found')
289
    elif port:
290
        #get the subnet
291
        try:
292
            subnet_db
293
        except NameError:
294
            subnet_db = port_db.subnet
295
    else:
296
        raise api.faults.BadRequest("Malformed request")
297

    
298
    res = {"id": str(router.id),
299
           "tenant_id": request.user_uniq,
300
           "port_id": port_db.id,
301
           "subnet_id": subnet_db.id}
302

    
303
    port_db.delete()  # need to add backend stuff
304
    data = json.dumps(res)
305
    return HttpResponse(data, status=200)
306

    
307

    
308
# util functions
309

    
310

    
311
def router_to_dict(router):
312
    d = {'id': str(router.id), 'name': router.name}
313
    d['user_id'] = router.userid
314
    d['tenant_id'] = router.userid
315
    d['admin_state_up'] = True
316
    external_net = router.neutron_networks.filter(public=True)
317
    if external_net:
318
        external_net = external_net[0]
319
        d['external_gateway_info'] = {'network_id': external_net.id}
320
    else:
321
        d['external_gateway_info'] = None
322
    return d
323

    
324

    
325
def render_router(request, routerdict, status=200):
326
    if request.serialization == 'xml':
327
        data = render_to_string('router.xml', {'router': routerdict})
328
    else:
329
        data = json.dumps({'router': routerdict})
330
    return HttpResponse(data, status=status)
331

    
332

    
333
# mock functions
334

    
335
def mock_disconnect(router, net):
336
    nic = models.NetworkInterface.objects.get(network=net, machine=router)
337
    nic.delete()
338

    
339

    
340
def mock_connect(router, net):
341
    nic = models.NetworkInterface(network=net, machine=router)
342
    nic.save()