From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id 8FE3A1FF396 for ; Wed, 22 May 2024 11:35:57 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 4F4E89717; Wed, 22 May 2024 11:36:13 +0200 (CEST) Date: Wed, 22 May 2024 11:35:59 +0200 From: Fabian =?iso-8859-1?q?Gr=FCnbichler?= To: Proxmox VE development discussion References: <20240429112124.3819357-1-d.csapak@proxmox.com> <20240429112124.3819357-2-d.csapak@proxmox.com> In-Reply-To: <20240429112124.3819357-2-d.csapak@proxmox.com> MIME-Version: 1.0 User-Agent: astroid/0.16.0 (https://github.com/astroidmail/astroid) Message-Id: <1716368756.oky8cjru96.astroid@yuna.none> X-SPAM-LEVEL: Spam detection results: 0 AWL -0.321 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment KAM_LOTSOFHASH 0.25 Emails with lots of hash-like gibberish SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [vmware.com, dmtf.org, cephconfig.pm, diskmanage.pm, lvmthinplugin.pm, ovf.pm, esxiplugin.pm, btrfsplugin.pm, pbsplugin.pm] URI_NOVOWEL 0.5 URI hostname has long non-vowel sequence Subject: Re: [pve-devel] [PATCH storage v3 01/10] copy OVF.pm from qemu-server X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Proxmox VE development discussion Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pve-devel-bounces@lists.proxmox.com Sender: "pve-devel" On April 29, 2024 1:21 pm, Dominik Csapak wrote: > copies the OVF.pm and relevant ovf tests from qemu-server. > We need it here, and it uses PVE::Storage already, and since there is no > intermediary package/repository we could put it, it seems fitting in > here. > > Put it in a new GuestImport module > > Signed-off-by: Dominik Csapak > --- > src/PVE/GuestImport/Makefile | 3 + > src/PVE/GuestImport/OVF.pm | 242 ++++++++++++++++++ > src/PVE/Makefile | 1 + > src/PVE/Storage/Makefile | 1 + > src/test/Makefile | 5 +- > src/test/ovf_manifests/Win10-Liz-disk1.vmdk | Bin 0 -> 65536 bytes > src/test/ovf_manifests/Win10-Liz.ovf | 142 ++++++++++ > .../ovf_manifests/Win10-Liz_no_default_ns.ovf | 142 ++++++++++ > .../ovf_manifests/Win_2008_R2_two-disks.ovf | 145 +++++++++++ > src/test/ovf_manifests/disk1.vmdk | Bin 0 -> 65536 bytes > src/test/ovf_manifests/disk2.vmdk | Bin 0 -> 65536 bytes > src/test/run_ovf_tests.pl | 71 +++++ > 12 files changed, 751 insertions(+), 1 deletion(-) > create mode 100644 src/PVE/GuestImport/Makefile > create mode 100644 src/PVE/GuestImport/OVF.pm > create mode 100644 src/test/ovf_manifests/Win10-Liz-disk1.vmdk > create mode 100755 src/test/ovf_manifests/Win10-Liz.ovf > create mode 100755 src/test/ovf_manifests/Win10-Liz_no_default_ns.ovf > create mode 100755 src/test/ovf_manifests/Win_2008_R2_two-disks.ovf > create mode 100644 src/test/ovf_manifests/disk1.vmdk > create mode 100644 src/test/ovf_manifests/disk2.vmdk > create mode 100755 src/test/run_ovf_tests.pl > > diff --git a/src/PVE/GuestImport/Makefile b/src/PVE/GuestImport/Makefile > new file mode 100644 > index 0000000..5948384 > --- /dev/null > +++ b/src/PVE/GuestImport/Makefile > @@ -0,0 +1,3 @@ > +.PHONY: install > +install: > + install -D -m 0644 OVF.pm ${DESTDIR}${PERLDIR}/PVE/GuestImport/OVF.pm > diff --git a/src/PVE/GuestImport/OVF.pm b/src/PVE/GuestImport/OVF.pm > new file mode 100644 > index 0000000..055ebf5 > --- /dev/null > +++ b/src/PVE/GuestImport/OVF.pm > @@ -0,0 +1,242 @@ > +# Open Virtualization Format import routines > +# https://www.dmtf.org/standards/ovf > +package PVE::GuestImport::OVF; > + > +use strict; > +use warnings; > + > +use XML::LibXML; > +use File::Spec; > +use File::Basename; > +use Data::Dumper; > +use Cwd 'realpath'; > + > +use PVE::Tools; > +use PVE::Storage; > + > +# map OVF resources types to descriptive strings > +# this will allow us to explore the xml tree without using magic numbers > +# http://schemas.dmtf.org/wbem/cim-html/2/CIM_ResourceAllocationSettingData.html > +my @resources = ( > + { id => 1, dtmf_name => 'Other' }, > + { id => 2, dtmf_name => 'Computer System' }, > + { id => 3, dtmf_name => 'Processor' }, > + { id => 4, dtmf_name => 'Memory' }, > + { id => 5, dtmf_name => 'IDE Controller', pve_type => 'ide' }, > + { id => 6, dtmf_name => 'Parallel SCSI HBA', pve_type => 'scsi' }, > + { id => 7, dtmf_name => 'FC HBA' }, > + { id => 8, dtmf_name => 'iSCSI HBA' }, > + { id => 9, dtmf_name => 'IB HCA' }, > + { id => 10, dtmf_name => 'Ethernet Adapter' }, > + { id => 11, dtmf_name => 'Other Network Adapter' }, > + { id => 12, dtmf_name => 'I/O Slot' }, > + { id => 13, dtmf_name => 'I/O Device' }, > + { id => 14, dtmf_name => 'Floppy Drive' }, > + { id => 15, dtmf_name => 'CD Drive' }, > + { id => 16, dtmf_name => 'DVD drive' }, > + { id => 17, dtmf_name => 'Disk Drive' }, > + { id => 18, dtmf_name => 'Tape Drive' }, > + { id => 19, dtmf_name => 'Storage Extent' }, > + { id => 20, dtmf_name => 'Other storage device', pve_type => 'sata'}, > + { id => 21, dtmf_name => 'Serial port' }, > + { id => 22, dtmf_name => 'Parallel port' }, > + { id => 23, dtmf_name => 'USB Controller' }, > + { id => 24, dtmf_name => 'Graphics controller' }, > + { id => 25, dtmf_name => 'IEEE 1394 Controller' }, > + { id => 26, dtmf_name => 'Partitionable Unit' }, > + { id => 27, dtmf_name => 'Base Partitionable Unit' }, > + { id => 28, dtmf_name => 'Power' }, > + { id => 29, dtmf_name => 'Cooling Capacity' }, > + { id => 30, dtmf_name => 'Ethernet Switch Port' }, > + { id => 31, dtmf_name => 'Logical Disk' }, > + { id => 32, dtmf_name => 'Storage Volume' }, > + { id => 33, dtmf_name => 'Ethernet Connection' }, > + { id => 34, dtmf_name => 'DMTF reserved' }, > + { id => 35, dtmf_name => 'Vendor Reserved'} > +); > + > +sub find_by { > + my ($key, $param) = @_; > + foreach my $resource (@resources) { > + if ($resource->{$key} eq $param) { > + return ($resource); > + } > + } > + return; > +} > + > +sub dtmf_name_to_id { > + my ($dtmf_name) = @_; > + my $found = find_by('dtmf_name', $dtmf_name); > + if ($found) { > + return $found->{id}; > + } else { > + return; > + } > +} > + > +sub id_to_pve { > + my ($id) = @_; > + my $resource = find_by('id', $id); > + if ($resource) { > + return $resource->{pve_type}; > + } else { > + return; > + } > +} > + > +# returns two references, $qm which holds qm.conf style key/values, and \@disks > +sub parse_ovf { > + my ($ovf, $debug) = @_; > + > + my $dom = XML::LibXML->load_xml(location => $ovf, no_blanks => 1); > + > + # register the xml namespaces in a xpath context object > + # 'ovf' is the default namespace so it will prepended to each xml element > + my $xpc = XML::LibXML::XPathContext->new($dom); > + $xpc->registerNs('ovf', 'http://schemas.dmtf.org/ovf/envelope/1'); > + $xpc->registerNs('rasd', 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData'); > + $xpc->registerNs('vssd', 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData'); > + > + > + # hash to save qm.conf parameters > + my $qm; > + > + #array to save a disk list > + my @disks; > + > + # easy xpath > + # walk down the dom until we find the matching XML element > + my $xpath_find_name = "/ovf:Envelope/ovf:VirtualSystem/ovf:Name"; > + my $ovf_name = $xpc->findvalue($xpath_find_name); > + > + if ($ovf_name) { > + # PVE::QemuServer::confdesc requires a valid DNS name > + ($qm->{name} = $ovf_name) =~ s/[^a-zA-Z0-9\-\.]//g; > + } else { > + warn "warning: unable to parse the VM name in this OVF manifest, generating a default value\n"; > + } > + > + # middle level xpath > + # element[child] search the elements which have this [child] > + my $processor_id = dtmf_name_to_id('Processor'); > + my $xpath_find_vcpu_count = "/ovf:Envelope/ovf:VirtualSystem/ovf:VirtualHardwareSection/ovf:Item[rasd:ResourceType=${processor_id}]/rasd:VirtualQuantity"; > + $qm->{'cores'} = $xpc->findvalue($xpath_find_vcpu_count); > + > + my $memory_id = dtmf_name_to_id('Memory'); > + my $xpath_find_memory = ("/ovf:Envelope/ovf:VirtualSystem/ovf:VirtualHardwareSection/ovf:Item[rasd:ResourceType=${memory_id}]/rasd:VirtualQuantity"); > + $qm->{'memory'} = $xpc->findvalue($xpath_find_memory); > + > + # middle level xpath > + # here we expect multiple results, so we do not read the element value with > + # findvalue() but store multiple elements with findnodes() > + my $disk_id = dtmf_name_to_id('Disk Drive'); > + my $xpath_find_disks="/ovf:Envelope/ovf:VirtualSystem/ovf:VirtualHardwareSection/ovf:Item[rasd:ResourceType=${disk_id}]"; > + my @disk_items = $xpc->findnodes($xpath_find_disks); > + > + # disks metadata is split in four different xml elements: > + # * as an Item node of type DiskDrive in the VirtualHardwareSection > + # * as an Disk node in the DiskSection > + # * as a File node in the References section > + # * each Item node also holds a reference to its owning controller > + # > + # we iterate over the list of Item nodes of type disk drive, and for each item, > + # find the corresponding Disk node, and File node and owning controller > + # when all the nodes has been found out, we copy the relevant information to > + # a $pve_disk hash ref, which we push to @disks; > + > + foreach my $item_node (@disk_items) { > + > + my $disk_node; > + my $file_node; > + my $controller_node; > + my $pve_disk; > + > + print "disk item:\n", $item_node->toString(1), "\n" if $debug; > + > + # from Item, find corresponding Disk node > + # here the dot means the search should start from the current element in dom > + my $host_resource = $xpc->findvalue('rasd:HostResource', $item_node); > + my $disk_section_path; > + my $disk_id; > + > + # RFC 3986 "2.3. Unreserved Characters" > + my $valid_uripath_chars = qr/[[:alnum:]]|[\-\._~]/; > + > + if ($host_resource =~ m|^ovf:/(${valid_uripath_chars}+)/(${valid_uripath_chars}+)$|) { > + $disk_section_path = $1; > + $disk_id = $2; > + } else { > + warn "invalid host ressource $host_resource, skipping\n"; > + next; > + } > + printf "disk section path: $disk_section_path and disk id: $disk_id\n" if $debug; > + > + # tricky xpath > + # @ means we filter the result query based on a the value of an item attribute ( @ = attribute) > + # @ needs to be escaped to prevent Perl double quote interpolation > + my $xpath_find_fileref = sprintf("/ovf:Envelope/ovf:DiskSection/\ > +ovf:Disk[\@ovf:diskId='%s']/\@ovf:fileRef", $disk_id); > + my $fileref = $xpc->findvalue($xpath_find_fileref); > + > + my $valid_url_chars = qr@${valid_uripath_chars}|/@; > + if (!$fileref || $fileref !~ m/^${valid_url_chars}+$/) { > + warn "invalid host ressource $host_resource, skipping\n"; > + next; > + } > + > + # from Disk Node, find corresponding filepath > + my $xpath_find_filepath = sprintf("/ovf:Envelope/ovf:References/ovf:File[\@ovf:id='%s']/\@ovf:href", $fileref); > + my $filepath = $xpc->findvalue($xpath_find_filepath); > + if (!$filepath) { > + warn "invalid file reference $fileref, skipping\n"; > + next; > + } > + print "file path: $filepath\n" if $debug; > + > + # from Item, find owning Controller type > + my $controller_id = $xpc->findvalue('rasd:Parent', $item_node); > + my $xpath_find_parent_type = sprintf("/ovf:Envelope/ovf:VirtualSystem/ovf:VirtualHardwareSection/\ > +ovf:Item[rasd:InstanceID='%s']/rasd:ResourceType", $controller_id); > + my $controller_type = $xpc->findvalue($xpath_find_parent_type); > + if (!$controller_type) { > + warn "invalid or missing controller: $controller_type, skipping\n"; > + next; > + } > + print "owning controller type: $controller_type\n" if $debug; > + > + # extract corresponding Controller node details > + my $adress_on_controller = $xpc->findvalue('rasd:AddressOnParent', $item_node); > + my $pve_disk_address = id_to_pve($controller_type) . $adress_on_controller; > + > + # resolve symlinks and relative path components > + # and die if the diskimage is not somewhere under the $ovf path > + my $ovf_dir = realpath(dirname(File::Spec->rel2abs($ovf))); should we maybe just enforce that $ovf must already be the absolute path? there is only one pre-existing caller, and the new one passes in the result of $plugin->path which should be an absolute path as well.. also, the usage of realpath here and below is lacking error handling (it returns undef and sets $! in case of an error). > + my $backing_file_path = realpath(join ('/', $ovf_dir, $filepath)); > + if ($backing_file_path !~ /^\Q${ovf_dir}\E/) { > + die "error parsing $filepath, are you using a symlink ?\n"; > + } with the later changes, the only thing this does is check that $filepath is not '..' or '.'. we could just enforce that instead? well, actually, '.' is not even handled by this (in the context of an OVA file having such a reference), it just trips up parse_volname later when it tries to get the format out of it, which thankfully happens before extraction ;) > + > + if (!-e $backing_file_path) { > + die "error parsing $filepath, file seems not to exist at $backing_file_path\n"; > + } > + > + ($backing_file_path) = $backing_file_path =~ m|^(/.*)|; # untaint > + > + my $virtual_size = PVE::Storage::file_size_info($backing_file_path); > + die "error parsing $backing_file_path, cannot determine file size\n" > + if !$virtual_size; > + > + $pve_disk = { > + disk_address => $pve_disk_address, > + backing_file => $backing_file_path, > + virtual_size => $virtual_size > + }; > + push @disks, $pve_disk; > + > + } > + > + return {qm => $qm, disks => \@disks}; > +} > + > +1; > diff --git a/src/PVE/Makefile b/src/PVE/Makefile > index d438804..e15a275 100644 > --- a/src/PVE/Makefile > +++ b/src/PVE/Makefile > @@ -6,6 +6,7 @@ install: > install -D -m 0644 Diskmanage.pm ${DESTDIR}${PERLDIR}/PVE/Diskmanage.pm > install -D -m 0644 CephConfig.pm ${DESTDIR}${PERLDIR}/PVE/CephConfig.pm > make -C Storage install > + make -C GuestImport install > make -C API2 install > make -C CLI install > > diff --git a/src/PVE/Storage/Makefile b/src/PVE/Storage/Makefile > index d5cc942..2daa0da 100644 > --- a/src/PVE/Storage/Makefile > +++ b/src/PVE/Storage/Makefile > @@ -14,6 +14,7 @@ SOURCES= \ > PBSPlugin.pm \ > BTRFSPlugin.pm \ > LvmThinPlugin.pm \ > + OVF.pm \ > ESXiPlugin.pm > > .PHONY: install > diff --git a/src/test/Makefile b/src/test/Makefile > index c54b10f..12991da 100644 > --- a/src/test/Makefile > +++ b/src/test/Makefile > @@ -1,6 +1,6 @@ > all: test > > -test: test_zfspoolplugin test_disklist test_bwlimit test_plugin > +test: test_zfspoolplugin test_disklist test_bwlimit test_plugin test_ovf > > test_zfspoolplugin: run_test_zfspoolplugin.pl > ./run_test_zfspoolplugin.pl > @@ -13,3 +13,6 @@ test_bwlimit: run_bwlimit_tests.pl > > test_plugin: run_plugin_tests.pl > ./run_plugin_tests.pl > + > +test_ovf: run_ovf_tests.pl > + ./run_ovf_tests.pl > diff --git a/src/test/ovf_manifests/Win10-Liz-disk1.vmdk b/src/test/ovf_manifests/Win10-Liz-disk1.vmdk > new file mode 100644 > index 0000000000000000000000000000000000000000..662354a3d1333a2f6c4364005e53bfe7cd8b9044 > GIT binary patch > literal 65536 > zcmeIvy>HV%7zbeUF`dK)46s zSXw zW^TMU0^M{}R2S(eR@1Ur*Q@eVF^^#r%c@u{hyC#J%V?Nq?*?z)=UG^1Wn9+n(yx6B > z(=ujtJiA)QVP~;guI5EOE2iV-%_??6=%y!^b+aeU_aA6Z4X2azC>{U!a5_FoJCkDB > zKRozW{5{ByIY=etVNVcI$B > zY@^?CwTN|j)tg?;i)G&AZFqPqoW(5P2K~XUq>9sqVVe!!?y@Y;)^#k~TefEvd2_XU > z^M@5mfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk4^iOdL%ftb > z5g~`p!f^fB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ > zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U > zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 > z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N > p0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK;Zui`~%h>XmtPp > > literal 0 > HcmV?d00001 > > diff --git a/src/test/ovf_manifests/Win10-Liz.ovf b/src/test/ovf_manifests/Win10-Liz.ovf > new file mode 100755 > index 0000000..bf4b41a > --- /dev/null > +++ b/src/test/ovf_manifests/Win10-Liz.ovf > @@ -0,0 +1,142 @@ > + > + > + > + > + > + > + > + Virtual disk information > + > + > + > + The list of logical networks > + > + The bridged network > + > + > + > + A virtual machine > + Win10-Liz > + > + The kind of installed guest operating system > + > + > + Virtual hardware requirements > + > + Virtual Hardware Family > + 0 > + Win10-Liz > + vmx-11 > + > + > + hertz * 10^6 > + Number of Virtual CPUs > + 4 virtual CPU(s) > + 1 > + 3 > + 4 > + > + > + byte * 2^20 > + Memory Size > + 6144MB of memory > + 2 > + 4 > + 6144 > + > + > + 0 > + SATA Controller > + sataController0 > + 3 > + vmware.sata.ahci > + 20 > + > + > + 0 > + USB Controller (XHCI) > + usb3 > + 4 > + vmware.usb.xhci > + 23 > + > + > + 0 > + USB Controller (EHCI) > + usb > + 5 > + vmware.usb.ehci > + 23 > + > + > + > + 0 > + SCSI Controller > + scsiController0 > + 6 > + lsilogicsas > + 6 > + > + > + true > + serial0 > + 7 > + 21 > + > + > + > + 0 > + disk0 > + ovf:/disk/vmdisk1 > + 8 > + 6 > + 17 > + > + > + 2 > + true > + bridged > + E1000e ethernet adapter on "bridged" > + ethernet0 > + 9 > + E1000e > + 10 > + > + > + > + false > + sound > + 10 > + vmware.soundcard.hdaudio > + 1 > + > + > + false > + video > + 11 > + 24 > + > + > + > + false > + vmci > + 12 > + vmware.vmci > + 1 > + > + > + 1 > + false > + cdrom0 > + 13 > + 3 > + 15 > + > + > + > + > + > + > + > + > + > diff --git a/src/test/ovf_manifests/Win10-Liz_no_default_ns.ovf b/src/test/ovf_manifests/Win10-Liz_no_default_ns.ovf > new file mode 100755 > index 0000000..b93540f > --- /dev/null > +++ b/src/test/ovf_manifests/Win10-Liz_no_default_ns.ovf > @@ -0,0 +1,142 @@ > + > + > + > + > + > + > + > + Virtual disk information > + > + > + > + The list of logical networks > + > + The bridged network > + > + > + > + A virtual machine > + Win10-Liz > + > + The kind of installed guest operating system > + > + > + Virtual hardware requirements > + > + Virtual Hardware Family > + 0 > + Win10-Liz > + vmx-11 > + > + > + hertz * 10^6 > + Number of Virtual CPUs > + 4 virtual CPU(s) > + 1 > + 3 > + 4 > + > + > + byte * 2^20 > + Memory Size > + 6144MB of memory > + 2 > + 4 > + 6144 > + > + > + 0 > + SATA Controller > + sataController0 > + 3 > + vmware.sata.ahci > + 20 > + > + > + 0 > + USB Controller (XHCI) > + usb3 > + 4 > + vmware.usb.xhci > + 23 > + > + > + 0 > + USB Controller (EHCI) > + usb > + 5 > + vmware.usb.ehci > + 23 > + > + > + > + 0 > + SCSI Controller > + scsiController0 > + 6 > + lsilogicsas > + 6 > + > + > + true > + serial0 > + 7 > + 21 > + > + > + > + 0 > + disk0 > + ovf:/disk/vmdisk1 > + 8 > + 6 > + 17 > + > + > + 2 > + true > + bridged > + E1000e ethernet adapter on "bridged" > + ethernet0 > + 9 > + E1000e > + 10 > + > + > + > + false > + sound > + 10 > + vmware.soundcard.hdaudio > + 1 > + > + > + false > + video > + 11 > + 24 > + > + > + > + false > + vmci > + 12 > + vmware.vmci > + 1 > + > + > + 1 > + false > + cdrom0 > + 13 > + 3 > + 15 > + > + > + > + > + > + > + > + > + > diff --git a/src/test/ovf_manifests/Win_2008_R2_two-disks.ovf b/src/test/ovf_manifests/Win_2008_R2_two-disks.ovf > new file mode 100755 > index 0000000..a563aab > --- /dev/null > +++ b/src/test/ovf_manifests/Win_2008_R2_two-disks.ovf > @@ -0,0 +1,145 @@ > + > + > + > + > + > + > + > + > + Virtual disk information > + > + > + > + > + The list of logical networks > + > + The bridged network > + > + > + > + A virtual machine > + Win_2008-R2x64 > + > + The kind of installed guest operating system > + > + > + Virtual hardware requirements > + > + Virtual Hardware Family > + 0 > + Win_2008-R2x64 > + vmx-11 > + > + > + hertz * 10^6 > + Number of Virtual CPUs > + 1 virtual CPU(s) > + 1 > + 3 > + 1 > + > + > + byte * 2^20 > + Memory Size > + 2048MB of memory > + 2 > + 4 > + 2048 > + > + > + 0 > + SATA Controller > + sataController0 > + 3 > + vmware.sata.ahci > + 20 > + > + > + 0 > + USB Controller (EHCI) > + usb > + 4 > + vmware.usb.ehci > + 23 > + > + > + > + 0 > + SCSI Controller > + scsiController0 > + 5 > + lsilogicsas > + 6 > + > + > + true > + serial0 > + 6 > + 21 > + > + > + > + 0 > + disk0 > + ovf:/disk/vmdisk1 > + 7 > + 5 > + 17 > + > + > + 1 > + disk1 > + ovf:/disk/vmdisk2 > + 8 > + 5 > + 17 > + > + > + 2 > + true > + bridged > + E1000 ethernet adapter on "bridged" > + ethernet0 > + 9 > + E1000 > + 10 > + > + > + > + false > + sound > + 10 > + vmware.soundcard.hdaudio > + 1 > + > + > + false > + video > + 11 > + 24 > + > + > + > + false > + vmci > + 12 > + vmware.vmci > + 1 > + > + > + 1 > + false > + cdrom0 > + 13 > + 3 > + 15 > + > + > + > + > + > + > + > + > + > + > diff --git a/src/test/ovf_manifests/disk1.vmdk b/src/test/ovf_manifests/disk1.vmdk > new file mode 100644 > index 0000000000000000000000000000000000000000..8660602343a1a955f9bcf2e6beaed99316dd8167 > GIT binary patch > literal 65536 > zcmeIvy>HV%7zbeUF`dK)46s zbJF?F{+-YFKK_yYyn2=-$&0qXY zqY>z*Sy|tuS*)j3xo%d~*K!`iCRTO1T8@X|%lB-2b2}Q2@{gmi&a1d=x<|K%7N%9q > zn|Qfh$8m45TCV10Gb^W)c4ZxVA@tMpzfJp2S{y#m?iwzx)01@a>+{9rJna?j=ZAyM > zqPW{FznsOxiSi~-&+ za#^%_7k)SjXE85!!SM7bspGUQewUqo+Glx@ubWtPwRL-yMO)CL`L7O2fB*pk1PBly > zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pkPg~&a(=JbS1PBlyK!5-N0!ISx > zkM7+PAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ > z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly > zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF > z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk > d1PBlyK!5-N0t5&UAV7cs0RjXF5cr=0{{Ra(Wheju > > literal 0 > HcmV?d00001 > > diff --git a/src/test/ovf_manifests/disk2.vmdk b/src/test/ovf_manifests/disk2.vmdk > new file mode 100644 > index 0000000000000000000000000000000000000000..c4634513348b392202898374f1c8d2d51d565b27 > GIT binary patch > literal 65536 > zcmeIvy>HV%7zbeUF`dK)46s ztLLQio&7tX?|uAp{Oj^rk|Zyh{<7(9yX&q=(mrq7>)ntf&y(cMe*SJh-aTX?eH9+& > z#z!O2Psc@dn~q~OEsJ%%D!&!;7&fu2iq&#-6u$l#k8ZBB&%=0f64qH6mv#5(X4k^B > zj9DEow(B_REmq6byr^fzbkeM>VlRY#diJkw-bwTQ2bx{O`BgehC%?a(PtMX_-hBS! > zV6(_?yX6%pcd>%ZCj`_<*{eCa6d4SQYmC$1K;F1Lf} > zc3v#=CU3(J2jMJcc^4cVA0$ z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAn>#W-ahT}R7ZdS0RjXF5Fl_M > z@c!W5Edc@q2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk > z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs > z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ > zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U > eAV7cs0RjXF5FkK+009C72oNAZfB=F2DR2*l=VfOA > > literal 0 > HcmV?d00001 > > diff --git a/src/test/run_ovf_tests.pl b/src/test/run_ovf_tests.pl > new file mode 100755 > index 0000000..5a80ab2 > --- /dev/null > +++ b/src/test/run_ovf_tests.pl > @@ -0,0 +1,71 @@ > +#!/usr/bin/perl > + > +use strict; > +use warnings; > +use lib qw(..); # prepend .. to @INC so we use the local version of PVE packages > + > +use FindBin '$Bin'; > +use PVE::GuestImport::OVF; > +use Test::More; > + > +use Data::Dumper; > + > +my $test_manifests = join ('/', $Bin, 'ovf_manifests'); > + > +print "parsing ovfs\n"; > + > +my $win2008 = eval { PVE::GuestImport::OVF::parse_ovf("$test_manifests/Win_2008_R2_two-disks.ovf") }; > +if (my $err = $@) { > + fail('parse win2008'); > + warn("error: $err\n"); > +} else { > + ok('parse win2008'); > +} > +my $win10 = eval { PVE::GuestImport::OVF::parse_ovf("$test_manifests/Win10-Liz.ovf") }; > +if (my $err = $@) { > + fail('parse win10'); > + warn("error: $err\n"); > +} else { > + ok('parse win10'); > +} > +my $win10noNs = eval { PVE::GuestImport::OVF::parse_ovf("$test_manifests/Win10-Liz_no_default_ns.ovf") }; > +if (my $err = $@) { > + fail("parse win10 no default rasd NS"); > + warn("error: $err\n"); > +} else { > + ok('parse win10 no default rasd NS'); > +} > + > +print "testing disks\n"; > + > +is($win2008->{disks}->[0]->{disk_address}, 'scsi0', 'multidisk vm has the correct first disk controller'); > +is($win2008->{disks}->[0]->{backing_file}, "$test_manifests/disk1.vmdk", 'multidisk vm has the correct first disk backing device'); > +is($win2008->{disks}->[0]->{virtual_size}, 2048, 'multidisk vm has the correct first disk size'); > + > +is($win2008->{disks}->[1]->{disk_address}, 'scsi1', 'multidisk vm has the correct second disk controller'); > +is($win2008->{disks}->[1]->{backing_file}, "$test_manifests/disk2.vmdk", 'multidisk vm has the correct second disk backing device'); > +is($win2008->{disks}->[1]->{virtual_size}, 2048, 'multidisk vm has the correct second disk size'); > + > +is($win10->{disks}->[0]->{disk_address}, 'scsi0', 'single disk vm has the correct disk controller'); > +is($win10->{disks}->[0]->{backing_file}, "$test_manifests/Win10-Liz-disk1.vmdk", 'single disk vm has the correct disk backing device'); > +is($win10->{disks}->[0]->{virtual_size}, 2048, 'single disk vm has the correct size'); > + > +is($win10noNs->{disks}->[0]->{disk_address}, 'scsi0', 'single disk vm (no default rasd NS) has the correct disk controller'); > +is($win10noNs->{disks}->[0]->{backing_file}, "$test_manifests/Win10-Liz-disk1.vmdk", 'single disk vm (no default rasd NS) has the correct disk backing device'); > +is($win10noNs->{disks}->[0]->{virtual_size}, 2048, 'single disk vm (no default rasd NS) has the correct size'); > + > +print "\ntesting vm.conf extraction\n"; > + > +is($win2008->{qm}->{name}, 'Win2008-R2x64', 'win2008 VM name is correct'); > +is($win2008->{qm}->{memory}, '2048', 'win2008 VM memory is correct'); > +is($win2008->{qm}->{cores}, '1', 'win2008 VM cores are correct'); > + > +is($win10->{qm}->{name}, 'Win10-Liz', 'win10 VM name is correct'); > +is($win10->{qm}->{memory}, '6144', 'win10 VM memory is correct'); > +is($win10->{qm}->{cores}, '4', 'win10 VM cores are correct'); > + > +is($win10noNs->{qm}->{name}, 'Win10-Liz', 'win10 VM (no default rasd NS) name is correct'); > +is($win10noNs->{qm}->{memory}, '6144', 'win10 VM (no default rasd NS) memory is correct'); > +is($win10noNs->{qm}->{cores}, '4', 'win10 VM (no default rasd NS) cores are correct'); > + > +done_testing(); > -- > 2.39.2 > > > > _______________________________________________ > pve-devel mailing list > pve-devel@lists.proxmox.com > https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel > > > _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel