~lutostag/ubuntu/trusty/maas/1.5.2+packagefix

« back to all changes in this revision

Viewing changes to src/maasserver/tests/test_api_node.py

  • Committer: Package Import Robot
  • Author(s): Andres Rodriguez
  • Date: 2014-03-28 10:43:53 UTC
  • mto: This revision was merged to the branch mainline in revision 57.
  • Revision ID: package-import@ubuntu.com-20140328104353-ekpolg0pm5xnvq2s
Tags: upstream-1.5+bzr2204
ImportĀ upstreamĀ versionĀ 1.5+bzr2204

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
import bson
24
24
from django.core.urlresolvers import reverse
25
25
from maasserver.enum import (
26
 
    ARCHITECTURE_CHOICES,
27
26
    DISTRO_SERIES,
28
 
    NODE_AFTER_COMMISSIONING_ACTION,
29
27
    NODE_STATUS,
30
28
    NODE_STATUS_CHOICES_DICT,
31
29
    )
39
37
    reload_objects,
40
38
    )
41
39
from maasserver.testing.api import APITestCase
 
40
from maasserver.testing.architecture import make_usable_architecture
42
41
from maasserver.testing.factory import factory
43
42
from maasserver.testing.oauthclient import OAuthAuthenticatedClient
44
43
from maasserver.testing.testcase import MAASServerTestCase
145
144
        self.assertItemsEqual(
146
145
            [mac.get_raw() for mac in macs], parsed_result['routers'])
147
146
 
 
147
    def test_GET_returns_zone(self):
 
148
        node = factory.make_node()
 
149
        response = self.client.get(self.get_node_uri(node))
 
150
        self.assertEqual(httplib.OK, response.status_code)
 
151
        parsed_result = json.loads(response.content)
 
152
        self.assertEqual(
 
153
            [node.zone.name, node.zone.description],
 
154
            [
 
155
                parsed_result['zone']['name'],
 
156
                parsed_result['zone']['description']])
 
157
 
148
158
    def test_GET_refuses_to_access_nonexistent_node(self):
149
159
        # When fetching a Node, the api returns a 'Not Found' (404) error
150
160
        # if no node is found.
406
416
 
407
417
    def test_PUT_updates_node(self):
408
418
        # The api allows the updating of a Node.
409
 
        node = factory.make_node(hostname='diane', owner=self.logged_in_user)
 
419
        node = factory.make_node(
 
420
            hostname='diane', owner=self.logged_in_user,
 
421
            architecture=make_usable_architecture(self))
410
422
        response = self.client_put(
411
423
            self.get_node_uri(node), {'hostname': 'francis'})
412
424
        parsed_result = json.loads(response.content)
418
430
 
419
431
    def test_PUT_omitted_hostname(self):
420
432
        hostname = factory.make_name('hostname')
421
 
        node = factory.make_node(hostname=hostname, owner=self.logged_in_user)
 
433
        arch = make_usable_architecture(self)
 
434
        node = factory.make_node(
 
435
            hostname=hostname, owner=self.logged_in_user, architecture=arch)
422
436
        response = self.client_put(
423
437
            self.get_node_uri(node),
424
 
            {'architecture': factory.getRandomChoice(ARCHITECTURE_CHOICES)})
 
438
            {'architecture': arch})
425
439
        self.assertEqual(httplib.OK, response.status_code, response.content)
426
440
        self.assertTrue(Node.objects.filter(hostname=hostname).exists())
427
441
 
428
442
    def test_PUT_ignores_unknown_fields(self):
429
443
        node = factory.make_node(
430
444
            owner=self.logged_in_user,
431
 
            after_commissioning_action=(
432
 
                NODE_AFTER_COMMISSIONING_ACTION.DEFAULT))
 
445
            architecture=make_usable_architecture(self))
433
446
        field = factory.getRandomString()
434
447
        response = self.client_put(
435
448
            self.get_node_uri(node),
446
459
        node = factory.make_node(
447
460
            owner=self.logged_in_user,
448
461
            power_type=original_power_type,
449
 
            after_commissioning_action=(
450
 
                NODE_AFTER_COMMISSIONING_ACTION.DEFAULT))
 
462
            architecture=make_usable_architecture(self))
