| | |
| | | */ |
| | | package org.opends.server.tools.upgrade; |
| | | |
| | | import static org.opends.messages.ConfigMessages.*; |
| | | import static org.opends.messages.ToolMessages.*; |
| | | import static org.opends.server.tools.upgrade.FileManager.*; |
| | | import static org.opends.server.tools.upgrade.Installation.*; |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | |
| | | import java.io.BufferedReader; |
| | | import java.io.File; |
| | | import java.io.FileInputStream; |
| | | import java.io.FileOutputStream; |
| | | import java.io.FileReader; |
| | | import java.io.FileWriter; |
| | | import java.io.IOException; |
| | | import java.io.*; |
| | | import java.util.LinkedList; |
| | | import java.util.SortedMap; |
| | | import java.util.TreeMap; |
| | | import java.util.logging.Level; |
| | | import java.util.logging.Logger; |
| | | |
| | | import org.forgerock.opendj.ldap.Attribute; |
| | | import org.forgerock.opendj.ldap.ConditionResult; |
| | | import org.forgerock.opendj.ldap.DN; |
| | | import org.forgerock.opendj.ldap.Entries; |
| | | import org.forgerock.opendj.ldap.Entry; |
| | | import org.forgerock.opendj.ldap.Filter; |
| | | import org.forgerock.opendj.ldap.LinkedHashMapEntry; |
| | | import org.forgerock.opendj.ldap.Matcher; |
| | | import org.forgerock.opendj.ldap.*; |
| | | import org.forgerock.opendj.ldap.requests.AddRequest; |
| | | import org.forgerock.opendj.ldap.requests.ModifyRequest; |
| | | import org.forgerock.opendj.ldap.requests.Requests; |
| | |
| | | import org.forgerock.opendj.ldap.schema.UnknownSchemaElementException; |
| | | import org.forgerock.opendj.ldif.LDIFEntryReader; |
| | | import org.forgerock.opendj.ldif.LDIFEntryWriter; |
| | | import org.opends.server.controls.PersistentSearchChangeType; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.protocols.ldap.LDAPFilter; |
| | | import org.opends.server.util.ChangeOperationType; |
| | | import org.opends.server.util.SetupUtils; |
| | | import org.opends.server.util.StaticUtils; |
| | | |
| | | import static org.opends.messages.ConfigMessages.INFO_CONFIG_FILE_HEADER; |
| | | import static org.opends.messages.ToolMessages.ERR_UPGRADE_UNKNOWN_OC_ATT; |
| | | import static org.opends.server.tools.upgrade.FileManager.deleteRecursively; |
| | | import static org.opends.server.tools.upgrade.FileManager.rename; |
| | | import static org.opends.server.tools.upgrade.Installation.CURRENT_CONFIG_FILE_NAME; |
| | | import static org.opends.server.tools.upgrade.Installation.SVC_SCRIPT_FILE_NAME; |
| | | import static org.opends.server.util.ServerConstants.EOL; |
| | | |
| | | /** |
| | | * Common utility methods needed by the upgrade. |
| | | */ |
| | |
| | | { |
| | | |
| | | /** |
| | | * Upgrade's logger. |
| | | * Logger for the upgrade. |
| | | */ |
| | | private final static Logger LOG = Logger |
| | | .getLogger(UpgradeCli.class.getName()); |
| | | |
| | | /** The config folder of the current installation. */ |
| | | static final File configDirectory = new File(getInstallationPath(), |
| | | /** The config folder of the current instance. */ |
| | | static final File configDirectory = new File(getInstancePath(), |
| | | Installation.CONFIG_PATH_RELATIVE); |
| | | |
| | | /** The config/schema folder of the current installation. */ |
| | | static final File configSchemaDirectory = new File(getInstallationPath(), |
| | | Installation.CONFIG_PATH_RELATIVE + File.separator |
| | | + Installation.SCHEMA_PATH_RELATIVE); |
| | | /** The config/schema folder of the current instance. */ |
| | | static final File configSchemaDirectory = new File( |
| | | configDirectory, Installation.SCHEMA_PATH_RELATIVE); |
| | | |
| | | /** The template folder of the current installation. */ |
| | | static final File templateDirectory = new File(getInstallationPath(), |
| | | Installation.CONFIG_PATH_RELATIVE + File.separator |
| | | + Installation.TEMPLATE_RELATIVE_PATH); |
| | | Installation.TEMPLATE_RELATIVE_PATH); |
| | | |
| | | /** The template/config folder of the current installation. */ |
| | | static final File templateConfigDirectory = new File(templateDirectory, |
| | | Installation.CONFIG_PATH_RELATIVE); |
| | | |
| | | /** The template/config/schema folder of the current installation. */ |
| | | static final File templateConfigSchemaDirectory = new File( |
| | | getInstallationPath(), Installation.TEMPLATE_RELATIVE_PATH |
| | | + File.separator + Installation.CONFIG_PATH_RELATIVE |
| | | + File.separator + Installation.SCHEMA_PATH_RELATIVE); |
| | | templateConfigDirectory, |
| | | Installation.SCHEMA_PATH_RELATIVE); |
| | | |
| | | /** The template/config folder of the current installation. */ |
| | | static final File templateConfigDirectory = new File( |
| | | getInstallationPath(), Installation.TEMPLATE_RELATIVE_PATH |
| | | + File.separator + Installation.CONFIG_PATH_RELATIVE); |
| | | |
| | | /** The config snmp security folder of the current installation. */ |
| | | /** The config/snmp/security folder of the current instance. */ |
| | | static final File configSnmpSecurityDirectory = new File( |
| | | getInstallationPath(), Installation.CONFIG_PATH_RELATIVE |
| | | + File.separator + Installation.SNMP_PATH_RELATIVE + File.separator |
| | | + Installation.SECURITY_PATH_RELATIVE); |
| | | configDirectory + File.separator + Installation.SNMP_PATH_RELATIVE |
| | | + File.separator + Installation.SECURITY_PATH_RELATIVE); |
| | | |
| | | /** |
| | | * Returns the path of the installation of the directory server. Note that |
| | |
| | | static String getInstancePathFromInstallPath(final String installPath) |
| | | { |
| | | String instancePathFileName = Installation.INSTANCE_LOCATION_PATH; |
| | | final File configureScriptPath = |
| | | final File _svcScriptPath = |
| | | new File(installPath + File.separator |
| | | + Installation.UNIX_CONFIGURE_FILE_NAME); |
| | | + SVC_SCRIPT_FILE_NAME); |
| | | |
| | | // look for /etc/opt/opends/instance.loc |
| | | // look for /etc/opt/opendj/instance.loc |
| | | File f = new File(instancePathFileName); |
| | | if (!configureScriptPath.exists() || !f.exists()) |
| | | if (!_svcScriptPath.exists() || !f.exists()) |
| | | { |
| | | // look for <installPath>/instance.loc |
| | | instancePathFileName = |
| | |
| | | * Do a best effort to avoid having a relative representation (for |
| | | * instance to avoid having ../../../). |
| | | */ |
| | | File canonical = f.getCanonicalFile(); |
| | | f = canonical; |
| | | f = f.getCanonicalFile(); |
| | | } |
| | | catch (IOException ioe) |
| | | { |
| | |
| | | * @return the instance root directory (the path where the instance is |
| | | * installed). |
| | | */ |
| | | static final String getInstancePath() |
| | | static String getInstancePath() |
| | | { |
| | | final String installPath = getInstallationPath(); |
| | | if (installPath == null) |
| | |
| | | * |
| | | * @return The server's installation path. |
| | | */ |
| | | static final String getInstallationPath() |
| | | static String getInstallationPath() |
| | | { |
| | | // The upgrade runs from the bits extracted by BuildExtractor |
| | | // in the staging directory. However |
| | |
| | | // This function is not in use actually but may be useful later |
| | | // eg. for rebuild index task. |
| | | @SuppressWarnings("unused") |
| | | private static final SortedMap<String, LinkedList<String>> getLocalBackends() |
| | | private static SortedMap<String, LinkedList<String>> getLocalBackends() |
| | | { |
| | | // Config.ldif path |
| | | final File configLdif = new File(configDirectory, |
| | |
| | | final Matcher includeFilter = filter.matcher(); |
| | | entryReader.setIncludeFilter(includeFilter); |
| | | |
| | | Entry entry = null; |
| | | while (entryReader.hasNext()) |
| | | { |
| | | LinkedList<String> dataRelativesToBck = new LinkedList<String>(); |
| | | entry = entryReader.readEntry(); |
| | | Entry entry = entryReader.readEntry(); |
| | | // Backend dn |
| | | dataRelativesToBck.add(entry.getAttribute("ds-cfg-base-dn") |
| | | .firstValueAsString()); |
| | |
| | | /** |
| | | * Updates the config file during the upgrade process. |
| | | * |
| | | * |
| | | * @param configPath |
| | | * The original path to the file. |
| | | * @param filter |
| | |
| | | * If an Exception occurs during the input output methods. |
| | | * @return The changes number that have occurred. |
| | | */ |
| | | static final int updateConfigFile(final String configPath, |
| | | final LDAPFilter filter, final PersistentSearchChangeType changeType, |
| | | static int updateConfigFile(final String configPath, |
| | | final LDAPFilter filter, final ChangeOperationType changeType, |
| | | final String... lines) throws IOException |
| | | { |
| | | final File original = new File(configPath); |
| | |
| | | writer.writeComment(INFO_CONFIG_FILE_HEADER.get()); |
| | | writer.setWrapColumn(0); |
| | | |
| | | Entry entry = null; |
| | | |
| | | boolean alreadyExist = false; |
| | | String dn = null; |
| | | if (filter == null && changeType == ChangeOperationType.ADD) |
| | | { |
| | | // For an Add, the first line should start with dn: |
| | | dn = lines[0].replaceFirst("dn: ",""); |
| | | } |
| | | while (entryReader.hasNext()) |
| | | { |
| | | entry = entryReader.readEntry(); |
| | | Entry entry = entryReader.readEntry(); |
| | | // Searching for the related entries |
| | | if (filter != null |
| | | && Filter.valueOf(filter.toString()).matches(entry) |
| | |
| | | LOG.log(Level.SEVERE, ex.getMessage()); |
| | | } |
| | | } |
| | | if (filter == null && changeType == PersistentSearchChangeType.ADD |
| | | && ("dn: " + entry.getName()).equals(lines[0])) |
| | | if (dn != null // This is an ADD |
| | | && entry.getName().equals(DN.valueOf(dn))) |
| | | { |
| | | LOG.log(Level.INFO, String.format("Entry %s found", entry.getName() |
| | | .toString())); |
| | |
| | | writer.writeEntry(entry); |
| | | } |
| | | |
| | | if (filter == null && changeType == PersistentSearchChangeType.ADD |
| | | && !alreadyExist) |
| | | // If it's an ADD and the entry doesn't exist yet |
| | | if (dn != null && !alreadyExist) |
| | | { |
| | | final AddRequest ar = Requests.newAddRequest(lines); |
| | | writer.writeEntry(ar); |
| | | LOG.log(Level.INFO, String.format("Entry successfully added %s in %s", |
| | | entry.getName().toString(), original.getAbsolutePath())); |
| | | dn, original.getAbsolutePath())); |
| | | changeCount++; |
| | | } |
| | | } |
| | |
| | | } |
| | | finally |
| | | { |
| | | // The reader and writer must be close before writing files. |
| | | // This causes exceptions under windozs OS. |
| | | // The reader and writer must be close before renaming files. |
| | | // Otherwise it causes exceptions under windows OS. |
| | | StaticUtils.close(entryReader, writer); |
| | | } |
| | | |
| | |
| | | |
| | | /** |
| | | * This task adds new attributes / object classes to the specified destination |
| | | * file. The new attributes and object classes must be originaly defined in |
| | | * file. The new attributes and object classes must be originally defined in |
| | | * the template file. |
| | | * |
| | | * @param templateFile |
| | |
| | | final LinkedList<String> definitionsList = new LinkedList<String>(); |
| | | |
| | | final Entry schemaEntry = reader.readEntry(); |
| | | Schema schema = null; |
| | | |
| | | schema = |
| | | Schema schema = |
| | | new SchemaBuilder(Schema.getCoreSchema()) |
| | | .addSchema(schemaEntry, true).toSchema(); |
| | | if (attributes != null) |
| | |
| | | * schema files are supposed to be. |
| | | */ |
| | | static void updateConfigUpgradeSchemaFile(final File folder, |
| | | final String revision) throws IOException |
| | | final String revision) throws Exception |
| | | { |
| | | // We need to upgrade the schema.ldif.<rev> file contained in the |
| | | // config/upgrade folder otherwise, we cannot enable the backend at |
| | |
| | | LOG.log(Level.INFO, String.format("Processing %s", f |
| | | .getAbsolutePath())); |
| | | reader = new LDIFEntryReader(new FileInputStream(f)); |
| | | while (reader.hasNext()) |
| | | try |
| | | { |
| | | try |
| | | while (reader.hasNext()) |
| | | { |
| | | final Entry entry = reader.readEntry(); |
| | | theNewSchemaEntry.setName(entry.getName()); |
| | |
| | | theNewSchemaEntry.addAttribute(at); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | LOG.log(Level.SEVERE, ex.getMessage()); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | throw new Exception("Error parsing existing schema file " |
| | | + f.getName() + " - " + ex.getMessage(), ex); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | // Checks if the parent exists (eg. embedded |
| | | // server doesn't seem to provide that folder) |
| | | if (!destination.getParentFile().exists()) |
| | | File parentDirectory = destination.getParentFile(); |
| | | if (!parentDirectory.exists()) |
| | | { |
| | | LOG.log(Level.INFO, String.format("File %s's parent doesn't exist", |
| | | destination.getPath())); |
| | | |
| | | destination.getParentFile().mkdirs(); |
| | | parentDirectory.mkdirs(); |
| | | |
| | | LOG.log(Level.INFO, String.format("Parent directory created.", |
| | | destination.getPath())); |
| | | LOG.log(Level.INFO, String.format("Parent directory %s created.", |
| | | parentDirectory.getPath())); |
| | | } |
| | | if (!destination.exists()) |
| | | { |
| | |
| | | } |
| | | finally |
| | | { |
| | | reader.close(); |
| | | writer.close(); |
| | | StaticUtils.close(reader, writer); |
| | | } |
| | | } |
| | | |
| | | private static String[] readLDIFLines(final DN dn, |
| | | final PersistentSearchChangeType changeType, final String... lines) |
| | | final ChangeOperationType changeType, final String... lines) |
| | | { |
| | | final String[] modifiedLines = new String[lines.length + 2]; |
| | | |
| | | int index = 0; |
| | | if (changeType == PersistentSearchChangeType.MODIFY) |
| | | if (changeType == ChangeOperationType.MODIFY) |
| | | { |
| | | modifiedLines[0] = "dn: " + dn; |
| | | modifiedLines[1] = "changetype: modify"; |