mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

jvergara
17.50.2008 3790dd899db51a47f770ee52f339cfd2539e2bbd
Fix for 2811 (dsreplication disable doesn't remove references to current server from replicated servers)
The fix makes dsreplication enable and dsreplication disable symmetric. When the user disables the last replicated suffix, we inform that the replication server will also be disabled. So when the last repilcated suffix is disabled, replication on cn=schema and cn=admin data are also disabled and the registration information updated properly.

Some changes have been made in ADSContext to make registerServer and unregisterServer symmetric: unregisterServer removes the references to the server keys and also the references to the server in the different server groups.

The code of DsFrameworkCliServer.java has also been updated since ADSContext.unregisterServer already updates the server groups.
6 files modified
443 ■■■■■ changed files
opends/src/ads/org/opends/admin/ads/ADSContext.java 92 ●●●●● patch | view | raw | blame | history
opends/src/ads/org/opends/admin/ads/ADSContextHelper.java 59 ●●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliMain.java 262 ●●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliReturnCode.java 9 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/admin_tool.properties 10 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/client/cli/DsFrameworkCliServer.java 11 ●●●●● patch | view | raw | blame | history
opends/src/ads/org/opends/admin/ads/ADSContext.java
@@ -504,7 +504,7 @@
        serverProperties.put(ServerProperty.ID,newServerId);
      }
      BasicAttributes attrs = makeAttrsFromServerProperties(serverProperties);
      dirContext.modifyAttributes(dn, InitialLdapContext.REPLACE_ATTRIBUTE,
      dirContext.modifyAttributes(dn, DirContext.REPLACE_ATTRIBUTE,
          attrs);
      if (serverProperties.containsKey(
                                ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE))
@@ -542,6 +542,11 @@
    LdapName dn = makeDNFromServerProperties(serverProperties);
    try
    {
      if (serverProperties.containsKey(
          ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE))
      {
        unregisterInstanceKeyCertificate(serverProperties, dn);
      }
      dirContext.destroySubcontext(dn);
    }
    catch (NameNotFoundException x)
@@ -554,6 +559,74 @@
      throw new ADSContextException(
          ADSContextException.ErrorType.ERROR_UNEXPECTED, x);
    }
    // Unregister the server in server groups
    try
    {
      NamingEnumeration ne;
      SearchControls sc = new SearchControls();
      String serverID = getServerID(serverProperties);
      if (serverID != null)
      {
        String memberAttrName = ServerGroupProperty.MEMBERS.getAttributeName();
        String filter = "("+memberAttrName+"=cn="+serverID+")";
        sc.setSearchScope(SearchControls.ONELEVEL_SCOPE);
        ne = dirContext.search(getServerGroupContainerDN(), filter, sc);
        while (ne.hasMore())
        {
          SearchResult sr = (SearchResult)ne.next();
          String groupDn = sr.getNameInNamespace();
          BasicAttribute newAttr = new BasicAttribute(memberAttrName);
          NamingEnumeration attrs = sr.getAttributes().getAll();
          while (attrs.hasMore())
          {
            Attribute attr = (Attribute)attrs.next();
            String attrID = attr.getID();
            if (attrID.equalsIgnoreCase(memberAttrName))
            {
              NamingEnumeration ae = attr.getAll();
              while (ae.hasMore())
              {
                String value = (String)ae.next();
                if (!value.equalsIgnoreCase("cn="+serverID))
                {
                  newAttr.add(value);
                }
              }
            }
          }
          BasicAttributes newAttrs = new BasicAttributes();
          newAttrs.put(newAttr);
          if (newAttr.size() > 0)
          {
            dirContext.modifyAttributes(groupDn, DirContext.REPLACE_ATTRIBUTE,
                newAttrs);
          }
          else
          {
            dirContext.modifyAttributes(groupDn, DirContext.REMOVE_ATTRIBUTE,
                newAttrs);
          }
        }
      }
    }
    catch (NameNotFoundException x)
    {
      throw new ADSContextException(
          ADSContextException.ErrorType.BROKEN_INSTALL);
    }
    catch (NoPermissionException x)
    {
      throw new ADSContextException(
          ADSContextException.ErrorType.ACCESS_PERMISSION);
    }
    catch (NamingException x)
    {
      throw new ADSContextException(
          ADSContextException.ErrorType.ERROR_UNEXPECTED, x);
    }
  }
  /**
@@ -2193,6 +2266,23 @@
  }
  /**
  Unregister instance key-pair public-key certificate provided in
  serverProperties..
  @param serverProperties Properties of the server being unregistered to which
  the instance key entry belongs.
  @param serverEntryDn The server's ADS entry DN.
  @throws NamingException In case some JNDI operation fails.
  */
 private void unregisterInstanceKeyCertificate(
         Map<ServerProperty, Object> serverProperties,
         LdapName serverEntryDn)
 throws ADSContextException {
   ADSContextHelper helper = new ADSContextHelper();
   helper.unregisterInstanceKeyCertificate(dirContext, serverProperties,
       serverEntryDn);
 }
  /**
   Return the set of valid (i.e., not tagged as compromised) instance key-pair
   public-key certificate entries in ADS.
   NOTE: calling this method assumes that all the jar files are present in the
opends/src/ads/org/opends/admin/ads/ADSContextHelper.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2007 Sun Microsystems, Inc.
 *      Portions Copyright 2007-2008 Sun Microsystems, Inc.
 */
