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