Skip to content
Open
35 changes: 35 additions & 0 deletions core/src/main/java/org/apache/cloudstack/backup/BackupAnswer.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@ public class BackupAnswer extends Answer {
private Long virtualSize;
private Map<String, String> volumes;
Boolean needsCleanup;
// Set by the NAS backup provider after a checkpoint/bitmap was created during this backup.
// The provider persists it in backup_details under NASBackupChainKeys.BITMAP_NAME.
private String bitmapCreated;
// Set when an incremental was requested but the agent had to fall back to a full
// (e.g. VM was stopped). Provider should record this backup as type=full.
private Boolean incrementalFallback;
// Set when the agent had to recreate the parent bitmap before this incremental
// (e.g. CloudStack rebuilt the domain XML on the previous VM start, losing bitmaps).
// The first incremental after a recreate is larger than usual; subsequent
// incrementals return to normal size. Informational — recorded in backup_details.
private String bitmapRecreated;

public BackupAnswer(final Command command, final boolean success, final String details) {
super(command, success, details);
Expand Down Expand Up @@ -68,4 +79,28 @@ public Boolean getNeedsCleanup() {
public void setNeedsCleanup(Boolean needsCleanup) {
this.needsCleanup = needsCleanup;
}

public String getBitmapCreated() {
return bitmapCreated;
}

public void setBitmapCreated(String bitmapCreated) {
this.bitmapCreated = bitmapCreated;
}

public Boolean getIncrementalFallback() {
return incrementalFallback != null && incrementalFallback;
}

public void setIncrementalFallback(Boolean incrementalFallback) {
this.incrementalFallback = incrementalFallback;
}

public String getBitmapRecreated() {
return bitmapRecreated;
}

public void setBitmapRecreated(String bitmapRecreated) {
this.bitmapRecreated = bitmapRecreated;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//

package org.apache.cloudstack.backup;

import com.cloud.agent.api.Command;
import com.cloud.agent.api.LogLevel;

/**
* Tells the KVM agent to rebase a NAS backup qcow2 onto a new backing parent. Used by the
* NAS backup provider during chain repair when a middle incremental is being deleted: the
* immediate child must absorb the soon-to-be-deleted parent's blocks and then re-link to
* the grandparent. Both target and new-backing paths are NAS-mount-relative.
*/
public class RebaseBackupCommand extends Command {
private String targetPath; // mount-relative path of the qcow2 to repoint
private String newBackingPath; // mount-relative path of the new backing parent
private String backupRepoType;
private String backupRepoAddress;
@LogLevel(LogLevel.Log4jLevel.Off)
private String mountOptions;

public RebaseBackupCommand(String targetPath, String newBackingPath,
String backupRepoType, String backupRepoAddress, String mountOptions) {
super();
this.targetPath = targetPath;
this.newBackingPath = newBackingPath;
this.backupRepoType = backupRepoType;
this.backupRepoAddress = backupRepoAddress;
this.mountOptions = mountOptions;
}

public String getTargetPath() {
return targetPath;
}

public String getNewBackingPath() {
return newBackingPath;
}

public String getBackupRepoType() {
return backupRepoType;
}

public String getBackupRepoAddress() {
return backupRepoAddress;
}

public String getMountOptions() {
return mountOptions == null ? "" : mountOptions;
}

@Override
public boolean executeInSequence() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ public class TakeBackupCommand extends Command {
@LogLevel(LogLevel.Log4jLevel.Off)
private String mountOptions;

// Incremental backup fields (NAS provider; null/empty for legacy full-only callers).
private String mode; // "full" or "incremental"; null => legacy behaviour (script default)
private String bitmapNew; // Checkpoint/bitmap name to create with this backup (timestamp-based)
private String bitmapParent; // Incremental: parent bitmap to read changes since
private String parentPath; // Incremental: parent backup file path on the mounted NAS (for qemu-img rebase)

public TakeBackupCommand(String vmName, String backupPath) {
super();
this.vmName = vmName;
Expand Down Expand Up @@ -106,6 +112,38 @@ public void setQuiesce(Boolean quiesce) {
this.quiesce = quiesce;
}

public String getMode() {
return mode;
}

public void setMode(String mode) {
this.mode = mode;
}

public String getBitmapNew() {
return bitmapNew;
}

public void setBitmapNew(String bitmapNew) {
this.bitmapNew = bitmapNew;
}

public String getBitmapParent() {
return bitmapParent;
}

public void setBitmapParent(String bitmapParent) {
this.bitmapParent = bitmapParent;
}

public String getParentPath() {
return parentPath;
}

public void setParentPath(String parentPath) {
this.parentPath = parentPath;
}

@Override
public boolean executeInSequence() {
return true;
Expand Down
Loading
Loading