001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Portions Copyright 2013-2016 ForgeRock AS. 015 */ 016package org.opends.server.tools.upgrade; 017 018import java.io.File; 019import java.io.FileWriter; 020import java.io.IOException; 021import java.util.Arrays; 022import java.util.LinkedList; 023import java.util.List; 024import java.util.NavigableMap; 025import java.util.TreeMap; 026 027import org.forgerock.i18n.LocalizableMessage; 028import org.forgerock.i18n.slf4j.LocalizedLogger; 029import org.opends.server.core.LockFileManager; 030import org.opends.server.tools.upgrade.UpgradeTasks.UpgradeCondition; 031import org.opends.server.util.BuildVersion; 032 033import com.forgerock.opendj.cli.ClientException; 034import com.forgerock.opendj.cli.ReturnCode; 035 036import static com.forgerock.opendj.cli.Utils.*; 037import static javax.security.auth.callback.ConfirmationCallback.*; 038import static javax.security.auth.callback.TextOutputCallback.WARNING; 039 040import static org.opends.messages.ToolMessages.*; 041import static org.opends.server.tools.upgrade.FormattedNotificationCallback.*; 042import static org.opends.server.tools.upgrade.LicenseFile.*; 043import static org.opends.server.tools.upgrade.UpgradeTasks.*; 044import static org.opends.server.tools.upgrade.UpgradeUtils.batDirectory; 045import static org.opends.server.tools.upgrade.UpgradeUtils.binDirectory; 046import static org.opends.server.tools.upgrade.UpgradeUtils.libDirectory; 047import static org.opends.server.util.StaticUtils.*; 048 049/** 050 * This class contains the table of upgrade tasks that need performing when 051 * upgrading from one version to another. 052 */ 053public final class Upgrade 054{ 055 /** Upgrade's logger. */ 056 private static LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 057 058 /** Upgrade supports version from 2.4.5. */ 059 private static BuildVersion UPGRADE_SUPPORTS_VERSION_FROM = BuildVersion.valueOf("2.4.5.0000"); 060 061 /** The success exit code value. */ 062 static final int EXIT_CODE_SUCCESS = 0; 063 /** The error exit code value. */ 064 static final int EXIT_CODE_ERROR = 1; 065 066 /** If the upgrade contains some post upgrade tasks to do. */ 067 private static boolean hasPostUpgradeTask; 068 069 /** If the upgrade script should exit with error code (useful for warnings) */ 070 private static boolean exitWithErrorCode; 071 072 /** Developers should register upgrade tasks below. */ 073 private static final NavigableMap<BuildVersion, List<UpgradeTask>> TASKS = new TreeMap<>(); 074 private static final List<UpgradeTask> MANDATORY_TASKS = new LinkedList<>(); 075 076 static 077 { 078 // @formatter:off 079 /** See OPENDJ-2716 */ 080 register("2.5.0", 081 newAttributeTypes(INFO_UPGRADE_TASK_2716_1_SUMMARY.get(), 082 "03-changelog.ldif", "1.3.6.1.4.1.36733.2.1.1.6"), // includedAttributes 083 newObjectClasses(INFO_UPGRADE_TASK_2716_2_SUMMARY.get(), 084 "03-changelog.ldif", "2.16.840.1.113730.3.2.1")); // changeLogEntry 085 086 register("2.5.0", 087 modifyConfigEntry(INFO_UPGRADE_TASK_6869_SUMMARY.get(), 088 "(objectClass=ds-cfg-collation-matching-rule)", 089 "add: ds-cfg-collation", 090 "ds-cfg-collation: de:1.3.6.1.4.1.42.2.27.9.4.28.1", 091 "ds-cfg-collation: de-DE:1.3.6.1.4.1.42.2.27.9.4.28.1", 092 "-", 093 "delete: ds-cfg-collation", 094 "ds-cfg-collation: de:1.3.6.1.4.1.142.2.27.9.4.28.1", 095 "ds-cfg-collation: de-DE:1.3.6.1.4.1.142.2.27.9.4.28.1")); 096 097 register("2.5.0", 098 modifyConfigEntry(INFO_UPGRADE_TASK_7192_SUMMARY.get(), 099 "(objectClass=ds-cfg-password-policy)", 100 "add: objectClass", 101 "objectClass: ds-cfg-authentication-policy", 102 "-", 103 "add: ds-cfg-java-class", 104 "ds-cfg-java-class: org.opends.server.core.PasswordPolicyFactory")); 105 106 register("2.5.0", 107 modifyConfigEntry(INFO_UPGRADE_TASK_7364_SUMMARY.get(), 108 "(ds-cfg-java-class=org.opends.server.loggers.TextAuditLogPublisher)", 109 "add: objectClass", 110 "objectClass: ds-cfg-file-based-audit-log-publisher", 111 "-", 112 "delete: objectClass", 113 "objectClass: ds-cfg-file-based-access-log-publisher")); 114 115 register("2.5.0", 116 renameSnmpSecurityConfig(INFO_UPGRADE_TASK_7466_SUMMARY.get())); 117 118 register("2.5.0", 119 newAttributeTypes(INFO_UPGRADE_TASK_7748_1_SUMMARY.get(), 120 "00-core.ldif", "1.3.6.1.4.1.36733.2.1.1.59"), //etag 121 addConfigEntry(INFO_UPGRADE_TASK_7748_2_SUMMARY.get(), 122 "dn: cn=etag,cn=Virtual Attributes,cn=config", 123 "changetype: add", 124 "objectClass: top", 125 "objectClass: ds-cfg-virtual-attribute", 126 "objectClass: ds-cfg-entity-tag-virtual-attribute", 127 "cn: etag", 128 "ds-cfg-java-class: org.opends.server.extensions." 129 + "EntityTagVirtualAttributeProvider", 130 "ds-cfg-enabled: true", 131 "ds-cfg-attribute-type: etag", 132 "ds-cfg-conflict-behavior: real-overrides-virtual", 133 "ds-cfg-checksum-algorithm: adler-32", 134 "ds-cfg-excluded-attribute: ds-sync-hist")); 135 136 register("2.5.0", 137 addConfigEntry(INFO_UPGRADE_TASK_7834_SUMMARY.get(), 138 "dn: cn=Password Expiration Time,cn=Virtual Attributes,cn=config", 139 "changetype: add", 140 "objectClass: top", 141 "objectClass: ds-cfg-virtual-attribute", 142 "objectClass: ds-cfg-password-expiration-time-virtual-attribute", 143 "cn: Password Expiration Time", 144 "ds-cfg-java-class: org.opends.server.extensions." 145 + "PasswordExpirationTimeVirtualAttributeProvider", 146 "ds-cfg-enabled: true", 147 "ds-cfg-attribute-type: ds-pwp-password-expiration-time", 148 "ds-cfg-conflict-behavior: virtual-overrides-real")); 149 150 register("2.5.0", 151 modifyConfigEntry(INFO_UPGRADE_TASK_7979_SUMMARY.get(), 152 "(ds-cfg-java-class=org.opends.server.schema.CertificateSyntax)", 153 "add: objectClass", 154 "objectClass: ds-cfg-certificate-attribute-syntax", 155 "-", 156 "add: ds-cfg-strict-format", 157 "ds-cfg-strict-format: false")); 158 159 register("2.6.0", 160 modifyConfigEntry(INFO_UPGRADE_TASK_8124_SUMMARY.get(), 161 "(ds-cfg-java-class=org.opends.server.schema.JPEGSyntax)", 162 "add: objectClass", 163 "objectClass: ds-cfg-jpeg-attribute-syntax", 164 "-", 165 "add: ds-cfg-strict-format", 166 "ds-cfg-strict-format: false")); 167 168 register("2.6.0", 169 modifyConfigEntry(INFO_UPGRADE_TASK_8133_SUMMARY.get(), 170 "(ds-cfg-java-class=org.opends.server.schema.CountryStringSyntax)", 171 "add: objectClass", 172 "objectClass: ds-cfg-country-string-attribute-syntax", 173 "-", 174 "add: ds-cfg-strict-format", 175 "ds-cfg-strict-format: false")); 176 177 register("2.6.0", 178 requireConfirmation(INFO_UPGRADE_TASK_8214_DESCRIPTION.get(), YES, 179 modifyConfigEntry(INFO_UPGRADE_TASK_8214_SUMMARY.get(), 180 "(ds-cfg-java-class=org.opends.server.extensions.IsMemberOfVirtualAttributeProvider)", 181 "add: ds-cfg-filter", 182 "ds-cfg-filter: (|(objectClass=person)(objectClass=groupOfNames)" 183 + "(objectClass=groupOfUniqueNames)(objectClass=groupOfEntries))", 184 "-", 185 "delete: ds-cfg-filter", 186 "ds-cfg-filter: (objectClass=person)"))); 187 188 register("2.6.0", 189 modifyConfigEntry(INFO_UPGRADE_TASK_8387_SUMMARY.get(), 190 "(objectClass=ds-cfg-dictionary-password-validator)", 191 "add: ds-cfg-check-substrings", 192 "ds-cfg-check-substrings: false")); 193 194 register("2.6.0", 195 modifyConfigEntry(INFO_UPGRADE_TASK_8389_SUMMARY.get(), 196 "(objectClass=ds-cfg-attribute-value-password-validator)", 197 "add: ds-cfg-check-substrings", 198 "ds-cfg-check-substrings: false")); 199 200 register("2.6.0", 201 addConfigEntry(INFO_UPGRADE_TASK_8487_SUMMARY.get(), 202 "dn: cn=PBKDF2,cn=Password Storage Schemes,cn=config", 203 "changetype: add", 204 "objectClass: top", 205 "objectClass: ds-cfg-password-storage-scheme", 206 "objectClass: ds-cfg-pbkdf2-password-storage-scheme", 207 "cn: PBKDF2", 208 "ds-cfg-java-class: org.opends.server.extensions." 209 + "PBKDF2PasswordStorageScheme", 210 "ds-cfg-enabled: true")); 211 212 register("2.6.0", 213 addConfigFile("http-config.json"), 214 addConfigEntry(INFO_UPGRADE_TASK_8613_SUMMARY.get(), 215 "dn: cn=HTTP Connection Handler,cn=Connection Handlers,cn=config", 216 "changetype: add", 217 "objectClass: ds-cfg-http-connection-handler", 218 "objectClass: ds-cfg-connection-handler", 219 "objectClass: top", 220 "ds-cfg-listen-port: 8080", 221 "cn: HTTP Connection Handler", 222 "ds-cfg-max-blocked-write-time-limit: 2 minutes", 223 "ds-cfg-ssl-client-auth-policy: optional", 224 "ds-cfg-use-tcp-keep-alive: true", 225 "ds-cfg-max-request-size: 5 megabytes", 226 "ds-cfg-use-tcp-no-delay: true", 227 "ds-cfg-allow-tcp-reuse-address: true", 228 "ds-cfg-accept-backlog: 128", 229 "ds-cfg-authentication-required: true", 230 "ds-cfg-buffer-size: 4096 bytes", 231 "ds-cfg-config-file: config/http-config.json", 232 "ds-cfg-listen-address: 0.0.0.0", 233 "ds-cfg-java-class: " + 234 "org.opends.server.protocols.http.HTTPConnectionHandler", 235 "ds-cfg-keep-stats: true", 236 "ds-cfg-ssl-cert-nickname: server-cert", 237 "ds-cfg-use-ssl: false", 238 "ds-cfg-enabled: false")); 239 240 register("2.6.0", 241 addConfigEntry(INFO_UPGRADE_TASK_8832_SUMMARY.get(), 242 "dn: cn=File-Based HTTP Access Logger,cn=Loggers,cn=config", 243 "changetype: add", 244 "objectClass: ds-cfg-file-based-http-access-log-publisher", 245 "objectClass: top", 246 "objectClass: ds-cfg-http-access-log-publisher", 247 "objectClass: ds-cfg-log-publisher", 248 "cn: File-Based HTTP Access Logger", 249 "ds-cfg-java-class: " + 250 "org.opends.server.loggers.TextHTTPAccessLogPublisher", 251 "ds-cfg-asynchronous: true", 252 "ds-cfg-log-file: logs/http-access", 253 "ds-cfg-rotation-policy: " + 254 "cn=24 Hours Time Limit Rotation Policy," + 255 "cn=Log Rotation Policies,cn=config", 256 "ds-cfg-rotation-policy: " + 257 "cn=Size Limit Rotation Policy,cn=Log Rotation Policies,cn=config", 258 "ds-cfg-retention-policy: " + 259 "cn=File Count Retention Policy,cn=Log Retention Policies,cn=config", 260 "ds-cfg-log-file-permissions: 640", 261 "ds-cfg-enabled: false")); 262 263 register("2.6.0", 264 newAttributeTypes(INFO_UPGRADE_TASK_8985_1_SUMMARY.get(), 265 "00-core.ldif", "1.2.840.113549.1.9.1"), // emailAddress 266 modifyConfigEntry(INFO_UPGRADE_TASK_8985_2_SUMMARY.get(), 267 "&(ds-cfg-java-class=org.opends.server.extensions." + 268 "SubjectAttributeToUserAttributeCertificateMapper)" + 269 "(ds-cfg-subject-attribute-mapping=e:mail)", 270 "delete:ds-cfg-subject-attribute-mapping", 271 "ds-cfg-subject-attribute-mapping: e:mail", 272 "-", 273 "add:ds-cfg-subject-attribute-mapping", 274 "ds-cfg-subject-attribute-mapping: emailAddress:mail")); 275 276 /** See OPENDJ-992 */ 277 register("2.6.0", 278 regressionInVersion("2.5.0", 279 rebuildIndexesNamed(INFO_UPGRADE_TASK_9013_DESCRIPTION.get(), 280 "ds-sync-hist"))); 281 282 /** See OPENDJ-1284 */ 283 register("2.8.0", // userCertificate OID / cACertificate OID 284 newAttributeTypes(INFO_UPGRADE_TASK_10133_1_SUMMARY.get(), 285 "00-core.ldif", "2.5.4.36", "2.5.4.37"), 286 addConfigEntry(INFO_UPGRADE_TASK_10133_2_SUMMARY.get(), 287 "dn: cn=Certificate Exact Matching Rule,cn=Matching Rules,cn=config", 288 "changetype: add", 289 "objectClass: top", 290 "objectClass: ds-cfg-matching-rule", 291 "objectClass: ds-cfg-equality-matching-rule", 292 "cn: Certificate Exact Matching Rule", 293 "ds-cfg-java-class: " 294 + "org.opends.server.schema.CertificateExactMatchingRuleFactory", 295 "ds-cfg-enabled: true")); 296 297 298 /** See OPENDJ-1295 */ 299 register("2.8.0", 300 copySchemaFile("03-pwpolicyextension.ldif")); 301 302 /** See OPENDJ-1490 and OPENDJ-1454 */ 303 register("2.8.0", 304 deleteConfigEntry(INFO_UPGRADE_TASK_10733_1_SUMMARY.get(), 305 "dn: ds-cfg-backend-id=replicationChanges,cn=Backends,cn=config"), 306 modifyConfigEntry(INFO_UPGRADE_TASK_10733_2_SUMMARY.get(), 307 "(objectClass=ds-cfg-dsee-compat-access-control-handler)", 308 "delete: ds-cfg-global-aci", 309 "ds-cfg-global-aci: " 310 + "(target=\"ldap:///dc=replicationchanges\")" 311 + "(targetattr=\"*\")" 312 + "(version 3.0; acl \"Replication backend access\"; " 313 + "deny (all) userdn=\"ldap:///anyone\";)")); 314 315 /** See OPENDJ-1351 */ 316 register("2.8.0", 317 modifyConfigEntry(INFO_UPGRADE_TASK_10820_SUMMARY.get(), 318 "(objectClass=ds-cfg-root-dn)", 319 "add: ds-cfg-default-root-privilege-name", 320 "ds-cfg-default-root-privilege-name: changelog-read")); 321 322 /** See OPENDJ-1580 */ 323 register("2.8.0", 324 addConfigEntry(INFO_UPGRADE_TASK_10908_SUMMARY.get(), 325 "dn: cn=PKCS5S2,cn=Password Storage Schemes,cn=config", 326 "changetype: add", 327 "objectClass: top", 328 "objectClass: ds-cfg-password-storage-scheme", 329 "objectClass: ds-cfg-pkcs5s2-password-storage-scheme", 330 "cn: PKCS5S2", 331 "ds-cfg-java-class: org.opends.server.extensions.PKCS5S2PasswordStorageScheme", 332 "ds-cfg-enabled: true")); 333 334 /** See OPENDJ-1322 and OPENDJ-1067 */ 335 register("2.8.0", 336 rerunJavaPropertiesTool(INFO_UPGRADE_TASK_9206_SUMMARY.get())); 337 338 register("2.8.0", 339 modifyConfigEntry(INFO_UPGRADE_TASK_10214_SUMMARY.get(), 340 "(ds-cfg-java-class=org.opends.server.loggers.debug.TextDebugLogPublisher)", 341 "delete:ds-cfg-java-class", 342 "-", 343 "add:ds-cfg-java-class", 344 "ds-cfg-java-class: org.opends.server.loggers.TextDebugLogPublisher")); 345 346 register("2.8.0", 347 modifyConfigEntry(INFO_UPGRADE_TASK_10232_SUMMARY.get(), 348 "(objectclass=ds-cfg-file-based-debug-log-publisher)", 349 "delete:ds-cfg-default-debug-level")); 350 351 register("2.8.0", 352 modifyConfigEntry(INFO_UPGRADE_TASK_10329_SUMMARY.get(), 353 "&(objectclass=ds-cfg-file-based-error-log-publisher)(cn=File-Based Error Logger)", 354 "delete:ds-cfg-default-severity", 355 "ds-cfg-default-severity: severe-warning", 356 "ds-cfg-default-severity: severe-error", 357 "ds-cfg-default-severity: fatal-error", 358 "-", 359 "add:ds-cfg-default-severity", 360 "ds-cfg-default-severity: error", 361 "ds-cfg-default-severity: warning" 362 )); 363 364 register("2.8.0", 365 modifyConfigEntry(INFO_UPGRADE_TASK_10339_SUMMARY.get(), 366 "&(objectclass=ds-cfg-file-based-error-log-publisher)(cn=Replication Repair Logger)", 367 "delete:ds-cfg-override-severity", 368 "-", 369 "add:ds-cfg-override-severity", 370 "ds-cfg-override-severity: SYNC=INFO,ERROR,WARNING,NOTICE")); 371 372 /** See OPENDJ-1545 */ 373 register("2.8.0", 374 deleteConfigEntry(INFO_UPGRADE_TASK_11237_1_SUMMARY.get(), 375 "dn: cn=Network Groups,cn=config"), 376 deleteConfigEntry(INFO_UPGRADE_TASK_11237_2_SUMMARY.get(), 377 "dn: cn=Workflows,cn=config"), 378 deleteConfigEntry(INFO_UPGRADE_TASK_11237_3_SUMMARY.get(), 379 "dn: cn=Workflow Elements,cn=config")); 380 register("2.8.0", 381 deleteConfigEntry(INFO_UPGRADE_TASK_11239_SUMMARY.get(), 382 "dn: cn=Network Group,cn=Plugins,cn=config")); 383 register("2.8.0", 384 deleteConfigEntry(INFO_UPGRADE_TASK_11339_SUMMARY.get(), 385 "dn: cn=Extensions,cn=config")); 386 387 /** See OPENDJ-1701 */ 388 register("2.8.0", 389 deleteConfigEntry(INFO_UPGRADE_TASK_11476_SUMMARY.get(), 390 "dn: cn=File System,cn=Entry Caches,cn=config")); 391 392 /** See OPENDJ-1869 */ 393 register("2.8.0", 394 modifyConfigEntry(INFO_UPGRADE_TASK_12226_SUMMARY.get(), 395 "(objectclass=ds-cfg-root-config)", 396 "delete: ds-cfg-entry-cache-preload")); 397 398 /** See OPENDJ-2054 */ 399 register("2.8.0", 400 deleteFile(new File(binDirectory, "dsframework")), 401 deleteFile(new File(batDirectory, "dsframework.bat"))); 402 403 /** If the upgraded version is a non OEM one, migrates local-db backends to JE Backend, see OPENDJ-2364 **/ 404 register("3.0.0", 405 conditionalUpgradeTasks( 406 new UpgradeCondition() { 407 @Override 408 public boolean shouldPerformUpgradeTasks(UpgradeContext context) throws ClientException { 409 return !isOEMVersion(); 410 } 411 412 @Override 413 public String toString() { 414 return "!isOEMVersion"; 415 } 416 }, 417 migrateLocalDBBackendsToJEBackends(), 418 modifyConfigEntry(INFO_UPGRADE_TASK_MIGRATE_JE_SUMMARY_2.get(), 419 "(objectClass=ds-cfg-local-db-backend)", 420 "replace: objectClass", 421 "objectClass: top", 422 "objectClass: ds-cfg-backend", 423 "objectClass: ds-cfg-pluggable-backend", 424 "objectClass: ds-cfg-je-backend", 425 "-", 426 "replace: ds-cfg-java-class", 427 "ds-cfg-java-class: org.opends.server.backends.jeb.JEBackend", 428 "-", 429 "delete: ds-cfg-import-thread-count", 430 "-", 431 "delete: ds-cfg-import-queue-size", 432 "-", 433 "delete: ds-cfg-subordinate-indexes-enabled", 434 "-" 435 ), 436 modifyConfigEntry(INFO_UPGRADE_TASK_MIGRATE_JE_SUMMARY_3.get(), 437 "(objectClass=ds-cfg-local-db-index)", 438 "replace: objectClass", 439 "objectClass: top", 440 "objectClass: ds-cfg-backend-index", 441 "-" 442 ), 443 modifyConfigEntry(INFO_UPGRADE_TASK_MIGRATE_JE_SUMMARY_4.get(), 444 "(objectClass=ds-cfg-local-db-vlv-index)", 445 "replace: objectClass", 446 "objectClass: top", 447 "objectClass: ds-cfg-backend-vlv-index", 448 "-", 449 "delete: ds-cfg-max-block-size", 450 "-" 451 ) 452 ) 453 ); 454 455 /** If the upgraded version is OEM, migrates local-db backends to PDB, see OPENDJ-2364 **/ 456 register("3.0.0", 457 conditionalUpgradeTasks( 458 new UpgradeCondition() { 459 @Override 460 public boolean shouldPerformUpgradeTasks(UpgradeContext context) throws ClientException { 461 return isOEMVersion(); 462 } 463 464 @Override 465 public String toString() { 466 return "isOEMVersion"; 467 } 468 }, 469 deleteFile(new File(libDirectory, "je.jar")), 470 requireConfirmation(INFO_UPGRADE_TASK_LOCAL_DB_TO_PDB_1_SUMMARY.get(), NO, 471 renameLocalDBBackendDirectories(), 472 // Convert JE backends to PDB backends. 473 modifyConfigEntry(INFO_UPGRADE_TASK_LOCAL_DB_TO_PDB_2_SUMMARY.get(), 474 "(objectclass=ds-cfg-local-db-backend)", 475 "delete: objectclass", 476 "objectclass: ds-cfg-local-db-backend", 477 "-", 478 "add: objectclass", 479 "objectclass: ds-cfg-pluggable-backend", 480 "objectclass: ds-cfg-pdb-backend", 481 "-", 482 "replace: ds-cfg-java-class", 483 "ds-cfg-java-class: org.opends.server.backends.pdb.PDBBackend", 484 "-", 485 "delete: ds-cfg-preload-time-limit", 486 "-", 487 "delete: ds-cfg-import-thread-count", 488 "-", 489 "delete: ds-cfg-import-queue-size", 490 "-", 491 "delete: ds-cfg-db-txn-write-no-sync", 492 "-", 493 "delete: ds-cfg-db-run-cleaner", 494 "-", 495 "delete: ds-cfg-db-cleaner-min-utilization", 496 "-", 497 "delete: ds-cfg-db-evictor-lru-only", 498 "-", 499 "delete: ds-cfg-db-evictor-core-threads", 500 "-", 501 "delete: ds-cfg-db-evictor-max-threads", 502 "-", 503 "delete: ds-cfg-db-evictor-keep-alive", 504 "-", 505 "delete: ds-cfg-db-evictor-nodes-per-scan", 506 "-", 507 "delete: ds-cfg-db-log-file-max", 508 "-", 509 "delete: ds-cfg-db-log-filecache-size", 510 "-", 511 "delete: ds-cfg-db-logging-file-handler-on", 512 "-", 513 "delete: ds-cfg-db-logging-level", 514 "-", 515 "delete: ds-cfg-db-checkpointer-bytes-interval", 516 "-", 517 "delete: ds-cfg-db-checkpointer-wakeup-interval", 518 "-", 519 "delete: ds-cfg-db-num-lock-tables", 520 "-", 521 "delete: ds-cfg-db-num-cleaner-threads", 522 "-", 523 "delete: ds-cfg-je-property", 524 "-", 525 "delete: ds-cfg-subordinate-indexes-enabled", 526 "-" 527 ), 528 // Convert JE backend indexes to PDB backend indexes. 529 modifyConfigEntry(INFO_UPGRADE_TASK_LOCAL_DB_TO_PDB_3_SUMMARY.get(), 530 "(objectclass=ds-cfg-local-db-index)", 531 "delete: objectclass", 532 "objectclass: ds-cfg-local-db-index", 533 "-", 534 "add: objectclass", 535 "objectclass: ds-cfg-backend-index", 536 "-" 537 ), 538 // Convert JE backend VLV indexes to PDB backend VLV indexes. 539 modifyConfigEntry(INFO_UPGRADE_TASK_LOCAL_DB_TO_PDB_4_SUMMARY.get(), 540 "(objectclass=ds-cfg-local-db-vlv-index)", 541 "delete: objectclass", 542 "objectclass: ds-cfg-local-db-vlv-index", 543 "-", 544 "add: objectclass", 545 "objectclass: ds-cfg-backend-vlv-index", 546 "-", 547 "delete: ds-cfg-max-block-size", 548 "-" 549 ) 550 ) 551 ) 552 ); 553 554 /** Remove dbtest tool (replaced by backendstat in 3.0.0) - see OPENDJ-1791 **/ 555 register("3.0.0", 556 deleteFile(new File(binDirectory, "dbtest")), 557 deleteFile(new File(batDirectory, "dbtest.bat"))); 558 559 /** 560 * Rebuild all indexes when upgrading to 3.0.0. 561 * 562 * 1) matching rules have changed in 2.8.0 and again in 3.0.0- see OPENDJ-1637 563 * 2) JE backend has been migrated to pluggable architecture. 564 */ 565 register("3.0.0", 566 rebuildAllIndexes(INFO_UPGRADE_TASK_11260_SUMMARY.get())); 567 568 /** See OPENDJ-1742 */ 569 register("3.0.0", 570 clearReplicationDbDirectory()); 571 572 /** See OPENDJ-2435 */ 573 register("4.0.0", 574 addConfigEntry(INFO_UPGRADE_TASK_BCRYPT_SCHEME_SUMMARY.get(), 575 "dn: cn=Bcrypt,cn=Password Storage Schemes,cn=config", 576 "changetype: add", 577 "objectClass: top", 578 "objectClass: ds-cfg-password-storage-scheme", 579 "objectClass: ds-cfg-bcrypt-password-storage-scheme", 580 "cn: Bcrypt", 581 "ds-cfg-java-class: org.opends.server.extensions.BcryptPasswordStorageScheme", 582 "ds-cfg-enabled: true")); 583 584 /** See OPENDJ-2683 */ 585 register("4.0.0", 586 deleteConfigEntry(INFO_UPGRADE_TASK_REMOVE_MATCHING_RULES.get(), 587 "cn=Auth Password Exact Equality Matching Rule,cn=Matching Rules,cn=config", 588 "cn=Bit String Equality Matching Rule,cn=Matching Rules,cn=config", 589 "cn=Boolean Equality Matching Rule,cn=Matching Rules,cn=config", 590 "cn=Case Exact Equality Matching Rule,cn=Matching Rules,cn=config", 591 "cn=Case Exact Ordering Matching Rule,cn=Matching Rules,cn=config", 592 "cn=Case Exact Substring Matching Rule,cn=Matching Rules,cn=config", 593 "cn=Case Exact IA5 Equality Matching Rule,cn=Matching Rules,cn=config", 594 "cn=Case Exact IA5 Substring Matching Rule,cn=Matching Rules,cn=config", 595 "cn=Case Ignore Equality Matching Rule,cn=Matching Rules,cn=config", 596 "cn=Case Ignore Ordering Matching Rule,cn=Matching Rules,cn=config", 597 "cn=Case Ignore Substring Matching Rule,cn=Matching Rules,cn=config", 598 "cn=Case Ignore IA5 Equality Matching Rule,cn=Matching Rules,cn=config", 599 "cn=Case Ignore IA5 Substring Matching Rule,cn=Matching Rules,cn=config", 600 "cn=Case Ignore List Equality Matching Rule,cn=Matching Rules,cn=config", 601 "cn=Case Ignore List Substring Matching Rule,cn=Matching Rules,cn=config", 602 "cn=Certificate Exact Matching Rule,cn=Matching Rules,cn=config", 603 "cn=Directory String First Component Equality Matching Rule,cn=Matching Rules,cn=config", 604 "cn=Distinguished Name Equality Matching Rule,cn=Matching Rules,cn=config", 605 "cn=Double Metaphone Approximate Matching Rule,cn=Matching Rules,cn=config", 606 "cn=Generalized Time Equality Matching Rule,cn=Matching Rules,cn=config", 607 "cn=Generalized Time Ordering Matching Rule,cn=Matching Rules,cn=config", 608 "cn=Integer Equality Matching Rule,cn=Matching Rules,cn=config", 609 "cn=Integer Ordering Matching Rule,cn=Matching Rules,cn=config", 610 "cn=Integer First Component Equality Matching Rule,cn=Matching Rules,cn=config", 611 "cn=Keyword Equality Matching Rule,cn=Matching Rules,cn=config", 612 "cn=Numeric String Equality Matching Rule,cn=Matching Rules,cn=config", 613 "cn=Numeric String Ordering Matching Rule,cn=Matching Rules,cn=config", 614 "cn=Numeric String Substring Matching Rule,cn=Matching Rules,cn=config", 615 "cn=Object Identifier Equality Matching Rule,cn=Matching Rules,cn=config", 616 "cn=Object Identifier First Component Equality Matching Rule,cn=Matching Rules,cn=config", 617 "cn=Octet String Equality Matching Rule,cn=Matching Rules,cn=config", 618 "cn=Octet String Ordering Matching Rule,cn=Matching Rules,cn=config", 619 "cn=Octet String Substring Matching Rule,cn=Matching Rules,cn=config", 620 "cn=Presentation Address Equality Matching Rule,cn=Matching Rules,cn=config", 621 "cn=Protocol Information Equality Matching Rule,cn=Matching Rules,cn=config", 622 "cn=Telephone Number Equality Matching Rule,cn=Matching Rules,cn=config", 623 "cn=Telephone Number Substring Matching Rule,cn=Matching Rules,cn=config", 624 "cn=Time Based Matching Rule,cn=Matching Rules,cn=config", 625 "cn=Unique Member Equality Matching Rule,cn=Matching Rules,cn=config", 626 "cn=User Password Exact Equality Matching Rule,cn=Matching Rules,cn=config", 627 "cn=UUID Equality Matching Rule,cn=Matching Rules,cn=config", 628 "cn=UUID Ordering Matching Rule,cn=Matching Rules,cn=config", 629 "cn=Word Equality Matching Rule,cn=Matching Rules,cn=config")); 630 631 /** see OPENDJ-2730 */ 632 register("4.0.0", removeOldJarFiles()); 633 634 register("4.0.0", 635 rebuildIndexesNamed(INFO_UPGRADE_REBUILD_INDEXES_DISTINGUISHED_NAME.get(), 636 "distinguishedName", "member", "owner", "roleOccupant", "seeAlso")); 637 638 /** 639 * All upgrades will refresh the server configuration schema and generate a new upgrade folder. 640 */ 641 registerLast( 642 copySchemaFile("02-config.ldif"), 643 updateConfigUpgradeFolder(), 644 postUpgradeRebuildIndexes()); 645 646 // @formatter:on 647 } 648 649 /** 650 * Returns a list containing all the tasks which are required in order to upgrade 651 * from {@code fromVersion} to {@code toVersion}. 652 * 653 * @param fromVersion 654 * The old version. 655 * @param toVersion 656 * The new version. 657 * @return A list containing all the tasks which are required in order to upgrade 658 * from {@code fromVersion} to {@code toVersion}. 659 */ 660 private static List<UpgradeTask> getUpgradeTasks(final BuildVersion fromVersion, final BuildVersion toVersion) 661 { 662 final List<UpgradeTask> tasks = new LinkedList<>(); 663 for (final List<UpgradeTask> subList : TASKS.subMap(fromVersion, false, 664 toVersion, true).values()) 665 { 666 tasks.addAll(subList); 667 } 668 tasks.addAll(MANDATORY_TASKS); 669 return tasks; 670 } 671 672 /** 673 * Upgrades the server from {@code fromVersion} to {@code toVersion} located in the upgrade context. 674 * 675 * @param context 676 * The context of the upgrade. 677 * @throws ClientException 678 * If an error occurred while performing the upgrade. 679 */ 680 public static void upgrade(final UpgradeContext context) 681 throws ClientException 682 { 683 // Checks and validates the version number. 684 isVersionCanBeUpdated(context); 685 686 // Server must be offline. 687 checkIfServerIsRunning(context); 688 689 context.notify(INFO_UPGRADE_TITLE.get(), TITLE_CALLBACK); 690 context.notify(INFO_UPGRADE_SUMMARY.get(context.getFromVersion(), context.getToVersion()), NOTICE_CALLBACK); 691 context.notify(INFO_UPGRADE_GENERAL_SEE_FOR_DETAILS.get(UpgradeLog.getLogFilePath()), NOTICE_CALLBACK); 692 693 // Checks License. 694 checkLicence(context); 695 696 logWarnAboutPatchesFolder(); 697 698 // Get the list of required upgrade tasks. 699 final List<UpgradeTask> tasks = 700 getUpgradeTasks(context.getFromVersion(), context.getToVersion()); 701 if (tasks.isEmpty()) 702 { 703 changeBuildInfoVersion(context); 704 return; 705 } 706 707 try 708 { 709 // Let tasks interact with the user in order to obtain user's selection. 710 context.notify(INFO_UPGRADE_REQUIREMENTS.get(), TITLE_CALLBACK); 711 for (final UpgradeTask task : tasks) 712 { 713 task.prepare(context); 714 } 715 716 // Starts upgrade 717 final int userResponse = context.confirmYN(INFO_UPGRADE_DISPLAY_CONFIRM_START.get(), YES); 718 if (userResponse == NO) 719 { 720 final LocalizableMessage message = INFO_UPGRADE_ABORTED_BY_USER.get(); 721 context.notify(message, WARNING); 722 throw new ClientException(ReturnCode.ERROR_UNEXPECTED, message); 723 } 724 725 // Perform the upgrade tasks. 726 context.notify(INFO_UPGRADE_PERFORMING_TASKS.get(), TITLE_CALLBACK); 727 for (final UpgradeTask task : tasks) 728 { 729 task.perform(context); 730 } 731 732 if (UpgradeTasks.countErrors == 0) 733 { 734 /* 735 * The end of a successful upgrade is marked up with the build info file update and the license, 736 * if present, requires the creation of an approval file. 737 */ 738 changeBuildInfoVersion(context); 739 740 createFileLicenseApproved(); 741 } 742 else 743 { 744 context.notify(ERR_UPGRADE_FAILS.get(UpgradeTasks.countErrors), TITLE_CALLBACK); 745 } 746 747 // Performs the post upgrade tasks. 748 if (hasPostUpgradeTask && UpgradeTasks.countErrors == 0) 749 { 750 context.notify(INFO_UPGRADE_PERFORMING_POST_TASKS.get(), TITLE_CALLBACK); 751 performPostUpgradeTasks(context, tasks); 752 context.notify(INFO_UPGRADE_POST_TASKS_COMPLETE.get(), TITLE_CALLBACK); 753 } 754 } 755 catch (final ClientException e) 756 { 757 context.notify(e.getMessageObject(), ERROR_CALLBACK); 758 throw e; 759 } 760 catch (final Exception e) 761 { 762 final LocalizableMessage message = ERR_UPGRADE_TASKS_FAIL.get(stackTraceToSingleLineString(e)); 763 context.notify(message, ERROR_CALLBACK); 764 throw new ClientException(ReturnCode.ERROR_UNEXPECTED, message, e); 765 } 766 finally 767 { 768 context.notify(INFO_UPGRADE_GENERAL_SEE_FOR_DETAILS.get(UpgradeLog.getLogFilePath()), NOTICE_CALLBACK); 769 logger.info(INFO_UPGRADE_PROCESS_END); 770 } 771 } 772 773 private static void performPostUpgradeTasks(final UpgradeContext context, final List<UpgradeTask> tasks) 774 throws ClientException 775 { 776 boolean isOk = true; 777 for (final UpgradeTask task : tasks) 778 { 779 if (isOk) 780 { 781 try 782 { 783 task.postUpgrade(context); 784 } 785 catch (ClientException e) 786 { 787 context.notify(e.getMessageObject(), WARNING); 788 needToExitWithErrorCode(); 789 isOk = false; 790 } 791 } 792 else 793 { 794 task.postponePostUpgrade(context); 795 } 796 } 797 } 798 799 private static void register(final String versionString, 800 final UpgradeTask... tasks) 801 { 802 final BuildVersion version = BuildVersion.valueOf(versionString); 803 List<UpgradeTask> taskList = TASKS.get(version); 804 if (taskList == null) 805 { 806 taskList = new LinkedList<>(); 807 TASKS.put(version, taskList); 808 } 809 taskList.addAll(Arrays.asList(tasks)); 810 } 811 812 private static void registerLast(final UpgradeTask... tasks) 813 { 814 MANDATORY_TASKS.addAll(Arrays.asList(tasks)); 815 } 816 817 /** 818 * The server must be offline during the upgrade. 819 * 820 * @throws ClientException 821 * An exception is thrown if the server is currently running. 822 */ 823 private static void checkIfServerIsRunning(final UpgradeContext context) throws ClientException 824 { 825 final String lockFile = LockFileManager.getServerLockFileName(); 826 827 final StringBuilder failureReason = new StringBuilder(); 828 try 829 { 830 // Assume that if we cannot acquire the lock file the server is running. 831 if (!LockFileManager.acquireExclusiveLock(lockFile, failureReason)) 832 { 833 final LocalizableMessage message = ERR_UPGRADE_REQUIRES_SERVER_OFFLINE.get(); 834 context.notify(message, NOTICE_CALLBACK); 835 throw new ClientException(ReturnCode.ERROR_UNEXPECTED, message); 836 } 837 } 838 finally 839 { 840 LockFileManager.releaseLock(lockFile, failureReason); 841 } 842 } 843 844 /** 845 * Checks if the version can be updated. 846 * 847 * @param context 848 * The current context which running the upgrade. 849 * @throws ClientException 850 * If an exception occurs - stops the process. 851 */ 852 private static void isVersionCanBeUpdated(final UpgradeContext context) 853 throws ClientException 854 { 855 if (context.getFromVersion().equals(context.getToVersion())) 856 { 857 // If the server is already up to date then treat it as a successful upgrade so that upgrade is idempotent. 858 final LocalizableMessage message = ERR_UPGRADE_VERSION_UP_TO_DATE.get(context.getToVersion()); 859 context.notify(message, NOTICE_CALLBACK); 860 throw new ClientException(ReturnCode.SUCCESS, message); 861 } 862 863 // The upgrade only supports version >= 2.4.5. 864 if (context.getFromVersion().compareTo(UPGRADE_SUPPORTS_VERSION_FROM) < 0) 865 { 866 final LocalizableMessage message = 867 INFO_UPGRADE_VERSION_IS_NOT_SUPPORTED.get(UPGRADE_SUPPORTS_VERSION_FROM, UPGRADE_SUPPORTS_VERSION_FROM); 868 context.notify(message, NOTICE_CALLBACK); 869 throw new ClientException(ReturnCode.ERROR_UNEXPECTED, message); 870 } 871 } 872 873 /** 874 * Writes the up to date's version number within the build info file. 875 * 876 * @param context 877 * The current context which running the upgrade. 878 * @throws ClientException 879 * If an exception occurs when displaying the message. 880 */ 881 private static void changeBuildInfoVersion(final UpgradeContext context) 882 throws ClientException 883 { 884 File buildInfoFile = new File(UpgradeUtils.configDirectory, Installation.BUILDINFO_RELATIVE_PATH); 885 try (FileWriter buildInfo = new FileWriter(buildInfoFile, false)) 886 { 887 888 // Write the new version 889 buildInfo.write(context.getToVersion().toString()); 890 891 context.notify(INFO_UPGRADE_SUCCESSFUL.get(context.getFromVersion(), context.getToVersion()), TITLE_CALLBACK); 892 } 893 catch (IOException e) 894 { 895 final LocalizableMessage message = LocalizableMessage.raw(e.getMessage()); 896 context.notify(message, ERROR_CALLBACK); 897 throw new ClientException(ReturnCode.ERROR_UNEXPECTED, message); 898 } 899 } 900 901 private static void checkLicence(final UpgradeContext context) 902 throws ClientException 903 { 904 // Check license 905 if (LicenseFile.exists() && !LicenseFile.isAlreadyApproved()) 906 { 907 context.notify(LocalizableMessage.raw(LINE_SEPARATOR + LicenseFile.getText())); 908 context.notify(INFO_LICENSE_DETAILS_CLI_LABEL.get()); 909 if (!context.isAcceptLicenseMode()) 910 { 911 final int answer; 912 913 // The force cannot answer yes to the license's question, which is not a task even if it requires a user 914 // interaction OR -an accept license mode to continue the process. 915 if (context.isForceUpgradeMode()) 916 { 917 answer = NO; 918 context.notify( 919 LocalizableMessage.raw(INFO_LICENSE_ACCEPT.get() + " " + INFO_PROMPT_NO_COMPLETE_ANSWER.get())); 920 } 921 else 922 { 923 answer = context.confirmYN(INFO_LICENSE_ACCEPT.get(), NO); 924 } 925 926 if (answer == NO) 927 { 928 System.exit(EXIT_CODE_SUCCESS); 929 } 930 else if (answer == YES) 931 { 932 LicenseFile.setApproval(true); 933 } 934 } 935 else 936 { 937 // We automatically accept the license with this option. 938 context.notify( 939 LocalizableMessage.raw(INFO_LICENSE_ACCEPT.get() + " " + INFO_PROMPT_YES_COMPLETE_ANSWER.get())); 940 LicenseFile.setApproval(true); 941 } 942 } 943 } 944 945 /** 946 * The classes folder is renamed by the script launcher to avoid 947 * incompatibility between patches and upgrade process. If a folder 948 * "classes.disabled" is found, this function just displays a warning in the 949 * log file, meaning the "classes" folder has been renamed. See upgrade.sh / 950 * upgrade.bat scripts which hold the renaming process. (OPENDJ-1098) 951 */ 952 private static void logWarnAboutPatchesFolder() 953 { 954 try 955 { 956 final File backup = new File(UpgradeUtils.getInstancePath(), "classes.disabled"); 957 if (backup.exists()) { 958 final File[] files = backup.listFiles(); 959 if (files != null && files.length > 0) 960 { 961 logger.warn(INFO_UPGRADE_CLASSES_FOLDER_RENAMED, backup.getAbsoluteFile()); 962 } 963 } 964 } 965 catch (SecurityException e) 966 { 967 logger.debug(LocalizableMessage.raw(e.getMessage()), e); 968 } 969 } 970 971 static void needToRunPostUpgradePhase() 972 { 973 Upgrade.hasPostUpgradeTask = true; 974 } 975 976 /** This method should be used when the upgrade tool has issued a warning. */ 977 static void needToExitWithErrorCode() 978 { 979 Upgrade.exitWithErrorCode = true; 980 } 981 982 /** 983 * {@code true} if the upgrade succeeded. 984 * 985 * @return {@code true} if the upgrade succeeded. 986 */ 987 static boolean isSuccess() 988 { 989 return !exitWithErrorCode; 990 } 991 992 /** Prevent instantiation. */ 993 private Upgrade() 994 { 995 // Nothing to do. 996 } 997}