Skip to content

Commit 38d386a

Browse files
abh1sarDaanHooglandlucas-a-martinsLucas MartinsPearl1594
authored andcommitted
Add Resource Limits to Backups and Object Storage (apache#10017)
Doc PR : apache/cloudstack-documentation#461 This PR fixes apache#8638 == Description Four new Resource Types have been added. Admin can configure corresponding resource limits for the tenants at different levels (domain, account, project) User dashboard's Storage section will show the new resources, their limits and current usage. 1. backup - No. of backups used by the account 2. backup_storage - Backup storage allocated for the account 3. bucket - No. of buckets used by the accounts 4. object_storage - Object storage allocated for the account. Some other related changes done to BnR framework: 1. Maximum number of Backups to retain can be specified while creating Backup schedules, similar to Scheduled snapshots. 2. Oldest Scheduled backup of the same interval type will be deleted once the number reaches the configured max Backups value. 3. Code refactor: Moved syncBackups method from BackupProvider to the framework BackupManagerImpl, as it is a common functionality and all providers were using duplicated code. Changes done to the Object Storage Framework 1. Quota parameter is made mandatory while creating a bucket. Bucket quota is considered to be the allocated space and will be used to enforce Resource limits. == Schema Changes: 1. New Column `max_backups` added to `backup_schedule` table 4. New Column `backup_interval_type` added to `backups` table == Api Changes: 1. createBackup: new Parameter `scheduleid`. It should be specified whenever a scheduled backup is created. This will translate to the `backup_interval_type` in the `backups` table. 3. createBackupScheduke: new Parameter `max_backups`. To specify maximum number of backups to retain for the given schedule. == Configurations: |Setting |Scope |Default Value |Description| |-------|--------|--------------|-----------| |backup.max.hourly |Global |8 |Maximum recurring hourly backups to be retained for an instance| |backup.max.daily |Global |8 |Maximum recurring daily backups to be retained for an instance| |backup.max.weekly |Global |8 |Maximum recurring weekly backups to be retained for an instance| |backup.max.monthly |Global |8 |Maximum recurring monthly backups to be retained for an instance| |max.account.backups| Global| 20 | The default maximum number of backups that can be created for an account| |max.account.backup.storage| Global| 400 | The default maximum backup storage space (in GiB) that can be used for an account| |max.domain.backups| Global| 40 | The default maximum number of backups that can be created for an domain| |max.domain.backup.storage| Global| 800 | The default maximum backup storage space (in GiB) that can be used for an domain| |max.project.backups| Global| 20 | The default maximum number of backups that can be created for an project| |max.project.backup.storage| Global| 400 | The default maximum backup storage space (in GiB) that can be used for an project| |Setting |Scope |Default Value |Description| |-------|--------|--------------|-----------| |max.account.buckets| Global| 20 | The default maximum number of buckets that can be created for an account| |max.account.object.storage| Global| 400 | The default maximum object storage space (in GiB) that can be used for an account| |max.domain.buckets| Global| 40 | The default maximum number of buckets that can be created for an domain| |max.domain.object.storage| Global| 800 | The default maximum object storage space (in GiB) that can be used for an domain| |max.project.buckets| Global| 20 | The default maximum number of buckets that can be created for an project| |max.project.object.storage| Global| 400 | The default maximum object storage space (in GiB) that can be used for an project| Co-authored-by: Daan Hoogland <daan@onecht.net> Co-authored-by: Lucas Martins <56271185+lucas-a-martins@users.noreply.github.com> Co-authored-by: Lucas Martins <lucas.martins@scclouds.com.br> Co-authored-by: Pearl Dsilva <pearl1594@gmail.com> Co-authored-by: Rohit Yadav <rohit.yadav@shapeblue.com>
1 parent d623eef commit 38d386a

File tree

58 files changed

+2182
-270
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+2182
-270
lines changed

api/src/main/java/com/cloud/configuration/Resource.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public interface Resource {
2121
short RESOURCE_UNLIMITED = -1;
2222
String UNLIMITED = "Unlimited";
2323

24-
enum ResourceType { // Primary and Secondary storage are allocated_storage and not the physical storage.
24+
enum ResourceType { // All storage type resources are allocated_storage and not the physical storage.
2525
user_vm("user_vm", 0),
2626
public_ip("public_ip", 1),
2727
volume("volume", 2),
@@ -33,7 +33,11 @@ enum ResourceType { // Primary and Secondary storage are allocated_storage and n
3333
cpu("cpu", 8),
3434
memory("memory", 9),
3535
primary_storage("primary_storage", 10),
36-
secondary_storage("secondary_storage", 11);
36+
secondary_storage("secondary_storage", 11),
37+
backup("backup", 12),
38+
backup_storage("backup_storage", 13),
39+
bucket("bucket", 14),
40+
object_storage("object_storage", 15);
3741

3842
private String name;
3943
private int ordinal;
@@ -62,6 +66,10 @@ public static ResourceType fromOrdinal(int ordinal) {
6266
}
6367
return null;
6468
}
69+
70+
public static Boolean isStorageType(ResourceType type) {
71+
return (type == primary_storage || type == secondary_storage || type == backup_storage || type == object_storage);
72+
}
6573
}
6674

6775
public static class ResourceOwnerType {

api/src/main/java/com/cloud/event/EventTypes.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,9 @@ public class EventTypes {
797797

798798
// DISASTER RECOVERY
799799
public static final String EVENT_DISASTER_RECOVERY_CLUSTER = "DISASTER.RECOVERY.CLUSTER";
800+
801+
// Resource Limit
802+
public static final String EVENT_RESOURCE_LIMIT_UPDATE = "RESOURCE.LIMIT.UPDATE";
800803

801804
static {
802805

api/src/main/java/com/cloud/storage/VolumeApiService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,4 +194,6 @@ Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account acc
194194
Volume cloneVolumeFromSnapshot(Volume volume, long snapshotId, Long vmId) throws StorageUnavailableException;
195195

196196
Volume updateCompressDedupVolume(UpdateCompressDedupCmd cmd);
197+
198+
Long getVolumePhysicalSize(Storage.ImageFormat format, String path, String chainInfo);
197199
}

api/src/main/java/org/apache/cloudstack/api/ApiConstants.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,15 @@ public class ApiConstants {
5151
public static final String AVAILABLE = "available";
5252
public static final String AVAILABLE_SUBNETS = "availablesubnets";
5353
public static final String AVAILABLE_VIRTUAL_MACHINE_COUNT = "availablevirtualmachinecount";
54+
public static final String BACKUP_AVAILABLE = "backupavailable";
5455
public static final String BACKUP_ID = "backupid";
56+
public static final String BACKUP_LIMIT = "backuplimit";
5557
public static final String BACKUP_OFFERING_NAME = "backupofferingname";
5658
public static final String BACKUP_OFFERING_ID = "backupofferingid";
59+
public static final String BACKUP_STORAGE_AVAILABLE = "backupstorageavailable";
60+
public static final String BACKUP_STORAGE_LIMIT = "backupstoragelimit";
61+
public static final String BACKUP_STORAGE_TOTAL = "backupstoragetotal";
62+
public static final String BACKUP_TOTAL = "backuptotal";
5763
public static final String BASE64_IMAGE = "base64image";
5864
public static final String BGP_PEERS = "bgppeers";
5965
public static final String BGP_PEER_IDS = "bgppeerids";
@@ -329,6 +335,7 @@ public class ApiConstants {
329335
public static final String MAC_ADDRESS = "macaddress";
330336
public static final String MAX = "max";
331337
public static final String MAX_SNAPS = "maxsnaps";
338+
public static final String MAX_BACKUPS = "maxbackups";
332339
public static final String MAX_CPU_NUMBER = "maxcpunumber";
333340
public static final String MAX_MEMORY = "maxmemory";
334341
public static final String MIN_CPU_NUMBER = "mincpunumber";
@@ -443,6 +450,7 @@ public class ApiConstants {
443450
public static final String QUALIFIERS = "qualifiers";
444451
public static final String QUERY_FILTER = "queryfilter";
445452
public static final String SCHEDULE = "schedule";
453+
public static final String SCHEDULE_ID = "scheduleid";
446454
public static final String SCOPE = "scope";
447455
public static final String SEARCH_BASE = "searchbase";
448456
public static final String SECONDARY_IP = "secondaryip";
@@ -1214,7 +1222,6 @@ public class ApiConstants {
12141222
public static final String MTU = "mtu";
12151223
public static final String AUTO_ENABLE_KVM_HOST = "autoenablekvmhost";
12161224
public static final String LIST_APIS = "listApis";
1217-
public static final String OBJECT_STORAGE_ID = "objectstorageid";
12181225
public static final String VERSIONING = "versioning";
12191226
public static final String OBJECT_LOCKING = "objectlocking";
12201227
public static final String ENCRYPTION = "encryption";
@@ -1228,7 +1235,6 @@ public class ApiConstants {
12281235
public static final String DISK_PATH = "diskpath";
12291236
public static final String IMPORT_SOURCE = "importsource";
12301237
public static final String TEMP_PATH = "temppath";
1231-
public static final String OBJECT_STORAGE = "objectstore";
12321238

12331239
public static final String FIRST_LOGIN = "firstlogin";
12341240

@@ -1277,6 +1283,15 @@ public class ApiConstants {
12771283
public static final String LISTHOSTDEVICES = "listhostdevices";
12781284
public static final String HOSTDEVICES_NAME = "hostdevicesname";
12791285
public static final String HOSTDEVICES_TEXT = "hostdevicestext";
1286+
// Object Storage related
1287+
public static final String BUCKET_AVAILABLE = "bucketavailable";
1288+
public static final String BUCKET_LIMIT = "bucketlimit";
1289+
public static final String BUCKET_TOTAL = "buckettotal";
1290+
public static final String OBJECT_STORAGE_ID = "objectstorageid";
1291+
public static final String OBJECT_STORAGE = "objectstore";
1292+
public static final String OBJECT_STORAGE_AVAILABLE = "objectstorageavailable";
1293+
public static final String OBJECT_STORAGE_LIMIT = "objectstoragelimit";
1294+
public static final String OBJECT_STORAGE_TOTAL = "objectstoragetotal";
12801295

12811296
public static final String PARAMETER_DESCRIPTION_ACTIVATION_RULE = "Quota tariff's activation rule. It can receive a JS script that results in either " +
12821297
"a boolean or a numeric value: if it results in a boolean value, the tariff value will be applied according to the result; if it results in a numeric value, the " +

api/src/main/java/org/apache/cloudstack/api/command/user/backup/CreateBackupCmd.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import javax.inject.Inject;
2121

22+
import com.cloud.storage.Snapshot;
2223
import org.apache.cloudstack.acl.RoleType;
2324
import org.apache.cloudstack.api.APICommand;
2425
import org.apache.cloudstack.api.ApiCommandResourceType;
@@ -27,6 +28,7 @@
2728
import org.apache.cloudstack.api.BaseAsyncCreateCmd;
2829
import org.apache.cloudstack.api.Parameter;
2930
import org.apache.cloudstack.api.ServerApiException;
31+
import org.apache.cloudstack.api.response.BackupScheduleResponse;
3032
import org.apache.cloudstack.api.response.SuccessResponse;
3133
import org.apache.cloudstack.api.response.UserVmResponse;
3234
import org.apache.cloudstack.backup.BackupManager;
@@ -60,6 +62,13 @@ public class CreateBackupCmd extends BaseAsyncCreateCmd {
6062
description = "ID of the VM")
6163
private Long vmId;
6264

65+
@Parameter(name = ApiConstants.SCHEDULE_ID,
66+
type = CommandType.LONG,
67+
entityType = BackupScheduleResponse.class,
68+
description = "backup schedule ID of the VM, if this is null, it indicates that it is a manual backup.",
69+
since = "4.21.0")
70+
private Long scheduleId;
71+
6372
/////////////////////////////////////////////////////
6473
/////////////////// Accessors ///////////////////////
6574
/////////////////////////////////////////////////////
@@ -68,14 +77,22 @@ public Long getVmId() {
6877
return vmId;
6978
}
7079

80+
public Long getScheduleId() {
81+
if (scheduleId != null) {
82+
return scheduleId;
83+
} else {
84+
return Snapshot.MANUAL_POLICY_ID;
85+
}
86+
}
87+
7188
/////////////////////////////////////////////////////
7289
/////////////// API Implementation///////////////////
7390
/////////////////////////////////////////////////////
7491

7592
@Override
7693
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
7794
try {
78-
boolean result = backupManager.createBackup(getVmId());
95+
boolean result = backupManager.createBackup(getVmId(), getScheduleId());
7996
if (result) {
8097
SuccessResponse response = new SuccessResponse(getCommandName());
8198
response.setResponseName(getCommandName());

api/src/main/java/org/apache/cloudstack/api/command/user/backup/CreateBackupScheduleCmd.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ public class CreateBackupScheduleCmd extends BaseCmd {
7575
description = "Specifies a timezone for this command. For more information on the timezone parameter, see TimeZone Format.")
7676
private String timezone;
7777

78+
@Parameter(name = ApiConstants.MAX_BACKUPS,
79+
type = CommandType.INTEGER,
80+
description = "maximum number of backups to retain",
81+
since = "4.21.0")
82+
private Integer maxBackups;
83+
7884
/////////////////////////////////////////////////////
7985
/////////////////// Accessors ///////////////////////
8086
/////////////////////////////////////////////////////
@@ -95,6 +101,10 @@ public String getTimezone() {
95101
return timezone;
96102
}
97103

104+
public Integer getMaxBackups() {
105+
return maxBackups;
106+
}
107+
98108
/////////////////////////////////////////////////////
99109
/////////////// API Implementation///////////////////
100110
/////////////////////////////////////////////////////

api/src/main/java/org/apache/cloudstack/api/command/user/bucket/CreateBucketCmd.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public class CreateBucketCmd extends BaseAsyncCreateCmd implements UserCmd {
7272
description = "Id of the Object Storage Pool where bucket is created")
7373
private long objectStoragePoolId;
7474

75-
@Parameter(name = ApiConstants.QUOTA, type = CommandType.INTEGER,description = "Bucket Quota in GB")
75+
@Parameter(name = ApiConstants.QUOTA, type = CommandType.INTEGER, required = true, description = "Bucket Quota in GiB")
7676
private Integer quota;
7777

7878
@Parameter(name = ApiConstants.ENCRYPTION, type = CommandType.BOOLEAN, description = "Enable bucket encryption")

api/src/main/java/org/apache/cloudstack/api/command/user/bucket/UpdateBucketCmd.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public class UpdateBucketCmd extends BaseCmd {
5656
@Parameter(name = ApiConstants.POLICY, type = CommandType.STRING, description = "Bucket Access Policy")
5757
private String policy;
5858

59-
@Parameter(name = ApiConstants.QUOTA, type = CommandType.INTEGER,description = "Bucket Quota in GB")
59+
@Parameter(name = ApiConstants.QUOTA, type = CommandType.INTEGER, description = "Bucket Quota in GiB")
6060
private Integer quota;
6161

6262
/////////////////////////////////////////////////////

api/src/main/java/org/apache/cloudstack/api/response/AccountResponse.java

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,30 @@ public class AccountResponse extends BaseResponse implements ResourceLimitAndCou
127127
@Param(description = "the total number of snapshots available for this account")
128128
private String snapshotAvailable;
129129

130+
@SerializedName(ApiConstants.BACKUP_LIMIT)
131+
@Param(description = "the total number of backups which can be stored by this account", since = "4.21.0")
132+
private String backupLimit;
133+
134+
@SerializedName(ApiConstants.BACKUP_TOTAL)
135+
@Param(description = "the total number of backups stored by this account", since = "4.21.0")
136+
private Long backupTotal;
137+
138+
@SerializedName(ApiConstants.BACKUP_AVAILABLE)
139+
@Param(description = "the total number of backups available to this account", since = "4.21.0")
140+
private String backupAvailable;
141+
142+
@SerializedName(ApiConstants.BACKUP_STORAGE_LIMIT)
143+
@Param(description = "the total backup storage space (in GiB) the account can own", since = "4.21.0")
144+
private String backupStorageLimit;
145+
146+
@SerializedName(ApiConstants.BACKUP_STORAGE_TOTAL)
147+
@Param(description = "the total backup storage space (in GiB) owned by the account", since = "4.21.0")
148+
private Long backupStorageTotal;
149+
150+
@SerializedName(ApiConstants.BACKUP_STORAGE_AVAILABLE)
151+
@Param(description = "the total backup storage space (in GiB) available to the account", since = "4.21.0")
152+
private String backupStorageAvailable;
153+
130154
@SerializedName("templatelimit")
131155
@Param(description = "the total number of templates which can be created by this account")
132156
private String templateLimit;
@@ -231,6 +255,30 @@ public class AccountResponse extends BaseResponse implements ResourceLimitAndCou
231255
@Param(description = "the total secondary storage space (in GiB) available to be used for this account", since = "4.2.0")
232256
private String secondaryStorageAvailable;
233257

258+
@SerializedName(ApiConstants.BUCKET_LIMIT)
259+
@Param(description = "the total number of buckets which can be stored by this account", since = "4.21.0")
260+
private String bucketLimit;
261+
262+
@SerializedName(ApiConstants.BUCKET_TOTAL)
263+
@Param(description = "the total number of buckets stored by this account", since = "4.21.0")
264+
private Long bucketTotal;
265+
266+
@SerializedName(ApiConstants.BUCKET_AVAILABLE)
267+
@Param(description = "the total number of buckets available to this account", since = "4.21.0")
268+
private String bucketAvailable;
269+
270+
@SerializedName(ApiConstants.OBJECT_STORAGE_LIMIT)
271+
@Param(description = "the total object storage space (in GiB) the account can own", since = "4.21.0")
272+
private String objectStorageLimit;
273+
274+
@SerializedName(ApiConstants.OBJECT_STORAGE_TOTAL)
275+
@Param(description = "the total object storage space (in GiB) owned by the account", since = "4.21.0")
276+
private Long objectStorageTotal;
277+
278+
@SerializedName(ApiConstants.OBJECT_STORAGE_AVAILABLE)
279+
@Param(description = "the total object storage space (in GiB) available to the account", since = "4.21.0")
280+
private String objectStorageAvailable;
281+
234282
@SerializedName(ApiConstants.STATE)
235283
@Param(description = "the state of the account")
236284
private String state;
@@ -386,6 +434,36 @@ public void setSnapshotAvailable(String snapshotAvailable) {
386434
this.snapshotAvailable = snapshotAvailable;
387435
}
388436

437+
@Override
438+
public void setBackupLimit(String backupLimit) {
439+
this.backupLimit = backupLimit;
440+
}
441+
442+
@Override
443+
public void setBackupTotal(Long backupTotal) {
444+
this.backupTotal = backupTotal;
445+
}
446+
447+
@Override
448+
public void setBackupAvailable(String backupAvailable) {
449+
this.backupAvailable = backupAvailable;
450+
}
451+
452+
@Override
453+
public void setBackupStorageLimit(String backupStorageLimit) {
454+
this.backupStorageLimit = backupStorageLimit;
455+
}
456+
457+
@Override
458+
public void setBackupStorageTotal(Long backupStorageTotal) {
459+
this.backupStorageTotal = backupStorageTotal;
460+
}
461+
462+
@Override
463+
public void setBackupStorageAvailable(String backupStorageAvailable) {
464+
this.backupStorageAvailable = backupStorageAvailable;
465+
}
466+
389467
@Override
390468
public void setTemplateLimit(String templateLimit) {
391469
this.templateLimit = templateLimit;
@@ -537,6 +615,36 @@ public void setSecondaryStorageAvailable(String secondaryStorageAvailable) {
537615
this.secondaryStorageAvailable = secondaryStorageAvailable;
538616
}
539617

618+
@Override
619+
public void setBucketLimit(String bucketLimit) {
620+
this.bucketLimit = bucketLimit;
621+
}
622+
623+
@Override
624+
public void setBucketTotal(Long bucketTotal) {
625+
this.bucketTotal = bucketTotal;
626+
}
627+
628+
@Override
629+
public void setBucketAvailable(String bucketAvailable) {
630+
this.bucketAvailable = bucketAvailable;
631+
}
632+
633+
@Override
634+
public void setObjectStorageLimit(String objectStorageLimit) {
635+
this.objectStorageLimit = objectStorageLimit;
636+
}
637+
638+
@Override
639+
public void setObjectStorageTotal(Long objectStorageTotal) {
640+
this.objectStorageTotal = objectStorageTotal;
641+
}
642+
643+
@Override
644+
public void setObjectStorageAvailable(String objectStorageAvailable) {
645+
this.objectStorageAvailable = objectStorageAvailable;
646+
}
647+
540648
public void setDefaultZone(String defaultZoneId) {
541649
this.defaultZoneId = defaultZoneId;
542650
}

api/src/main/java/org/apache/cloudstack/api/response/BackupScheduleResponse.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,22 @@ public class BackupScheduleResponse extends BaseResponse {
3737
@Param(description = "ID of the VM")
3838
private String vmId;
3939

40-
@SerializedName("schedule")
40+
@SerializedName(ApiConstants.SCHEDULE)
4141
@Param(description = "time the backup is scheduled to be taken.")
4242
private String schedule;
4343

44-
@SerializedName("intervaltype")
44+
@SerializedName(ApiConstants.INTERVAL_TYPE)
4545
@Param(description = "the interval type of the backup schedule")
4646
private DateUtil.IntervalType intervalType;
4747

48-
@SerializedName("timezone")
48+
@SerializedName(ApiConstants.TIMEZONE)
4949
@Param(description = "the time zone of the backup schedule")
5050
private String timezone;
5151

52+
@SerializedName(ApiConstants.MAX_BACKUPS)
53+
@Param(description = "maximum number of backups retained")
54+
private Integer maxBakups;
55+
5256
public String getVmName() {
5357
return vmName;
5458
}
@@ -88,4 +92,8 @@ public String getTimezone() {
8892
public void setTimezone(String timezone) {
8993
this.timezone = timezone;
9094
}
95+
96+
public void setMaxBakups(Integer maxBakups) {
97+
this.maxBakups = maxBakups;
98+
}
9199
}

0 commit comments

Comments
 (0)