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

jvergara
22.52.2007 34eeb0f7371dcd4fb24dae2c25918a96d9a65f32
Fix for issue 2613

The upgrader is breaking replication (and not just dsreplication).

The problem occurs because the upgrader is systematically overwriting the contents of the admin-backend.ldif file when it should not. The fix consists on not updating this file unless it does not exist.

The same fix has been applied to tool.properties since it was also systematically overwritten (and so the user lost the changes made to it).

Appart some fixes related to message formatting are also included in the attached diff file. The code used to display messages with HTML formatting in CLI mode, so specific messages have been added when the upgrade is run from the command line.

Finally the code of the upgrader has been updated to use the MenuBuilder class. This is done to have a consistent output with the rest of the command-lines.
7 files modified
299 ■■■■ changed files
opendj-sdk/opends/src/messages/messages/quicksetup.properties 16 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/CliUserInteraction.java 96 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/Installation.java 26 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/upgrader/MigrationManager.java 112 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/upgrader/UpgradeFileFilter.java 4 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/upgrader/UpgradeProgressStep.java 3 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java 42 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/messages/messages/quicksetup.properties
@@ -406,20 +406,34 @@
INFO_ERROR_UPGRADE_MIGRATION=Migration Error
INFO_ERROR_UPGRADE_MIGRATION_ADD=An attempt to add entry <b>%s</b> to the \
 newly upgraded server was unsuccessful.
INFO_ERROR_UPGRADE_MIGRATION_ADD_CLI=An attempt to add entry %s to the \
 newly upgraded server was unsuccessful.
INFO_ERROR_UPGRADE_MIGRATION_CONFIG=Configuration Migration Error
INFO_ERROR_UPGRADE_MIGRATION_DELETE=An attempt to delete entry <b>%s</b> to \
 the newly upgraded server was unsuccessful.
INFO_ERROR_UPGRADE_MIGRATION_MODIFY=An attempt to modify entry <b>%s</b> to \
 the newly upgraded server was unsuccessful.
 INFO_ERROR_UPGRADE_MIGRATION_DELETE_CLI=An attempt to delete entry %s to \
 the newly upgraded server was unsuccessful.
INFO_ERROR_UPGRADE_MIGRATION_MODIFY_CLI=An attempt to modify entry %s to \
 the newly upgraded server was unsuccessful.
INFO_ERROR_UPGRADE_MIGRATION_NOTE=You can cancel this upgrade altogether, \
 continue anyway or retry this operation.  If you cancel the server will be \
 restored to the state it was in before the upgrade was attempted.  If you \
 continue you should be aware that the server may not configured as it was \
 before this upgrade.  A copy of the original installation files will be kept \
 in <i>%s</i>.
INFO_ERROR_UPGRADE_MIGRATION_NOTE_CLI=You can cancel this upgrade altogether, \
 continue anyway or retry this operation.  If you cancel the server will be \
 restored to the state it was in before the upgrade was attempted.  If you \
 continue you should be aware that the server may not configured as it was \
 before this upgrade.  A copy of the original installation files will be kept \
 in %s.
INFO_ERROR_UPGRADE_MIGRATION_SCHEMA=Schema Migration Error
INFO_ERROR_UPGRADE_MIGRATION_UNEXPECTED=An unexpected error occurred while \
 processing entry <b>%s</b>.
INFO_ERROR_UPGRADE_MIGRATION_UNEXPECTED_CLI=An unexpected error occurred while \
 processing entry %s.
INFO_ERROR_UPGRADED_SERVER_STARTS_WITH_ERRORS=The upgraded server starts with \
 errors: %s
INFO_ERROR_UPGRADING_COMPONENTS=Error upgrading components.
@@ -959,6 +973,8 @@
INFO_SUMMARY_UPGRADE_ABORT=Canceling Upgrade...
INFO_SUMMARY_UPGRADE_APPLYING_CONFIG_CUSTOMIZATION=Applying Configuration \
 Customizations...
INFO_SUMMARY_UPGRADE_APPLYING_ADS_CUSTOMIZATION=Applying Registration \
 Customizations...
INFO_SUMMARY_UPGRADE_APPLYING_SCHEMA_CUSTOMIZATION=Applying Schema \
 Customizations...
