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