40
def get_node_interfaces_uri(node):
41
"""Return a Node's interfaces URI on the API."""
40
def get_interfaces_uri(node):
41
"""Return a interfaces URI on the API."""
43
'node_interfaces_handler', args=[node.system_id])
46
def get_node_interface_uri(interface, node=None):
47
"""Return a Node's interface URI on the API."""
43
'interfaces_handler', args=[node.system_id])
46
def get_interface_uri(interface, node=None):
47
"""Return a interface URI on the API."""
48
48
if isinstance(interface, Interface):
50
50
node = interface.get_node()
51
51
interface = interface.id
53
'node_interface_handler', args=[node.system_id, interface])
53
'interface_handler', args=[node.system_id, interface])
56
56
def make_complex_interface(node, name=None):
74
74
return bond_interface, parents, [vlan_nic_10, vlan_nic_11]
77
class TestNodeInterfacesAPI(APITestCase):
77
class TestInterfacesAPI(APITestCase):
79
79
def test_handler_path(self):
80
80
node = factory.make_Node()
82
82
'/api/1.0/nodes/%s/interfaces/' % (node.system_id),
83
get_node_interfaces_uri(node))
83
get_interfaces_uri(node))
85
85
def test_read(self):
86
86
node = factory.make_Node()
87
87
bond, parents, children = make_complex_interface(node)
88
uri = get_node_interfaces_uri(node)
88
uri = get_interfaces_uri(node)
89
89
response = self.client.get(uri)
91
91
self.assertEqual(httplib.OK, response.status_code, response.content)
100
100
self.assertItemsEqual(expected_ids, result_ids)
102
def test_read_on_device(self):
103
parent = factory.make_Node()
104
device = factory.make_Node(
105
owner=self.logged_in_user, installable=False, parent=parent)
106
interface = factory.make_Interface(
107
INTERFACE_TYPE.PHYSICAL, node=device)
108
uri = get_interfaces_uri(device)
109
response = self.client.get(uri)
111
self.assertEqual(httplib.OK, response.status_code, response.content)
112
self.assertEqual(interface.id, json.loads(response.content)[0]['id'])
102
114
def test_create_physical(self):
103
115
self.become_admin()
104
116
for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN):
132
144
"enabled": Equals(True),
147
def test_create_physical_on_device(self):
148
parent = factory.make_Node()
149
device = factory.make_Node(
150
owner=self.logged_in_user, installable=False, parent=parent)
151
mac = factory.make_mac_address()
152
name = factory.make_name("eth")
153
vlan = factory.make_VLAN()
155
factory.make_name("tag")
158
uri = get_interfaces_uri(device)
159
response = self.client.post(uri, {
160
"op": "create_physical",
164
"tags": ",".join(tags),
168
httplib.OK, response.status_code, response.content)
169
self.assertThat(json.loads(response.content), ContainsDict({
170
"mac_address": Equals(mac),
171
"name": Equals(name),
172
"vlan": ContainsDict({
173
"id": Equals(vlan.id),
175
"type": Equals("physical"),
176
"tags": Equals(tags),
177
"enabled": Equals(True),
135
180
def test_create_physical_disabled(self):
136
181
self.become_admin()
137
182
for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN):
171
216
mac = factory.make_mac_address()
172
217
name = factory.make_name("eth")
173
218
vlan = factory.make_VLAN()
174
uri = get_node_interfaces_uri(node)
219
uri = get_interfaces_uri(node)
175
220
response = self.client.post(uri, {
176
221
"op": "create_physical",
177
222
"mac_address": mac,
203
248
mac = factory.make_mac_address()
204
249
name = factory.make_name("eth")
205
250
vlan = factory.make_VLAN()
206
uri = get_node_interfaces_uri(node)
251
uri = get_interfaces_uri(node)
207
252
response = self.client.post(uri, {
208
253
"op": "create_physical",
209
254
"mac_address": mac,
216
261
def test_create_physical_requires_mac_name_and_vlan(self):
217
262
self.become_admin()
218
263
node = factory.make_Node(status=NODE_STATUS.READY)
219
uri = get_node_interfaces_uri(node)
264
uri = get_interfaces_uri(node)
220
265
response = self.client.post(uri, {
221
266
"op": "create_physical",
235
280
INTERFACE_TYPE.PHYSICAL)
236
281
name = factory.make_name("eth")
237
282
vlan = factory.make_VLAN()
238
uri = get_node_interfaces_uri(node)
283
uri = get_interfaces_uri(node)
239
284
response = self.client.post(uri, {
240
285
"op": "create_physical",
241
286
"mac_address": "%s" % interface_on_other_node.mac_address,
291
336
parent_2_iface.name,
292
337
], parsed_interface['parents'])
339
def test_create_bond_404_on_device(self):
340
parent = factory.make_Node()
341
device = factory.make_Node(
342
owner=self.logged_in_user, installable=False, parent=parent)
343
uri = get_interfaces_uri(device)
344
response = self.client.post(uri, {
348
httplib.NOT_FOUND, response.status_code, response.content)
294
350
def test_create_bond_requires_admin(self):
295
351
node = factory.make_Node()
296
352
vlan = factory.make_VLAN()
299
355
parent_2_iface = factory.make_Interface(
300
356
INTERFACE_TYPE.PHYSICAL, vlan=vlan, node=node)
301
357
name = factory.make_name("bond")
302
uri = get_node_interfaces_uri(node)
358
uri = get_interfaces_uri(node)
303
359
response = self.client.post(uri, {
304
360
"op": "create_bond",
305
361
"mac": "%s" % parent_1_iface.mac_address,
335
391
parent_2_iface = factory.make_Interface(
336
392
INTERFACE_TYPE.PHYSICAL, vlan=vlan, node=node)
337
393
name = factory.make_name("bond")
338
uri = get_node_interfaces_uri(node)
394
uri = get_interfaces_uri(node)
339
395
response = self.client.post(uri, {
340
396
"op": "create_bond",
341
397
"mac": "%s" % parent_1_iface.mac_address,
349
405
def test_create_bond_requires_name_vlan_and_parents(self):
350
406
self.become_admin()
351
407
node = factory.make_Node(status=NODE_STATUS.READY)
352
uri = get_node_interfaces_uri(node)
408
uri = get_interfaces_uri(node)
353
409
response = self.client.post(uri, {
354
410
"op": "create_bond",
394
450
"tags": Equals(tags),
453
def test_create_vlan_404_on_device(self):
454
parent = factory.make_Node()
455
device = factory.make_Node(
456
owner=self.logged_in_user, installable=False, parent=parent)
457
uri = get_interfaces_uri(device)
458
response = self.client.post(uri, {
462
httplib.NOT_FOUND, response.status_code, response.content)
397
464
def test_create_vlan_requires_admin(self):
398
465
node = factory.make_Node()
399
466
untagged_vlan = factory.make_VLAN()
400
467
parent_iface = factory.make_Interface(
401
468
INTERFACE_TYPE.PHYSICAL, vlan=untagged_vlan, node=node)
402
469
tagged_vlan = factory.make_VLAN()
403
uri = get_node_interfaces_uri(node)
470
uri = get_interfaces_uri(node)
404
471
response = self.client.post(uri, {
405
472
"op": "create_vlan",
406
473
"vlan": tagged_vlan.vid,
412
479
def test_create_vlan_requires_vlan_and_parent(self):
413
480
self.become_admin()
414
481
node = factory.make_Node()
415
uri = get_node_interfaces_uri(node)
482
uri = get_interfaces_uri(node)
416
483
response = self.client.post(uri, {
417
484
"op": "create_vlan",
433
500
self.assertEqual(
434
501
'/api/1.0/nodes/%s/interfaces/%s/' % (
435
502
node.system_id, interface.id),
436
get_node_interface_uri(interface, node=node))
503
get_interface_uri(interface, node=node))
438
505
def test_read(self):
439
506
node = factory.make_Node()
503
uri = get_node_interface_uri(bond)
570
uri = get_interface_uri(bond)
504
571
response = self.client.get(uri)
505
572
self.assertEqual(httplib.OK, response.status_code, response.content)
506
573
parsed_interface = json.loads(response.content)
514
581
"mac_address": Equals("%s" % bond.mac_address),
515
582
"tags": Equals(bond.tags),
516
"resource_uri": Equals(get_node_interface_uri(bond)),
583
"resource_uri": Equals(get_interface_uri(bond)),
517
584
"params": Equals(bond.params),
518
585
"effective_mtu": Equals(bond.get_effective_mtu()),
533
600
def test_read_by_specifier(self):
534
601
node = factory.make_Node(hostname="tasty-biscuits")
535
602
bond0, _, _ = make_complex_interface(node, name="bond0")
536
uri = get_node_interface_uri(
603
uri = get_interface_uri(
537
604
"hostname:tasty-biscuits,name:bond0", node=node)
538
605
response = self.client.get(uri)
539
606
self.assertEqual(httplib.OK, response.status_code, response.content)
540
607
parsed_interface = json.loads(response.content)
541
608
self.assertEqual(bond0.id, parsed_interface['id'])
610
def test_read_device_interface(self):
611
parent = factory.make_Node()
612
device = factory.make_Node(installable=False, parent=parent)
613
interface = factory.make_Interface(
614
INTERFACE_TYPE.PHYSICAL, node=device)
615
uri = get_interface_uri(interface)
616
response = self.client.get(uri)
617
self.assertEqual(httplib.OK, response.status_code, response.content)
618
parsed_interface = json.loads(response.content)
619
self.assertEqual(interface.id, parsed_interface['id'])
543
621
def test_read_404_when_invalid_id(self):
544
622
node = factory.make_Node()
546
'node_interface_handler',
547
625
args=[node.system_id, random.randint(100, 1000)])
548
626
response = self.client.get(uri)
549
627
self.assertEqual(
557
635
INTERFACE_TYPE.PHYSICAL, node=node)
558
636
new_name = factory.make_name("name")
559
637
new_vlan = factory.make_VLAN()
560
uri = get_node_interface_uri(interface)
638
uri = get_interface_uri(interface)
561
639
response = self.client.put(uri, {
562
640
"name": new_name,
563
641
"vlan": new_vlan.id,
568
646
self.assertEquals(new_name, parsed_interface["name"])
569
647
self.assertEquals(new_vlan.vid, parsed_interface["vlan"]["vid"])
649
def test_update_device_physical_interface(self):
650
node = factory.make_Node()
651
device = factory.make_Node(
652
owner=self.logged_in_user, installable=False, parent=node)
653
interface = factory.make_Interface(
654
INTERFACE_TYPE.PHYSICAL, node=device)
655
new_name = factory.make_name("name")
656
new_vlan = factory.make_VLAN()
657
uri = get_interface_uri(interface)
658
response = self.client.put(uri, {
663
httplib.OK, response.status_code, response.content)
664
parsed_interface = json.loads(response.content)
665
self.assertEquals(new_name, parsed_interface["name"])
666
self.assertEquals(new_vlan.vid, parsed_interface["vlan"]["vid"])
571
668
def test_update_bond_interface(self):
572
669
self.become_admin()
573
670
for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN):
574
671
node = factory.make_Node(status=status)
575
672
bond, [nic_0, nic_1], [vlan_10, vlan_11] = make_complex_interface(
577
uri = get_node_interface_uri(bond)
674
uri = get_interface_uri(bond)
578
675
response = self.client.put(uri, {
579
676
"parents": [nic_0.id],
592
689
physical_interface = factory.make_Interface(
593
690
INTERFACE_TYPE.PHYSICAL, node=node)
594
uri = get_node_interface_uri(vlan_10)
691
uri = get_interface_uri(vlan_10)
595
692
response = self.client.put(uri, {
596
693
"parent": physical_interface.id,
605
702
node = factory.make_Node()
606
703
interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, node=node)
607
704
new_name = factory.make_name("name")
608
uri = get_node_interface_uri(interface)
705
uri = get_interface_uri(interface)
609
706
response = self.client.put(uri, {
610
707
"name": new_name,
634
731
interface = factory.make_Interface(
635
732
INTERFACE_TYPE.PHYSICAL, node=node)
636
733
new_name = factory.make_name("name")
637
uri = get_node_interface_uri(interface)
734
uri = get_interface_uri(interface)
638
735
response = self.client.put(uri, {
639
736
"name": new_name,
646
743
for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN):
647
744
node = factory.make_Node(interface=True, status=status)
648
745
interface = node.get_boot_interface()
649
uri = get_node_interface_uri(interface)
746
uri = get_interface_uri(interface)
650
747
response = self.client.delete(uri)
651
748
self.assertEqual(
652
749
httplib.NO_CONTENT, response.status_code, response.content)
653
750
self.assertIsNone(reload_object(interface))
752
def test_delete_deletes_device_interface(self):
753
parent = factory.make_Node()
754
device = factory.make_Node(
755
owner=self.logged_in_user, installable=False, parent=parent)
756
interface = factory.make_Interface(
757
INTERFACE_TYPE.PHYSICAL, node=device)
758
uri = get_interface_uri(interface)
759
response = self.client.delete(uri)
761
httplib.NO_CONTENT, response.status_code, response.content)
762
self.assertIsNone(reload_object(interface))
655
764
def test_delete_403_when_not_admin(self):
656
765
node = factory.make_Node(interface=True)
657
766
interface = node.get_boot_interface()
658
uri = get_node_interface_uri(interface)
767
uri = get_interface_uri(interface)
659
768
response = self.client.delete(uri)
660
769
self.assertEqual(
661
770
httplib.FORBIDDEN, response.status_code, response.content)
662
771
self.assertIsNotNone(reload_object(interface))
664
773
def test_delete_404_when_invalid_id(self):
665
775
node = factory.make_Node()
667
'node_interface_handler',
668
778
args=[node.system_id, random.randint(100, 1000)])
669
779
response = self.client.delete(uri)
670
780
self.assertEqual(
691
801
node = factory.make_Node(interface=True, status=status)
692
802
interface = node.get_boot_interface()
693
uri = get_node_interface_uri(interface)
803
uri = get_interface_uri(interface)
694
804
response = self.client.delete(uri)
695
805
self.assertEqual(
696
806
httplib.CONFLICT, response.status_code, response.content)
703
813
for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN):
704
814
node = factory.make_Node(interface=True, status=status)
705
815
interface = node.get_boot_interface()
706
uri = get_node_interface_uri(interface)
816
uri = get_interface_uri(interface)
707
817
response = self.client.post(uri, {
708
818
"op": "link_subnet",
709
819
"mode": INTERFACE_LINK_TYPE.DHCP,
716
826
"mode": Equals(INTERFACE_LINK_TYPE.DHCP),
829
def test_link_subnet_creates_link_on_device(self):
830
parent = factory.make_Node()
831
device = factory.make_Node(
832
owner=self.logged_in_user, installable=False, parent=parent)
833
interface = factory.make_Interface(
834
INTERFACE_TYPE.PHYSICAL, node=device)
835
subnet = factory.make_Subnet(vlan=interface.vlan)
836
uri = get_interface_uri(interface)
837
response = self.client.post(uri, {
839
"mode": INTERFACE_LINK_TYPE.STATIC,
843
httplib.OK, response.status_code, response.content)
844
parsed_response = json.loads(response.content)
846
parsed_response["links"][0], ContainsDict({
847
"mode": Equals(INTERFACE_LINK_TYPE.STATIC),
850
def test_link_subnet_on_device_only_allows_static(self):
851
parent = factory.make_Node()
852
device = factory.make_Node(
853
owner=self.logged_in_user, installable=False, parent=parent)
854
interface = factory.make_Interface(
855
INTERFACE_TYPE.PHYSICAL, node=device)
857
INTERFACE_LINK_TYPE.AUTO,
858
INTERFACE_LINK_TYPE.DHCP,
859
INTERFACE_LINK_TYPE.LINK_UP]:
860
uri = get_interface_uri(interface)
861
response = self.client.post(uri, {
866
httplib.BAD_REQUEST, response.status_code, response.content)
719
868
def test_link_subnet_raises_error(self):
720
869
self.become_admin()
721
870
for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN):
722
871
node = factory.make_Node(interface=True, status=status)
723
872
interface = node.get_boot_interface()
724
uri = get_node_interface_uri(interface)
873
uri = get_interface_uri(interface)
725
874
response = self.client.post(uri, {
726
875
"op": "link_subnet",
734
883
def test_link_subnet_requries_admin(self):
735
884
node = factory.make_Node(interface=True)
736
885
interface = node.get_boot_interface()
737
uri = get_node_interface_uri(interface)
886
uri = get_interface_uri(interface)
738
887
response = self.client.post(uri, {
739
888
"op": "link_subnet",
762
911
node = factory.make_Node(interface=True, status=status)
763
912
interface = node.get_boot_interface()
764
uri = get_node_interface_uri(interface)
913
uri = get_interface_uri(interface)
765
914
response = self.client.post(uri, {
766
915
"op": "link_subnet",
767
916
"mode": INTERFACE_LINK_TYPE.DHCP,
781
930
dhcp_ip = factory.make_StaticIPAddress(
782
931
alloc_type=IPADDRESS_TYPE.DHCP, ip="",
783
932
subnet=subnet, interface=interface)
784
uri = get_node_interface_uri(interface)
933
uri = get_interface_uri(interface)
785
934
response = self.client.post(uri, {
786
935
"op": "unlink_subnet",
787
936
"id": dhcp_ip.id,
790
939
httplib.OK, response.status_code, response.content)
791
940
self.assertIsNone(reload_object(dhcp_ip))
942
def test_unlink_subnet_deletes_link_on_device(self):
943
parent = factory.make_Node()
944
device = factory.make_Node(
945
owner=self.logged_in_user, installable=False, parent=parent)
946
interface = factory.make_Interface(
947
INTERFACE_TYPE.PHYSICAL, node=device)
948
subnet = factory.make_Subnet()
949
static_ip = factory.make_StaticIPAddress(
950
alloc_type=IPADDRESS_TYPE.STICKY,
951
subnet=subnet, interface=interface)
952
uri = get_interface_uri(interface)
953
response = self.client.post(uri, {
954
"op": "unlink_subnet",
958
httplib.OK, response.status_code, response.content)
959
self.assertIsNone(reload_object(static_ip))
793
961
def test_unlink_subnet_raises_error(self):
794
962
self.become_admin()
795
963
for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN):
796
964
node = factory.make_Node(interface=True, status=status)
797
965
interface = node.get_boot_interface()
798
uri = get_node_interface_uri(interface)
966
uri = get_interface_uri(interface)
799
967
response = self.client.post(uri, {
800
968
"op": "unlink_subnet",
808
976
def test_unlink_subnet_requries_admin(self):
809
977
node = factory.make_Node(interface=True)
810
978
interface = node.get_boot_interface()
811
uri = get_node_interface_uri(interface)
979
uri = get_interface_uri(interface)
812
980
response = self.client.post(uri, {
813
981
"op": "unlink_subnet",
836
1004
node = factory.make_Node(interface=True, status=status)
837
1005
interface = node.get_boot_interface()
838
uri = get_node_interface_uri(interface)
1006
uri = get_interface_uri(interface)
839
1007
response = self.client.post(uri, {
840
1008
"op": "unlink_subnet",
855
1023
link_ip = factory.make_StaticIPAddress(
856
1024
alloc_type=IPADDRESS_TYPE.AUTO, ip="",
857
1025
subnet=subnet, interface=interface)
858
uri = get_node_interface_uri(interface)
1026
uri = get_interface_uri(interface)
859
1027
response = self.client.post(uri, {
860
1028
"op": "set_default_gateway",
861
1029
"link_id": link_ip.id
877
1045
link_ip = factory.make_StaticIPAddress(
878
1046
alloc_type=IPADDRESS_TYPE.AUTO, ip="",
879
1047
subnet=subnet, interface=interface)
880
uri = get_node_interface_uri(interface)
1048
uri = get_interface_uri(interface)
881
1049
response = self.client.post(uri, {
882
1050
"op": "set_default_gateway",
883
1051
"link_id": link_ip.id
891
1059
for status in (NODE_STATUS.READY, NODE_STATUS.BROKEN):
892
1060
node = factory.make_Node(interface=True, status=status)
893
1061
interface = node.get_boot_interface()
894
uri = get_node_interface_uri(interface)
1062
uri = get_interface_uri(interface)
895
1063
response = self.client.post(uri, {
896
1064
"op": "set_default_gateway",
904
1072
def test_set_default_gateway_requries_admin(self):
905
1073
node = factory.make_Node(interface=True)
906
1074
interface = node.get_boot_interface()
907
uri = get_node_interface_uri(interface)
1075
uri = get_interface_uri(interface)
908
1076
response = self.client.post(uri, {
909
1077
"op": "set_default_gateway",
932
1100
node = factory.make_Node(interface=True, status=status)
933
1101
interface = node.get_boot_interface()
934
uri = get_node_interface_uri(interface)
1102
uri = get_interface_uri(interface)
935
1103
response = self.client.post(uri, {
936
1104
"op": "set_default_gateway",