def test__permission_errors(self): user = factory.make_User() source = factory.make_Machine(with_boot_disk=False) factory.make_PhysicalBlockDevice(node=source, size=8 * 1024**3, name="sda") factory.make_Interface(node=source, name='eth0') destination = factory.make_Machine(status=NODE_STATUS.READY, with_boot_disk=False) factory.make_PhysicalBlockDevice(node=destination, size=8 * 1024**3, name="sda") factory.make_Interface(node=destination, name='eth0') form = CloneForm(user, data={ 'source': source.system_id, 'destinations': [destination.system_id], 'storage': True, 'interfaces': True, }) self.assertFalse(form.is_valid()) self.assertEquals( { 'destinations': [ 'Machine 0 in the array did not validate: ' 'Select a valid choice. %s is not one of the available ' 'choices.' % destination.system_id ], }, form.errors)
def test_POST_create_validates_architecture(self): hostname = factory.make_name("hostname") power_type = 'ipmi' power_parameters = { "power_address": factory.make_ip_address(), "power_user": factory.make_name("power-user"), "power_pass": factory.make_name("power-pass"), "power_driver": 'LAN_2_0', "mac_address": '', "power_boot_type": 'auto', } factory.make_Machine(hostname=hostname, status=NODE_STATUS.NEW, architecture='', power_type=power_type, power_parameters=power_parameters) response = self.client.post( reverse('machines_handler'), { 'hostname': 'maas-enlistment', 'architecture': factory.make_name('arch'), 'power_type': power_type, 'mac_addresses': factory.make_mac_address(), 'power_parameters': json.dumps(power_parameters), }) self.assertEqual(http.client.BAD_REQUEST, response.status_code)
def test_permission_errors(self): user = factory.make_User() source = factory.make_Machine(with_boot_disk=False) factory.make_PhysicalBlockDevice(node=source, size=8 * 1024**3, name="sda") factory.make_Interface(node=source, name="eth0") destination = factory.make_Machine( status=random.choice( [NODE_STATUS.READY, NODE_STATUS.FAILED_TESTING]), with_boot_disk=False, ) factory.make_PhysicalBlockDevice(node=destination, size=8 * 1024**3, name="sda") factory.make_Interface(node=destination, name="eth0") form = CloneForm( user, data={ "source": source.system_id, "destinations": [destination.system_id], "storage": True, "interfaces": True, }, ) self.assertFalse(form.is_valid()) self.assertEqual( { "destinations": [ f"Machine 1 is invalid: Select a valid choice. {destination.system_id} is not one of the available choices." ] }, form.errors, )
def test__source_destination_smaller_storage(self): user = factory.make_admin() source = factory.make_Machine(with_boot_disk=False) factory.make_PhysicalBlockDevice(node=source, size=8 * 1024**3, name="sda") destination = factory.make_Machine(status=NODE_STATUS.READY, with_boot_disk=False) factory.make_PhysicalBlockDevice(node=destination, size=4 * 1024**3, name="sda") form = CloneForm(user, data={ 'source': source.system_id, 'destinations': [destination.system_id], 'storage': True, }) self.assertFalse(form.is_valid()) self.assertEquals( { 'destinations': [ 'Machine 0 in the array did not validate: ' 'destination boot disk(sda) is smaller than ' 'source boot disk(sda)' ], }, form.errors)
def test_source_destination_missing_nic(self): user = factory.make_admin() source = factory.make_Machine(with_boot_disk=False) factory.make_Interface(node=source, name="eth0") destination = factory.make_Machine( status=random.choice( [NODE_STATUS.READY, NODE_STATUS.FAILED_TESTING]), with_boot_disk=False, ) factory.make_Interface(node=destination, name="eth1") form = CloneForm( user, data={ "source": source.system_id, "destinations": [destination.system_id], "interfaces": True, }, ) self.assertFalse(form.is_valid()) self.assertEqual( { "destinations": [ "Machine 1 in the array did not validate: " "destination node physical interfaces do not match " "the source nodes physical interfaces: eth0" ] }, form.errors, )
def test_POST_create_validates_architecture(self): hostname = factory.make_name("hostname") power_type = "ipmi" power_parameters = { "power_address": factory.make_ip_address(), "power_user": factory.make_name("power-user"), "power_pass": factory.make_name("power-pass"), "power_driver": "LAN_2_0", "mac_address": "", "power_boot_type": "auto", } factory.make_Machine( hostname=hostname, status=NODE_STATUS.NEW, architecture="", power_type=power_type, power_parameters=power_parameters, ) response = self.client.post( reverse("machines_handler"), { "hostname": "maas-enlistment", "architecture": factory.make_name("arch"), "power_type": power_type, "mac_addresses": factory.make_mac_address(), "power_parameters": json.dumps(power_parameters), }, ) self.assertEqual(http.client.BAD_REQUEST, response.status_code)
def test__performs_clone(self): user = factory.make_admin() source = factory.make_Machine(with_boot_disk=False) factory.make_PhysicalBlockDevice(node=source, size=8 * 1024**3, name="sda") factory.make_Interface(node=source, name='eth0') destination1 = factory.make_Machine(status=NODE_STATUS.READY, with_boot_disk=False) factory.make_PhysicalBlockDevice(node=destination1, size=8 * 1024**3, name="sda") factory.make_Interface(node=destination1, name='eth0') destination2 = factory.make_Machine(status=NODE_STATUS.READY, with_boot_disk=False) factory.make_PhysicalBlockDevice(node=destination2, size=8 * 1024**3, name="sda") factory.make_Interface(node=destination2, name='eth0') form = CloneForm(user, data={ 'source': source.system_id, 'destinations': [destination1.system_id, destination2.system_id], 'storage': True, 'interfaces': True, }) self.assertTrue(form.is_valid()) # An exception here will cause the test to fail. form.save()
def test_get_machine_count(self): user = factory.make_User() handler = ResourcePoolHandler(user, {}, None) pool = factory.make_ResourcePool() factory.make_Machine(pool=pool) result = handler.get({"id": pool.id}) self.assertEqual(1, result['machine_total_count'])
def test_get_maas_stats(self): # Make one component of everything factory.make_RegionRackController() factory.make_RegionController() factory.make_RackController() factory.make_Machine(cpu_count=2, memory=200) factory.make_Machine(cpu_count=3, memory=100) factory.make_Device() stats = get_maas_stats() machine_stats = get_machine_stats() # Due to floating point calculation subtleties, sometimes the value the # database returns is off by one compared to the value Python # calculates, so just get it directly from the database for the test. total_storage = machine_stats['total_storage'] compare = { "controllers": { "regionracks": 1, "regions": 1, "racks": 1, }, "nodes": { "machines": 2, "devices": 1, }, "machine_stats": { "total_cpu": 5, "total_mem": 300, "total_storage": total_storage, }, } self.assertEquals(stats, json.dumps(compare))
def test_multiple_errors(self): user = factory.make_admin() source = factory.make_Machine(status=NODE_STATUS.READY, with_boot_disk=False) factory.make_PhysicalBlockDevice(node=source, size=8 * 1024**3, name="sda") destination = factory.make_Machine(status=NODE_STATUS.READY, with_boot_disk=False) factory.make_PhysicalBlockDevice(node=destination, size=4 * 1024**3, name="sda") form = CloneForm( user, data={ "source": source.system_id, "destinations": [source.system_id, destination.system_id], "storage": True, }, ) self.assertFalse(form.is_valid()) self.assertEqual( { "destinations": [ f"Source machine {source} cannot be a destination machine.", f"{destination} is invalid: " "destination boot disk(sda) is smaller than " "source boot disk(sda)", ] }, form.errors, )
def test_source_destination_smaller_storage(self): user = factory.make_admin() source = factory.make_Machine(with_boot_disk=False) factory.make_PhysicalBlockDevice(node=source, size=8 * 1024**3, name="sda") destination = factory.make_Machine( status=random.choice( [NODE_STATUS.READY, NODE_STATUS.FAILED_TESTING]), with_boot_disk=False, ) factory.make_PhysicalBlockDevice(node=destination, size=4 * 1024**3, name="sda") form = CloneForm( user, data={ "source": source.system_id, "destinations": [destination.system_id], "storage": True, }, ) self.assertFalse(form.is_valid()) self.assertEqual( { "destinations": [ "Machine 1 in the array did not validate: " "destination boot disk(sda) is smaller than " "source boot disk(sda)" ] }, form.errors, )
def test_get_vm_hosts_stats_machine_usage(self): lxd_vm_host = self.make_pod(cpu=10, mem=100, pod_type="lxd") lxd_machine = factory.make_Machine(bmc=lxd_vm_host, cpu_count=1, memory=10) factory.make_VirtualMachine(bmc=lxd_vm_host, machine=lxd_machine) virsh_vm_host = self.make_pod(cpu=20, mem=200, pod_type="virsh") virsh_machine = factory.make_Machine(bmc=virsh_vm_host, cpu_count=2, memory=20) factory.make_VirtualMachine(bmc=virsh_vm_host, machine=virsh_machine) stats = get_vm_hosts_stats(power_type="lxd") compare = { "vm_hosts": 1, "vms": 1, "available_resources": { "cores": 10, "memory": 100, "over_cores": 10.0, "over_memory": 100.0, "storage": 0, }, "utilized_resources": { "cores": 1, "memory": 10, "storage": 0 }, } self.assertEqual(compare, stats)
def test_get_machine_ready_count(self): user = factory.make_User() handler = ResourcePoolHandler(user, {}, None) pool = factory.make_ResourcePool() factory.make_Machine(pool=pool, status=NODE_STATUS.NEW) factory.make_Machine(pool=pool, status=NODE_STATUS.READY) result = handler.get({"id": pool.id}) self.assertEqual(2, result['machine_total_count']) self.assertEqual(1, result['machine_ready_count'])
def test_DELETE_calls_async_delete(self): pod = factory.make_Pod() for _ in range(3): factory.make_Machine(bmc=pod) mock_eventual = MagicMock() mock_async_delete = self.patch(Pod, "async_delete") mock_async_delete.return_value = mock_eventual response = self.client.delete(get_pod_uri(pod)) self.assertEqual(http.client.NO_CONTENT, response.status_code, response.content) self.assertThat(mock_eventual.wait, MockCalledOnceWith(60))
def test_get_machines_by_architecture(self): arches = [ "amd64/generic", "s390x/generic", "ppc64el/generic", "arm64/generic", "i386/generic", ] for arch in arches: factory.make_Machine(architecture=arch) stats = get_machines_by_architecture() compare = {"amd64": 1, "i386": 1, "arm64": 1, "ppc64el": 1, "s390x": 1} self.assertEqual(stats, compare)
def test_get_workload_annotations_stats_machines(self): machine1 = factory.make_Machine(status=NODE_STATUS.DEPLOYED) machine2 = factory.make_Machine(status=NODE_STATUS.DEPLOYED) machine3 = factory.make_Machine(status=NODE_STATUS.DEPLOYED) factory.make_Machine(status=NODE_STATUS.DEPLOYED) OwnerData.objects.set_owner_data(machine1, { "key1": "value1", "key2": "value2" }) OwnerData.objects.set_owner_data(machine2, {"key1": "value1"}) OwnerData.objects.set_owner_data(machine3, {"key2": "value2"}) workload_stats = get_workload_annotations_stats() self.assertEqual(3, workload_stats["annotated_machines"])
def test_yields_boot_rack_addresses_when_machine_has_booted(self): machine = factory.make_Machine() address = factory.make_StaticIPAddress( interface=factory.make_Interface(node=machine)) rack_primary = factory.make_RackController() rack_primary_address = factory.make_StaticIPAddress( interface=factory.make_Interface(node=rack_primary), subnet=address.subnet, ) rack_secondary = factory.make_RackController() rack_secondary_address = factory.make_StaticIPAddress( interface=factory.make_Interface(node=rack_secondary), subnet=address.subnet, ) rack_other = factory.make_RackController() rack_other_address = factory.make_StaticIPAddress( # noqa interface=factory.make_Interface(node=rack_other), subnet=address.subnet, ) vlan = address.subnet.vlan vlan.primary_rack = rack_primary vlan.secondary_rack = rack_secondary vlan.dhcp_on = True vlan.save() servers = get_servers_for(machine) self.assertThat( servers, IsSetOfServers( {rack_primary_address.ip, rack_secondary_address.ip}), )
def test_POST_create_returns_machine_with_matching_mac(self): hostname = factory.make_name('hostname') machine = factory.make_Machine(hostname=hostname, status=NODE_STATUS.NEW, architecture='') macs = [ str(factory.make_Interface(node=machine).mac_address) for _ in range(3) ] architecture = make_usable_architecture(self) response = self.client.post( reverse('machines_handler'), { 'hostname': 'maas-enlistment', 'architecture': architecture, 'mac_addresses': [ # Machine only has to match one MAC address. random.choice(macs), # A MAC address unknown to MAAS shouldn't effect finding # the machine. factory.make_MAC(), ], }) self.assertEqual(http.client.OK, response.status_code) machine = reload_object(machine) self.assertEqual(hostname, machine.hostname) self.assertEqual(architecture, machine.architecture) self.assertEqual(machine.system_id, json_load_bytes(response.content)['system_id'])
def test_PUT(self): self.become_admin() node = factory.make_Machine(status=NODE_STATUS.READY) vmfs = factory.make_VMFS(node=node) new_name = factory.make_name('name') new_uuid = str(uuid.uuid4()) new_bd = factory.make_PhysicalBlockDevice(node=node) new_partition = factory.make_Partition(node=node) del_partition = random.choice(vmfs.filesystems.all()).get_parent() partition_ids = set( [fs.get_parent().id for fs in vmfs.filesystems.all()]) partition_ids.add(new_partition.id) partition_ids.remove(del_partition.id) response = self.client.put( self.get_vmfs_uri(vmfs), { 'name': new_name, 'uuid': new_uuid, 'add_block_devices': [random.choice([new_bd.id, new_bd.name])], 'add_partitions': [random.choice([new_partition.id, new_partition.name])], 'remove_partitions': [random.choice([del_partition.id, del_partition.name])], }) self.assertThat(response, HasStatusCode(http.client.OK)) vmfs = reload_object(vmfs) partition_ids.add(new_bd.get_partitiontable().partitions.first().id) self.assertEquals(new_name, vmfs.name) self.assertEquals(new_uuid, vmfs.uuid) self.assertItemsEqual( partition_ids, [fs.get_parent().id for fs in vmfs.filesystems.all()])
def test_DELETE(self): self.become_admin() node = factory.make_Machine(status=NODE_STATUS.READY) vmfs = factory.make_VMFS(node=node) response = self.client.delete(self.get_vmfs_uri(vmfs)) self.assertThat(response, HasStatusCode(http.client.NO_CONTENT)) self.assertIsNone(reload_object(vmfs))
def test_save_purges_orphaned_script_results_storage(self): node = factory.make_Machine() physical_blockdevice = node.physicalblockdevice_set.first() script = factory.make_Script( parameters={"storage": { "type": "storage" }}) old_script_set = factory.make_ScriptSet(node=node) old_script_result = factory.make_ScriptResult( script=script, script_set=old_script_set, status=factory.pick_choice(SCRIPT_STATUS_CHOICES, but_not=[SCRIPT_STATUS.PASSED]), parameters={"storage": { "type": "storage", "value": "all" }}, ) new_script_set = factory.make_ScriptSet(node=node) new_script_result = factory.make_ScriptResult( script=script, script_set=new_script_set, status=SCRIPT_STATUS.PENDING, parameters={ "storage": { "type": "storage", "value": { "physical_blockdevice": physical_blockdevice }, } }, ) self.assertIsNone(reload_object(old_script_result)) self.assertIsNotNone(reload_object(new_script_result))
def test_save_sets_physical_blockdevice_from_parameters(self): node = factory.make_Machine() script_set = factory.make_ScriptSet(node=node) physical_blockdevice = node.physicalblockdevice_set.first() script_result = factory.make_ScriptResult( script_set=script_set, parameters={'storage': { 'type': 'storage', 'value': { 'name': physical_blockdevice.name, 'id_path': physical_blockdevice.id_path, 'model': physical_blockdevice.model, 'serial': physical_blockdevice.serial, 'physical_blockdevice': physical_blockdevice, }}}) self.assertEquals( physical_blockdevice, script_result.physical_blockdevice) self.assertDictEqual({'storage': { 'type': 'storage', 'value': { 'name': physical_blockdevice.name, 'id_path': physical_blockdevice.id_path, 'model': physical_blockdevice.model, 'serial': physical_blockdevice.serial, 'physical_blockdevice_id': physical_blockdevice.id, }}}, script_result.parameters)
def test_save_sets_interface_from_parameters(self): node = factory.make_Machine() script_set = factory.make_ScriptSet(node=node) interface = factory.make_Interface(node=node) script_result = factory.make_ScriptResult( script_set=script_set, parameters={ 'interface': { 'type': 'interface', 'value': { 'name': interface.name, 'mac_address': str(interface.mac_address), 'vendor': interface.vendor, 'product': interface.product, 'interface': interface, } } }) self.assertEquals(interface, script_result.interface) self.assertIsNone(script_result.physical_blockdevice) self.assertDictEqual( { 'interface': { 'type': 'interface', 'value': { 'name': interface.name, 'mac_address': str(interface.mac_address), 'vendor': interface.vendor, 'product': interface.product, 'interface_id': interface.id, } } }, script_result.parameters)
def test__source_destination_match_error(self): user = factory.make_admin() source = factory.make_Machine( status=random.choice( [NODE_STATUS.READY, NODE_STATUS.FAILED_TESTING] ) ) form = CloneForm( user, data={ "source": source.system_id, "destinations": [source.system_id], "storage": True, }, ) self.assertFalse(form.is_valid()) self.assertEquals( { "destinations": [ "Machine 0 in the array did not validate: " "Source machine cannot be a destination machine." ] }, form.errors, )
def test_yields_boot_cluster_address_when_machine_has_booted(self): Config.objects.set_config("ntp_external_only", False) machine = factory.make_Machine() address = factory.make_StaticIPAddress( interface=factory.make_Interface(node=machine)) rack_primary = factory.make_RackController(subnet=address.subnet) rack_primary_address = factory.make_StaticIPAddress( interface=factory.make_Interface(node=rack_primary), subnet=address.subnet) rack_secondary = factory.make_RackController(subnet=address.subnet) rack_secondary_address = factory.make_StaticIPAddress( interface=factory.make_Interface(node=rack_secondary), subnet=address.subnet) vlan = address.subnet.vlan vlan.primary_rack = rack_primary vlan.secondary_rack = rack_secondary vlan.dhcp_on = True vlan.save() configuration = generate_ntp_configuration(machine) self.assertThat( dict(configuration), Equals({ "ntp": { "servers": sorted( (rack_primary_address.ip, rack_secondary_address.ip), key=IPAddress), "pools": [], }, }))
def test_list_switches_includes_link_type_machine(self): owner = factory.make_User() handler = SwitchHandler(owner, {}, None) machine = factory.make_Machine(owner=owner) factory.make_Switch(node=machine) self.assertItemsEqual( ['machine'], [result['link_type'] for result in handler.list({})])
def test_yields_nothing_when_machine_has_no_boot_cluster_address(self): Config.objects.set_config("ntp_external_only", False) machine = factory.make_Machine() machine.boot_cluster_ip = None machine.save() configuration = generate_ntp_configuration(machine) self.assertThat(dict(configuration), Equals({}))
def test_hardware_info(self): self.become_admin() machine = factory.make_Machine(owner=self.user) system_vendor = factory.make_NodeMetadata(machine, 'system_vendor') system_product = factory.make_NodeMetadata(machine, 'system_product') system_version = factory.make_NodeMetadata(machine, 'system_version') system_serial = factory.make_NodeMetadata(machine, 'system_serial') cpu_model = factory.make_NodeMetadata(machine, 'cpu_model') mainboard_vendor = factory.make_NodeMetadata( machine, 'mainboard_vendor') mainboard_product = factory.make_NodeMetadata( machine, 'mainboard_product') mainboard_firmware_version = factory.make_NodeMetadata( machine, 'mainboard_firmware_version') mainboard_firmware_date = factory.make_NodeMetadata( machine, 'mainboard_firmware_date') factory.make_NodeMetadata(machine) response = self.client.get(self.get_node_uri(machine)) parsed_result = json_load_bytes(response.content) self.assertThat(response, HasStatusCode(http.client.OK)) self.assertDictEqual({ 'system_vendor': system_vendor.value, 'system_product': system_product.value, 'system_version': system_version.value, 'system_serial': system_serial.value, 'cpu_model': cpu_model.value, 'mainboard_vendor': mainboard_vendor.value, 'mainboard_product': mainboard_product.value, 'mainboard_firmware_version': mainboard_firmware_version.value, 'mainboard_firmware_date': mainboard_firmware_date.value, }, parsed_result['hardware_info'])
def test_health_status(self): self.become_admin() machine = factory.make_Machine(owner=self.user) commissioning_script_set = factory.make_ScriptSet( result_type=RESULT_TYPE.COMMISSIONING, node=machine) testing_script_set = factory.make_ScriptSet( result_type=RESULT_TYPE.TESTING, node=machine) make_script_result = partial(factory.make_ScriptResult, script_set=testing_script_set, status=factory.pick_choice( SCRIPT_STATUS_CHOICES, but_not=[SCRIPT_STATUS.ABORTED])) commissioning_script_result = make_script_result( script_set=commissioning_script_set, script=factory.make_Script(script_type=SCRIPT_TYPE.COMMISSIONING)) cpu_script_result = make_script_result(script=factory.make_Script( script_type=SCRIPT_TYPE.TESTING, hardware_type=HARDWARE_TYPE.CPU)) memory_script_result = make_script_result( script=factory.make_Script(script_type=SCRIPT_TYPE.TESTING, hardware_type=HARDWARE_TYPE.MEMORY)) storage_script_result = make_script_result( script=factory.make_Script(script_type=SCRIPT_TYPE.TESTING, hardware_type=HARDWARE_TYPE.STORAGE)) node_script_result = make_script_result(script=factory.make_Script( script_type=SCRIPT_TYPE.TESTING, hardware_type=HARDWARE_TYPE.NODE)) testing_script_results = ( machine.get_latest_testing_script_results.exclude( status=SCRIPT_STATUS.ABORTED)) testing_status = get_status_from_qs(testing_script_results) response = self.client.get(self.get_node_uri(machine)) parsed_result = json_load_bytes(response.content) status = lambda s: get_status_from_qs([s]) status_name = lambda s: SCRIPT_STATUS_CHOICES[status(s)][1] self.assertThat(response, HasStatusCode(http.client.OK)) self.assertEquals(status(commissioning_script_result), parsed_result['commissioning_status']) self.assertEquals(status_name(commissioning_script_result), parsed_result['commissioning_status_name']) self.assertEquals(testing_status, parsed_result['testing_status']) self.assertEquals(SCRIPT_STATUS_CHOICES[testing_status][1], parsed_result['testing_status_name']) self.assertEquals(status(cpu_script_result), parsed_result['cpu_test_status']) self.assertEquals(status_name(cpu_script_result), parsed_result['cpu_test_status_name']) self.assertEquals(status(memory_script_result), parsed_result['memory_test_status']) self.assertEquals(status_name(memory_script_result), parsed_result['memory_test_status_name']) self.assertEquals(status(storage_script_result), parsed_result['storage_test_status']) self.assertEquals(status_name(storage_script_result), parsed_result['storage_test_status_name']) self.assertEquals(status(node_script_result), parsed_result['other_test_status']) self.assertEquals(status_name(node_script_result), parsed_result['other_test_status_name'])
def test_get_object_respects_queryset(self): handler = self.make_nodes_handler(queryset=Device.objects.all()) machine = factory.make_Machine() device = factory.make_Device() returned_device = handler.get_object({"system_id": device.system_id}) self.assertEqual(device.hostname, returned_device.hostname) self.assertRaises(HandlerDoesNotExistError, handler.get_object, {"system_id": machine.system_id})