private PushButton createButton(final Pair<T, V> item, boolean plusButton) {
    final T value = item.getFirst();
    final V widget = item.getSecond();

    final PushButton button =
        new PushButton(new Image(plusButton ? resources.increaseIcon() : resources.decreaseIcon()));
    button.addStyleName(style.buttonStyle());
    button.addStyleName("buttonStyle_pfly_fix"); // $NON-NLS-1$

    button.addClickHandler(
        plusButton
            ? new ClickHandler() {

              @Override
              public void onClick(ClickEvent event) {
                getEntry(widget).removeLastButton();
                Pair<T, V> item = addGhostEntry();
                onAdd(item.getFirst(), item.getSecond());
              }
            }
            : new ClickHandler() {

              @Override
              public void onClick(ClickEvent event) {
                if (vetoRemoveWidget(item, value, widget)) {
                  return;
                }

                doRemoveItem(item, value, widget);
              }
            });

    return button;
  }
Пример #2
0
  private static GraphicsDevice getCompatibleGraphics(
      VmDeviceType videoDeviceType, Version clusterVersion, VmBase vmBase) {
    GraphicsDevice graphicsDevice = null;
    GraphicsType compatibleType = null;

    OsRepository osRepository = SimpleDependencyInjector.getInstance().get(OsRepository.class);
    for (Pair<GraphicsType, DisplayType> graphicsDisplayPair :
        osRepository.getGraphicsAndDisplays(vmBase.getOsId(), clusterVersion)) {
      if (graphicsDisplayPair.getSecond().getDefaultVmDeviceType() == videoDeviceType) {
        compatibleType = graphicsDisplayPair.getFirst();

        // previously to spice+vnc, QXL was only used by spice, so prefer spice if available
        if (videoDeviceType == VmDeviceType.QXL && compatibleType == GraphicsType.SPICE) {
          break;
        }
      }
    }

    if (compatibleType != null) {
      graphicsDevice = new GraphicsDevice(compatibleType.getCorrespondingDeviceType());
      graphicsDevice.setId(new VmDeviceId(Guid.newGuid(), vmBase.getId()));
    }

    return graphicsDevice;
  }
  /**
   * Retrieve a storage domain using a specified storage domain ID.
   *
   * @param storageDomainId the domain's ID
   * @return the storage domain
   */
  @SuppressWarnings("unchecked")
  protected StorageDomain getStorageDomainById(Guid storageDomainId) {
    VDSReturnValue returnValue;

    try {
      returnValue =
          executeHSMGetStorageDomainInfo(
              new HSMGetStorageDomainInfoVDSCommandParameters(
                  getParameters().getVdsId(), storageDomainId));
    } catch (RuntimeException e) {
      log.error(
          "Could not get info for storage domain ID: '{}': {}", storageDomainId, e.getMessage());
      log.debug("Exception", e);
      return null;
    }

    Pair<StorageDomainStatic, SANState> result =
        (Pair<StorageDomainStatic, SANState>) returnValue.getReturnValue();
    StorageDomainStatic storageDomainStatic = result.getFirst();
    storageDomainStatic.setStorageType(getParameters().getStorageType());

    StorageDomain storageDomain = new StorageDomain();
    storageDomain.setStorageStaticData(storageDomainStatic);

    return storageDomain;
  }
 @Override
 protected void executeVdsBrokerCommand() {
   result = getBroker().getStorageDomainInfo(getParameters().getStorageDomainId().toString());
   proceedProxyReturnValue();
   Pair<StorageDomainStatic, Guid> pairSdStatic =
       BuildStorageStaticFromXmlRpcStruct(result.storageInfo);
   pairSdStatic.getFirst().setId(getParameters().getStorageDomainId());
   setReturnValue(pairSdStatic);
 }
 @Override
 public M flush() {
   modelItems.clear();
   for (Pair<T, V> item : items) {
     T value = item.getFirst();
     if (!isGhost(value)) {
       modelItems.add(value);
     }
   }
   return model;
 }
  private static Pair<StorageDomainStatic, Guid> BuildStorageStaticFromXmlRpcStruct(
      Map<String, Object> xmlRpcStruct) {
    Pair<StorageDomainStatic, Guid> returnValue = new Pair<StorageDomainStatic, Guid>();
    StorageDomainStatic sdStatic = new StorageDomainStatic();
    if (xmlRpcStruct.containsKey("name")) {
      sdStatic.setStorageName(xmlRpcStruct.get("name").toString());
    }
    if (xmlRpcStruct.containsKey("type")) {
      sdStatic.setStorageType(
          EnumUtils.valueOf(StorageType.class, xmlRpcStruct.get("type").toString(), true));
    }
    if (xmlRpcStruct.containsKey("class")) {
      String domainType = xmlRpcStruct.get("class").toString();
      if ("backup".equalsIgnoreCase(domainType)) {
        sdStatic.setStorageDomainType(StorageDomainType.ImportExport);
      } else {
        sdStatic.setStorageDomainType(EnumUtils.valueOf(StorageDomainType.class, domainType, true));
      }
    }
    if (xmlRpcStruct.containsKey("version")) {
      sdStatic.setStorageFormat(StorageFormatType.forValue(xmlRpcStruct.get("version").toString()));
    }
    if (sdStatic.getStorageType() != StorageType.UNKNOWN) {
      if (sdStatic.getStorageType().isFileDomain() && xmlRpcStruct.containsKey("remotePath")) {
        String path = xmlRpcStruct.get("remotePath").toString();
        List<StorageServerConnections> connections =
            DbFacade.getInstance().getStorageServerConnectionDao().getAllForStorage(path);
        if (connections.isEmpty()) {
          sdStatic.setConnection(new StorageServerConnections());
          sdStatic.getConnection().setconnection(path);
          sdStatic.getConnection().setstorage_type(sdStatic.getStorageType());
        } else {
          sdStatic.setStorage(connections.get(0).getid());
          sdStatic.setConnection(connections.get(0));
        }
      } else if (sdStatic.getStorageType() != StorageType.NFS
          && (xmlRpcStruct.containsKey("vguuid"))) {
        sdStatic.setStorage(xmlRpcStruct.get("vguuid").toString());
      }
    }
    if (xmlRpcStruct.containsKey("state")) {
      sdStatic.setSanState(
          EnumUtils.valueOf(
              SANState.class, xmlRpcStruct.get("state").toString().toUpperCase(), false));
    }
    returnValue.setFirst(sdStatic);
    Object[] poolUUIDs = (Object[]) xmlRpcStruct.get("pool");
    if (poolUUIDs.length != 0) {
      returnValue.setSecond(Guid.createGuidFromString(poolUUIDs[0].toString()));
    }

    return returnValue;
  }
 @Override
 protected void executeQueryCommand() {
   ArrayList<StorageDomain> returnValue = new ArrayList<>();
   VDSReturnValue vdsReturnValue =
       runVdsCommand(
           VDSCommandType.HSMGetStorageDomainsList,
           new HSMGetStorageDomainsListVDSCommandParameters(
               getParameters().getId(),
               Guid.Empty,
               null,
               getParameters().getStorageDomainType(),
               getParameters().getPath()));
   if (vdsReturnValue.getSucceeded()) {
     ArrayList<Guid> guidsFromIrs = (ArrayList<Guid>) vdsReturnValue.getReturnValue();
     HashSet<Guid> guidsFromDb = new HashSet<>();
     if (guidsFromIrs.size() > 0) {
       List<StorageDomain> domainsInDb = storageDomainDao.getAll();
       for (StorageDomain domain : domainsInDb) {
         guidsFromDb.add(domain.getId());
       }
       for (Guid domainId : guidsFromIrs) {
         if (!guidsFromDb.contains(domainId)) {
           Pair<StorageDomainStatic, Guid> domainFromIrs =
               (Pair<StorageDomainStatic, Guid>)
                   runVdsCommand(
                           VDSCommandType.HSMGetStorageDomainInfo,
                           new HSMGetStorageDomainInfoVDSCommandParameters(
                               getParameters().getId(), domainId))
                       .getReturnValue();
           StorageDomain domain = new StorageDomain();
           domain.setStorageStaticData(domainFromIrs.getFirst());
           domain.setStoragePoolId(domainFromIrs.getSecond());
           if (getParameters().getStorageFormatType() == null
               || getParameters().getStorageFormatType() == domain.getStorageFormat()) {
             if (getParameters().getStorageType() != null
                 && domain.getStorageType().getValue()
                     != getParameters().getStorageType().getValue()) {
               log.warn(
                   "The storage type of domain {} has been changed from {} to {}",
                   domain.getStorageName(),
                   domain.getStorageType().toString(),
                   getParameters().getStorageType().toString());
               domain.setStorageType(getParameters().getStorageType());
             }
             returnValue.add(domain);
           }
         }
       }
     }
     getQueryReturnValue().setReturnValue(returnValue);
   }
 }
 @Override
 protected void executeQueryCommand() {
   Guid vdsGroupId = getParameters().getId();
   List<VM> vms = getDbFacade().getVmDao().getAllForVdsGroup(vdsGroupId);
   List<Pair<Guid, VmNumaNode>> nodes =
       getDbFacade().getVmNumaNodeDao().getVmNumaNodeInfoByVdsGroupId(vdsGroupId);
   for (VM vm : vms) {
     for (Pair<Guid, VmNumaNode> pairnode : nodes) {
       if (vm.getId().equals(pairnode.getFirst())) {
         vm.getvNumaNodeList().add(pairnode.getSecond());
       }
     }
   }
   getQueryReturnValue().setReturnValue(vms);
 }