451
463
        self.client_put(
452
464
            self.get_node_uri(node),
453
465
            {'power_type': new_power_type}
461
473
        new_power_type = factory.getRandomPowerType(
462
474
            but_not=original_power_type)
463
475
        node = factory.make_node(
464
 
            owner=self.logged_in_user,
465
 
            power_type=original_power_type,
466
 
            after_commissioning_action=(
467
 
                NODE_AFTER_COMMISSIONING_ACTION.DEFAULT))
 
476
            owner=self.logged_in_user, power_type=original_power_type)
468
477
        self.client_put(
469
478
            self.get_node_uri(node),
470
479
            {'power_type': new_power_type}
476
485
    def test_resource_uri_points_back_at_node(self):
477
486
        # When a Node is returned by the API, the field 'resource_uri'
478
487
        # provides the URI for this Node.
479
 
        node = factory.make_node(hostname='diane', owner=self.logged_in_user)
 
488
        node = factory.make_node(
 
489
            hostname='diane', owner=self.logged_in_user,
 
490
            architecture=make_usable_architecture(self))
480
491
        response = self.client_put(
481
492
            self.get_node_uri(node), {'hostname': 'francis'})
482
493
        parsed_result = json.loads(response.content)
488
499
    def test_PUT_rejects_invalid_data(self):
489
500
        # If the data provided to update a node is invalid, a 'Bad request'
490
501
        # response is returned.
491
 
        node = factory.make_node(hostname='diane', owner=self.logged_in_user)
 
502
        node = factory.make_node(
 
503
            hostname='diane', owner=self.logged_in_user,
 
504
            architecture=make_usable_architecture(self))
492
505
        response = self.client_put(
493
506
            self.get_node_uri(node), {'hostname': 'too long' * 100})
494
507
        parsed_result = json.loads(response.content)
523
536
        self.become_admin()
524
537
        node = factory.make_node(
525
538
            owner=self.logged_in_user,
526
 
            power_type='ether_wake')
 
539
            power_type='ether_wake',
 
540
            architecture=make_usable_architecture(self))
527
541
        # Create a power_parameter valid for the selected power_type.
528
542
        new_power_address = factory.getRandomMACAddress()
529
543
        response = self.client_put(
539
553
        self.become_admin()
540
554
        node = factory.make_node(
541
555
            owner=self.logged_in_user,
542
 
            power_type=factory.getRandomPowerType())
 
556
            power_type=factory.getRandomPowerType(),
 
557
            architecture=make_usable_architecture(self))
543
558
        response = self.client_put(
544
559
            self.get_node_uri(node),
545
560
            {'cpu_count': 1, 'memory': 1024, 'storage': 2048})
553
568
        self.become_admin()
554
569
        node = factory.make_node(
555
570
            owner=self.logged_in_user,
556
 
            power_type='ether_wake')
 
571
            power_type='ether_wake',
 
572
            architecture=make_usable_architecture(self))
557
573
        # Create an invalid power_parameter for WoL (not a valid
558
574
        # MAC address).
559
575
        new_power_address = factory.getRandomString()
574
590
        node = factory.make_node(
575
591
            owner=self.logged_in_user,
576
592
            power_type='ether_wake',
577
 
            power_parameters=power_parameters)
 
593
            power_parameters=power_parameters,
 
594
            architecture=make_usable_architecture(self))
578
595
        response = self.client_put(
579
596
            self.get_node_uri(node),
580
597
            {'power_parameters_unknown_param': factory.getRandomString()})
596
613
        node = factory.make_node(
597
614
            owner=self.logged_in_user,
598
615
            power_type='ether_wake',
599
 
            power_parameters=power_parameters)
 
616
            power_parameters=power_parameters,
 
617
            architecture=make_usable_architecture(self))
600
618
        response = self.client_put(
601
619
            self.get_node_uri(node),
602
620
            {'power_type': ''})
613
631
        node = factory.make_node(
614
632
            owner=self.logged_in_user,
615
633
            power_type='ether_wake',
616
 
            power_parameters=power_parameters)
 
634
            power_parameters=power_parameters,
 
635
            architecture=make_usable_architecture(self))
617
636
        new_param = factory.getRandomString()
