Parse dmesg to get more accurate memory.
[virt-p2v.git] / virt-p2v
index 4e27c77..922ad40 100755 (executable)
--- a/virt-p2v
+++ b/virt-p2v
@@ -117,6 +117,8 @@ let test_dialog_stages = false
 #load "mlnewt.cma";;
 #directory "+xml-light";;
 #load "xml-light.cma";;
+#directory "+libvirt";;
+#load "mllibvirt.cma";;
 
 open Unix
 open Printf
@@ -936,10 +938,32 @@ let rec main ttyname =
 
   (* Autodetect system memory. *)
   let system_memory =
-    let mem = shget "head -1 /proc/meminfo | awk '{print $2/1024}'" in
-    match mem with
-    | Some (mem::_) -> int_of_float (float_of_string mem)
-    | _ -> 256 in
+    (* Try to parse dmesg first to find the 'Memory:' report when
+     * the kernel booted.  If available, this can give us an
+     * indication of usable RAM on this system.
+     *)
+    let dmesg = shget "dmesg" in
+    try
+      let dmesg =
+       match dmesg with Some lines -> lines | None -> raise Not_found in
+      let line =
+       List.find (fun line -> String.starts_with line "Memory: ") dmesg in
+      let subs = Pcre.exec ~pat:"k/([[:digit:]]+)k available" line in
+      let mem = Pcre.get_substring subs 1 in
+      int_of_string mem / 1024
+    with
+      Not_found | Failure "int_of_string" ->
+       (* 'dmesg' can't be parsed.  The backup plan is to look
+        * at /proc/meminfo.
+        *)
+       let mem = shget "head -1 /proc/meminfo | awk '{print $2/1024}'" in
+       match mem with
+       | Some (mem::_) -> int_of_float (float_of_string mem)
+
+       (* For some reason even /proc/meminfo didn't work.  Just
+        * assume 256 MB instead.
+        *)
+       | _ -> 256 in
 
   (* Autodetect system # pCPUs. *)
   let system_nr_cpus =
@@ -1366,6 +1390,40 @@ let rec main ttyname =
        config_devices_to_send, config_root_filesystem, config_target
     ) in
 
+  (* Try to get the capabilities from the remote machine.  If we fail
+   * it doesn't matter too much.
+   *)
+  let capabilities =
+    try
+      if not config_target.tgt_libvirtd then raise Not_found;
+
+      let proto, path =
+       match config_target.tgt_hypervisor with
+       | Some Xen -> "xen", "/"
+       | Some (QEMU|KVM) -> "qemu", "/system"
+       | None -> raise Not_found in
+      let name =
+       sprintf "%s+ssh://%s@%s:%s%s"
+         proto config_ssh.ssh_username
+         config_ssh.ssh_host config_ssh.ssh_port path in
+      eprintf "fetch capabilities from %S\n%!" name;
+
+      let conn = Libvirt.Connect.connect_readonly ~name () in
+      let caps = Libvirt.Connect.get_capabilities conn in
+      Libvirt.Connect.close conn;
+
+      eprintf "capabilities:\n%s\n%!" caps;
+
+      Some caps
+    with
+    | Not_found -> None
+    | Libvirt.Virterror err ->
+       eprintf "libvirt error: %s\n%!" (Libvirt.Virterror.to_string err);
+       None
+    | Invalid_argument str ->
+       eprintf "libvirt error: %s\n%!" str;
+       None in
+
   (* In test mode, exit here before we do Bad Things to the developer's
    * hard disk.
    *)