For Red Hat-derived guests using the old network scripts, derive the list of network interfaces from the files ‘/etc/sysconfig/network-scripts/ifcfg-*’. This also works for Red Hat-derived guests using NetworkManager, although perhaps in future we should write a specific parser for them. --- daemon/inspect_fs_unix.ml | 85 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/daemon/inspect_fs_unix.ml b/daemon/inspect_fs_unix.ml index 4dd89fa8f..3f1f026d5 100644 --- a/daemon/inspect_fs_unix.ml +++ b/daemon/inspect_fs_unix.ml @@ -474,7 +474,8 @@ let rec check_linux_root mountable data = data.arch <- check_architecture (); data.fstab <- Inspect_fs_unix_fstab.check_fstab ~mdadm_conf:true mountable os_type; - data.hostname <- check_hostname_linux () + data.hostname <- check_hostname_linux (); + data.interfaces <- check_network_interfaces_linux () and check_architecture () = let rec loop = function @@ -546,6 +547,88 @@ and check_hostname_from_sysconfig_network aug = *) aug_get_noerrors aug "/files/etc/sysconfig/network/HOSTNAME" +and check_network_interfaces_linux () = + (* If there are any /etc/sysconfig/network-scripts/ifcfg-* files + * then we assume old Red Hat network scripts style. Note if + * we ever support NetworkManager explicitly, or systemd-networkd, + * then those should be checked _before_ this line. + *) + match check_old_redhat_network_scripts () with + | Some interfaces -> Some interfaces + | None -> None + +and check_old_redhat_network_scripts () = + with_return (fun {return} -> + let conf_dir = "/etc/sysconfig/network-scripts" in + if not (Is.is_dir conf_dir) then return None; + + (* Get the list of all files and filter for "ifcfg-*". *) + let chroot = Chroot.create ~name:"check_old_redhat_network_scripts" () in + let files = Chroot.f chroot Sys.readdir conf_dir in + let files = Array.to_list files in + let files = List.sort compare files in + let files = List.filter (fun n -> String.is_prefix n "ifcfg-") files in + let files = List.filter (fun n -> not (is_editor_backup n)) files in + let files = + List.filter_map ( + fun filename -> + match Chroot.f chroot read_small_file (conf_dir // filename) with + | None -> None + | Some lines -> Some (filename, lines) + ) files in + if files = [] then return None; + + (* At this point we are going to return one interface per file. *) + let interfaces = List.map check_old_redhat_ifcfg_file files in + Some interfaces + ) + +(* Load the file and map the key=value pairs found into params. + * For ifcfg-* files this mapping is largely an identity map + * except: + * - keys "TYPE", "HWADDR", "NAME" and "DEVICE" get special treatment + * - key is lowercased + * - comments are ignored and values must be unquoted + * - values like "yes", "no", etc are translated to "1" and "0" + * + * The if_name comes from: "DEVICE", "NAME" or the ifcfg- filename + * with the first taking priority. + *) +and check_old_redhat_ifcfg_file (filename, lines) = + let default_name = + assert (String.is_prefix filename "ifcfg-"); + String.sub filename 6 (String.length filename - 6) in + + let lines = parse_key_value_strings ~unquote:shell_unquote lines in + let lines = List.map (fun (k, v) -> String.lowercase_ascii k, v) lines in + + let if_type = ref "" in + let if_hwaddr = ref "" in + let device = ref "" in + let name = ref "" in + let params = ref [] in + List.iter ( + function + | "type", v -> if_type := String.lowercase_ascii v + | "hwaddr", v -> if_hwaddr := String.lowercase_ascii v + | "device", v -> device := v + | "name", v -> name := v + | k, v when is_true_noraise v -> List.push_front (k, "1") params + | k, v when is_false_noraise v -> List.push_front (k, "0") params + | kv -> List.push_front kv params + ) lines; + + let if_name = + if !device <> "" then !device + else if !name <> "" then !name + else default_name in + + { Structs.if_type = !if_type; if_hwaddr = !if_hwaddr; if_name }, !params + +and is_editor_backup filename = + String.is_suffix filename "~" || + String.is_suffix filename "*.bak" + (* The currently mounted device looks like a Linux /usr. *) let check_linux_usr data = data.os_type <- Some OS_TYPE_LINUX; -- 2.19.0.rc0