Пример #9
0
  /**
   * lock Vms which has db entity i.e they are managed by a VmManager
   *
   * @param pair
   * @return true if lock acquired
   */
  private boolean tryLockVmForUpdate(Pair<VM, VmInternalData> pair) {
    Guid vmId = getVmId(pair);

    if (vmId != null) {
      VmManager vmManager = getResourceManager().getVmManager(vmId);

      if (vmManager.trylock()) {
        if (!vmManager.isLatestData(pair.getSecond(), vdsManager.getVdsId())) {
          log.warn(
              "skipping VM '{}' from this monitoring cycle"
                  + " - newer VM data was already processed",
              vmId);
          vmManager.unlock();
        } else if (vmManager.getVmDataChangedTime() != null
            && fetchTime - vmManager.getVmDataChangedTime() <= 0) {
          log.warn(
              "skipping VM '{}' from this monitoring cycle"
                  + " - the VM data has changed since fetching the data",
              vmId);
          vmManager.unlock();
        } else {
          // store the locked managers to finally release them at the end of the cycle
          vmManagers.put(vmId, vmManager);
          return true;
        }
      } else {
        log.debug(
            "skipping VM '{}' from this monitoring cycle" + " - the VM is locked by its VmManager ",
            getVmId(pair));
      }
    }
    return false;
  }
