예제 #1
0
  private String getMigrationNetworkIp() {

    if (!FeatureSupported.migrationNetwork(getVm().getVdsGroupCompatibilityVersion())) {
      return null;
    }

    Network migrationNetwork = null;

    // Find migrationNetworkCluster
    List<Network> allNetworksInCluster = getNetworkDao().getAllForCluster(getVm().getVdsGroupId());

    for (Network tempNetwork : allNetworksInCluster) {
      if (tempNetwork.getCluster().isMigration()) {
        migrationNetwork = tempNetwork;
        break;
      }
    }

    if (migrationNetwork != null) {

      // assure migration network is active on source host
      if (getMigrationNetworkAddress(getVds().getId(), migrationNetwork.getName()) == null) {
        return null;
      }

      // find migration IP address on destination host
      return getMigrationNetworkAddress(getDestinationVds().getId(), migrationNetwork.getName());
    }

    return null;
  }
예제 #2
0
 private boolean isTunnelMigrationUsed() {
   if (!FeatureSupported.tunnelMigration(getVm().getVdsGroupCompatibilityVersion())) {
     return false;
   }
   // if vm has no override for tunnel migration (its null),
   // use cluster's setting
   return getVm().getTunnelMigration() != null
       ? getVm().getTunnelMigration()
       : getVdsGroup().isTunnelMigration();
 }
예제 #3
0
  /**
   * Actually process the VM device update in DB.
   *
   * @param vm
   */
  private void processVmDevices(Map vm) {
    if (vm == null || vm.get(VdsProperties.vm_guid) == null) {
      log.error("Received NULL VM or VM id when processing VM devices, abort.");
      return;
    }

    Guid vmId = new Guid((String) vm.get(VdsProperties.vm_guid));
    Set<Guid> processedDevices = new HashSet<Guid>();
    List<VmDevice> devices = getDbFacade().getVmDeviceDao().getVmDeviceByVmId(vmId);
    Map<VmDeviceId, VmDevice> deviceMap = Entities.businessEntitiesById(devices);

    for (Object o : (Object[]) vm.get(VdsProperties.Devices)) {
      Map device = (Map<String, Object>) o;
      if (device.get(VdsProperties.Address) == null) {
        logDeviceInformation(vmId, device);
        continue;
      }

      Guid deviceId = getDeviceId(device);
      VmDevice vmDevice = deviceMap.get(new VmDeviceId(deviceId, vmId));
      String logicalName = null;
      if (deviceId != null
          && FeatureSupported.reportedDisksLogicalNames(
              getVdsManager().getGroupCompatibilityVersion())
          && VmDeviceType.DISK.getName().equals(device.get(VdsProperties.Device))) {
        try {
          logicalName =
              getDeviceLogicalName((Map<?, ?>) vm.get(VdsProperties.GuestDiskMapping), deviceId);
        } catch (Exception e) {
          log.error(
              "error while getting device name when processing, vm '{}', device info '{}' with exception, skipping '{}'",
              vmId,
              device,
              e.getMessage());
          log.error("Exception", e);
        }
      }

      if (deviceId == null || vmDevice == null) {
        deviceId = addNewVmDevice(vmId, device, logicalName);
      } else {
        vmDevice.setIsPlugged(Boolean.TRUE);
        vmDevice.setAddress(((Map<String, String>) device.get(VdsProperties.Address)).toString());
        vmDevice.setAlias(StringUtils.defaultString((String) device.get(VdsProperties.Alias)));
        vmDevice.setLogicalName(logicalName);
        addVmDeviceToList(vmDevice);
      }

      processedDevices.add(deviceId);
    }

    handleRemovedDevices(vmId, processedDevices, devices);
  }
예제 #4
0
  /**
   * Checking that the interfaces are all configured, interfaces with no network are allowed only if
   * network linking is supported.
   *
   * @return true if all VM network interfaces are attached to existing cluster networks, or to no
   *     network (when network linking is supported).
   */
  protected ValidationResult validateInterfacesConfigured(VM vm) {
    for (VmNetworkInterface nic : vm.getInterfaces()) {
      if (nic.getVnicProfileId() == null) {
        return FeatureSupported.networkLinking(vm.getVdsGroupCompatibilityVersion())
            ? ValidationResult.VALID
            : new ValidationResult(
                VdcBllMessages.ACTION_TYPE_FAILED_INTERFACE_NETWORK_NOT_CONFIGURED);
      }
    }

    return ValidationResult.VALID;
  }
예제 #5
0
  @Override
  protected boolean canDoAction() {
    if (getVm() == null) {
      return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_VM_NOT_FOUND);
    }
    if (getVm().getStatus() != VMStatus.Up) {
      return failVmStatusIllegal();
    }
    if (!FeatureSupported.vmSlaPolicy(getVm().getVdsGroupCompatibilityVersion())) {
      return failCanDoAction(EngineMessage.VM_SLA_POLICY_NOT_SUPPORTED);
    }

    return true;
  }
예제 #6
0
  private Boolean getMigrateCompressed() {
    if (FeatureSupported.migrationCompression(getVm().getVdsGroupCompatibilityVersion())) {
      if (getVm().getMigrateCompressed() != null) {
        return getVm().getMigrateCompressed();
      }

      if (getVdsGroup().getMigrateCompressed() != null) {
        return getVdsGroup().getMigrateCompressed();
      }

      return Config.getValue(ConfigValues.DefaultMigrationCompression);
    }

    return null;
  }
예제 #7
0
  private Boolean getAutoConverge() {
    if (FeatureSupported.autoConvergence(getVm().getVdsGroupCompatibilityVersion())) {
      if (getVm().getAutoConverge() != null) {
        return getVm().getAutoConverge();
      }

      if (getVdsGroup().getAutoConverge() != null) {
        return getVdsGroup().getAutoConverge();
      }

      return Config.getValue(ConfigValues.DefaultAutoConvergence);
    }

    return null;
  }
예제 #8
0
 protected void getDowntime() {
   if (FeatureSupported.migrateDowntime(getVm().getVdsGroupCompatibilityVersion())) {
     try {
       VDSReturnValue retVal =
           runVdsCommand(
               VDSCommandType.MigrateStatus,
               new MigrateStatusVDSCommandParameters(getDestinationVdsId(), getVmId()));
       if (retVal != null) {
         actualDowntime = (Integer) retVal.getReturnValue();
       }
     } catch (EngineException e) {
       migrationErrorCode = e.getErrorCode();
     }
   }
 }
