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