Пример #10
0
  protected T getMethod() {
    if (method == null) {
      VdsStatic vdsStatic = getAndSetVdsStatic();

      Pair<String, URL> urlInfo =
          XmlRpcUtils.getConnectionUrl(
              vdsStatic.getHostName(),
              vdsStatic.getPort(),
              "",
              Config.<Boolean>getValue(ConfigValues.EncryptHostCommunication));

      method = concreteCreateMethod(urlInfo.getFirst());
    }

    return method;
  }
Пример #11
0
  protected void processExternallyManagedVms() {
    // Fetching for details from the host
    // and marking the VMs for addition
    List<String> vmsToQuery = new ArrayList<>(externalVms.size());
    for (Pair<VM, VmInternalData> pair : externalVms) {
      vmsToQuery.add(pair.getSecond().getVmDynamic().getId().toString());
    }
    if (!vmsToQuery.isEmpty()) {
      // Query VDSM for VMs info, and creating a proper VMStatic to be used when importing them
      Map[] vmsInfo = getVmInfo(vmsToQuery);
      for (Map vmInfo : vmsInfo) {
        Guid vmId = Guid.createGuidFromString((String) vmInfo.get(VdsProperties.vm_guid));
        VmStatic vmStatic = new VmStatic();
        vmStatic.setId(vmId);
        vmStatic.setCreationDate(new Date());
        vmStatic.setVdsGroupId(vdsManager.getVdsGroupId());
        String vmNameOnHost = (String) vmInfo.get(VdsProperties.vm_name);

        if (StringUtils.equals(
            Config.<String>getValue(ConfigValues.HostedEngineVmName), vmNameOnHost)) {
          // its a hosted engine VM -> import it and skip the external VM phase
          importHostedEngineVM(vmInfo);
          continue;
        } else {
          vmStatic.setName(String.format(EXTERNAL_VM_NAME_FORMAT, vmNameOnHost));
          vmStatic.setOrigin(OriginType.EXTERNAL);
        }

        vmStatic.setNumOfSockets(
            VdsBrokerObjectsBuilder.parseIntVdsProperty(vmInfo.get(VdsProperties.num_of_cpus)));
        vmStatic.setMemSizeMb(
            VdsBrokerObjectsBuilder.parseIntVdsProperty(vmInfo.get(VdsProperties.mem_size_mb)));
        vmStatic.setSingleQxlPci(false);

        externalVmsToAdd.add(vmStatic);
        log.info(
            "Importing VM '{}' as '{}', as it is running on the on Host, but does not exist in the engine.",
            vmNameOnHost,
            vmStatic.getName());
      }
    }
  }
  protected void doRemoveItem(Pair<T, V> item, T value, V widget) {
    ListIterator<Pair<T, V>> last = items.listIterator(items.size());
    if (!last.hasPrevious()) { // just a precaution; if there's no item, there should be no button
      return;
    }

    if (item == last.previous()
        && last.hasPrevious()
        && this.showAddButton) { // add plus button to previous item
      Pair<T, V> previousItem = last.previous();
      getEntry(previousItem.getSecond()).appendButton(createButton(previousItem, true));
    }

    removeEntry(item);
    onRemove(value, widget);

    if (items.isEmpty() && this.showGhost) {
      Pair<T, V> ghostItem = addGhostEntry();
      onAdd(ghostItem.getFirst(), ghostItem.getSecond());
    }
  }
