[Libguestfs] [PATCH v2 API PROPOSAL 4/5] inspection: Derive interface information from old Red Hat network scripts.

Richard W.M. Jones rjones at redhat.com
Mon Oct 1 19:16:48 UTC 2018


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




More information about the Libguestfs mailing list