예제 #9
0
  /**
   * @param clusterNetworksNames cluster logical networks names
   * @param interfaceNetworkNames VM interface network names
   * @return true if all VM network interfaces are attached to existing cluster networks
   */
  protected ValidationResult validateInterfacesAttachedToClusterNetworks(
      VM vm, final Set<String> clusterNetworkNames, final Set<String> interfaceNetworkNames) {

    Set<String> result = new HashSet<String>(interfaceNetworkNames);
    result.removeAll(clusterNetworkNames);
    if (FeatureSupported.networkLinking(vm.getVdsGroupCompatibilityVersion())) {
      result.remove(null);
    }

    // If after removing the cluster network names we still have objects, then we have interface on
    // networks that
    // aren't attached to the cluster
    return result.isEmpty()
        ? ValidationResult.VALID
        : new ValidationResult(
            VdcBllMessages.ACTION_TYPE_FAILED_NETWORK_NOT_IN_CLUSTER,
            String.format("$networks %1$s", StringUtils.join(result, ",")));
  }
  protected boolean validate() {
    VM vm = parentCommand.getVm();
    if (vm == null) {
      parentCommand.addCanDoActionMessage(EngineMessage.ACTION_TYPE_FAILED_VM_NOT_FOUND);
      return false;
    } else {
      targetCluster = DbFacade.getInstance().getVdsGroupDao().get(targetClusterId);
      if (targetCluster == null) {
        parentCommand.addCanDoActionMessage(EngineMessage.VM_CLUSTER_IS_NOT_VALID);
        return false;
      }

      // Check that the target cluster is in the same data center.
      if (!targetCluster.getStoragePoolId().equals(vm.getStoragePoolId())) {
        parentCommand.addCanDoActionMessage(
            EngineMessage.VM_CANNOT_MOVE_TO_CLUSTER_IN_OTHER_STORAGE_POOL);
        return false;
      }

      List<VmNic> interfaces = DbFacade.getInstance().getVmNicDao().getAllForVm(vm.getId());

      Version clusterCompatibilityVersion = targetCluster.getCompatibilityVersion();
      if (!validateDestinationClusterContainsNetworks(interfaces)
          || !validateNics(interfaces, clusterCompatibilityVersion)) {
        return false;
      }

      // Check if VM static parameters are compatible for new cluster.
      boolean isCpuSocketsValid =
          AddVmCommand.checkCpuSockets(
              vm.getStaticData().getNumOfSockets(),
              vm.getStaticData().getCpuPerSocket(),
              vm.getStaticData().getThreadsPerCpu(),
              clusterCompatibilityVersion.getValue(),
              parentCommand.getReturnValue().getCanDoActionMessages());
      if (!isCpuSocketsValid) {
        return false;
      }

      // Check that the USB policy is legal
      if (!VmHandler.isUsbPolicyLegal(
          vm.getUsbPolicy(),
          vm.getOs(),
          targetCluster,
          parentCommand.getReturnValue().getCanDoActionMessages())) {
        return false;
      }

      // Check if the display type is supported
      if (!VmHandler.isGraphicsAndDisplaySupported(
          vm.getOs(),
          VmDeviceUtils.getGraphicsTypesOfEntity(vm.getId()),
          vm.getDefaultDisplayType(),
          parentCommand.getReturnValue().getCanDoActionMessages(),
          clusterCompatibilityVersion)) {
        return false;
      }

      if (VmDeviceUtils.hasVirtioScsiController(vm.getId())) {
        // Verify cluster compatibility
        if (!FeatureSupported.virtIoScsi(targetCluster.getCompatibilityVersion())) {
          return parentCommand.failCanDoAction(
              EngineMessage.VIRTIO_SCSI_INTERFACE_IS_NOT_AVAILABLE_FOR_CLUSTER_LEVEL);
        }

        // Verify OS compatibility
        if (!VmHandler.isOsTypeSupportedForVirtioScsi(
            vm.getOs(),
            targetCluster.getCompatibilityVersion(),
            parentCommand.getReturnValue().getCanDoActionMessages())) {
          return false;
        }
      }

      // A existing VM cannot be changed into a cluster without a defined architecture
      if (targetCluster.getArchitecture() == ArchitectureType.undefined) {
        return parentCommand.failCanDoAction(
            EngineMessage.ACTION_TYPE_FAILED_CLUSTER_UNDEFINED_ARCHITECTURE);
      } else if (targetCluster.getArchitecture() != vm.getClusterArch()) {
        return parentCommand.failCanDoAction(
            EngineMessage.ACTION_TYPE_FAILED_VM_CLUSTER_DIFFERENT_ARCHITECTURES);
      }
    }
    return true;
  }
  private Map<String, Object> generateNetworks() {
    Map<String, Object> networks = new HashMap<String, Object>();
    NetworkQoSDao qosDao = getDbFacade().getQosDao();
    for (Network network : getParameters().getNetworks()) {
      Map<String, Object> opts = new HashMap<String, Object>();
      VdsNetworkInterface iface =
          findNetworkInterface(
              network.getName(), getParameters().getInterfaces(), getParameters().getBonds());
      String ifaceNameWithoutVlan = NetworkUtils.stripVlan(iface);
      Boolean bonded = findInterfaceByName(ifaceNameWithoutVlan).getBonded();
      String type = (bonded != null && bonded) ? "bonding" : "nic";
      opts.put(type, ifaceNameWithoutVlan);
      if (NetworkUtils.isVlan(network)) {
        opts.put("vlan", network.getVlanId().toString());
      }

      if (iface.getBootProtocol() != null) {
        addBootProtocol(opts, iface);
      }

      if (network.getMtu() == 0) {
        opts.put("mtu", NetworkUtils.getDefaultMtu().toString());
      } else {
        opts.put("mtu", String.valueOf(network.getMtu()));
      }

      opts.put("bridged", Boolean.toString(network.isVmNetwork()));
      if (network.isVmNetwork()) {
        opts.put(VdsProperties.STP, network.getStp() ? "yes" : "no");
      }

      VDS host = getDbFacade().getVdsDao().get(getParameters().getVdsId());
      Version version = host.getVdsGroupCompatibilityVersion();
      if (qosConfiguredOnInterface(iface, network) && FeatureSupported.hostNetworkQos(version)) {
        NetworkQosMapper qosMapper =
            new NetworkQosMapper(
                opts, VdsProperties.HOST_QOS_INBOUND, VdsProperties.HOST_QOS_OUTBOUND);
        qosMapper.serialize(
            iface.isQosOverridden() ? iface.getQos() : qosDao.get(network.getQosId()));
      }

      Set<Version> supportedClusterVersionsSet = host.getSupportedClusterVersionsSet();
      if (supportedClusterVersionsSet == null || supportedClusterVersionsSet.isEmpty()) {
        log.warnFormat(
            "Host {0} ({1}) doesn't contain Supported Cluster Versions, therefore 'defaultRoute'"
                + " will not be sent via the SetupNetworks",
            host.getName(), host.getId());
      } else if (FeatureSupported.defaultRoute(Collections.max(supportedClusterVersionsSet))
          && NetworkUtils.isManagementNetwork(network)
          && (iface.getBootProtocol() == NetworkBootProtocol.DHCP
              || (iface.getBootProtocol() == NetworkBootProtocol.STATIC_IP
                  && StringUtils.isNotEmpty(iface.getGateway())))) {
        opts.put(DEFAULT_ROUTE, Boolean.TRUE);
      }

      if (iface.hasCustomProperties()) {
        opts.put(VdsProperties.NETWORK_CUSTOM_PROPERTIES, iface.getCustomProperties());
      }

      networks.put(network.getName(), opts);
    }

    for (String net : getParameters().getRemovedNetworks()) {
      networks.put(net, REMOVE_OBJ);
    }

    return networks;
  }
  protected void buildVmProperties() {
    createInfo.put(VdsProperties.vm_guid, vm.getId().toString());
    createInfo.put(VdsProperties.vm_name, vm.getName());
    createInfo.put(VdsProperties.mem_size_mb, vm.getVmMemSizeMb());
    createInfo.put(VdsProperties.mem_guaranteed_size_mb, vm.getMinAllocatedMem());
    createInfo.put(VdsProperties.smartcardEnabled, Boolean.toString(vm.isSmartcardEnabled()));
    createInfo.put(VdsProperties.num_of_cpus, String.valueOf(vm.getNumOfCpus()));
    if (Config.<Boolean>getValue(ConfigValues.SendSMPOnRunVm)) {
      createInfo.put(VdsProperties.cores_per_socket, (Integer.toString(vm.getCpuPerSocket())));
      if (FeatureSupported.supportedInConfig(
          ConfigValues.HotPlugCpuSupported,
          vm.getVdsGroupCompatibilityVersion(),
          vm.getClusterArch())) {
        createInfo.put(
            VdsProperties.max_number_of_cpus,
            String.valueOf(
                Config.<Integer>getValue(
                    ConfigValues.MaxNumOfVmCpus, vm.getVdsGroupCompatibilityVersion().getValue())));
      }
    }
    final String compatibilityVersion = vm.getVdsGroupCompatibilityVersion().toString();
    addCpuPinning(compatibilityVersion);
    createInfo.put(VdsProperties.emulatedMachine, getVdsGroup().getEmulatedMachine());
    // send cipher suite and spice secure channels parameters only if ssl
    // enabled.
    if (Config.<Boolean>getValue(ConfigValues.SSLEnabled)) {
      createInfo.put(
          VdsProperties.spiceSslCipherSuite, Config.<String>getValue(ConfigValues.CipherSuite));
      createInfo.put(
          VdsProperties.SpiceSecureChannels,
          Config.<String>getValue(ConfigValues.SpiceSecureChannels, compatibilityVersion));
    }
    createInfo.put(VdsProperties.kvmEnable, vm.getKvmEnable().toString().toLowerCase());
    createInfo.put(VdsProperties.acpiEnable, vm.getAcpiEnable().toString().toLowerCase());

    createInfo.put(
        VdsProperties.Custom,
        VmPropertiesUtils.getInstance()
            .getVMProperties(vm.getVdsGroupCompatibilityVersion(), vm.getStaticData()));
    createInfo.put(VdsProperties.vm_type, "kvm"); // "qemu", "kvm"
    if (vm.isRunAndPause()) {
      createInfo.put(VdsProperties.launch_paused_param, "true");
    }
    if (vm.isUseHostCpuFlags()) {
      createInfo.put(VdsProperties.cpuType, "hostPassthrough");
    } else if (vm.getVdsGroupCpuFlagsData() != null) {
      createInfo.put(VdsProperties.cpuType, vm.getVdsGroupCpuFlagsData());
    }
    createInfo.put(VdsProperties.niceLevel, String.valueOf(vm.getNiceLevel()));
    if (vm.getCpuShares() > 0) {
      createInfo.put(VdsProperties.cpuShares, String.valueOf(vm.getCpuShares()));
    }
    if (!StringUtils.isEmpty(vm.getHibernationVolHandle())) {
      createInfo.put(VdsProperties.hiberVolHandle, vm.getHibernationVolHandle());
    }

    String keyboardLayout = vm.getDynamicData().getVncKeyboardLayout();
    if (keyboardLayout == null) {
      keyboardLayout = vm.getDefaultVncKeyboardLayout();
      if (keyboardLayout == null) {
        keyboardLayout = Config.<String>getValue(ConfigValues.VncKeyboardLayout);
      }
    }

    createInfo.put(VdsProperties.KeyboardLayout, keyboardLayout);
    if (osRepository.isLinux(vm.getVmOsId())) {
      createInfo.put(VdsProperties.PitReinjection, "false");
    }

    if (vm.getDisplayType() == DisplayType.vnc) {
      createInfo.put(VdsProperties.TabletEnable, "true");
    }
    createInfo.put(
        VdsProperties.transparent_huge_pages, vm.isTransparentHugePages() ? "true" : "false");
  }