Пример #13
0
  @Override
  protected void executeCommand() {
    initConnectionList(true);

    for (Map.Entry<StorageType, List<StorageServerConnections>> connectionToType :
        getConnectionsTypeMap().entrySet()) {
      disconnectStorageByType(connectionToType.getKey(), connectionToType.getValue());
      Pair<Boolean, AuditLogType> result =
          StorageHelperDirector.getInstance()
              .getItem(connectionToType.getKey())
              .disconnectHostFromStoragePoolServersCommandCompleted(getParameters());
      if (!result.getFirst()) {
        auditLogDirector.log(new AuditLogableBase(getParameters().getVdsId()), result.getSecond());
      }
    }

    // Unregister libvirt secrets when required (for Cinder storage domains).
    CINDERStorageHelper CINDERStorageHelper = new CINDERStorageHelper();
    if (CINDERStorageHelper.isActiveCinderDomainAvailable(getStoragePool().getId())) {
      unregisterLibvirtSecrets();
    }
  }
Пример #14
0
  private void addDefaultGraphicsDevice() {
    VmDevice device =
        VmDeviceCommonUtils.findVmDeviceByGeneralType(
            vmBase.getManagedDeviceMap(), VmDeviceGeneralType.GRAPHICS);
    if (device != null) {
      return;
    }

    List<Pair<GraphicsType, DisplayType>> graphicsAndDisplays =
        osRepository.getGraphicsAndDisplays(vmBase.getOsId(), new Version(getVersion()));
    GraphicsType graphicsType =
        vmBase.getDefaultDisplayType() == DisplayType.cirrus
            ? GraphicsType.VNC
            : GraphicsType.SPICE;
    GraphicsType supportedGraphicsType = null;
    for (Pair<GraphicsType, DisplayType> pair : graphicsAndDisplays) {
      if (pair.getSecond() == vmBase.getDefaultDisplayType()) {
        if (pair.getFirst() == graphicsType) {
          supportedGraphicsType = graphicsType;
          break;
        }
        if (supportedGraphicsType == null) {
          supportedGraphicsType = pair.getFirst();
        }
      }
    }
    if (supportedGraphicsType != null) {
      device = new GraphicsDevice(supportedGraphicsType.getCorrespondingDeviceType());
      device.setId(new VmDeviceId(Guid.newGuid(), vmBase.getId()));
      addManagedVmDevice(device);
    } else {
      log.warn(
          "Cannot find any graphics type for display type {} supported by OS {} in compatibility version {}",
          vmBase.getDefaultDisplayType().name(),
          osRepository.getOsName(vmBase.getOsId()),
          getVersion());
    }
  }
