[PATCH v3 0/3] New API - find_block
by Matteo Cafasso
v3:
- fixed attribute walk callback: checking against TSK_FS_BLOCK_FLAG_RAW flag would
exclude compressed data blocks which are still important.
Yet we want to exclude sparse blocks (TSK_FS_BLOCK_FLAG_SPARSE) as they are not stored
on the disk.
Matteo Cafasso (3):
New API: internal_find_block
New API: find_block
find_block: added API tests
daemon/tsk.c | 91 ++++++++++++++++++++++++++++++++++++++++++++
generator/actions.ml | 25 ++++++++++++
src/MAX_PROC_NR | 2 +-
src/tsk.c | 17 +++++++++
tests/tsk/Makefile.am | 1 +
tests/tsk/test-find-block.sh | 66 ++++++++++++++++++++++++++++++++
6 files changed, 201 insertions(+), 1 deletion(-)
create mode 100755 tests/tsk/test-find-block.sh
--
2.9.3
8 years, 1 month
[PATCH v5] v2v: linux: correctly reconfigure the initrd on Debian
by Tomáš Golembiovský
Using update-initramfs is the native way of updating initrd on Debian
based systems.
To add some modules to the image we can list them in file
/etc/initramfs-tools/modules.
Signed-off-by: Tomáš Golembiovský <tgolembi(a)redhat.com>
---
v2v/convert_linux.ml | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/v2v/convert_linux.ml b/v2v/convert_linux.ml
index 08f4b2a..6b4197d 100644
--- a/v2v/convert_linux.ml
+++ b/v2v/convert_linux.ml
@@ -478,6 +478,15 @@ let rec convert ~keep_serial_console (g : G.guestfs) inspect source rcaps =
ignore (g#command (Array.of_list args))
in
+ let run_update_initramfs_command () =
+ let args =
+ "/usr/sbin/update-initramfs" ::
+ (if verbose () then [ "-v" ] else [])
+ @ [ "-c"; "-k"; mkinitrd_kv ]
+ in
+ ignore (g#command (Array.of_list args))
+ in
+
if g#is_file ~followsymlinks:true "/sbin/dracut" then
run_dracut_command "/sbin/dracut"
else if g#is_file ~followsymlinks:true "/usr/bin/dracut" then
@@ -491,6 +500,29 @@ let rec convert ~keep_serial_console (g : G.guestfs) inspect source rcaps =
"-k"; kernel.ki_vmlinuz |]
)
)
+ else if family = `Debian_family then (
+ if not (g#is_file ~followsymlinks:true "/usr/sbin/update-initramfs") then
+ error (f_"unable to rebuild initrd (%s) because update-initramfs was not found in the guest")
+ initrd;
+
+ if List.length modules > 0 then (
+ (* The modules to add to initrd are defined in:
+ * /etc/initramfs-tools/modules
+ * File format is same as modules(5).
+ *)
+ let path = "/files/etc/initramfs-tools/modules" in
+ g#aug_transform "modules" "/etc/initramfs-tools/modules";
+ Linux.augeas_reload g;
+ g#aug_set (sprintf "%s/#comment[last()+1]" path)
+ "The following modules were added by virt-v2v";
+ List.iter (
+ fun m -> g#aug_clear (sprintf "%s/%s" path m)
+ ) modules;
+ g#aug_save ();
+ );
+
+ run_update_initramfs_command ()
+ )
else if g#is_file ~followsymlinks:true "/sbin/mkinitrd" then (
let module_args = List.map (sprintf "--with=%s") modules in
let args =
--
2.9.3
8 years, 1 month
[PATCH v2] libvirt: read disk paths from pools (RHBZ#1366049)
by Pino Toscano
A disk of type 'volume' is stored as
<source pool='pool_name' volume='volume_name'/>
and its real location is inside the 'volume_name', as 'pool_name': in
this case, query libvirt for the actual path of the specified volume in
the specified pool.
Adjust the code so that:
- for_each_disk gets the virConnectPtr, needed to do operations with
libvirt
- when extracting the disk filename depending on the type, the code
snippet doing it can directly set 'filename', without setting an XPath
result variable
Only file-based volumes are supported for now; more types can be added
(with proper testing) later on.
---
src/libvirt-domain.c | 134 +++++++++++++++++++++++++----
tests/disks/test-qemu-drive-libvirt.sh | 16 ++++
tests/disks/test-qemu-drive-libvirt.xml.in | 37 ++++++++
3 files changed, 172 insertions(+), 15 deletions(-)
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index d54814f..4d4142d 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -40,8 +40,9 @@
#if defined(HAVE_LIBVIRT)
static xmlDocPtr get_domain_xml (guestfs_h *g, virDomainPtr dom);
-static ssize_t for_each_disk (guestfs_h *g, xmlDocPtr doc, int (*f) (guestfs_h *g, const char *filename, const char *format, int readonly, const char *protocol, char *const *server, const char *username, void *data), void *data);
+static ssize_t for_each_disk (guestfs_h *g, virConnectPtr conn, xmlDocPtr doc, int (*f) (guestfs_h *g, const char *filename, const char *format, int readonly, const char *protocol, char *const *server, const char *username, void *data), void *data);
static int libvirt_selinux_label (guestfs_h *g, xmlDocPtr doc, char **label_rtn, char **imagelabel_rtn);
+static char *filename_from_pool (guestfs_h *g, virConnectPtr conn, const char *pool_nane, const char *volume_name);
static void
ignore_errors (void *ignore, virErrorPtr ignore2)
@@ -311,7 +312,7 @@ guestfs_impl_add_libvirt_dom (guestfs_h *g, void *domvp,
* all disks are added or none are added.
*/
ckp = guestfs_int_checkpoint_drives (g);
- r = for_each_disk (g, doc, add_disk, &data);
+ r = for_each_disk (g, virDomainGetConnect (dom), doc, add_disk, &data);
if (r == -1)
guestfs_int_rollback_drives (g, ckp);
@@ -466,6 +467,7 @@ libvirt_selinux_label (guestfs_h *g, xmlDocPtr doc,
*/
static ssize_t
for_each_disk (guestfs_h *g,
+ virConnectPtr conn,
xmlDocPtr doc,
int (*f) (guestfs_h *g,
const char *filename, const char *format,
@@ -509,6 +511,8 @@ for_each_disk (guestfs_h *g,
CLEANUP_XMLXPATHFREEOBJECT xmlXPathObjectPtr xpprotocol = NULL;
CLEANUP_XMLXPATHFREEOBJECT xmlXPathObjectPtr xphost = NULL;
CLEANUP_XMLXPATHFREEOBJECT xmlXPathObjectPtr xpusername = NULL;
+ CLEANUP_XMLXPATHFREEOBJECT xmlXPathObjectPtr xppool = NULL;
+ CLEANUP_XMLXPATHFREEOBJECT xmlXPathObjectPtr xpvolume = NULL;
xmlAttrPtr attr;
int readonly;
int t;
@@ -628,22 +632,66 @@ for_each_disk (guestfs_h *g,
* TODO: secrets: ./auth/secret/@type,
* ./auth/secret/@usage || ./auth/secret/@uuid
*/
- } else
- continue; /* type <> "file", "block", or "network", skip it */
+ } else if (STREQ (type, "volume")) { /* type = "volume", use source/@volume */
+ CLEANUP_FREE char *pool = NULL;
+ CLEANUP_FREE char *volume = NULL;
+
+ xpathCtx->node = nodes->nodeTab[i];
- assert (xpfilename);
- assert (xpfilename->nodesetval);
- if (xpfilename->nodesetval->nodeNr > 0) {
- assert (xpfilename->nodesetval->nodeTab[0]);
- assert (xpfilename->nodesetval->nodeTab[0]->type ==
+ /* Get the source pool. Required. */
+ xppool = xmlXPathEvalExpression (BAD_CAST "./source/@pool",
+ xpathCtx);
+ if (xppool == NULL ||
+ xppool->nodesetval == NULL ||
+ xppool->nodesetval->nodeNr == 0)
+ continue;
+ assert (xppool->nodesetval->nodeTab[0]);
+ assert (xppool->nodesetval->nodeTab[0]->type ==
+ XML_ATTRIBUTE_NODE);
+ attr = (xmlAttrPtr) xppool->nodesetval->nodeTab[0];
+ pool = (char *) xmlNodeListGetString (doc, attr->children, 1);
+
+ /* Get the source volume. Required. */
+ xpvolume = xmlXPathEvalExpression (BAD_CAST "./source/@volume",
+ xpathCtx);
+ if (xpvolume == NULL ||
+ xpvolume->nodesetval == NULL ||
+ xpvolume->nodesetval->nodeNr == 0)
+ continue;
+ assert (xpvolume->nodesetval->nodeTab[0]);
+ assert (xpvolume->nodesetval->nodeTab[0]->type ==
XML_ATTRIBUTE_NODE);
- attr = (xmlAttrPtr) xpfilename->nodesetval->nodeTab[0];
- filename = (char *) xmlNodeListGetString (doc, attr->children, 1);
- debug (g, "disk[%zu]: filename: %s", i, filename);
+ attr = (xmlAttrPtr) xpvolume->nodesetval->nodeTab[0];
+ volume = (char *) xmlNodeListGetString (doc, attr->children, 1);
+
+ debug (g, "disk[%zu]: pool: %s; volume: %s", i, pool, volume);
+
+ filename = filename_from_pool (g, conn, pool, volume);
+ if (filename == NULL)
+ continue; /* filename_from_pool already called error() */
+ } else
+ continue; /* type is not handled above, skip it */
+
+ /* Allow any of the code blocks above (handling a disk type)
+ * to directly get the filename (setting 'filename'), with no need
+ * for an XPath evaluation.
+ */
+ if (filename == NULL) {
+ assert (xpfilename);
+ assert (xpfilename->nodesetval);
+ if (xpfilename->nodesetval->nodeNr > 0) {
+ assert (xpfilename->nodesetval->nodeTab[0]);
+ assert (xpfilename->nodesetval->nodeTab[0]->type ==
+ XML_ATTRIBUTE_NODE);
+ attr = (xmlAttrPtr) xpfilename->nodesetval->nodeTab[0];
+ filename = (char *) xmlNodeListGetString (doc, attr->children, 1);
+ }
+ else
+ /* For network protocols (eg. nbd), name may be omitted. */
+ filename = safe_strdup (g, "");
}
- else
- /* For network protocols (eg. nbd), name may be omitted. */
- filename = safe_strdup (g, "");
+
+ debug (g, "disk[%zu]: filename: %s", i, filename);
/* Get the disk format (may not be set). */
xpathCtx->node = nodes->nodeTab[i];
@@ -784,6 +832,62 @@ get_domain_xml (guestfs_h *g, virDomainPtr dom)
return doc;
}
+static char *
+filename_from_pool (guestfs_h *g, virConnectPtr conn,
+ const char *pool_name, const char *volume_name)
+{
+ char *filename = NULL;
+ virErrorPtr err;
+ virStoragePoolPtr pool = NULL;
+ virStorageVolPtr vol = NULL;
+ virStorageVolInfo info;
+ int ret;
+
+ pool = virStoragePoolLookupByName (conn, pool_name);
+ if (pool == NULL) {
+ err = virGetLastError ();
+ error (g, _("no libvirt pool called '%s': %s"),
+ pool_name, err->message);
+ goto cleanup;
+ }
+
+ vol = virStorageVolLookupByName (pool, volume_name);
+ if (vol == NULL) {
+ err = virGetLastError ();
+ error (g, _("no volume called '%s' in the libvirt pool '%s': %s"),
+ volume_name, pool_name, err->message);
+ goto cleanup;
+ }
+
+ ret = virStorageVolGetInfo (vol, &info);
+ if (ret < 0) {
+ err = virGetLastError ();
+ error (g, _("cannot get information of the libvirt volume '%s': %s"),
+ volume_name, err->message);
+ goto cleanup;
+ }
+
+ debug (g, "type of libvirt volume %s: %d", volume_name, info.type);
+
+ /* Support only file-based volumes for now. */
+ if (info.type != VIR_STORAGE_VOL_FILE)
+ goto cleanup;
+
+ filename = virStorageVolGetPath (vol);
+ if (filename == NULL) {
+ err = virGetLastError ();
+ error (g, _("cannot get the filename of the libvirt volume '%s': %s"),
+ volume_name, err->message);
+ goto cleanup;
+ }
+
+ cleanup:
+ if (vol) virStorageVolFree (vol);
+ if (pool) virStoragePoolFree (pool);
+
+ return filename;
+}
+
#else /* no libvirt at compile time */
#define NOT_IMPL(r) \
diff --git a/tests/disks/test-qemu-drive-libvirt.sh b/tests/disks/test-qemu-drive-libvirt.sh
index 215a99e..b2656ba 100755
--- a/tests/disks/test-qemu-drive-libvirt.sh
+++ b/tests/disks/test-qemu-drive-libvirt.sh
@@ -47,6 +47,12 @@ export LIBGUESTFS_BACKEND=direct
export LIBGUESTFS_HV="${abs_srcdir}/debug-qemu.sh"
export DEBUG_QEMU_FILE="${abs_builddir}/test-qemu-drive-libvirt.out"
+# Setup the fake pool.
+pool_dir=tmp
+rm -rf "$pool_dir"
+mkdir "$pool_dir"
+touch "$pool_dir/in-pool"
+
function check_output ()
{
if [ ! -f "$DEBUG_QEMU_FILE" ]; then
@@ -104,8 +110,18 @@ check_output
grep -sq -- '-drive file=sheepdog:volume,' "$DEBUG_QEMU_FILE" || fail
rm "$DEBUG_QEMU_FILE"
+# Local, stored in a pool.
+
+$guestfish -d pool1 run ||:
+check_output
+grep -sq -- "-drive file=$abs_builddir/tmp/in-pool" "$DEBUG_QEMU_FILE" || fail
+rm "$DEBUG_QEMU_FILE"
+
# To do:
# HTTP - curl not yet supported by libvirt
# SSH.
+
+# Clean up.
+rm -r "$pool_dir"
diff --git a/tests/disks/test-qemu-drive-libvirt.xml.in b/tests/disks/test-qemu-drive-libvirt.xml.in
index e8e6252..f0b7fe0 100644
--- a/tests/disks/test-qemu-drive-libvirt.xml.in
+++ b/tests/disks/test-qemu-drive-libvirt.xml.in
@@ -132,4 +132,41 @@
</devices>
</domain>
+ <domain type='test' xmlns:test='http://libvirt.org/schemas/domain/test/1.0'>
+ <test:runstate>5</test:runstate> <!-- 5 == VIR_DOMAIN_SHUTOFF -->
+ <name>pool1</name>
+ <memory>1048576</memory>
+ <os>
+ <type>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <devices>
+ <disk type='volume' device='disk'>
+ <driver name='qemu'/>
+ <source pool='pool1' volume='in-pool'/>
+ <target dev='vda' bus='virtio'/>
+ </disk>
+ </devices>
+ </domain>
+
+ <pool type='dir'>
+ <name>pool1</name>
+ <uuid>12345678-1234-1234-1234-1234567890ab</uuid>
+ <target>
+ <path>@abs_builddir@/tmp</path>
+ </target>
+
+ <volume type='file'>
+ <name>in-pool</name>
+ <capacity unit='bytes'>1048576</capacity>
+ <key>@abs_builddir@/tmp/in-pool</key>
+ <source>
+ </source>
+ <target>
+ <path>@abs_builddir@/tmp/in-pool</path>
+ </target>
+ </volume>
+
+ </pool>
+
</node>
--
2.7.4
8 years, 1 month
[PATCH] v2v: Support <listen type='socket'> and <listen type='none'> (RHBZ#1378022).
by Richard W.M. Jones
Since libvirt 2.0.0, these two new <listen/> types have been
supported: https://libvirt.org/formatdomain.html#elementsGraphics
This change just copies that configuration over from the source to the
destination if the destination is also libvirt.
Since we previously used 'LNone' to mean "no parseable <listen/>
element" I also had to change previous uses of 'LNone' to 'LNoListen',
so we can use 'LNone' to mean "<listen type='none'>".
Thanks: Ming Xie.
---
v2v/input_disk.ml | 2 +-
v2v/input_libvirtxml.ml | 17 ++++++++++++-----
v2v/output_libvirt.ml | 9 ++++++++-
v2v/types.ml | 8 ++++++--
v2v/types.mli | 4 +++-
5 files changed, 30 insertions(+), 10 deletions(-)
diff --git a/v2v/input_disk.ml b/v2v/input_disk.ml
index e07222f..2852ce9 100644
--- a/v2v/input_disk.ml
+++ b/v2v/input_disk.ml
@@ -84,7 +84,7 @@ class input_disk input_format disk = object
s_firmware = UnknownFirmware; (* causes virt-v2v to autodetect *)
s_display =
Some { s_display_type = Window; s_keymap = None; s_password = None;
- s_listen = LNone; s_port = None };
+ s_listen = LNoListen; s_port = None };
s_video = None;
s_sound = None;
s_disks = [disk];
diff --git a/v2v/input_libvirtxml.ml b/v2v/input_libvirtxml.ml
index 33e878e..d94591f 100644
--- a/v2v/input_libvirtxml.ml
+++ b/v2v/input_libvirtxml.ml
@@ -96,24 +96,31 @@ let parse_libvirt_xml ?conn xml =
let nr_nodes = Xml.xpathobj_nr_nodes obj in
if nr_nodes < 1 then (
match xpath_string "@listen" with
- | None -> LNone | Some a -> LAddress a
+ | None -> LNoListen | Some a -> LAddress a
) else (
(* Use only the first <listen> configuration. *)
match xpath_string "listen[1]/@type" with
- | None -> LNone
+ | None -> LNoListen
| Some "address" ->
(match xpath_string "listen[1]/@address" with
- | None -> LNone
+ | None -> LNoListen
| Some a -> LAddress a
)
| Some "network" ->
(match xpath_string "listen[1]/@network" with
- | None -> LNone
+ | None -> LNoListen
| Some n -> LNetwork n
)
+ | Some "socket" ->
+ (match xpath_string "listen[1]/@socket" with
+ | None -> LNoListen
+ | Some n -> LSocket n
+ )
+ | Some "none" ->
+ LNone
| Some t ->
warning (f_"<listen type='%s'> in the input libvirt XML was ignored") t;
- LNone
+ LNoListen
) in
let port =
match xpath_string "@autoport" with
diff --git a/v2v/output_libvirt.ml b/v2v/output_libvirt.ml
index e934335..ac91922 100644
--- a/v2v/output_libvirt.ml
+++ b/v2v/output_libvirt.ml
@@ -281,13 +281,20 @@ let create_libvirt_xml ?pool source target_buses guestcaps
(match source.s_display with
| Some { s_listen = listen } ->
(match listen with
+ | LNoListen -> ()
| LAddress a ->
let sub = e "listen" [ "type", "address"; "address", a ] [] in
append_child sub graphics
| LNetwork n ->
let sub = e "listen" [ "type", "network"; "network", n ] [] in
append_child sub graphics
- | LNone -> ())
+ | LSocket s ->
+ let sub = e "listen" [ "type", "socket"; "socket", s ] [] in
+ append_child sub graphics
+ | LNone ->
+ let sub = e "listen" [ "type", "none" ] [] in
+ append_child sub graphics
+ )
| None -> ());
(match source.s_display with
| Some { s_port = Some p } ->
diff --git a/v2v/types.ml b/v2v/types.ml
index c43db24..bf4365c 100644
--- a/v2v/types.ml
+++ b/v2v/types.ml
@@ -82,9 +82,11 @@ and source_display = {
}
and s_display_type = Window | VNC | Spice
and s_display_listen =
- | LNone
+ | LNoListen
| LAddress of string
| LNetwork of string
+ | LSocket of string
+ | LNone
and source_video = Source_other_video of string |
Source_Cirrus | Source_QXL
@@ -227,9 +229,11 @@ and string_of_source_display { s_display_type = typ;
(match keymap with None -> "" | Some km -> " " ^ km)
(match password with None -> "" | Some _ -> " with password")
(match listen with
- | LNone -> ""
+ | LNoListen -> ""
| LAddress a -> sprintf " listening on address %s" a
| LNetwork n -> sprintf " listening on network %s" n
+ | LSocket s -> sprintf " listening on Unix domain socket %s" s
+ | LNone -> " listening on private fd"
)
and string_of_source_video = function
diff --git a/v2v/types.mli b/v2v/types.mli
index 2727383..514565c 100644
--- a/v2v/types.mli
+++ b/v2v/types.mli
@@ -139,9 +139,11 @@ and source_display = {
}
and s_display_type = Window | VNC | Spice
and s_display_listen =
- | LNone
+ | LNoListen (** No parseable <listen/> element. *)
| LAddress of string (** Listen address. *)
| LNetwork of string (** Listen network. *)
+ | LSocket of string (** Listen Unix domain socket. *)
+ | LNone (** <listen type='none'> *)
(** Video adapter model. *)
and source_video = Source_other_video of string |
--
2.9.3
8 years, 1 month
[PATCH] libvirt: read disk paths from pools (RHBZ#1366049)
by Pino Toscano
A disk of type 'volume' is stored as
<source pool='pool_name' volume='volume_name'/>
and its real location is inside the 'volume_name', as 'pool_name': in
this case, query libvirt for the actual path of the specified volume in
the specified pool.
Adjust the code so that:
- for_each_disk gets the virConnectPtr, needed to do operations with
libvirt
- when extracting the disk filename depending on the type, the code
snippet doing it can directly set 'filename', without setting an XPath
result variable
Only file-based volumes are supported for now; more types can be added
(with proper testing) later on.
---
src/libvirt-domain.c | 131 +++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 117 insertions(+), 14 deletions(-)
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index d54814f..50759e3 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -40,8 +40,9 @@
#if defined(HAVE_LIBVIRT)
static xmlDocPtr get_domain_xml (guestfs_h *g, virDomainPtr dom);
-static ssize_t for_each_disk (guestfs_h *g, xmlDocPtr doc, int (*f) (guestfs_h *g, const char *filename, const char *format, int readonly, const char *protocol, char *const *server, const char *username, void *data), void *data);
+static ssize_t for_each_disk (guestfs_h *g, virConnectPtr conn, xmlDocPtr doc, int (*f) (guestfs_h *g, const char *filename, const char *format, int readonly, const char *protocol, char *const *server, const char *username, void *data), void *data);
static int libvirt_selinux_label (guestfs_h *g, xmlDocPtr doc, char **label_rtn, char **imagelabel_rtn);
+static char *filename_from_pool (guestfs_h *g, virConnectPtr conn, const char *pool_nane, const char *volume_name);
static void
ignore_errors (void *ignore, virErrorPtr ignore2)
@@ -311,7 +312,7 @@ guestfs_impl_add_libvirt_dom (guestfs_h *g, void *domvp,
* all disks are added or none are added.
*/
ckp = guestfs_int_checkpoint_drives (g);
- r = for_each_disk (g, doc, add_disk, &data);
+ r = for_each_disk (g, virDomainGetConnect (dom), doc, add_disk, &data);
if (r == -1)
guestfs_int_rollback_drives (g, ckp);
@@ -466,6 +467,7 @@ libvirt_selinux_label (guestfs_h *g, xmlDocPtr doc,
*/
static ssize_t
for_each_disk (guestfs_h *g,
+ virConnectPtr conn,
xmlDocPtr doc,
int (*f) (guestfs_h *g,
const char *filename, const char *format,
@@ -509,6 +511,8 @@ for_each_disk (guestfs_h *g,
CLEANUP_XMLXPATHFREEOBJECT xmlXPathObjectPtr xpprotocol = NULL;
CLEANUP_XMLXPATHFREEOBJECT xmlXPathObjectPtr xphost = NULL;
CLEANUP_XMLXPATHFREEOBJECT xmlXPathObjectPtr xpusername = NULL;
+ CLEANUP_XMLXPATHFREEOBJECT xmlXPathObjectPtr xppool = NULL;
+ CLEANUP_XMLXPATHFREEOBJECT xmlXPathObjectPtr xpvolume = NULL;
xmlAttrPtr attr;
int readonly;
int t;
@@ -628,22 +632,65 @@ for_each_disk (guestfs_h *g,
* TODO: secrets: ./auth/secret/@type,
* ./auth/secret/@usage || ./auth/secret/@uuid
*/
+ } else if (STREQ (type, "volume")) { /* type = "volume", use source/@volume */
+ CLEANUP_FREE char *pool = NULL;
+ CLEANUP_FREE char *volume = NULL;
+
+ xpathCtx->node = nodes->nodeTab[i];
+
+ /* Get the source pool. Required. */
+ xppool = xmlXPathEvalExpression (BAD_CAST "./source/@pool",
+ xpathCtx);
+ if (xppool == NULL ||
+ xppool->nodesetval == NULL ||
+ xppool->nodesetval->nodeNr == 0)
+ continue;
+ assert (xppool->nodesetval->nodeTab[0]);
+ assert (xppool->nodesetval->nodeTab[0]->type ==
+ XML_ATTRIBUTE_NODE);
+ attr = (xmlAttrPtr) xppool->nodesetval->nodeTab[0];
+ pool = (char *) xmlNodeListGetString (doc, attr->children, 1);
+
+ /* Get the source volume. Required. */
+ xpvolume = xmlXPathEvalExpression (BAD_CAST "./source/@volume",
+ xpathCtx);
+ if (xpvolume == NULL ||
+ xpvolume->nodesetval == NULL ||
+ xpvolume->nodesetval->nodeNr == 0)
+ continue;
+ assert (xpvolume->nodesetval->nodeTab[0]);
+ assert (xpvolume->nodesetval->nodeTab[0]->type ==
+ XML_ATTRIBUTE_NODE);
+ attr = (xmlAttrPtr) xpvolume->nodesetval->nodeTab[0];
+ volume = (char *) xmlNodeListGetString (doc, attr->children, 1);
+
+ debug (g, "disk[%zu]: pool: %s; volume: %s", i, pool, volume);
+
+ filename = filename_from_pool (g, conn, pool, volume);
+ if (filename == NULL)
+ continue; /* filename_from_pool already called error() */
} else
continue; /* type <> "file", "block", or "network", skip it */
- assert (xpfilename);
- assert (xpfilename->nodesetval);
- if (xpfilename->nodesetval->nodeNr > 0) {
- assert (xpfilename->nodesetval->nodeTab[0]);
- assert (xpfilename->nodesetval->nodeTab[0]->type ==
- XML_ATTRIBUTE_NODE);
- attr = (xmlAttrPtr) xpfilename->nodesetval->nodeTab[0];
- filename = (char *) xmlNodeListGetString (doc, attr->children, 1);
- debug (g, "disk[%zu]: filename: %s", i, filename);
+ /* Allow a disk type to directly get the filename, with no need
+ * for an XPath evaluation.
+ */
+ if (filename == NULL) {
+ assert (xpfilename);
+ assert (xpfilename->nodesetval);
+ if (xpfilename->nodesetval->nodeNr > 0) {
+ assert (xpfilename->nodesetval->nodeTab[0]);
+ assert (xpfilename->nodesetval->nodeTab[0]->type ==
+ XML_ATTRIBUTE_NODE);
+ attr = (xmlAttrPtr) xpfilename->nodesetval->nodeTab[0];
+ filename = (char *) xmlNodeListGetString (doc, attr->children, 1);
+ }
+ else
+ /* For network protocols (eg. nbd), name may be omitted. */
+ filename = safe_strdup (g, "");
}
- else
- /* For network protocols (eg. nbd), name may be omitted. */
- filename = safe_strdup (g, "");
+
+ debug (g, "disk[%zu]: filename: %s", i, filename);
/* Get the disk format (may not be set). */
xpathCtx->node = nodes->nodeTab[i];
@@ -784,6 +831,62 @@ get_domain_xml (guestfs_h *g, virDomainPtr dom)
return doc;
}
+static char *
+filename_from_pool (guestfs_h *g, virConnectPtr conn,
+ const char *pool_name, const char *volume_name)
+{
+ char *filename = NULL;
+ virErrorPtr err;
+ virStoragePoolPtr pool = NULL;
+ virStorageVolPtr vol = NULL;
+ virStorageVolInfo info;
+ int ret;
+
+ pool = virStoragePoolLookupByName (conn, pool_name);
+ if (pool == NULL) {
+ err = virGetLastError ();
+ error (g, _("no libvirt pool called '%s': %s"),
+ pool_name, err->message);
+ goto cleanup;
+ }
+
+ vol = virStorageVolLookupByName (pool, volume_name);
+ if (vol == NULL) {
+ err = virGetLastError ();
+ error (g, _("no volume called '%s' in the libvirt pool '%s': %s"),
+ volume_name, pool_name, err->message);
+ goto cleanup;
+ }
+
+ ret = virStorageVolGetInfo (vol, &info);
+ if (ret < 0) {
+ err = virGetLastError ();
+ error (g, _("cannot get information of the libvirt volume '%s': %s"),
+ volume_name, err->message);
+ goto cleanup;
+ }
+
+ debug (g, "type of libvirt volume %s: %d", volume_name, info.type);
+
+ /* Support only file-based volumes for now. */
+ if (info.type != VIR_STORAGE_VOL_FILE)
+ goto cleanup;
+
+ filename = virStorageVolGetPath (vol);
+ if (filename == NULL) {
+ err = virGetLastError ();
+ error (g, _("cannot get the filename of the libvirt volume '%s': %s"),
+ volume_name, err->message);
+ goto cleanup;
+ }
+
+ cleanup:
+ if (vol) virStorageVolFree (vol);
+ if (pool) virStoragePoolFree (pool);
+
+ return filename;
+}
+
#else /* no libvirt at compile time */
#define NOT_IMPL(r) \
--
2.7.4
8 years, 1 month
[PATCH] v2v: -i libvirtxml: ignore <listen type='none'> (RHBZ#1378022)
by Pino Toscano
When reading a libvirt XML which has:
<graphics ...>
<listen type='none'/>
</graphics>
then just ignore it, as it is (roughly) the same as no <listen> child
elements at all. This avoids a warning about an unknown listen type.
---
v2v/input_libvirtxml.ml | 1 +
1 file changed, 1 insertion(+)
diff --git a/v2v/input_libvirtxml.ml b/v2v/input_libvirtxml.ml
index 33e878e..1540798 100644
--- a/v2v/input_libvirtxml.ml
+++ b/v2v/input_libvirtxml.ml
@@ -101,6 +101,7 @@ let parse_libvirt_xml ?conn xml =
(* Use only the first <listen> configuration. *)
match xpath_string "listen[1]/@type" with
| None -> LNone
+ | Some "none" -> LNone
| Some "address" ->
(match xpath_string "listen[1]/@address" with
| None -> LNone
--
2.7.4
8 years, 1 month
[PATCH v2 0/3] New API - find_block
by Matteo Cafasso
v2:
- use boolean field in struct
- move refactoring to previous series
Matteo Cafasso (3):
New API: internal_find_block
New API: find_block
find_block: added API tests
daemon/tsk.c | 90 ++++++++++++++++++++++++++++++++++++++++++++
generator/actions.ml | 25 ++++++++++++
src/MAX_PROC_NR | 2 +-
src/tsk.c | 17 +++++++++
tests/tsk/Makefile.am | 1 +
tests/tsk/test-find-block.sh | 66 ++++++++++++++++++++++++++++++++
6 files changed, 200 insertions(+), 1 deletion(-)
create mode 100755 tests/tsk/test-find-block.sh
--
2.9.3
8 years, 1 month
[PATCH v7 0/4] New API - find_inode
by Matteo Cafasso
v7:
- Merge src/tsk.c refactoring patch with #4 of find_block series
Matteo Cafasso (4):
lib: logic refactoring
New API: internal_find_inode
New API: find_inode
find_inode: added API tests
daemon/tsk.c | 52 ++++++++++++++++++++++++++++++++++
generator/actions.ml | 21 ++++++++++++++
src/MAX_PROC_NR | 2 +-
src/tsk.c | 52 ++++++++++++++++++++++++++--------
tests/tsk/Makefile.am | 3 +-
tests/tsk/test-find-inode.sh | 66 ++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 182 insertions(+), 14 deletions(-)
create mode 100755 tests/tsk/test-find-inode.sh
--
2.9.3
8 years, 1 month
[PATCH 0/3] add crypto/LUKS support in some OCaml-based tools
by Pino Toscano
Hi,
this series refactors some guestfish code (not much), and exposes it
via Common_utils, so it is possible to decrypt LUKS partitions when
using virt-customize, virt-get-kernel, virt-sparsify, and virt-sysprep.
This brings them closer in features with C tools.
Most probably a couple more of other OCaml-based tools (virt-v2v to
convert encrypted guests, and virt-builder to use encrypted templates),
but that is left for implementation at a later time.
Thanks,
Pino Toscano (3):
fish: move disk decryption helpers in own file
mllib: expose disk decrypt functionalities
OCaml tools: add crypto support (RHBZ#1362649)
align/Makefile.am | 1 +
cat/Makefile.am | 1 +
customize/customize_main.ml | 5 +-
customize/virt-customize.pod | 12 +++++
df/Makefile.am | 1 +
diff/Makefile.am | 1 +
edit/Makefile.am | 1 +
fish/Makefile.am | 1 +
fish/decrypt.c | 102 +++++++++++++++++++++++++++++++++++++++++
fish/inspect.c | 68 ---------------------------
fish/options.h | 4 +-
format/Makefile.am | 1 +
fuse/Makefile.am | 1 +
get-kernel/get_kernel.ml | 5 +-
get-kernel/virt-get-kernel.pod | 12 +++++
inspector/Makefile.am | 1 +
mllib/Makefile.am | 3 ++
mllib/common_utils-c.c | 75 ++++++++++++++++++++++++++++++
mllib/common_utils.ml | 22 ++++++++-
mllib/common_utils.mli | 10 +++-
rescue/Makefile.am | 1 +
sparsify/cmdline.ml | 2 +-
sparsify/copying.ml | 3 ++
sparsify/in_place.ml | 3 ++
sparsify/virt-sparsify.pod | 12 +++++
sysprep/main.ml | 5 +-
sysprep/virt-sysprep.pod | 12 +++++
27 files changed, 290 insertions(+), 75 deletions(-)
create mode 100644 fish/decrypt.c
create mode 100644 mllib/common_utils-c.c
--
2.7.4
8 years, 1 month
[PATCH 0/4] New API - find_block
by Matteo Cafasso
This series is ready for review but requires the previous one to be merged first:
https://www.redhat.com/archives/libguestfs/2016-September/msg00101.html
The find_block API allows the User to search all the filesystem entries
referring to a given data block and returns a tsk_dirent structure
for each of them.
Use case examples:
- Check whether a block containing a deleted file has been re-used to store a new one.
- Map a certain area of a disk with the contained files.
Matteo Cafasso (4):
New API: internal_find_block
New API: find_block
find_block: added API tests
TSK: small refactoring
daemon/tsk.c | 89 ++++++++++++++++++++++++++++++++++++++++++++
generator/actions.ml | 25 +++++++++++++
src/MAX_PROC_NR | 2 +-
src/tsk.c | 65 +++++++++++++++++++-------------
tests/tsk/Makefile.am | 1 +
tests/tsk/test-find-block.sh | 66 ++++++++++++++++++++++++++++++++
6 files changed, 221 insertions(+), 27 deletions(-)
create mode 100755 tests/tsk/test-find-block.sh
--
2.9.3
8 years, 1 month