def test__renders_expected_output(self): node = factory.make_Node_with_Interface_on_Subnet( interface_count=2) interfaces = list(node.interface_set.all()) vlan = node.interface_set.first().vlan bond_iface = factory.make_Interface( iftype=INTERFACE_TYPE.BOND, node=node, vlan=vlan, parents=interfaces) bond_iface.params = { "bond_mode": "balance-rr", } bond_iface.save() factory.make_StaticIPAddress( interface=bond_iface, alloc_type=IPADDRESS_TYPE.STICKY, subnet=bond_iface.vlan.subnet_set.first()) net_config = self.collect_interface_config(node, filter="physical") net_config += self.collect_interface_config(node, filter="bond") net_config += self.collectDNSConfig(node) config = compose_curtin_network_config(node) self.assertNetworkConfig(net_config, config)
def test_GET_query_with_invalid_macs_returns_sensible_error(self): # If specifying an invalid MAC, make sure the error that's # returned is not a crazy stack trace, but something nice to # humans. bad_mac1 = '00:E0:81:DD:D1:ZZ' # ZZ is bad. bad_mac2 = '00:E0:81:DD:D1:XX' # XX is bad. node = factory.make_Node_with_Interface_on_Subnet() ok_mac = node.get_boot_interface().mac_address make_events(node=node) response = self.client.get( reverse('events_handler'), { 'op': 'query', 'mac_address': [bad_mac1, bad_mac2, ok_mac], 'level': 'DEBUG' }) self.expectThat(response.status_code, Equals(http.client.BAD_REQUEST)) self.expectThat( response.content, Contains(b"Invalid MAC address(es): 00:E0:81:DD:D1:ZZ, " b"00:E0:81:DD:D1:XX"))
def test__returns_commissioning_os_series_for_other_oses(self): osystem = Config.objects.get_config('default_osystem') release = Config.objects.get_config('default_distro_series') rack_controller = factory.make_RackController() local_ip = factory.make_ip_address() remote_ip = factory.make_ip_address() self.make_node(arch_name='amd64') node = factory.make_Node_with_Interface_on_Subnet( status=NODE_STATUS.DEPLOYING, osystem="centos", distro_series="centos71", architecture="amd64/generic", primary_rack=rack_controller) mac = node.get_boot_interface().mac_address observed_config = get_config(rack_controller.system_id, local_ip, remote_ip, mac=mac) self.assertEqual(osystem, observed_config["osystem"]) self.assertEqual(release, observed_config["release"])
def test_DELETE_delete_with_force(self): self.become_admin() vlan = factory.make_VLAN() subnet = factory.make_Subnet(vlan=vlan) region = factory.make_Node_with_Interface_on_Subnet( node_type=NODE_TYPE.REGION_CONTROLLER, subnet=subnet, vlan=vlan) ip = factory.make_StaticIPAddress( interface=region.interface_set.first()) factory.make_Pod(ip_address=ip) mock_async_delete = self.patch(Pod, "async_delete") response = self.client.delete( self.get_region_uri(region), QUERY_STRING=urlencode({"force": "true"}, doseq=True), ) self.assertEqual( http.client.NO_CONTENT, response.status_code, explain_unexpected_response(http.client.NO_CONTENT, response), ) self.assertThat(mock_async_delete, MockCallsMatch(call()))
def test_GET_query_with_macs_returns_matching_nodes(self): # The "list" operation takes optional "mac_address" parameters. Only # events for nodes with matching MAC addresses will be returned. nodes = [ factory.make_Node_with_Interface_on_Subnet() for _ in range(3) ] events = [factory.make_Event(node=node) for node in nodes] first_node = nodes[0] first_node_mac = first_node.get_boot_interface().mac_address first_event = events[0] # Pertains to the first node. response = self.client.get(reverse('events_handler'), { 'op': 'query', 'mac_address': [first_node_mac], 'level': 'DEBUG' }) parsed_result = json_load_bytes(response.content) self.assertItemsEqual( [first_event.id], extract_event_ids(parsed_result)) self.assertEqual(1, parsed_result['count'])
def test__marks_failed_if_save_raises(self): mock_pod_form = Mock() self.mock_PodForm.return_value = mock_pod_form mock_pod_form.errors = {} mock_pod_form.is_valid = Mock() mock_pod_form.is_valid.return_value = True mock_pod_form.save = Mock() mock_pod_form.save.side_effect = ValueError node = factory.make_Node_with_Interface_on_Subnet( status=NODE_STATUS.DEPLOYING, agent_name="maas-kvm-pod", install_kvm=True) factory.make_StaticIPAddress(interface=node.boot_interface) meta = NodeMetadata.objects.create( node=node, key="virsh_password", value="xyz123") _create_pod_for_deployment(node) meta = reload_object(meta) self.assertThat(meta, Is(None)) self.assertThat(node.status, Equals(NODE_STATUS.FAILED_DEPLOYMENT)) self.assertThat(node.error_description, DocTestMatches( POD_CREATION_ERROR))
def test__input_interface_defaults_boot_interface_during_commiss(self): node = factory.make_Node_with_Interface_on_Subnet( status=NODE_STATUS.COMMISSIONING) script = factory.make_Script( parameters={"interface": { "type": "interface" }}) form = ParametersForm(data={}, script=script, node=node) self.assertTrue(form.is_valid(), form.errors) self.assertEquals(1, len(form.cleaned_data["input"])) self.assertDictEqual( { "name": node.boot_interface.name, "mac_address": str(node.boot_interface.mac_address), "vendor": node.boot_interface.vendor, "product": node.boot_interface.product, "interface": node.boot_interface, }, form.cleaned_data["input"][0]["interface"]["value"], )
def test_dnsresource_address_overrides_domain(self): # DNSResource.address_ttl _does_, however, override Domain.ttl for # addresses that do not have nodes associated with them. global_ttl = random.randint(100, 199) Config.objects.set_config('default_dns_ttl', global_ttl) subnet = factory.make_Subnet(cidr="10.0.0.0/23") domain = factory.make_Domain(ttl=random.randint(200, 299)) node = factory.make_Node_with_Interface_on_Subnet( status=NODE_STATUS.READY, subnet=subnet, domain=domain, address_ttl=random.randint(300, 399)) boot_iface = node.get_boot_interface() [boot_ip] = boot_iface.claim_auto_ips() dnsrr = factory.make_DNSResource(domain=domain, address_ttl=random.randint(400, 499)) node_ips = {boot_ip.ip} dnsrr_ips = { ip.ip for ip in dnsrr.ip_addresses.all() if ip is not None } expected_forward = { node.hostname: HostnameIPMapping(node.system_id, node.address_ttl, node_ips, node.node_type), dnsrr.name: HostnameIPMapping(None, dnsrr.address_ttl, dnsrr_ips, None), } expected_reverse = { node.fqdn: HostnameIPMapping(node.system_id, node.address_ttl, node_ips, node.node_type), dnsrr.fqdn: HostnameIPMapping(None, dnsrr.address_ttl, dnsrr_ips, None) } zones = ZoneGenerator(domain, subnet, default_ttl=global_ttl, serial=random.randint(0, 65535)).as_list() self.assertEqual(expected_forward, zones[0]._mapping) self.assertEqual(expected_reverse, zones[1]._mapping)
def test_dnsresource_address_does_not_affect_addresses_when_node_set(self): # If a node has the same FQDN as a DNSResource, then we use whatever # address_ttl there is on the Node (whether None, or not) rather than # that on any DNSResource addresses with the same FQDN. global_ttl = random.randint(100, 199) Config.objects.set_config("default_dns_ttl", global_ttl) subnet = factory.make_Subnet(cidr="10.0.0.0/23") domain = factory.make_Domain(ttl=random.randint(200, 299)) node = factory.make_Node_with_Interface_on_Subnet( status=NODE_STATUS.READY, subnet=subnet, domain=domain, address_ttl=random.randint(300, 399), ) boot_iface = node.get_boot_interface() [boot_ip] = boot_iface.claim_auto_ips() dnsrr = factory.make_DNSResource( name=node.hostname, domain=domain, address_ttl=random.randint(400, 499), ) ips = {ip.ip for ip in dnsrr.ip_addresses.all() if ip is not None} ips.add(boot_ip.ip) expected_forward = { node.hostname: HostnameIPMapping( node.system_id, node.address_ttl, ips, node.node_type, dnsrr.id ) } expected_reverse = { node.fqdn: HostnameIPMapping( node.system_id, node.address_ttl, ips, node.node_type, dnsrr.id ) } zones = ZoneGenerator( domain, subnet, default_ttl=global_ttl, serial=random.randint(0, 65535), ).as_list() self.assertEqual(expected_forward, zones[0]._mapping) self.assertEqual(expected_reverse, zones[1]._mapping)
def test__renders_expected_output(self): node = factory.make_Node_with_Interface_on_Subnet() boot_interface = node.get_boot_interface() vlan = boot_interface.vlan mac_address = factory.make_mac_address() bridge_iface = factory.make_Interface( iftype=INTERFACE_TYPE.BRIDGE, node=node, vlan=vlan, parents=[boot_interface], mac_address=mac_address) bridge_iface.params = { "bridge_fd": 0, "bridge_stp": True, } bridge_iface.save() factory.make_StaticIPAddress( interface=bridge_iface, alloc_type=IPADDRESS_TYPE.STICKY, subnet=bridge_iface.vlan.subnet_set.first()) net_config = self.collect_interface_config(node, filter="physical") net_config += self.collect_interface_config(node, filter="bridge") net_config += self.collectDNSConfig(node) config = compose_curtin_network_config(node) self.assertNetworkConfig(net_config, config)
def test_domain_ttl_overrides_global(self): global_ttl = random.randint(100, 199) Config.objects.set_config('default_dns_ttl', global_ttl) subnet = factory.make_Subnet(cidr="10.0.0.0/23") domain = factory.make_Domain(ttl=random.randint(200, 299)) node = factory.make_Node_with_Interface_on_Subnet( status=NODE_STATUS.READY, subnet=subnet, domain=domain) boot_iface = node.get_boot_interface() [boot_ip] = boot_iface.claim_auto_ips() expected_forward = { node.hostname: HostnameIPMapping( node.system_id, domain.ttl, {boot_ip.ip}, node.node_type)} expected_reverse = { node.fqdn: HostnameIPMapping( node.system_id, domain.ttl, {boot_ip.ip}, node.node_type)} zones = ZoneGenerator( domain, subnet, default_ttl=global_ttl, serial=random.randint(0, 65535)).as_list() self.assertEqual(expected_forward, zones[0]._mapping) self.assertEqual(expected_reverse, zones[1]._mapping)
def test_does_nothing_if_not_machine(self): node = factory.make_Node_with_Interface_on_Subnet( node_type=factory.pick_choice( NODE_TYPE_CHOICES, but_not=[NODE_TYPE.MACHINE] ), status=random.choice(self.reserved_statuses), power_state=POWER_STATE.ON, ) for interface in node.interface_set.all(): interface.claim_auto_ips() # Hack to get around node transition model Node.objects.filter(id=node.id).update(status=self.status) node = reload_object(node) node.power_state = POWER_STATE.OFF node.save() for ip in StaticIPAddress.objects.filter( interface__node=node, alloc_type=IPADDRESS_TYPE.AUTO ): self.assertIsNotNone(ip.ip)
def test_store_result_yaml_can_set_interface_link_connected(self): node = factory.make_Node_with_Interface_on_Subnet() script_set = factory.make_ScriptSet(node=node) script = factory.make_Script( parameters={"interface": { "type": "interface" }}) script_result = factory.make_ScriptResult( status=SCRIPT_STATUS.RUNNING, script=script, script_set=script_set, interface=node.boot_interface, ) script_result.store_result(0, result=yaml.safe_dump({ "link_connected": False }).encode()) self.assertFalse(reload_object(node.boot_interface).link_connected)
def test__default_parameters(self): subnet = factory.make_Subnet() user = factory.make_User() node = factory.make_Node_with_Interface_on_Subnet( subnet=subnet, status=NODE_STATUS.READY) factory.make_StaticIPAddress( alloc_type=IPADDRESS_TYPE.USER_RESERVED, subnet=subnet, user=user) factory.make_StaticIPAddress( alloc_type=IPADDRESS_TYPE.STICKY, subnet=subnet, user=user, interface=node.get_boot_interface()) response = self.client.get( get_subnet_uri(subnet), { 'op': 'ip_addresses', }) self.assertEqual( http.client.OK, response.status_code, explain_unexpected_response(http.client.OK, response)) result = json.loads(response.content.decode(settings.DEFAULT_CHARSET)) expected_result = subnet.render_json_for_related_ips( with_username=True, with_summary=True) self.assertThat(result, Equals(expected_result))
def test__dhcp_configurations_rendered(self): node = factory.make_Node_with_Interface_on_Subnet( ip_version=self.ip_version) iface = node.interface_set.first() subnet = iface.vlan.subnet_set.first() factory.make_StaticIPAddress(ip=None, alloc_type=IPADDRESS_TYPE.DHCP, interface=iface, subnet=subnet) # Patch resolve_hostname() to return the appropriate network version # IP address for MAAS hostname. resolve_hostname = self.patch(maasserver.server_address, "resolve_hostname") if self.ip_version == 4: resolve_hostname.return_value = {IPAddress("127.0.0.1")} else: resolve_hostname.return_value = {IPAddress("::1")} config = compose_curtin_network_config(node) config_yaml = yaml.safe_load(config[0]) self.assertThat( config_yaml['network']['config'][0]['subnets'][0]['type'], Equals('dhcp' + str(IPNetwork(subnet.cidr).version)))
def test_expiry_removes_lease_keeps_discovered_subnet(self): subnet = factory.make_ipv4_Subnet_with_IPRanges( with_static_range=False, dhcp_on=True) node = factory.make_Node_with_Interface_on_Subnet(subnet=subnet) boot_interface = node.get_boot_interface() dynamic_range = subnet.get_dynamic_ranges()[0] ip = factory.pick_ip_in_IPRange(dynamic_range) kwargs = self.make_kwargs(action="expiry", mac=boot_interface.mac_address, ip=ip) update_lease(**kwargs) sip = StaticIPAddress.objects.filter( alloc_type=IPADDRESS_TYPE.DISCOVERED, ip=None, subnet=subnet, interface=boot_interface).first() self.assertIsNotNone( sip, "DISCOVERED IP address shold have been created without an " "IP address.") self.assertItemsEqual([boot_interface.id], sip.interface_set.values_list("id", flat=True))
def test_read_all_with_only_implicit_records(self): self.become_admin() domain = Domain.objects.get_default_domain() uri = get_dnsresources_uri() machine = factory.make_Node_with_Interface_on_Subnet( status=NODE_STATUS.DEPLOYED, domain=domain) factory.make_StaticIPAddress(interface=machine.boot_interface) response = self.client.get( uri, { 'all': 'true', } ) self.assertEqual( http.client.OK, response.status_code, response.content) expected_ids = [-1] result_ids = [ dnsresource["id"] for dnsresource in json.loads( response.content.decode(settings.DEFAULT_CHARSET)) ] self.assertItemsEqual(expected_ids, result_ids)
def test__returns_commissioning_os_when_erasing_disks(self): self.patch(boot_module, 'get_boot_filenames').return_value = ( None, None, None) commissioning_osystem = factory.make_name("os") Config.objects.set_config( "commissioning_osystem", commissioning_osystem) commissioning_series = factory.make_name("series") Config.objects.set_config( "commissioning_distro_series", commissioning_series) rack_controller = factory.make_RackController() local_ip = factory.make_ip_address() remote_ip = factory.make_ip_address() node = factory.make_Node_with_Interface_on_Subnet( status=NODE_STATUS.DISK_ERASING, osystem=factory.make_name("centos"), distro_series=factory.make_name("release"), primary_rack=rack_controller) mac = node.get_boot_interface().mac_address observed_config = get_config( rack_controller.system_id, local_ip, remote_ip, mac=mac) self.assertEqual(commissioning_osystem, observed_config['osystem']) self.assertEqual(commissioning_series, observed_config['release'])
def test__renders_expected_output(self): node = factory.make_Node_with_Interface_on_Subnet(interface_count=2) phys_ifaces = list(node.interface_set.all()) phys_vlan = node.interface_set.first().vlan bond_iface = factory.make_Interface(iftype=INTERFACE_TYPE.BOND, node=node, vlan=phys_vlan, parents=phys_ifaces) bond_iface.params = { "bond_mode": "balance-rr", } bond_iface.save() vlan_iface = factory.make_Interface(iftype=INTERFACE_TYPE.VLAN, node=node, parents=[bond_iface]) subnet = factory.make_Subnet(vlan=vlan_iface.vlan) factory.make_StaticIPAddress(interface=vlan_iface, subnet=subnet) net_config = self.collect_interface_config(node, filter="physical") net_config += self.collect_interface_config(node, filter="bond") net_config += self.collect_interface_config(node, filter="vlan") net_config += self.collect_dns_config(node) config = compose_curtin_network_config(node) self.assertNetworkConfig(net_config, config)
def test_supernet_inherits_rfc2317_net(self): domain = Domain.objects.get_default_domain() subnet1 = factory.make_Subnet(host_bits=2) net = IPNetwork(subnet1.cidr) if net.version == 6: prefixlen = random.randint(121, 124) else: prefixlen = random.randint(22, 24) parent = IPNetwork("%s/%d" % (net.network, prefixlen)) parent = IPNetwork("%s/%d" % (parent.network, prefixlen)) subnet2 = factory.make_Subnet(cidr=parent) node = factory.make_Node_with_Interface_on_Subnet( subnet=subnet1, vlan=subnet1.vlan, fabric=subnet1.vlan.fabric, domain=domain, ) boot_iface = node.boot_interface factory.make_StaticIPAddress(interface=boot_iface, subnet=subnet1) default_ttl = random.randint(10, 300) Config.objects.set_config("default_dns_ttl", default_ttl) zones = ZoneGenerator( domain, [subnet1, subnet2], default_ttl=default_ttl, serial=random.randint(0, 65535), ).as_list() self.assertThat( zones, MatchesSetwise( forward_zone(domain.name), reverse_zone(domain.name, subnet1.cidr), reverse_zone(domain.name, subnet2.cidr), ), ) self.assertEqual(set(), zones[1]._rfc2317_ranges) self.assertEqual({net}, zones[2]._rfc2317_ranges)
def test_list_uses_consistent_queries(self): user = factory.make_User() handler = SubnetHandler(user, {}, None) subnet = factory.make_Subnet() factory.make_Interface(iftype=INTERFACE_TYPE.UNKNOWN, subnet=subnet) self.assertIsNone(handler.cache.get("staticroutes")) queries_one, _ = count_queries(handler.list, {}) for _ in range(10): subnet = factory.make_Subnet() for x in range(5): node = factory.make_Node_with_Interface_on_Subnet( subnet=subnet, status=NODE_STATUS.READY) iface = node.interface_set.first() factory.make_StaticIPAddress(alloc_type=IPADDRESS_TYPE.STICKY, subnet=subnet, interface=iface) self.assertIsNotNone(handler.cache["staticroutes"]) del handler.cache["staticroutes"] queries_all, _ = count_queries(handler.list, {}) self.assertEquals(queries_one, queries_all) self.assertIsNotNone(handler.cache["staticroutes"]) self.assertEquals(4, queries_one)
def test_expiry_does_not_keep_adding_null_ip_records_repeated_calls(self): subnet = factory.make_ipv4_Subnet_with_IPRanges( with_static_range=False, dhcp_on=True) # Create a bunch of null IPs to show the effects of bug 1817056. null_ips = [ StaticIPAddress( created=timezone.now(), updated=timezone.now(), ip=None, alloc_type=IPADDRESS_TYPE.DISCOVERED, subnet=subnet, ) for _ in range(10) ] StaticIPAddress.objects.bulk_create(null_ips) node = factory.make_Node_with_Interface_on_Subnet(subnet=subnet) boot_interface = node.get_boot_interface() boot_interface.ip_addresses.add(*null_ips) dynamic_range = subnet.get_dynamic_ranges()[0] ip = factory.pick_ip_in_IPRange(dynamic_range) kwargs = self.make_kwargs(action="expiry", mac=boot_interface.mac_address, ip=ip) null_ip_query = StaticIPAddress.objects.filter( alloc_type=IPADDRESS_TYPE.DISCOVERED, ip=None, subnet=subnet) update_lease(**kwargs) # XXX: We shouldn't need to record the previous count and # instead expect the count to be 1. This will be addressed # in bug 1817305. previous_null_ip_count = null_ip_query.count() previous_interface_ip_count = boot_interface.ip_addresses.count() update_lease(**kwargs) self.assertEqual(previous_null_ip_count, null_ip_query.count()) self.assertEqual(previous_interface_ip_count, boot_interface.ip_addresses.count())
def test_creates_lease_for_bond_interface(self): subnet = factory.make_ipv4_Subnet_with_IPRanges( with_static_range=False, dhcp_on=True) node = factory.make_Node_with_Interface_on_Subnet(subnet=subnet) boot_interface = node.get_boot_interface() dynamic_range = subnet.get_dynamic_ranges()[0] ip = factory.pick_ip_in_IPRange(dynamic_range) bond_interface = factory.make_Interface( INTERFACE_TYPE.BOND, mac_address=boot_interface.mac_address, parents=[boot_interface], ) kwargs = self.make_kwargs(action="commit", mac=bond_interface.mac_address, ip=ip) update_lease(**kwargs) sip = StaticIPAddress.objects.filter( alloc_type=IPADDRESS_TYPE.DISCOVERED, ip=ip).first() self.assertThat( sip, MatchesStructure.byEquality( alloc_type=IPADDRESS_TYPE.DISCOVERED, ip=ip, subnet=subnet, lease_time=kwargs["lease_time"], created=datetime.fromtimestamp(kwargs["timestamp"]), updated=datetime.fromtimestamp(kwargs["timestamp"]), ), ) self.assertItemsEqual( [boot_interface.id, bond_interface.id], sip.interface_set.values_list("id", flat=True), )
def test__running_or_installing_emits_event_with_interface_parameter(self): node = factory.make_Node_with_Interface_on_Subnet() script = factory.make_Script(script_type=SCRIPT_TYPE.TESTING) script_set = factory.make_ScriptSet( result_type=RESULT_TYPE.TESTING, node=node) script_result = factory.make_ScriptResult( status=SCRIPT_STATUS.PENDING, script=script, script_set=script_set, interface=node.boot_interface) script_result.status = random.choice(list(SCRIPT_STATUS_RUNNING)) script_result.save() latest_event = Event.objects.last() self.assertEqual( ( EVENT_TYPES.RUNNING_TEST, EVENT_DETAILS[EVENT_TYPES.RUNNING_TEST].description, '%s on %s' % (script_result.name, node.boot_interface.name) ), ( latest_event.type.name, latest_event.type.description, latest_event.description, ))
def create_node_with_interface(self, params=None): if params is None: params = {} return factory.make_Node_with_Interface_on_Subnet(**params)
def test_get_with_pod_host(self): admin = factory.make_admin() handler = PodHandler(admin, {}, None) vlan = factory.make_VLAN(dhcp_on=True) subnet = factory.make_Subnet(vlan=vlan) node = factory.make_Node_with_Interface_on_Subnet(subnet=subnet) ip = factory.make_StaticIPAddress(interface=node.boot_interface, subnet=subnet) numa_node0 = node.default_numanode numa_node0.cores = [0, 3] numa_node0.memory = 4096 numa_node0.save() factory.make_NUMANode(node=node, cores=[1, 4], memory=1024) factory.make_NUMANode(node=node, cores=[2, 5], memory=2048) pod = self.make_pod_with_hints(pod_type="lxd", host=node, ip_address=ip) factory.make_VirtualMachine( memory=1024, pinned_cores=[0], hugepages_backed=False, bmc=pod, machine=factory.make_Node(system_id="vm0"), ) factory.make_VirtualMachine( memory=1024, pinned_cores=[2, 5], hugepages_backed=False, bmc=pod, machine=factory.make_Node(system_id="vm1"), ) expected_data = handler.full_dehydrate(pod) result = handler.get({"id": pod.id}) self.assertItemsEqual(expected_data.keys(), result.keys()) for key in expected_data: self.assertEqual(expected_data[key], result[key], key) self.assertThat(result, Equals(expected_data)) self.assertThat(result["host"], Equals(node.system_id)) self.assertThat(result["attached_vlans"], Equals([subnet.vlan_id])) self.assertThat(result["boot_vlans"], Equals([subnet.vlan_id])) self.assertEqual( result["numa_pinning"], [ { "cores": { "allocated": [0], "free": [3] }, "interfaces": [ { "id": 100, "name": "eth4", "virtual_functions": { "allocated": 4, "free": 12 }, }, { "id": 200, "name": "eth5", "virtual_functions": { "allocated": 14, "free": 2 }, }, ], "memory": { "general": { "allocated": 1024 * MB, "free": 3072 * MB }, "hugepages": [], }, "node_id": 0, "vms": [ { "pinned_cores": [0], "system_id": "vm0", "networks": [ { "guest_nic_id": 101, "host_nic_id": 100 }, { "guest_nic_id": 102, "host_nic_id": 100 }, ], }, ], }, { "cores": { "allocated": [], "free": [1, 4] }, "interfaces": [ { "id": 100, "name": "eth4", "virtual_functions": { "allocated": 4, "free": 12 }, }, { "id": 200, "name": "eth5", "virtual_functions": { "allocated": 14, "free": 2 }, }, ], "memory": { "general": { "allocated": 0, "free": 1024 * MB }, "hugepages": [], }, "node_id": 1, "vms": [], }, { "cores": { "allocated": [2, 5], "free": [] }, "interfaces": [ { "id": 100, "name": "eth4", "virtual_functions": { "allocated": 4, "free": 12 }, }, { "id": 200, "name": "eth5", "virtual_functions": { "allocated": 14, "free": 2 }, }, ], "memory": { "general": { "allocated": 1024 * MB, "free": 1024 * MB }, "hugepages": [], }, "node_id": 2, "vms": [ { "pinned_cores": [2, 5], "system_id": "vm1", "networks": [ { "guest_nic_id": 101, "host_nic_id": 100 }, { "guest_nic_id": 102, "host_nic_id": 100 }, ], }, ], }, ], )
def test_returns_interface_ips_but_no_nulls(self): default_domain = Domain.objects.get_default_domain().name domain = factory.make_Domain(name="henry") subnet = factory.make_Subnet(cidr=str(IPNetwork("10/29").cidr)) subnet.gateway_ip = str(IPAddress(IPNetwork(subnet.cidr).ip + 1)) subnet.save() # Create a node with two interfaces, with NULL ips node = factory.make_Node_with_Interface_on_Subnet( subnet=subnet, vlan=subnet.vlan, fabric=subnet.vlan.fabric, domain=domain, interface_count=3, ) dnsdata = factory.make_DNSData(domain=domain) boot_iface = node.boot_interface interfaces = list(node.interface_set.all().exclude(id=boot_iface.id)) # Now go add IP addresses to the boot interface, and one other boot_ip = factory.make_StaticIPAddress( interface=boot_iface, subnet=subnet ) sip = factory.make_StaticIPAddress( interface=interfaces[0], subnet=subnet ) default_ttl = random.randint(10, 300) Config.objects.set_config("default_dns_ttl", default_ttl) zones = ZoneGenerator( domain, subnet, default_ttl=default_ttl, serial=random.randint(0, 65535), ).as_list() self.assertThat( zones, MatchesSetwise( forward_zone("henry"), reverse_zone(default_domain, "10/29"), reverse_zone(default_domain, "10/24"), ), ) self.assertEqual( { node.hostname: HostnameIPMapping( node.system_id, default_ttl, {"%s" % boot_ip.ip}, node.node_type, ), "%s.%s" % (interfaces[0].name, node.hostname): HostnameIPMapping( node.system_id, default_ttl, {"%s" % sip.ip}, node.node_type, ), }, zones[0]._mapping, ) self.assertEqual( { dnsdata.dnsresource.name: HostnameRRsetMapping( None, {(default_ttl, dnsdata.rrtype, dnsdata.rrdata)} ) }.items(), zones[0]._other_mapping.items(), ) self.assertEqual( { node.fqdn: HostnameIPMapping( node.system_id, default_ttl, {"%s" % boot_ip.ip}, node.node_type, ), "%s.%s" % (interfaces[0].name, node.fqdn): HostnameIPMapping( node.system_id, default_ttl, {"%s" % sip.ip}, node.node_type, ), }, zones[1]._mapping, ) self.assertEqual({}, zones[2]._mapping)
def make_node(self, arch_name=None, **kwargs): architecture = make_usable_architecture(self, arch_name=arch_name) return factory.make_Node_with_Interface_on_Subnet( architecture="%s/generic" % architecture.split('/')[0], **kwargs)
def test_get_with_pod_host(self): admin = factory.make_admin() handler = PodHandler(admin, {}, None) vlan = factory.make_VLAN(dhcp_on=True) subnet = factory.make_Subnet(vlan=vlan) node = factory.make_Node_with_Interface_on_Subnet(subnet=subnet) ip = factory.make_StaticIPAddress(interface=node.boot_interface, subnet=subnet) numa_node0 = node.default_numanode numa_node0.cores = [0, 3] numa_node0.memory = 4096 numa_node0.save() factory.make_NUMANode(node=node, cores=[1, 4], memory=1024) factory.make_NUMANode(node=node, cores=[2, 5], memory=2048) project = factory.make_string() pod = self.make_pod_with_hints( pod_type="lxd", parameters={"project": project}, host=node, ip_address=ip, ) vm0 = factory.make_VirtualMachine( project=project, memory=1024, pinned_cores=[0], hugepages_backed=False, bmc=pod, machine=factory.make_Node(system_id="vm0"), ) vm1 = factory.make_VirtualMachine( project=project, memory=1024, pinned_cores=[2, 5], hugepages_backed=False, bmc=pod, machine=factory.make_Node(system_id="vm1"), ) expected_numa_details = [ { "cores": { "allocated": [0], "free": [3] }, "interfaces": [node.boot_interface.id], "memory": { "general": { "allocated": 1024 * MB, "free": 3072 * MB }, "hugepages": [], }, "node_id": 0, "vms": [vm0.id], }, { "cores": { "allocated": [], "free": [1, 4] }, "interfaces": [], "memory": { "general": { "allocated": 0, "free": 1024 * MB }, "hugepages": [], }, "node_id": 1, "vms": [], }, { "cores": { "allocated": [2, 5], "free": [] }, "interfaces": [], "memory": { "general": { "allocated": 1024 * MB, "free": 1024 * MB }, "hugepages": [], }, "node_id": 2, "vms": [vm1.id], }, ] result = handler.get({"id": pod.id}) self.assertThat(result["host"], Equals(node.system_id)) self.assertThat(result["attached_vlans"], Equals([subnet.vlan_id])) self.assertThat(result["boot_vlans"], Equals([subnet.vlan_id])) resources = result["resources"] self.assertEqual( resources["cores"], { "allocated_other": 0, "allocated_tracked": 3, "free": 3 }, ) self.assertEqual( resources["interfaces"], [{ "id": node.boot_interface.id, "name": node.boot_interface.name, "numa_index": 0, "virtual_functions": { "allocated_other": 0, "allocated_tracked": 0, "free": 0, }, }], ) self.assertEqual( resources["memory"], { "general": { "allocated_other": 0, "allocated_tracked": 2147483648, "free": 5368709120, }, "hugepages": { "allocated_other": 0, "allocated_tracked": 0, "free": 0, }, }, ) self.assertEqual(resources["numa"], expected_numa_details) self.assertEqual(resources["vm_count"], {"other": 0, "tracked": 2}) self.assertCountEqual( resources["vms"], [ { "id": vm0.id, "system_id": "vm0", "memory": 1024 * MB, "hugepages_backed": False, "pinned_cores": [0], "unpinned_cores": 0, }, { "id": vm1.id, "system_id": "vm1", "memory": 1024 * MB, "hugepages_backed": False, "pinned_cores": [2, 5], "unpinned_cores": 0, }, ], )
def test_POST_power_on_checks_permission(self): machine = factory.make_Node_with_Interface_on_Subnet( owner=factory.make_User()) response = self.client.post( self.get_node_uri(machine), {'op': 'power_on'}) self.assertEqual(http.client.FORBIDDEN, response.status_code)