Пример #15
0
 private void processVmsWithDevicesChange() {
   // Handle VM devices were changed (for 3.1 cluster and above)
   if (!VmDeviceCommonUtils.isOldClusterVersion(vdsManager.getGroupCompatibilityVersion())) {
     // If there are vms that require updating,
     // get the new info from VDSM in one call, and then update them all
     if (!vmsWithChangedDevices.isEmpty()) {
       ArrayList<String> vmsToUpdate = new ArrayList<>(vmsWithChangedDevices.size());
       for (Pair<VM, VmInternalData> pair : vmsWithChangedDevices) {
         Guid vmId = pair.getFirst().getId();
         // update only if the vm marked to change, otherwise it might have skipped because data
         // invalidated
         // this ensure the vmManager lock is taken
         if (vmDynamicToSave.containsKey(vmId)) {
           vmDynamicToSave.get(vmId).setHash(pair.getSecond().getVmDynamic().getHash());
           vmsToUpdate.add(vmId.toString());
         } else {
           log.warn("VM '{}' not in changed list, skipping devices update.", vmId);
         }
       }
       updateVmDevices(vmsToUpdate);
     }
   }
 }
Пример #16
0
 private List<ClusterPolicyUnit> getclusterPolicyUnit(ClusterPolicy entity) {
   Map<Guid, ClusterPolicyUnit> map = new HashMap<Guid, ClusterPolicyUnit>();
   ClusterPolicyUnit unit;
   if (entity.getFilters() != null) {
     for (Guid policyUnitId : entity.getFilters()) {
       unit = getClusterPolicyUnit(entity, policyUnitId, map);
       if (entity.getFilterPositionMap() != null) {
         Integer position = entity.getFilterPositionMap().get(policyUnitId);
         unit.setFilterSequence(position != null ? position : 0);
       }
     }
   }
   if (entity.getFunctions() != null) {
     for (Pair<Guid, Integer> pair : entity.getFunctions()) {
       unit = getClusterPolicyUnit(entity, pair.getFirst(), map);
       unit.setFactor(pair.getSecond());
     }
   }
   if (entity.getBalance() != null) {
     getClusterPolicyUnit(entity, entity.getBalance(), map);
   }
   return new ArrayList<ClusterPolicyUnit>(map.values());
 }
