Dudi Maroshi has uploaded a new change for review.
Change subject: engine: On vm replacement vialidate vm Numa config match host
Numa config
......................................................................
engine: On vm replacement vialidate vm Numa config match host Numa config
When vm is replaced from host A to host B. And has pinned NUMA configuration.
The vm NUMA configuration, is validated to match host B NUMA configuration.
The validatation is made in UpdateVmCommand at canDoAction().
The algorithm is:
1. Get destination host NUMA nodes into a set.
2. Iterate over vm NUMA nodes
2.1 If vm NUMA node is not referencing a NUMA node in the destination host set
fail the validation
Change-Id: If32c7fede611dd3d1d0efeaae41f57f8273b7e37
Bug-Url: https://bugzilla.redhat.com/1177259
Signed-off-by: Dudi Maroshi <[email protected]>
---
M
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmCommand.java
M
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllMessages.java
M backend/manager/modules/dal/src/main/resources/bundles/AppErrors.properties
M
frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/AppErrors.java
M
frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties
5 files changed, 101 insertions(+), 22 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/70/38770/1
diff --git
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmCommand.java
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmCommand.java
index 31ed265..9ad5c58 100644
---
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmCommand.java
+++
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmCommand.java
@@ -5,9 +5,11 @@
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
import org.apache.commons.codec.CharEncoding;
import org.apache.commons.codec.binary.Base64;
@@ -45,6 +47,7 @@
import org.ovirt.engine.core.common.businessentities.Snapshot;
import org.ovirt.engine.core.common.businessentities.VM;
import org.ovirt.engine.core.common.businessentities.VMStatus;
+import org.ovirt.engine.core.common.businessentities.VdsNumaNode;
import org.ovirt.engine.core.common.businessentities.VmBase;
import org.ovirt.engine.core.common.businessentities.VmDevice;
import org.ovirt.engine.core.common.businessentities.VmDeviceGeneralType;
@@ -80,7 +83,7 @@
import org.ovirt.engine.core.utils.linq.Predicate;
public class UpdateVmCommand<T extends VmManagementParametersBase> extends
VmManagementCommandBase<T>
- implements QuotaVdsDependent, RenamedEntityInfoProvider{
+ implements QuotaVdsDependent, RenamedEntityInfoProvider {
private static final Base64 BASE_64 = new Base64(0, null);
private VM oldVm;
private boolean quotaSanityOnly = false;
@@ -100,7 +103,8 @@
if (isVmExist()) {
Version clusterVersion = getVdsGroup().getCompatibilityVersion();
-
getVmPropertiesUtils().separateCustomPropertiesToUserAndPredefined(clusterVersion,
parameters.getVmStaticData());
+
getVmPropertiesUtils().separateCustomPropertiesToUserAndPredefined(clusterVersion,
+ parameters.getVmStaticData());
getVmPropertiesUtils().separateCustomPropertiesToUserAndPredefined(clusterVersion,
getVm().getStaticData());
}
VmHandler.updateDefaultTimeZone(parameters.getVmStaticData());
@@ -112,7 +116,6 @@
updateParametersVmFromInstanceType();
}
-
private VmPropertiesUtils getVmPropertiesUtils() {
return VmPropertiesUtils.getInstance();
@@ -190,16 +193,19 @@
if (rngDevs.isEmpty()) {
if (getParameters().getRngDevice() != null) {
RngDeviceParameters params = new
RngDeviceParameters(getParameters().getRngDevice(), true);
- rngCommandResult =
runInternalAction(VdcActionType.AddRngDevice, params,
cloneContextAndDetachFromParent());
+ rngCommandResult =
+ runInternalAction(VdcActionType.AddRngDevice,
params, cloneContextAndDetachFromParent());
}
} else {
if (getParameters().getRngDevice() == null) {
RngDeviceParameters params = new
RngDeviceParameters(rngDevs.get(0), true);
- rngCommandResult =
runInternalAction(VdcActionType.RemoveRngDevice, params,
cloneContextAndDetachFromParent());
+ rngCommandResult =
+ runInternalAction(VdcActionType.RemoveRngDevice,
params, cloneContextAndDetachFromParent());
} else {
RngDeviceParameters params = new
RngDeviceParameters(getParameters().getRngDevice(), true);
params.getRngDevice().setDeviceId(rngDevs.get(0).getDeviceId());
- rngCommandResult =
runInternalAction(VdcActionType.UpdateRngDevice, params,
cloneContextAndDetachFromParent());
+ rngCommandResult =
+ runInternalAction(VdcActionType.UpdateRngDevice,
params, cloneContextAndDetachFromParent());
}
}
@@ -300,12 +306,16 @@
watchdogParameters.setId(getParameters().getVmId());
if (getParameters().getWatchdog() == null) {
// there is a watchdog in the vm, there should not be any,
so let's delete
- runInternalAction(VdcActionType.RemoveWatchdog,
watchdogParameters, cloneContextAndDetachFromParent());
+ runInternalAction(VdcActionType.RemoveWatchdog,
+ watchdogParameters,
+ cloneContextAndDetachFromParent());
} else {
// there is a watchdog in the vm, we have to update.
watchdogParameters.setAction(getParameters().getWatchdog().getAction());
watchdogParameters.setModel(getParameters().getWatchdog().getModel());
- runInternalAction(VdcActionType.UpdateWatchdog,
watchdogParameters, cloneContextAndDetachFromParent());
+ runInternalAction(VdcActionType.UpdateWatchdog,
+ watchdogParameters,
+ cloneContextAndDetachFromParent());
}
}
@@ -349,8 +359,10 @@
private List<GraphicsDevice> getGraphicsDevices() {
if (cachedGraphics == null) {
- cachedGraphics = getBackend()
- .runInternalQuery(VdcQueryType.GetGraphicsDevices, new
IdQueryParameters(getParameters().getVmId())).getReturnValue();
+ cachedGraphics =
+ getBackend()
+ .runInternalQuery(VdcQueryType.GetGraphicsDevices,
+ new
IdQueryParameters(getParameters().getVmId())).getReturnValue();
}
return cachedGraphics;
}
@@ -566,7 +578,8 @@
// Check if number of monitors passed is legal
if (!VmHandler.isNumOfMonitorsLegal(
-
VmHandler.getResultingVmGraphics(VmDeviceUtils.getGraphicsTypesOfEntity(getVmId()),
getParameters().getGraphicsDevices()),
+
VmHandler.getResultingVmGraphics(VmDeviceUtils.getGraphicsTypesOfEntity(getVmId()),
+ getParameters().getGraphicsDevices()),
getParameters().getVmStaticData().getNumOfMonitors(),
getReturnValue().getCanDoActionMessages())) {
return
failCanDoAction(VdcBllMessages.ACTION_TYPE_FAILED_ILLEGAL_NUM_OF_MONITORS);
@@ -588,7 +601,7 @@
if (!AddVmCommand.checkCpuSockets(vmFromParams.getNumOfSockets(),
vmFromParams.getCpuPerSocket(),
getVdsGroup().getCompatibilityVersion()
- .toString(), getReturnValue().getCanDoActionMessages())) {
+ .toString(),
getReturnValue().getCanDoActionMessages())) {
return false;
}
@@ -599,7 +612,8 @@
}
// we save the content in base64 string
for (Map.Entry<String, String> entry :
getParameters().getVmPayload().getFiles().entrySet()) {
- entry.setValue(new
String(BASE_64.encode(entry.getValue().getBytes()),
Charset.forName(CharEncoding.UTF_8)));
+ entry.setValue(new
String(BASE_64.encode(entry.getValue().getBytes()),
+ Charset.forName(CharEncoding.UTF_8)));
}
}
@@ -622,14 +636,16 @@
// Check if the graphics and display from parameters are supported
if (!VmHandler.isGraphicsAndDisplaySupported(vmFromParams.getOs(),
-
VmHandler.getResultingVmGraphics(VmDeviceUtils.getGraphicsTypesOfEntity(getVmId()),
getParameters().getGraphicsDevices()),
+
VmHandler.getResultingVmGraphics(VmDeviceUtils.getGraphicsTypesOfEntity(getVmId()),
+ getParameters().getGraphicsDevices()),
vmFromParams.getDefaultDisplayType(),
getReturnValue().getCanDoActionMessages(),
getVdsGroup().getCompatibilityVersion())) {
return false;
}
- if
(!FeatureSupported.isMigrationSupported(getVdsGroup().getArchitecture(),
getVdsGroup().getCompatibilityVersion())
+ if
(!FeatureSupported.isMigrationSupported(getVdsGroup().getArchitecture(),
+ getVdsGroup().getCompatibilityVersion())
&& vmFromParams.getMigrationSupport() !=
MigrationSupport.PINNED_TO_HOST) {
return
failCanDoAction(VdcBllMessages.VM_MIGRATION_IS_NOT_SUPPORTED);
}
@@ -660,14 +676,16 @@
}
// Verify OS compatibility
- if
(!VmHandler.isOsTypeSupportedForVirtioScsi(vmFromParams.getOs(),
getVdsGroup().getCompatibilityVersion(),
+ if (!VmHandler.isOsTypeSupportedForVirtioScsi(vmFromParams.getOs(),
+ getVdsGroup().getCompatibilityVersion(),
getReturnValue().getCanDoActionMessages())) {
return false;
}
}
VmValidator vmValidator = createVmValidator(vmFromParams);
- if (Boolean.FALSE.equals(getParameters().isVirtioScsiEnabled()) &&
!validate(vmValidator.canDisableVirtioScsi(null))) {
+ if (Boolean.FALSE.equals(getParameters().isVirtioScsiEnabled())
+ && !validate(vmValidator.canDisableVirtioScsi(null))) {
return false;
}
@@ -691,7 +709,57 @@
return false;
}
+ // validate vm Numa pinning match host Numa nodes
+ if (vmFromParams.getMigrationSupport() ==
MigrationSupport.PINNED_TO_HOST &&
+ isReplacingNumaPinnedVm()) {
+ return
failCanDoAction(VdcBllMessages.VM_NUMA_NODE_MISMATCHED_HOST);
+ }
+
return true;
+ }
+
+ /*
+ * Identify replaced host: Match each vm Numa node Guid to dedicated host
Numa node. If there is NO match, the host
+ * was replaced.
+ */
+ private boolean isReplacingNumaPinnedVm() {
+ Guid dedicatedVdsGuid = getVm().getDedicatedVmForVds();
+ if (dedicatedVdsGuid == null)
+ return false;
+ // question for review: is it safe to assume vm run at least once
prior to replacement?
+ // question for review: Why getVm().getDynamicData().getLastVdsRunOn()
not working - relevant db column is
+ // empty, shell we fix?
+
+ // get dedicated host Numa nodes information
+ List<VdsNumaNode> hostNumaNodesList = getDbFacade().getVdsNumaNodeDAO()
+ .getAllVdsNumaNodeByVdsId(dedicatedVdsGuid);
+ if (hostNumaNodesList == null || hostNumaNodesList.size() == 0)
+ return false;
+
+ // Collect dedicatedVds Numa nodes Guids into a set
+ Set<Guid> hostNumaNodesGuidsSet = new HashSet<Guid>();
+ for (VdsNumaNode vdsNumaNode : hostNumaNodesList) {
+ hostNumaNodesGuidsSet.add(vdsNumaNode.getId());
+ }
+
+ // question for review: is it safe to read numaNodesList from
parameters
+ List<VmNumaNode> numaNodesList =
getParameters().getVmStaticData().getvNumaNodeList();
+ if (numaNodesList != null && numaNodesList.size() > 0) {
+ for (VmNumaNode vmNumaNode : numaNodesList) {
+ if (vmNumaNode.getVdsNumaNodeList() != null &&
vmNumaNode.getVdsNumaNodeList().size() > 0) {
+ Guid physicalNumaNodeGuid =
vmNumaNode.getVdsNumaNodeList().get(0).getFirst();
+ // continue if vmNumaNode is not pinned to physical Numa
node.
+ if (physicalNumaNodeGuid != null) {
+ // if vm Numa node NOT identified as dedicated host
Numa node, this is replacement command
+ if
(!hostNumaNodesGuidsSet.contains(physicalNumaNodeGuid)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ boolean retVal = false; // debug variable for error testing
+ return retVal;
}
protected boolean isDedicatedVdsExistOnSameCluster(VmBase vm,
@@ -728,8 +796,9 @@
/**
* check if we need to use running-configuration
- * @return true if vm is running and we change field that has
@EditableOnVmStatusField annotation
- * or runningConfiguration already exist
+ *
+ * @return true if vm is running and we change field that has
@EditableOnVmStatusField annotation or
+ * runningConfiguration already exist
*/
private boolean isRunningConfigurationNeeded() {
return getVm().isNextRunConfigurationExists() ||
@@ -765,7 +834,8 @@
final boolean isDedicatedVmForVdsChanged =
!(getVm().getDedicatedVmForVds() == null ?
getParameters().getVmStaticData().getDedicatedVmForVds() == null :
-
getVm().getDedicatedVmForVds().equals(getParameters().getVmStaticData().getDedicatedVmForVds()));
+
getVm().getDedicatedVmForVds().equals(getParameters().getVmStaticData()
+ .getDedicatedVmForVds()));
final boolean isCpuPinningChanged =
!(getVm().getCpuPinning() == null ?
@@ -795,7 +865,8 @@
protected Map<String, Pair<String, String>> getExclusiveLocks() {
if (!StringUtils.isBlank(getParameters().getVm().getName())) {
return Collections.singletonMap(getParameters().getVm().getName(),
-
LockMessagesMatchUtil.makeLockingPair(LockingGroup.VM_NAME,
VdcBllMessages.ACTION_TYPE_FAILED_VM_IS_BEING_UPDATED));
+ LockMessagesMatchUtil.makeLockingPair(LockingGroup.VM_NAME,
+
VdcBllMessages.ACTION_TYPE_FAILED_VM_IS_BEING_UPDATED));
}
return null;
}
@@ -839,6 +910,7 @@
}
return list;
}
+
@Override
public String getEntityType() {
return VdcObjectType.VM.getVdcObjectTranslation();
@@ -856,8 +928,9 @@
@Override
public void setEntityId(AuditLogableBase logable) {
- logable.setVmId(oldVm.getId());
+ logable.setVmId(oldVm.getId());
}
+
@Override
public void addQuotaPermissionSubject(List<PermissionSubject>
quotaPermissionList) {
// if only quota sanity is checked the user may use a quota he cannot
consume
diff --git
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllMessages.java
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllMessages.java
index 9d145a6..26c650f 100644
---
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllMessages.java
+++
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllMessages.java
@@ -415,6 +415,7 @@
VM_NUMA_NODE_PINNED_INDEX_ERROR(ErrorType.BAD_PARAMETERS),
VM_NUMA_NODE_MEMRORY_ERROR(ErrorType.BAD_PARAMETERS),
VM_NUMA_NODE_PREFERRED_NOT_PINNED_TO_SINGLE_NODE(ErrorType.BAD_PARAMETERS),
+ VM_NUMA_NODE_MISMATCHED_HOST(ErrorType.BAD_PARAMETERS),
CANNOT_PREVIEW_ACTIVE_SNAPSHOT(ErrorType.BAD_PARAMETERS),
VM_CANNOT_SUSPENDE_HAS_RUNNING_TASKS(ErrorType.CONFLICT),
VM_CANNOT_REMOVE_HAS_RUNNING_TASKS(ErrorType.CONFLICT),
diff --git
a/backend/manager/modules/dal/src/main/resources/bundles/AppErrors.properties
b/backend/manager/modules/dal/src/main/resources/bundles/AppErrors.properties
index f651363..af5a389 100644
---
a/backend/manager/modules/dal/src/main/resources/bundles/AppErrors.properties
+++
b/backend/manager/modules/dal/src/main/resources/bundles/AppErrors.properties
@@ -744,6 +744,7 @@
VM_NUMA_NODE_PINNED_INDEX_ERROR=NUMA node pinned index error.
VM_NUMA_NODE_MEMRORY_ERROR=NUMA node memory error.
VM_NUMA_NODE_PREFERRED_NOT_PINNED_TO_SINGLE_NODE=Preferred NUMA tune mode is
allowed for a single pinned Virtual NUMA Node.
+VM_NUMA_NODE_MISMATCHED_HOST= Cannot ${action} ${type}. Host replacement for
vm with pinned NUMA nodes, not allowed.
ACTION_TYPE_FAILED_TEMPLATE_NOT_FOUND_ON_EXPORT_DOMAIN=Cannot export VM.
Template ${TemplateName} does not exist on the export domain. if you want to
export VM without its Template please use TemplateMustExists=false
ACTION_TYPE_FAILED_VM_NOT_FOUND_ON_EXPORT_DOMAIN=Cannot delete VM, VM not
exists in export domain
ACTION_NOT_SUPPORTED_FOR_CLUSTER_POOL_LEVEL=The Action ${action} ${type} is
not supported for this Cluster or Data Center compatibility version
diff --git
a/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/AppErrors.java
b/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/AppErrors.java
index e66ea57..756eb5b 100644
---
a/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/AppErrors.java
+++
b/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/AppErrors.java
@@ -3460,6 +3460,9 @@
@DefaultStringValue("Preferred NUMA tune mode is allowed for a single
pinned Virtual NUMA Node.")
String VM_NUMA_NODE_PREFERRED_NOT_PINNED_TO_SINGLE_NODE();
+ @DefaultStringValue("Cannot ${action} ${type}: Host replacment for vm with
pinned NUMA nodes not allowed.")
+ String VM_NUMA_NODE_MISMATCHED_HOST();
+
@DefaultStringValue("$detailMessage it is not a Hosted Engine host.")
String VAR__DETAIL__NOT_HE_HOST();
diff --git
a/frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties
b/frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties
index dc00ce6..f66b2b7 100644
---
a/frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties
+++
b/frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties
@@ -150,6 +150,7 @@
VMT_CANNOT_UPDATE_VERSION_NAME=Cannot update the name of Sub-Templates, Only
the Version name can be updated.
DIRECTORY_GROUP_CANNOT_REMOVE_DIRECTORY_GROUP_ATTACHED_TO_VM=Cannot remove
Directory Group. Detach Directory Group from VM first.
VM_NOT_FOUND=VM not found
+VM_NUMA_NODE_MISMATCHED_HOST= Cannot ${action} ${type}. Host replacement for
vm with pinned NUMA nodes, not allowed.
ACTION_TYPE_FAILED_CLUSTER_UNDEFINED_ARCHITECTURE=Cannot ${action} ${type}.
The cluster does not have a defined architecture.
ACTION_TYPE_FAILED_VM_IN_PREVIEW=Cannot ${action} ${type}. VM is previewing a
Snapshot.
ACTION_TYPE_FAILED_STORAGE_DELETE_VMS_IN_PREVIEW=Cannot ${action} ${type}. The
following VMs are previewing a snapshot: ${vms}.
--
To view, visit https://gerrit.ovirt.org/38770
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: If32c7fede611dd3d1d0efeaae41f57f8273b7e37
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Dudi Maroshi <[email protected]>
_______________________________________________
Engine-patches mailing list
[email protected]
http://lists.ovirt.org/mailman/listinfo/engine-patches