package org.ovirt.engine.ui.uicommonweb.models.vms; import java.util.HashSet; import java.util.List; import java.util.Set; import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.businessentities.Quota; import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.businessentities.storage.Disk; import org.ovirt.engine.core.common.businessentities.storage.DiskImage; import org.ovirt.engine.core.common.businessentities.storage.DiskStorageType; import org.ovirt.engine.core.common.validation.VmActionByVmOriginTypeValidator; import org.ovirt.engine.core.compat.Version; import org.ovirt.engine.ui.uicommonweb.UICommand; import org.ovirt.engine.ui.uicommonweb.help.HelpTag; import org.ovirt.engine.ui.uicommonweb.models.EntityModel; import org.ovirt.engine.ui.uicompat.ConstantsManager; import org.ovirt.engine.ui.uicompat.UIConstants; import org.ovirt.engine.ui.uicompat.UIMessages; import org.ovirt.engine.ui.uicompat.external.StringUtils; public class InstanceImageLineModel extends EntityModel { public static final String CANCEL_DISK = "CancelDisk"; //$NON-NLS-1$ public static final String DISK = "_Disk"; //$NON-NLS-1$ private UIMessages messages = ConstantsManager.getInstance().getMessages(); private UIConstants constants = ConstantsManager.getInstance().getConstants(); private UICommand attachCommand; private UICommand createEditCommand; private EntityModel<AbstractDiskModel> diskModel = new EntityModel<>(); // if the disk already exists in the engine or is just created here but not yet submitted private boolean diskExists; private EntityModel<String> name = new EntityModel<>(); private InstanceImagesModel parentModel; private VM vm; private boolean active = true; private boolean changed; public InstanceImageLineModel(InstanceImagesModel parentModel) { this.parentModel = parentModel; attachCommand = new UICommand("attachCommand", this); //$NON-NLS-1$ createEditCommand = new UICommand("createEditCommand", this); //$NON-NLS-1$ } private void fillData() { if (diskModel.getEntity() == null) { return; } if (diskModel.getEntity() instanceof InstanceImagesAttachDiskModel) { List<EntityModel<DiskModel>> disks = ((InstanceImagesAttachDiskModel) diskModel.getEntity()).getSelectedDisks(); if (disks.size() != 0) { updateName(disks.get(0).getEntity()); } } else { updateName(diskModel.getEntity()); } } private void updateName(DiskModel diskModel) { Disk disk = diskModel.getDisk(); if (disk == null) { return; } String diskName = disk.getDiskAlias(); String size = Long.toString(disk.getSize()); if (disk.getDiskStorageType() == DiskStorageType.IMAGE || disk.getDiskStorageType() == DiskStorageType.CINDER) { size = Long.toString(((DiskImage) disk).getSizeInGigabytes()); } String type; if (diskExists) { type = constants.existingDisk(); } else if (getDiskModel().getEntity() instanceof InstanceImagesAttachDiskModel) { type = constants.attachingDisk(); } else { type = constants.creatingDisk(); } name.setEntity(messages.vmDialogDisk(diskName, size, type, diskModel.getIsBootable().getEntity() ? constants.bootDisk() : "")); } private void toggleActive() { if (vm != null && !VmActionByVmOriginTypeValidator.isCommandAllowed(vm, VdcActionType.UpdateVmDisk)) { active = false; } } public void initialize(Disk disk, VM vm) { this.vm = vm; active = true; diskExists = disk != null; toggleActive(); attachCommand.setIsAvailable(!diskExists && active); if (disk == null) { return; } final AbstractDiskModel model = new EditDiskModel() { @Override public void onSave() { if (validate()) { flush(); getDiskModel().setEntity(this); // Flagging the model as 'changed' // Todo: perform a deep differentiation analyze on the disks (original/edited) objects. InstanceImageLineModel.this.setChanged(true); // needed because the "entity" instances are the same so the event is not fired fillData(); setDiskModel(null); } } @Override public void updateInterface(Version clusterVersion) { InstanceImageLineModel.this.updateInterface(clusterVersion, this); } @Override protected void updateBootableDiskAvailable() { updateBootableFrom(parentModel.getAllCurrentDisksModels()); } }; model.setDisk(disk); model.setVm(vm); setupModelAsDialog(model, ConstantsManager.getInstance().getConstants().editVirtualDiskTitle(), HelpTag.edit_virtual_disk, "edit_virtual_disk"); //$NON-NLS-1$ model.initialize(); diskModel.setEntity(model); fillData(); } public EntityModel<AbstractDiskModel> getDiskModel() { return diskModel; } public EntityModel<String> getName() { return name; } public void setName(EntityModel<String> name) { this.name = name; } public boolean isGhost() { return diskModel.getEntity() == null; } public void attachDisk() { if (parentModel.getUnitVmModel().getSelectedCluster() == null || parentModel.getUnitVmModel().getSelectedDataCenter() == null) { return; } InstanceImagesAttachDiskModel model = new InstanceImagesAttachDiskModel() { @Override public void onSave() { if (validate()) { flush(); List<EntityModel<DiskModel>> selectedDisks = getSelectedDisks(); if (selectedDisks.size() == 1) { // only 0 or 1 is allowed setDisk(selectedDisks.iterator().next().getEntity().getDisk()); } getDiskModel().setEntity(this); InstanceImageLineModel.this.setChanged(true); setDiskModel(null); // from now on only editing is possible attachCommand.setIsAvailable(false); fillData(); } } @Override public void updateInterface(Version clusterVersion) { InstanceImageLineModel.this.updateInterface(clusterVersion, this); } @Override protected void updateBootableDiskAvailable() { updateBootableFrom(parentModel.getAllCurrentDisksModels()); } @Override protected List<Disk> getAttachedNotSubmittedDisks() { return parentModel.getNotYetAttachedNotAttachableDisks(); } }; VM realOrFakeVm = vm; Version compatibilityVersion = parentModel.getUnitVmModel().getSelectedCluster().getCompatibilityVersion(); if (realOrFakeVm == null) { realOrFakeVm = new VM(); realOrFakeVm.setId(null); realOrFakeVm.setClusterId(parentModel.getUnitVmModel().getSelectedCluster().getId()); realOrFakeVm.setStoragePoolId(parentModel.getUnitVmModel().getSelectedDataCenter().getId()); realOrFakeVm.setClusterCompatibilityVersion(compatibilityVersion); } model.setVm(realOrFakeVm); setupModelAsDialog(model, ConstantsManager.getInstance().getConstants().attachVirtualDiskTitle(), HelpTag.attach_virtual_disk, "attach_virtual_disk"); //$NON-NLS-1$ setDiskModel(model); model.initialize(parentModel.getAllCurrentDisksModels()); maybeLoadAttachableDisks(model); } private void maybeLoadAttachableDisks(InstanceImagesAttachDiskModel model) { if (model.getVm().getId() == null) { Integer osType = parentModel.getUnitVmModel().getOSType().getSelectedItem(); Version compatibilityVersion = parentModel.getUnitVmModel().getSelectedCluster().getCompatibilityVersion(); model.loadAttachableDisks(osType, compatibilityVersion, getDisk()); } else { model.loadAttachableDisks(getDisk()); } } public void createEditDisk() { if (parentModel.getUnitVmModel().getSelectedCluster() == null || parentModel.getUnitVmModel().getSelectedDataCenter() == null) { return; } if (getDiskModel().getEntity() == null) { showNewDialog(); } else { showPreviouslyShownDialog(); } } private void showPreviouslyShownDialog() { getDiskModel().getEntity().updateBootableFrom(parentModel.getAllCurrentDisksModels()); if (getDiskModel().getEntity() instanceof InstanceImagesAttachDiskModel) { // needed to re-filter in case the OS or the compatibility version changed maybeLoadAttachableDisks((InstanceImagesAttachDiskModel) getDiskModel().getEntity()); } setDiskModel(getDiskModel().getEntity()); } private void showNewDialog() { final AbstractDiskModel model = new NewDiskModel() { @Override public void onSave() { if (validate()) { flush(); getDiskModel().setEntity(this); InstanceImageLineModel.this.setChanged(true); setDiskModel(null); // the "new" turns into "edit" - no need for attach anymore attachCommand.setIsAvailable(false); fillData(); Disk disk = super.getDisk(); if (disk.getDiskStorageType() == DiskStorageType.IMAGE || disk.getDiskStorageType() == DiskStorageType.CINDER) { ((DiskImage) disk).setActive(true); } } } @Override public void updateInterface(Version clusterVersion) { InstanceImageLineModel.this.updateInterface(clusterVersion, this); } @Override protected void updateBootableDiskAvailable() { updateBootableFrom(parentModel.getAllCurrentDisksModels()); } }; VM vm = new VM(); vm.setClusterId(parentModel.getUnitVmModel().getSelectedCluster().getId()); vm.setStoragePoolId(parentModel.getUnitVmModel().getSelectedDataCenter().getId()); vm.setClusterCompatibilityVersion(parentModel.getUnitVmModel().getSelectedCluster().getCompatibilityVersion()); Quota selectedQuota = parentModel.getUnitVmModel().getQuota().getSelectedItem(); vm.setQuotaId(selectedQuota == null ? null : selectedQuota.getId()); model.setVm(vm); model.getSizeExtend().setIsAvailable(false); setupModelAsDialog(model, ConstantsManager.getInstance().getConstants().newVirtualDiskTitle(), HelpTag.new_virtual_disk, "new_virtual_disk"); //$NON-NLS-1$ setDiskModel(model); model.initialize(parentModel.getAllCurrentDisksModels()); if (model.getIsBootable().getIsChangable()) { model.getIsBootable().setEntity(true); } if (getVm() != null) { model.setVm(getVm()); ((NewDiskModel)model).updateSuggestedDiskAliasFromServer(); } else { String currentVmName = parentModel.getUnitVmModel().getName().getEntity(); if (!StringUtils.isEmpty(currentVmName)) { // if already set the VM name on the new VM dialog, suggest the name according to the name model.getAlias().setEntity(suggestAliasForNewVm(currentVmName)); } } } private String suggestAliasForNewVm(String currentVmName) { Set<String> aliases = createDiskAliasesList(); String suggestedAlias; int i = 0; do { i++; suggestedAlias = currentVmName + DISK + i; } while (aliases.contains(suggestedAlias)); return suggestedAlias; } private Set<String> createDiskAliasesList() { Set<String> res = new HashSet<>(); for (Disk disk : parentModel.getAllCurrentDisks()) { res.add(disk.getDiskAlias()); } return res; } private void setupModelAsDialog(AbstractDiskModel model, String title, HelpTag helpTag, String hashName) { model.setTitle(title); model.setHelpTag(helpTag); model.setHashName(hashName); UICommand cancelCommand = new UICommand(CANCEL_DISK, this); cancelCommand.setTitle(ConstantsManager.getInstance().getConstants().cancel()); cancelCommand.setIsCancel(true); model.setCancelCommand(cancelCommand); } private void setDiskModel(AbstractDiskModel model) { if (parentModel.getParentListModel() instanceof HasDiskWindow) { ((HasDiskWindow) parentModel.getParentListModel()).setDiskWindow(model); } } @Override public void executeCommand(UICommand command) { if (!active) { // don't listen to this commands anymore - no need to show any more windows return; } if (CANCEL_DISK.equals(command.getName())) { setDiskModel(null); } else if (command == createEditCommand) { createEditDisk(); } else if (command == attachCommand) { attachDisk(); } else { super.executeCommand(command); } } public boolean isBootable() { if (isGhost()) { return false; } return diskModel.getEntity().getIsBootable().getEntity(); } public Disk getDisk() { AbstractDiskModel diskModel = getDiskModel().getEntity(); if (diskModel == null) { return null; } if (diskModel.getDisk() != null) { return diskModel.getDisk(); } DiskStorageType diskStorageType = diskModel.getDiskStorageType().getEntity(); if (diskStorageType == DiskStorageType.IMAGE) { return diskModel.getDiskImage(); } if (diskStorageType == DiskStorageType.LUN) { return diskModel.getLunDisk(); } return null; } public boolean isDiskExists() { return diskExists; } public VM getVm() { return vm; } public UICommand getAttachCommand() { return attachCommand; } public UICommand getCreateEditCommand() { return createEditCommand; } public void setEnabled(boolean enabled) { attachCommand.setIsExecutionAllowed(enabled); createEditCommand.setIsExecutionAllowed(enabled); } public void deactivate() { active = false; } public void updateInterface(Version clusterVersion, AbstractDiskModel model) { model.getIsVirtioScsiEnabled().setEntity(Boolean.TRUE.equals(parentModel.getUnitVmModel().getIsVirtioScsiEnabled().getEntity())); model.updateInterfaceList(clusterVersion); } public boolean isChanged() { return changed; } public void setChanged(boolean changed) { this.changed = changed; } }