Пример #17
0
 @Test
 public void testSnmpManagersParsing() {
   List<Snmp.Host> expectedManagers = new ArrayList<>();
   StringBuilder snmpManagers = new StringBuilder();
   for (Pair<String, String> host : hosts) {
     expectedManagers.add(new Snmp.Host(host.getFirst(), host.getSecond()));
     snmpManagers.append(host.getFirst());
     if (host.getSecond() != null) {
       snmpManagers.append(":").append(host.getSecond());
     }
     snmpManagers.append(" ");
   }
   Snmp.Profile profile =
       new Snmp.Profile(snmpManagers.toString(), "public", "1.3.6.1.4.1.2312.13.1.1");
   for (int i = 0; i < expectedManagers.size(); i++) {
     Snmp.Host parsed = profile.hosts.get(i);
     Snmp.Host expected = expectedManagers.get(i);
     Assert.assertEquals(parsed.name, expected.name);
     Assert.assertEquals(parsed.port, expected.port);
   }
 }
 private void removeEntry(Pair<T, V> item) {
   items.remove(item);
   removeWidget(item.getSecond());
 }
 private static void assertCredentials(
     Pair<String, String> credentials, String userName, String password) {
   assertEquals(userName, credentials.getFirst());
   assertEquals(password, credentials.getSecond());
 }
 private void updateEnabled() {
   for (Pair<T, V> item : items) {
     toggleEnabled(item.getFirst(), item.getSecond());
   }
 }
Пример #21
0
 protected VmAnalyzer getVmAnalyzer(Pair<VM, VmInternalData> pair) {
   return new VmAnalyzer(pair.getFirst(), pair.getSecond(), this, auditLogDirector);
 }
