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