Skip to content

Commit

Permalink
[PLAT-16332] Implement continuous backup and restore for NFS storage
Browse files Browse the repository at this point in the history
Summary: Adds support for backup and restore operations needed to use continuous backup features with NFS backup storage config. Moves default methods up to StorageUtil level which is parent class for both NFSUtil and CloudUtils. Also updates release version parsing to actually match on digits to handle both cloud cases where full path to release is parsed and NFS where only version directory path is parsed.

Test Plan: Set up nfs server on different VM, mount /mnt/nfs to the NFS server. Schedule continuous backups and ensure backups appear on NFS server. Perform restore and ensure restore is successful.

Reviewers: dshubin, vkumar

Reviewed By: vkumar

Subscribers: yugaware

Differential Revision: https://phorge.dev.yugabyte.com/D41397
  • Loading branch information
mchiddy committed Jan 29, 2025
1 parent 2bc0c1a commit bf87067
Show file tree
Hide file tree
Showing 5 changed files with 397 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
import com.yugabyte.yw.commissioner.AbstractTaskBase;
import com.yugabyte.yw.commissioner.BaseTaskDependencies;
import com.yugabyte.yw.commissioner.Commissioner;
import com.yugabyte.yw.common.CloudUtil;
import com.yugabyte.yw.common.CloudUtilFactory;
import com.yugabyte.yw.common.PlatformServiceException;
import com.yugabyte.yw.common.ReleaseContainer;
import com.yugabyte.yw.common.ReleaseManager;
import com.yugabyte.yw.common.ShellResponse;
import com.yugabyte.yw.common.StorageUtil;
import com.yugabyte.yw.common.StorageUtilFactory;
import com.yugabyte.yw.common.ha.PlatformReplicationHelper;
import com.yugabyte.yw.common.ha.PlatformReplicationManager;
import com.yugabyte.yw.forms.AbstractTaskParams;
Expand All @@ -45,7 +45,7 @@
@Slf4j
public class CreateYbaBackup extends AbstractTaskBase {

private final CloudUtilFactory cloudUtilFactory;
private final StorageUtilFactory storageUtilFactory;
private final PlatformReplicationHelper replicationHelper;
private final PlatformReplicationManager replicationManager;
private final ReleaseManager releaseManager;
Expand All @@ -55,12 +55,12 @@ protected CreateYbaBackup(
BaseTaskDependencies baseTaskDependencies,
PlatformReplicationHelper replicationHelper,
PlatformReplicationManager replicationManager,
CloudUtilFactory cloudUtilFactory,
StorageUtilFactory storageUtilFactory,
ReleaseManager releaseManager) {
super(baseTaskDependencies);
this.replicationHelper = replicationHelper;
this.replicationManager = replicationManager;
this.cloudUtilFactory = cloudUtilFactory;
this.storageUtilFactory = storageUtilFactory;
this.releaseManager = releaseManager;
}

Expand Down Expand Up @@ -132,20 +132,20 @@ public void run() {
INTERNAL_SERVER_ERROR,
"Could not find customer config with provided storage config UUID during create.");
}
CloudUtil cloudUtil = cloudUtilFactory.getCloudUtil(customerConfig.getName());
if (!cloudUtil.uploadYbaBackup(customerConfig.getDataObject(), backup, taskParams.dirName)) {
StorageUtil storageUtil = storageUtilFactory.getStorageUtil(customerConfig.getName());
if (!storageUtil.uploadYbaBackup(customerConfig.getDataObject(), backup, taskParams.dirName)) {
throw new PlatformServiceException(
INTERNAL_SERVER_ERROR, "Could not upload YBA backup to cloud storage.");
}

if (!cloudUtil.cleanupUploadedBackups(customerConfig.getDataObject(), taskParams.dirName)) {
if (!storageUtil.cleanupUploadedBackups(customerConfig.getDataObject(), taskParams.dirName)) {
log.warn(
"Error cleaning up uploaded backups to cloud storage, please delete manually to avoid"
+ " incurring unexpected costs.");
}

Set<String> remoteReleases =
cloudUtil.getRemoteReleaseVersions(customerConfig.getDataObject(), taskParams.dirName);
storageUtil.getRemoteReleaseVersions(customerConfig.getDataObject(), taskParams.dirName);
// Get all local full paths
Map<String, ReleaseContainer> localReleaseContainers =
releaseManager.getAllLocalReleaseContainersByVersion();
Expand All @@ -159,7 +159,7 @@ public void run() {
.getLocalReleasePathStrings()
.forEach(
release -> {
cloudUtil.uploadYBDBRelease(
storageUtil.uploadYBDBRelease(
customerConfig.getDataObject(),
new File(release),
taskParams.dirName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
import com.typesafe.config.Config;
import com.yugabyte.yw.commissioner.AbstractTaskBase;
import com.yugabyte.yw.commissioner.BaseTaskDependencies;
import com.yugabyte.yw.common.CloudUtil;
import com.yugabyte.yw.common.CloudUtilFactory;
import com.yugabyte.yw.common.PlatformServiceException;
import com.yugabyte.yw.common.ReleaseContainer;
import com.yugabyte.yw.common.ReleaseManager;
import com.yugabyte.yw.common.StorageUtil;
import com.yugabyte.yw.common.StorageUtilFactory;
import com.yugabyte.yw.common.Util;
import com.yugabyte.yw.common.ha.PlatformReplicationHelper;
import com.yugabyte.yw.common.ha.PlatformReplicationManager;
Expand All @@ -35,7 +35,7 @@
@Slf4j
public class RestoreContinuousBackup extends AbstractTaskBase {

private final CloudUtilFactory cloudUtilFactory;
private final StorageUtilFactory storageUtilFactory;
private final PlatformReplicationHelper replicationHelper;
private final PlatformReplicationManager replicationManager;
private final Config appConfig;
Expand All @@ -46,13 +46,13 @@ protected RestoreContinuousBackup(
BaseTaskDependencies baseTaskDependencies,
PlatformReplicationHelper replicationHelper,
PlatformReplicationManager replicationManager,
CloudUtilFactory cloudUtilFactory,
StorageUtilFactory storageUtilFactory,
Config appConfig,
ReleaseManager releaseManager) {
super(baseTaskDependencies);
this.replicationHelper = replicationHelper;
this.replicationManager = replicationManager;
this.cloudUtilFactory = cloudUtilFactory;
this.storageUtilFactory = storageUtilFactory;
this.appConfig = appConfig;
this.releaseManager = releaseManager;
}
Expand Down Expand Up @@ -81,9 +81,9 @@ public void run() {
INTERNAL_SERVER_ERROR,
"Could not find customer config with provided storage config UUID during restore.");
}
CloudUtil cloudUtil = cloudUtilFactory.getCloudUtil(customerConfig.getName());
StorageUtil storageUtil = storageUtilFactory.getStorageUtil(customerConfig.getName());
File backup =
cloudUtil.downloadYbaBackup(
storageUtil.downloadYbaBackup(
customerConfig.getDataObject(),
taskParams.backupDir,
replicationHelper.getReplicationDirFor(taskParams.storageConfigUUID.toString()));
Expand All @@ -94,11 +94,11 @@ public void run() {

// Restore any missing YBDB releases from remote storage
Set<String> toDownloadReleases =
cloudUtil.getRemoteReleaseVersions(customerConfig.getDataObject(), taskParams.backupDir);
storageUtil.getRemoteReleaseVersions(customerConfig.getDataObject(), taskParams.backupDir);
Map<String, ReleaseContainer> localReleaseContainers =
releaseManager.getAllLocalReleaseContainersByVersion();
toDownloadReleases.removeAll(localReleaseContainers.keySet());
if (!cloudUtil.downloadRemoteReleases(
if (!storageUtil.downloadRemoteReleases(
customerConfig.getDataObject(),
toDownloadReleases,
appConfig.getString(Util.YB_RELEASES_PATH),
Expand Down
47 changes: 0 additions & 47 deletions managed/src/main/java/com/yugabyte/yw/common/CloudUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,14 @@
import com.yugabyte.yw.models.configs.data.CustomerConfigData;
import com.yugabyte.yw.models.helpers.NodeDetails;
import com.yugabyte.yw.models.helpers.ProxyConfig;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.MapUtils;
Expand Down Expand Up @@ -51,7 +47,6 @@ public static enum Protocol {

public static final String KEY_LOCATION_SUFFIX = Util.KEY_LOCATION_SUFFIX;
public static final String SUCCESS = "success";
public static final String YBDB_RELEASES = "ybdb_releases";
int FILE_DOWNLOAD_BUFFER_SIZE = 8 * 1024;

public static final String DUMMY_DATA = "dummy-text";
Expand Down Expand Up @@ -116,38 +111,6 @@ default UUID getRandomUUID() {
return UUID.randomUUID();
}

public default boolean uploadYbaBackup(
CustomerConfigData configData, File backup, String backupDir) {
return false;
}

public default boolean cleanupUploadedBackups(CustomerConfigData configData, String backupDir) {
return false;
}

public default File downloadYbaBackup(
CustomerConfigData configData, String backupDir, Path localDir) {
return null;
}

public default boolean uploadYBDBRelease(
CustomerConfigData configData, File release, String backupDir, String version) {
return false;
}

public default Set<String> getRemoteReleaseVersions(
CustomerConfigData configData, String backupDir) {
return new HashSet<>();
}

public default boolean downloadRemoteReleases(
CustomerConfigData configData,
Set<String> releaseVersions,
String releasesPath,
String backupDir) {
return false;
}

public default RestorePreflightResponse
generateYBBackupRestorePreflightResponseWithoutBackupObject(
AdvancedRestorePreflightParams preflightParams, CustomerConfigData configData) {
Expand Down Expand Up @@ -217,14 +180,4 @@ public default org.yb.ybc.ProxyConfig createYbcProxyConfig(
}
return null;
}

public default String extractReleaseVersion(String key, String backupDir) {
String regex = String.format("%s/%s/([^/]+)/([^/]+)$", backupDir, YBDB_RELEASES);
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(key);
if (matcher.matches()) {
return matcher.group(1);
}
return null;
}
}
Loading

0 comments on commit bf87067

Please sign in to comment.