Пример #22
0
 private Guid getVmId(Pair<VM, VmInternalData> pair) {
   return (pair.getFirst() != null)
       ? pair.getFirst().getId()
       : ((pair.getSecond() != null) ? pair.getSecond().getVmDynamic().getId() : null);
 }
  protected boolean checkAddEditValidations() {
    List<ClusterPolicy> clusterPolicies = schedulingManager.getClusterPolicies();
    if (getClusterPolicy() == null) {
      return failValidation(EngineMessage.ACTION_TYPE_FAILED_CLUSTER_POLICY_PARAMETERS_INVALID);
    }
    for (ClusterPolicy clusterPolicy : clusterPolicies) {
      if (!clusterPolicy.getId().equals(getClusterPolicy().getId())
          && clusterPolicy.getName().equals(getClusterPolicy().getName())) {
        return failValidation(EngineMessage.ACTION_TYPE_FAILED_CLUSTER_POLICY_NAME_INUSE);
      }
    }
    Map<Guid, PolicyUnitImpl> map = schedulingManager.getPolicyUnitsMap();
    Set<Guid> existingPolicyUnits = new HashSet<>();
    // check filter policy units
    if (getClusterPolicy().getFilters() != null) {
      for (Guid filterId : getClusterPolicy().getFilters()) {
        if (isPolicyUnitExists(filterId, existingPolicyUnits)) {
          return failValidation(
              EngineMessage.ACTION_TYPE_FAILED_CLUSTER_POLICY_DUPLICATE_POLICY_UNIT);
        }
        PolicyUnitImpl policyUnitImpl = map.get(filterId);
        if (policyUnitImpl == null) {
          return failValidation(
              EngineMessage.ACTION_TYPE_FAILED_CLUSTER_POLICY_UNKNOWN_POLICY_UNIT);
        }
        if (policyUnitImpl.getPolicyUnit().getPolicyUnitType() != PolicyUnitType.FILTER) {
          return failValidation(
              EngineMessage.ACTION_TYPE_FAILED_CLUSTER_POLICY_FILTER_NOT_IMPLEMENTED);
        }
      }
    }
    // check filters positions (there could be only one filter attached to first (-1) and last (-1)
    if (getClusterPolicy().getFilterPositionMap() != null) {
      boolean hasFirst = false;
      boolean hasLast = false;
      for (Integer position : getClusterPolicy().getFilterPositionMap().values()) {
        if (position == -1) {
          if (!hasFirst) {
            hasFirst = true;
          } else {
            return failValidation(
                EngineMessage.ACTION_TYPE_FAILED_CLUSTER_POLICY_ONLY_ONE_FILTER_CAN_BE_FIRST);
          }
        } else if (position == 1) {
          if (!hasLast) {
            hasLast = true;
          } else {
            return failValidation(
                EngineMessage.ACTION_TYPE_FAILED_CLUSTER_POLICY_ONLY_ONE_FILTER_CAN_BE_LAST);
          }
        }
      }
    }
    // check function policy units
    if (getClusterPolicy().getFunctions() != null) {
      for (Pair<Guid, Integer> functionPair : getClusterPolicy().getFunctions()) {
        if (isPolicyUnitExists(functionPair.getFirst(), existingPolicyUnits)) {
          return failValidation(
              EngineMessage.ACTION_TYPE_FAILED_CLUSTER_POLICY_DUPLICATE_POLICY_UNIT);
        }
        PolicyUnitImpl policyUnitImpl = map.get(functionPair.getFirst());
        if (policyUnitImpl == null) {
          return failValidation(
              EngineMessage.ACTION_TYPE_FAILED_CLUSTER_POLICY_UNKNOWN_POLICY_UNIT);
        }
        if (policyUnitImpl.getPolicyUnit().getPolicyUnitType() != PolicyUnitType.WEIGHT) {
          return failValidation(
              EngineMessage.ACTION_TYPE_FAILED_CLUSTER_POLICY_FUNCTION_NOT_IMPLEMENTED);
        }
        if (functionPair.getSecond() < 0) {
          return failValidation(
              EngineMessage.ACTION_TYPE_FAILED_CLUSTER_POLICY_FUNCTION_FACTOR_NEGATIVE);
        }
      }
    }
    // check balance policy unit
    if (getClusterPolicy().getBalance() != null) {
      PolicyUnitImpl policyUnitImpl = map.get(getClusterPolicy().getBalance());
      if (policyUnitImpl == null) {
        return failValidation(EngineMessage.ACTION_TYPE_FAILED_CLUSTER_POLICY_UNKNOWN_POLICY_UNIT);
      }
      if (policyUnitImpl.getPolicyUnit().getPolicyUnitType() != PolicyUnitType.LOAD_BALANCING) {
        return failValidation(
            EngineMessage.ACTION_TYPE_FAILED_CLUSTER_POLICY_BALANCE_NOT_IMPLEMENTED);
      }
    }

    List<ValidationError> validationErrors =
        SimpleCustomPropertiesUtil.getInstance()
            .validateProperties(
                schedulingManager.getCustomPropertiesRegexMap(getClusterPolicy()),
                getClusterPolicy().getParameterMap());
    if (!validationErrors.isEmpty()) {
      SimpleCustomPropertiesUtil.getInstance()
          .handleCustomPropertiesError(validationErrors, getReturnValue().getValidationMessages());
      return false;
    }
    return true;
  }
  public void proceedCommandExecution() {
    // Steps are executed such that:
    //  a) all logic before the command runs is idempotent
    //  b) the command is the last action in the step
    // This allows for recovery after a crash at any point during command execution.

    log.debug("Proceeding with execution of RemoveSnapshotSingleDiskLiveCommand");
    if (getParameters().getCommandStep() == null) {
      getParameters().setCommandStep(getInitialMergeStepForImage(getParameters().getImageId()));
      getParameters().setChildCommands(new HashMap<RemoveSnapshotSingleDiskLiveStep, Guid>());
    }

    // Upon recovery or after invoking a new child command, our map may be missing an entry
    syncChildCommandList();
    Guid currentChildId = getCurrentChildId();

    VdcReturnValueBase vdcReturnValue = null;
    if (currentChildId != null) {
      switch (CommandCoordinatorUtil.getCommandStatus(currentChildId)) {
        case ACTIVE:
        case NOT_STARTED:
          log.info(
              "Waiting on Live Merge command step '{}' to complete",
              getParameters().getCommandStep());
          return;

        case SUCCEEDED:
          CommandEntity cmdEntity = CommandCoordinatorUtil.getCommandEntity(currentChildId);
          if (cmdEntity.isCallbackEnabled() && !cmdEntity.isCallbackNotified()) {
            log.info(
                "Waiting on Live Merge command step '{}' to finalize",
                getParameters().getCommandStep());
            return;
          }

          vdcReturnValue = CommandCoordinatorUtil.getCommandReturnValue(currentChildId);
          if (vdcReturnValue != null && vdcReturnValue.getSucceeded()) {
            log.debug("Child command '{}' succeeded", getParameters().getCommandStep());
            getParameters().setCommandStep(getParameters().getNextCommandStep());
            break;
          } else {
            log.error(
                "Child command '{}' failed: {}",
                getParameters().getCommandStep(),
                (vdcReturnValue != null
                    ? vdcReturnValue.getExecuteFailedMessages()
                    : "null return value"));
            setCommandStatus(CommandStatus.FAILED);
            return;
          }

        case FAILED:
        case FAILED_RESTARTED:
          log.error("Failed child command status for step '{}'", getParameters().getCommandStep());
          setCommandStatus(CommandStatus.FAILED);
          return;

        case UNKNOWN:
          log.error("Unknown child command status for step '{}'", getParameters().getCommandStep());
          setCommandStatus(CommandStatus.FAILED);
          return;
      }
    }

    log.info("Executing Live Merge command step '{}'", getParameters().getCommandStep());

    Pair<VdcActionType, ? extends VdcActionParametersBase> nextCommand = null;
    switch (getParameters().getCommandStep()) {
      case EXTEND:
        nextCommand = new Pair<>(VdcActionType.MergeExtend, buildMergeParameters());
        getParameters().setNextCommandStep(RemoveSnapshotSingleDiskLiveStep.MERGE);
        break;
      case MERGE:
        nextCommand = new Pair<>(VdcActionType.Merge, buildMergeParameters());
        getParameters().setNextCommandStep(RemoveSnapshotSingleDiskLiveStep.MERGE_STATUS);
        break;
      case MERGE_STATUS:
        getParameters().setMergeCommandComplete(true);
        nextCommand = new Pair<>(VdcActionType.MergeStatus, buildMergeParameters());
        getParameters().setNextCommandStep(RemoveSnapshotSingleDiskLiveStep.DESTROY_IMAGE);
        break;
      case DESTROY_IMAGE:
        if (vdcReturnValue != null) {
          getParameters()
              .setMergeStatusReturnValue(
                  (MergeStatusReturnValue) vdcReturnValue.getActionReturnValue());
        } else if (getParameters().getMergeStatusReturnValue() == null) {
          // If the images were already merged, just add the orphaned image
          getParameters().setMergeStatusReturnValue(synthesizeMergeStatusReturnValue());
        }
        nextCommand = new Pair<>(VdcActionType.DestroyImage, buildDestroyImageParameters());
        getParameters().setNextCommandStep(RemoveSnapshotSingleDiskLiveStep.COMPLETE);
        break;
      case COMPLETE:
        getParameters().setDestroyImageCommandComplete(true);
        setCommandStatus(CommandStatus.SUCCEEDED);
        break;
    }

    persistCommand(getParameters().getParentCommand(), true);
    if (nextCommand != null) {
      CommandCoordinatorUtil.executeAsyncCommand(
          nextCommand.getFirst(), nextCommand.getSecond(), cloneContextAndDetachFromParent());
      // Add the child, but wait, it's a race!  child will start, task may spawn, get polled, and we
      // won't have the child id
    }
  }