001/* 002 * Copyright 2008-2019 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2015-2019 Ping Identity Corporation 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU General Public License (GPLv2 only) 010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 011 * as published by the Free Software Foundation. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Public License for more details. 017 * 018 * You should have received a copy of the GNU General Public License 019 * along with this program; if not, see <http://www.gnu.org/licenses>. 020 */ 021package com.unboundid.ldap.sdk.unboundidds.tasks; 022 023 024 025import java.util.ArrayList; 026import java.util.Arrays; 027import java.util.Collections; 028import java.util.Date; 029import java.util.LinkedHashMap; 030import java.util.List; 031import java.util.Map; 032 033import com.unboundid.ldap.sdk.Attribute; 034import com.unboundid.ldap.sdk.Entry; 035import com.unboundid.util.NotMutable; 036import com.unboundid.util.StaticUtils; 037import com.unboundid.util.ThreadSafety; 038import com.unboundid.util.ThreadSafetyLevel; 039import com.unboundid.util.Validator; 040 041import static com.unboundid.ldap.sdk.unboundidds.tasks.TaskMessages.*; 042 043 044 045/** 046 * This class defines a Directory Server task that can be used to restore a 047 * backup. 048 * <BR> 049 * <BLOCKQUOTE> 050 * <B>NOTE:</B> This class, and other classes within the 051 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 052 * supported for use against Ping Identity, UnboundID, and 053 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 054 * for proprietary functionality or for external specifications that are not 055 * considered stable or mature enough to be guaranteed to work in an 056 * interoperable way with other types of LDAP servers. 057 * </BLOCKQUOTE> 058 * <BR> 059 * The properties that are available for use with this type of task include: 060 * <UL> 061 * <LI>The path to the backup directory in which the backup resides. This 062 * must be provided when scheduling a new task of this type.</LI> 063 * <LI>The backup ID of the backup to be restored. If this is not provided 064 * when scheduling an instance of this task, then the most recent backup 065 * in the backup directory will be selected.</LI> 066 * <LI>A flag that indicates whether to attempt to restore the backup or 067 * only to verify it to determine whether it appears to be valid (e.g., 068 * validate the digest and/or signature, make sure that the backend 069 * considers it valid, etc.).</LI> 070 * <LI>The path to a file containing a passphrase to use to generate the 071 * encryption key.</LI> 072 * </UL> 073 074 */ 075@NotMutable() 076@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 077public final class RestoreTask 078 extends Task 079{ 080 /** 081 * The fully-qualified name of the Java class that is used for the restore 082 * task. 083 */ 084 static final String RESTORE_TASK_CLASS = 085 "com.unboundid.directory.server.tasks.RestoreTask"; 086 087 088 089 /** 090 * The name of the attribute used to specify the path to the backup directory 091 * containing the backup to restore. 092 */ 093 private static final String ATTR_BACKUP_DIRECTORY = 094 "ds-backup-directory-path"; 095 096 097 098 /** 099 * The name of the attribute used to specify the backup ID of the backup to 100 * restore. 101 */ 102 private static final String ATTR_BACKUP_ID = "ds-backup-id"; 103 104 105 106 /** 107 * The name of the attribute used to specify the path to a file that contains 108 * the passphrase to use to generate the encryption key. 109 */ 110 private static final String ATTR_ENCRYPTION_PASSPHRASE_FILE = 111 "ds-task-restore-encryption-passphrase-file"; 112 113 114 115 /** 116 * The name of the attribute used to indicate whether to only verify the 117 * backup but not actually restore it. 118 */ 119 private static final String ATTR_VERIFY_ONLY = 120 "ds-task-restore-verify-only"; 121 122 123 124 /** 125 * The name of the object class used in restore task entries. 126 */ 127 private static final String OC_RESTORE_TASK = "ds-task-restore"; 128 129 130 131 /** 132 * The task property for the backup directory. 133 */ 134 private static final TaskProperty PROPERTY_BACKUP_DIRECTORY = 135 new TaskProperty(ATTR_BACKUP_DIRECTORY, 136 INFO_DISPLAY_NAME_BACKUP_DIRECTORY.get(), 137 INFO_DESCRIPTION_BACKUP_DIRECTORY_RESTORE.get(), 138 String.class, true, false, false); 139 140 141 142 /** 143 * The task property for the backup ID. 144 */ 145 private static final TaskProperty PROPERTY_BACKUP_ID = 146 new TaskProperty(ATTR_BACKUP_ID, INFO_DISPLAY_NAME_BACKUP_ID.get(), 147 INFO_DESCRIPTION_BACKUP_ID_RESTORE.get(), String.class, 148 false, false, true); 149 150 151 152 /** 153 * The task property that will be used for the encryption passphrase file. 154 */ 155 private static final TaskProperty PROPERTY_ENCRYPTION_PASSPHRASE_FILE = 156 new TaskProperty(ATTR_ENCRYPTION_PASSPHRASE_FILE, 157 INFO_DISPLAY_NAME_ENCRYPTION_PASSPHRASE_FILE.get(), 158 INFO_DESCRIPTION_ENCRYPTION_PASSPHRASE_FILE.get(), 159 String.class, false, false, true); 160 161 162 163 /** 164 * The task property for the verify only flag. 165 */ 166 private static final TaskProperty PROPERTY_VERIFY_ONLY = 167 new TaskProperty(ATTR_VERIFY_ONLY, INFO_DISPLAY_NAME_VERIFY_ONLY.get(), 168 INFO_DESCRIPTION_VERIFY_ONLY.get(), Boolean.class, 169 false, false, false); 170 171 172 173 /** 174 * The serial version UID for this serializable class. 175 */ 176 private static final long serialVersionUID = -8441221098187125379L; 177 178 179 180 // Indicates whether to only verify the backup without restoring it. 181 private final boolean verifyOnly; 182 183 // The path to the backup directory containing the backup to restore. 184 private final String backupDirectory; 185 186 // The path to a file containing the passphrase to use to generate the 187 // encryption key. 188 private final String encryptionPassphraseFile; 189 190 // The backup ID of the backup to restore. 191 private final String backupID; 192 193 194 195 /** 196 * Creates a new uninitialized restore task instance which should only be used 197 * for obtaining general information about this task, including the task name, 198 * description, and supported properties. Attempts to use a task created with 199 * this constructor for any other reason will likely fail. 200 */ 201 public RestoreTask() 202 { 203 verifyOnly = false; 204 backupDirectory = null; 205 backupID = null; 206 encryptionPassphraseFile = null; 207 } 208 209 210 211 /** 212 * Creates a new restore task with the provided information. 213 * 214 * @param taskID The task ID to use for this task. If it is 215 * {@code null} then a UUID will be generated for use 216 * as the task ID. 217 * @param backupDirectory The path to the directory on the server containing 218 * the backup to restore. It may be an absolute path 219 * or relative to the server root directory. It must 220 * not be {@code null}. 221 * @param backupID The backup ID of the backup to restore. If this 222 * is {@code null} then the most recent backup in the 223 * specified backup directory will be restored. 224 * @param verifyOnly Indicates whether to only verify the backup 225 * without restoring it. 226 */ 227 public RestoreTask(final String taskID, final String backupDirectory, 228 final String backupID, final boolean verifyOnly) 229 { 230 this(taskID, backupDirectory, backupID, verifyOnly, null, null, null, null, 231 null); 232 } 233 234 235 236 /** 237 * Creates a new restore task with the provided information. 238 * 239 * @param taskID The task ID to use for this task. If it is 240 * {@code null} then a UUID will be generated 241 * for use as the task ID. 242 * @param backupDirectory The path to the directory on the server 243 * containing the backup to restore. It may 244 * be an absolute path or relative to the 245 * server root directory. It must not be 246 * {@code null}. 247 * @param backupID The backup ID of the backup to restore. If 248 * this is {@code null} then the most recent 249 * backup in the specified backup directory 250 * will be restored. 251 * @param verifyOnly Indicates whether to only verify the backup 252 * without restoring it. 253 * @param scheduledStartTime The time that this task should start 254 * running. 255 * @param dependencyIDs The list of task IDs that will be required 256 * to complete before this task will be 257 * eligible to start. 258 * @param failedDependencyAction Indicates what action should be taken if 259 * any of the dependencies for this task do 260 * not complete successfully. 261 * @param notifyOnCompletion The list of e-mail addresses of individuals 262 * that should be notified when this task 263 * completes. 264 * @param notifyOnError The list of e-mail addresses of individuals 265 * that should be notified if this task does 266 * not complete successfully. 267 */ 268 public RestoreTask(final String taskID, final String backupDirectory, 269 final String backupID, final boolean verifyOnly, 270 final Date scheduledStartTime, 271 final List<String> dependencyIDs, 272 final FailedDependencyAction failedDependencyAction, 273 final List<String> notifyOnCompletion, 274 final List<String> notifyOnError) 275 { 276 this(taskID, backupDirectory, backupID, verifyOnly, null, 277 scheduledStartTime, dependencyIDs, failedDependencyAction, 278 notifyOnCompletion, notifyOnError); 279 } 280 281 282 283 /** 284 * Creates a new restore task with the provided information. 285 * 286 * @param taskID The task ID to use for this task. If it 287 * is {@code null} then a UUID will be 288 * generated for use as the task ID. 289 * @param backupDirectory The path to the directory on the server 290 * containing the backup to restore. It may 291 * be an absolute path or relative to the 292 * server root directory. It must not be 293 * {@code null}. 294 * @param backupID The backup ID of the backup to restore. 295 * If this is {@code null} then the most 296 * recent backup in the specified backup 297 * directory will be restored. 298 * @param verifyOnly Indicates whether to only verify the 299 * backup without restoring it. 300 * @param encryptionPassphraseFile The path to a file containing the 301 * passphrase to use to generate the 302 * encryption key. It amy be {@code null} 303 * if the backup is not to be encrypted, or 304 * if the key should be obtained in some 305 * other way. 306 * @param scheduledStartTime The time that this task should start 307 * running. 308 * @param dependencyIDs The list of task IDs that will be 309 * required to complete before this task 310 * will be eligible to start. 311 * @param failedDependencyAction Indicates what action should be taken if 312 * any of the dependencies for this task do 313 * not complete successfully. 314 * @param notifyOnCompletion The list of e-mail addresses of 315 * individuals that should be notified when 316 * this task completes. 317 * @param notifyOnError The list of e-mail addresses of 318 * individuals that should be notified if 319 * this task does not complete successfully. 320 */ 321 public RestoreTask(final String taskID, final String backupDirectory, 322 final String backupID, final boolean verifyOnly, 323 final String encryptionPassphraseFile, 324 final Date scheduledStartTime, 325 final List<String> dependencyIDs, 326 final FailedDependencyAction failedDependencyAction, 327 final List<String> notifyOnCompletion, 328 final List<String> notifyOnError) 329 { 330 this(taskID, backupDirectory, backupID, verifyOnly, 331 encryptionPassphraseFile, scheduledStartTime, dependencyIDs, 332 failedDependencyAction, null, notifyOnCompletion, null, 333 notifyOnError, null, null, null); 334 } 335 336 337 338 /** 339 * Creates a new restore task with the provided information. 340 * 341 * @param taskID The task ID to use for this task. If it 342 * is {@code null} then a UUID will be 343 * generated for use as the task ID. 344 * @param backupDirectory The path to the directory on the server 345 * containing the backup to restore. It may 346 * be an absolute path or relative to the 347 * server root directory. It must not be 348 * {@code null}. 349 * @param backupID The backup ID of the backup to restore. 350 * If this is {@code null} then the most 351 * recent backup in the specified backup 352 * directory will be restored. 353 * @param verifyOnly Indicates whether to only verify the 354 * backup without restoring it. 355 * @param encryptionPassphraseFile The path to a file containing the 356 * passphrase to use to generate the 357 * encryption key. It amy be {@code null} 358 * if the backup is not to be encrypted, or 359 * if the key should be obtained in some 360 * other way. 361 * @param scheduledStartTime The time that this task should start 362 * running. 363 * @param dependencyIDs The list of task IDs that will be 364 * required to complete before this task 365 * will be eligible to start. 366 * @param failedDependencyAction Indicates what action should be taken if 367 * any of the dependencies for this task do 368 * not complete successfully. 369 * @param notifyOnStart The list of e-mail addresses of individuals 370 * that should be notified when this task 371 * starts running. 372 * @param notifyOnCompletion The list of e-mail addresses of individuals 373 * that should be notified when this task 374 * completes. 375 * @param notifyOnSuccess The list of e-mail addresses of individuals 376 * that should be notified if this task 377 * completes successfully. 378 * @param notifyOnError The list of e-mail addresses of individuals 379 * that should be notified if this task does 380 * not complete successfully. 381 * @param alertOnStart Indicates whether the server should send an 382 * alert notification when this task starts. 383 * @param alertOnSuccess Indicates whether the server should send an 384 * alert notification if this task completes 385 * successfully. 386 * @param alertOnError Indicates whether the server should send an 387 * alert notification if this task fails to 388 * complete successfully. 389 */ 390 public RestoreTask(final String taskID, final String backupDirectory, 391 final String backupID, final boolean verifyOnly, 392 final String encryptionPassphraseFile, 393 final Date scheduledStartTime, 394 final List<String> dependencyIDs, 395 final FailedDependencyAction failedDependencyAction, 396 final List<String> notifyOnStart, 397 final List<String> notifyOnCompletion, 398 final List<String> notifyOnSuccess, 399 final List<String> notifyOnError, 400 final Boolean alertOnStart, final Boolean alertOnSuccess, 401 final Boolean alertOnError) 402 { 403 super(taskID, RESTORE_TASK_CLASS, scheduledStartTime, 404 dependencyIDs, failedDependencyAction, notifyOnStart, 405 notifyOnCompletion, notifyOnSuccess, notifyOnError, alertOnStart, 406 alertOnSuccess, alertOnError); 407 408 Validator.ensureNotNull(backupDirectory); 409 410 this.backupDirectory = backupDirectory; 411 this.backupID = backupID; 412 this.verifyOnly = verifyOnly; 413 this.encryptionPassphraseFile = encryptionPassphraseFile; 414 } 415 416 417 418 /** 419 * Creates a new restore task from the provided entry. 420 * 421 * @param entry The entry to use to create this restore task. 422 * 423 * @throws TaskException If the provided entry cannot be parsed as a restore 424 * task entry. 425 */ 426 public RestoreTask(final Entry entry) 427 throws TaskException 428 { 429 super(entry); 430 431 432 // Get the backup directory. It must be present. 433 backupDirectory = entry.getAttributeValue(ATTR_BACKUP_DIRECTORY); 434 if (backupDirectory == null) 435 { 436 throw new TaskException(ERR_RESTORE_NO_BACKUP_DIRECTORY.get( 437 getTaskEntryDN())); 438 } 439 440 441 // Get the backup ID. It may be absent. 442 backupID = entry.getAttributeValue(ATTR_BACKUP_ID); 443 444 445 // Get the verifyOnly flag. It may be absent. 446 verifyOnly = parseBooleanValue(entry, ATTR_VERIFY_ONLY, false); 447 448 449 // Get the path to the encryption passphrase file. It may be absent. 450 encryptionPassphraseFile = 451 entry.getAttributeValue(ATTR_ENCRYPTION_PASSPHRASE_FILE); 452 } 453 454 455 456 /** 457 * Creates a new restore task from the provided set of task properties. 458 * 459 * @param properties The set of task properties and their corresponding 460 * values to use for the task. It must not be 461 * {@code null}. 462 * 463 * @throws TaskException If the provided set of properties cannot be used to 464 * create a valid restore task. 465 */ 466 public RestoreTask(final Map<TaskProperty,List<Object>> properties) 467 throws TaskException 468 { 469 super(RESTORE_TASK_CLASS, properties); 470 471 boolean v = false; 472 String b = null; 473 String f = null; 474 String i = null; 475 476 for (final Map.Entry<TaskProperty,List<Object>> entry : 477 properties.entrySet()) 478 { 479 final TaskProperty p = entry.getKey(); 480 final String attrName = p.getAttributeName(); 481 final List<Object> values = entry.getValue(); 482 483 if (attrName.equalsIgnoreCase(ATTR_BACKUP_DIRECTORY)) 484 { 485 b = parseString(p, values, b); 486 } 487 else if (attrName.equalsIgnoreCase(ATTR_BACKUP_ID)) 488 { 489 i = parseString(p, values, i); 490 } 491 else if (attrName.equalsIgnoreCase(ATTR_VERIFY_ONLY)) 492 { 493 v = parseBoolean(p, values, v); 494 } 495 else if (attrName.equalsIgnoreCase(ATTR_ENCRYPTION_PASSPHRASE_FILE)) 496 { 497 f = parseString(p, values, f); 498 } 499 } 500 501 if (b == null) 502 { 503 throw new TaskException(ERR_RESTORE_NO_BACKUP_DIRECTORY.get( 504 getTaskEntryDN())); 505 } 506 507 backupDirectory = b; 508 backupID = i; 509 verifyOnly = v; 510 encryptionPassphraseFile = f; 511 } 512 513 514 515 /** 516 * {@inheritDoc} 517 */ 518 @Override() 519 public String getTaskName() 520 { 521 return INFO_TASK_NAME_RESTORE.get(); 522 } 523 524 525 526 /** 527 * {@inheritDoc} 528 */ 529 @Override() 530 public String getTaskDescription() 531 { 532 return INFO_TASK_DESCRIPTION_RESTORE.get(); 533 } 534 535 536 537 /** 538 * Retrieves the path to the backup directory which contains the backup to 539 * restore. It may be either an absolute path or one that is relative to the 540 * server root. 541 * 542 * @return The path to the backup directory which contains the backup to 543 * restore. 544 */ 545 public String getBackupDirectory() 546 { 547 return backupDirectory; 548 } 549 550 551 552 /** 553 * Retrieves the backup ID of the backup to restore. 554 * 555 * @return The backup ID of the backup to restore, or {@code null} if the 556 * most recent backup in the backup directory should be restored. 557 */ 558 public String getBackupID() 559 { 560 return backupID; 561 } 562 563 564 565 /** 566 * Indicates whether the backup should only be verified without actually being 567 * restored. 568 * 569 * @return {@code true} if the backup should be verified but not restored, or 570 * {@code false} if it should be restored. 571 */ 572 public boolean verifyOnly() 573 { 574 return verifyOnly; 575 } 576 577 578 579 /** 580 * Retrieves the path to a file that contains the passphrase to use to 581 * generate the encryption key. 582 * 583 * @return The path to a file that contains the passphrase to use to 584 * generate the encryption key, or {@code null} if the backup is 585 * not encrypted or if the encryption key should be obtained through 586 * some other means. 587 */ 588 public String getEncryptionPassphraseFile() 589 { 590 return encryptionPassphraseFile; 591 } 592 593 594 595 /** 596 * {@inheritDoc} 597 */ 598 @Override() 599 protected List<String> getAdditionalObjectClasses() 600 { 601 return Collections.singletonList(OC_RESTORE_TASK); 602 } 603 604 605 606 /** 607 * {@inheritDoc} 608 */ 609 @Override() 610 protected List<Attribute> getAdditionalAttributes() 611 { 612 final ArrayList<Attribute> attrs = new ArrayList<>(10); 613 614 attrs.add(new Attribute(ATTR_BACKUP_DIRECTORY, backupDirectory)); 615 attrs.add(new Attribute(ATTR_VERIFY_ONLY, String.valueOf(verifyOnly))); 616 617 if (backupID != null) 618 { 619 attrs.add(new Attribute(ATTR_BACKUP_ID, backupID)); 620 } 621 622 if (encryptionPassphraseFile != null) 623 { 624 attrs.add(new Attribute(ATTR_ENCRYPTION_PASSPHRASE_FILE, 625 encryptionPassphraseFile)); 626 } 627 628 return attrs; 629 } 630 631 632 633 /** 634 * {@inheritDoc} 635 */ 636 @Override() 637 public List<TaskProperty> getTaskSpecificProperties() 638 { 639 final List<TaskProperty> propList = Arrays.asList( 640 PROPERTY_BACKUP_DIRECTORY, 641 PROPERTY_BACKUP_ID, 642 PROPERTY_VERIFY_ONLY, 643 PROPERTY_ENCRYPTION_PASSPHRASE_FILE); 644 645 return Collections.unmodifiableList(propList); 646 } 647 648 649 650 /** 651 * {@inheritDoc} 652 */ 653 @Override() 654 public Map<TaskProperty,List<Object>> getTaskPropertyValues() 655 { 656 final LinkedHashMap<TaskProperty,List<Object>> props = 657 new LinkedHashMap<>(StaticUtils.computeMapCapacity(10)); 658 659 props.put(PROPERTY_BACKUP_DIRECTORY, 660 Collections.<Object>singletonList(backupDirectory)); 661 662 if (backupID == null) 663 { 664 props.put(PROPERTY_BACKUP_ID, Collections.emptyList()); 665 } 666 else 667 { 668 props.put(PROPERTY_BACKUP_ID, 669 Collections.<Object>singletonList(backupID)); 670 } 671 672 props.put(PROPERTY_VERIFY_ONLY, 673 Collections.<Object>singletonList(verifyOnly)); 674 675 if (encryptionPassphraseFile == null) 676 { 677 props.put(PROPERTY_ENCRYPTION_PASSPHRASE_FILE, Collections.emptyList()); 678 } 679 else 680 { 681 props.put(PROPERTY_ENCRYPTION_PASSPHRASE_FILE, 682 Collections.<Object>singletonList(encryptionPassphraseFile)); 683 } 684 685 props.putAll(super.getTaskPropertyValues()); 686 return Collections.unmodifiableMap(props); 687 } 688}