277
253
rack_vlan = rack_interface_link['subnet']['vlan']['name']
279
255
maas_dhcp_cmd = [
280
'vlan', 'update', rack_fabric, rack_vlan, 'dhcp_on=True',
281
'primary_rack=%s' % primary_rack_system_id]
283
output, err = self._run_maas_cli(maas_dhcp_cmd)
286
vlan_result = loads(output)
289
#from maas.provisioningserver.service_monitor import get_service_state
290
pause_until_released(ng_list.__repr__())
291
# The JSON object returned by MAAS doesn't include the router_ip
292
# address, so let's remove it from the dhcp_config before comparing.
256
'vlan', 'update', rack_fabric, rack_vlan, 'dhcp_on=True',
257
'primary_rack=%s' % primary_rack_system_id
259
output, _ = self._run_maas_cli(maas_dhcp_cmd)
260
vlan_result = loads(output)
293
261
self.assertEqual(True, vlan_result['dhcp_on'])
295
263
def _boot_nodes(self):
365
337
command = ["juju", "--debug"]
366
338
command.extend(args)
367
339
retcode, output, err = run_command(command, env=env)
368
command_name = " ".join(map(pipes.quote, command))
340
command_name = " ".join(command)
369
341
self.addDetail(command_name, text_content(output))
370
342
self.addDetail(command_name, text_content(err))
371
343
return retcode, output, err
373
345
def get_juju_status(self):
374
346
# Juju2 status defaults to tabular so we need to force YAML
375
_, status_output, _ = self._run_juju_command(["status", "--format=yaml"])
347
_, status_output, _ = self._run_juju_command(
348
["status", "--format=yaml"]
376
350
status = yaml.safe_load(status_output)
536
511
place to put a pause."""
537
512
# pause_until_released('test_maas_logged_in')
538
513
cmd = ["maas", "list"]
539
retcode, output, err = run_command(cmd)
514
retcode, _, err = run_command(cmd)
540
515
self.assertEqual(0, retcode)
541
516
self.assertEqual('', err)
543
518
def test_set_main_archive(self):
544
output, err = self._run_maas_cli([
519
output, _ = self._run_maas_cli([
545
520
"maas", "set-config", "name=main_archive",
546
521
"value=%s" % MAIN_ARCHIVE])
547
522
self.assertThat(output, Contains("OK"))
548
output, err = self._run_maas_cli([
523
output, _ = self._run_maas_cli([
549
524
"maas", "get-config", "name=main_archive"])
550
525
self.assertThat(output, Contains(MAIN_ARCHIVE))
656
631
def test_create_dynamic_range(self):
657
output, err = self._run_maas_cli(
632
output, _ = self._run_maas_cli(
658
633
['ipranges', 'create', 'type=dynamic',
659
634
'start_ip=%s' % REGION_DHCP_CONFIG['ip_range_low'],
660
635
'end_ip=%s' % REGION_DHCP_CONFIG['ip_range_high']])
661
# If the range was configured correct, it should return the subnet where
662
# the range belogs to. As such, we check the output to ensure it is there.
663
self.assertThat(output, Contains('"cidr": "%s"' % REGION_DHCP_CONFIG['cidr']))
664
# TODO: We need to read all IP ranges for the subnet and check that the range
665
# has actually been created regardless whether we checked the output above.
666
output, err = self._run_maas_cli(
636
# If the range was configured correct, it should return the subnet
637
# where the range belogs to. As such, we check the output to ensure
640
output, Contains('"cidr": "%s"' % REGION_DHCP_CONFIG['cidr'])
642
# TODO: We need to read all IP ranges for the subnet and check that
643
# the range has actually been created regardless whether we checked
645
_, _ = self._run_maas_cli(
667
646
['ipranges', 'read'])
669
648
def _get_rack_systemid_on_region(self):
670
output, err = self._run_maas_cli(["rack-controllers", "read"])
649
output, _ = self._run_maas_cli(["rack-controllers", "read"])
671
650
rack_controllers = loads(output)
673
652
for rack in rack_controllers:
750
729
def test_check_dhcp_service_systemctl(self):
751
730
cmd = ["systemctl", "status", "maas-dhcpd"]
752
# systemd will return 3 if a 'condition failed. This typically means that
753
# /var/lib/maas/dhcpd.conf is not there yet, and we should wait for a bit
754
# to see if the config is written and maas-dhcp is brought up by the rack.
731
# systemd will return 3 if a 'condition failed. This typically means
732
# that /var/lib/maas/dhcpd.conf is not there yet, and we should wait
733
# for a bit to see if the config is written and maas-dhcp is brought up
755
735
retcode, output, err = run_command(cmd)
756
736
while retcode != 0:
757
737
# query systemd every 3 seconds to see if maas-dhcpd us running
759
739
retcode, output, err = run_command(cmd)
760
#pause_until_released((retcode, output, err).__repr__())
761
740
self.assertEqual(0, retcode)
762
741
self.assertIn('Active: active (running)', output)
763
742
self.assertEqual('', err)
817
796
'Space feature only available after 1.9')
818
797
def test_add_new_spaces(self):
819
798
# Create 2 new spaces.
820
output, err = self._run_maas_cli(
799
output, _ = self._run_maas_cli(
821
800
['spaces', 'create', 'name=test-space'])
822
801
out_dict = loads(output)
823
802
self.assertEqual('test-space', out_dict['name'])
824
output, err = self._run_maas_cli(
825
['spaces', 'create', 'name=delete-space'])
826
out_dict = loads(output)
827
self.assertEqual('delete-space', out_dict['name'])
803
output, _ = self._run_maas_cli(
804
['spaces', 'create', 'name=delete-space']
806
delete_space = loads(output)
807
self.assertEqual('delete-space', delete_space['name'])
830
810
StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'),
831
811
'Subnet feature only available after 1.9')
832
812
def test_add_subnet_to_space(self):
833
output, err = self._run_maas_cli(
813
output, _ = self._run_maas_cli(
834
814
['subnets', 'create', 'space=0', 'name=test-subnet',
835
815
'cidr=192.168.200.0/24'])
836
816
out_dict = loads(output)
860
840
StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'),
861
841
'Subnet feature only available after 1.9')
862
842
def test_delete_subnet(self):
863
_, err = self._run_maas_cli(['subnet', 'delete', 'test-subnet'])
864
output, err = self._run_maas_cli(['subnets', 'read'])
866
self.assertEqual(1, len(out), 'space-0 should now have 1 subnet')
867
self.assertNotIn('test-subnet', [n['name'] for n in out])
843
self._run_maas_cli(['subnet', 'delete', 'test-subnet'])
844
output, _ = self._run_maas_cli(['subnets', 'read'])
845
subnets = loads(output)
846
self.assertEqual(1, len(subnets), 'space-0 should now have 1 subnet')
847
self.assertNotIn('test-subnet', [subnet['name'] for subnet in subnets])
868
848
self.assertEqual(
869
out[0]['name'], out[0]['cidr'],
849
subnets[0]['name'], subnets[0]['cidr'],
870
850
'Name and CIDR should be equal for the default subnet.')
873
853
StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'),
874
854
'Space feature only available after 1.9')
875
855
def test_delete_space(self):
876
_, err = self._run_maas_cli(['space', 'delete', 'delete-space'])
856
self._run_maas_cli(['space', 'delete', 'delete-space'])
877
857
# List the remaining zones after the delete command.
878
output, err = self._run_maas_cli(['spaces', 'read'])
858
output, _ = self._run_maas_cli(['spaces', 'read'])
879
859
out_dict = loads(output)
880
860
self.assertNotIn(
881
861
'delete-space', [item['name'] for item in out_dict])
886
866
'Fabric feature only available after 1.9')
887
867
def test_add_new_fabrics(self):
888
868
# Create 2 new fabrics.
889
output, err = self._run_maas_cli(
869
output, _ = self._run_maas_cli(
890
870
['fabrics', 'create', 'name=test-fabric'])
891
out_dict = loads(output)
892
self.assertEqual('test-fabric', out_dict['name'])
893
output, err = self._run_maas_cli(
871
test_fabric = loads(output)
872
self.assertEqual('test-fabric', test_fabric['name'])
873
output, _ = self._run_maas_cli(
894
874
['fabrics', 'create', 'name=delete-fabric'])
895
out_dict = loads(output)
896
self.assertEqual('delete-fabric', out_dict['name'])
875
delete_fabric = loads(output)
876
self.assertEqual('delete-fabric', delete_fabric['name'])
899
879
StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'),
900
880
'VLAN feature only available after 1.9')
901
881
def test_add_vlan_to_fabric(self):
902
output, err = self._run_maas_cli(
882
output, _ = self._run_maas_cli(
903
883
['vlans', 'create', 'test-fabric', 'name=test-vlan', 'vid=2'])
904
out_dict = loads(output)
905
self.assertEqual('test-vlan', out_dict['name'])
906
self.assertEqual('test-fabric', out_dict['fabric'])
907
self.assertEqual(2, out_dict['vid'])
884
test_vlan = loads(output)
885
self.assertEqual('test-vlan', test_vlan['name'])
886
self.assertEqual('test-fabric', test_vlan['fabric'])
887
self.assertEqual(2, test_vlan['vid'])
910
890
StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'),
911
891
'Fabric feature only available after 1.9')
912
892
def test_list_fabrics(self):
913
output, err = self._run_maas_cli(['fabrics', 'read'])
914
out_dict = loads(output)
915
fabric_names = [item['name'] for item in out_dict]
893
output, _ = self._run_maas_cli(['fabrics', 'read'])
894
fabrics = loads(output)
895
fabric_names = [fabric['name'] for fabric in fabrics]
916
896
self.assertThat(fabric_names, Contains('test-fabric'))
917
897
fabric_names.remove('test-fabric')
918
898
self.assertThat(fabric_names, Contains('delete-fabric'))
919
899
fabric_names.remove('delete-fabric')
920
900
for fabric_name in fabric_names:
921
self.assertThat(fabric_name, MatchesRegex('fabric-\d$'))
901
self.assertThat(fabric_name, MatchesRegex(r'fabric-\d$'))
924
904
[[v['name'] for v in f['vlans']]
925
for f in out_dict if f['name'] == 'test-fabric'][0])
905
for f in fabrics if f['name'] == 'test-fabric'][0])
928
908
StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'),
929
909
'VLAN feature only available after 1.9')
930
910
def test_list_vlans(self):
931
output, err = self._run_maas_cli(['vlans', 'read', 'test-fabric'])
932
out_dict = loads(output)
911
output, _ = self._run_maas_cli(['vlans', 'read', 'test-fabric'])
912
vlans = loads(output)
933
913
expected = ['untagged', 'test-vlan']
934
self.assertItemsEqual(expected, [v['name'] for v in out_dict])
914
self.assertItemsEqual(expected, [v['name'] for v in vlans])
937
917
StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'),
938
918
'VLAN feature only available after 1.9')
939
919
def test_delete_vlan(self):
940
_, err = self._run_maas_cli(
941
['vlan', 'delete', 'test-fabric', 'test-vlan'])
942
output, err = self._run_maas_cli(['vlans', 'read', 'test-fabric'])
944
self.assertNotIn('test-vlan', [v['name'] for v in out])
945
self.assertEqual(1, len(out), 'Fabric should have only one VLAN now.')
920
self._run_maas_cli(['vlan', 'delete', 'test-fabric', 'test-vlan'])
921
output, _ = self._run_maas_cli(['vlans', 'read', 'test-fabric'])
922
vlans = loads(output)
923
self.assertNotIn('test-vlan', [v['name'] for v in vlans])
925
1, len(vlans), 'Fabric should have only one VLAN now.'
947
928
def test_reserve_bmc_range(self):
948
_, err = self._run_maas_cli(
949
['ipranges', 'create', 'type=reserved',
950
'start_ip=' + BMC_START_IP, 'end_ip=' + BMC_END_IP,
953
output, err = self._run_maas_cli(
930
'ipranges', 'create', 'type=reserved',
931
'start_ip=' + BMC_START_IP, 'end_ip=' + BMC_END_IP,
934
output, _ = self._run_maas_cli(
954
935
['ipranges', 'read']
937
ipranges = loads(output)
957
938
# TODO: assert that newly created range is there
960
if range['comment'] == 'BMCs':
940
for iprange in ipranges:
941
if iprange['comment'] == 'BMCs':
962
943
self.assertIsNotNone(bmc_range, 'BMC range not found')
963
944
self.assertThat(bmc_range['start_ip'], Equals(BMC_START_IP))
964
945
self.assertThat(bmc_range['end_ip'], Equals(BMC_END_IP))
995
976
@skipUnless(USE_PPC_NODES, "Not testing PPC systems")
996
977
def test_add_boot_source_selection_ppc64el(self):
997
978
# Add the ppc64el boot source selection to all boot sources
998
output, err = self._run_maas_cli(["boot-sources", "read"])
979
output, _ = self._run_maas_cli(["boot-sources", "read"])
999
980
boot_sources = loads(output)
1000
981
for source in boot_sources:
1001
output, err = self._run_maas_cli(
982
output, _ = self._run_maas_cli(
1002
983
["boot-source-selections", "read", str(source["id"])]
1004
selections = loads(output)
1005
985
# To add a new arch we need to specify the arches= parameter
1006
986
# multiple times, e.g. arches=amd64 arches=ppc64el
1007
for selection in selections:
987
for selection in loads(output):
1008
988
new_arches = selection['arches'] + ['ppc64el']
1009
989
selection_update_params = [
1010
990
'arches={arch}'.format(arch=arch) for arch in new_arches
1012
output, err = self._run_maas_cli([
992
output, _ = self._run_maas_cli([
1013
993
"boot-source-selection",
1015
995
str(source["id"]),
1016
996
str(selection["id"]),
1017
997
] + selection_update_params)
1018
998
updated_selection = loads(output)
1019
self.assertThat(updated_selection["arches"], Equals(new_arches))
1000
updated_selection["arches"], Equals(new_arches)
1021
1003
def test_start_image_import(self):
1022
output, err = self._run_maas_cli(
1023
["boot-resources", "import"])
1025
output, Contains("Import of boot resources started")
1004
output, _ = self._run_maas_cli(["boot-resources", "import"])
1005
self.assertThat(output, Contains("Import of boot resources started"))
1028
1007
@timeout(60 * 60) # Allow for up to one hour
1029
1008
def test_region_imported_images(self):
1428
1413
def copy_juju_log(cls):
1429
1414
# Use timeout because juju debug-log never returns (known juju bug).
1430
ret, stdout, stderr = run_command(
1431
["timeout", "10", "juju", "debug-log", "--replay", "-l", "TRACE"])
1415
_, stdout, _ = run_command(
1416
["timeout", "10", "juju", "debug-log", "--replay", "-l", "TRACE"]
1432
1418
log_dir = "/var/log/maas"
1433
1419
stdout_path = os.path.join(log_dir, 'juju-log-replay.stdout')
1434
1420
with open(stdout_path, 'wb') as w_file:
1435
1421
w_file.write(stdout.encode('utf-8'))
1436
ret, stdout, stderr = run_command([
1437
"juju", "scp", "0:/var/log/juju/*", log_dir])
1423
["juju", "scp", "0:/var/log/juju/*", log_dir]
1440
1427
def tearDownClass(cls):