/** * Remove all illegal disks which were associated with the given snapshot. This is done in order * to be able to switch correctly between snapshots where illegal images might be present. * * @param snapshotId The ID of the snapshot for who to remove illegal images for. */ public void removeAllIllegalDisks(Guid snapshotId) { for (DiskImage diskImage : getDiskImageDao().getAllSnapshotsForVmSnapshot(snapshotId)) { if (diskImage.getimageStatus() == ImageStatus.ILLEGAL) { ImagesHandler.removeDiskImage(diskImage); } } }
@Test public void testRemoveImageFromSnapshotConfiguration() throws OvfReaderException { Guid vmId = Guid.newGuid(); VM vm = new VM(); vm.setId(vmId); vm.setStoragePoolId(Guid.newGuid()); vm.setVmtName(RandomUtils.instance().nextString(10)); vm.setOrigin(OriginType.OVIRT); vm.setDbGeneration(1L); Guid vmSnapshotId = Guid.newGuid(); DiskImage disk1 = addTestDisk(vm, vmSnapshotId); DiskImage disk2 = addTestDisk(vm, vmSnapshotId); OvfManager ovfManager = new OvfManager(); ArrayList<DiskImage> disks = new ArrayList<DiskImage>(Arrays.asList(disk1, disk2)); String ovf = ovfManager.ExportVm(vm, disks, Version.v3_1); Snapshot snap = new Snapshot(); snap.setVmConfiguration(ovf); snap.setId(vmSnapshotId); when(snapshotDAO.get(vmSnapshotId)).thenReturn(snap); doReturn(disk2).when(cmd).getDiskImage(); doReturn(disk2).when(cmd).getImage(); doReturn(disk2.getId()).when(cmd).getImageId(); Snapshot actual = cmd.prepareSnapshotConfigWithoutImageSingleImage(vmSnapshotId, disk2.getImageId()); String actualOvf = actual.getVmConfiguration(); ArrayList<DiskImage> actualImages = new ArrayList<DiskImage>(); ovfManager.ImportVm(actualOvf, new VM(), actualImages, new ArrayList<VmNetworkInterface>()); assertEquals("Wrong number of disks", 1, actualImages.size()); assertEquals("Wrong disk", disk1, actualImages.get(0)); }
@Test public void testGetSuggestedDiskAliasNotNullAliasDisk() { disk1.setDiskAlias("someAlias"); assertEquals( "a new alias was generated instead of returning the pre-defined one", disk1.getDiskAlias(), ImagesHandler.getSuggestedDiskAlias(disk1, prefix, 1)); }
/** * Validate whether a disk can be shareable. Disk can be shareable if it is not based on qcow FS, * which means it should not be based on a template image with thin provisioning, it also should * not contain snapshots and it is not bootable. * * @return Indication whether the disk can be shared or not. */ protected boolean validateShareableDisk() { if (DiskStorageType.LUN == _oldDisk.getDiskStorageType()) { return true; } boolean isDiskUpdatedToShareable = getParameters().getDiskInfo().isShareable(); boolean isDiskShareable = _oldDisk.isShareable(); // Check if VM is not during snapshot. if (getSnapshotDao().exists(getVmId(), SnapshotStatus.IN_PREVIEW)) { addCanDoActionMessage(VdcBllMessages.ACTION_TYPE_FAILED_VM_IN_PREVIEW); return false; } // If user want to update the disk to be shareable then update the vm snapshot id to be null. if (!isDiskShareable && isDiskUpdatedToShareable) { List<DiskImage> diskImageList = getDiskImageDao().getAllSnapshotsForImageGroup(_oldDisk.getId()); // If disk image list is more then one then we assume that it has a snapshot, since one image // is the active // disk and all the other images are the snapshots. if ((diskImageList.size() > 1) || !Guid.Empty.equals(((DiskImage) _oldDisk).getit_guid())) { addCanDoActionMessage(VdcBllMessages.SHAREABLE_DISK_IS_NOT_SUPPORTED_FOR_DISK); return false; } if (!isVersionSupportedForShareable( _oldDisk, getStoragePoolDAO() .get(getVm().getstorage_pool_id()) .getcompatibility_version() .getValue())) { addCanDoActionMessage(VdcBllMessages.ACTION_NOT_SUPPORTED_FOR_CLUSTER_POOL_LEVEL); return false; } DiskImage diskImage = (DiskImage) getParameters().getDiskInfo(); if (!isVolumeFormatSupportedForShareable(diskImage.getvolume_format())) { addCanDoActionMessage(VdcBllMessages.SHAREABLE_DISK_IS_NOT_SUPPORTED_BY_VOLUME_FORMAT); return false; } diskImage.setvm_snapshot_id(null); } else if (isDiskShareable && !isDiskUpdatedToShareable) { if (getVmDAO().getVmsListForDisk(_oldDisk.getId()).size() > 1) { addCanDoActionMessage(VdcBllMessages.DISK_IS_ALREADY_SHARED_BETWEEN_VMS); return false; } // If disk is not floating, then update its vm snapshot id to the active VM snapshot. ((DiskImage) _oldDisk) .setvm_snapshot_id( DbFacade.getInstance() .getSnapshotDao() .getId(getVmId(), SnapshotType.ACTIVE) .getValue()); } return true; }
/** @return The snapshots to add to the disk */ private static ArrayList<DiskImage> mockSnapshots() { Guid snapshotGuid = Guid.newGuid(); DiskImage expectedSnapshot = new DiskImage(); expectedSnapshot.setImageId(snapshotGuid); ArrayList<DiskImage> snapshots = new ArrayList<DiskImage>(1); snapshots.add(expectedSnapshot); return snapshots; }
/** @return A disk to add to the VM */ private static DiskImage mockDisk() { // Prepare the disk Guid diskGuid = Guid.newGuid(); Guid itGuid = Guid.newGuid(); final DiskImage expectedDisk = new DiskImage(); expectedDisk.setImageId(diskGuid); expectedDisk.setImageTemplateId(itGuid); return expectedDisk; }
@Override public int compare(DiskImage x, DiskImage y) { if (x.getcreation_date().before(y.getcreation_date())) { return -1; } if (x.getcreation_date().after(y.getcreation_date())) { return 1; } return 0; }
@Override public int compare(DiskImage x, DiskImage y) { if (x.getlastModified().before(y.getlastModified())) { return -1; } if (x.getlastModified().after(y.getlastModified())) { return 1; } return 0; }
/** Adds the given vm metadata to the given map */ private String buildMetadataDictionaryForVm(VM vm) { ArrayList<DiskImage> AllVmImages = new ArrayList<DiskImage>(); List<DiskImage> filteredDisks = ImagesHandler.filterImageDisks(vm.getDiskList(), false, true, true); for (DiskImage diskImage : filteredDisks) { List<DiskImage> images = ImagesHandler.getAllImageSnapshots(diskImage.getImageId()); AllVmImages.addAll(images); } return ovfManager.ExportVm(vm, AllVmImages, ClusterUtils.getCompatibilityVersion(vm)); }
/** * parses a given ovf to a VmTemplate, initialized with images and interfaces. * * @param ovf * @return VmTemplate that represents the given ovf data * @throws OvfReaderException */ public VmTemplate readVmTemplateFromOvf(String ovf) throws OvfReaderException { ArrayList<DiskImage> diskImages = new ArrayList<DiskImage>(); ArrayList<VmNetworkInterface> interfaces = new ArrayList<VmNetworkInterface>(); VmTemplate template = new VmTemplate(); ovfManager.ImportTemplate(ovf, template, diskImages, interfaces); template.setInterfaces(interfaces); // add disk map for (DiskImage disk : diskImages) { template.getDiskTemplateMap().put(disk.getId(), disk); } return template; }
@Override protected void executeCommand() { final DiskImage newDiskImage = getParameters().getDiskImage(); newDiskImage.setDiskAlias( ImagesHandler.getDiskAliasWithDefault( newDiskImage, generateDefaultAliasForRegiteredDisk(Calendar.getInstance()))); ArrayList<Guid> storageIds = new ArrayList<>(); storageIds.add(getParameters().getStorageDomainId()); newDiskImage.setStorageIds(storageIds); addDiskImageToDb(newDiskImage, getCompensationContext()); getReturnValue().setActionReturnValue(newDiskImage.getId()); getReturnValue().setSucceeded(true); }
@Test public void testGetAllStorageIdsForImageIds() { Guid sdIdShared = Guid.newGuid(); Guid sdId1 = Guid.newGuid(); Guid sdId2 = Guid.newGuid(); disk1.setStorageIds(new ArrayList<Guid>(Arrays.asList(sdId1, sdIdShared))); disk2.setStorageIds(new ArrayList<Guid>(Arrays.asList(sdId2, sdIdShared))); Set<Guid> result = ImagesHandler.getAllStorageIdsForImageIds(Arrays.asList(disk1, disk2)); assertEquals("Wrong number of Guids returned", 3, result.size()); assertTrue("Wrong Guids returned", result.containsAll(Arrays.asList(sdId1, sdId2, sdIdShared))); }
@Test public void testImagesSubtract() { disk1.setId(Guid.newGuid()); disk2.setId(Guid.newGuid()); disk3.setId(Guid.newGuid()); List<DiskImage> list1 = new ArrayList<>(Arrays.asList(disk1, disk2, disk3)); List<DiskImage> list2 = new ArrayList<>(Arrays.asList(disk2, disk3)); List<DiskImage> intersection = ImagesHandler.imagesSubtract(list1, list2); assertEquals("Intersection should contain only one disk", intersection.size(), 1); assertTrue("Intersection should contains disk1", intersection.contains(disk1)); }
@Test public void testImagesIntersection() { disk1.setId(Guid.newGuid()); disk2.setId(Guid.newGuid()); disk3.setId(Guid.newGuid()); List<DiskImage> list1 = new ArrayList<>(Arrays.asList(disk1, disk2)); List<DiskImage> list2 = new ArrayList<>(Arrays.asList(disk1, disk3)); List<DiskImage> intersection = ImagesHandler.imagesIntersection(list1, list2); assertTrue( "Intersection should contain only disk1", intersection.size() == 1 && intersection.contains(disk1)); }
@Test public void testGetSuggestedDiskAliasNullAliasDisk() { disk1.setDiskAlias(null); assertEquals( "disk with null alias does not give the default name", prefix + ImagesHandler.DISK + ImagesHandler.DefaultDriveName, ImagesHandler.getSuggestedDiskAlias(disk1, prefix, 1)); }
@Test public void filterImageDisksFilterDiskSnapshots() { disk1.setActive(true); List<DiskImage> result = ImagesHandler.filterImageDisks(Arrays.asList(disk1, disk2), false, false, true); assertEquals("Wrong number of Guids returned", 1, result.size()); assertTrue("The result should contain the active image disk", result.contains(disk1)); }
@Override protected boolean canDoAction() { boolean retValue = true; if (getVm() == null) { retValue = false; addCanDoActionMessage(VdcBllMessages.ACTION_TYPE_FAILED_VM_NOT_FOUND); } for (Guid imageId : getParameters().getImageIds()) { DiskImage disk = DbFacade.getInstance().getDiskImageDAO().get(imageId); if (disk == null) { retValue = false; addCanDoActionMessage(VdcBllMessages.ACTION_TYPE_FAILED_VM_IMAGE_DOES_NOT_EXIST); break; } retValue = retValue && ImagesHandler.PerformImagesChecks( getVmId(), getReturnValue().getCanDoActionMessages(), getVm().getstorage_pool_id(), disk.getstorage_id().getValue(), false, true, false, false, true, true, true); if (!retValue) { break; } } if (!retValue) { addCanDoActionMessage(VdcBllMessages.VAR__ACTION__REMOVE); addCanDoActionMessage(VdcBllMessages.VAR__TYPE__VM_DISK); } return retValue; }
public static DiskModel DiskToModel(Disk disk) { DiskModel diskModel = new DiskModel(); diskModel.setIsNew(true); diskModel.getAlias().setEntity(disk.getDiskAlias()); if (disk.getDiskStorageType() == DiskStorageType.IMAGE) { DiskImage diskImage = (DiskImage) disk; EntityModel sizeEntity = new EntityModel(); sizeEntity.setEntity(diskImage.getSizeInGigabytes()); diskModel.setSize(sizeEntity); ListModel volumeList = new ListModel(); volumeList.setItems( (diskImage.getvolume_type() == VolumeType.Preallocated ? new ArrayList<VolumeType>(Arrays.asList(new VolumeType[] {VolumeType.Preallocated})) : DataProvider.GetVolumeTypeList())); volumeList.setSelectedItem(diskImage.getvolume_type()); diskModel.setVolumeType(volumeList); } diskModel.setDisk(disk); return diskModel; }
/** * Synchronize the VM's Disks with the images from the snapshot:<br> * * <ul> * <li>Existing disks are updated. * <li>Disks that don't exist anymore get re-added. * <ul> * <li>If the image is still in the DB, the disk is linked to it. * <li>If the image is not in the DB anymore, the disk will be marked as "broken" * </ul> * </ul> * * @param vmId The VM ID is needed to re-add disks. * @param snapshotId The snapshot ID is used to find only the VM disks at the time. * @param disksFromSnapshot The disks that existed in the snapshot. */ protected void synchronizeDisksFromSnapshot( Guid vmId, Guid snapshotId, Guid activeSnapshotId, List<DiskImage> disksFromSnapshot) { List<Guid> diskIdsFromSnapshot = new ArrayList<Guid>(); // Sync disks that exist or existed in the snapshot. for (DiskImage diskImage : disksFromSnapshot) { diskIdsFromSnapshot.add(diskImage.getimage_group_id()); Disk disk = diskImage.getDisk(); if (getDiskDao().exists(disk.getId())) { getDiskDao().update(disk); } else { // If can't find the image, insert it as illegal so that it can't be used and make the // device unplugged. if (getDiskImageDao().getSnapshotById(diskImage.getId()) == null) { diskImage.setimageStatus(ImageStatus.ILLEGAL); diskImage.setvm_snapshot_id(activeSnapshotId); ImagesHandler.addImage( diskImage, true, new image_storage_domain_map(diskImage.getId(), diskImage.getstorage_ids().get(0))); } ImagesHandler.addDiskToVm(disk, vmId); } } // Remove all disks that didn't exist in the snapshot. for (VmDevice vmDevice : getVmDeviceDao() .getVmDeviceByVmIdTypeAndDevice( vmId, VmDeviceType.DISK.getName(), VmDeviceType.DISK.getName())) { if (!diskIdsFromSnapshot.contains(vmDevice.getDeviceId())) { getDiskDao().remove(vmDevice.getDeviceId()); getVmDeviceDao().remove(vmDevice.getId()); } } }
@SuppressWarnings("rawtypes") public void assertExecuteQueryCommandResult( Guid requestedUser, boolean includeDiskData, boolean expectedResults) { mockQueryParameters(requestedUser, includeDiskData); // Mock the result of the DAO final VM expectedVM = mockVMFromDAO(requestedUser); final DiskImage expectedDisk = mockDisk(); final ArrayList<DiskImage> snapshots = mockSnapshots(); DiskImage expectedSnapshot = snapshots.get(0); // Mock the disks, if needed if (includeDiskData) { doAnswer( new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { expectedDisk.getSnapshots().addAll(snapshots); expectedVM.getDiskMap().put(expectedDisk.getId(), expectedDisk); expectedVM.getDiskList().add(expectedDisk); return null; } }) .when(getQuery()) .updateDisksFromDB(expectedVM); doNothing().when(getQuery()).fillImagesBySnapshots(expectedVM); } doAnswer( new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { return null; } }) .when(getQuery()) .updateVmInit(expectedVM); doNothing().when(getQuery()).updateVmGuestAgentVersion(expectedVM); getQuery().executeQueryCommand(); @SuppressWarnings("unchecked") List<VM> actualVMs = (List<VM>) getQuery().getQueryReturnValue().getReturnValue(); if (!expectedResults) { assertTrue("no VMs should have been returned", actualVMs.isEmpty()); } else { assertEquals("wrong number of VMs returned", 1, actualVMs.size()); VM actualVM = actualVMs.get(0); assertEquals("wrong VMs returned", expectedVM, actualVM); if (includeDiskData) { assertEquals("Wrong number of disks on VM", 1, actualVM.getDiskList().size()); DiskImage actualDisk = actualVM.getDiskList().get(0); assertEquals("Wrong disk on VM", expectedDisk, actualDisk); assertEquals("Wrong number of snapshots", 1, actualDisk.getSnapshots().size()); DiskImage actualSnapshot = actualDisk.getSnapshots().get(0); assertEquals("Wrong snapshot", expectedSnapshot, actualSnapshot); } } }
/** <exception>VdcDAL.IrsBrokerIRSErrorException. */ public DiskImage buildImageEntity(Map<String, Object> xmlRpcStruct) { DiskImage newImage = new DiskImage(); try { newImage.setImageId(new Guid((String) xmlRpcStruct.get(IrsProperties.uuid))); newImage.setParentId(new Guid((String) xmlRpcStruct.get(IrsProperties.parent))); newImage.setDescription((String) xmlRpcStruct.get(IrsProperties.description)); newImage.setImageStatus( EnumUtils.valueOf( ImageStatus.class, (String) xmlRpcStruct.get(IrsProperties.ImageStatus), true)); if (xmlRpcStruct.containsKey(IrsProperties.size)) { newImage.setSize(Long.parseLong(xmlRpcStruct.get(IrsProperties.size).toString()) * 512); } if (xmlRpcStruct.containsKey("capacity")) { newImage.setSize(Long.parseLong(xmlRpcStruct.get("capacity").toString())); } if (xmlRpcStruct.containsKey("truesize")) { newImage.setActualSizeInBytes(Long.parseLong(xmlRpcStruct.get("truesize").toString())); } if (xmlRpcStruct.containsKey("ctime")) { long secsSinceEpoch = Long.parseLong(xmlRpcStruct.get("ctime").toString()); newImage.setCreationDate(MakeDTFromCTime(secsSinceEpoch)); } if (xmlRpcStruct.containsKey("mtime")) { long secsSinceEpoch = Long.parseLong(xmlRpcStruct.get("mtime").toString()); newImage.setLastModifiedDate(MakeDTFromCTime(secsSinceEpoch)); } if (xmlRpcStruct.containsKey("domain")) { newImage.setStorageIds( new ArrayList<Guid>(Arrays.asList(new Guid(xmlRpcStruct.get("domain").toString())))); } if (xmlRpcStruct.containsKey("image")) { newImage.setimage_group_id(new Guid(xmlRpcStruct.get("image").toString())); } if (xmlRpcStruct.containsKey("type")) { newImage.setVolumeType( EnumUtils.valueOf(VolumeType.class, xmlRpcStruct.get("type").toString(), true)); } if (xmlRpcStruct.containsKey("format")) { newImage.setvolumeFormat( EnumUtils.valueOf(VolumeFormat.class, xmlRpcStruct.get("format").toString(), true)); } } catch (RuntimeException ex) { log.errorFormat("irsBroker::buildImageEntity::Failed building DIskImage"); printReturnValue(); log.error(ex.getMessage(), ex); newImage = null; } return newImage; }
@Test public void testGetDiskAliasWithDefaultNotNullAlias() { disk1.setDiskAlias("alias"); assertEquals("alias", ImagesHandler.getDiskAliasWithDefault(disk1, "default")); }
@Override public int compare(DiskImage x, DiskImage y) { return DateTimeUtils.getTimeOfDay(x.getlastModified()) .compareTo(DateTimeUtils.getTimeOfDay(y.getlastModified())); }
private static DiskImage addTestDisk(VM vm, Guid snapshotId) { Guid imageId = Guid.newGuid(); DiskImage disk = new DiskImage(); disk.setImageId(imageId); disk.setId(Guid.newGuid()); disk.setVolumeType(VolumeType.Sparse); disk.setvolumeFormat(VolumeFormat.COW); disk.setDiskInterface(DiskInterface.VirtIO); disk.setStoragePoolId(vm.getStoragePoolId()); disk.setActive(Boolean.TRUE); disk.setPlugged(Boolean.TRUE); disk.setReadOnly(Boolean.FALSE); disk.setVmSnapshotId(snapshotId); disk.setImageStatus(ImageStatus.OK); disk.setAppList(""); disk.setDescription(""); vm.getDiskList().add(disk); vm.getDiskMap().put(imageId, disk); return disk; }