276
251
rack_vlan = rack_interface_link['subnet']['vlan']['name']
278
253
maas_dhcp_cmd = [
279
'vlan', 'update', rack_fabric, rack_vlan, 'dhcp_on=True',
280
'primary_rack=%s' % primary_rack_system_id]
282
output, err = self._run_maas_cli(maas_dhcp_cmd)
285
vlan_result = loads(output)
288
#from maas.provisioningserver.service_monitor import get_service_state
289
pause_until_released(ng_list.__repr__())
290
# The JSON object returned by MAAS doesn't include the router_ip
291
# address, so let's remove it from the dhcp_config before comparing.
254
'vlan', 'update', rack_fabric, rack_vlan, 'dhcp_on=True',
255
'primary_rack=%s' % primary_rack_system_id
257
output, _ = self._run_maas_cli(maas_dhcp_cmd)
258
vlan_result = loads(output)
292
259
self.assertEqual(True, vlan_result['dhcp_on'])
294
261
def _boot_nodes(self):
364
335
command = ["juju", "--debug"]
365
336
command.extend(args)
366
337
retcode, output, err = run_command(command, env=env)
367
command_name = " ".join(map(pipes.quote, command))
338
command_name = " ".join(command)
368
339
self.addDetail(command_name, text_content(output))
369
340
self.addDetail(command_name, text_content(err))
370
341
return retcode, output, err
372
343
def get_juju_status(self):
373
344
# Juju2 status defaults to tabular so we need to force YAML
374
_, status_output, _ = self._run_juju_command(["status", "--format=yaml"])
345
_, status_output, _ = self._run_juju_command(
346
["status", "--format=yaml"]
375
348
status = yaml.safe_load(status_output)
535
509
place to put a pause."""
536
510
# pause_until_released('test_maas_logged_in')
537
511
cmd = ["maas", "list"]
538
retcode, output, err = run_command(cmd)
512
retcode, _, err = run_command(cmd)
539
513
self.assertEqual(0, retcode)
540
514
self.assertEqual('', err)
542
516
def test_set_main_archive(self):
543
output, err = self._run_maas_cli([
517
output, _ = self._run_maas_cli([
544
518
"maas", "set-config", "name=main_archive",
545
519
"value=%s" % MAIN_ARCHIVE])
546
520
self.assertThat(output, Contains("OK"))
547
output, err = self._run_maas_cli([
521
output, _ = self._run_maas_cli([
548
522
"maas", "get-config", "name=main_archive"])
549
523
self.assertThat(output, Contains(MAIN_ARCHIVE))
655
629
def test_create_dynamic_range(self):
656
output, err = self._run_maas_cli(
630
output, _ = self._run_maas_cli(
657
631
['ipranges', 'create', 'type=dynamic',
658
632
'start_ip=%s' % REGION_DHCP_CONFIG['ip_range_low'],
659
633
'end_ip=%s' % REGION_DHCP_CONFIG['ip_range_high']])
660
# If the range was configured correct, it should return the subnet where
661
# the range belogs to. As such, we check the output to ensure it is there.
662
self.assertThat(output, Contains('"cidr": "%s"' % REGION_DHCP_CONFIG['cidr']))
663
# TODO: We need to read all IP ranges for the subnet and check that the range
664
# has actually been created regardless whether we checked the output above.
665
output, err = self._run_maas_cli(
634
# If the range was configured correct, it should return the subnet
635
# where the range belogs to. As such, we check the output to ensure
638
output, Contains('"cidr": "%s"' % REGION_DHCP_CONFIG['cidr'])
640
# TODO: We need to read all IP ranges for the subnet and check that
641
# the range has actually been created regardless whether we checked
643
_, _ = self._run_maas_cli(
666
644
['ipranges', 'read'])
668
646
def _get_rack_systemid_on_region(self):
669
output, err = self._run_maas_cli(["rack-controllers", "read"])
647
output, _ = self._run_maas_cli(["rack-controllers", "read"])
670
648
rack_controllers = loads(output)
672
650
for rack in rack_controllers:
749
727
def test_check_dhcp_service_systemctl(self):
750
728
cmd = ["systemctl", "status", "maas-dhcpd"]
751
# systemd will return 3 if a 'condition failed. This typically means that
752
# /var/lib/maas/dhcpd.conf is not there yet, and we should wait for a bit
753
# to see if the config is written and maas-dhcp is brought up by the rack.
729
# systemd will return 3 if a 'condition failed. This typically means
730
# that /var/lib/maas/dhcpd.conf is not there yet, and we should wait
731
# for a bit to see if the config is written and maas-dhcp is brought up
754
733
retcode, output, err = run_command(cmd)
755
734
while retcode != 0:
756
735
# query systemd every 3 seconds to see if maas-dhcpd us running
758
737
retcode, output, err = run_command(cmd)
759
#pause_until_released((retcode, output, err).__repr__())
760
738
self.assertEqual(0, retcode)
761
739
self.assertIn('Active: active (running)', output)
762
740
self.assertEqual('', err)
816
794
'Space feature only available after 1.9')
817
795
def test_add_new_spaces(self):
818
796
# Create 2 new spaces.
819
output, err = self._run_maas_cli(
797
output, _ = self._run_maas_cli(
820
798
['spaces', 'create', 'name=test-space'])
821
799
out_dict = loads(output)
822
800
self.assertEqual('test-space', out_dict['name'])
823
output, err = self._run_maas_cli(
824
['spaces', 'create', 'name=delete-space'])
825
out_dict = loads(output)
826
self.assertEqual('delete-space', out_dict['name'])
801
output, _ = self._run_maas_cli(
802
['spaces', 'create', 'name=delete-space']
804
delete_space = loads(output)
805
self.assertEqual('delete-space', delete_space['name'])
829
808
StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'),
830
809
'Subnet feature only available after 1.9')
831
810
def test_add_subnet_to_space(self):
832
output, err = self._run_maas_cli(
811
output, _ = self._run_maas_cli(
833
812
['subnets', 'create', 'space=0', 'name=test-subnet',
834
813
'cidr=192.168.200.0/24'])
835
814
out_dict = loads(output)
859
838
StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'),
860
839
'Subnet feature only available after 1.9')
861
840
def test_delete_subnet(self):
862
_, err = self._run_maas_cli(['subnet', 'delete', 'test-subnet'])
863
output, err = self._run_maas_cli(['subnets', 'read'])
865
self.assertEqual(1, len(out), 'space-0 should now have 1 subnet')
866
self.assertNotIn('test-subnet', [n['name'] for n in out])
841
self._run_maas_cli(['subnet', 'delete', 'test-subnet'])
842
output, _ = self._run_maas_cli(['subnets', 'read'])
843
subnets = loads(output)
844
self.assertEqual(1, len(subnets), 'space-0 should now have 1 subnet')
845
self.assertNotIn('test-subnet', [subnet['name'] for subnet in subnets])
867
846
self.assertEqual(
868
out[0]['name'], out[0]['cidr'],
847
subnets[0]['name'], subnets[0]['cidr'],
869
848
'Name and CIDR should be equal for the default subnet.')
872
851
StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'),
873
852
'Space feature only available after 1.9')
874
853
def test_delete_space(self):
875
_, err = self._run_maas_cli(['space', 'delete', 'delete-space'])
854
self._run_maas_cli(['space', 'delete', 'delete-space'])
876
855
# List the remaining zones after the delete command.
877
output, err = self._run_maas_cli(['spaces', 'read'])
856
output, _ = self._run_maas_cli(['spaces', 'read'])
878
857
out_dict = loads(output)
879
858
self.assertNotIn(
880
859
'delete-space', [item['name'] for item in out_dict])
885
864
'Fabric feature only available after 1.9')
886
865
def test_add_new_fabrics(self):
887
866
# Create 2 new fabrics.
888
output, err = self._run_maas_cli(
867
output, _ = self._run_maas_cli(
889
868
['fabrics', 'create', 'name=test-fabric'])
890
out_dict = loads(output)
891
self.assertEqual('test-fabric', out_dict['name'])
892
output, err = self._run_maas_cli(
869
test_fabric = loads(output)
870
self.assertEqual('test-fabric', test_fabric['name'])
871
output, _ = self._run_maas_cli(
893
872
['fabrics', 'create', 'name=delete-fabric'])
894
out_dict = loads(output)
895
self.assertEqual('delete-fabric', out_dict['name'])
873
delete_fabric = loads(output)
874
self.assertEqual('delete-fabric', delete_fabric['name'])
898
877
StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'),
899
878
'VLAN feature only available after 1.9')
900
879
def test_add_vlan_to_fabric(self):
901
output, err = self._run_maas_cli(
880
output, _ = self._run_maas_cli(
902
881
['vlans', 'create', 'test-fabric', 'name=test-vlan', 'vid=2'])
903
out_dict = loads(output)
904
self.assertEqual('test-vlan', out_dict['name'])
905
self.assertEqual('test-fabric', out_dict['fabric'])
906
self.assertEqual(2, out_dict['vid'])
882
test_vlan = loads(output)
883
self.assertEqual('test-vlan', test_vlan['name'])
884
self.assertEqual('test-fabric', test_vlan['fabric'])
885
self.assertEqual(2, test_vlan['vid'])
909
888
StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'),
910
889
'Fabric feature only available after 1.9')
911
890
def test_list_fabrics(self):
912
output, err = self._run_maas_cli(['fabrics', 'read'])
913
out_dict = loads(output)
914
fabric_names = [item['name'] for item in out_dict]
891
output, _ = self._run_maas_cli(['fabrics', 'read'])
892
fabrics = loads(output)
893
fabric_names = [fabric['name'] for fabric in fabrics]
915
894
self.assertThat(fabric_names, Contains('test-fabric'))
916
895
fabric_names.remove('test-fabric')
917
896
self.assertThat(fabric_names, Contains('delete-fabric'))
918
897
fabric_names.remove('delete-fabric')
919
898
for fabric_name in fabric_names:
920
self.assertThat(fabric_name, MatchesRegex('fabric-\d$'))
899
self.assertThat(fabric_name, MatchesRegex(r'fabric-\d$'))
923
902
[[v['name'] for v in f['vlans']]
924
for f in out_dict if f['name'] == 'test-fabric'][0])
903
for f in fabrics if f['name'] == 'test-fabric'][0])
927
906
StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'),
928
907
'VLAN feature only available after 1.9')
929
908
def test_list_vlans(self):
930
output, err = self._run_maas_cli(['vlans', 'read', 'test-fabric'])
931
out_dict = loads(output)
909
output, _ = self._run_maas_cli(['vlans', 'read', 'test-fabric'])
910
vlans = loads(output)
932
911
expected = ['untagged', 'test-vlan']
933
self.assertItemsEqual(expected, [v['name'] for v in out_dict])
912
self.assertItemsEqual(expected, [v['name'] for v in vlans])
936
915
StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'),
937
916
'VLAN feature only available after 1.9')
938
917
def test_delete_vlan(self):
939
_, err = self._run_maas_cli(
940
['vlan', 'delete', 'test-fabric', 'test-vlan'])
941
output, err = self._run_maas_cli(['vlans', 'read', 'test-fabric'])
943
self.assertNotIn('test-vlan', [v['name'] for v in out])
944
self.assertEqual(1, len(out), 'Fabric should have only one VLAN now.')
918
self._run_maas_cli(['vlan', 'delete', 'test-fabric', 'test-vlan'])
919
output, _ = self._run_maas_cli(['vlans', 'read', 'test-fabric'])
920
vlans = loads(output)
921
self.assertNotIn('test-vlan', [v['name'] for v in vlans])
923
1, len(vlans), 'Fabric should have only one VLAN now.'
946
926
def test_reserve_bmc_range(self):
947
_, err = self._run_maas_cli(
948
['ipranges', 'create', 'type=reserved',
949
'start_ip=' + BMC_START_IP, 'end_ip=' + BMC_END_IP,
952
output, err = self._run_maas_cli(
928
'ipranges', 'create', 'type=reserved',
929
'start_ip=' + BMC_START_IP, 'end_ip=' + BMC_END_IP,
932
output, _ = self._run_maas_cli(
953
933
['ipranges', 'read']
935
ipranges = loads(output)
956
936
# TODO: assert that newly created range is there
959
if range['comment'] == 'BMCs':
938
for iprange in ipranges:
939
if iprange['comment'] == 'BMCs':
961
941
self.assertIsNotNone(bmc_range, 'BMC range not found')
962
942
self.assertThat(bmc_range['start_ip'], Equals(BMC_START_IP))
963
943
self.assertThat(bmc_range['end_ip'], Equals(BMC_END_IP))
994
974
@skipUnless(USE_PPC_NODES, "Not testing PPC systems")
995
975
def test_add_boot_source_selection_ppc64el(self):
996
976
# Add the ppc64el boot source selection to all boot sources
997
output, err = self._run_maas_cli(["boot-sources", "read"])
977
output, _ = self._run_maas_cli(["boot-sources", "read"])
998
978
boot_sources = loads(output)
999
979
for source in boot_sources:
1000
output, err = self._run_maas_cli(
980
output, _ = self._run_maas_cli(
1001
981
["boot-source-selections", "read", str(source["id"])]
1003
selections = loads(output)
1004
983
# To add a new arch we need to specify the arches= parameter
1005
984
# multiple times, e.g. arches=amd64 arches=ppc64el
1006
for selection in selections:
985
for selection in loads(output):
1007
986
new_arches = selection['arches'] + ['ppc64el']
1008
987
selection_update_params = [
1009
988
'arches={arch}'.format(arch=arch) for arch in new_arches
1011
output, err = self._run_maas_cli([
990
output, _ = self._run_maas_cli([
1012
991
"boot-source-selection",
1014
993
str(source["id"]),
1015
994
str(selection["id"]),
1016
995
] + selection_update_params)
1017
996
updated_selection = loads(output)
1018
self.assertThat(updated_selection["arches"], Equals(new_arches))
998
updated_selection["arches"], Equals(new_arches)
1020
1001
def test_start_image_import(self):
1021
output, err = self._run_maas_cli(
1022
["boot-resources", "import"])
1024
output, Contains("Import of boot resources started")
1002
output, _ = self._run_maas_cli(["boot-resources", "import"])
1003
self.assertThat(output, Contains("Import of boot resources started"))
1027
1005
@timeout(60 * 60) # Allow for up to one hour
1028
1006
def test_region_imported_images(self):
1366
1350
def copy_juju_log(cls):
1367
1351
# Use timeout because juju debug-log never returns (known juju bug).
1368
ret, stdout, stderr = run_command(
1369
["timeout", "10", "juju", "debug-log", "--replay", "-l", "TRACE"])
1352
_, stdout, _ = run_command(
1353
["timeout", "10", "juju", "debug-log", "--replay", "-l", "TRACE"]
1370
1355
log_dir = "/var/log/maas"
1371
1356
stdout_path = os.path.join(log_dir, 'juju-log-replay.stdout')
1372
1357
with open(stdout_path, 'wb') as w_file:
1373
1358
w_file.write(stdout.encode('utf-8'))
1374
ret, stdout, stderr = run_command([
1375
"juju", "scp", "0:/var/log/juju/*", log_dir])
1360
["juju", "scp", "0:/var/log/juju/*", log_dir]
1378
1364
def tearDownClass(cls):