WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-api

[Xen-API] [PATCH] Include VHD parents in VM metadata export

To: Xen-API <xen-api@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-API] [PATCH] Include VHD parents in VM metadata export
From: Ewan Mellor <ewan.mellor@xxxxxxxxxxxxx>
Date: Mon, 5 Jul 2010 12:08:55 +0100
Delivery-date: Mon, 05 Jul 2010 04:09:06 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-api-request@lists.xensource.com?subject=help>
List-id: Discussion of API issues surrounding Xen <xen-api.lists.xensource.com>
List-post: <mailto:xen-api@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-api>, <mailto:xen-api-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-api>, <mailto:xen-api-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-api-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mutt/1.5.18 (2008-05-17)
The VM metadata export handler (/export_metadata) will output the metadata
of a VM, all its snapshots, and all their attached VDIs.  However, it doesn't
walk the tree of VDIs defined by the VDI.sm_config["vhd_parent"] field.  For
a full-fidelity representation, having the parent VDIs is very useful.

This patch adds an "include_vhd_parents=(true|false)" option to the the
/export_metadata handler.  With this option on, the entire tree of VDIs is
exported.

This patch does not change the /export URL handler, does not change any
behaviour when include_vhd_parents is false or missing, and copes gracefully
with a missing or malformed vhd_parent entry.

Cheers,

Ewan.
--
diff -r 5be897c9bd07 ocaml/xapi/export.ml
--- a/ocaml/xapi/export.ml      Sat Jun 19 13:41:12 2010 +0100
+++ b/ocaml/xapi/export.ml      Mon Jul 05 11:58:53 2010 +0100
@@ -49,11 +49,31 @@
     incr counter;
     "Ref:" ^ (string_of_int this)
 
-let rec update_table ~__context ~include_snapshots ~preserve_power_state 
~table vm =
+let rec update_table ~__context ~include_snapshots ~preserve_power_state 
~include_vhd_parents ~table vm =
   let add r = 
          if not (Hashtbl.mem table (Ref.string_of r)) then
                  Hashtbl.add table (Ref.string_of r)(make_id ()) in
- 
+
+  let rec add_vdi v =
+    add v;
+    let r = Db.VDI.get_record ~__context ~self:v in
+    add r.API.vDI_SR;
+    if include_vhd_parents then
+      begin
+        let sm_config = r.API.vDI_sm_config in
+        if List.mem_assoc Xapi_globs.vhd_parent sm_config then
+          begin
+            let parent_uuid = List.assoc Xapi_globs.vhd_parent sm_config in
+            try
+              let parent_ref = Db.VDI.get_by_uuid ~__context ~uuid:parent_uuid
+              in add_vdi parent_ref
+            with _ ->
+              warn "VM.export_metadata: lookup of parent VDI %s failed"
+                parent_uuid
+          end
+      end
+  in
+
   if Db.is_valid_ref vm && not (Hashtbl.mem table (Ref.string_of vm)) then 
begin
   add vm;
   let vm = Db.VM.get_record ~__context ~self:vm in
@@ -69,22 +89,18 @@
               let vbd = Db.VBD.get_record ~__context ~self:vbd in
               if not(vbd.API.vBD_empty)
               then
-                let vdi = vbd.API.vBD_VDI in
-                add vdi;
-                let vdi = Db.VDI.get_record ~__context ~self:vdi in
-                add vdi.API.vDI_SR end) 
+                add_vdi vbd.API.vBD_VDI
+              end) 
        vm.API.vM_VBDs;
   (* If we need to include snapshots, update the table for VMs in the 
'snapshots' field *) 
   if include_snapshots then
          List.iter 
