managed/src/main/java/com/yugabyte/yw/common/PlacementInfoUtil.java
/**
   * Helper API to set some of the non user supplied information in task params.
   * @param taskParams : Universe task params.
   * @param customerId : Current customer's id.
   * @param placementUuid : uuid of the cluster user is working on.
   * @param clusterOpType : Cluster Operation Type (CREATE/EDIT)
   */
Helper API to set some of the non user supplied information in task params.
@param taskParams : Universe task params.
@param customerId : Current customer's id.
@param placementUuid : uuid of the cluster user is working on.
@param clusterOpType : Cluster Operation Type (CREATE/EDIT)
Helper API to set some of the non user supplied information in task params . @param taskParams : Universe task params . @param customerId : Current customer ' s id . @param placementUuid : uuid of the cluster user is working on . @param clusterOpType : Cluster Operation Type ( CREATE / EDIT )
public static void updateUniverseDefinition(UniverseDefinitionTaskParams taskParams,
                                              Long customerId,
                                              UUID placementUuid,
                                              ClusterOperationType clusterOpType) {
    Cluster cluster = taskParams.getClusterByUuid(placementUuid);
    if (taskParams.nodeDetailsSet == null) {
      taskParams.nodeDetailsSet = new HashSet<>();
    }
    Universe universe = null;
    if (taskParams.universeUUID == null) {
      taskParams.universeUUID = UUID.randomUUID();
    } else {
      try {
        universe = Universe.get(taskParams.universeUUID);
      } catch (Exception e) {
        LOG.info("Universe with UUID {} not found, configuring new universe.",
                 taskParams.universeUUID);
      }
    }
    String universeName = universe == null ?
        taskParams.getPrimaryCluster().userIntent.universeName :
        universe.getUniverseDetails().getPrimaryCluster().userIntent.universeName;
    taskParams.nodePrefix = Util.getNodePrefix(customerId, universeName);
    ConfigureNodesMode mode;
    if (cluster.placementInfo == null &&
        clusterOpType.equals(ClusterOperationType.CREATE)) {
      taskParams.nodeDetailsSet.removeIf(n -> n.isInPlacement(placementUuid));
      cluster.placementInfo = getPlacementInfo(cluster.clusterType, cluster.userIntent);
      LOG.info("Placement created={}.", cluster.placementInfo);
      configureNodeStates(taskParams, null, ConfigureNodesMode.NEW_CONFIG, cluster);
      return;
    }
    LOG.info("Placement={}, numNodes={}, AZ={}.", cluster.placementInfo,
             taskParams.nodeDetailsSet.size(), taskParams.userAZSelected);
    if (taskParams.userAZSelected && universe != null) {
      mode = ConfigureNodesMode.NEW_CONFIG_FROM_PLACEMENT_INFO;
      configureNodeStates(taskParams, universe, mode, cluster);
      return;
    }
    Cluster oldCluster = null;
    if (clusterOpType.equals(ClusterOperationType.EDIT)) {
      if (universe == null) {
        throw new IllegalArgumentException("Cannot perform edit operation on " +
            cluster.clusterType + " without universe.");
      }
      oldCluster = cluster.clusterType.equals(PRIMARY) ?
          universe.getUniverseDetails().getPrimaryCluster() :
          universe.getUniverseDetails().getReadOnlyClusters().get(0);
      if (!oldCluster.uuid.equals(placementUuid)) {
        throw new IllegalArgumentException("Mismatched uuid between existing cluster " +
            oldCluster.uuid + " and requested " + placementUuid + " for " + cluster.clusterType +
            " cluster in universe " + universe.universeUUID);
       }
      verifyEditParams(oldCluster, cluster);
    }
    boolean primaryClusterEdit = cluster.clusterType.equals(PRIMARY) &&
        clusterOpType.equals(ClusterOperationType.EDIT);
    boolean readOnlyClusterEdit = cluster.clusterType.equals(ASYNC) &&
        clusterOpType.equals(ClusterOperationType.EDIT);
    LOG.info("Update mode info: primEdit={}, roEdit={}, opType={}, cluster={}.",
             primaryClusterEdit, readOnlyClusterEdit, clusterOpType, cluster.clusterType);
    if (primaryClusterEdit) {
      assert oldCluster != null;
      if (didAffinitizedLeadersChange(oldCluster.placementInfo,
                                      cluster.placementInfo)) {
        mode = ConfigureNodesMode.UPDATE_CONFIG_FROM_PLACEMENT_INFO;
      } else {
        mode = getPureExpandOrShrinkMode(universe.getUniverseDetails(), taskParams, cluster);
        taskParams.nodeDetailsSet.clear();
        taskParams.nodeDetailsSet.addAll(universe.getNodes());
      }
    } else {
      if (readOnlyClusterEdit) {
        assert oldCluster != null;
      }
      mode = getPureExpandOrShrinkMode(readOnlyClusterEdit ? universe.getUniverseDetails() : null,
                                       taskParams, cluster);
    }
    boolean mode_changed = false;
    if (clusterOpType.equals(ClusterOperationType.CREATE)) {
      int totalRF = 0;
      for (PlacementCloud cloud : cluster.placementInfo.cloudList) {
        for (PlacementRegion region : cloud.regionList) {
          for (PlacementAZ az : region.azList) {
            totalRF += az.replicationFactor;
          }
        }
      }
      int rf = cluster.userIntent.replicationFactor;
      LOG.info("UserIntent replication factor={} while total zone replication factor={}.",
                rf, totalRF);
      if (rf < totalRF) {
        cluster.placementInfo = getPlacementInfo(cluster.clusterType, cluster.userIntent);
        LOG.info("New placement has {} zones.", getNumZones(cluster.placementInfo));
        taskParams.nodeDetailsSet.removeIf(n -> n.isInPlacement(placementUuid));
        mode = ConfigureNodesMode.NEW_CONFIG;
        mode_changed = true;
      }
    }
    if (!mode_changed && (mode == ConfigureNodesMode.NEW_CONFIG)) {
      boolean changeNodeStates = false;
      if (isProviderOrRegionChange(
              cluster,
              (primaryClusterEdit || readOnlyClusterEdit) ?
                  universe.getNodes() : taskParams.nodeDetailsSet)) {
        LOG.info("Provider or region changed, getting new placement info.");
        cluster.placementInfo = getPlacementInfo(cluster.clusterType, cluster.userIntent);
        changeNodeStates = true;
      } else {
        String newInstType = cluster.userIntent.instanceType;
        String existingInstType =
            taskParams.getNodesInCluster(cluster.uuid).iterator().next().cloudInfo.instance_type;
        if (!newInstType.equals(existingInstType)) {
          LOG.info("Performing full move with existing placement info for instance type change " +
                   "from  {} to {}.", existingInstType, newInstType);
          clearPlacementAZCounts(cluster.placementInfo);
          changeNodeStates = true;
        } 
      }
      if (!changeNodeStates && oldCluster != null && !oldCluster.areTagsSame(cluster)) {
        LOG.info("No node config change needed, only instance tags changed.");
        return;
      }
      taskParams.nodeDetailsSet.removeIf(n -> n.isInPlacement(placementUuid));
    }
    configureNodeStates(taskParams, universe, mode, cluster);
  }