package org.opends.admin.ads;
@@ -31,6 +31,7 @@
import java.util.SortedSet;
import java.util.TreeSet;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
@@ -197,7 +198,7 @@
  @param serverEntryDn The server's ADS entry DN.
  @throws ADSContextException In case some JNDI operation fails or there is a
  problem getting the instance public key certificate ID.
  */
   */
  public void registerInstanceKeyCertificate(
      InitialLdapContext ctx, Map<ServerProperty, Object> serverProperties,
      LdapName serverEntryDn)
@@ -285,6 +286,60 @@
    }
  }
  /**
  Unregister instance key-pair public-key certificate provided in
  serverProperties.
  @param ctx the connection to the server.
  @param serverProperties Properties of the server being unregistered to which
  the instance key entry belongs.
  @param serverEntryDn The server's ADS entry DN.
  @throws ADSContextException In case some JNDI operation fails.
  */
  public void unregisterInstanceKeyCertificate(
      InitialLdapContext ctx, Map<ServerProperty, Object> serverProperties,
      LdapName serverEntryDn)
  throws ADSContextException {
    assert serverProperties.containsKey(
        ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE);
    if (! serverProperties.containsKey(
        ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE)) {
      return;
    }
    /* these attributes are used both to search for an existing certificate
     entry and, if one does not exist, add a new certificate entry */
    final BasicAttributes keyAttrs = new BasicAttributes();
    final Attribute oc = new BasicAttribute("objectclass");
    oc.add("top"); oc.add("ds-cfg-instance-key");
    keyAttrs.put(oc);
    keyAttrs.put(new BasicAttribute(
        ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE.getAttributeName()
        + ";binary",
        serverProperties.get(
            ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE)));
    /* search for public-key certificate entry in ADS DIT */
    final String attrIDs[] = { "ds-cfg-key-id" };
    try
    {
      final NamingEnumeration<SearchResult> results = ctx.search(
          ADSContext.getInstanceKeysContainerDN(), keyAttrs, attrIDs);
      if (results.hasMore()) {
        SearchResult res = results.next();
        ctx.destroySubcontext(res.getNameInNamespace());
      }
    }
    catch (NameNotFoundException nnfe)
    {
    }
    catch (NamingException ne)
    {
      throw new ADSContextException(
          ADSContextException.ErrorType.ERROR_UNEXPECTED, ne);
    }
  }
  /**
   * Returns the crypto instance key objectclass name as defined in
   * ConfigConstants.
opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliMain.java
@@ -1217,8 +1217,16 @@
      if (!disableSchema && !disableADS)
      {
        println();
        cancelled = !askConfirmation(
            INFO_REPLICATION_CONFIRM_DISABLE_GENERIC.get(), true, LOG);
        if (disableAllBaseDns(ctx, uData))
        {
          cancelled = !askConfirmation(
              INFO_REPLICATION_CONFIRM_DISABLE_LAST_SUFFIXES.get(), true, LOG);
        }
        else
        {
          cancelled = !askConfirmation(
              INFO_REPLICATION_CONFIRM_DISABLE_GENERIC.get(), true, LOG);
        }
        println();
      }
    }
@@ -4593,8 +4601,90 @@
      }
    }
    /**
     * Try to figure out if we must explicitly disable replication on
     * cn=admin data and cn=schema.
     */
    boolean forceDisableSchema = false;
    boolean forceDisableADS = false;
    boolean schemaReplicated = false;
    boolean adsReplicated = false;
    boolean disableAllBaseDns = disableAllBaseDns(ctx, uData);
    Collection<ReplicaDescriptor> replicas = getReplicas(ctx);
    for (ReplicaDescriptor rep : replicas)
    {
      String dn = rep.getSuffix().getDN();
      if (rep.isReplicated())
      {
        if (Utils.areDnsEqual(ADSContext.getAdministrationSuffixDN(), dn))
        {
          adsReplicated = true;
        }
        else if (Utils.areDnsEqual(Constants.SCHEMA_DN, dn))
        {
          schemaReplicated = true;
        }
      }
    }
    if (disableAllBaseDns)
    {
      // Unregister the server from the ADS
      server.updateAdsPropertiesWithServerProperties();
      try
      {
        adsCtx.unregisterServer(server.getAdsProperties());
        try
        {
          // To be sure that the change gets propagated
          Thread.sleep(2000);
        }
        catch (Throwable t)
        {
        }
      }
      catch (ADSContextException adce)
      {
        LOG.log(Level.INFO, "Error unregistering server: "+
            server.getAdsProperties(), adce);
        println();
        println(
            ERR_REPLICATION_UPDATING_ADS.get(adce.getMessage()));
        println();
      }
    }
    if (disableAllBaseDns)
    {
      forceDisableSchema = schemaReplicated;
      forceDisableADS = adsReplicated;
      for (String dn : uData.getBaseDNs())
      {
        if (Utils.areDnsEqual(ADSContext.getAdministrationSuffixDN(), dn))
        {
          // The user already asked this to be explicitly disabled
          forceDisableADS = false;
        }
        else if (Utils.areDnsEqual(Constants.SCHEMA_DN, dn))
        {
          // The user already asked this to be explicitly disabled
          forceDisableSchema = false;
        }
      }
    }
    Set<String> suffixesToDisable = new HashSet<String>(uData.getBaseDNs());
    if (forceDisableSchema)
    {
      suffixesToDisable.add(Constants.SCHEMA_DN);
    }
    if (forceDisableADS)
    {
      suffixesToDisable.add(ADSContext.getAdministrationSuffixDN());
    }
    String replicationServerHostPort = server.getReplicationServerHostPort();
    for (String baseDN : uData.getBaseDNs())
    for (String baseDN : suffixesToDisable)
    {
      try
      {
@@ -4613,7 +4703,7 @@
    {
      Set<ServerDescriptor> serversToUpdate =
        new LinkedHashSet<ServerDescriptor>();
      for (String baseDN : uData.getBaseDNs())
      for (String baseDN : suffixesToDisable)
      {
        SuffixDescriptor suffix = getSuffix(baseDN, cache, server);
        if (suffix != null)
@@ -4629,7 +4719,38 @@
      for (ServerDescriptor s : serversToUpdate)
      {
        removeReferencesInServer(s, replicationServerHostPort, bindDn, pwd,
            uData.getBaseDNs());
            suffixesToDisable, disableAllBaseDns);
      }
      if (disableAllBaseDns)
      {
        // Disable replication server
        disableReplicationServer(ctx);
        // Wait to be sure that changes are taken into account and reset the
        // contents of the ADS.
        try
        {
          Thread.sleep(2000);
        }
        catch (Throwable t)
        {
        }
        for (ServerDescriptor s: serversToUpdate)
        {
          try
          {
            adsCtx.unregisterServer(s.getAdsProperties());
          }
          catch (ADSContextException adce)
          {
            LOG.log(Level.INFO, "Error unregistering server: "+
                s.getAdsProperties(), adce);
            println();
            println(
                ERR_REPLICATION_UPDATING_ADS.get(adce.getMessage()));
            println();
          }
        }
      }
    }
  }
@@ -6178,12 +6299,14 @@
   * @param pwd the password that must be used to log to the server.
   * @param baseDNs the list of base DNs where we want to remove the references
   * to the provided replication server.
   * @param removeFromReplicationServers if references must be removed from
   * the replication servers.
   * @throws ReplicationCliException if there is an error updating the
   * configuration.
   */
  private void removeReferencesInServer(ServerDescriptor server,
      String replicationServer, String bindDn, String pwd,
      Collection<String> baseDNs)
      Collection<String> baseDNs, boolean updateReplicationServers)
  throws ReplicationCliException
  {
    ServerLoader loader = new ServerLoader(server.getAdsProperties(), bindDn,
@@ -6263,6 +6386,37 @@
            }
          }
        }
        if (updateReplicationServers && sync.hasReplicationServer())
        {
          ReplicationServerCfgClient rServerObj = sync.getReplicationServer();
          Set<String> replServers = rServerObj.getReplicationServer();
          if (replServers != null)
          {
            String replServer = null;
            for (String o : replServers)
            {
              if (replicationServer.equalsIgnoreCase(o))
              {
                replServer = o;
                break;
              }
            }
            if (replServer != null)
            {
              replServers.remove(replServer);
              if (replServers.size() > 0)
              {
                rServerObj.setReplicationServer(replServers);
                rServerObj.commit();
              }
              else
              {
                sync.removeReplicationServer();
                sync.commit();
              }
            }
          }
        }
      }
    }
    catch (NamingException ne)
