package org.ovirt.engine.core.bll.network.template;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import javax.inject.Inject;
import org.apache.commons.lang.StringUtils;
import org.ovirt.engine.core.bll.context.CommandContext;
import org.ovirt.engine.core.bll.utils.PermissionSubject;
import org.ovirt.engine.core.bll.validator.VmNicValidator;
import org.ovirt.engine.core.bll.validator.VmValidator;
import org.ovirt.engine.core.common.AuditLogType;
import org.ovirt.engine.core.common.VdcObjectType;
import org.ovirt.engine.core.common.action.AddVmTemplateInterfaceParameters;
import org.ovirt.engine.core.common.businessentities.VmDevice;
import org.ovirt.engine.core.common.businessentities.VmDeviceId;
import org.ovirt.engine.core.common.businessentities.VmEntityType;
import org.ovirt.engine.core.common.businessentities.network.VmNic;
import org.ovirt.engine.core.common.errors.EngineMessage;
import org.ovirt.engine.core.common.utils.VmDeviceType;
import org.ovirt.engine.core.common.validation.group.UpdateEntity;
import org.ovirt.engine.core.compat.Version;
import org.ovirt.engine.core.dao.VmDeviceDao;
import org.ovirt.engine.core.dao.network.VmNicDao;
public class UpdateVmTemplateInterfaceCommand<T extends AddVmTemplateInterfaceParameters>
extends VmTemplateInterfaceCommandBase<T> {
@Inject
private VmNicDao vmNicDao;
@Inject
private VmDeviceDao vmDeviceDao;
public UpdateVmTemplateInterfaceCommand(T parameters, CommandContext cmdContext) {
super(parameters, cmdContext);
}
@Override
protected void executeCommand() {
vmNicDao.update(getParameters().getInterface());
VmDevice vmDevice =
vmDeviceDao.get(new VmDeviceId(getParameters().getInterface().getId(),
getParameters().getVmTemplateId()));
vmDevice.setPlugged(getParameters().getInterface().isPlugged());
vmDevice.setDevice(getParameters().getInterface().isPassthrough() ? VmDeviceType.HOST_DEVICE.getName()
: VmDeviceType.BRIDGE.getName());
vmDeviceDao.update(vmDevice);
setSucceeded(true);
}
@Override
protected boolean validate() {
if (!super.validate()) {
return false;
}
if (!validate(linkedToTemplate())) {
return false;
}
List<VmNic> interfaces = vmNicDao.getAllForTemplate(getParameters().getVmTemplateId());
if (!validate(templateExists())) {
return false;
}
// Interface oldIface = interfaces.First(i => i.id ==
// AddVmInterfaceParameters.Interface.id);
VmNic oldIface = interfaces.stream()
.filter(i -> i.getId().equals(getParameters().getInterface().getId())).findFirst().orElse(null);
if (oldIface == null) {
addValidationMessage(EngineMessage.VM_INTERFACE_NOT_EXIST);
return false;
}
if (!updateVnicForBackwardCompatibility(oldIface)) {
return false;
}
// not relevant for instance types - will be checked when a VM will be created out of it
if (getVmTemplate().getTemplateType() != VmEntityType.INSTANCE_TYPE) {
Version clusterCompatibilityVersion = getCluster().getCompatibilityVersion();
VmNicValidator nicValidator = new VmNicValidator(getParameters().getInterface(), clusterCompatibilityVersion, getVmTemplate().getOsId());
if (!validate(nicValidator.isCompatibleWithOs())
|| !validate(nicValidator.profileValid(getVmTemplate().getClusterId()))
|| !validate(nicValidator.typeMatchesProfile())
|| !validate(nicValidator.passthroughIsLinked())) {
return false;
}
if (!checkPciAndIdeLimit(oldIface, new ArrayList<>(interfaces), clusterCompatibilityVersion)) {
return false;
}
}
if (!StringUtils.equals(oldIface.getName(), getInterfaceName()) && !interfaceNameUnique(interfaces)) {
return false;
}
return true;
}
private boolean checkPciAndIdeLimit(VmNic oldIface,
List<VmNic> interfaces,
Version clusterCompatibilityVersion) {
interfaces.remove(oldIface);
interfaces.add(getParameters().getInterface());
return validate(VmValidator.checkPciAndIdeLimit(getVmTemplate().getOsId(),
clusterCompatibilityVersion,
getVmTemplate().getNumOfMonitors(),
interfaces,
getTemplateDiskVmElements(),
getVmDeviceUtils().hasVirtioScsiController(getVmTemplate().getId()),
getVmDeviceUtils().hasWatchdog(getVmTemplate().getId()),
getVmDeviceUtils().hasMemoryBalloon(getVmTemplate().getId()),
getVmDeviceUtils().hasSoundDevice(getVmTemplate().getId())));
}
@Override
protected List<Class<?>> getValidationGroups() {
addValidationGroup(UpdateEntity.class);
return super.getValidationGroups();
}
/**
* Set the parameters for bll messages, such as type and action,
*/
@Override
protected void setActionMessageParameters() {
super.setActionMessageParameters();
addValidationMessage(EngineMessage.VAR__ACTION__UPDATE);
}
@Override
public AuditLogType getAuditLogTypeValue() {
return getSucceeded() ? AuditLogType.NETWORK_UPDATE_TEMPLATE_INTERFACE
: AuditLogType.NETWORK_UPDATE_TEMPLATE_INTERFACE_FAILED;
}
@Override
public List<PermissionSubject> getPermissionCheckSubjects() {
List<PermissionSubject> permissionList = super.getPermissionCheckSubjects();
VmNic nic = getParameters().getInterface();
if (nic != null && nic.getVnicProfileId() != null && getVmTemplate() != null) {
VmNic oldNic = vmNicDao.get(nic.getId());
if (oldNic == null || isVnicProfileChanged(oldNic, nic)) {
permissionList.add(new PermissionSubject(nic.getVnicProfileId(),
VdcObjectType.VnicProfile,
getActionType().getActionGroup()));
}
}
return permissionList;
}
private boolean isVnicProfileChanged(VmNic oldNic, VmNic newNic) {
return !Objects.equals(oldNic.getVnicProfileId(), newNic.getVnicProfileId());
}
}