Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (10.3 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
from logging import getLogger
17

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

    
21
log = getLogger(__name__)
22

    
23

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

    
34

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

    
48

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

    
60

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

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

    
67
    user_routers = utils.filter_modified_since(request, objects=user_routers)
68

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

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

    
78
    return HttpResponse(data, status=200)
79

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

87
    try:
88
        server = req['router']
89
        name = server['name']
90
    except (KeyError, AssertionError):
91
        raise api.faults.BadRequest("Malformed request")
92
    metadata = server.get('metadata', {})
93
    assert isinstance(metadata, dict)
94
    image_id = server['imageRef']
95
    flavor_id = server['flavorRef']
96
    personality = server.get('personality', [])
97
    assert isinstance(personality, list)
98
    private_networks = server.get("networks", [])
99
    assert isinstance(private_networks, list)
100
    floating_ips = server.get("floating_ips", [])
101
    assert isinstance(floating_ips, list)
102
    # Verify that personalities are well-formed
103
    util.verify_personality(personality)
104
    # Get image information
105
    image = util.get_image_dict(image_id, user_id)
106
    # Get flavor (ensure it is active)
107
    flavor = util.get_flavor(flavor_id, include_deleted=False)
108
    # Generate password
109
    password = util.random_password()
110
    vm = servers.create(user_id,
111
                        name,
112
                        #password,
113
                        #flavor,
114
                        #image,
115
                        #metadata=metadata,
116
                        #personality=personality,
117
                        #private_networks=private_networks,
118
                        #floating_ips=floating_ips
119
                        )
120

121
    server = router_to_dict(vm, detail=True)
122
    server['status'] = 'BUILD'
123
    server['adminPass'] = password
124

125
    response = render_router(request, server, status=202)
126

127
    return response
128

129

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

    
136
    router_dict = router_to_dict(router)
137
    return render_router(request, router_dict)
138

    
139

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

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

    
149
    #servers.destroy(router)
150

    
151
    router.deleted = True
152
    router.save()
153
    return HttpResponse(status=204)
154

    
155

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

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

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

    
173
    try:
174
        net = server['external_gateway_info']['network_id']
175

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

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

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

    
191
    router.save()
192
    routerdict = router_to_dict(router)
193
    return render_router(request, routerdict, 200)
194

    
195

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

    
201
    router_info = utils.get_request_dict(request)
202

    
203
    subnet = False
204
    try:
205
        subnet_id = router_info["subnet_id"]
206
        subnet = True
207
        subnet_obj = subnet_views.get_subnet_fromdb(subnet_id,
208
                                        request.user_unique)
209
    except KeyError:
210
        pass
211

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

    
228
    if subnet:
229
        #create nic with the subnet and add to the vm
230
        nic = models.NetworkInteface(machine=router,
231
                                    subnet=subnet_obj,
232
                                    network=subnet_obj.network
233
                                    ipv4=subnet.gateway
234
                                    )
235
        nic.save()
236
        port_id = nic.id
237
    else:
238
        #connect the nic
239
        nic_obj.machine = router
240
        nic_obj.save()
241
        subnet_id = nic.subnet.id
242

    
243
    res = {"port_id":port_db.id,
244
            "subnet_id":subnet_db.id
245
          }
246

    
247
    data = json.dumps(res)
248
    return HttpResponse(data, status=200)
249

    
250
@api.api_method(http_method='PUT', user_required=True, logger=log)
251
def remove_interface(request, router_id):
252

    
253
    log.debug('remove interface from router %s', router_id)
254
    router = util.get_vm(router_id, request.user_uniq)
255

    
256
    info = utils.get_request_dict(request)
257

    
258
    subnet = False
259
    try:
260
        subnet_id = info["subnet_id"]
261
        subnet = True
262
        subnet_db = subnet_views.get_subnet_fromdb(subnet_id,
263
                                request.user_unique)
264
    except KeyError:
265
        pass
266

    
267
    port = False
268
    try:
269
        port_id = info['port_id']
270
        port = True
271
        try:
272
            nic_obj = models.NetworkInteface.objects.get(id=port_id)
273
        except (ValueError, models.NetworkInteraface.DoesNotExist):
274
            raise api.faults.ItemNotFound('Port not found')
275
    except KeyError:
276
        pass
277

    
278
    if port and subnet:
279
        #validate port-subnet combination else return 409
280
        #subnet must be the first of the port
281
        if not port_db is subnet_db:
282
            return HttpResponse(status=409)
283

    
284
    if subnet:
285
        #get the port
286
        if not port_db:
287
            port_db = subnet_db.neutron_nics.get(machine=router)
288
    elif port:
289
        #get the subnet
290
        if not subnet_db:
291
            subnet_db = port_db.subnet
292
    else:
293
        raise api.faults.BadRequest("Malformed request")
294

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

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

    
305

    
306
# util functions
307

    
308

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

    
322

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

    
330

    
331
# mock functions
332

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

    
337
def mock_connect(router, net):
338
    nic = models.NetworkInterface(network=net, machine=router)
339
    nic.save()