Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (15.8 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
COMPUTE_URL = get_service_path(cyclades_services, 'compute',
44
                               version='v2.0')
45
PORTS_URL = join_urls(COMPUTE_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.network.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.network.userid)
74
        self.assertEqual(response.status_code, 204)
75
        with override_settings(settings, GANETI_USE_HOTPLUG=False):
76
            response = self.delete(url, user=nic.network.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.network.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.network.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.network.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_no_network(self):
121
        request = {
122
            "port": {
123
                "device_id": "123",
124
                "name": "port1",
125
                "network_id": "123"
126
            }
127
        }
128
        response = self.post(PORTS_URL, params=json.dumps(request))
129
        self.assertEqual(response.status_code, 404)
130

    
131
    @patch("synnefo.db.models.get_rapi_client")
132
    def test_create_port_private_net(self, mrapi):
133
        net = dbmf.NetworkFactory(public=False)
134
        dbmf.IPv4SubnetFactory(network=net)
135
        dbmf.IPv6SubnetFactory(network=net)
136
        sg1 = dbmf.SecurityGroupFactory()
137
        sg2 = dbmf.SecurityGroupFactory()
138
        vm = dbmf.VirtualMachineFactory(userid=net.userid)
139
        request = {
140
            "port": {
141
                "name": "port1",
142
                "network_id": str(net.id),
143
                "device_id": str(vm.id),
144
                "security_groups": [str(sg1.id), str(sg2.id)]
145
            }
146
        }
147
        mrapi().ModifyInstance.return_value = 42
148
        with override_settings(settings, GANETI_USE_HOTPLUG=False):
149
            response = self.post(PORTS_URL, params=json.dumps(request),
150
                                 user=net.userid)
151
        self.assertEqual(response.status_code, 400)
152
        with override_settings(settings, GANETI_USE_HOTPLUG=True):
153
            response = self.post(PORTS_URL, params=json.dumps(request),
154
                                 user=net.userid)
155
        self.assertEqual(response.status_code, 201)
156

    
157
    def test_create_port_public_net_no_ip(self):
158
        net = dbmf.NetworkFactory(public=True)
159
        vm = dbmf.VirtualMachineFactory(userid=net.userid)
160
        request = {
161
            "port": {
162
                "name": "port1",
163
                "network_id": str(net.id),
164
                "device_id": str(vm.id),
165
            }
166
        }
167
        response = self.post(PORTS_URL, params=json.dumps(request),
168
                             user=net.userid)
169
        self.assertEqual(response.status_code, 400)
170

    
171
    def test_create_port_public_net_wrong_ip(self):
172
        net = dbmf.NetworkFactory(public=True)
173
        vm = dbmf.VirtualMachineFactory(userid=net.userid)
174
        request = {
175
            "port": {
176
                "name": "port1",
177
                "network_id": str(net.id),
178
                "device_id": str(vm.id),
179
                "fixed_ips": [{"ip_address": "8.8.8.8"}]
180
            }
181
        }
182
        response = self.post(PORTS_URL, params=json.dumps(request),
183
                             user=net.userid)
184
        self.assertEqual(response.status_code, 404)
185

    
186
    def test_create_port_public_net_conflict(self):
187
        net = dbmf.NetworkFactory(public=True)
188
        fip = dbmf.FloatingIPFactory(nic=None, userid=net.userid)
189
        vm = dbmf.VirtualMachineFactory(userid=net.userid)
190
        request = {
191
            "port": {
192
                "name": "port1",
193
                "network_id": str(net.id),
194
                "device_id": str(vm.id),
195
                "fixed_ips": [{"ip_address": fip.address}]
196
            }
197
        }
198
        response = self.post(PORTS_URL, params=json.dumps(request),
199
                             user=net.userid)
200
        self.assertEqual(response.status_code, 409)
201

    
202
    def test_create_port_public_net_taken_ip(self):
203
        net = dbmf.NetworkFactory(public=True)
204
        fip = dbmf.FloatingIPFactory(network=net, userid=net.userid)
205
        vm = dbmf.VirtualMachineFactory(userid=net.userid)
206
        request = {
207
            "port": {
208
                "name": "port1",
209
                "network_id": str(net.id),
210
                "device_id": str(vm.id),
211
                "fixed_ips": [{"ip_address": fip.address}]
212
            }
213
        }
214
        response = self.post(PORTS_URL, params=json.dumps(request),
215
                             user=net.userid)
216
        self.assertEqual(response.status_code, 409)
217

    
218
    @patch("synnefo.db.models.get_rapi_client")
219
    def test_create_port_with_floating_ip(self, mrapi):
220
        vm = dbmf.VirtualMachineFactory()
221
        fip = dbmf.FloatingIPFactory(network__public=True, nic=None,
222
                                     userid=vm.userid)
223
        request = {
224
            "port": {
225
                "name": "port1",
226
                "network_id": str(fip.network_id),
227
                "device_id": str(vm.id),
228
                "fixed_ips": [{"ip_address": fip.address}]
229
            }
230
        }
231
        mrapi().ModifyInstance.return_value = 42
232
        with override_settings(settings, GANETI_USE_HOTPLUG=True):
233
            response = self.post(PORTS_URL, params=json.dumps(request),
234
                                 user=vm.userid)
235
        self.assertEqual(response.status_code, 201)
236

    
237
    @patch("synnefo.db.models.get_rapi_client")
238
    def test_create_port_with_address(self, mrapi):
239
        """Test creation if IP address is specified."""
240
        mrapi().ModifyInstance.return_value = 42
241
        vm = dbmf.VirtualMachineFactory()
242
        net = dbmf.NetworkWithSubnetFactory(userid=vm.userid,
243
                                            public=False,
244
                                            subnet__cidr="192.168.2.0/24",
245
                                            subnet__pool__size=1,
246
                                            subnet__pool__offset=1)
247
        request = {
248
            "port": {
249
                "name": "port_with_address",
250
                "network_id": str(net.id),
251
                "device_id": str(vm.id),
252
                "fixed_ips": [{"ip_address": "192.168.2.1"}]
253
            }
254
        }
255
        with override_settings(settings, GANETI_USE_HOTPLUG=True):
256
            response = self.post(PORTS_URL, params=json.dumps(request),
257
                                 user=vm.userid)
258
        self.assertEqual(response.status_code, 201)
259
        new_port_ip = json.loads(response.content)["port"]["fixed_ips"][0]
260
        self.assertEqual(new_port_ip["ip_address"], "192.168.2.1")
261

    
262
        # But 409 if address is already used
263
        with override_settings(settings, GANETI_USE_HOTPLUG=True):
264
            response = self.post(PORTS_URL, params=json.dumps(request),
265
                                 user=vm.userid)
266
        self.assertConflict(response)
267

    
268
        # And bad request if IPv6 address is specified
269
        request["port"]["fixed_ips"][0]["ip_address"] = "babe::"
270
        with override_settings(settings, GANETI_USE_HOTPLUG=True):
271
            response = self.post(PORTS_URL, params=json.dumps(request),
272
                                 user=vm.userid)
273
        self.assertBadRequest(response)
274

    
275
    def test_create_port_without_device(self):
276
        net = dbmf.NetworkWithSubnetFactory(userid="test_user",
277
                                            public=False,
278
                                            subnet__cidr="192.168.2.0/24",
279
                                            subnet__pool__size=3,
280
                                            subnet__pool__offset=1)
281
        request = {
282
            "port": {
283
                "name": "port_with_address",
284
                "network_id": str(net.id),
285
            }
286
        }
287
        response = self.post(PORTS_URL, params=json.dumps(request),
288
                             user="test_user")
289
        self.assertEqual(response.status_code, 201)
290
        new_port = json.loads(response.content)["port"]
291
        self.assertEqual(new_port["device_id"], None)
292
        # And with address
293
        request["port"]["fixed_ips"] = [{"ip_address": "192.168.2.2"}]
294
        with override_settings(settings, GANETI_USE_HOTPLUG=True):
295
            response = self.post(PORTS_URL, params=json.dumps(request),
296
                                 user="test_user")
297
        self.assertEqual(response.status_code, 201)
298
        new_port = json.loads(response.content)["port"]
299
        self.assertEqual(new_port["device_id"], None)
300
        self.assertEqual(new_port["fixed_ips"][0]["ip_address"], "192.168.2.2")
301

    
302
    def test_add_nic_to_deleted_network(self):
303
        user = 'userr'
304
        vm = dbmf.VirtualMachineFactory(name='yo', userid=user,
305
                                        operstate="ACTIVE")
306
        net = dbmf.NetworkFactory(state='ACTIVE', userid=user,
307
                                  deleted=True)
308
        request = {
309
            "port": {
310
                "device_id": str(vm.id),
311
                "name": "port1",
312
                "network_id": str(net.id)
313
            }
314
        }
315
        response = self.post(PORTS_URL, params=json.dumps(request),
316
                             user=net.userid)
317
        self.assertBadRequest(response)
318

    
319
    def test_add_nic_to_public_network(self):
320
        user = 'userr'
321
        vm = dbmf.VirtualMachineFactory(name='yo', userid=user)
322
        net = dbmf.NetworkFactory(state='ACTIVE', userid=user, public=True)
323
        request = {
324
            "port": {
325
                "device_id": str(vm.id),
326
                "name": "port1",
327
                "network_id": str(net.id)
328
            }
329
        }
330
        response = self.post(PORTS_URL, params=json.dumps(request),
331
                             user=net.userid)
332
        self.assertBadRequest(response)
333
        #self.assertFault(response, 403, 'forbidden')
334

    
335
    def test_add_nic_malformed_2(self):
336
        user = 'userr'
337
        vm = dbmf.VirtualMachineFactory(name='yo', userid=user)
338
        net = dbmf.NetworkFactory(state='ACTIVE', userid=user)
339
        request = {
340
            "port": {
341
                "device_id": str(vm.id),
342
                "name": "port1"
343
            }
344
        }
345
        response = self.post(PORTS_URL, params=json.dumps(request),
346
                             user=net.userid)
347
        self.assertBadRequest(response)
348

    
349
    def test_add_nic_not_active(self):
350
        """Test connecting VM to non-active network"""
351
        user = 'dummy'
352
        vm = dbmf.VirtualMachineFactory(name='yo', userid=user)
353
        net = dbmf.NetworkFactory(state='PENDING', userid=user)
354
        request = {
355
            "port": {
356
                "device_id": str(vm.id),
357
                "name": "port1",
358
                "network_id": str(net.id)
359
            }
360
        }
361
        response = self.post(PORTS_URL, params=json.dumps(request),
362
                             user=net.userid)
363
        # Test that returns BuildInProgress
364
        self.assertEqual(response.status_code, 409)
365

    
366
#    def test_add_nic_full_network(self, mrapi):
367
#        """Test connecting VM to a full network"""
368
#        user = 'userr'
369
#        vm = dbmf.VirtualMachineFactory(name='yo', userid=user,
370
#                                            operstate="STARTED")
371
#        net = dbmf.NetworkFactory(state='ACTIVE', subnet='10.0.0.0/30',
372
#                                      userid=user, dhcp=True)
373
#        pool = net.get_pool()
374
#        while not pool.empty():
375
#            pool.get()
376
#        pool.save()
377
#        pool = net.get_pool()
378
#        self.assertTrue(pool.empty())
379
#        request = {'add': {'serverRef': vm.id}}
380
#        response = self.mypost('networks/%d/action' % net.id,
381
#                               net.userid, json.dumps(request), 'json')
382
#        # Test that returns OverLimit
383
#        self.assertEqual(response.status_code, 413)
384
#        self.assertFalse(mrapi.called)