[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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



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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.