-                 (fun snap -> update_table ~__context ~include_snapshots:false 
~preserve_power_state ~table snap)
+                 (fun snap -> update_table ~__context ~include_snapshots:false 
~preserve_power_state ~include_vhd_parents ~table snap)
                  vm.API.vM_snapshots;
   (* If VM is suspended then add the suspend_VDI *)
   let vdi = vm.API.vM_suspend_VDI in
   if preserve_power_state && vm.API.vM_power_state = `Suspended && 
Db.is_valid_ref vdi then begin
-    add vdi;
-    let vdi = Db.VDI.get_record ~__context ~self:vdi in
-    add vdi.API.vDI_SR
+    add_vdi vdi
   end;
   (* Add also the guest metrics *)
   add vm.API.vM_guest_metrics;
@@ -94,7 +110,7 @@
   add vm.API.vM_affinity;
 
   (* Add the parent VM *)
-  if include_snapshots then update_table ~__context ~include_snapshots:false 
~preserve_power_state ~table vm.API.vM_parent
+  if include_snapshots then update_table ~__context ~include_snapshots:false 
~preserve_power_state ~include_vhd_parents ~table vm.API.vM_parent
   end
 
 (** Walk the graph of objects and update the table of Ref -> ids for each 
object we wish
@@ -271,9 +287,9 @@
 (* on normal export, do not include snapshot metadata;
    on metadata-export, include snapshots fields of the exported VM as well as 
the VM records of VMs 
    which are snapshots of the exported VM. *)
-let vm_metadata ~with_snapshot_metadata ~preserve_power_state ~__context ~vms =
+let vm_metadata ~with_snapshot_metadata ~preserve_power_state 
~include_vhd_parents ~__context ~vms =
   let table = create_table () in
-  List.iter (update_table ~__context ~include_snapshots:with_snapshot_metadata 
~preserve_power_state ~table) vms;
+  List.iter (update_table ~__context ~include_snapshots:with_snapshot_metadata 
~preserve_power_state ~include_vhd_parents ~table) vms;
   let objects = make_all ~with_snapshot_metadata ~preserve_power_state table 
__context in
   let header = { version = this_version __context;
                   objects = objects } in
@@ -287,19 +303,20 @@
        with _ -> "invalid"
 
 (** Export a VM's metadata only *)
-let export_metadata ~__context ~with_snapshot_metadata ~preserve_power_state 
~vms s =
+let export_metadata ~__context ~with_snapshot_metadata ~preserve_power_state 
~include_vhd_parents ~vms s =
        begin match vms with
        | [] -> failwith "need to specify at least one VM"
-       | [vm] -> info "VM.export_metadata: VM = %s; with_snapshot_metadata = 
'%b'; preserve_power_state = '%s" 
+       | [vm] -> info "VM.export_metadata: VM = %s; with_snapshot_metadata = 
'%b'; include_vhd_parents = '%b'; preserve_power_state = '%s" 
                                (string_of_vm ~__context vm)
                                with_snapshot_metadata
+                               include_vhd_parents
                                (string_of_bool preserve_power_state)
        | vms -> info "VM.export_metadata: VM = %s; with_snapshot_metadata = 
'%b'; preserve_power_state = '%s"
                                (String.concat ", " (List.map (string_of_vm 
~__context) vms)) 
                                with_snapshot_metadata
                                (string_of_bool preserve_power_state) end;
 
-       let _, ova_xml = vm_metadata ~with_snapshot_metadata 
~preserve_power_state ~__context ~vms in
+       let _, ova_xml = vm_metadata ~with_snapshot_metadata 
~preserve_power_state ~include_vhd_parents ~__context ~vms in
        let hdr = Tar.Header.make Xva.xml_filename (Bigbuffer.length ova_xml) in
        Tar.write_block hdr (fun s -> Tar.write_bigbuffer s ova_xml) s
 
@@ -308,7 +325,7 @@
          (string_of_vm ~__context vm_ref)
          (string_of_bool preserve_power_state);
 
-  let table, ova_xml = vm_metadata ~with_snapshot_metadata:false  
~preserve_power_state ~__context ~vms:[vm_ref] in
+  let table, ova_xml = vm_metadata ~with_snapshot_metadata:false  
~preserve_power_state ~include_vhd_parents:false ~__context ~vms:[vm_ref] in
 
   debug "Outputting ova.xml";
 
@@ -361,10 +378,16 @@
       Helpers.call_api_functions 
         ~__context (fun rpc session_id -> Client.VM.get_by_uuid rpc session_id 
uuid) 
 
+let bool_from_request ~__context (req: request) k =
+       if List.mem_assoc k req.query
+       then bool_of_string (List.assoc k req.query)
+       else false
+
 let export_all_vms_from_request ~__context (req: request) = 
-       if List.mem_assoc "all" req.query
-       then bool_of_string (List.assoc "all" req.query)
-       else false
+       bool_from_request ~__context req "all"
+
+let include_vhd_parents_from_request ~__context (req: request) = 
+       bool_from_request ~__context req "include_vhd_parents"
 
 let metadata_handler (req: request) s = 
        debug "metadata_handler called";
@@ -373,6 +396,7 @@
        (* Xapi_http.with_context always completes the task at the end *)
        Xapi_http.with_context "VM.export_metadata" req s
                (fun __context ->
+                       let include_vhd_parents = 
include_vhd_parents_from_request ~__context req in
                        let export_all = export_all_vms_from_request ~__context 
req in
 
                        (* Get the VM refs. In case of exporting the metadata 
of a particular VM, return a singleton list containing the vm ref.  *)
@@ -405,7 +429,7 @@
                        (* lock all the VMs before exporting their metadata *)
                        List.iter (fun vm -> lock_vm ~__context ~vm ~task_id 
`metadata_export) vm_refs;
                        finally
-                               (fun () -> export_metadata 
~with_snapshot_metadata:true ~preserve_power_state:true ~__context ~vms:vm_refs 
s)
+                               (fun () -> export_metadata 
~with_snapshot_metadata:true ~preserve_power_state:true ~include_vhd_parents 
~__context ~vms:vm_refs s)
                                (fun () ->
                                         List.iter (fun vm -> unlock_vm 
~__context ~vm ~task_id) vm_refs;
                                         Tar.write_end s);

Attachment: export-include-vhd-parents.patch
Description: Text Data

_______________________________________________
xen-api mailing list
xen-api@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/mailman/listinfo/xen-api
<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-API] [PATCH] Include VHD parents in VM metadata export, Ewan Mellor <=