INFO_SUMMARY_UPGRADE_BACKING_UP_DB=Backing Up Data...
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/CliUserInteraction.java
@@ -28,15 +28,19 @@
package org.opends.quicksetup;
import org.opends.messages.Message;
import org.opends.messages.MessageBuilder;
import static org.opends.messages.AdminToolMessages.*;
import org.opends.quicksetup.util.Utils;
import org.opends.server.util.StaticUtils;
import org.opends.server.util.cli.CLIException;
import org.opends.server.util.cli.ConsoleApplication;
import org.opends.server.util.cli.Menu;
import org.opends.server.util.cli.MenuBuilder;
import org.opends.server.util.cli.MenuResult;
import java.util.List;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.io.PrintStream;
@@ -82,61 +86,74 @@
  public Object confirm(Message summary, Message details, Message fineDetails,
                        Message title, MessageType type, Message[] options,
                        Message def, Message viewDetailsOption) {
    List<String> sOptions = new ArrayList<String>();
    MenuBuilder<Integer> builder = new MenuBuilder<Integer>(this);
    MessageBuilder b = new MessageBuilder();
    b.append(summary);
    b.append(Constants.LINE_SEPARATOR);
    b.append(details);
    builder.setPrompt(b.toMessage());
    int defInt = -1;
    for (int i = 0; i < options.length; i++) {
      sOptions.add(createOption(i + 1, options[i].toString()));
      if (options[i].equals(def)) {
    for (int i=0; i<options.length; i++)
    {
      builder.addNumberedOption(options[i], MenuResult.success(i+1));
      if (options[i].equals(def))
      {
        defInt = i + 1;
      }
    }
    if (fineDetails != null) {
      sOptions.add(createOption(options.length + 1,
              viewDetailsOption != null ?
                      viewDetailsOption.toString() :
                      INFO_CLI_VIEW_DETAILS.get().toString()));
      Message detailsPrompt = viewDetailsOption;
      if (detailsPrompt == null)
      {
        detailsPrompt = INFO_CLI_VIEW_DETAILS.get();
      }
      builder.addNumberedOption(detailsPrompt,
          MenuResult.success(options.length + 1));
    }
    println(summary);
    println();
    println(details);
    builder.setDefault(Message.raw(String.valueOf(defInt)),
        MenuResult.success(defInt));
    Menu<Integer> menu = builder.toMenu();
    Object returnValue = null;
    boolean menuDisplayed = false;
    while (returnValue == null) {
      println();
      for (String o : sOptions) {
        println(o);
      }
      print(
          Message.raw("%s%n[%s]:",
              INFO_CLI_NUMBER_PROMPT.get().toString(),
              Integer.toString(defInt)));
      String response = "";
      int respInt = -1;
      try
      {
        response = readLineOfInput(null);
        if (menuDisplayed)
        {
          println();
          builder.setPrompt(null);
          menu = builder.toMenu();
        }
        MenuResult<Integer> m = menu.run();
        menuDisplayed = true;
        if (m.isSuccess())
        {
          respInt = m.getValue();
        }
        else
        {
          // Should never happen.
          throw new RuntimeException();
        }
      }
      catch (CLIException ce)
      {
        respInt = defInt;
        LOG.log(Level.WARNING, "Error reading input: "+ce, ce);
      }
      int respInt = -1;
      if (response.equals("")) {
        respInt = defInt;
      } else {
        try {
          respInt = Integer.parseInt(response);
        } catch (Exception e) {
          // do nothing;
        }
      }
      if (fineDetails != null && respInt == options.length + 1) {
        println();
        println(String.valueOf(fineDetails));
      } else if (respInt > 0 && respInt <= options.length) {
        returnValue = options[respInt - 1];
      } else {
        println(INFO_CLI_INVALID_RESPONSE.get()+" " + response);
        returnValue = options[respInt - 1];
      }
    }
    return returnValue;
@@ -166,13 +183,6 @@
    return readInput(prompt, defaultValue, LOG);
  }
  private String createOption(int index, String option) {
    return new StringBuilder().
            append(Integer.toString(index)).
            append(". ").
            append(option).toString();
  }
  private void println(String text) {
    text = Utils.convertHtmlBreakToLineSeparator(text);
    text = Utils.stripHtml(text);
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/Installation.java
@@ -27,6 +27,7 @@
package org.opends.quicksetup;
import org.opends.admin.ads.ADSContext;
import org.opends.messages.Message;
import static org.opends.messages.QuickSetupMessages.*;
@@ -136,6 +137,12 @@
  public static final String BASE_CONFIG_FILE_PREFIX ="config.ldif.";
  /**
   * The relative path to the tools.properties file.
   */
  public static final String TOOLS_PROPERTIES =
    CONFIG_PATH_RELATIVE+File.separator+"tools.properties";
  /**
   * The UNIX setup script file name.
   */
  public static final String UNIX_SETUP_FILE_NAME = "setup";
@@ -464,6 +471,15 @@
  }
  /**
   * Returns the path to the tools properties file.
   *
   * @return the path to the tools properties file.
   */
  public File getToolsPropertiesFile() {
    return new File(getRootDirectory(), TOOLS_PROPERTIES);
  }
  /**
   * Creates a File object representing config/upgrade/schema.ldif.current
   * which the server creates the first time it starts if there are schema
   * customizations.
@@ -526,6 +542,16 @@
  }
  /**
   * Returns the path to the ADS file of the directory server.  Note
   * that this method assumes that this code is being run locally.
   *
   * @return the path of the ADS file of the directory server.
   */
  public File getADSBackendFile() {
    return new File(getRootDirectory(), ADSContext.getAdminLDIFFile());
  }
  /**
   * Returns the relative path of the directory containing the binaries/scripts
   * of the Open DS installation.  The path is relative to the installation
   * path.
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/upgrader/MigrationManager.java
@@ -38,6 +38,7 @@
import org.opends.quicksetup.Constants;
import org.opends.quicksetup.util.ExternalTools;
import org.opends.quicksetup.util.FileManager;
import org.opends.quicksetup.util.Utils;
import org.opends.quicksetup.util.OperationOutput;
import org.opends.quicksetup.util.InProcessServerController;
@@ -184,6 +185,59 @@
  }
  /**
   * Tells whether the ADS backend file must be migrated or not.
   * This method assumes that the ADS backend file in the original install
   * has not been overwritten.
   * @return <CODE>true</CODE> if the tools properties file must be migrated
   * and <CODE>false</CODE> otherwise.
   * @throws IOException if there is an error accessing the installation
   * information.
   */
  public boolean mustMigrateADS() throws IOException {
    return !installation.getADSBackendFile().exists();
  }
  /**
   * Migrates the ADS backend file.
   * @param newADSFile the new ADS backend file.
   * @throws ApplicationException if there is an error copying the new
   * ADS backend file.
   */
  public void migrateADS(File newADSFile) throws ApplicationException
  {
    FileManager fileManager = new FileManager();
    fileManager.copy(newADSFile, installation.getConfigurationDirectory(),
        true);
  }
  /**
   * Tells whether the tools properties file must be migrated or not.
   * This method assumes that the tools properties file in the original install
   * has not been overwritten.
   * @return <CODE>true</CODE> if the tools properties file must be migrated
   * and <CODE>false</CODE> otherwise.
   */
  public boolean mustMigrateToolProperties()
  {
   return !installation.getToolsPropertiesFile().exists();
  }
  /**
   * Migrates the tools properties file.
   * @param newPropertiesFile the new properties file.
   * @throws ApplicationException if there is an error copying the new
   * properties file.
   */
  public void migrateToolPropertiesFile(File newPropertiesFile)
  throws ApplicationException
  {
    FileManager fileManager = new FileManager();
    fileManager.copy(newPropertiesFile,
        installation.getConfigurationDirectory(), true);
  }
  /**
   * Migrates a schema using the diff file generated by a call
   * to {@link MigrationManager#calculateSchemaCustomizations()}.
   * @throws ApplicationException if there is an error migrating the
@@ -223,7 +277,7 @@
   * {@link #calculateConfigCustomizations()} must first be made in
   * order for this value to be valid.
   *
   * @return boolean where true indicates schema customization
   * @return boolean where true indicates configuration customization
   * @throws java.io.IOException if there was a problem reading the
   *         current configuration file.
   */
@@ -231,6 +285,7 @@
    return installation.getCurrentConfiguration().hasBeenModified();
  }
  /**
   * Applies modifications contained in an LDIF file to the server.
   *
@@ -301,32 +356,82 @@
  private Message getModificationErrorMessage(ChangeRecordEntry cre) {
    MessageBuilder msg = new MessageBuilder();
    if (Utils.isCli())
    {
      msg.append(Constants.LINE_SEPARATOR);
    }
    else
    {
    msg.append(Constants.HTML_LINE_BREAK);
    }
    if (cre != null) {
      switch (cre.getChangeOperationType()) {
        case MODIFY:
          if (Utils.isCli())
          {
            msg.append(INFO_ERROR_UPGRADE_MIGRATION_MODIFY_CLI.get(
                cre.getDN().toNormalizedString()));
          }
          else
          {
          msg.append(INFO_ERROR_UPGRADE_MIGRATION_MODIFY.get(
                  cre.getDN().toNormalizedString()));
          }
          break;
        case ADD:
          if (Utils.isCli())
          {
            msg.append(INFO_ERROR_UPGRADE_MIGRATION_ADD_CLI.get(
                cre.getDN().toNormalizedString()));
          }
          else
          {
          msg.append(INFO_ERROR_UPGRADE_MIGRATION_ADD.get(
                  cre.getDN().toNormalizedString()));
          }
          break;
        case DELETE:
          if (Utils.isCli())
          {
            msg.append(INFO_ERROR_UPGRADE_MIGRATION_DELETE_CLI.get(
                cre.getDN().toNormalizedString()));
          }
          else
          {
          msg.append(INFO_ERROR_UPGRADE_MIGRATION_DELETE.get(
                  cre.getDN().toNormalizedString()));
          }
          break;
        default:
          LOG.log(Level.INFO, "Unexpected change operation type " +
                cre.getChangeOperationType());
        if (Utils.isCli())
        {
          msg.append(INFO_ERROR_UPGRADE_MIGRATION_UNEXPECTED_CLI.get(
              cre.getDN().toNormalizedString()));
        }
        else
        {
          msg.append(INFO_ERROR_UPGRADE_MIGRATION_UNEXPECTED.get(
                  cre.getDN().toNormalizedString()));
        }
          break;
      }
    }
    if (Utils.isCli())
    {
      msg.append(Constants.LINE_SEPARATOR);
      msg.append(Constants.LINE_SEPARATOR);
      msg.append(INFO_ERROR_UPGRADE_MIGRATION_NOTE_CLI.get(
          Utils.getPath(backupDir)));
    }
    else
    {
    msg.append(Constants.HTML_LINE_BREAK);
    msg.append(Constants.HTML_LINE_BREAK);
    msg.append(INFO_ERROR_UPGRADE_MIGRATION_NOTE.get(Utils.getPath(backupDir)));
      msg.append(INFO_ERROR_UPGRADE_MIGRATION_NOTE.get(
          Utils.getPath(backupDir)));
    }
    return msg.toMessage();
  }
@@ -355,4 +460,7 @@
    return new File(backupDir, "schema.custom.diff");
  }
  private File getCustomADSDiffFile() throws IOException {
    return new File(backupDir, "admin-backend.custom.diff");
  }
}
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/upgrader/UpgradeFileFilter.java
@@ -53,6 +53,10 @@
            Upgrader.ROOT_FILES_TO_IGNORE_DURING_BACKUP) {
      filesToIgnore.add(new File(root, rootFileNamesToIgnore));
    }
    for (String rootFileNamesToIgnore :
      Upgrader.FILES_TO_IGNORE_DURING_BACKUP) {
      filesToIgnore.add(new File(root, rootFileNamesToIgnore));
    }
  }
  /**
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/upgrader/UpgradeProgressStep.java
@@ -68,6 +68,9 @@
  APPLYING_CONFIGURATION_CUSTOMIZATIONS(
          INFO_SUMMARY_UPGRADE_APPLYING_CONFIG_CUSTOMIZATION.get(), 75),
  APPLYING_ADS_CUSTOMIZATIONS(
          INFO_SUMMARY_UPGRADE_APPLYING_ADS_CUSTOMIZATION.get(), 78),
  VERIFYING(INFO_SUMMARY_UPGRADE_VERIFYING.get(), 80),
  STARTING_SERVER(INFO_SUMMARY_STARTING.get(), 90),
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java
@@ -30,6 +30,8 @@
import org.opends.quicksetup.CliApplication;
import static org.opends.quicksetup.Installation.*;
import static org.opends.messages.QuickSetupMessages.*;
import org.opends.admin.ads.ADSContext;
import org.opends.messages.Message;
import org.opends.messages.MessageBuilder;
@@ -134,6 +136,12 @@
          TMP_PATH_RELATIVE // tmp
  };
  // Files that will be ignored during backup
  static final String[] FILES_TO_IGNORE_DURING_BACKUP = {
          TOOLS_PROPERTIES, // tools.properties
          ADSContext.getAdminLDIFFile() // admin-backend.ldif
  };
  private ProgressStep currentProgressStep = UpgradeProgressStep.NOT_STARTED;
  /**
@@ -827,6 +835,40 @@
        checkAbort();
        if (migration.mustMigrateADS())
        {
          try {
            LOG.log(Level.INFO, "Applying registration changes");
            migration.migrateADS(
                getStagedInstallation().getADSBackendFile());
            LOG.log(Level.INFO, "custom registration application finished");
          } catch (ApplicationException e) {
            notifyListeners(getFormattedErrorWithLineBreak());
            LOG.log(Level.INFO,
                "Error applying registration customizations", e);
            throw e;
          }
        }
        checkAbort();
        if (migration.mustMigrateToolProperties())
        {
          try {
            LOG.log(Level.INFO, "Applying tools properties");
            migration.migrateToolPropertiesFile(
                getStagedInstallation().getToolsPropertiesFile());
            LOG.log(Level.INFO, "tools properties application finished");
          } catch (ApplicationException e) {
            notifyListeners(getFormattedErrorWithLineBreak());
            LOG.log(Level.INFO,
                "Error applying tools properties changes", e);
            throw e;
          }
        }
        checkAbort();
        try {
          LOG.log(Level.INFO, "stopping server");
          // This class imports classes from the server