예제 #13
0
  @Override
  protected boolean canDoAction() {
    final VM vm = getVm();

    if (vm == null) {
      return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_VM_NOT_FOUND);
    }

    if (!canRunActionOnNonManagedVm()) {
      return false;
    }

    VmValidator vmValidator = new VmValidator(vm);
    if (!validate(vmValidator.isVmPluggedDiskNotUsingScsiReservation())) {
      return false;
    }

    if (!FeatureSupported.isMigrationSupported(
        getVdsGroup().getArchitecture(), getVdsGroup().getCompatibilityVersion())) {
      return failCanDoAction(EngineMessage.MIGRATION_IS_NOT_SUPPORTED);
    }

    // If VM is pinned to host, no migration can occur
    if (vm.getMigrationSupport() == MigrationSupport.PINNED_TO_HOST) {
      return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_VM_IS_PINNED_TO_HOST);
    }

    if (vm.getMigrationSupport() == MigrationSupport.IMPLICITLY_NON_MIGRATABLE
        && !getParameters().isForceMigrationForNonMigratableVm()) {
      return failCanDoAction(
          EngineMessage
              .ACTION_TYPE_FAILED_VM_IS_NON_MIGRTABLE_AND_IS_NOT_FORCED_BY_USER_TO_MIGRATE);
    }

    switch (vm.getStatus()) {
      case MigratingFrom:
        return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_MIGRATION_IN_PROGRESS);

      case NotResponding:
        return failVmStatusIllegal();

      case Paused:
        if (vm.getVmPauseStatus() == VmPauseStatus.EIO) {
          return failCanDoAction(EngineMessage.MIGRATE_PAUSED_EIO_VM_IS_NOT_SUPPORTED);
        }
        break;

      default:
    }

    if (!vm.isQualifyToMigrate()) {
      return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_VM_IS_NOT_RUNNING);
    }

    if (!validate(
            vmValidator.vmNotHavingPluggedDiskSnapshots(
                EngineMessage.ACTION_TYPE_FAILED_VM_HAS_PLUGGED_DISK_SNAPSHOT))
        || !validate(vmValidator.vmNotHavingPassthroughVnics())) {
      return false;
    }

    if (getParameters().getTargetVdsGroupId() != null) {
      ChangeVmClusterValidator changeVmClusterValidator =
          new ChangeVmClusterValidator(this, getParameters().getTargetVdsGroupId());
      if (!changeVmClusterValidator.validate()) {
        return false;
      }
    }

    return validate(new SnapshotsValidator().vmNotDuringSnapshot(vm.getId()))
        // This check was added to prevent migration of VM while its disks are being migrated
        // TODO: replace it with a better solution
        && validate(
            new DiskImagesValidator(ImagesHandler.getPluggedActiveImagesForVm(vm.getId()))
                .diskImagesNotLocked())
        && schedulingManager.canSchedule(
            getVdsGroup(),
            getVm(),
            getVdsBlackList(),
            getParameters().getInitialHosts(),
            getDestinationHostList(),
            getReturnValue().getCanDoActionMessages());
  }
