Skip to content

Commit b645ba4

Browse files
authored
Miscellaneous IPv6 fixes and cleanup (#6421)
With this PR, `xapi` and `xcp-networkd` now properly handle emergency network resets on an IPv6-only host (when it's an individual host as well as when it's in a pool as a supporter and as a coordinator) Tested manually, see also the required `xsconsole` PR: xapi-project/xsconsole#55.
2 parents c5efca2 + 5f84b06 commit b645ba4

File tree

3 files changed

+77
-61
lines changed

3 files changed

+77
-61
lines changed

ocaml/networkd/lib/network_config.ml

Lines changed: 73 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,51 @@ let bridge_naming_convention (device : string) =
3434
else
3535
"br" ^ device
3636

37+
let get_list_from ~sep ~key args =
38+
List.assoc_opt key args
39+
|> Option.map (fun v -> Astring.String.cuts ~empty:false ~sep v)
40+
|> Option.value ~default:[]
41+
42+
let parse_ipv4_config args = function
43+
| Some "static" ->
44+
let ip = List.assoc "IP" args |> Unix.inet_addr_of_string in
45+
let prefixlen = List.assoc "NETMASK" args |> netmask_to_prefixlen in
46+
let gateway =
47+
Option.map Unix.inet_addr_of_string (List.assoc_opt "GATEWAY" args)
48+
in
49+
(Static4 [(ip, prefixlen)], gateway)
50+
| Some "dhcp" ->
51+
(DHCP4, None)
52+
| _ ->
53+
(None4, None)
54+
55+
let parse_ipv6_config args = function
56+
| Some "static" ->
57+
let ipv6_arg = List.assoc "IPv6" args in
58+
let ip, prefixlen =
59+
Scanf.sscanf ipv6_arg "%s@/%d" (fun ip prefixlen ->
60+
let ip = ip |> Unix.inet_addr_of_string in
61+
(ip, prefixlen)
62+
)
63+
in
64+
let gateway =
65+
Option.map Unix.inet_addr_of_string (List.assoc_opt "IPv6_GATEWAY" args)
66+
in
67+
(Static6 [(ip, prefixlen)], gateway)
68+
| Some "dhcp" ->
69+
(DHCP6, None)
70+
| Some "autoconf" ->
71+
(Autoconf6, None)
72+
| _ ->
73+
(None6, None)
74+
75+
let parse_dns_config args =
76+
let nameservers =
77+
get_list_from ~sep:"," ~key:"DNS" args |> List.map Unix.inet_addr_of_string
78+
in
79+
let domains = get_list_from ~sep:" " ~key:"DOMAIN" args in
80+
(nameservers, domains)
81+
3782
let read_management_conf () =
3883
try
3984
let management_conf =
@@ -42,35 +87,23 @@ let read_management_conf () =
4287
in
4388
let args =
4489
Astring.String.cuts ~empty:false ~sep:"\n" (String.trim management_conf)
45-
in
46-
let args =
47-
List.map
48-
(fun s ->
49-
match Astring.String.cuts ~sep:"=" s with
50-
| [k; v] ->
51-
(k, Astring.String.trim ~drop:(( = ) '\'') v)
52-
| _ ->
53-
("", "")
54-
)
55-
args
90+
|> List.filter_map (fun s ->
91+
match Astring.String.cut ~sep:"=" s with
92+
| Some (_, "") | None ->
93+
None
94+
| Some (k, v) ->
95+
Some (k, Astring.String.trim ~drop:(( = ) '\'') v)
96+
)
5697
in
5798
debug "Firstboot file management.conf has: %s"
5899
(String.concat "; " (List.map (fun (k, v) -> k ^ "=" ^ v) args)) ;
59100
let vlan = List.assoc_opt "VLAN" args in
60-
let bond_mode =
61-
Option.value ~default:"" (List.assoc_opt "BOND_MODE" args)
62-
in
63-
let bond_members =
64-
match List.assoc_opt "BOND_MEMBERS" args with
65-
| None ->
66-
[]
67-
| Some x ->
68-
String.split_on_char ',' x
69-
in
101+
let bond_mode = List.assoc_opt "BOND_MODE" args in
102+
let bond_members = get_list_from ~sep:"," ~key:"BOND_MEMBERS" args in
70103
let device =
71104
(* Take 1st member of bond *)
72105
match (bond_mode, bond_members) with
73-
| "", _ | _, [] -> (
106+
| None, _ | _, [] -> (
74107
match List.assoc_opt "LABEL" args with
75108
| Some x ->
76109
x
@@ -105,45 +138,28 @@ let read_management_conf () =
105138
bridge
106139
in
107140
let mac = Network_utils.Ip.get_mac device in
108-
let ipv4_conf, ipv4_gateway, dns =
109-
match List.assoc "MODE" args with
110-
| "static" ->
111-
let ip = List.assoc "IP" args |> Unix.inet_addr_of_string in
112-
let prefixlen = List.assoc "NETMASK" args |> netmask_to_prefixlen in
113-
let gateway =
114-
if List.mem_assoc "GATEWAY" args then
115-
Some (List.assoc "GATEWAY" args |> Unix.inet_addr_of_string)
116-
else
117-
None
118-
in
119-
let nameservers =
120-
if List.mem_assoc "DNS" args && List.assoc "DNS" args <> "" then
121-
List.map Unix.inet_addr_of_string
122-
(Astring.String.cuts ~empty:false ~sep:","
123-
(List.assoc "DNS" args)
124-
)
125-
else
126-
[]
127-
in
128-
let domains =
129-
if List.mem_assoc "DOMAIN" args && List.assoc "DOMAIN" args <> ""
130-
then
131-
Astring.String.cuts ~empty:false ~sep:" "
132-
(List.assoc "DOMAIN" args)
133-
else
134-
[]
135-
in
136-
let dns = (nameservers, domains) in
137-
(Static4 [(ip, prefixlen)], gateway, dns)
138-
| "dhcp" ->
139-
(DHCP4, None, ([], []))
140-
| _ ->
141-
(None4, None, ([], []))
141+
let dns = parse_dns_config args in
142+
let (ipv4_conf, ipv4_gateway), (ipv6_conf, ipv6_gateway) =
143+
match (List.assoc_opt "MODE" args, List.assoc_opt "MODEV6" args) with
144+
| None, None ->
145+
error "%s: at least one of 'MODE', 'MODEV6' needs to be specified"
146+
__FUNCTION__ ;
147+
raise Read_error
148+
| v4, v6 ->
149+
(parse_ipv4_config args v4, parse_ipv6_config args v6)
142150
in
143151

144152
let phy_interface = {default_interface with persistent_i= true} in
145153
let bridge_interface =
146-
{default_interface with ipv4_conf; ipv4_gateway; persistent_i= true; dns}
154+
{
155+
default_interface with
156+
ipv4_conf
157+
; ipv4_gateway
158+
; ipv6_conf
159+
; ipv6_gateway
160+
; persistent_i= true
161+
; dns
162+
}
147163
in
148164
let interface_config, bridge_config =
149165
let primary_bridge_conf =

ocaml/xapi/xapi.ml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -760,9 +760,9 @@ let check_network_reset () =
760760
) ;
761761
(* Remove trigger file *)
762762
Unix.unlink Xapi_globs.network_reset_trigger
763-
with _ -> ()
764-
765-
(* TODO: catch specific exception for missing fields in reset_file and inform user *)
763+
with e ->
764+
D.error "%s: exception: %s (%s)" __FUNCTION__ (Printexc.to_string e)
765+
(Printexc.get_backtrace ())
766766

767767
(** Make sure our license is set correctly *)
768768
let handle_licensing () =

python3/bin/xe-reset-networking

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ if __name__ == "__main__":
8787
f = open(pool_conf, 'r')
8888
try:
8989
l = f.readline()
90-
ls = l.split(':')
90+
ls = l.split(':', maxsplit=1)
9191
if ls[0].strip() == 'master':
9292
master = True
9393
address = 'localhost'

0 commit comments

Comments
 (0)