Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / api / tests / ports.py @ 14402edc

History | View | Annotate | Download (16.3 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.i
33

    
34
from django.conf import settings
35
from snf_django.utils.testing import BaseAPITest, override_settings
36
from django.utils import simplejson as json
37
from synnefo.cyclades_settings import cyclades_services
38
from synnefo.lib.services import get_service_path
39
from synnefo.lib import join_urls
40
from mock import patch
41
import synnefo.db.models_factory as dbmf
42

    
43
NETWORK_URL = get_service_path(cyclades_services, 'network',
44
                               version='v2.0')
45
PORTS_URL = join_urls(NETWORK_URL, "ports/")
46

    
47

    
48
class PortTest(BaseAPITest):
49
    def test_get_ports(self):
50
        url = join_urls(PORTS_URL)
51
        response = self.get(url)
52
        self.assertEqual(response.status_code, 200)
53
        ports = json.loads(response.content)
54
        self.assertEqual(ports, {"ports": []})
55

    
56
    def test_get_port_unfound(self):
57
        url = join_urls(PORTS_URL, "123")
58
        response = self.get(url)
59
        self.assertEqual(response.status_code, 404)
60

    
61
    def test_get_port(self):
62
        nic = dbmf.NetworkInterfaceFactory()
63
        url = join_urls(PORTS_URL, str(nic.id))
64
        response = self.get(url, user=nic.userid)
65
        self.assertEqual(response.status_code, 200)
66

    
67
    @patch("synnefo.db.models.get_rapi_client")
68
    def test_delete_port(self, mrapi):
69
        nic = dbmf.NetworkInterfaceFactory(device_owner='vm')
70
        url = join_urls(PORTS_URL, str(nic.id))
71
        mrapi().ModifyInstance.return_value = 42
72
        with override_settings(settings, GANETI_USE_HOTPLUG=True):
73
            response = self.delete(url, user=nic.userid)
74
        self.assertEqual(response.status_code, 204)
75
        with override_settings(settings, GANETI_USE_HOTPLUG=False):
76
            response = self.delete(url, user=nic.userid)
77
        self.assertEqual(response.status_code, 400)
78

    
79
    def test_remove_nic_malformed(self):
80
        url = join_urls(PORTS_URL, "123")
81
        response = self.delete(url)
82
        self.assertItemNotFound(response)
83

    
84
    def test_update_port_name(self):
85
        nic = dbmf.NetworkInterfaceFactory(device_owner='vm')
86
        url = join_urls(PORTS_URL, str(nic.id))
87
        request = {'port': {"name": "test-name"}}
88
        response = self.put(url, params=json.dumps(request),
89
                            user=nic.userid)
90
        self.assertEqual(response.status_code, 200)
91
        res = json.loads(response.content)
92
        self.assertEqual(res['port']['name'], "test-name")
93

    
94
    # def test_update_port_sg_unfound(self):
95
    #     sg1 = dbmf.SecurityGroupFactory()
96
    #     nic = dbmf.NetworkInterfaceFactory(device_owner='vm')
97
    #     nic.security_groups.add(sg1)
98
    #     nic.save()
99
    #     url = join_urls(PORTS_URL, str(nic.id))
100
    #     request = {'port': {"security_groups": ["123"]}}
101
    #     response = self.put(url, params=json.dumps(request),
102
    #                         user=nic.userid)
103
    #     self.assertEqual(response.status_code, 404)
104

    
105
    # def test_update_port_sg(self):
106
    #     sg1 = dbmf.SecurityGroupFactory()
107
    #     sg2 = dbmf.SecurityGroupFactory()
108
    #     sg3 = dbmf.SecurityGroupFactory()
109
    #     nic = dbmf.NetworkInterfaceFactory(device_owner='vm')
110
    #     nic.security_groups.add(sg1)
111
    #     nic.save()
112
    #     url = join_urls(PORTS_URL, str(nic.id))
113
    #     request = {'port': {"security_groups": [str(sg2.id), str(sg3.id)]}}
114
    #     response = self.put(url, params=json.dumps(request),
115
    #                         user=nic.userid)
116
    #     res = json.loads(response.content)
117
    #     self.assertEqual(res['port']['security_groups'],
118
    #                      [str(sg2.id), str(sg3.id)])
119

    
120
    def test_create_port_invalid(self):
121
        # No network
122
        request = {
123
            "port": {
124
                "device_id": "123",
125
                "name": "port1",
126
                "network_id": "123"
127
            }
128
        }
129
        response = self.post(PORTS_URL, params=json.dumps(request))
130
        self.assertEqual(response.status_code, 404)
131
        net = dbmf.NetworkFactory(public=True)
132
        request = {
133
            "port": {
134
                "name": "port1",
135
                "network_id": net.id,
136
                "fixed_ips": ["lala"]
137
            }
138
        }
139
        response = self.post(PORTS_URL, params=json.dumps(request))
140
        self.assertEqual(response.status_code, 400, response.content)
141

    
142
    @patch("synnefo.db.models.get_rapi_client")
143
    def test_create_port_private_net(self, mrapi):
144
        net = dbmf.NetworkFactory(public=False)
145
        dbmf.IPv4SubnetFactory(network=net)
146
        dbmf.IPv6SubnetFactory(network=net)
147
        sg1 = dbmf.SecurityGroupFactory()
148
        sg2 = dbmf.SecurityGroupFactory()
149
        vm = dbmf.VirtualMachineFactory(userid=net.userid)
150
        request = {
151
            "port": {
152
                "name": "port1",
153
                "network_id": str(net.id),
154
                "device_id": str(vm.id),
155
                "security_groups": [str(sg1.id), str(sg2.id)]
156
            }
157
        }
158
        mrapi().ModifyInstance.return_value = 42
159
        with override_settings(settings, GANETI_USE_HOTPLUG=False):
160
            response = self.post(PORTS_URL, params=json.dumps(request),
161
                                 user=net.userid)
162
        self.assertEqual(response.status_code, 400)
163
        with override_settings(settings, GANETI_USE_HOTPLUG=True):
164
            response = self.post(PORTS_URL, params=json.dumps(request),
165
                                 user=net.userid)
166
        self.assertEqual(response.status_code, 201)
167

    
168
    def test_create_port_public_net_no_ip(self):
169
        net = dbmf.NetworkFactory(public=True)
170
        vm = dbmf.VirtualMachineFactory(userid=net.userid)
171
        request = {
172
            "port": {
173
                "name": "port1",
174
                "network_id": str(net.id),
175
                "device_id": str(vm.id),
176
            }
177
        }
178
        response = self.post(PORTS_URL, params=json.dumps(request),
179
                             user=net.userid)
180
        self.assertEqual(response.status_code, 400)
181

    
182
    def test_create_port_public_net_wrong_ip(self):
183
        net = dbmf.NetworkFactory(public=True)
184
        vm = dbmf.VirtualMachineFactory(userid=net.userid)
185
        request = {
186
            "port": {
187
                "name": "port1",
188
                "network_id": str(net.id),
189
                "device_id": str(vm.id),
190
                "fixed_ips": [{"ip_address": "8.8.8.8"}]
191
            }
192
        }
193
        response = self.post(PORTS_URL, params=json.dumps(request),
194
                             user=net.userid)
195
        self.assertEqual(response.status_code, 404)
196

    
197
    def test_create_port_public_net_conflict(self):
198
        net = dbmf.NetworkFactory(public=True)
199
        fip = dbmf.FloatingIPFactory(nic=None, userid=net.userid)
200
        vm = dbmf.VirtualMachineFactory(userid=net.userid)
201
        request = {
202
            "port": {
203
                "name": "port1",
204
                "network_id": str(net.id),
205
                "device_id": str(vm.id),
206
                "fixed_ips": [{"ip_address": fip.address}]
207
            }
208
        }
209
        response = self.post(PORTS_URL, params=json.dumps(request),
210
                             user=net.userid)
211
        self.assertEqual(response.status_code, 409)
212

    
213
    def test_create_port_public_net_taken_ip(self):
214
        net = dbmf.NetworkFactory(public=True)
215
        fip = dbmf.FloatingIPFactory(network=net, userid=net.userid)
216
        vm = dbmf.VirtualMachineFactory(userid=net.userid)
217
        request = {
218
            "port": {
219
                "name": "port1",
220
                "network_id": str(net.id),
221
                "device_id": str(vm.id),
222
                "fixed_ips": [{"ip_address": fip.address}]
223
            }
224
        }
225
        response = self.post(PORTS_URL, params=json.dumps(request),
226
                             user=net.userid)
227
        self.assertEqual(response.status_code, 409)
228

    
229
    @patch("synnefo.db.models.get_rapi_client")
230
    def test_create_port_with_floating_ip(self, mrapi):
231
        vm = dbmf.VirtualMachineFactory()
232
        fip = dbmf.FloatingIPFactory(network__public=True, nic=None,
233
                                     userid=vm.userid)
234
        request = {
235
            "port": {
236
                "name": "port1",
237
                "network_id": str(fip.network_id),
238
                "device_id": str(vm.id),
239
                "fixed_ips": [{"ip_address": fip.address}]
240
            }
241
        }
242
        mrapi().ModifyInstance.return_value = 42
243
        with override_settings(settings, GANETI_USE_HOTPLUG=True):
244
            response = self.post(PORTS_URL, params=json.dumps(request),
245
                                 user=vm.userid)
246
        self.assertEqual(response.status_code, 201)
247

    
248
    @patch("synnefo.db.models.get_rapi_client")
249
    def test_create_port_with_address(self, mrapi):
250
        """Test creation if IP address is specified."""
251
        mrapi().ModifyInstance.return_value = 42
252
        vm = dbmf.VirtualMachineFactory()
253
        net = dbmf.NetworkWithSubnetFactory(userid=vm.userid,
254
                                            public=False,
255
                                            subnet__cidr="192.168.2.0/24",
256
                                            subnet__gateway=None,
257
                                            subnet__pool__size=1,
258
                                            subnet__pool__offset=1)
259
        request = {
260
            "port": {
261
                "name": "port_with_address",
262
                "network_id": str(net.id),
263
                "device_id": str(vm.id),
264
                "fixed_ips": [{"ip_address": "192.168.2.1"}]
265
            }
266
        }
267
        with override_settings(settings, GANETI_USE_HOTPLUG=True):
268
            response = self.post(PORTS_URL, params=json.dumps(request),
269
                                 user=vm.userid)
270
        self.assertEqual(response.status_code, 201)
271
        new_port_ip = json.loads(response.content)["port"]["fixed_ips"][0]
272
        self.assertEqual(new_port_ip["ip_address"], "192.168.2.1")
273

    
274
        # But 409 if address is already used
275
        with override_settings(settings, GANETI_USE_HOTPLUG=True):
276
            response = self.post(PORTS_URL, params=json.dumps(request),
277
                                 user=vm.userid)
278
        self.assertConflict(response)
279

    
280
        # And bad request if IPv6 address is specified
281
        request["port"]["fixed_ips"][0]["ip_address"] = "babe::"
282
        with override_settings(settings, GANETI_USE_HOTPLUG=True):
283
            response = self.post(PORTS_URL, params=json.dumps(request),
284
                                 user=vm.userid)
285
        self.assertBadRequest(response)
286

    
287
    def test_create_port_without_device(self):
288
        net = dbmf.NetworkWithSubnetFactory(userid="test_user",
289
                                            public=False,
290
                                            subnet__cidr="192.168.2.0/24",
291
                                            subnet__gateway=None,
292
                                            subnet__pool__size=3,
293
                                            subnet__pool__offset=1)
294
        request = {
295
            "port": {
296
                "name": "port_with_address",
297
                "network_id": str(net.id),
298
            }
299
        }
300
        response = self.post(PORTS_URL, params=json.dumps(request),
301
                             user="test_user")
302
        self.assertEqual(response.status_code, 201)
303
        new_port = json.loads(response.content)["port"]
304
        self.assertEqual(new_port["device_id"], None)
305
        # And with address
306
        request["port"]["fixed_ips"] = [{"ip_address": "192.168.2.2"}]
307
        with override_settings(settings, GANETI_USE_HOTPLUG=True):
308
            response = self.post(PORTS_URL, params=json.dumps(request),
309
                                 user="test_user")
310
        self.assertEqual(response.status_code, 201)
311
        new_port = json.loads(response.content)["port"]
312
        self.assertEqual(new_port["device_id"], None)
313
        self.assertEqual(new_port["fixed_ips"][0]["ip_address"], "192.168.2.2")
314

    
315
    def test_add_nic_to_deleted_network(self):
316
        user = 'userr'
317
        vm = dbmf.VirtualMachineFactory(name='yo', userid=user,
318
                                        operstate="ACTIVE")
319
        net = dbmf.NetworkFactory(state='ACTIVE', userid=user,
320
                                  deleted=True)
321
        request = {
322
            "port": {
323
                "device_id": str(vm.id),
324
                "name": "port1",
325
                "network_id": str(net.id)
326
            }
327
        }
328
        response = self.post(PORTS_URL, params=json.dumps(request),
329
                             user=net.userid)
330
        self.assertBadRequest(response)
331

    
332
    def test_add_nic_to_public_network(self):
333
        user = 'userr'
334
        vm = dbmf.VirtualMachineFactory(name='yo', userid=user)
335
        net = dbmf.NetworkFactory(state='ACTIVE', userid=user, public=True)
336
        request = {
337
            "port": {
338
                "device_id": str(vm.id),
339
                "name": "port1",
340
                "network_id": str(net.id)
341
            }
342
        }
343
        response = self.post(PORTS_URL, params=json.dumps(request),
344
                             user=net.userid)
345
        self.assertBadRequest(response)
346
        #self.assertFault(response, 403, 'forbidden')
347

    
348
    def test_add_nic_malformed_2(self):
349
        user = 'userr'
350
        vm = dbmf.VirtualMachineFactory(name='yo', userid=user)
351
        net = dbmf.NetworkFactory(state='ACTIVE', userid=user)
352
        request = {
353
            "port": {
354
                "device_id": str(vm.id),
355
                "name": "port1"
356
            }
357
        }
358
        response = self.post(PORTS_URL, params=json.dumps(request),
359
                             user=net.userid)
360
        self.assertBadRequest(response)
361

    
362
    def test_add_nic_not_active(self):
363
        """Test connecting VM to non-active network"""
364
        user = 'dummy'
365
        vm = dbmf.VirtualMachineFactory(name='yo', userid=user)
366
        net = dbmf.NetworkFactory(state='PENDING', userid=user)
367
        request = {
368
            "port": {
369
                "device_id": str(vm.id),
370
                "name": "port1",
371
                "network_id": str(net.id)
372
            }
373
        }
374
        response = self.post(PORTS_URL, params=json.dumps(request),
375
                             user=net.userid)
376
        # Test that returns BuildInProgress
377
        self.assertEqual(response.status_code, 409)
378

    
379
#    def test_add_nic_full_network(self, mrapi):
380
#        """Test connecting VM to a full network"""
381
#        user = 'userr'
382
#        vm = dbmf.VirtualMachineFactory(name='yo', userid=user,
383
#                                            operstate="STARTED")
384
#        net = dbmf.NetworkFactory(state='ACTIVE', subnet='10.0.0.0/30',
385
#                                      userid=user, dhcp=True)
386
#        pool = net.get_pool()
387
#        while not pool.empty():
388
#            pool.get()
389
#        pool.save()
390
#        pool = net.get_pool()
391
#        self.assertTrue(pool.empty())
392
#        request = {'add': {'serverRef': vm.id}}
393
#        response = self.mypost('networks/%d/action' % net.id,
394
#                               net.userid, json.dumps(request), 'json')
395
#        # Test that returns OverLimit
396
#        self.assertEqual(response.status_code, 413)
397
#        self.assertFalse(mrapi.called)