Richard W.M. Jones
2023-Jun-08 10:38 UTC
[Libguestfs] [PATCH] VxFS Filesystem support to libguestfs
Reposting this patch as a patch, original message here: https://listman.redhat.com/archives/libguestfs/2023-June/031722.html
Richard W.M. Jones
2023-Jun-08 10:38 UTC
[Libguestfs] [PATCH] VxFS Filesystem support to libguestfs
From: Ravi Singh <ravi.singh at veritas.com> --- appliance/hostfiles.in | 4 ++ appliance/init | 2 + daemon/Makefile.am | 7 +++ daemon/guestfsd.c | 3 + daemon/listfs.ml | 17 ++++++ daemon/vm.ml | 68 ++++++++++++++++++++++ daemon/vm.mli | 24 ++++++++ daemon/vxfs.c | 119 ++++++++++++++++++++++++++++++++++++++ daemon/vxvm_type.ml | 17 ++++++ daemon/vxvm_type.mli | 24 ++++++++ generator/actions_core.ml | 32 ++++++++++ generator/proc_nr.ml | 3 + lib/MAX_PROC_NR | 2 +- po/POTFILES | 1 + 14 files changed, 322 insertions(+), 1 deletion(-) diff --git a/appliance/hostfiles.in b/appliance/hostfiles.in index e78c79bd34..e519ad1787 100644 --- a/appliance/hostfiles.in +++ b/appliance/hostfiles.in @@ -17,3 +17,7 @@ dnl OPENMANDRIVA=1 For OpenMandriva. /etc/ld.so.cache /lib/lsb/* /usr/share/augeas/lenses/*.aug +/etc/vx/vxfs +/etc/vx/veki +/etc/vx/vxvm-startup +/opt/VRTS/bin/fstyp diff --git a/appliance/init b/appliance/init index d410566597..535a3d6b19 100755 --- a/appliance/init +++ b/appliance/init @@ -22,6 +22,8 @@ mount -t proc /proc /proc mount -t sysfs /sys /sys # devtmpfs is required since udev 176 mount -t devtmpfs /dev /dev +# Create dev directory for all VxVM device files. +mkdir -p /dev/vx ln -s /proc/self/fd /dev/fd # Parse the kernel command line early (must be after /proc is mounted). diff --git a/daemon/Makefile.am b/daemon/Makefile.am index bb2e58d014..8d3d9c8255 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -51,6 +51,8 @@ generator_built = \ link.mli \ listfs.mli \ lvm.mli \ + vm.mli \ + vxvm_type.mli \ lvm_dm.mli \ md.mli \ mount.mli \ @@ -208,6 +210,7 @@ guestfsd_SOURCES = \ wc.c \ xattr.c \ xfs.c \ + vxfs.c \ yara.c \ zero.c \ zerofree.c @@ -294,6 +297,8 @@ SOURCES_MLI = \ link.mli \ listfs.mli \ lvm.mli \ + vm.mli \ + vxvm_type.mli \ lvm_dm.mli \ lvm_utils.mli \ md.mli \ @@ -328,6 +333,8 @@ SOURCES_ML = \ ldm.ml \ link.ml \ lvm.ml \ + vm.ml \ + vxvm_type.ml \ lvm_utils.ml \ lvm_dm.ml \ findfs.ml \ diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c index 33c297de33..7b202ea53c 100644 --- a/daemon/guestfsd.c +++ b/daemon/guestfsd.c @@ -273,6 +273,9 @@ main (int argc, char *argv[]) */ udev_settle (); + /* Start vxfs services */ + do_vxfs_start(); + /* Send the magic length message which indicates that * userspace is up inside the guest. */ diff --git a/daemon/listfs.ml b/daemon/listfs.ml index 2376b61dbc..10e32d8c04 100644 --- a/daemon/listfs.ml +++ b/daemon/listfs.ml @@ -25,6 +25,11 @@ open Std_utils * contain filesystems, so we filter them out. *) let rec list_filesystems () + + (* Check if the vxvm services are available. As we are trying to read + * vxvm disk layout + *) + let has_vxvm = Optgroups.vxvm_available () in let has_lvm2 = Optgroups.lvm2_available () in let has_ldm = Optgroups.ldm_available () in @@ -53,6 +58,12 @@ let rec list_filesystems () let mds = List.filter is_not_partitioned_device mds in List.iter (check_with_vfs_type ret) mds; + (* VxVM. *) + if has_vxvm then ( + let vxvm_vol = Vm.vxvm () in + List.iter (check_with_vxvmvol_type ret) vxvm_vol + ); + (* LVM. *) if has_lvm2 then ( let lvs = Lvm.lvs () in @@ -192,3 +203,9 @@ and check_with_vfs_type ret device else List.push_back ret (mountable, vfs_type) + +(* Check for the vxvm volume type *) +and check_with_vxvmvol_type ret device + let mountable = Mountable.of_device device in + let vxvmvol_typ = Vxvm_type.vxvmvol_type mountable in + List.push_back ret (mountable, vxvmvol_typ) diff --git a/daemon/vm.ml b/daemon/vm.ml new file mode 100644 index 0000000000..d01b9e273d --- /dev/null +++ b/daemon/vm.ml @@ -0,0 +1,68 @@ +open Unix +open Printf + +open Std_utils +open Str +open Utils + +let rec vxvm () + let a = command "vxdisk" ["-q"; "list"; "-p"; "-x"; "DG_NAME"] in + let lines = String.nsplit "\n" a in + let lines = List.map String.trim lines in + let lines = List.filter ((<>) "") lines in + + (* Create a list of list *) + let lines = List.filter_map ( + fun line -> + let s = Str.regexp "[ \t\r\n]" in + let str = Str.bounded_split s line 2 in + match str with + | [ a; b ] -> + Some (sprintf "%s" b) + | _-> None + ) lines in + + (* Trim of all the whitespaces from each element of the list *) + let lines = List.map String.trim lines in + + (* Skip the lines with "-" *) + let lines = List.filter ((<>) "-") lines in + let lines = List.sort_uniq compare lines in + let _ = List.iter (eprintf "%s") lines in + + (* Import the disk group that is in the deported state *) + let _ = List.map ( + fun x -> + let r, out, err = commandr "vxdg" ["list"; x] in + match r with + | 0 -> None + | _ -> + Some (command "vxdg" ["-Cf"; "import"; x]) + ) lines in + + let out = command "vxprint" [ "-s"; "-F"; "%{dg_name}/%{v_name}"; "-A"; "-Q" ] in + convert_vxvm_output ~prefix:"/dev/vx/dsk/" out + +and convert_vxvm_output ?prefix out + let lines = String.nsplit "\n" out in + + (* Skip leading and trailing ("pvs", I'm looking at you) whitespace. *) + let lines = List.map String.trim lines in + + (* Skip empty lines. *) + let lines = List.filter ((<>) "") lines in + + (* Ignore "unknown device" message (RHBZ#1054761). *) + let lines = List.filter ((<>) "unknown device") lines in + + (* Remove Duplicate elements *) + let lines = List.sort_uniq compare lines in + + (* Add a prefix? *) + let lines + match prefix with + | None -> lines + | Some prefix -> List.map ((^) prefix) lines in + + (* Sort and return. *) + List.sort compare lines diff --git a/daemon/vm.mli b/daemon/vm.mli new file mode 100644 index 0000000000..98db6b4f9d --- /dev/null +++ b/daemon/vm.mli @@ -0,0 +1,24 @@ +(* libguestfs generated file + * WARNING: THIS FILE IS GENERATED FROM THE FOLLOWING FILES: + * generator/daemon.ml + * and from the code in the generator/ subdirectory. + * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. + * + * Copyright (C) 2009-2020 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *) + +val vxvm : unit -> string list diff --git a/daemon/vxfs.c b/daemon/vxfs.c new file mode 100644 index 0000000000..75e18f9525 --- /dev/null +++ b/daemon/vxfs.c @@ -0,0 +1,119 @@ +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <dirent.h> + +#include "daemon.h" + +/* This is used to check if we have the vxvm utility + * in place. + */ +int +optgroup_vxvm_available (void) +{ + + CLEANUP_FREE char *err = NULL; + int r; + + r = commandr (NULL, &err, "vxdctl", "list", NULL); + + return r == 0; +} + +int opt_servicefile_available (const char *path) +{ + CLEANUP_FREE char *testpath; + if (path == NULL) return 0; + if (asprintf (&testpath, "%s/%s", "/etc/vx", path) == -1) return 0; + if (access (testpath, X_OK) == 0) + return 1; + + /* Not found. */ + return 0; +} + +int +optgroup_vxfs_available (void) +{ + return filesystem_available ("vxfs"); +} + +/* Starting Infoscale related services in the daemon which is + * required to read vxvm supported disk layout version, here we are + * first initialising the lisence then starting all the related + * services to read the files from vxvm disk layout + */ +int +do_vxfs_start (void) +{ + CLEANUP_FREE char *err = NULL, *err2 = NULL, + *err3 = NULL, *err4 = NULL, *err5 = NULL, *err6 = NULL; + int r; + + /** + * Setup the license on the appliance to configure + * Infoscale services. + */ + r = commandr (NULL, &err, "vxkeyless", "--quiet", "set", "ENTERPRISE", NULL); + if (r == -1){ + reply_with_error ("vxkeyless set error:%s", err); + return -1; + } + + /** + * Start Veki service. + */ + if (opt_servicefile_available("veki") == 0) return -1; + r = commandr (NULL, &err2, "/etc/vx/veki", "start", NULL); + if (r == -1){ + reply_with_error ("veki start error:%s", err2); + return -1; + } + + /** + * Start vxfs service. + */ + if (opt_servicefile_available("vxfs") == 0) return -1; + r = commandr (NULL, &err3, "/etc/vx/vxfs", "start", NULL); + if (r == -1){ + reply_with_error ("vxfs start error:%s", err3); + return -1; + } + + /** + * Start vxvm related services. + */ + if (opt_servicefile_available("vxvm-startup") == 0) return -1; + r = commandr (NULL, &err4, "sh", "/etc/vx/vxvm-startup", NULL); + if (r == -1){ + reply_with_error ("vxvm start error:%s", err4); + return -1; + } + + /** + * Trigger vxdctl init to generate volboot file + */ + r = commandr (NULL, &err5, "vxdctl", "init", NULL); + if (r == -1){ + reply_with_error ("vxdctl init error:%s", err5); + return -1; + } + + /** + * Enabling this would allow us to use vxvm related + * commands + */ + r = commandr (NULL, &err6, "vxdctl", "enable", NULL); + if (r == -1){ + reply_with_error ("vxdctl enable error:%s", err6); + return -1; + } + + return 0; +} diff --git a/daemon/vxvm_type.ml b/daemon/vxvm_type.ml new file mode 100644 index 0000000000..9a01151ee3 --- /dev/null +++ b/daemon/vxvm_type.ml @@ -0,0 +1,17 @@ +open Std_utils + +open Utils + +(* Detrmine the VxVM volume type using the fstype command + * This would help us determine the vxfs specific volumes. + *) +let rec vxvmvol_type { Mountable.m_device=device }+ Option.default "" (get_vxvmvol_type device) + +and get_vxvmvol_type device + let r, out, err + commandr "/opt/VRTS/bin/fstyp" [ device ] in + match r with + | 0 -> Some (String.chomp out) + | 2 -> None + | _ -> failwithf "fstyp: %s: %s" device err diff --git a/daemon/vxvm_type.mli b/daemon/vxvm_type.mli new file mode 100644 index 0000000000..b1387454a6 --- /dev/null +++ b/daemon/vxvm_type.mli @@ -0,0 +1,24 @@ +(* libguestfs generated file + * WARNING: THIS FILE IS GENERATED FROM THE FOLLOWING FILES: + * generator/daemon.ml + * and from the code in the generator/ subdirectory. + * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. + * + * Copyright (C) 2009-2020 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *) + +val vxvmvol_type : Mountable.t -> string diff --git a/generator/actions_core.ml b/generator/actions_core.ml index addbe4ec15..c1af43b3e6 100644 --- a/generator/actions_core.ml +++ b/generator/actions_core.ml @@ -1808,6 +1808,38 @@ This returns a list of the logical volume device names See also C<guestfs_lvs_full>, C<guestfs_list_filesystems>." }; +{ defaults with + name = "vxvm"; added = (0, 0, 1); + style = RStringList (RDevice, "logvols"), [], []; + impl = OCaml "Vm.vxvm"; + optional = Some "vxvm"; + shortdesc = "list the VxVM volumes (vxvm)"; + longdesc = "\ +List all the VxVM volumes detected. This is the equivalent +of the L<vxdisk list> command. + +This returns a list of the VxVM volume device names +(eg. F</dev/vx/dsk/DiskGroup/Volume>). + +See also C<guestfs_list_filesystems>." }; + +{ defaults with + name = "vxvmvol_type"; added = (0, 0, 1); + style = RString (RPlainString, "fstype"), [String (Mountable, "mountable")], []; + impl = OCaml "Vxvm_type.vxvmvol_type"; + shortdesc = "get the VxVM Volume type corresponding to a mounted device"; + longdesc = "\ +This command returns the filesystem type corresponding to +the filesystem on C<mountable>." }; + +{ defaults with + name = "vxfs_start"; added = (0, 0, 1); + style = RErr, [], []; + shortdesc = "this command is used to start vxfs service"; + longdesc = "\ +In order to start vxfs service in the guestfsd we use +this command" }; + { defaults with name = "pvs_full"; added = (0, 0, 4); style = RStructList ("physvols", "lvm_pv"), [], []; diff --git a/generator/proc_nr.ml b/generator/proc_nr.ml index f71a849c98..9086f26c77 100644 --- a/generator/proc_nr.ml +++ b/generator/proc_nr.ml @@ -516,6 +516,9 @@ let proc_nr = [ 511, "internal_readdir"; 512, "clevis_luks_unlock"; 513, "inspect_get_build_id"; +514, "vxvm"; +515, "vxvmvol_type"; +516, "vxfs_start" ] (* End of list. If adding a new entry, add it at the end of the list diff --git a/lib/MAX_PROC_NR b/lib/MAX_PROC_NR index 31cf34b8d0..1c599d4ff3 100644 --- a/lib/MAX_PROC_NR +++ b/lib/MAX_PROC_NR @@ -1 +1 @@ -513 +516 diff --git a/po/POTFILES b/po/POTFILES index 1facee0a3c..1989b17c8c 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -144,6 +144,7 @@ daemon/uuids.c daemon/wc.c daemon/xattr.c daemon/xfs.c +daemon/vxfs.c daemon/yara.c daemon/zero.c daemon/zerofree.c -- 2.40.1