Tomáš Golembiovský
2018-Feb-18 14:26 UTC
[Libguestfs] [PATCH 0/3] Make generated OVF more conforming to standard
The main reason for creating different OVF is that it can be used to create VM by oVirt REST API. The RHV export domain flavor cannot be used that way. Tomáš Golembiovský (3): v2v: tests: check generated OVF v2v: ovf: Create OVF more aligned with the standard v2v: vdsm: add --vdsm-fixed-ovf option v2v/cmdline.ml | 5 ++ v2v/create_ovf.ml | 108 ++++++++++++++++++++++--------- v2v/create_ovf.mli | 2 +- v2v/output_rhv.ml | 2 +- v2v/output_vdsm.ml | 9 ++- v2v/output_vdsm.mli | 1 + v2v/test-v2v-o-rhv.ovf.expected | 92 ++++++++++++++++++++++++++ v2v/test-v2v-o-rhv.sh | 20 ++++++ v2v/test-v2v-o-vdsm-options.ovf.expected | 92 ++++++++++++++++++++++++++ v2v/test-v2v-o-vdsm-options.sh | 19 +++++- v2v/virt-v2v.pod | 7 ++ 11 files changed, 322 insertions(+), 35 deletions(-) create mode 100644 v2v/test-v2v-o-rhv.ovf.expected create mode 100644 v2v/test-v2v-o-vdsm-options.ovf.expected -- 2.16.1
Tomáš Golembiovský
2018-Feb-18 14:26 UTC
[Libguestfs] [PATCH 1/3] v2v: tests: check generated OVF
Check the generated OVF for -o rhv and -o vdsm outputs. Variable UUIDs and date/times are filtered out. Make sure the the important UUIDs (disk, volume, VM) are where we think they should be. Signed-off-by: Tomáš Golembiovský <tgolembi@redhat.com> --- v2v/test-v2v-o-rhv.ovf.expected | 92 ++++++++++++++++++++++++++++++++ v2v/test-v2v-o-rhv.sh | 20 +++++++ v2v/test-v2v-o-vdsm-options.ovf.expected | 92 ++++++++++++++++++++++++++++++++ v2v/test-v2v-o-vdsm-options.sh | 16 ++++++ 4 files changed, 220 insertions(+) create mode 100644 v2v/test-v2v-o-rhv.ovf.expected create mode 100644 v2v/test-v2v-o-vdsm-options.ovf.expected diff --git a/v2v/test-v2v-o-rhv.ovf.expected b/v2v/test-v2v-o-rhv.ovf.expected new file mode 100644 index 000000000..8fb41d77f --- /dev/null +++ b/v2v/test-v2v-o-rhv.ovf.expected @@ -0,0 +1,92 @@ +<?xml version='1.0' encoding='utf-8'?> +<ovf:Envelope xmlns:rasd='http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData' xmlns:vssd='http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ovf='http://schemas.dmtf.org/ovf/envelope/1/' ovf:version='0.9'> + <!-- generated by virt-v2v 1.38.0 --> + <References> + <File ovf:href='#DISK_ID#/#VOL_ID#' ovf:id='#VOL_ID#' ovf:size='536870912' ovf:description='generated by virt-v2v 1.38.0'/> + </References> + <Section xsi:type='ovf:NetworkSection_Type'> + <Info>List of networks</Info> + <Network ovf:name='default'/> + </Section> + <Section xsi:type='ovf:DiskSection_Type'> + <Info>List of Virtual Disks</Info> + <Disk ovf:diskId='#VOL_ID#' ovf:size='1' ovf:fileRef='#DISK_ID#/#VOL_ID#' ovf:parentRef='' ovf:vm_snapshot_id='#UUID#' ovf:volume-format='RAW' ovf:volume-type='Sparse' ovf:format='http://en.wikipedia.org/wiki/Byte' ovf:disk-interface='IDE' ovf:disk-type='System' ovf:boot='True' ovf:actual_size='1'/> + </Section> + <Content ovf:id='out' xsi:type='ovf:VirtualSystem_Type'> + <Name>windows</Name> + <TemplateId>00000000-0000-0000-0000-000000000000</TemplateId> + <TemplateName>Blank</TemplateName> + <Description>generated by virt-v2v 1.38.0</Description> + <Domain/> + <CreationDate>#DATE#</CreationDate> + <IsInitilized>True</IsInitilized> + <IsAutoSuspend>False</IsAutoSuspend> + <TimeZone/> + <IsStateless>False</IsStateless> + <VmType>0</VmType> + <DefaultDisplayType>1</DefaultDisplayType> + <Section ovf:id='#VM_ID#' ovf:required='false' xsi:type='ovf:OperatingSystemSection_Type'> + <Info>Microsoft Windows 7 Phony Edition</Info> + <Description>Windows7</Description> + </Section> + <Section xsi:type='ovf:VirtualHardwareSection_Type'> + <Info>1 CPU, 1024 Memory</Info> + <Item> + <rasd:Caption>1 virtual cpu</rasd:Caption> + <rasd:Description>Number of virtual CPU</rasd:Description> + <rasd:InstanceId>1</rasd:InstanceId> + <rasd:ResourceType>3</rasd:ResourceType> + <rasd:num_of_sockets>1</rasd:num_of_sockets> + <rasd:cpu_per_socket>1</rasd:cpu_per_socket> + </Item> + <Item> + <rasd:Caption>1024 MB of memory</rasd:Caption> + <rasd:Description>Memory Size</rasd:Description> + <rasd:InstanceId>2</rasd:InstanceId> + <rasd:ResourceType>4</rasd:ResourceType> + <rasd:AllocationUnits>MegaBytes</rasd:AllocationUnits> + <rasd:VirtualQuantity>1024</rasd:VirtualQuantity> + </Item> + <Item> + <rasd:Caption>USB Controller</rasd:Caption> + <rasd:InstanceId>3</rasd:InstanceId> + <rasd:ResourceType>23</rasd:ResourceType> + <rasd:UsbPolicy>Disabled</rasd:UsbPolicy> + </Item> + <Item> + <rasd:Caption>Graphical Controller</rasd:Caption> + <rasd:InstanceId>#UUID#</rasd:InstanceId> + <rasd:ResourceType>20</rasd:ResourceType> + <Type>video</Type> + <rasd:VirtualQuantity>1</rasd:VirtualQuantity> + <rasd:Device>qxl</rasd:Device> + </Item> + <Item> + <rasd:Caption>Drive 1</rasd:Caption> + <rasd:InstanceId>#VOL_ID#</rasd:InstanceId> + <rasd:ResourceType>17</rasd:ResourceType> + <Type>disk</Type> + <rasd:HostResource>#DISK_ID#/#VOL_ID#</rasd:HostResource> + <rasd:Parent>00000000-0000-0000-0000-000000000000</rasd:Parent> + <rasd:Template>00000000-0000-0000-0000-000000000000</rasd:Template> + <rasd:ApplicationList/> + <rasd:StorageId>12345678-1234-1234-1234-123456789abc</rasd:StorageId> + <rasd:StoragePoolId>00000000-0000-0000-0000-000000000000</rasd:StoragePoolId> + <rasd:CreationDate>#DATE#</rasd:CreationDate> + <rasd:LastModified>#DATE#</rasd:LastModified> + <rasd:last_modified_date>#DATE#</rasd:last_modified_date> + <BootOrder>1</BootOrder> + </Item> + <Item> + <rasd:InstanceId>#UUID#</rasd:InstanceId> + <rasd:Caption>Ethernet adapter on default</rasd:Caption> + <rasd:ResourceType>10</rasd:ResourceType> + <rasd:ResourceSubType>1</rasd:ResourceSubType> + <Type>interface</Type> + <rasd:Connection>default</rasd:Connection> + <rasd:Name>eth0</rasd:Name> + <rasd:MACAddress>00:11:22:33:44:55</rasd:MACAddress> + </Item> + </Section> + </Content> +</ovf:Envelope> diff --git a/v2v/test-v2v-o-rhv.sh b/v2v/test-v2v-o-rhv.sh index 413e01348..d9fddf852 100755 --- a/v2v/test-v2v-o-rhv.sh +++ b/v2v/test-v2v-o-rhv.sh @@ -60,4 +60,24 @@ test -f $vol popd +# Compare resulting OVF +VM_ID=$(basename $(ls -1d $d/12345678-1234-1234-1234-123456789abc/master/vms/*)) +DISK_ID=$(basename $(ls -1d $d/12345678-1234-1234-1234-123456789abc/images/*)) +VOL_ID=$(basename $(ls -1d $d/12345678-1234-1234-1234-123456789abc/images/$DISK_ID/*.meta) .meta) +OVF=$(ls -1d $d/12345678-1234-1234-1234-123456789abc/master/vms/$VM_ID/$VM_ID.ovf) + +RE_UUID='\<[0-9a-fA-F]\{8\}-[0-9a-fA-F]\{4\}-[0-9a-fA-F]\{4\}-[0-9a-fA-F]\{4\}-[0-9a-fA-F]\{12\}\>' + +# Filter variable strings +sed -i \ + -e "s/$DISK_ID/#DISK_ID#/g" \ + -e "s/$VM_ID/#VM_ID#/g" \ + -e "s/$VOL_ID/#VOL_ID#/g" \ + -e 's/<rasd:InstanceId>'"$RE_UUID"'</<rasd:InstanceId>#UUID#</' \ + -e 's/<\(rasd:\)\?\(CreationDate\|LastModified\|last_modified_date\)>[^<]*</<\1\2>#DATE#</' \ + -e 's/\<ovf:vm_snapshot_id='"'$RE_UUID'/ovf:vm_snapshot_id='#UUID#'/g" \ + "$OVF" + +diff -u test-v2v-o-rhv.ovf.expected "$OVF" + rm -r $d diff --git a/v2v/test-v2v-o-vdsm-options.ovf.expected b/v2v/test-v2v-o-vdsm-options.ovf.expected new file mode 100644 index 000000000..fafd0dd53 --- /dev/null +++ b/v2v/test-v2v-o-vdsm-options.ovf.expected @@ -0,0 +1,92 @@ +<?xml version='1.0' encoding='utf-8'?> +<ovf:Envelope xmlns:rasd='http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData' xmlns:vssd='http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ovf='http://schemas.dmtf.org/ovf/envelope/1/' ovf:version='0.9'> + <!-- generated by virt-v2v 1.38.0 --> + <References> + <File ovf:href='IMAGE/VOL' ovf:id='VOL' ovf:size='536870912' ovf:description='generated by virt-v2v 1.38.0'/> + </References> + <Section xsi:type='ovf:NetworkSection_Type'> + <Info>List of networks</Info> + <Network ovf:name='default'/> + </Section> + <Section xsi:type='ovf:DiskSection_Type'> + <Info>List of Virtual Disks</Info> + <Disk ovf:diskId='VOL' ovf:size='1' ovf:fileRef='IMAGE/VOL' ovf:parentRef='' ovf:vm_snapshot_id='#UUID#' ovf:volume-format='COW' ovf:volume-type='Sparse' ovf:format='http://en.wikipedia.org/wiki/Byte' ovf:disk-interface='IDE' ovf:disk-type='System' ovf:boot='True' ovf:actual_size='1'/> + </Section> + <Content ovf:id='out' xsi:type='ovf:VirtualSystem_Type'> + <Name>windows</Name> + <TemplateId>00000000-0000-0000-0000-000000000000</TemplateId> + <TemplateName>Blank</TemplateName> + <Description>generated by virt-v2v 1.38.0</Description> + <Domain/> + <CreationDate>#DATE#</CreationDate> + <IsInitilized>True</IsInitilized> + <IsAutoSuspend>False</IsAutoSuspend> + <TimeZone/> + <IsStateless>False</IsStateless> + <VmType>0</VmType> + <DefaultDisplayType>1</DefaultDisplayType> + <Section ovf:id='VM' ovf:required='false' xsi:type='ovf:OperatingSystemSection_Type'> + <Info>Microsoft Windows 7 Phony Edition</Info> + <Description>Windows7</Description> + </Section> + <Section xsi:type='ovf:VirtualHardwareSection_Type'> + <Info>1 CPU, 1024 Memory</Info> + <Item> + <rasd:Caption>1 virtual cpu</rasd:Caption> + <rasd:Description>Number of virtual CPU</rasd:Description> + <rasd:InstanceId>1</rasd:InstanceId> + <rasd:ResourceType>3</rasd:ResourceType> + <rasd:num_of_sockets>1</rasd:num_of_sockets> + <rasd:cpu_per_socket>1</rasd:cpu_per_socket> + </Item> + <Item> + <rasd:Caption>1024 MB of memory</rasd:Caption> + <rasd:Description>Memory Size</rasd:Description> + <rasd:InstanceId>2</rasd:InstanceId> + <rasd:ResourceType>4</rasd:ResourceType> + <rasd:AllocationUnits>MegaBytes</rasd:AllocationUnits> + <rasd:VirtualQuantity>1024</rasd:VirtualQuantity> + </Item> + <Item> + <rasd:Caption>USB Controller</rasd:Caption> + <rasd:InstanceId>3</rasd:InstanceId> + <rasd:ResourceType>23</rasd:ResourceType> + <rasd:UsbPolicy>Disabled</rasd:UsbPolicy> + </Item> + <Item> + <rasd:Caption>Graphical Controller</rasd:Caption> + <rasd:InstanceId>#UUID#</rasd:InstanceId> + <rasd:ResourceType>20</rasd:ResourceType> + <Type>video</Type> + <rasd:VirtualQuantity>1</rasd:VirtualQuantity> + <rasd:Device>qxl</rasd:Device> + </Item> + <Item> + <rasd:Caption>Drive 1</rasd:Caption> + <rasd:InstanceId>VOL</rasd:InstanceId> + <rasd:ResourceType>17</rasd:ResourceType> + <Type>disk</Type> + <rasd:HostResource>IMAGE/VOL</rasd:HostResource> + <rasd:Parent>00000000-0000-0000-0000-000000000000</rasd:Parent> + <rasd:Template>00000000-0000-0000-0000-000000000000</rasd:Template> + <rasd:ApplicationList/> + <rasd:StorageId>12345678-1234-1234-1234-123456789abc</rasd:StorageId> + <rasd:StoragePoolId>00000000-0000-0000-0000-000000000000</rasd:StoragePoolId> + <rasd:CreationDate>#DATE#</rasd:CreationDate> + <rasd:LastModified>#DATE#</rasd:LastModified> + <rasd:last_modified_date>#DATE#</rasd:last_modified_date> + <BootOrder>1</BootOrder> + </Item> + <Item> + <rasd:InstanceId>#UUID#</rasd:InstanceId> + <rasd:Caption>Ethernet adapter on default</rasd:Caption> + <rasd:ResourceType>10</rasd:ResourceType> + <rasd:ResourceSubType>1</rasd:ResourceSubType> + <Type>interface</Type> + <rasd:Connection>default</rasd:Connection> + <rasd:Name>eth0</rasd:Name> + <rasd:MACAddress>00:11:22:33:44:55</rasd:MACAddress> + </Item> + </Section> + </Content> +</ovf:Envelope> diff --git a/v2v/test-v2v-o-vdsm-options.sh b/v2v/test-v2v-o-vdsm-options.sh index 1da252f17..509a12499 100755 --- a/v2v/test-v2v-o-vdsm-options.sh +++ b/v2v/test-v2v-o-vdsm-options.sh @@ -73,4 +73,20 @@ qemu-img info VOL | grep 'compat: 1.1' popd +# Compare resulting OVF +OVF="$d/12345678-1234-1234-1234-123456789abc/master/vms/VM/VM.ovf" + +RE_UUID='\<[0-9a-fA-F]\{8\}-[0-9a-fA-F]\{4\}-[0-9a-fA-F]\{4\}-[0-9a-fA-F]\{4\}-[0-9a-fA-F]\{12\}\>' + +# Filter variable strings +sed -i \ + -e 's/<rasd:InstanceId>'"$RE_UUID"'</<rasd:InstanceId>#UUID#</' \ + -e 's/<\(rasd:\)\?\(CreationDate\|LastModified\|last_modified_date\)>[^<]*</<\1\2>#DATE#</' \ + -e 's/\<ovf:vm_snapshot_id='"'$RE_UUID'/ovf:vm_snapshot_id='#UUID#'/g" \ + "$OVF" + + +diff -u test-v2v-o-vdsm-options.ovf.expected \ + "$OVF" + rm -r $d -- 2.16.1
Tomáš Golembiovský
2018-Feb-18 14:26 UTC
[Libguestfs] [PATCH 2/3] v2v: ovf: Create OVF more aligned with the standard
For historical reasons the OVF used in RHV export domain contains some deviations from the OVF standard. The format used in -o rhv has to remain fixed but for -o vdsm and we could produce much nicer OVF. This patch serves as a preparatory step to this. The main reason for creating different OVF is that it can be used to create VM by oVirt REST API. The RHV export domain flavor cannot be used that way. For now the virt-v2v behavior is unchanged. The modified output will be enabled in some later patch. Signed-off-by: Tomáš Golembiovský <tgolembi@redhat.com> --- v2v/create_ovf.ml | 108 ++++++++++++++++++++++++++++++++++++++--------------- v2v/create_ovf.mli | 2 +- v2v/output_rhv.ml | 2 +- v2v/output_vdsm.ml | 3 +- 4 files changed, 82 insertions(+), 33 deletions(-) diff --git a/v2v/create_ovf.ml b/v2v/create_ovf.ml index f60ca9ed3..8d16cf175 100644 --- a/v2v/create_ovf.ml +++ b/v2v/create_ovf.ml @@ -269,7 +269,7 @@ let create_meta_files output_alloc sd_uuid image_uuids targets (* Create the OVF file. *) let rec create_ovf source targets guestcaps inspect - output_alloc sd_uuid image_uuids vol_uuids vm_uuid + output_alloc sd_uuid image_uuids vol_uuids vm_uuid rhv_export_flavor assert (List.length targets = List.length vol_uuids); let memsize_mb = source.s_memory /^ 1024L /^ 1024L in @@ -288,12 +288,22 @@ let rec create_ovf source targets guestcaps inspect ] [ Comment generated_by; e "References" [] []; - e "Section" ["xsi:type", "ovf:NetworkSection_Type"] [ - e "Info" [] [PCData "List of networks"] - ]; - e "Section" ["xsi:type", "ovf:DiskSection_Type"] [ - e "Info" [] [PCData "List of Virtual Disks"] - ]; + if rhv_export_flavor then + e "Section" ["xsi:type", "ovf:NetworkSection_Type"] [ + e "Info" [] [PCData "List of networks"] + ] + else + e "NetworkSection" [] [ + e "Info" [] [PCData "List of networks"] + ]; + if rhv_export_flavor then + e "Section" ["xsi:type", "ovf:DiskSection_Type"] [ + e "Info" [] [PCData "List of Virtual Disks"] + ] + else + e "DiskSection" [] [ + e "Info" [] [PCData "List of Virtual Disks"] + ]; let content_subnodes = ref [ e "Name" [] [PCData source.s_name]; @@ -326,11 +336,18 @@ let rec create_ovf source targets guestcaps inspect ); List.push_back content_subnodes ( - e "Section" ["ovf:id", vm_uuid; "ovf:required", "false"; - "xsi:type", "ovf:OperatingSystemSection_Type"] [ + let osinfo_subnodes = [ e "Info" [] [PCData inspect.i_product_name]; e "Description" [] [PCData ostype]; - ] + ] in + if rhv_export_flavor then + e "Section" ["ovf:id", vm_uuid; "ovf:required", "false"; + "xsi:type", "ovf:OperatingSystemSection_Type"] + osinfo_subnodes + else + e "OperatingSystemSection" ["ovf:id", vm_uuid; + "ovf:required", "false"] + osinfo_subnodes ); let virtual_hardware_section_items = ref [ @@ -424,16 +441,23 @@ let rec create_ovf source targets guestcaps inspect ); List.push_back content_subnodes ( - e "Section" ["xsi:type", "ovf:VirtualHardwareSection_Type"] - !virtual_hardware_section_items + if rhv_export_flavor then + e "Section" ["xsi:type", "ovf:VirtualHardwareSection_Type"] + !virtual_hardware_section_items + else + e "VirtualHardwareSection" [] !virtual_hardware_section_items ); - e "Content" ["ovf:id", "out"; "xsi:type", "ovf:VirtualSystem_Type"] - !content_subnodes + if rhv_export_flavor then + e "Content" ["ovf:id", "out"; "xsi:type", "ovf:VirtualSystem_Type"] + !content_subnodes + else + e "VirtualSystem" ["ovf:id", "out"] !content_subnodes ] in (* Add disks to the OVF XML. *) - add_disks targets guestcaps output_alloc sd_uuid image_uuids vol_uuids ovf; + add_disks targets guestcaps output_alloc sd_uuid image_uuids vol_uuids + rhv_export_flavor ovf; (* Old virt-v2v ignored removable media. XXX *) @@ -462,20 +486,30 @@ let rec create_ovf source targets guestcaps inspect ovf (* This modifies the OVF DOM, adding a section for each disk. *) -and add_disks targets guestcaps output_alloc sd_uuid image_uuids vol_uuids ovf +and add_disks targets guestcaps output_alloc sd_uuid image_uuids vol_uuids + rhv_export_flavor ovf let references let nodes = path_to_nodes ovf ["ovf:Envelope"; "References"] in match nodes with | [] | _::_::_ -> assert false | [node] -> node in let disk_section - let sections = path_to_nodes ovf ["ovf:Envelope"; "Section"] in - try find_node_by_attr sections ("xsi:type", "ovf:DiskSection_Type") - with Not_found -> assert false in + let nodes = path_to_nodes ovf ["ovf:Envelope"; "DiskSection"] in + match nodes with + | [node] -> node + | [] | _::_::_ -> let sections + path_to_nodes ovf ["ovf:Envelope"; "Section"] in + try find_node_by_attr sections ("xsi:type", "ovf:DiskSection_Type") + with Not_found -> assert false in let virtualhardware_section - let sections = path_to_nodes ovf ["ovf:Envelope"; "Content"; "Section"] in - try find_node_by_attr sections ("xsi:type", "ovf:VirtualHardwareSection_Type") - with Not_found -> assert false in + let nodes = path_to_nodes ovf + ["ovf:Envelope"; "VirtualSystem"; "VirtualHardwareSection"] in + match nodes with + | [node] -> node + | [] | _::_::_ -> let sections + path_to_nodes ovf ["ovf:Envelope"; "Content"; "Section"] in + try find_node_by_attr sections ("xsi:type", "ovf:VirtualHardwareSection_Type") + with Not_found -> assert false in (* Iterate over the disks, adding them to the OVF document. *) List.iteri ( @@ -489,7 +523,12 @@ and add_disks targets guestcaps output_alloc sd_uuid image_uuids vol_uuids ovf let is_bootable_drive = i == 0 in let boot_order = i+1 in - let fileref = sprintf "%s/%s" image_uuid vol_uuid in + let fileref + if rhv_export_flavor then + sprintf "%s/%s" image_uuid vol_uuid + else + vol_uuid + in (* ovf:size and ovf:actual_size fields are integer GBs. If you * use floating point numbers then RHV will fail to parse them. @@ -535,7 +574,7 @@ and add_disks targets guestcaps output_alloc sd_uuid image_uuids vol_uuids ovf (* Add disk to DiskSection. *) let disk let attrs = ref [ - "ovf:diskId", vol_uuid; + "ovf:diskId", if rhv_export_flavor then vol_uuid else image_uuid ; "ovf:size", Int64.to_string size_gb; "ovf:fileRef", fileref; "ovf:parentRef", ""; @@ -595,13 +634,22 @@ and add_disks targets guestcaps output_alloc sd_uuid image_uuids vol_uuids ovf (* This modifies the OVF DOM, adding a section for each NIC. *) and add_networks nics guestcaps ovf let network_section - let sections = path_to_nodes ovf ["ovf:Envelope"; "Section"] in - try find_node_by_attr sections ("xsi:type", "ovf:NetworkSection_Type") - with Not_found -> assert false in + let nodes = path_to_nodes ovf ["ovf:Envelope"; "NetworkSection"] in + match nodes with + | [node] -> node + | [] | _::_::_ -> let sections + path_to_nodes ovf ["ovf:Envelope"; "Section"] in + try find_node_by_attr sections ("xsi:type", "ovf:NetworkSection_Type") + with Not_found -> assert false in let virtualhardware_section - let sections = path_to_nodes ovf ["ovf:Envelope"; "Content"; "Section"] in - try find_node_by_attr sections ("xsi:type", "ovf:VirtualHardwareSection_Type") - with Not_found -> assert false in + let nodes = path_to_nodes ovf + ["ovf:Envelope"; "VirtualSystem"; "VirtualHardwareSection"] in + match nodes with + | [node] -> node + | [] | _::_::_ -> let sections + path_to_nodes ovf ["ovf:Envelope"; "Content"; "Section"] in + try find_node_by_attr sections ("xsi:type", "ovf:VirtualHardwareSection_Type") + with Not_found -> assert false in (* Iterate over the NICs, adding them to the OVF document. *) List.iteri ( diff --git a/v2v/create_ovf.mli b/v2v/create_ovf.mli index 07e8af6a0..43a8cfc71 100644 --- a/v2v/create_ovf.mli +++ b/v2v/create_ovf.mli @@ -25,7 +25,7 @@ create OVF for another target management system then we would need to heavily modify or even duplicate this code. *) -val create_ovf : Types.source -> Types.target list -> Types.guestcaps -> Types.inspect -> Types.output_allocation -> string -> string list -> string list -> string -> DOM.doc +val create_ovf : Types.source -> Types.target list -> Types.guestcaps -> Types.inspect -> Types.output_allocation -> string -> string list -> string list -> string -> bool -> DOM.doc (** Create the OVF file. Actually a {!DOM} document is created, not a file. It can be written diff --git a/v2v/output_rhv.ml b/v2v/output_rhv.ml index 0b732e4cf..77e7a627e 100644 --- a/v2v/output_rhv.ml +++ b/v2v/output_rhv.ml @@ -275,7 +275,7 @@ object (* Create the metadata. *) let ovf = Create_ovf.create_ovf source targets guestcaps inspect - output_alloc esd_uuid image_uuids vol_uuids vm_uuid in + output_alloc esd_uuid image_uuids vol_uuids vm_uuid true in (* Write it to the metadata file. *) let dir = esd_mp // esd_uuid // "master" // "vms" // vm_uuid in diff --git a/v2v/output_vdsm.ml b/v2v/output_vdsm.ml index 828ad7bda..b2188dd8b 100644 --- a/v2v/output_vdsm.ml +++ b/v2v/output_vdsm.ml @@ -175,7 +175,8 @@ object output_alloc dd_uuid vdsm_params.image_uuids vdsm_params.vol_uuids - vdsm_params.vm_uuid in + vdsm_params.vm_uuid + true in (* Write it to the metadata file. *) let file = vdsm_params.ovf_output // vdsm_params.vm_uuid ^ ".ovf" in -- 2.16.1
Tomáš Golembiovský
2018-Feb-18 14:26 UTC
[Libguestfs] [PATCH 3/3] v2v: vdsm: add --vdsm-fixed-ovf option
Add option for -o vdsm that enables output of the modified OVF. oVirt engine should already be able to consume the OVF, but let's not take any chances and enable it only by command line argument. It can be made default later when it receives proper testing. Signed-off-by: Tomáš Golembiovský <tgolembi@redhat.com> --- v2v/cmdline.ml | 5 +++++ v2v/output_vdsm.ml | 8 ++++++-- v2v/output_vdsm.mli | 1 + v2v/test-v2v-o-vdsm-options.ovf.expected | 26 +++++++++++++------------- v2v/test-v2v-o-vdsm-options.sh | 3 ++- v2v/virt-v2v.pod | 7 +++++++ 6 files changed, 34 insertions(+), 16 deletions(-) diff --git a/v2v/cmdline.ml b/v2v/cmdline.ml index efad080cc..409d5dfab 100644 --- a/v2v/cmdline.ml +++ b/v2v/cmdline.ml @@ -75,6 +75,7 @@ let parse_cmdline () let vddk_vimapiver = ref None in let vdsm_vm_uuid = ref None in let vdsm_ovf_output = ref None in (* default "." *) + let vdsm_fixed_ovf = ref false in let vdsm_compat = ref "0.10" in let set_vdsm_compat s = vdsm_compat := s in @@ -251,6 +252,8 @@ let parse_cmdline () s_"Output VM UUID"; [ L"vdsm-ovf-output" ], Getopt.String ("-", set_string_option_once "--vdsm-ovf-output" vdsm_ovf_output), s_"Output OVF file"; + [ L"vdsm-fixed-ovf" ], Getopt.Set vdsm_fixed_ovf, + s_"Produce OVF that is more conforming to the standard"; [ L"vmtype" ], Getopt.String ("-", vmtype_warning), s_"Ignored for backwards compatibility"; ] in @@ -327,6 +330,7 @@ read the man page virt-v2v(1). let vdsm_vol_uuids = List.rev !vdsm_vol_uuids in let vdsm_vm_uuid = !vdsm_vm_uuid in let vdsm_ovf_output = Option.default "." !vdsm_ovf_output in + let vdsm_fixed_ovf = !vdsm_fixed_ovf in (* No arguments and machine-readable mode? Print out some facts * about what this binary supports. @@ -542,6 +546,7 @@ read the man page virt-v2v(1). vm_uuid = vdsm_vm_uuid; ovf_output = vdsm_ovf_output; compat = vdsm_compat; + legacy_ovf = not vdsm_fixed_ovf; } in Output_vdsm.output_vdsm os vdsm_params output_alloc, output_format, output_alloc in diff --git a/v2v/output_vdsm.ml b/v2v/output_vdsm.ml index b2188dd8b..9d0568f3e 100644 --- a/v2v/output_vdsm.ml +++ b/v2v/output_vdsm.ml @@ -32,6 +32,7 @@ type vdsm_params = { vm_uuid : string; ovf_output : string; compat : string; + legacy_ovf : bool; } class output_vdsm os vdsm_params output_alloc @@ -39,7 +40,7 @@ object inherit output method as_options - sprintf "-o vdsm -os %s%s%s --vdsm-vm-uuid %s --vdsm-ovf-output %s%s" os + sprintf "-o vdsm -os %s%s%s --vdsm-vm-uuid %s --vdsm-ovf-output %s%s%s" os (String.concat "" (List.map (sprintf " --vdsm-image-uuid %s") vdsm_params.image_uuids)) (String.concat "" @@ -49,6 +50,9 @@ object (match vdsm_params.compat with | "0.10" -> "" (* currently this is the default, so don't print it *) | s -> sprintf " --vdsm-compat=%s" s) + (match vdsm_params.legacy_ovf with + | true -> "" (* currently this is the default, so don't print it *) + | false -> "--vdsm-fixed-ovf") method supported_firmware = [ TargetBIOS ] @@ -176,7 +180,7 @@ object vdsm_params.image_uuids vdsm_params.vol_uuids vdsm_params.vm_uuid - true in + vdsm_params.legacy_ovf in (* Write it to the metadata file. *) let file = vdsm_params.ovf_output // vdsm_params.vm_uuid ^ ".ovf" in diff --git a/v2v/output_vdsm.mli b/v2v/output_vdsm.mli index 95a84ee46..24793596d 100644 --- a/v2v/output_vdsm.mli +++ b/v2v/output_vdsm.mli @@ -24,6 +24,7 @@ type vdsm_params = { vm_uuid : string; (* --vdsm-vm-uuid *) ovf_output : string; (* --vdsm-ovf-output *) compat : string; (* --vdsm-compat=0.10|1.1 *) + legacy_ovf : bool; (* --vdsm-fixed-ovf *) } (** Miscellaneous extra command line parameters used by VDSM. *) diff --git a/v2v/test-v2v-o-vdsm-options.ovf.expected b/v2v/test-v2v-o-vdsm-options.ovf.expected index fafd0dd53..2934a6dd3 100644 --- a/v2v/test-v2v-o-vdsm-options.ovf.expected +++ b/v2v/test-v2v-o-vdsm-options.ovf.expected @@ -2,17 +2,17 @@ <ovf:Envelope xmlns:rasd='http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData' xmlns:vssd='http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ovf='http://schemas.dmtf.org/ovf/envelope/1/' ovf:version='0.9'> <!-- generated by virt-v2v 1.38.0 --> <References> - <File ovf:href='IMAGE/VOL' ovf:id='VOL' ovf:size='536870912' ovf:description='generated by virt-v2v 1.38.0'/> + <File ovf:href='VOL' ovf:id='VOL' ovf:size='536870912' ovf:description='generated by virt-v2v 1.38.0'/> </References> - <Section xsi:type='ovf:NetworkSection_Type'> + <NetworkSection> <Info>List of networks</Info> <Network ovf:name='default'/> - </Section> - <Section xsi:type='ovf:DiskSection_Type'> + </NetworkSection> + <DiskSection> <Info>List of Virtual Disks</Info> - <Disk ovf:diskId='VOL' ovf:size='1' ovf:fileRef='IMAGE/VOL' ovf:parentRef='' ovf:vm_snapshot_id='#UUID#' ovf:volume-format='COW' ovf:volume-type='Sparse' ovf:format='http://en.wikipedia.org/wiki/Byte' ovf:disk-interface='IDE' ovf:disk-type='System' ovf:boot='True' ovf:actual_size='1'/> - </Section> - <Content ovf:id='out' xsi:type='ovf:VirtualSystem_Type'> + <Disk ovf:diskId='IMAGE' ovf:size='1' ovf:fileRef='VOL' ovf:parentRef='' ovf:vm_snapshot_id='#UUID#' ovf:volume-format='COW' ovf:volume-type='Sparse' ovf:format='http://en.wikipedia.org/wiki/Byte' ovf:disk-interface='IDE' ovf:disk-type='System' ovf:boot='True' ovf:actual_size='1'/> + </DiskSection> + <VirtualSystem ovf:id='out'> <Name>windows</Name> <TemplateId>00000000-0000-0000-0000-000000000000</TemplateId> <TemplateName>Blank</TemplateName> @@ -25,11 +25,11 @@ <IsStateless>False</IsStateless> <VmType>0</VmType> <DefaultDisplayType>1</DefaultDisplayType> - <Section ovf:id='VM' ovf:required='false' xsi:type='ovf:OperatingSystemSection_Type'> + <OperatingSystemSection ovf:id='VM' ovf:required='false'> <Info>Microsoft Windows 7 Phony Edition</Info> <Description>Windows7</Description> - </Section> - <Section xsi:type='ovf:VirtualHardwareSection_Type'> + </OperatingSystemSection> + <VirtualHardwareSection> <Info>1 CPU, 1024 Memory</Info> <Item> <rasd:Caption>1 virtual cpu</rasd:Caption> @@ -66,7 +66,7 @@ <rasd:InstanceId>VOL</rasd:InstanceId> <rasd:ResourceType>17</rasd:ResourceType> <Type>disk</Type> - <rasd:HostResource>IMAGE/VOL</rasd:HostResource> + <rasd:HostResource>VOL</rasd:HostResource> <rasd:Parent>00000000-0000-0000-0000-000000000000</rasd:Parent> <rasd:Template>00000000-0000-0000-0000-000000000000</rasd:Template> <rasd:ApplicationList/> @@ -87,6 +87,6 @@ <rasd:Name>eth0</rasd:Name> <rasd:MACAddress>00:11:22:33:44:55</rasd:MACAddress> </Item> - </Section> - </Content> + </VirtualHardwareSection> + </VirtualSystem> </ovf:Envelope> diff --git a/v2v/test-v2v-o-vdsm-options.sh b/v2v/test-v2v-o-vdsm-options.sh index 509a12499..03a30de46 100755 --- a/v2v/test-v2v-o-vdsm-options.sh +++ b/v2v/test-v2v-o-vdsm-options.sh @@ -54,7 +54,8 @@ $VG virt-v2v --debug-gc \ --vdsm-vol-uuid VOL \ --vdsm-vm-uuid VM \ --vdsm-ovf-output $d/12345678-1234-1234-1234-123456789abc/master/vms/VM \ - --vdsm-compat=1.1 + --vdsm-compat=1.1 \ + --vdsm-fixed-ovf # Test the OVF metadata was created. test -f $d/12345678-1234-1234-1234-123456789abc/master/vms/VM/VM.ovf diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod index b2face339..9a047d390 100644 --- a/v2v/virt-v2v.pod +++ b/v2v/virt-v2v.pod @@ -759,6 +759,13 @@ hex digit can be C<0-9> or C<a-f>), conforming to S<OSF DCE 1.1>. These options can only be used with I<-o vdsm>. +=item B<--vdsm-fixed-ovf> + +OVF generated for RHV contains some deviations from the standard (notably some +sections are introduced by different elements). This option instruct virt-v2v +to create more conforming version of the OVF. This may later become the +default. + =item B<-v> =item B<--verbose> -- 2.16.1
Richard W.M. Jones
2018-Feb-20 10:08 UTC
Re: [Libguestfs] [PATCH 2/3] v2v: ovf: Create OVF more aligned with the standard
On Sun, Feb 18, 2018 at 03:26:09PM +0100, Tomáš Golembiovský wrote:> (* Create the OVF file. *) > let rec create_ovf source targets guestcaps inspect > - output_alloc sd_uuid image_uuids vol_uuids vm_uuid > + output_alloc sd_uuid image_uuids vol_uuids vm_uuid rhv_export_flavorrhv_export_flavor is a boolean here. TBH I'd use something a bit more descriptive such as a variant: type ovf_flavour | RHVExportStorageDomain | OVFStandard and then code like this becomes:> + if rhv_export_flavor then > + e "Section" ["xsi:type", "ovf:NetworkSection_Type"] [ > + e "Info" [] [PCData "List of networks"] > + ] > + else > + e "NetworkSection" [] [ > + e "Info" [] [PCData "List of networks"] > + ];(match ovf_flavour with | RHVExportStorageDomain -> ... | OVFStandard -> ... ) Note the parentheses around match which are required. This is implemented by OCaml in exactly the same way as a boolean so there is no loss of efficiency.> let disk_section > - let sections = path_to_nodes ovf ["ovf:Envelope"; "Section"] in > - try find_node_by_attr sections ("xsi:type", "ovf:DiskSection_Type") > - with Not_found -> assert false in > + let nodes = path_to_nodes ovf ["ovf:Envelope"; "DiskSection"] in > + match nodes with > + | [node] -> node > + | [] | _::_::_ -> let sections > + path_to_nodes ovf ["ovf:Envelope"; "Section"] in > + try find_node_by_attr sections ("xsi:type", "ovf:DiskSection_Type") > + with Not_found -> assert false inThis pattern is repeated several times but I'm not really clear what you're trying to do. Isn't it an error if several nodes match the first path? In any case how about abstracting the pattern into a new function: (* Add a comment explaining exactly what it does *) let get_section path1 path2 path2_attr let nodes = path_to_nodes path1 in match nodes with | [node] -> node | _::_::_ -> assert false (* an error? *) | [] -> let nodes = path_to_nodes ovf path2 in try find_node_by_attr nodes path2_attr with Not_found -> assert false in (* ... *) let disk_section = get_section ["ovf:Envelope"; "Section"] ["ovf:Envelope"; "DiskSection"] ("xsi:type", "ovf:DiskSection_Type") in Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 100 libraries supported. http://fedoraproject.org/wiki/MinGW
Richard W.M. Jones
2018-Feb-20 10:10 UTC
Re: [Libguestfs] [PATCH 3/3] v2v: vdsm: add --vdsm-fixed-ovf option
On Sun, Feb 18, 2018 at 03:26:10PM +0100, Tomáš Golembiovský wrote:> Add option for -o vdsm that enables output of the modified OVF. oVirt > engine should already be able to consume the OVF, but let's not take any > chances and enable it only by command line argument. It can be made > default later when it receives proper testing. > > Signed-off-by: Tomáš Golembiovský <tgolembi@redhat.com> > --- > v2v/cmdline.ml | 5 +++++ > v2v/output_vdsm.ml | 8 ++++++-- > v2v/output_vdsm.mli | 1 + > v2v/test-v2v-o-vdsm-options.ovf.expected | 26 +++++++++++++------------- > v2v/test-v2v-o-vdsm-options.sh | 3 ++- > v2v/virt-v2v.pod | 7 +++++++ > 6 files changed, 34 insertions(+), 16 deletions(-) > > diff --git a/v2v/cmdline.ml b/v2v/cmdline.ml > index efad080cc..409d5dfab 100644 > --- a/v2v/cmdline.ml > +++ b/v2v/cmdline.ml > @@ -75,6 +75,7 @@ let parse_cmdline () > let vddk_vimapiver = ref None in > let vdsm_vm_uuid = ref None in > let vdsm_ovf_output = ref None in (* default "." *) > + let vdsm_fixed_ovf = ref false inThe "fixed" OVF means standard OVF? If so let's call it vdsm_ovf_standard, which ties in with the suggestion in the previous patch that we don't use a boolean but use a more descriptive type.> let vdsm_compat = ref "0.10" in > let set_vdsm_compat s = vdsm_compat := s in > @@ -251,6 +252,8 @@ let parse_cmdline () > s_"Output VM UUID"; > [ L"vdsm-ovf-output" ], Getopt.String ("-", set_string_option_once "--vdsm-ovf-output" vdsm_ovf_output), > s_"Output OVF file"; > + [ L"vdsm-fixed-ovf" ], Getopt.Set vdsm_fixed_ovf, > + s_"Produce OVF that is more conforming to the standard"; > [ L"vmtype" ], Getopt.String ("-", vmtype_warning), > s_"Ignored for backwards compatibility"; > ] in > @@ -327,6 +330,7 @@ read the man page virt-v2v(1). > let vdsm_vol_uuids = List.rev !vdsm_vol_uuids in > let vdsm_vm_uuid = !vdsm_vm_uuid in > let vdsm_ovf_output = Option.default "." !vdsm_ovf_output in > + let vdsm_fixed_ovf = !vdsm_fixed_ovf in > > (* No arguments and machine-readable mode? Print out some facts > * about what this binary supports. > @@ -542,6 +546,7 @@ read the man page virt-v2v(1). > vm_uuid = vdsm_vm_uuid; > ovf_output = vdsm_ovf_output; > compat = vdsm_compat; > + legacy_ovf = not vdsm_fixed_ovf;Double negatives ... The use of booleans here is very confusing, but generally the patch is OK. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-p2v converts physical machines to virtual machines. Boot with a live CD or over the network (PXE) and turn machines into KVM guests. http://libguestfs.org/virt-v2v
Richard W.M. Jones
2018-Feb-20 10:18 UTC
Re: [Libguestfs] [PATCH 1/3] v2v: tests: check generated OVF
On Sun, Feb 18, 2018 at 03:26:08PM +0100, Tomáš Golembiovský wrote:> Check the generated OVF for -o rhv and -o vdsm outputs. Variable UUIDs > and date/times are filtered out. Make sure the the important UUIDs > (disk, volume, VM) are where we think they should be. > > Signed-off-by: Tomáš Golembiovský <tgolembi@redhat.com> > --- > v2v/test-v2v-o-rhv.ovf.expected | 92 ++++++++++++++++++++++++++++++++ > v2v/test-v2v-o-rhv.sh | 20 +++++++ > v2v/test-v2v-o-vdsm-options.ovf.expected | 92 ++++++++++++++++++++++++++++++++ > v2v/test-v2v-o-vdsm-options.sh | 16 ++++++The tests fail for me because my version of virt-v2v does not use this exact string:> + <!-- generated by virt-v2v 1.38.0 -->Also you need to add at least some of these files to v2v/Makefile.am EXTRA_DIST (the second long list in the file). Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-p2v converts physical machines to virtual machines. Boot with a live CD or over the network (PXE) and turn machines into KVM guests. http://libguestfs.org/virt-v2v
Apparently Analagous Threads
- [PATCH v2 0/3] Make generated OVF more conforming to standard
- [PATCH 1/2] Revert "v2v: oVirt changed the ResourceType for QXL video devices (RHBZ#1598715)."
- do we have support for xmlns in xml for v2v?
- GIT: [PATCH 0/5] v2v: Multiple fixes for handling semi-standard OVA files (RHBZ#1152998).
- [PATCH v3 0/3] SUSE VMDP support