public static void updateUniverseDefinition ( UniverseDefinitionTaskParams taskParams , Long customerId , UUID placementUuid , ClusterOperationType clusterOpType ) { Cluster cluster = taskParams . getClusterByUuid ( placementUuid ) ; if ( taskParams . nodeDetailsSet == null ) { taskParams . nodeDetailsSet = new HashSet < > ( ) ; } Universe universe = null ; if ( taskParams . universeUUID == null ) { taskParams . universeUUID = UUID . randomUUID ( ) ; } else { try { universe = Universe . get ( taskParams . universeUUID ) ; } catch ( Exception e ) { LOG . info ( "Universe with UUID {} not found, configuring new universe." , taskParams . universeUUID ) ; } } String universeName = universe == null ? taskParams . getPrimaryCluster ( ) . userIntent . universeName : universe . getUniverseDetails ( ) . getPrimaryCluster ( ) . userIntent . universeName ; taskParams . nodePrefix = Util . getNodePrefix ( customerId , universeName ) ; ConfigureNodesMode mode ; if ( cluster . placementInfo == null && clusterOpType . equals ( ClusterOperationType . CREATE ) ) { taskParams . nodeDetailsSet . removeIf ( n -> n . isInPlacement ( placementUuid ) ) ; cluster . placementInfo = getPlacementInfo ( cluster . clusterType , cluster . userIntent ) ; LOG . info ( "Placement created={}." , cluster . placementInfo ) ; configureNodeStates ( taskParams , null , ConfigureNodesMode . NEW_CONFIG , cluster ) ; return ; } LOG . info ( "Placement={}, numNodes={}, AZ={}." , cluster . placementInfo , taskParams . nodeDetailsSet . size ( ) , taskParams . userAZSelected ) ; if ( taskParams . userAZSelected && universe != null ) { mode = ConfigureNodesMode . NEW_CONFIG_FROM_PLACEMENT_INFO ; configureNodeStates ( taskParams , universe , mode , cluster ) ; return ; } Cluster oldCluster = null ; if ( clusterOpType . equals ( ClusterOperationType . EDIT ) ) { if ( universe == null ) { throw new IllegalArgumentException ( "Cannot perform edit operation on " + cluster . clusterType + " without universe." ) ; } oldCluster = cluster . clusterType . equals ( PRIMARY ) ? universe . getUniverseDetails ( ) . getPrimaryCluster ( ) : universe . getUniverseDetails ( ) . getReadOnlyClusters ( ) . get ( 0 ) ; if ( ! oldCluster . uuid . equals ( placementUuid ) ) { throw new IllegalArgumentException ( "Mismatched uuid between existing cluster " + oldCluster . uuid + " and requested " + placementUuid + " for " + cluster . clusterType + " cluster in universe " + universe . universeUUID ) ; } verifyEditParams ( oldCluster , cluster ) ; } boolean primaryClusterEdit = cluster . clusterType . equals ( PRIMARY ) && clusterOpType . equals ( ClusterOperationType . EDIT ) ; boolean readOnlyClusterEdit = cluster . clusterType . equals ( ASYNC ) && clusterOpType . equals ( ClusterOperationType . EDIT ) ; LOG . info ( "Update mode info: primEdit={}, roEdit={}, opType={}, cluster={}." , primaryClusterEdit , readOnlyClusterEdit , clusterOpType , cluster . clusterType ) ; if ( primaryClusterEdit ) { assert oldCluster != null ; if ( didAffinitizedLeadersChange ( oldCluster . placementInfo , cluster . placementInfo ) ) { mode = ConfigureNodesMode . UPDATE_CONFIG_FROM_PLACEMENT_INFO ; } else { mode = getPureExpandOrShrinkMode ( universe . getUniverseDetails ( ) , taskParams , cluster ) ; taskParams . nodeDetailsSet . clear ( ) ; taskParams . nodeDetailsSet . addAll ( universe . getNodes ( ) ) ; } } else { if ( readOnlyClusterEdit ) { assert oldCluster != null ; } mode = getPureExpandOrShrinkMode ( readOnlyClusterEdit ? universe . getUniverseDetails ( ) : null , taskParams , cluster ) ; } boolean mode_changed = false ; if ( clusterOpType . equals ( ClusterOperationType . CREATE ) ) { int totalRF = 0 ; for ( PlacementCloud cloud : cluster . placementInfo . cloudList ) { for ( PlacementRegion region : cloud . regionList ) { for ( PlacementAZ az : region . azList ) { totalRF += az . replicationFactor ; } } } int rf = cluster . userIntent . replicationFactor ; LOG . info ( "UserIntent replication factor={} while total zone replication factor={}." , rf , totalRF ) ; if ( rf < totalRF ) { cluster . placementInfo = getPlacementInfo ( cluster . clusterType , cluster . userIntent ) ; LOG . info ( "New placement has {} zones." , getNumZones ( cluster . placementInfo ) ) ; taskParams . nodeDetailsSet . removeIf ( n -> n . isInPlacement ( placementUuid ) ) ; mode = ConfigureNodesMode . NEW_CONFIG ; mode_changed = true ; } } if ( ! mode_changed && ( mode == ConfigureNodesMode . NEW_CONFIG ) ) { boolean changeNodeStates = false ; if ( isProviderOrRegionChange ( cluster , ( primaryClusterEdit || readOnlyClusterEdit ) ? universe . getNodes ( ) : taskParams . nodeDetailsSet ) ) { LOG . info ( "Provider or region changed, getting new placement info." ) ; cluster . placementInfo = getPlacementInfo ( cluster . clusterType , cluster . userIntent ) ; changeNodeStates = true ; } else { String newInstType = cluster . userIntent . instanceType ; String existingInstType = taskParams . getNodesInCluster ( cluster . uuid ) . iterator ( ) . next ( ) . cloudInfo . instance_type ; if ( ! newInstType . equals ( existingInstType ) ) { LOG . info ( "Performing full move with existing placement info for instance type change " + "from  {} to {}." , existingInstType , newInstType ) ; clearPlacementAZCounts ( cluster . placementInfo ) ; changeNodeStates = true ; } } if ( ! changeNodeStates && oldCluster != null && ! oldCluster . areTagsSame ( cluster ) ) { LOG . info ( "No node config change needed, only instance tags changed." ) ; return ; } taskParams . nodeDetailsSet . removeIf ( n -> n . isInPlacement ( placementUuid ) ) ; } configureNodeStates ( taskParams , universe , mode , cluster ) ; }
Helper API to set some of the non user supplied information in task params.
Helper API to set some of the non user supplied information in task params .
// Create node details set if needed. // Compose a default prefix for the nodes. This can be overwritten by instance tags (on AWS). // If no placement info, and if this is the first primary or readonly cluster create attempt, // choose a new placement. // Verify the provided edit parameters, if in edit universe case, and get the mode. // Otherwise it is a primary or readonly cluster creation phase changes. // If user AZ Selection is made for Edit get a new configuration from placement info. // For primary cluster edit only there is possibility of leader changes. // If RF is not compatible with number of placement zones, reset the placement during create. // For ex., when RF goes from 3/5/7 to 1, we want to show only one zone. When RF goes from 1 // to 5, we will show existing zones. ResetConfig can be used to change zone count. // Compute RF across all chosen zones to be <= user RF. // If not a pure expand/shrink, we will pick a new set of nodes. If the provider or region list // changed, we will pick a new placement (i.e full move, create primary/RO cluster). // else can check if RF changed : not supported yet. // Compute the node states that should be configured for this operation.