618
637
        response = self.client_put(
619
638
            self.get_node_uri(node),
641
660
        node = factory.make_node(
642
661
            owner=self.logged_in_user,
643
662
            power_type='ether_wake',
644
 
            power_parameters=power_parameters)
 
663
            power_parameters=power_parameters,
 
664
            architecture=make_usable_architecture(self))
645
665
        new_param = factory.getRandomString()
646
666
        response = self.client_put(
647
667
            self.get_node_uri(node),
660
680
        # With power_parameters_skip_check, arbitrary data
661
681
        # can be put in a Node's power_parameter field.
662
682
        self.become_admin()
663
 
        node = factory.make_node(owner=self.logged_in_user)
 
683
        node = factory.make_node(
 
684
            owner=self.logged_in_user,
 
685
            architecture=make_usable_architecture(self))
664
686
        new_param = factory.getRandomString()
665
687
        new_value = factory.getRandomString()
666
688
        response = self.client_put(
679
701
        node = factory.make_node(
680
702
            owner=self.logged_in_user,
681
703
            power_type='ether_wake',
682
 
            power_parameters=factory.getRandomString())
 
704
            power_parameters=factory.getRandomString(),
 
705
            architecture=make_usable_architecture(self))
683
706
        response = self.client_put(
684
707
            self.get_node_uri(node),
685
708
            {'power_parameters_mac_address': ''})
692
715
    def test_PUT_sets_zone(self):
693
716
        self.become_admin()
694
717
        new_zone = factory.make_zone()
695
 
        node = factory.make_node()
 
718
        node = factory.make_node(architecture=make_usable_architecture(self))
696
719
 
697
720
        response = self.client_put(
698
721
            self.get_node_uri(node), {'zone': new_zone.name})
704
727
    def test_PUT_does_not_set_zone_if_not_present(self):
705
728
        self.become_admin()
706
729
        new_name = factory.make_name()
707
 
        node = factory.make_node()
 
730
        node = factory.make_node(architecture=make_usable_architecture(self))
708
731
        old_zone = node.zone
709
732
 
710
733
        response = self.client_put(
734
757
    def test_PUT_without_zone_leaves_zone_unchanged(self):
735
758
        self.become_admin()
736
759
        zone = factory.make_zone()
737
 
        node = factory.make_node(zone=zone)
 
760
        node = factory.make_node(
 
761
            zone=zone, architecture=make_usable_architecture(self))
738
762
 
739
763
        response = self.client_put(self.get_node_uri(node), {})
740
764
 
744
768
 
745
769
    def test_PUT_zone_change_requires_admin(self):
746
770
        new_zone = factory.make_zone()
747
 
        node = factory.make_node(owner=self.logged_in_user)
 
771
        node = factory.make_node(
 
772
            owner=self.logged_in_user,
 
773
            architecture=make_usable_architecture(self))
748
774
        old_zone = node.zone
749
775
 
750
776
        response = self.client_put(
861
887
        url = reverse('node_handler', args=['does-not-exist'])
862
888
        response = self.client.get(url, {'op': 'details'})
863
889
        self.assertEqual(httplib.NOT_FOUND, response.status_code)
864
 
 
865
 
 
866
 
class TestListConnectedNetworks(APITestCase):
867
 
    """Tests for /api/1.0/nodes/<node>/?op=list_connected_networks."""
868
 
 
869
 
    def test_returns_connected_networks(self):
870
 
        networks = [factory.make_network() for i in range(5)]
871
 
        connected_networks = networks[:3]
872
 
        node = factory.make_node(networks=connected_networks)
873
 
        url = reverse('node_handler', args=[node.system_id])
874
 
 
875
 
        response = self.client.get(url, {'op': 'list_connected_networks'})
876
 
 
877
 
        self.assertEqual(httplib.OK, response.status_code)
878
 
        connected_networks_names = [
879
 
            network.name for network in connected_networks]
880
 
        self.assertItemsEqual(
881
 
            connected_networks_names,
882
 
            [network['name'] for network in json.loads(response.content)])
883
 
 
884
 
 
885
 
class TestConnectNetworks(APITestCase):
886
 
    """Tests for /api/1.0/nodes/<node>/?op=connect_networks."""
887
 
 
888
 
    def test_connect_networks_connects_networks(self):
889
 
        self.become_admin()
890
 
        networks = [factory.make_network() for i in range(3)]
891
 
        node = factory.make_node()
892
 
 
893
 
        response = self.client.post(
894
 
            reverse('node_handler', args=[node.system_id]),
895
 
            {
896
 
                'op': 'connect_networks',
897
 
                'networks': [network.name for network in networks],
898
 
            })
899
 
 
900
 
        self.assertEqual(httplib.OK, response.status_code)
901
 
        self.assertItemsEqual(networks, node.networks.all())
902
 
 
903
 
    def test_connect_networks_ignores_already_connected_networks(self):
904
 
        self.become_admin()
905
 
        networks = [factory.make_network() for i in range(3)]
906
 
        node = factory.make_node(networks=networks)
907
 
 
908
 
        response = self.client.post(
909
 
            reverse('node_handler', args=[node.system_id]),
910
 
            {
911
 
                'op': 'connect_networks',
912
 
                'networks': [network.name for network in networks],
913
 
            })
914
 
 
915
 
        self.assertEqual(httplib.OK, response.status_code)
916
 
        self.assertItemsEqual(networks, node.networks.all())
917
 
 
918
 
    def test_connect_networks_fails_for_unknown_networks(self):
919
 
        self.become_admin()
920
 
        unknown_network_name = factory.make_name('agent-name')
921
 
        node = factory.make_node()
922
 
 
923
 
        response = self.client.post(
924
 
            reverse('node_handler', args=[node.system_id]),
925
 
            {
926
 
                'op': 'connect_networks',
927
 
                'networks': [unknown_network_name],
928
 
            })
929
 
 
930
 
        self.assertEqual(
931
 
            (
932
 
                httplib.BAD_REQUEST,
933
 
                {"networks": [
934
 
                    'Unknown network(s): %s.' % unknown_network_name]},
935
 
            ),
936
 
            (response.status_code, json.loads(response.content)))
937
 
 
938
 
    def test_connect_networks_requires_admin(self):
939
 
        node = factory.make_node()
940
 
        response = self.client.post(
941
 
            reverse('node_handler', args=[node.system_id]),
942
 
            {
943
 
                'op': 'connect_networks',
944
 
                'networks': [],
945
 
            })
946
 
        self.assertEqual(httplib.FORBIDDEN, response.status_code)
947
 
 
948
 
 
949
 
class TestDisconnectNetworks(APITestCase):
950
 
    """Tests for /api/1.0/nodes/<node>/?op=disconnect_networks."""
951
 
 
952
 
    def test_disconnect_networks_disconnects_networks(self):
953
 
        self.become_admin()
954
 
        networks = [factory.make_network() for i in range(3)]
955
 
        other_networks = [factory.make_network() for i in range(3)]
956
 
        node = factory.make_node(networks=(networks + other_networks))
957
 
 
958
 
        response = self.client.post(
959
 
            reverse('node_handler', args=[node.system_id]),
960
 
            {
961
 
                'op': 'disconnect_networks',
962
 
                'networks': [network.name for network in networks],
963
 
            })
964
 
 
965
 
        self.assertEqual(httplib.OK, response.status_code)
966
 
        self.assertItemsEqual(other_networks, node.networks.all())
967
 
 
968
 
    def test_disconnect_networks_ignores_already_disconnected_networks(self):
969
 
        self.become_admin()
970
 
        networks = [factory.make_network() for i in range(3)]
971
 
        other_networks = [factory.make_network() for i in range(3)]
972
 
        node = factory.make_node(networks=networks)
973
 
 
974
 
        response = self.client.post(
975
 
            reverse('node_handler', args=[node.system_id]),
976
 
            {
977
 
                'op': 'disconnect_networks',
978
 
                'networks': [network.name for network in other_networks],
979
 
            })
980
 
 
981
 
        self.assertEqual(httplib.OK, response.status_code)
982
 
        self.assertItemsEqual(networks, node.networks.all())
983
 
 
984
 
    def test_disconnect_networks_requires_admin(self):
985
 
        node = factory.make_node()
986
 
        response = self.client.post(
987
 
            reverse('node_handler', args=[node.system_id]),
988
 
            {
989
 
                'op': 'disconnect_networks',
990
 
                'networks': [],
991
 
            })
992
 
        self.assertEqual(httplib.FORBIDDEN, response.status_code)