@@ -6364,6 +6518,61 @@
  }
  /**
   * Disables the replication server for a given server.
   * @param ctx the connection to the server.
   * @throws ReplicationCliException if there is an error updating the
   * configuration of the server.
   */
  private void disableReplicationServer(InitialLdapContext ctx)
  throws ReplicationCliException
  {
    String hostPort = ConnectionUtils.getHostPort(ctx);
    try
    {
      ManagementContext mCtx = LDAPManagementContext.createFromContext(
          JNDIDirContextAdaptor.adapt(ctx));
      RootCfgClient root = mCtx.getRootConfiguration();
      ReplicationSynchronizationProviderCfgClient sync = null;
      ReplicationServerCfgClient replicationServer = null;
      try
      {
        sync = (ReplicationSynchronizationProviderCfgClient)
        root.getSynchronizationProvider("Multimaster Synchronization");
        if (sync.hasReplicationServer())
        {
          replicationServer = sync.getReplicationServer();
        }
      }
      catch (ManagedObjectNotFoundException monfe)
      {
        // It does not exist.
        LOG.log(Level.INFO, "No synchronization found on "+ hostPort +".",
            monfe);
      }
      if (replicationServer != null)
      {
        String s = String.valueOf(replicationServer.getReplicationPort());
        printProgress(formatter.getFormattedWithPoints(
            INFO_REPLICATION_DISABLING_REPLICATION_SERVER.get(s,
                hostPort)));
        sync.removeReplicationServer();
        sync.commit();
        printProgress(formatter.getFormattedDone());
        printlnProgress();
      }
    }
    catch (OpenDsException ode)
    {
      throw new ReplicationCliException(
          ERR_REPLICATION_DISABLING_REPLICATIONSERVER.get(hostPort),
          ERROR_DISABLING_REPLICATION_SERVER,
          ode);
    }
  }
  /**
   * Returns a message object for the given NamingException.
   * @param ne the NamingException.
   * @param hostPort the hostPort representation of the server we were
@@ -6939,4 +7148,45 @@
    }
    return areEqual;
  }
  /**
   * Tells whether we are trying to disable all the replicated suffixes.
   * @param uData the disable replication data provided by the user.
   * @return <CODE>true</CODE> if we want to disable all the replicated suffixes
   * and <CODE>false</CODE> otherwise.
   */
  private boolean disableAllBaseDns(InitialLdapContext ctx,
      DisableReplicationUserData uData)
  {
    boolean returnValue = true;
    Collection<ReplicaDescriptor> replicas = getReplicas(ctx);
    Set<String> replicatedSuffixes = new HashSet<String>();
    for (ReplicaDescriptor rep : replicas)
    {
      String dn = rep.getSuffix().getDN();
      if (rep.isReplicated())
      {
        replicatedSuffixes.add(dn);
      }
    }
    for (String dn1 : replicatedSuffixes)
    {
      if (!Utils.areDnsEqual(ADSContext.getAdministrationSuffixDN(), dn1) &&
          !Utils.areDnsEqual(Constants.SCHEMA_DN, dn1))
      {
        boolean found = false;
        for (String dn2 : uData.getBaseDNs())
        {
          found = Utils.areDnsEqual(dn1, dn2);
          break;
        }
        if (!found)
        {
          returnValue = false;
        }
      }
    }
    return returnValue;
  }
}
opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliReturnCode.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2007 Sun Microsystems, Inc.
 *      Portions Copyright 2007-2008 Sun Microsystems, Inc.
 */
