Skip to content

Commit 081e992

Browse files
authored
xapi/nm: Send non-empty dns to networkd when using IPv6 autoconf (#6664)
Because Autoconf is not DHCP, networkd uses the dns value to write to resolv.conf. This is done on ocaml/networkd/bin/network_server.ml line 745 This allows to have non-empty resolv.conf when using IPv6 autoconf. xapi-idl/network: Remove code duplication for DNS persistence decisions: Previously both xapi and networkd had to inspect the IP configuration to decide whether the DNS values should be persistend into /etc/resolv.conf. This actually lead to a mismatch in them. Instead use an option value for DNS that simply means that if there's a value, it must be persisted. Now xapi decides the instances where these values are written. Treat a couple of empty lists as a lack of value to avoid writing empty resolv.conf files. This can happen when updating a host from previous versions, which use empty lists when using DHCP. Tested manually by installing a version with this change and restarting the toolstack. The file is kept intact, unlike the previous version of the change that did not take into account the update behaviour. This is PR fixed version of #6586
2 parents 0010c74 + 4d12701 commit 081e992

File tree

5 files changed

+46
-42
lines changed

5 files changed

+46
-42
lines changed

ocaml/networkd/bin/network_server.ml

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,8 @@ module Interface = struct
554554
let set_dns _ dbg ~name ~nameservers ~domains =
555555
Debug.with_thread_associated dbg
556556
(fun () ->
557-
update_config name {(get_config name) with dns= (nameservers, domains)} ;
557+
update_config name
558+
{(get_config name) with dns= Some (nameservers, domains)} ;
558559
debug "Configuring DNS for %s: nameservers: [%s]; domains: [%s]" name
559560
(String.concat ", " (List.map Unix.string_of_inet_addr nameservers))
560561
(String.concat ", " domains) ;
@@ -727,7 +728,7 @@ module Interface = struct
727728
; ipv6_conf
728729
; ipv6_gateway
729730
; ipv4_routes
730-
; dns= nameservers, domains
731+
; dns
731732
; mtu
732733
; ethtool_settings
733734
; ethtool_offload
@@ -736,16 +737,13 @@ module Interface = struct
736737
) ) ->
737738
update_config name c ;
738739
exec (fun () ->
739-
(* We only apply the DNS settings when not in a DHCP mode
740-
to avoid conflicts. The `dns` field
741-
should really be an option type so that we don't have to
742-
derive the intention of the caller by looking at other
743-
fields. *)
744-
match (ipv4_conf, ipv6_conf) with
745-
| Static4 _, _ | _, Static6 _ | _, Autoconf6 ->
746-
set_dns () dbg ~name ~nameservers ~domains
747-
| _ ->
740+
(* Old configs used empty dns lists to mean none, keep that
741+
behaviour instead of writing an empty resolv.conf *)
742+
match dns with
743+
| None | Some ([], []) ->
748744
()
745+
| Some (nameservers, domains) ->
746+
set_dns () dbg ~name ~nameservers ~domains
749747
) ;
750748
exec (fun () -> set_ipv4_conf dbg name ipv4_conf) ;
751749
exec (fun () ->

ocaml/networkd/bin_db/networkd_db.ml

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,20 +76,25 @@ let _ =
7676
[("gateway", Unix.string_of_inet_addr addr)]
7777
in
7878
let dns =
79-
let dns' =
80-
List.map Unix.string_of_inet_addr (fst interface_config.dns)
81-
in
82-
if dns' = [] then
83-
[]
84-
else
85-
[("dns", String.concat "," dns')]
79+
interface_config.dns
80+
|> Option.map fst
81+
|> Option.map (List.map Unix.string_of_inet_addr)
82+
|> Option.fold ~none:[] ~some:(function
83+
| [] ->
84+
[]
85+
| dns' ->
86+
[("dns", String.concat "," dns')]
87+
)
8688
in
8789
let domains =
88-
let domains' = snd interface_config.dns in
89-
if domains' = [] then
90-
[]
91-
else
92-
[("domain", String.concat "," domains')]
90+
interface_config.dns
91+
|> Option.map snd
92+
|> Option.fold ~none:[] ~some:(function
93+
| [] ->
94+
[]
95+
| domains' ->
96+
[("domain", String.concat "," domains')]
97+
)
9398
in
9499
mode @ addrs @ gateway @ dns @ domains
95100
| None4 ->

ocaml/networkd/lib/network_config.ml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ let bridge_naming_convention (device : string) =
3737
let get_list_from ~sep ~key args =
3838
List.assoc_opt key args
3939
|> Option.map (fun v -> Astring.String.cuts ~empty:false ~sep v)
40-
|> Option.value ~default:[]
4140

4241
let parse_ipv4_config args = function
4342
| Some "static" ->
@@ -73,11 +72,13 @@ let parse_ipv6_config args = function
7372
(None6, None)
7473

7574
let parse_dns_config args =
76-
let nameservers =
77-
get_list_from ~sep:"," ~key:"DNS" args |> List.map Unix.inet_addr_of_string
75+
let ( let* ) = Option.bind in
76+
let* nameservers =
77+
get_list_from ~sep:"," ~key:"DNS" args
78+
|> Option.map (List.map Unix.inet_addr_of_string)
7879
in
79-
let domains = get_list_from ~sep:" " ~key:"DOMAIN" args in
80-
(nameservers, domains)
80+
let* domains = get_list_from ~sep:" " ~key:"DOMAIN" args in
81+
Some (nameservers, domains)
8182

8283
let read_management_conf () =
8384
try
@@ -103,15 +104,15 @@ let read_management_conf () =
103104
let device =
104105
(* Take 1st member of bond *)
105106
match (bond_mode, bond_members) with
106-
| None, _ | _, [] -> (
107+
| None, _ | _, (None | Some []) -> (
107108
match List.assoc_opt "LABEL" args with
108109
| Some x ->
109110
x
110111
| None ->
111112
error "%s: missing LABEL in %s" __FUNCTION__ management_conf ;
112113
raise Read_error
113114
)
114-
| _, hd :: _ ->
115+
| _, Some (hd :: _) ->
115116
hd
116117
in
117118
Inventory.reread_inventory () ;

ocaml/xapi-idl/network/network_interface.ml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,10 @@ type interface_config_t = {
158158
; ipv6_conf: ipv6 [@default None6]
159159
; ipv6_gateway: Unix.inet_addr option [@default None]
160160
; ipv4_routes: ipv4_route_t list [@default []]
161-
; dns: Unix.inet_addr list * string list [@default [], []]
161+
; dns: (Unix.inet_addr list * string list) option [@default None]
162+
(** the list
163+
of nameservers and domains to persist in /etc/resolv.conf. Must be None when
164+
using a DHCP mode *)
162165
; mtu: int [@default 1500]
163166
; ethtool_settings: (string * string) list [@default []]
164167
; ethtool_offload: (string * string) list [@default [("lro", "off")]]
@@ -200,7 +203,7 @@ let default_interface =
200203
; ipv6_conf= None6
201204
; ipv6_gateway= None
202205
; ipv4_routes= []
203-
; dns= ([], [])
206+
; dns= None
204207
; mtu= 1500
205208
; ethtool_settings= []
206209
; ethtool_offload= [("lro", "off")]

ocaml/xapi/nm.ml

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -634,28 +634,25 @@ let bring_pif_up ~__context ?(management_interface = false) (pif : API.ref_PIF)
634634
rc.API.pIF_ip_configuration_mode = `Static
635635
| `IPv6 ->
636636
rc.API.pIF_ipv6_configuration_mode = `Static
637+
|| rc.API.pIF_ipv6_configuration_mode = `Autoconf
637638
in
638639
let dns =
639640
match (static, rc.API.pIF_DNS) with
640641
| false, _ | true, "" ->
641-
([], [])
642+
None
642643
| true, pif_dns ->
643644
let nameservers =
644645
List.map Unix.inet_addr_of_string
645-
(String.split ',' pif_dns)
646+
(String.split_on_char ',' pif_dns)
646647
in
647648
let domains =
648649
match List.assoc_opt "domain" rc.API.pIF_other_config with
649-
| None ->
650+
| None | Some "" ->
650651
[]
651-
| Some domains -> (
652-
try String.split ',' domains
653-
with _ ->
654-
warn "Invalid DNS search domains: %s" domains ;
655-
[]
656-
)
652+
| Some domains ->
653+
String.split_on_char ',' domains
657654
in
658-
(nameservers, domains)
655+
Some (nameservers, domains)
659656
in
660657
let mtu = determine_mtu rc net_rc in
661658
let ethtool_settings, ethtool_offload =

0 commit comments

Comments
 (0)