private <T extends DataObject> boolean hasDataInCF(Class<T> clazz) {
    if (excludeClasses.contains(clazz)) {
      return false; // ignore the data in those CFs
    }

    // true: query only active object ids, for below reason:
    // add VDC should succeed just when remove the data in vdc2.
    List<URI> ids = dbClient.queryByType(clazz, true, null, 2);

    if (clazz.equals(TenantOrg.class) || clazz.equals(ObjectStore.class)) {
      if (ids.size() > 1) {
        // at least one non-root tenant exist
        return true;
      }

      return false;
    }

    if (!ids.isEmpty()) {
      log.info("The class {} has data e.g. id={}", clazz.getSimpleName(), ids.get(0));
      return true;
    }

    return false;
  }
 private void updateBlackListForReconnectedVdc() {
   List<URI> vdcIds = dbClient.queryByType(VirtualDataCenter.class, true);
   dbClient.clearBlackList();
   log.info("After clear, get current black list {}", dbClient.getBlacklist());
   for (URI vdcId : vdcIds) {
     VirtualDataCenter vdc = dbClient.queryObject(VirtualDataCenter.class, vdcId);
     if (vdc.getConnectionStatus() == VirtualDataCenter.ConnectionStatus.DISCONNECTED) {
       log.info("Add vdc {} with status {} to blacklist", vdc.getId(), vdc.getConnectionStatus());
       dbClient.addVdcNodesToBlacklist(vdc);
     }
   }
 }
  private VirtualDataCenter getLocalVdc() {
    List<URI> ids = dbClient.queryByType(VirtualDataCenter.class, true);

    for (URI id : ids) {
      VirtualDataCenter vdc = dbClient.queryObject(VirtualDataCenter.class, id);
      if (vdc.getLocal() == true) {
        return vdc;
      }
    }

    throw new RuntimeException("Failed to find local vdc");
  }
 private void updateVdcStatusInDB(List<VdcConfig> vdcConfigs) {
   List<URI> vdcIdIter = new ArrayList<>();
   List<URI> vdcIds = dbClient.queryByType(VirtualDataCenter.class, true);
   for (URI id : vdcIds) {
     vdcIdIter.add(id);
   }
   for (VdcConfig vdcConfig : vdcConfigs) {
     log.info("current config's id is {}", vdcConfig.getId());
     if (vdcIdIter.contains(vdcConfig.getId())) {
       VirtualDataCenter vdc = dbClient.queryObject(VirtualDataCenter.class, vdcConfig.getId());
       vdc.setConnectionStatus(
           VirtualDataCenter.ConnectionStatus.valueOf(vdcConfig.getConnectionStatus()));
       dbClient.updateAndReindexObject(vdc);
     }
   }
 }
  @PUT
  @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
  public Response syncVdcConfig(VdcConfigSyncParam param) {
    log.info("Acquired gobal lock, vdc {}...", param.getVirtualDataCenters().size());

    VdcConfig.ConfigChangeType type =
        VdcConfig.ConfigChangeType.valueOf(param.getConfigChangeType());
    log.info("Current config change type is {}", type);

    switch (type) {
      case DISCONNECT_VDC:
        String disconntecedvdcId = param.getAssignedVdcId();
        try {
          disconnectVdc(disconntecedvdcId);
        } catch (Exception e) {
          throw GeoException.fatals.disconnectRemoteSyncFailed(disconntecedvdcId, e.getMessage());
        }
        break;
      case RECONNECT_VDC:
        String reconnectVdcId = param.getAssignedVdcId();
        try {
          VirtualDataCenter localVdc = VdcUtil.getLocalVdc();
          // If the local vdc is the one need to be reconnected back, trigger a node repair for
          // geodb
          if (localVdc.getId().toString().equals(reconnectVdcId)) {
            log.info(
                "Perform sync vdc config operation and node repair for the reconnected vdc {}",
                reconnectVdcId);
            VirtualDataCenter reconnVdc =
                dbClient.queryObject(VirtualDataCenter.class, new URI(reconnectVdcId));

            // Update operated local db, make sure all the vdcs in operated vdc'd db have the same
            // status with others.
            log.info("Reconnect ops update local db for operatedVdc");
            updateVdcStatusInDB(param.getVirtualDataCenters());
            log.info("Reconnect ops update local db done");

            // Clean blacklist for reconnected vdc
            log.info("Reconnect ops to clean blacklist for reconnected vdc.");
            updateBlackListForReconnectedVdc();
            log.info("Reconnect ops: new blacklist is {}", dbClient.getBlacklist());

            helper.syncVdcConfig(param.getVirtualDataCenters(), null);

            log.info("Current strategy options is {}", dbClient.getGeoStrategyOptions());
            log.info("Current schema version for Geo is {}", dbClient.getGeoSchemaVersions());

            geoBackgroundTasks.startGeodbNodeRepair();

          } else {
            reconnectVdc(reconnectVdcId);
          }
        } catch (Exception e) {
          throw GeoException.fatals.reconnectRemoteSyncFailed(reconnectVdcId, e.getMessage());
        }
        break;
      default:
        Iterator<URI> srcVdcIdIter = dbClient.queryByType(VirtualDataCenter.class, true).iterator();

        String assignedVdcId = param.getAssignedVdcId();
        String geoEncryptionKey = param.getGeoEncryptionKey();

        // for add-vdc
        if (assignedVdcId != null && geoEncryptionKey != null) {
          log.info("This vdc will be added to a geo system.");
          if (!srcVdcIdIter.hasNext()) {
            throw GeoException.fatals.connectVDCLocalMultipleVDC(assignedVdcId);
          }
          URI srcVdcId = srcVdcIdIter.next();
          // Delete the local vdc record
          VirtualDataCenter existingVdc = dbClient.queryObject(VirtualDataCenter.class, srcVdcId);
          dbClient.markForDeletion(existingVdc);
          log.info(
              "The existing vdc {} has been removed. The current vdc id will be {}.",
              srcVdcId,
              assignedVdcId);

          helper.setGeoEncryptionKey(geoEncryptionKey);
          log.info("geo encryption key has been updated");
          helper.resetStaleLocalObjects();

          dbClient.stopClusterGossiping();
        } else if (assignedVdcId == null && geoEncryptionKey == null) {
          log.info("Sync'ing new vdc info to existing geo system.");
        } else {
          throw GeoException.fatals.remoteVDCGeoEncryptionMissing();
        }

        helper.syncVdcConfig(param.getVirtualDataCenters(), assignedVdcId);

        if (isRemoveOp(param)) {
          log.info("Disable grossip to avoid schema version disagreement errors");
          dbClient.stopClusterGossiping();
        }

        break;
    }
    return Response.ok().build();
  }