package org.opends.guitools.replicationcli;
@@ -176,7 +176,12 @@
   * Error launching pre external initialization.
   */
  ERROR_LAUNCHING_POST_EXTERNAL_INITIALIZATION(24,
      ERR_REPLICATION_NO_MESSAGE.get());
      ERR_REPLICATION_NO_MESSAGE.get()),
  /**
   * Error disabling replication server.
   */
  ERROR_DISABLING_REPLICATION_SERVER(25, ERR_REPLICATION_NO_MESSAGE.get());
  private Message message;
opends/src/messages/messages/admin_tool.properties
@@ -20,7 +20,7 @@
#
# CDDL HEADER END
#
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
#      Portions Copyright 2006-2008 Sun Microsystems, Inc.
@@ -659,6 +659,10 @@
INFO_REPLICATION_CONFIRM_DISABLE_GENERIC=Disabling replication will make the \
 data under the selected base DNs not to be synchronized with other servers \
 any more.  Do you want to continue?
INFO_REPLICATION_CONFIRM_DISABLE_LAST_SUFFIXES=Disabling replication will make \
 the data under the selected base DNs not to be synchronized with other \
 servers any more.  The replication port on the server will also be disabled.  \
 Do you want to continue?
INFO_REPLICATION_CONFIRM_INITIALIZE_ADS=You chose to initialize the contents \
 of base DN %s on server %s with the contents in server %s.  This base DN is \
 used by the replication mechanism and by some administrative tools and it is \