예제 #14
0
  @Override
  protected boolean canDoAction() {
    final VM vm = getVm();

    if (vm == null) {
      return failCanDoAction(VdcBllMessages.ACTION_TYPE_FAILED_VM_NOT_FOUND);
    }

    if (!canRunActionOnNonManagedVm()) {
      return false;
    }

    if (!FeatureSupported.isMigrationSupported(
        getVdsGroup().getArchitecture(), getVdsGroup().getcompatibility_version())) {
      return failCanDoAction(VdcBllMessages.MIGRATION_IS_NOT_SUPPORTED);
    }

    // If VM is pinned to host, no migration can occur
    if (vm.getMigrationSupport() == MigrationSupport.PINNED_TO_HOST) {
      return failCanDoAction(VdcBllMessages.ACTION_TYPE_FAILED_VM_IS_PINNED_TO_HOST);
    }

    if (vm.getMigrationSupport() == MigrationSupport.IMPLICITLY_NON_MIGRATABLE
        && !getParameters().isForceMigrationForNonMigratableVm()) {
      return failCanDoAction(
          VdcBllMessages
              .ACTION_TYPE_FAILED_VM_IS_NON_MIGRTABLE_AND_IS_NOT_FORCED_BY_USER_TO_MIGRATE);
    }

    switch (vm.getStatus()) {
      case MigratingFrom:
        return failCanDoAction(VdcBllMessages.ACTION_TYPE_FAILED_MIGRATION_IN_PROGRESS);

      case NotResponding:
        return failCanDoAction(
            VdcBllMessages.ACTION_TYPE_FAILED_VM_STATUS_ILLEGAL,
            LocalizedVmStatus.from(VMStatus.NotResponding));

      case Paused:
        if (vm.getVmPauseStatus() == VmPauseStatus.EIO) {
          return failCanDoAction(VdcBllMessages.MIGRATE_PAUSED_EIO_VM_IS_NOT_SUPPORTED);
        }
        break;

      default:
    }

    if (!vm.isQualifyToMigrate()) {
      return failCanDoAction(VdcBllMessages.ACTION_TYPE_FAILED_VM_IS_NOT_RUNNING);
    }

    VmValidator vmValidator = new VmValidator(vm);

    if (!validate(
        vmValidator.vmNotHavingPluggedDiskSnapshots(
            VdcBllMessages.ACTION_TYPE_FAILED_VM_HAS_PLUGGED_DISK_SNAPSHOT))) {
      return false;
    }

    if (getDestinationVds() != null && getDestinationVds().getStatus() != VDSStatus.Up) {
      addCanDoActionMessage(VdcBllMessages.VAR__HOST_STATUS__UP);
      return failCanDoAction(VdcBllMessages.ACTION_TYPE_FAILED_VDS_STATUS_ILLEGAL);
    }

    return validate(new SnapshotsValidator().vmNotDuringSnapshot(vm.getId()))
        // This check was added to prevent migration of VM while its disks are being migrated
        // TODO: replace it with a better solution
        && validate(
            new DiskImagesValidator(ImagesHandler.getPluggedActiveImagesForVm(vm.getId()))
                .diskImagesNotLocked())
        && SchedulingManager.getInstance()
            .canSchedule(
                getVdsGroup(),
                getVm(),
                getVdsBlackList(),
                getParameters().getInitialHosts(),
                getDestinationVdsId(),
                getReturnValue().getCanDoActionMessages());
  }
  @Override
  protected boolean canDoAction() {
    if (getVdsGroup() == null) {
      return failCanDoAction(EngineMessage.VDS_CLUSTER_IS_NOT_VALID);
    }

    // A Pool cannot be added in a cluster without a defined architecture
    if (getVdsGroup().getArchitecture() == ArchitectureType.undefined) {
      return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_CLUSTER_UNDEFINED_ARCHITECTURE);
    }

    VmPool pool = getVmPoolDao().getByName(getParameters().getVmPool().getName());
    if (pool != null
        && (getActionType() == VdcActionType.AddVmPoolWithVms
            || !pool.getVmPoolId().equals(getParameters().getVmPoolId()))) {
      return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_NAME_ALREADY_USED);
    }

    setStoragePoolId(getVdsGroup().getStoragePoolId());
    if (!validate(new StoragePoolValidator(getStoragePool()).isUp())) {
      return false;
    }

    // check if the selected template is compatible with Cluster architecture.
    if (!getVmTemplate().getId().equals(VmTemplateHandler.BLANK_VM_TEMPLATE_ID)
        && getVdsGroup().getArchitecture() != getVmTemplate().getClusterArch()) {
      return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_TEMPLATE_IS_INCOMPATIBLE);
    }

    if (!verifyAddVM()) {
      return false;
    }

    if (getVmTemplate().getDiskTemplateMap().values().size() != diskInfoDestinationMap.size()) {
      log.error(
          "Can not found any default active domain for one of the disks of template with id '{}'",
          getVmTemplate().getId());
      addCanDoActionMessage(EngineMessage.ACTION_TYPE_FAILED_MISSED_STORAGES_FOR_SOME_DISKS);
      return false;
    }

    List<Guid> storageIds = new ArrayList<>();
    for (DiskImage diskImage : diskInfoDestinationMap.values()) {
      Guid storageId = diskImage.getStorageIds().get(0);
      if (!storageIds.contains(storageId) && !areTemplateImagesInStorageReady(storageId)) {
        return false;
      }
      storageIds.add(storageId);
    }

    if (getActionType() == VdcActionType.AddVmPoolWithVms && getParameters().getVmsCount() < 1) {
      return failCanDoAction(EngineMessage.VM_POOL_CANNOT_CREATE_WITH_NO_VMS);
    }

    if (getParameters().getVmStaticData().isStateless()) {
      return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_VM_FROM_POOL_CANNOT_BE_STATELESS);
    }

    if (getParameters().getVmPool().getPrestartedVms()
        > getParameters().getVmPool().getAssignedVmsCount() + getParameters().getVmsCount()) {
      return failCanDoAction(
          EngineMessage.ACTION_TYPE_FAILED_PRESTARTED_VMS_CANNOT_EXCEED_VMS_COUNT);
    }

    if (Boolean.TRUE.equals(getParameters().isVirtioScsiEnabled())
        && !FeatureSupported.virtIoScsi(getVdsGroup().getCompatibilityVersion())) {
      return failCanDoAction(
          EngineMessage.VIRTIO_SCSI_INTERFACE_IS_NOT_AVAILABLE_FOR_CLUSTER_LEVEL);
    }
    if (!setAndValidateDiskProfiles()) {
      return false;
    }
    if (!setAndValidateCpuProfile()) {
      return false;
    }
    return checkDestDomains();
  }