feat(backup): add chain-metadata keys + nas.backup.full.every config

NASBackupChainKeys defines the keys this provider stores under the
existing backup_details kv table (parent_backup_id, bitmap_name,
chain_id, chain_position, type). This keeps the backups table
provider-agnostic per the RFC review.

nas.backup.full.every is a zone-scoped ConfigKey that controls how
often a full backup is taken; the remaining backups in the cycle are
incremental. Counts backups (not days), so it works for hourly,
daily, and ad-hoc schedules. Default 10. Set to 1 to disable
incrementals (every backup is full).

Refs: apache/cloudstack#12899
This commit is contained in:
James Peru 2026-04-27 18:49:38 +03:00
parent f2a9202d74
commit 1981469099
2 changed files with 59 additions and 1 deletions

View File

@ -0,0 +1,47 @@
// 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;
/**
* Keys used by the NAS backup provider when storing incremental-chain metadata
* in the existing {@code backup_details} key/value table. Stored here (not on
* the {@code backups} table) so other providers do not need a schema change to
* support their own incremental implementations.
*/
public final class NASBackupChainKeys {
/** UUID of the parent backup (full or previous incremental). Empty for full backups. */
public static final String PARENT_BACKUP_ID = "nas.parent_backup_id";
/** QEMU dirty-bitmap name created by this backup, used as the {@code <incremental>} reference for the next one. */
public static final String BITMAP_NAME = "nas.bitmap_name";
/** Identifier shared by every backup in the same chain (the full anchors a chain; its incrementals inherit the id). */
public static final String CHAIN_ID = "nas.chain_id";
/** Position within the chain: 0 for the full, 1 for the first incremental, and so on. */
public static final String CHAIN_POSITION = "nas.chain_position";
/** Backup type marker: {@value #TYPE_FULL} or {@value #TYPE_INCREMENTAL}. Mirrors {@code backups.type} for fast lookup without a join. */
public static final String TYPE = "nas.type";
public static final String TYPE_FULL = "full";
public static final String TYPE_INCREMENTAL = "incremental";
private NASBackupChainKeys() {
}
}

View File

@ -85,6 +85,16 @@ public class NASBackupProvider extends AdapterBase implements BackupProvider, Co
true,
BackupFrameworkEnabled.key());
ConfigKey<Integer> NASBackupFullEvery = new ConfigKey<>("Advanced", Integer.class,
"nas.backup.full.every",
"10",
"Take a full NAS backup every Nth backup; remaining backups in between are incremental. " +
"Counts backups, not days, so it works for hourly, daily, and ad-hoc schedules. " +
"Set to 1 to disable incrementals (every backup is full).",
true,
ConfigKey.Scope.Zone,
BackupFrameworkEnabled.key());
@Inject
private BackupDao backupDao;
@ -629,7 +639,8 @@ public class NASBackupProvider extends AdapterBase implements BackupProvider, Co
@Override
public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey[]{
NASBackupRestoreMountTimeout
NASBackupRestoreMountTimeout,
NASBackupFullEvery
};
}