@@ -702,6 +706,8 @@
 not find a peer to start the initialization after several tries.  Details: %s
SEVERE_ERR_REPLICATION_CONFIGURING_REPLICATIONSERVER=Error configuring \
 replication port on server %s.
SEVERE_ERR_REPLICATION_DISABLING_REPLICATIONSERVER=Error disabling \
 replication port on server %s.
SEVERE_ERR_REPLICATION_CONFIGURING_BASEDN=Error updating replication \
 configuration on base DN %s of server %s.
SEVERE_ERR_REPLICATION_UPDATING_ADS=Error updating Registration information.  \
@@ -717,6 +723,8 @@
 %s of server %s
INFO_REPLICATION_DISABLING_BASEDN=Disabling replication on base DN %s of \
 server %s
INFO_REPLICATION_DISABLING_REPLICATION_SERVER=Disabling replication port %s of \
 server %s
INFO_REPLICATION_STATUS_NO_BASEDNS=No base DNs found.
INFO_REPLICATION_STATUS_BASEDN=Base DN
INFO_REPLICATION_STATUS_IS_REPLICATED=Replication
opends/src/server/org/opends/server/admin/client/cli/DsFrameworkCliServer.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2008 Sun Microsystems, Inc.
 */
package org.opends.server.admin.client.cli;
import org.opends.messages.Message;
@@ -668,15 +668,6 @@
        {
          throw new ADSContextException (ErrorType.NOT_YET_REGISTERED) ;
        }
        Set groupList = (Set) serverProperties.get(ServerProperty.GROUPS);
        if (groupList != null)
        {
          for (Object groupId : groupList.toArray())
          {
            DsFrameworkCliServerGroup.removeServerFromGroup(adsCtx,
                (String) groupId, serverId);
          }
        }
        // unregister the server
        adsCtx.unregisterServer(map);