Revision 3aecadc8 snf-cyclades-app/synnefo/api/tests/servers.py

b/snf-cyclades-app/synnefo/api/tests/servers.py
340 340
        response = self.mypost('servers/42/metadata/foo')
341 341
        self.assertMethodNotAllowed(response)
342 342

  
343

  
344 343
fixed_image = Mock()
345 344
fixed_image.return_value = {'location': 'pithos://foo',
346 345
                            'checksum': '1234',
......
355 354
class ServerCreateAPITest(ComputeAPITest):
356 355
    def setUp(self):
357 356
        self.flavor = mfactory.FlavorFactory()
358
        # Create public network and backend
359
        subnet = mfactory.IPv4SubnetFactory(network__public=True)
360
        self.network = subnet.network
361 357
        self.backend = mfactory.BackendFactory()
362
        mfactory.BackendNetworkFactory(network=self.network,
363
                                       backend=self.backend,
364
                                       operstate="ACTIVE")
365 358
        self.request = {
366 359
            "server": {
367 360
                "name": "new-server-test",
......
374 367
                "personality": []
375 368
            }
376 369
        }
370
        # Create dummy public IPv6 network
371
        sub6 = mfactory.IPv6SubnetFactory(network__public=True)
372
        self.net6 = sub6.network
373
        self.network_settings = {
374
            "CYCLADES_DEFAULT_SERVER_NETWORKS": [],
375
            "CYCLADES_FORCED_SERVER_NETWORKS": ["SNF:ANY_PUBLIC_IPV6"]
376
        }
377 377

  
378 378
    def test_create_server(self, mrapi):
379 379
        """Test if the create server call returns the expected response
380 380
           if a valid request has been speficied."""
381 381

  
382 382
        mrapi().CreateInstance.return_value = 12
383
        with override_settings(settings, DEFAULT_INSTANCE_NETWORKS=[]):
383
        with override_settings(settings, **self.network_settings):
384 384
            with mocked_quotaholder():
385 385
                response = self.mypost('servers', 'test_user',
386 386
                                       json.dumps(self.request), 'json')
......
398 398
        self.assertEqual(api_server['name'], db_vm.name)
399 399
        self.assertEqual(api_server['status'], db_vm.operstate)
400 400

  
401
        # Test drained flag in Network:
402
        self.network.drained = True
403
        self.network.save()
404
        with mocked_quotaholder():
405
            response = self.mypost('servers', 'test_user',
406
                                   json.dumps(self.request), 'json')
407
        self.assertEqual(response.status_code, 503, "serviceUnavailable")
408

  
409
    def test_create_server_with_port(self, mrapi):
410
        mrapi().CreateInstance.return_value = 42
411
        ip = mfactory.IPv4AddressFactory(nic__machine=None)
412
        port1 = ip.nic
401
    def test_create_server_no_flavor(self, mrapi):
413 402
        request = deepcopy(self.request)
414
        request["server"]["networks"] = [{"port": port1.id}]
415
        with mocked_quotaholder():
416
            response = self.mypost("servers", port1.userid,
417
                                   json.dumps(request), 'json')
403
        request["server"]["flavorRef"] = 42
404
        with override_settings(settings, **self.network_settings):
405
            with mocked_quotaholder():
406
                response = self.mypost('servers', 'test_user',
407
                                       json.dumps(request), 'json')
408
        self.assertItemNotFound(response)
409

  
410
    def test_create_server_error(self, mrapi):
411
        """Test if the create server call returns the expected response
412
           if a valid request has been speficied."""
413
        mrapi().CreateInstance.side_effect = GanetiApiError("..ganeti is down")
414

  
415
        request = self.request
416
        with override_settings(settings, **self.network_settings):
417
            with mocked_quotaholder():
418
                response = self.mypost('servers', 'test_user',
419
                                       json.dumps(request), 'json')
418 420
        self.assertEqual(response.status_code, 202)
419
        vm_id = json.loads(response.content)["server"]["id"]
420
        port1 = NetworkInterface.objects.get(id=port1.id)
421
        self.assertEqual(port1.machine_id, vm_id)
422
        # 409 if already used
423
        with mocked_quotaholder():
424
            response = self.mypost("servers", port1.userid,
425
                                   json.dumps(request), 'json')
426
        self.assertConflict(response)
427
        # Test permissions
428
        ip = mfactory.IPv4AddressFactory(userid="user1", nic__userid="user1")
429
        port2 = ip.nic
430
        request["server"]["networks"] = [{"port": port2.id}]
431
        with mocked_quotaholder():
432
            response = self.mypost("servers", "user2",
433
                                   json.dumps(request), 'json')
434
        self.assertEqual(response.status_code, 404)
421
        mrapi().CreateInstance.assert_called_once()
422
        vm = VirtualMachine.objects.get()
423
        # The VM has not been deleted
424
        self.assertFalse(vm.deleted)
425
        # but is in "ERROR" operstate
426
        self.assertEqual(vm.operstate, "ERROR")
435 427

  
436
    def test_create_network_settings(self, mrapi):
428
    def test_create_network_info(self, mrapi):
437 429
        mrapi().CreateInstance.return_value = 12
438
        # Create public network and backend
439
        subnet1 = mfactory.IPv4SubnetFactory(network__userid="test_user")
440
        bnet1 = mfactory.BackendNetworkFactory(network=subnet1.network,
441
                                               backend=self.backend,
442
                                               operstate="ACTIVE")
443
        subnet2 = mfactory.IPv4SubnetFactory(network__userid="test_user")
444
        bnet2 = mfactory.BackendNetworkFactory(network=subnet2.network,
445
                                               backend=self.backend,
446
                                               operstate="ACTIVE")
430

  
447 431
        # User requested private networks
432
        s1 = mfactory.IPv4SubnetFactory(network__userid="test")
433
        s2 = mfactory.IPv6SubnetFactory(network__userid="test")
434
        # and a public IPv6
448 435
        request = deepcopy(self.request)
449
        request["server"]["networks"] = [{"uuid": bnet1.network.id},
450
                                         {"uuid": bnet2.network.id}]
451
        with override_settings(settings,
452
                               DEFAULT_INSTANCE_NETWORKS=[
453
                                   "SNF:ANY_PUBLIC"]):
436
        request["server"]["networks"] = [{"uuid": s1.network_id},
437
                                         {"uuid": s2.network_id}]
438
        with override_settings(settings, **self.network_settings):
454 439
            with mocked_quotaholder():
455
                response = self.mypost('servers', 'test_user',
440
                response = self.mypost('servers', "test",
456 441
                                       json.dumps(request), 'json')
457 442
        self.assertEqual(response.status_code, 202)
458 443
        name, args, kwargs = mrapi().CreateInstance.mock_calls[0]
459 444
        self.assertEqual(len(kwargs["nics"]), 3)
460
        self.assertEqual(kwargs["nics"][0]["network"],
461
                         self.network.backend_id)
462
        self.assertEqual(kwargs["nics"][1]["network"],
463
                         bnet1.network.backend_id)
464
        self.assertEqual(kwargs["nics"][2]["network"],
465
                         bnet2.network.backend_id)
466

  
467
        subnet3 = mfactory.IPv4SubnetFactory(network__public=True,
468
                                             network__floating_ip_pool=True)
469
        bnet3 = mfactory.BackendNetworkFactory(network=subnet3.network,
470
                                               backend=self.backend,
471
                                               operstate="ACTIVE")
472
        request["server"]["floating_ips"] = []
473
        with override_settings(settings,
474
                               DEFAULT_INSTANCE_NETWORKS=[bnet3.network.id]):
475
            with mocked_quotaholder():
476
                response = self.mypost('servers', 'test_user',
477
                                       json.dumps(request), 'json')
478
        self.assertEqual(response.status_code, 202)
479
        name, args, kwargs = mrapi().CreateInstance.mock_calls[1]
480
        self.assertEqual(len(kwargs["nics"]), 3)
481
        self.assertEqual(kwargs["nics"][0]["network"],
482
                         bnet3.network.backend_id)
483
        self.assertEqual(kwargs["nics"][1]["network"],
484
                         bnet1.network.backend_id)
485
        self.assertEqual(kwargs["nics"][2]["network"],
486
                         bnet2.network.backend_id)
487

  
488
        # test invalid network in DEFAULT_INSTANCE_NETWORKS
489
        with override_settings(settings, DEFAULT_INSTANCE_NETWORKS=[42]):
490
            response = self.mypost('servers', 'test_user',
491
                                   json.dumps(request), 'json')
492
        self.assertFault(response, 500, "internalServerError")
493

  
494
        # test connect to public netwok
445
        self.assertEqual(kwargs["nics"][0]["network"], self.net6.backend_id)
446
        self.assertEqual(kwargs["nics"][1]["network"], s1.network.backend_id)
447
        self.assertEqual(kwargs["nics"][2]["network"], s2.network.backend_id)
448

  
449
        # but fail if others user network
450
        s3 = mfactory.IPv6SubnetFactory(network__userid="test_other")
495 451
        request = deepcopy(self.request)
496
        request["server"]["networks"] = [{"uuid": self.network.id}]
497
        with override_settings(settings,
498
                               DEFAULT_INSTANCE_NETWORKS=["SNF:ANY_PUBLIC"]):
499
            response = self.mypost('servers', 'test_user',
500
                                   json.dumps(request), 'json')
501
        self.assertBadRequest(response)
452
        request["server"]["networks"] = [{"uuid": s3.network_id}]
453
        response = self.mypost('servers', "test", json.dumps(request), 'json')
454
        self.assertEqual(response.status_code, 404)
502 455

  
503
        # test wrong user
456
        # User requested public networks
457
        # but no floating IP..
458
        s1 = mfactory.IPv4SubnetFactory(network__public=True)
504 459
        request = deepcopy(self.request)
505
        request["server"]["networks"] = [{"uuid": bnet1.network.id}]
506
        with override_settings(settings,
507
                               DEFAULT_INSTANCE_NETWORKS=["SNF:ANY_PUBLIC"]):
508
            with mocked_quotaholder():
509
                response = self.mypost('servers', 'dummy_user',
510
                                       json.dumps(request), 'json')
511
        self.assertItemNotFound(response)
460
        request["server"]["networks"] = [{"uuid": s1.network_id}]
461
        response = self.mypost('servers', "test", json.dumps(request), 'json')
462
        self.assertEqual(response.status_code, 409)
512 463

  
513
        # Test floating IPs
464
        # Add one floating IP
465
        fp1 = mfactory.IPv4AddressFactory(userid="test", subnet=s1,
466
                                          network=s1.network,
467
                                          floating_ip=True, nic=None)
468
        self.assertEqual(fp1.nic, None)
514 469
        request = deepcopy(self.request)
515
        fp1 = mfactory.FloatingIPFactory(address="10.0.0.2",
516
                                         userid="test_user",
517
                                         network=self.network,
518
                                         nic=None)
519
        fp2 = mfactory.FloatingIPFactory(address="10.0.0.3",
520
                                         userid="test_user",
521
                                         network=self.network,
522
                                         nic=None)
523
        request["server"]["networks"] = [{"uuid": bnet1.network.id},
524
                                         {"uuid": fp1.network.id,
525
                                          "fixed_ip": fp1.address},
526
                                         {"uuid": fp2.network.id,
527
                                          "fixed_ip": fp2.address}]
528
        with override_settings(settings,
529
                               DEFAULT_INSTANCE_NETWORKS=[bnet3.network.id]):
530
            with mocked_quotaholder():
531
                response = self.mypost('servers', 'test_user',
470
        request["server"]["networks"] = [{"uuid": s1.network_id,
471
                                          "fixed_ip": fp1.address}]
472
        with mocked_quotaholder():
473
            with override_settings(settings, **self.network_settings):
474
                response = self.mypost('servers', "test",
532 475
                                       json.dumps(request), 'json')
533 476
        self.assertEqual(response.status_code, 202)
534
        api_server = json.loads(response.content)['server']
535
        vm = VirtualMachine.objects.get(id=api_server["id"])
536
        fp1 = IPAddress.objects.get(floating_ip=True, id=fp1.id)
537
        fp2 = IPAddress.objects.get(floating_ip=True, id=fp2.id)
538
        self.assertEqual(fp1.nic.machine, vm)
539
        self.assertEqual(fp2.nic.machine, vm)
540
        name, args, kwargs = mrapi().CreateInstance.mock_calls[2]
541
        self.assertEqual(len(kwargs["nics"]), 4)
542
        self.assertEqual(kwargs["nics"][0]["network"],
543
                         bnet3.network.backend_id)
544
        self.assertEqual(kwargs["nics"][1]["network"],
545
                         bnet1.network.backend_id)
546
        self.assertEqual(kwargs["nics"][2]["network"], fp1.network.backend_id)
547
        self.assertEqual(kwargs["nics"][2]["ip"], fp1.address)
548
        self.assertEqual(kwargs["nics"][3]["network"], fp2.network.backend_id)
549
        self.assertEqual(kwargs["nics"][3]["ip"], fp2.address)
477
        server_id = json.loads(response.content)["server"]["id"]
478
        fp1 = IPAddress.objects.get(id=fp1.id)
479
        self.assertEqual(fp1.nic.machine_id, server_id)
550 480

  
551
    def test_create_server_no_flavor(self, mrapi):
481
        # check used floating IP
482
        response = self.mypost('servers', "test", json.dumps(request), 'json')
483
        self.assertEqual(response.status_code, 409)
484

  
485
        # Add more floating IP. but check auto-reserve
486
        fp2 = mfactory.IPv4AddressFactory(userid="test", subnet=s1,
487
                                          network=s1.network,
488
                                          floating_ip=True, nic=None)
489
        self.assertEqual(fp2.nic, None)
552 490
        request = deepcopy(self.request)
553
        request["server"]["flavorRef"] = 42
491
        request["server"]["networks"] = [{"uuid": s1.network_id}]
554 492
        with mocked_quotaholder():
555
            response = self.mypost('servers', 'test_user',
556
                                   json.dumps(request), 'json')
557
        self.assertItemNotFound(response)
493
            with override_settings(settings, **self.network_settings):
494
                response = self.mypost('servers', "test",
495
                                       json.dumps(request), 'json')
496
        self.assertEqual(response.status_code, 202)
497
        server_id = json.loads(response.content)["server"]["id"]
498
        fp2 = IPAddress.objects.get(id=fp2.id)
499
        self.assertEqual(fp2.nic.machine_id, server_id)
558 500

  
559
    def test_create_server_error(self, mrapi):
560
        """Test if the create server call returns the expected response
561
           if a valid request has been speficied."""
562
        mrapi().CreateInstance.side_effect = GanetiApiError("..ganeti is down")
501
        name, args, kwargs = mrapi().CreateInstance.mock_calls[-1]
502
        self.assertEqual(len(kwargs["nics"]), 2)
503
        self.assertEqual(kwargs["nics"][0]["network"], self.net6.backend_id)
504
        self.assertEqual(kwargs["nics"][1]["network"], fp2.network.backend_id)
563 505

  
564
        request = self.request
565
        with mocked_quotaholder():
566
            response = self.mypost('servers', 'test_user',
567
                                   json.dumps(request), 'json')
506
    def test_create_network_settings(self, mrapi):
507
        mrapi().CreateInstance.return_value = 12
508
        # User requested private networks
509
        # no public IPv4
510
        network_settings = {
511
            "CYCLADES_DEFAULT_SERVER_NETWORKS": [],
512
            "CYCLADES_FORCED_SERVER_NETWORKS": ["SNF:ANY_PUBLIC_IPV4"]
513
        }
514
        with override_settings(settings, **network_settings):
515
            response = self.mypost('servers', "test", json.dumps(self.request),
516
                                   'json')
517
        self.assertEqual(response.status_code, 503)
518
        # no public IPv4, IPv6 exists
519
        network_settings = {
520
            "CYCLADES_DEFAULT_SERVER_NETWORKS": [],
521
            "CYCLADES_FORCED_SERVER_NETWORKS": ["SNF:ANY_PUBLIC"]
522
        }
523
        with override_settings(settings, **network_settings):
524
            response = self.mypost('servers', "test", json.dumps(self.request),
525
                                   'json')
568 526
        self.assertEqual(response.status_code, 202)
569
        mrapi().CreateInstance.assert_called_once()
570
        vm = VirtualMachine.objects.get()
571
        # The VM has not been deleted
572
        self.assertFalse(vm.deleted)
573
        # but is in "ERROR" operstate
574
        self.assertEqual(vm.operstate, "ERROR")
527
        server_id = json.loads(response.content)["server"]["id"]
528
        vm = VirtualMachine.objects.get(id=server_id)
529
        self.assertEqual(vm.nics.get().ipv4_address, None)
530

  
531
        # IPv4 exists
532
        mfactory.IPv4SubnetFactory(network__public=True,
533
                                   cidr="192.168.2.0/24",
534
                                   pool__offset=2,
535
                                   pool__size=1)
536
        with override_settings(settings, **network_settings):
537
            response = self.mypost('servers', "test", json.dumps(self.request),
538
                                   'json')
539
        self.assertEqual(response.status_code, 202)
540
        server_id = json.loads(response.content)["server"]["id"]
541
        vm = VirtualMachine.objects.get(id=server_id)
542
        self.assertEqual(vm.nics.get().ipv4_address, "192.168.2.2")
543

  
544
        # Fixed networks
545
        net1 = mfactory.NetworkFactory(userid="test")
546
        net2 = mfactory.NetworkFactory(userid="test")
547
        net3 = mfactory.NetworkFactory(userid="test")
548
        network_settings = {
549
            "CYCLADES_DEFAULT_SERVER_NETWORKS": [],
550
            "CYCLADES_FORCED_SERVER_NETWORKS": [net1.id, [net2.id, net3.id],
551
                                                (net3.id, net2.id)]
552
        }
553
        with override_settings(settings, **network_settings):
554
            response = self.mypost('servers', "test", json.dumps(self.request),
555
                                   'json')
556
        self.assertEqual(response.status_code, 202)
557
        server_id = json.loads(response.content)["server"]["id"]
558
        vm = VirtualMachine.objects.get(id=server_id)
559
        self.assertEqual(len(vm.nics.all()), 3)
560

  
561
    def test_create_server_with_port(self, mrapi):
562
        mrapi().CreateInstance.return_value = 42
563
        ip = mfactory.IPv4AddressFactory(nic__machine=None)
564
        port1 = ip.nic
565
        request = deepcopy(self.request)
566
        request["server"]["networks"] = [{"port": port1.id}]
567
        with override_settings(settings, **self.network_settings):
568
            with mocked_quotaholder():
569
                response = self.mypost("servers", port1.userid,
570
                                       json.dumps(request), 'json')
571
        self.assertEqual(response.status_code, 202)
572
        vm_id = json.loads(response.content)["server"]["id"]
573
        port1 = NetworkInterface.objects.get(id=port1.id)
574
        self.assertEqual(port1.machine_id, vm_id)
575
        # 409 if already used
576
        with override_settings(settings, **self.network_settings):
577
            with mocked_quotaholder():
578
                response = self.mypost("servers", port1.userid,
579
                                       json.dumps(request), 'json')
580
        self.assertConflict(response)
581
        # Test permissions
582
        ip = mfactory.IPv4AddressFactory(userid="user1", nic__userid="user1")
583
        port2 = ip.nic
584
        request["server"]["networks"] = [{"port": port2.id}]
585
        with override_settings(settings, **self.network_settings):
586
            with mocked_quotaholder():
587
                response = self.mypost("servers", "user2",
588
                                       json.dumps(request), 'json')
589
        self.assertEqual(response.status_code, 404)
575 590

  
576 591

  
577 592
@patch('synnefo.logic.rapi_pool.GanetiRapiClient')

Also available in: Unified diff