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}