def test_add_file_then_change_to_disk(self): """Add a disk as a file, then make it a proper disk.""" self.instance.package = self.minimal_ovf intermediate_ovf = os.path.join(self.temp_dir, "mid.ovf") self.instance.output = intermediate_ovf self.instance.file = self.blank_vmdk self.instance.file_id = "mydisk" self.instance.run() self.instance.finished() self.check_diff(file1=self.minimal_ovf, file2=intermediate_ovf, expected=""" <ovf:Envelope xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1"> - <ovf:References /> + <ovf:References> + <ovf:File ovf:href="blank.vmdk" ovf:id="mydisk" ovf:size="{0}" /> + </ovf:References> <ovf:VirtualSystem ovf:id="x"> """.format(self.FILE_SIZE['blank.vmdk'])) from COT.add_disk import COTAddDisk ad = COTAddDisk(UI()) ad.package = intermediate_ovf ad.output = self.temp_file ad.disk_image = self.blank_vmdk ad.file_id = "mydisk" ad.run() self.assertLogged(**self.TYPE_NOT_SPECIFIED_GUESS_HARDDISK) self.assertLogged(**self.CONTROLLER_NOT_SPECIFIED_GUESS_IDE) self.assertLogged(**self.OVERWRITING_FILE) self.assertLogged(**self.ADDRESS_ON_PARENT_NOT_SPECIFIED) ad.finished() ad.destroy() self.check_diff(file1=intermediate_ovf, expected=""" <?xml version='1.0' encoding='utf-8'?> -<ovf:Envelope xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1"> +<ovf:Envelope xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1" \ xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/\ CIM_ResourceAllocationSettingData"> <ovf:References> ... </ovf:References> + <ovf:DiskSection> + <ovf:Info>Virtual disk information</ovf:Info> + <ovf:Disk ovf:capacity="512" ovf:capacityAllocationUnits="byte * 2^20" \ ovf:diskId="mydisk" ovf:fileRef="mydisk" ovf:format="http://www.vmware.com/\ interfaces/specifications/vmdk.html#streamOptimized" /> + </ovf:DiskSection> <ovf:VirtualSystem ovf:id="x"> ... <ovf:Info /> + <ovf:Item> + <rasd:Address>0</rasd:Address> + <rasd:Description>IDE Controller 0</rasd:Description> + <rasd:ElementName>IDE Controller</rasd:ElementName> + <rasd:InstanceID>1</rasd:InstanceID> + <rasd:ResourceType>5</rasd:ResourceType> + </ovf:Item> + <ovf:Item> + <rasd:AddressOnParent>0</rasd:AddressOnParent> + <rasd:ElementName>Hard Disk Drive</rasd:ElementName> + <rasd:HostResource>ovf:/disk/mydisk</rasd:HostResource> + <rasd:InstanceID>2</rasd:InstanceID> + <rasd:Parent>1</rasd:Parent> + <rasd:ResourceType>17</rasd:ResourceType> + </ovf:Item> </ovf:VirtualHardwareSection> """)
class TestCOTAddDisk(COT_UT): """Test cases for the COTAddDisk module.""" def setUp(self): """Test case setup function called automatically prior to each test.""" super(TestCOTAddDisk, self).setUp() self.instance = COTAddDisk(UI()) self.instance.output = self.temp_file def test_readiness(self): """Test ready_to_run() under various combinations of parameters.""" self.instance.package = self.input_ovf ready, reason = self.instance.ready_to_run() self.assertFalse(ready) self.assertTrue(re.search("DISK_IMAGE is a mandatory", reason)) self.assertRaises(InvalidInputError, self.instance.run) self.instance.disk_image = self.blank_vmdk ready, reason = self.instance.ready_to_run() self.assertTrue(ready) self.instance.address = "1:0" ready, reason = self.instance.ready_to_run() self.assertFalse(ready) self.assertTrue(re.search("controller", reason)) self.assertRaises(InvalidInputError, self.instance.run) self.instance.controller = "ide" ready, reason = self.instance.ready_to_run() self.assertTrue(ready) # address without controller is not allowed, # but controller without address is OK self.instance.address = None ready, reason = self.instance.ready_to_run() self.assertTrue(ready) def test_conflicting_args_1(self): """Test conflicting arguments are detected and rejected.""" # TODO - it would be nice to detect this in ready_to_run() # rather than run() self.instance.package = self.input_ovf self.instance.disk_image = self.blank_vmdk # file2 exists and is mapped to IDE 1:0 but we request IDE 1:1 self.instance.controller = "ide" self.instance.address = "1:1" self.instance.file_id = "file2" self.assertRaises(ValueMismatchError, self.instance.run) self.assertLogged(**self.TYPE_NOT_SPECIFIED_GUESS_HARDDISK) def test_conflicting_args_2(self): """Test conflicting arguments are detected and rejected.""" # TODO - it would be nice to detect this in ready_to_run() # rather than run() self.instance.package = self.input_ovf self.instance.disk_image = self.input_iso # ovf contains input.iso but we're asking it to overwrite input.vmdk self.instance.file_id = "vmdisk1" self.assertRaises(ValueMismatchError, self.instance.run) self.assertLogged(**self.TYPE_NOT_SPECIFIED_GUESS_CDROM) def test_conflicting_args_3(self): """Test conflicting arguments are detected and rejected.""" # TODO - it would be nice to detect this in ready_to_run() # rather than run() self.instance.package = self.input_ovf self.instance.disk_image = self.input_vmdk # ovf contains input.vmdk but we're asking it to overwrite input.iso self.instance.controller = "ide" self.instance.address = "1:0" self.assertRaises(ValueMismatchError, self.instance.run) self.assertLogged(**self.TYPE_NOT_SPECIFIED_GUESS_HARDDISK) def test_new_hard_disk(self): """Test adding a new hard disk to the OVF.""" self.instance.package = self.input_ovf self.instance.disk_image = self.blank_vmdk self.instance.run() self.assertLogged(**self.TYPE_NOT_SPECIFIED_GUESS_HARDDISK) self.assertLogged(**self.CONTROLLER_NOT_SPECIFIED_GUESS_IDE) self.instance.finished() self.check_diff(""" <ovf:File ovf:href="input.iso" ovf:id="file2" ovf:size="{iso_size}" /> + <ovf:File ovf:href="blank.vmdk" ovf:id="blank.vmdk" \ ovf:size="{blank_size}" /> </ovf:References> ... <ovf:Disk ovf:capacity="1" ovf:capacityAllocationUnits="byte * 2^30" \ ovf:diskId="vmdisk1" ovf:fileRef="file1" ovf:format=\ "http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" /> + <ovf:Disk ovf:capacity="512" ovf:capacityAllocationUnits="byte * 2^20" \ ovf:diskId="blank.vmdk" ovf:fileRef="blank.vmdk" ovf:format=\ "http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" /> </ovf:DiskSection> ... </ovf:Item> + <ovf:Item> + <rasd:AddressOnParent>0</rasd:AddressOnParent> + <rasd:ElementName>Hard Disk Drive</rasd:ElementName> + <rasd:HostResource>ovf:/disk/blank.vmdk</rasd:HostResource> + <rasd:InstanceID>14</rasd:InstanceID> + <rasd:Parent>5</rasd:Parent> + <rasd:ResourceType>17</rasd:ResourceType> + </ovf:Item> </ovf:VirtualHardwareSection> """.format(iso_size=self.FILE_SIZE['input.iso'], blank_size=self.FILE_SIZE['blank.vmdk'])) # Make sure the disk file is copied over self.assertTrue(filecmp.cmp(self.blank_vmdk, os.path.join(self.temp_dir, "blank.vmdk")), "disk file should be exported unchanged") def test_new_hard_disk_and_explicit_controller(self): """Test adding a hard disk to an explicitly new SCSI controller.""" self.instance.package = self.input_ovf self.instance.disk_image = self.blank_vmdk self.instance.controller = "scsi" self.instance.address = "1:0" self.instance.run() self.assertLogged(**self.TYPE_NOT_SPECIFIED_GUESS_HARDDISK) self.instance.finished() self.check_diff(""" <ovf:File ovf:href="input.iso" ovf:id="file2" ovf:size="{iso_size}" /> + <ovf:File ovf:href="blank.vmdk" ovf:id="blank.vmdk" \ ovf:size="{blank_size}" /> </ovf:References> ... <ovf:Disk ovf:capacity="1" ovf:capacityAllocationUnits="byte * 2^30" \ ovf:diskId="vmdisk1" ovf:fileRef="file1" ovf:format=\ "http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" /> + <ovf:Disk ovf:capacity="512" ovf:capacityAllocationUnits="byte * 2^20" \ ovf:diskId="blank.vmdk" ovf:fileRef="blank.vmdk" ovf:format=\ "http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" /> </ovf:DiskSection> ... </ovf:Item> + <ovf:Item> + <rasd:Address>1</rasd:Address> + <rasd:Description>SCSI Controller 1</rasd:Description> + <rasd:ElementName>SCSI Controller</rasd:ElementName> + <rasd:InstanceID>14</rasd:InstanceID> + <rasd:ResourceSubType>lsilogic</rasd:ResourceSubType> + <rasd:ResourceType>6</rasd:ResourceType> + </ovf:Item> + <ovf:Item> + <rasd:AddressOnParent>0</rasd:AddressOnParent> + <rasd:ElementName>Hard Disk Drive</rasd:ElementName> + <rasd:HostResource>ovf:/disk/blank.vmdk</rasd:HostResource> + <rasd:InstanceID>15</rasd:InstanceID> + <rasd:Parent>14</rasd:Parent> + <rasd:ResourceType>17</rasd:ResourceType> + </ovf:Item> </ovf:VirtualHardwareSection> """.format(iso_size=self.FILE_SIZE['input.iso'], blank_size=self.FILE_SIZE['blank.vmdk'])) # Make sure the disk file is copied over self.assertTrue(filecmp.cmp(self.blank_vmdk, os.path.join(self.temp_dir, "blank.vmdk")), "disk file should be exported unchanged") def test_new_hard_disk_and_automatic_controller(self): """Add a new hard disk and create an IDE controller automatically.""" # Since the primary IDE0 controller is already full in the IOSv OVF, # COT will need to automatically create IDE1 controller self.instance.package = self.iosv_ovf self.instance.disk_image = self.blank_vmdk self.instance.run() self.assertLogged(**self.TYPE_NOT_SPECIFIED_GUESS_HARDDISK) self.assertLogged(**self.CONTROLLER_NOT_SPECIFIED_GUESS_IDE) self.assertLogged(**self.ADDRESS_ON_PARENT_NOT_SPECIFIED) self.instance.finished() self.check_diff(file1=self.iosv_ovf, expected=""" <ovf:File ovf:href="input.vmdk" ovf:id="vios-adventerprisek9-m.vmdk" \ ovf:size="{input_size}" /> + <ovf:File ovf:href="blank.vmdk" ovf:id="blank.vmdk" \ ovf:size="{blank_size}" /> </ovf:References> ... <ovf:Disk ovf:capacity="1073741824" ovf:capacityAllocationUnits="byte" \ ovf:diskId="vios-adventerprisek9-m.vmdk" \ ovf:fileRef="vios-adventerprisek9-m.vmdk" ovf:format=\ "http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" /> + <ovf:Disk ovf:capacity="512" ovf:capacityAllocationUnits="byte * 2^20" \ ovf:diskId="blank.vmdk" ovf:fileRef="blank.vmdk" ovf:format=\ "http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" /> </ovf:DiskSection> ... </ovf:Item> + <ovf:Item> + <rasd:Address>1</rasd:Address> + <rasd:Description>IDE Controller 1</rasd:Description> + <rasd:ElementName>IDE Controller</rasd:ElementName> + <rasd:InstanceID>6</rasd:InstanceID> + <rasd:ResourceSubType>virtio</rasd:ResourceSubType> + <rasd:ResourceType>5</rasd:ResourceType> + </ovf:Item> + <ovf:Item> + <rasd:AddressOnParent>0</rasd:AddressOnParent> + <rasd:ElementName>Hard Disk Drive</rasd:ElementName> + <rasd:HostResource>ovf:/disk/blank.vmdk</rasd:HostResource> + <rasd:InstanceID>7</rasd:InstanceID> + <rasd:Parent>6</rasd:Parent> + <rasd:ResourceType>17</rasd:ResourceType> + </ovf:Item> <ovf:Item ovf:required="false">""" .format(input_size=self.FILE_SIZE['input.vmdk'], blank_size=self.FILE_SIZE['blank.vmdk'])) def test_new_hard_disk_v09(self): """Test adding a disk to a version 0.9 OVF.""" self.instance.package = self.v09_ovf self.instance.disk_image = self.blank_vmdk self.instance.run() self.assertLogged(**self.TYPE_NOT_SPECIFIED_GUESS_HARDDISK) self.assertLogged(**self.CONTROLLER_NOT_SPECIFIED_GUESS_IDE) self.instance.finished() # Default controller for generic platform is IDE for hard disks self.check_diff(file1=self.v09_ovf, expected=""" <ovf:File ovf:href="input.vmdk" ovf:id="file1" ovf:size="{input_size}" /> + <ovf:File ovf:href="blank.vmdk" ovf:id="blank.vmdk" \ ovf:size="{blank_size}" /> </ovf:References> ... <ovf:Disk ovf:capacity="1073741824" ovf:diskId="vmdisk1" \ ovf:fileRef="file1" ovf:format="http://www.vmware.com/specifications/\ vmdk.html#sparse" /> + <ovf:Disk ovf:capacity="536870912" ovf:diskId="blank.vmdk" \ ovf:fileRef="blank.vmdk" ovf:format="http://www.vmware.com/interfaces/\ specifications/vmdk.html#streamOptimized" /> </ovf:Section> ... </ovf:Item> + <ovf:Item> + <rasd:Caption>Hard Disk Drive</rasd:Caption> + <rasd:InstanceId>9</rasd:InstanceId> + <rasd:ResourceType>17</rasd:ResourceType> + <rasd:HostResource>/disk/blank.vmdk</rasd:HostResource> + <rasd:Parent>5</rasd:Parent> + <rasd:AddressOnParent>1</rasd:AddressOnParent> + </ovf:Item> </ovf:Section>""".format(input_size=self.FILE_SIZE['input.vmdk'], blank_size=self.FILE_SIZE['blank.vmdk'])) def test_new_hard_disk_v20_vbox(self): """Test adding a new hard disk to a v2.0 OVF from VirtualBox.""" self.instance.package = self.v20_vbox_ovf self.instance.disk_image = self.blank_vmdk self.instance.run() self.assertLogged(**self.TYPE_NOT_SPECIFIED_GUESS_HARDDISK) self.assertLogged(**self.CONTROLLER_NOT_SPECIFIED_GUESS_IDE) self.instance.finished() # TODO - vbox XML is not very clean so the diffs are large... # self.check_diff('', file1=self.v20_vbox_ovf) # ovftool does not consider vbox ovfs to be valid self.validate_output_with_ovftool = False def test_overwrite_hard_disk_fileid(self): """Overwrite an existing disk by specifying matching file-id.""" self.instance.package = self.input_ovf self.instance.disk_image = self.blank_vmdk self.instance.file_id = 'file1' # For coverage's sake, let's change the controller subtype too self.instance.subtype = "virtio" self.instance.run() self.assertLogged(**self.TYPE_NOT_SPECIFIED_GUESS_HARDDISK) self.assertLogged(**self.OVERWRITING_FILE) self.assertLogged(**self.OVERWRITING_DISK) self.assertLogged(**self.OVERWRITING_DISK_ITEM) self.instance.finished() self.check_diff(""" <ovf:References> - <ovf:File ovf:href="input.vmdk" ovf:id="file1" ovf:size="{input_size}" /> + <ovf:File ovf:href="blank.vmdk" ovf:id="file1" ovf:size="{blank_size}" /> <ovf:File ovf:href="input.iso" ovf:id="file2" ovf:size="{iso_size}" /> ... <ovf:Info>Virtual disk information</ovf:Info> - <ovf:Disk ovf:capacity="1" ovf:capacityAllocationUnits="byte * 2^30" \ ovf:diskId="vmdisk1" ovf:fileRef="file1" ovf:format=\ "http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" /> + <ovf:Disk ovf:capacity="512" ovf:capacityAllocationUnits="byte * 2^20" \ ovf:diskId="vmdisk1" ovf:fileRef="file1" ovf:format=\ "http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" /> </ovf:DiskSection> ... <rasd:InstanceID>3</rasd:InstanceID> - <rasd:ResourceSubType>lsilogic</rasd:ResourceSubType> + <rasd:ResourceSubType>virtio</rasd:ResourceSubType> <rasd:ResourceType>6</rasd:ResourceType> """.format(input_size=self.FILE_SIZE['input.vmdk'], blank_size=self.FILE_SIZE['blank.vmdk'], iso_size=self.FILE_SIZE['input.iso'])) # Make sure the old disk is not copied self.assertFalse(os.path.exists(os.path.join(self.temp_dir, "input.vmdk")), "old disk should be replaced, not exported") # Make sure the new disk is copied self.assertTrue(filecmp.cmp(self.blank_vmdk, os.path.join(self.temp_dir, "blank.vmdk")), "newly added disk should be exported unchanged") def test_overwrite_hard_disk_address(self): """Overwrite an existing disk by matching controller address.""" self.instance.package = self.input_ovf self.instance.disk_image = self.blank_vmdk self.instance.controller = 'scsi' self.instance.address = "0:0" self.instance.run() self.assertLogged(**self.TYPE_NOT_SPECIFIED_GUESS_HARDDISK) self.assertLogged(**self.OVERWRITING_FILE) self.assertLogged(**self.OVERWRITING_DISK) self.assertLogged(**self.OVERWRITING_DISK_ITEM) self.instance.finished() self.check_diff(""" <ovf:References> - <ovf:File ovf:href="input.vmdk" ovf:id="file1" ovf:size="{input_size}" /> + <ovf:File ovf:href="blank.vmdk" ovf:id="file1" ovf:size="{blank_size}" /> <ovf:File ovf:href="input.iso" ovf:id="file2" ovf:size="{iso_size}" /> ... <ovf:Info>Virtual disk information</ovf:Info> - <ovf:Disk ovf:capacity="1" ovf:capacityAllocationUnits="byte * 2^30" \ ovf:diskId="vmdisk1" ovf:fileRef="file1" ovf:format=\ "http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" /> + <ovf:Disk ovf:capacity="512" ovf:capacityAllocationUnits="byte * 2^20" \ ovf:diskId="vmdisk1" ovf:fileRef="file1" ovf:format=\ "http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" /> </ovf:DiskSection> """.format(input_size=self.FILE_SIZE['input.vmdk'], blank_size=self.FILE_SIZE['blank.vmdk'], iso_size=self.FILE_SIZE['input.iso'])) # Make sure the old disk is not copied self.assertFalse(os.path.exists(os.path.join(self.temp_dir, "input.vmdk")), "old disk should be replaced, not exported") # Make sure the new disk is copied self.assertTrue(filecmp.cmp(self.blank_vmdk, os.path.join(self.temp_dir, "blank.vmdk")), "new disk should be exported unchanged") def test_overwrite_harddisk_with_cdrom(self): """Replace a hard disk with a cd-rom.""" self.instance.package = self.v09_ovf self.instance.disk_image = self.input_iso self.instance.type = 'cdrom' self.instance.controller = 'scsi' self.instance.address = "0:0" self.instance.run() self.assertLogged(**self.OVERWRITING_FILE) self.assertLogged(**self.OVERWRITING_DISK) # TODO can we block this? self.assertLogged(**self.OVERWRITING_DISK_ITEM) self.assertLogged(**self.DELETING_DISK) self.assertLogged(**self.DELETING_DISK_SECTION) self.instance.finished() self.check_diff(file1=self.v09_ovf, expected=""" <ovf:References> - <ovf:File ovf:href="input.vmdk" ovf:id="file1" ovf:size="{vmdk_size}" /> + <ovf:File ovf:href="input.iso" ovf:id="file1" ovf:size="{iso_size}" /> </ovf:References> - <ovf:Section xsi:type="ovf:DiskSection_Type"> - <ovf:Info>Meta-information about the virtual disks</ovf:Info> - <ovf:Disk ovf:capacity="1073741824" ovf:diskId="vmdisk1" \ ovf:fileRef="file1" ovf:format=\ "http://www.vmware.com/specifications/vmdk.html#sparse" /> - </ovf:Section> <ovf:Section xsi:type="ovf:NetworkSection_Type"> ... <rasd:InstanceId>7</rasd:InstanceId> - <rasd:ResourceType>17</rasd:ResourceType> - <rasd:HostResource>/disk/vmdisk1</rasd:HostResource> + <rasd:ResourceType>15</rasd:ResourceType> + <rasd:HostResource>/file/file1</rasd:HostResource> <rasd:Parent>4</rasd:Parent> """.format(vmdk_size=self.FILE_SIZE['input.vmdk'], iso_size=self.FILE_SIZE['input.iso'])) # Make sure the old disk is not copied self.assertFalse(os.path.exists(os.path.join(self.temp_dir, "input.vmdk")), "old disk should be replaced, not exported") # Make sure the new disk is copied self.assertTrue(filecmp.cmp(self.input_iso, os.path.join(self.temp_dir, "input.iso")), "new disk should be exported unchanged") def test_overwrite_cdrom_with_harddisk(self): """Replace a cd-rom with a hard disk.""" self.instance.package = self.input_ovf self.instance.disk_image = self.blank_vmdk self.instance.type = 'harddisk' self.instance.controller = 'ide' self.instance.address = "1:0" self.instance.run() self.assertLogged(**self.OVERWRITING_FILE) self.assertLogged(**self.OVERWRITING_DISK_ITEM) self.instance.finished() self.check_diff(""" <ovf:File ovf:href="input.vmdk" ovf:id="file1" ovf:size="{vmdk_size}" /> - <ovf:File ovf:href="input.iso" ovf:id="file2" ovf:size="{iso_size}" /> + <ovf:File ovf:href="blank.vmdk" ovf:id="file2" ovf:size="{blank_size}" /> </ovf:References> ... <ovf:Disk ovf:capacity="1" ovf:capacityAllocationUnits="byte * 2^30" \ ovf:diskId="vmdisk1" ovf:fileRef="file1" ovf:format=\ "http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" /> + <ovf:Disk ovf:capacity="512" ovf:capacityAllocationUnits="byte * 2^20" \ ovf:diskId="file2" ovf:fileRef="file2" ovf:format=\ "http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" /> </ovf:DiskSection> ... <rasd:ElementName>CD-ROM 1</rasd:ElementName> - <rasd:HostResource>ovf:/file/file2</rasd:HostResource> + <rasd:HostResource>ovf:/disk/file2</rasd:HostResource> <rasd:InstanceID>7</rasd:InstanceID> <rasd:Parent>4</rasd:Parent> - <rasd:ResourceType>15</rasd:ResourceType> + <rasd:ResourceType>17</rasd:ResourceType> </ovf:Item> """.format(vmdk_size=self.FILE_SIZE['input.vmdk'], iso_size=self.FILE_SIZE['input.iso'], blank_size=self.FILE_SIZE['blank.vmdk'])) # Make sure the old disk is not copied self.assertFalse(os.path.exists(os.path.join(self.temp_dir, "input.iso")), "old disk should be replaced, not exported") # Make sure the new disk is copied self.assertTrue(filecmp.cmp(self.blank_vmdk, os.path.join(self.temp_dir, "blank.vmdk")), "new disk should be exported unchanged") def test_disk_conversion(self): """Make sure hard disk is converted to stream-optimized VMDK format.""" # Create a qcow2 image and add it as a new disk new_qcow2 = os.path.join(self.temp_dir, "new.qcow2") # Make it a small file to keep the test fast create_disk_image(new_qcow2, capacity="16M") self.instance.package = self.input_ovf self.instance.disk_image = new_qcow2 self.instance.controller = 'scsi' self.instance.run() self.assertLogged(**self.TYPE_NOT_SPECIFIED_GUESS_HARDDISK) self.instance.finished() # Make sure the disk was converted and added to the OVF self.check_diff(""" <ovf:File ovf:href="input.iso" ovf:id="file2" ovf:size="{iso_size}" /> + <ovf:File ovf:href="new.vmdk" ovf:id="new.vmdk" ovf:size="{new_size}" /> </ovf:References> ... <ovf:Disk ovf:capacity="1" ovf:capacityAllocationUnits="byte * 2^30" \ ovf:diskId="vmdisk1" ovf:fileRef="file1" ovf:format=\ "http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" /> + <ovf:Disk ovf:capacity="16" ovf:capacityAllocationUnits="byte * 2^20" \ ovf:diskId="new.vmdk" ovf:fileRef="new.vmdk" ovf:format=\ "http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" /> </ovf:DiskSection> ... </ovf:Item> + <ovf:Item> + <rasd:AddressOnParent>1</rasd:AddressOnParent> + <rasd:ElementName>Hard Disk Drive</rasd:ElementName> + <rasd:HostResource>ovf:/disk/new.vmdk</rasd:HostResource> + <rasd:InstanceID>14</rasd:InstanceID> + <rasd:Parent>3</rasd:Parent> + <rasd:ResourceType>17</rasd:ResourceType> + </ovf:Item> </ovf:VirtualHardwareSection> """.format(iso_size=self.FILE_SIZE['input.iso'], new_size=os.path.getsize(os.path.join(self.temp_dir, "new.vmdk")))) # Make sure the disk was actually converted to the right format format, subformat = get_disk_format(os.path.join(self.temp_dir, "new.vmdk")) self.assertEqual(format, 'vmdk') self.assertEqual(subformat, "streamOptimized") def test_disk_conversion_and_replacement(self): """Convert a disk to implicitly replace an existing disk.""" # Create a qcow2 image and add it as replacement for the existing vmdk new_qcow2 = os.path.join(self.temp_dir, "input.qcow2") # Keep it small! create_disk_image(new_qcow2, capacity="16M") self.instance.package = self.input_ovf self.instance.disk_image = new_qcow2 self.instance.run() self.assertLogged(**self.TYPE_NOT_SPECIFIED_GUESS_HARDDISK) self.assertLogged(**self.OVERWRITING_FILE) self.assertLogged(**self.OVERWRITING_DISK) self.assertLogged(**self.OVERWRITING_DISK_ITEM) self.instance.finished() # Make sure the disk was converted and replaced the existing disk self.check_diff(""" <ovf:References> - <ovf:File ovf:href="input.vmdk" ovf:id="file1" ovf:size="{input_size}" /> + <ovf:File ovf:href="input.vmdk" ovf:id="file1" ovf:size="{new_size}" /> <ovf:File ovf:href="input.iso" ovf:id="file2" ovf:size="{iso_size}" /> ... <ovf:Info>Virtual disk information</ovf:Info> - <ovf:Disk ovf:capacity="1" ovf:capacityAllocationUnits="byte * 2^30" \ ovf:diskId="vmdisk1" ovf:fileRef="file1" ovf:format=\ "http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" /> + <ovf:Disk ovf:capacity="16" ovf:capacityAllocationUnits="byte * 2^20" \ ovf:diskId="vmdisk1" ovf:fileRef="file1" ovf:format=\ "http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" /> </ovf:DiskSection> """.format(input_size=self.FILE_SIZE['input.vmdk'], iso_size=self.FILE_SIZE['input.iso'], new_size=os.path.getsize(os.path.join(self.temp_dir, "input.vmdk")))) def test_add_disk_no_existing(self): """Add a disk to an OVF that doesn't currently have any. Verify correct creation of various OVF sub-sections. """ self.instance.package = self.minimal_ovf self.instance.disk_image = self.blank_vmdk self.instance.run() self.assertLogged(**self.TYPE_NOT_SPECIFIED_GUESS_HARDDISK) self.assertLogged(**self.CONTROLLER_NOT_SPECIFIED_GUESS_IDE) self.assertLogged(**self.ADDRESS_ON_PARENT_NOT_SPECIFIED) self.instance.finished() self.check_diff(file1=self.minimal_ovf, expected=""" <?xml version='1.0' encoding='utf-8'?> -<ovf:Envelope xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1"> - <ovf:References /> +<ovf:Envelope xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1" \ xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/\ CIM_ResourceAllocationSettingData"> + <ovf:References> + <ovf:File ovf:href="blank.vmdk" ovf:id="blank.vmdk" \ ovf:size="{blank_size}" /> + </ovf:References> + <ovf:DiskSection> + <ovf:Info>Virtual disk information</ovf:Info> + <ovf:Disk ovf:capacity="512" ovf:capacityAllocationUnits="byte * 2^20" \ ovf:diskId="blank.vmdk" ovf:fileRef="blank.vmdk" ovf:format=\ "http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" /> + </ovf:DiskSection> <ovf:VirtualSystem ovf:id="x"> ... <ovf:Info /> + <ovf:Item> + <rasd:Address>0</rasd:Address> + <rasd:Description>IDE Controller 0</rasd:Description> + <rasd:ElementName>IDE Controller</rasd:ElementName> + <rasd:InstanceID>1</rasd:InstanceID> + <rasd:ResourceType>5</rasd:ResourceType> + </ovf:Item> + <ovf:Item> + <rasd:AddressOnParent>0</rasd:AddressOnParent> + <rasd:ElementName>Hard Disk Drive</rasd:ElementName> + <rasd:HostResource>ovf:/disk/blank.vmdk</rasd:HostResource> + <rasd:InstanceID>2</rasd:InstanceID> + <rasd:Parent>1</rasd:Parent> + <rasd:ResourceType>17</rasd:ResourceType> + </ovf:Item> </ovf:VirtualHardwareSection> """.format(blank_size=self.FILE_SIZE['blank.vmdk'])) def test_add_cdrom_to_existing_controller(self): """Add a CDROM drive to an existing controller.""" self.instance.package = self.input_ovf self.instance.disk_image = self.blank_vmdk self.instance.type = "cdrom" self.instance.controller = "scsi" self.instance.address = "0:1" self.instance.run() self.instance.finished() self.check_diff(""" <ovf:File ovf:href="input.iso" ovf:id="file2" ovf:size="360448" /> + <ovf:File ovf:href="blank.vmdk" ovf:id="blank.vmdk" \ ovf:size="{blank_size}" /> </ovf:References> ... </ovf:Item> + <ovf:Item> + <rasd:AddressOnParent>1</rasd:AddressOnParent> + <rasd:ElementName>CD-ROM Drive</rasd:ElementName> + <rasd:HostResource>ovf:/file/blank.vmdk</rasd:HostResource> + <rasd:InstanceID>14</rasd:InstanceID> + <rasd:Parent>3</rasd:Parent> + <rasd:ResourceType>15</rasd:ResourceType> + </ovf:Item> </ovf:VirtualHardwareSection> """.format(blank_size=self.FILE_SIZE['blank.vmdk'])) def test_add_disk_no_room(self): """Negative test - add a disk to an OVF whose controllers are full.""" # iosv.ovf already has two disks. Add a third disk... self.instance.package = self.iosv_ovf self.instance.disk_image = self.blank_vmdk self.instance.run() self.assertLogged(**self.TYPE_NOT_SPECIFIED_GUESS_HARDDISK) self.assertLogged(**self.CONTROLLER_NOT_SPECIFIED_GUESS_IDE) self.assertLogged(**self.ADDRESS_ON_PARENT_NOT_SPECIFIED) self.instance.finished() self.check_diff(file1=self.iosv_ovf, expected=""" <ovf:File ovf:href="input.vmdk" ovf:id="vios-adventerprisek9-m.vmdk" \ ovf:size="152576" /> + <ovf:File ovf:href="blank.vmdk" ovf:id="blank.vmdk" \ ovf:size="{blank_size}" /> </ovf:References> ... <ovf:Disk ovf:capacity="1073741824" ovf:capacityAllocationUnits="byte" \ ovf:diskId="vios-adventerprisek9-m.vmdk" \ ovf:fileRef="vios-adventerprisek9-m.vmdk" \ ovf:format="http://www.vmware.com/interfaces/specifications/\ vmdk.html#streamOptimized" /> + <ovf:Disk ovf:capacity="512" ovf:capacityAllocationUnits="byte * 2^20" \ ovf:diskId="blank.vmdk" ovf:fileRef="blank.vmdk" \ ovf:format="http://www.vmware.com/interfaces/specifications/\ vmdk.html#streamOptimized" /> </ovf:DiskSection> ... </ovf:Item> + <ovf:Item> + <rasd:Address>1</rasd:Address> + <rasd:Description>IDE Controller 1</rasd:Description> + <rasd:ElementName>IDE Controller</rasd:ElementName> + <rasd:InstanceID>6</rasd:InstanceID> + <rasd:ResourceSubType>virtio</rasd:ResourceSubType> + <rasd:ResourceType>5</rasd:ResourceType> + </ovf:Item> + <ovf:Item> + <rasd:AddressOnParent>0</rasd:AddressOnParent> + <rasd:ElementName>Hard Disk Drive</rasd:ElementName> + <rasd:HostResource>ovf:/disk/blank.vmdk</rasd:HostResource> + <rasd:InstanceID>7</rasd:InstanceID> + <rasd:Parent>6</rasd:Parent> + <rasd:ResourceType>17</rasd:ResourceType> + </ovf:Item> <ovf:Item ovf:required="false"> """.format(blank_size=self.FILE_SIZE['blank.vmdk'])) # Add a fourth disk... self.instance.package = self.temp_file self.instance.disk_image = resource_filename(__name__, 'input.iso') self.instance.run() self.assertLogged(**self.TYPE_NOT_SPECIFIED_GUESS_CDROM) self.assertLogged(**self.CONTROLLER_NOT_SPECIFIED_GUESS_IDE) self.instance.finished() self.check_diff(file1=self.iosv_ovf, expected=""" <ovf:File ovf:href="input.vmdk" ovf:id="vios-adventerprisek9-m.vmdk" \ ovf:size="152576" /> + <ovf:File ovf:href="blank.vmdk" ovf:id="blank.vmdk" \ ovf:size="{blank_size}" /> + <ovf:File ovf:href="input.iso" ovf:id="input.iso" ovf:size="{iso_size}" /> </ovf:References> ... <ovf:Disk ovf:capacity="1073741824" ovf:capacityAllocationUnits="byte" \ ovf:diskId="vios-adventerprisek9-m.vmdk" \ ovf:fileRef="vios-adventerprisek9-m.vmdk" ovf:format="http://www.vmware.com/\ interfaces/specifications/vmdk.html#streamOptimized" /> + <ovf:Disk ovf:capacity="512" ovf:capacityAllocationUnits="byte * 2^20" \ ovf:diskId="blank.vmdk" ovf:fileRef="blank.vmdk" \ ovf:format="http://www.vmware.com/interfaces/specifications/\ vmdk.html#streamOptimized" /> </ovf:DiskSection> ... </ovf:Item> + <ovf:Item> + <rasd:Address>1</rasd:Address> + <rasd:Description>IDE Controller 1</rasd:Description> + <rasd:ElementName>IDE Controller</rasd:ElementName> + <rasd:InstanceID>6</rasd:InstanceID> + <rasd:ResourceSubType>virtio</rasd:ResourceSubType> + <rasd:ResourceType>5</rasd:ResourceType> + </ovf:Item> + <ovf:Item> + <rasd:AddressOnParent>0</rasd:AddressOnParent> + <rasd:ElementName>Hard Disk Drive</rasd:ElementName> + <rasd:HostResource>ovf:/disk/blank.vmdk</rasd:HostResource> + <rasd:InstanceID>7</rasd:InstanceID> + <rasd:Parent>6</rasd:Parent> + <rasd:ResourceType>17</rasd:ResourceType> + </ovf:Item> + <ovf:Item> + <rasd:AddressOnParent>1</rasd:AddressOnParent> + <rasd:ElementName>CD-ROM Drive</rasd:ElementName> + <rasd:HostResource>ovf:/file/input.iso</rasd:HostResource> + <rasd:InstanceID>8</rasd:InstanceID> + <rasd:Parent>6</rasd:Parent> + <rasd:ResourceType>15</rasd:ResourceType> + </ovf:Item> <ovf:Item ovf:required="false"> """.format(blank_size=self.FILE_SIZE['blank.vmdk'], iso_size=self.FILE_SIZE['input.iso'])) # Create a qcow2 image new_qcow2 = os.path.join(self.temp_dir, "foozle.qcow2") # Keep it small! create_disk_image(new_qcow2, capacity="16M") # Try to add a fifth disk - IDE controllers are full! self.instance.package = self.temp_file self.instance.disk_image = new_qcow2 self.assertRaises(ValueTooHighError, self.instance.run) self.assertLogged(**self.TYPE_NOT_SPECIFIED_GUESS_HARDDISK) self.assertLogged(**self.CONTROLLER_NOT_SPECIFIED_GUESS_IDE) def test_overwrite_implicit_file_id(self): """file_id defaults to filename if not set.""" self.instance.package = self.invalid_ovf self.instance.disk_image = resource_filename(__name__, "input.vmdk") self.instance.run() self.assertLogged(**self.UNRECOGNIZED_PRODUCT_CLASS) self.assertLogged(**self.NONEXISTENT_FILE) self.assertLogged(**self.TYPE_NOT_SPECIFIED_GUESS_HARDDISK) self.assertLogged(**self.CONTROLLER_NOT_SPECIFIED_GUESS_IDE) self.assertLogged(**self.OVERWRITING_FILE) self.assertLogged(**self.OVERWRITING_DISK) self.instance.finished() self.assertLogged(msg="Removing unused network") self.check_diff(file1=self.invalid_ovf, expected=""" <ovf:References> - <ovf:File ovf:href="this_is_a_really_long_filename_for_a_disk.vmdk" \ ovf:id="input.vmdk" ovf:size="{input_size}" /> + <ovf:File ovf:href="input.vmdk" ovf:id="input.vmdk" \ ovf:size="{input_size}" /> <ovf:File ovf:href="input.iso" ovf:id="input.iso" ovf:size="360448" /> ... </ovf:Network> - <ovf:Network ovf:name="name-but-no-description" /> </ovf:NetworkSection> ... </ovf:Item> + <ovf:Item> + <rasd:AddressOnParent>1</rasd:AddressOnParent> + <rasd:ElementName>Hard Disk Drive</rasd:ElementName> + <rasd:HostResource>ovf:/disk/input.vmdk</rasd:HostResource> + <rasd:InstanceID>6</rasd:InstanceID> + <rasd:Parent>1</rasd:Parent> + <rasd:ResourceType>17</rasd:ResourceType> + </ovf:Item> <ovf:Item ovf:configuration="myprofile"> """.format(input_size=self.FILE_SIZE['input.vmdk'])) # ovftool will fail because invalid_ovf has an invalid Disk fileRef self.validate_output_with_ovftool = False def test_overwrite_disk_with_bad_host_resource(self): """Negative test - invalid HostResource value in OVF.""" self.instance.package = self.invalid_ovf self.instance.disk_image = self.blank_vmdk self.instance.controller = "ide" self.instance.address = "0:0" with self.assertRaises(ValueUnsupportedError) as cm: self.instance.run() self.assertTrue(re.search("HostResource", str(cm.exception))) self.assertLogged(**self.UNRECOGNIZED_PRODUCT_CLASS) self.assertLogged(**self.NONEXISTENT_FILE) self.assertLogged(**self.TYPE_NOT_SPECIFIED_GUESS_HARDDISK) self.assertLogged(levelname='WARNING', msg="Unrecognized HostResource format") def test_overwrite_disk_with_bad_parent_by_file(self): """Negative test - invalid parent for disk, identified by filename.""" self.instance.package = self.invalid_ovf self.instance.disk_image = resource_filename(__name__, 'input.iso') self.assertRaises(LookupError, self.instance.run) self.assertLogged(**self.UNRECOGNIZED_PRODUCT_CLASS) self.assertLogged(**self.NONEXISTENT_FILE) self.assertLogged(**self.TYPE_NOT_SPECIFIED_GUESS_CDROM) def test_overwrite_disk_with_bad_parent_by_fileid(self): """Negative test - invalid parent for disk, identified by fileid.""" self.instance.package = self.invalid_ovf self.instance.disk_image = self.blank_vmdk self.instance.file_id = "input.iso" self.assertRaises(LookupError, self.instance.run) self.assertLogged(**self.UNRECOGNIZED_PRODUCT_CLASS) self.assertLogged(**self.NONEXISTENT_FILE) self.assertLogged(**self.TYPE_NOT_SPECIFIED_GUESS_HARDDISK) def test_overwrite_disk_with_bad_fileref(self): """Negative test - invalid fileref in OVF.""" self.instance.package = self.invalid_ovf self.instance.disk_image = self.blank_vmdk self.instance.file_id = "flash2" self.assertRaises(LookupError, self.instance.run) self.assertLogged(**self.UNRECOGNIZED_PRODUCT_CLASS) self.assertLogged(**self.NONEXISTENT_FILE) self.assertLogged(**self.TYPE_NOT_SPECIFIED_GUESS_HARDDISK)