Feature/hostname resolution scaffolding win#4992
Conversation
Let the host resolve "<instance>.multipass" to a guest's current IP, without changing the global ICSDomain or running a resolver process. The guest advertises a dotted DHCP hostname so the ICS proxy stores it as "<instance>.multipass.mshome.net". The host appends "mshome.net" to the typed name and a narrow NRPT rule sends ".multipass.mshome.net" queries to the gateway proxy. Add an NrptRule RAII type that writes the rule to the NRPT registry and removes it on destruction, wire it into the build, and add an integration test that boots Alpine and checks resolution end to end.
There was a problem hiding this comment.
Pull request overview
Adds Windows/Hyper-V DNS resolution scaffolding by introducing explicit HCN DNS configuration support (creation + query parsing) and an NRPT rule RAII helper, along with cloud-init fixtures and end-to-end/component integration tests that exercise hostname/FQDN resolution paths through ICS.
Changes:
- Add
HcnDnsmodel + formatting, allow optional"Dns"block in HCN network creation JSON, and parse flattened DNS fields on HCN query (networks + endpoints). - Add
NrptRuleRAII helper for writing/removing local NRPT rules via the registry (and link required Windows libs). - Add new cloud-init fixtures and expand Hyper-V “big bang” integration tests to validate DNS suffix + NRPT-based name resolution behavior.
Reviewed changes
Copilot reviewed 24 out of 25 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/unit/test_data/cloud-init-fqdn-multipass/README.md | Documents runtime-generated NoCloud seed approach for dotted DHCP hostname tests. |
| tests/unit/test_data/cloud-init-fqdn-multipass/make_seed_iso.py | Generates NoCloud seed ISO at runtime for unique dotted DHCP hostname (pycdlib-based). |
| tests/unit/test_data/cloud-init-dhcp-hostname/user-data | Cloud-init config to re-run udhcpc with option-12 hostname advertising. |
| tests/unit/test_data/cloud-init-dhcp-hostname/README.md | Documents committed ISO fixture purpose and regeneration steps. |
| tests/unit/test_data/cloud-init-dhcp-hostname/meta-data | Sets guest local-hostname for DHCP-hostname integration test. |
| tests/unit/hyperv_api/test_ut_hyperv_hcn_dns.cpp | Unit tests for HcnDns JSON formatting (narrow/wide/empty lists). |
| tests/unit/hyperv_api/test_ut_hyperv_hcn_api.cpp | Adds unit test verifying "Dns" object is emitted in created network config JSON. |
| tests/unit/hyperv_api/test_it_hyperv_hcn_api.cpp | Integration coverage for network/endpoint DNS query results and inheritance. |
| tests/unit/hyperv_api/test_bb_cit_hyperv.cpp | Adds end-to-end tests for ICS/NRPT/hostname resolution and runtime ISO generation. |
| tests/unit/hyperv_api/mock_hyperv_hcn_api.h | Extends mock API with HcnQueryEndpointProperties. |
| tests/unit/hyperv_api/CMakeLists.txt | Adds new test_ut_hyperv_hcn_dns.cpp to Windows unit tests build. |
| src/platform/backends/hyperv_api/hcn/hyperv_hcn_wrapper.h | Adds endpoint query API and includes endpoint info type. |
| src/platform/backends/hyperv_api/hcn/hyperv_hcn_wrapper.cpp | Implements endpoint query + flattened DNS parsing; adds DNS parsing to network query. |
| src/platform/backends/hyperv_api/hcn/hyperv_hcn_network_info.h | Extends network info with optional DNS settings. |
| src/platform/backends/hyperv_api/hcn/hyperv_hcn_endpoint_info.h | New endpoint info struct including inherited DNS settings. |
| src/platform/backends/hyperv_api/hcn/hyperv_hcn_dns.h | New HcnDns type + fmt formatter declaration. |
| src/platform/backends/hyperv_api/hcn/hyperv_hcn_dns.cpp | Implements fmt formatting for HcnDns. |
| src/platform/backends/hyperv_api/hcn/hyperv_hcn_create_network_params.h | Adds optional dns field to network creation parameters. |
| src/platform/backends/hyperv_api/hcn/hyperv_hcn_create_network_params.cpp | Emits "Dns" fragment only when params.dns is set. |
| src/platform/backends/hyperv_api/hcn/hyperv_hcn_api.h | Adds HcnQueryEndpointProperties API surface. |
| src/platform/backends/hyperv_api/hcn/hyperv_hcn_api.cpp | Wires HcnQueryEndpointProperties to the underlying Win32 API call. |
| src/platform/backends/hyperv_api/dns/nrpt_rule.h | New RAII type for local NRPT registry rules. |
| src/platform/backends/hyperv_api/dns/nrpt_rule.cpp | Implements NRPT registry write/remove logic + GUID generation. |
| src/platform/backends/hyperv_api/CMakeLists.txt | Adds new source files and links advapi32/rpcrt4. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| #include <algorithm> | ||
| #include <chrono> | ||
| #include <cstdio> | ||
| #include <filesystem> | ||
| #include <fstream> |
| std::ofstream out(output, std::ios::binary); | ||
| for (const auto& part : parts) | ||
| { | ||
| std::ifstream in(part, std::ios::binary); | ||
| out << in.rdbuf(); | ||
| } |
| (void)run_powershell(fmt::format( | ||
| "Set-DnsClientGlobalSetting -SuffixSearchList @('{}'); " | ||
| "Set-ItemProperty -Path '{}' -Name AppendToMultiLabelName -Value 1 -Type DWord", | ||
| append_suffix, dnscache_key)); |
| else | ||
| (void)run_powershell(fmt::format( | ||
| "Set-ItemProperty -Path '{}' -Name AppendToMultiLabelName -Value {} -Type DWord", | ||
| suffix_key, saved_amln)); |
| return run_powershell(fmt::format( | ||
| "(Resolve-DnsName -Name {} -Type A -QuickTimeout " | ||
| "-ErrorAction SilentlyContinue | Where-Object {{ $_.Type -eq 'A' }}).IPAddress " | ||
| "-join ','", | ||
| name)); |
| const auto script = | ||
| fmt::format("{}/cloud-init-fqdn-multipass/make_seed_iso.py", test_data_path); | ||
| const std::filesystem::path& iso_ref = cloud_init_iso_path; | ||
| const auto build_out = run_powershell( | ||
| fmt::format("python '{}' --hostname '{}' --output '{}' 2>&1", | ||
| script, | ||
| guest_hostname, | ||
| iso_ref.string())); | ||
| ASSERT_TRUE(std::filesystem::exists(iso_ref)) << "seed ISO build failed: " << build_out; | ||
| } |
| if (suffix) | ||
| dns.search = multipass::utils::split(suffix->as_string().c_str(), ","); | ||
| if (servers) | ||
| dns.server_list = multipass::utils::split(servers->as_string().c_str(), ","); | ||
| return dns; |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4992 +/- ##
==========================================
- Coverage 87.77% 87.60% -0.16%
==========================================
Files 273 274 +1
Lines 14685 14649 -36
==========================================
- Hits 12888 12832 -56
- Misses 1797 1817 +20 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
TBD