@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();
  }