package org.ovirt.engine.core.bll; import java.util.List; import org.ovirt.engine.core.common.AuditLogType; import org.ovirt.engine.core.common.action.VmManagementParametersBase; import org.ovirt.engine.core.common.businessentities.MigrationSupport; import org.ovirt.engine.core.common.businessentities.VDS; import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.businessentities.VmNetworkInterface; import org.ovirt.engine.core.common.businessentities.VmStatic; import org.ovirt.engine.core.common.businessentities.network; import org.ovirt.engine.core.common.queries.IsVmWithSameNameExistParameters; import org.ovirt.engine.core.common.queries.VdcQueryType; import org.ovirt.engine.core.common.validation.group.UpdateEntity; import org.ovirt.engine.core.common.vdscommands.IrsBaseVDSCommandParameters; import org.ovirt.engine.core.common.vdscommands.VDSCommandType; import org.ovirt.engine.core.compat.DateTime; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.compat.StringHelper; import org.ovirt.engine.core.dal.VdcBllMessages; import org.ovirt.engine.core.dal.dbbroker.DbFacade; import org.ovirt.engine.core.utils.linq.LinqUtils; import org.ovirt.engine.core.utils.linq.Predicate; import org.ovirt.engine.core.utils.vmproperties.VmPropertiesUtils; import org.ovirt.engine.core.utils.vmproperties.VmPropertiesUtils.VMCustomProperties; import org.ovirt.engine.core.utils.vmproperties.VmPropertiesUtils.ValidationError; public class UpdateVmCommand<T extends VmManagementParametersBase> extends VmManagementCommandBase<T> { private VmStatic mOldVmStatic; public UpdateVmCommand(T parameters) { super(parameters); } @Override public AuditLogType getAuditLogTypeValue() { return getSucceeded() ? AuditLogType.USER_UPDATE_VM : AuditLogType.USER_FAILED_UPDATE_VM; } @Override protected void ExecuteVmCommand() { if (getParameters().getVmStaticData() != null) { mOldVmStatic = getVm().getStaticData(); /** * patch */ getParameters().getVmStaticData().setcreation_date(mOldVmStatic.getcreation_date()); if (getParameters().getVmStaticData().getcreation_date().equals(DateTime.getMinValue()) || getParameters().getVmStaticData().getcreation_date().equals(DateTime.getMinValue())) { getParameters().getVmStaticData().setcreation_date(getNow()); } if (mOldVmStatic != null) { UpdateVmNetworks(); UpdateVmData(); if (((Boolean) Backend .getInstance() .getResourceManager() .RunVdsCommand(VDSCommandType.IsValid, new IrsBaseVDSCommandParameters(getVm().getstorage_pool_id())).getReturnValue()) .booleanValue()) { // Set the VM to null, to fetch it again from the DB ,instead from the cache. // We want to get the VM current data that was updated to the DB. setVm(null); UpdateVmInSpm(getVm().getstorage_pool_id(), new java.util.ArrayList<VM>(java.util.Arrays.asList(new VM[] { getVm() }))); } setSucceeded(true); } } } private void UpdateVmNetworks() { VmStatic dbVm = DbFacade.getInstance().getVmStaticDAO().get(getParameters().getVmStaticData().getId()); // check if the cluster has changed if (!dbVm.getvds_group_id().equals(getParameters().getVmStaticData().getvds_group_id())) { List<network> networks = DbFacade .getInstance() .getNetworkDAO() .getAllForCluster( getParameters().getVmStaticData().getvds_group_id()); List<VmNetworkInterface> interfaces = DbFacade.getInstance() .getVmNetworkInterfaceDAO() .getAllForVm(getParameters().getVmStaticData().getId()); for (final VmNetworkInterface iface : interfaces) { // LINQ 29456 // network net = networks.FirstOrDefault(n => iface.network_name // == n.name); // // if network not exists in cluster we remove the network to // interface connection // if (net == null) // { // iface.network_name = null; // DbFacade.Instance.updateVmInterface(iface.InterfaceDynamic); // } network net = LinqUtils.firstOrNull(networks, new Predicate<network>() { @Override public boolean eval(network n) { return iface.getNetworkName().equals(n.getname()); } }); // if network not exists in cluster we remove the network to // interface connection if (net == null) { iface.setNetworkName(null); DbFacade.getInstance().getVmNetworkInterfaceDAO().update(iface); } } } } @Override protected List<Class<?>> getValidationGroups() { addValidationGroup(UpdateEntity.class); return super.getValidationGroups(); } @Override protected void setActionMessageParameters() { addCanDoActionMessage(VdcBllMessages.VAR__ACTION__UPDATE); addCanDoActionMessage(VdcBllMessages.VAR__TYPE__VM); } @Override protected boolean canDoAction() { boolean retValue = false; List<ValidationError> validationErrors = null; String vmName = getParameters().getVm().getvm_name(); if (vmName == null || vmName.isEmpty()) { retValue = false; addCanDoActionMessage(VdcBllMessages.ACTION_TYPE_FAILED_NAME_MAY_NOT_BE_EMPTY); } else { // check that VM name is not too long boolean vmNameValidLength = isVmNameValidLength(getParameters().getVm()); if (!vmNameValidLength) { retValue = false; addCanDoActionMessage(VdcBllMessages.ACTION_TYPE_FAILED_NAME_LENGTH_IS_TOO_LONG); } else if (getVm().getStaticData() != null) { VM vm = DbFacade.getInstance().getVmDAO().getById(getVm().getStaticData().getId()); // Checking if a desktop with same name already exists VmStatic vmStaticDataFromParams = getParameters().getVmStaticData(); boolean exists = (Boolean) Backend .getInstance() .runInternalQuery(VdcQueryType.IsVmWithSameNameExist, new IsVmWithSameNameExistParameters(vmStaticDataFromParams.getvm_name())) .getReturnValue(); if (exists && (!StringHelper.EqOp(vm.getvm_name(), vmStaticDataFromParams.getvm_name()))) { addCanDoActionMessage(VdcBllMessages.ACTION_TYPE_FAILED_VM_ALREADY_EXIST); } else if (!(validationErrors = VmPropertiesUtils.validateVMProperties(vmStaticDataFromParams)).isEmpty()) { handleCustomPropertiesError(validationErrors, getReturnValue().getCanDoActionMessages()); } else if (vmStaticDataFromParams.getauto_startup() && vmStaticDataFromParams.getMigrationSupport() == MigrationSupport.PINNED_TO_HOST) { getReturnValue().getCanDoActionMessages().add( VdcBllMessages.ACTION_TYPE_FAILED_VM_CANNOT_BE_HIGHLY_AVAILABLE_AND_PINNED_TO_HOST .toString()); } else if (VmHandler.isMemorySizeLegal(vmStaticDataFromParams.getos(), vmStaticDataFromParams.getmem_size_mb(), getReturnValue().getCanDoActionMessages(), getVdsGroup().getcompatibility_version().toString())) { if (StringHelper.EqOp(vmStaticDataFromParams.getvm_name(), "")) { getReturnValue().getCanDoActionMessages() .add(VdcBllMessages.VM_NAME_CANNOT_BE_EMPTY.toString()); } else if (vm != null) { setCustomDefinedProperties(vmStaticDataFromParams); setCustomDefinedProperties(getVm().getStaticData()); retValue = VmHandler.mUpdateVmsStatic.IsUpdateValid(getVm().getStaticData(), vmStaticDataFromParams, vm.getstatus()); if (!retValue) { addCanDoActionMessage(VdcBllMessages.VM_CANNOT_UPDATE_ILLEGAL_FIELD); } else if (!getVm().getStaticData().getvds_group_id() .equals(vmStaticDataFromParams.getvds_group_id())) { addCanDoActionMessage(VdcBllMessages.VM_CANNOT_UPDATE_CLUSTER); retValue = false; } if (vmStaticDataFromParams.getdedicated_vm_for_vds() != null) { VDS vds = DbFacade.getInstance().getVdsDAO().get( new Guid(vmStaticDataFromParams.getdedicated_vm_for_vds().toString())); // if vds doesnt exist or not the same cluster if (vds == null || !vds.getvds_group_id().equals(vmStaticDataFromParams.getvds_group_id())) { addCanDoActionMessage(VdcBllMessages.VM_CANNOT_UPDATE_DEFAULT_VDS_NOT_VALID); retValue = false; } } if (vm.getnum_of_monitors() < vmStaticDataFromParams.getnum_of_monitors()) { // LINQ 29456 // List<DiskImageBase> allDisks = // DbFacade.Instance.GetImagesByVmGuid(VmId).Select(a // => // (DiskImageBase)a).ToList(); // List<Interface> interfaces = // DbFacade.Instance.getIterfacesByVmId(VmId); // retValue = // CheckPCIAndIDELimit(VmManagementParameters.VmStaticData.num_of_monitors, // interfaces, allDisks); List allDisks = DbFacade.getInstance().getDiskImageDAO().getAllForVm(getVmId()); List<VmNetworkInterface> interfaces = DbFacade.getInstance() .getVmNetworkInterfaceDAO().getAllForVm(getVmId()); retValue = CheckPCIAndIDELimit(vmStaticDataFromParams.getnum_of_monitors(), interfaces, allDisks, getReturnValue().getCanDoActionMessages()); } if (!VmTemplateCommand.IsVmPriorityValueLegal(vmStaticDataFromParams.getpriority(), getReturnValue().getCanDoActionMessages())) { retValue = false; } if (retValue && vm.getVmPoolId() != null && vmStaticDataFromParams.getis_stateless()) { addCanDoActionMessage(VdcBllMessages.ACTION_TYPE_FAILED_VM_FROM_POOL_CANNOT_BE_STATELESS); retValue = false; } } } if (retValue) { retValue = AddVmCommand.CheckCpuSockets(vmStaticDataFromParams.getnum_of_sockets(), vmStaticDataFromParams.getcpu_per_socket(), getVdsGroup().getcompatibility_version() .toString(), getReturnValue().getCanDoActionMessages()); } // Check id dedicated host is same as VM cluster if (retValue) { retValue = isDedicatedVdsOnSameCluster(getParameters().getVmStaticData()); } } } return retValue; } private void setCustomDefinedProperties(VmStatic vmStaticDataFromParams) { VMCustomProperties properties = VmPropertiesUtils.parseProperties(vmStaticDataFromParams.getCustomProperties()); vmStaticDataFromParams.setPredefinedProperties(properties.getPredefinedProperties()); vmStaticDataFromParams.setUserDefinedProperties(properties.getUseDefinedProperties()); } private void UpdateVmData() { DbFacade.getInstance().getVmStaticDAO().update(getParameters().getVmStaticData()); // VM vm = // ResourceManager.Instance.getVm(VmManagementParameters.VmStaticData.vm_guid); // if (vm != null) // { // vm.StaticData = VmManagementParameters.VmStaticData; // } } @Override public Guid getVmId() { if (super.getVmId().equals(Guid.Empty)) { super.setVmId(getParameters().getVmStaticData().getId()); } return super.getVmId(); } }