Skip to content

Commit f01ed01

Browse files
committed
Merge branch 'clone-edit-existing-offerings' of https://github.com/apache/cloudstack into clone-edit-existing-offerings
2 parents da85858 + 9907d5a commit f01ed01

File tree

41 files changed

+10698
-1833
lines changed

Some content is hidden

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

41 files changed

+10698
-1833
lines changed

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

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,18 @@
2424
import org.apache.cloudstack.api.ApiConstants;
2525
import org.apache.cloudstack.api.command.admin.config.ResetCfgCmd;
2626
import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd;
27+
import org.apache.cloudstack.api.command.admin.network.CloneNetworkOfferingCmd;
2728
import org.apache.cloudstack.api.command.admin.network.CreateGuestNetworkIpv6PrefixCmd;
2829
import org.apache.cloudstack.api.command.admin.network.CreateManagementNetworkIpRangeCmd;
29-
import org.apache.cloudstack.api.command.admin.network.CreateNetworkOfferingCmd;
3030
import org.apache.cloudstack.api.command.admin.network.DeleteGuestNetworkIpv6PrefixCmd;
3131
import org.apache.cloudstack.api.command.admin.network.DeleteManagementNetworkIpRangeCmd;
3232
import org.apache.cloudstack.api.command.admin.network.DeleteNetworkOfferingCmd;
3333
import org.apache.cloudstack.api.command.admin.network.ListGuestNetworkIpv6PrefixesCmd;
34+
import org.apache.cloudstack.api.command.admin.network.NetworkOfferingBaseCmd;
3435
import org.apache.cloudstack.api.command.admin.network.UpdateNetworkOfferingCmd;
3536
import org.apache.cloudstack.api.command.admin.network.UpdatePodManagementNetworkIpRangeCmd;
37+
import org.apache.cloudstack.api.command.admin.offering.CloneDiskOfferingCmd;
38+
import org.apache.cloudstack.api.command.admin.offering.CloneServiceOfferingCmd;
3639
import org.apache.cloudstack.api.command.admin.offering.CreateDiskOfferingCmd;
3740
import org.apache.cloudstack.api.command.admin.offering.CreateServiceOfferingCmd;
3841
import org.apache.cloudstack.api.command.admin.offering.DeleteDiskOfferingCmd;
@@ -105,6 +108,33 @@ public interface ConfigurationService {
105108
*/
106109
ServiceOffering createServiceOffering(CreateServiceOfferingCmd cmd);
107110

111+
/**
112+
* Clones a service offering with optional parameter overrides
113+
*
114+
* @param cmd
115+
* the command object that specifies the source offering ID and optional parameter overrides
116+
* @return the newly created service offering cloned from source, null otherwise
117+
*/
118+
ServiceOffering cloneServiceOffering(CloneServiceOfferingCmd cmd);
119+
120+
/**
121+
* Clones a disk offering with optional parameter overrides
122+
*
123+
* @param cmd
124+
* the command object that specifies the source offering ID and optional parameter overrides
125+
* @return the newly created disk offering cloned from source, null otherwise
126+
*/
127+
DiskOffering cloneDiskOffering(CloneDiskOfferingCmd cmd);
128+
129+
/**
130+
* Clones a network offering with optional parameter overrides
131+
*
132+
* @param cmd
133+
* the command object that specifies the source offering ID and optional parameter overrides
134+
* @return the newly created network offering cloned from source, null otherwise
135+
*/
136+
NetworkOffering cloneNetworkOffering(CloneNetworkOfferingCmd cmd);
137+
108138
/**
109139
* Updates a service offering
110140
*
@@ -282,7 +312,7 @@ Vlan updateVlanAndPublicIpRange(UpdateVlanIpRangeCmd cmd) throws ConcurrentOpera
282312

283313
boolean releasePublicIpRange(ReleasePublicIpRangeCmd cmd);
284314

285-
NetworkOffering createNetworkOffering(CreateNetworkOfferingCmd cmd);
315+
NetworkOffering createNetworkOffering(NetworkOfferingBaseCmd cmd);
286316

287317
NetworkOffering updateNetworkOffering(UpdateNetworkOfferingCmd cmd);
288318

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,11 +374,13 @@ public class EventTypes {
374374

375375
// Service Offerings
376376
public static final String EVENT_SERVICE_OFFERING_CREATE = "SERVICE.OFFERING.CREATE";
377+
public static final String EVENT_SERVICE_OFFERING_CLONE = "SERVICE.OFFERING.CLONE";
377378
public static final String EVENT_SERVICE_OFFERING_EDIT = "SERVICE.OFFERING.EDIT";
378379
public static final String EVENT_SERVICE_OFFERING_DELETE = "SERVICE.OFFERING.DELETE";
379380

380381
// Disk Offerings
381382
public static final String EVENT_DISK_OFFERING_CREATE = "DISK.OFFERING.CREATE";
383+
public static final String EVENT_DISK_OFFERING_CLONE = "DISK.OFFERING.CLONE";
382384
public static final String EVENT_DISK_OFFERING_EDIT = "DISK.OFFERING.EDIT";
383385
public static final String EVENT_DISK_OFFERING_DELETE = "DISK.OFFERING.DELETE";
384386

@@ -399,6 +401,7 @@ public class EventTypes {
399401

400402
// Network offerings
401403
public static final String EVENT_NETWORK_OFFERING_CREATE = "NETWORK.OFFERING.CREATE";
404+
public static final String EVENT_NETWORK_OFFERING_CLONE = "NETWORK.OFFERING.CLONE";
402405
public static final String EVENT_NETWORK_OFFERING_ASSIGN = "NETWORK.OFFERING.ASSIGN";
403406
public static final String EVENT_NETWORK_OFFERING_EDIT = "NETWORK.OFFERING.EDIT";
404407
public static final String EVENT_NETWORK_OFFERING_REMOVE = "NETWORK.OFFERING.REMOVE";
@@ -598,6 +601,7 @@ public class EventTypes {
598601

599602
// VPC offerings
600603
public static final String EVENT_VPC_OFFERING_CREATE = "VPC.OFFERING.CREATE";
604+
public static final String EVENT_VPC_OFFERING_CLONE = "VPC.OFFERING.CLONE";
601605
public static final String EVENT_VPC_OFFERING_UPDATE = "VPC.OFFERING.UPDATE";
602606
public static final String EVENT_VPC_OFFERING_DELETE = "VPC.OFFERING.DELETE";
603607

@@ -630,6 +634,7 @@ public class EventTypes {
630634

631635
// Backup and Recovery events
632636
public static final String EVENT_VM_BACKUP_IMPORT_OFFERING = "BACKUP.IMPORT.OFFERING";
637+
public static final String EVENT_VM_BACKUP_OFFERING_CLONE = "BACKUP.OFFERING.CLONE";
633638
public static final String EVENT_VM_BACKUP_OFFERING_ASSIGN = "BACKUP.OFFERING.ASSIGN";
634639
public static final String EVENT_VM_BACKUP_OFFERING_REMOVE = "BACKUP.OFFERING.REMOVE";
635640
public static final String EVENT_VM_BACKUP_CREATE = "BACKUP.CREATE";
@@ -1045,11 +1050,13 @@ public class EventTypes {
10451050

10461051
// Service Offerings
10471052
entityEventDetails.put(EVENT_SERVICE_OFFERING_CREATE, ServiceOffering.class);
1053+
entityEventDetails.put(EVENT_SERVICE_OFFERING_CLONE, ServiceOffering.class);
10481054
entityEventDetails.put(EVENT_SERVICE_OFFERING_EDIT, ServiceOffering.class);
10491055
entityEventDetails.put(EVENT_SERVICE_OFFERING_DELETE, ServiceOffering.class);
10501056

10511057
// Disk Offerings
10521058
entityEventDetails.put(EVENT_DISK_OFFERING_CREATE, DiskOffering.class);
1059+
entityEventDetails.put(EVENT_DISK_OFFERING_CLONE, DiskOffering.class);
10531060
entityEventDetails.put(EVENT_DISK_OFFERING_EDIT, DiskOffering.class);
10541061
entityEventDetails.put(EVENT_DISK_OFFERING_DELETE, DiskOffering.class);
10551062

@@ -1070,6 +1077,7 @@ public class EventTypes {
10701077

10711078
// Network offerings
10721079
entityEventDetails.put(EVENT_NETWORK_OFFERING_CREATE, NetworkOffering.class);
1080+
entityEventDetails.put(EVENT_NETWORK_OFFERING_CLONE, NetworkOffering.class);
10731081
entityEventDetails.put(EVENT_NETWORK_OFFERING_ASSIGN, NetworkOffering.class);
10741082
entityEventDetails.put(EVENT_NETWORK_OFFERING_EDIT, NetworkOffering.class);
10751083
entityEventDetails.put(EVENT_NETWORK_OFFERING_REMOVE, NetworkOffering.class);

api/src/main/java/com/cloud/network/vpc/VpcProvisioningService.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.List;
2121
import java.util.Map;
2222

23+
import org.apache.cloudstack.api.command.admin.vpc.CloneVPCOfferingCmd;
2324
import org.apache.cloudstack.api.command.admin.vpc.CreateVPCOfferingCmd;
2425
import org.apache.cloudstack.api.command.admin.vpc.UpdateVPCOfferingCmd;
2526
import org.apache.cloudstack.api.command.user.vpc.ListVPCOfferingsCmd;
@@ -34,6 +35,8 @@ public interface VpcProvisioningService {
3435

3536
VpcOffering createVpcOffering(CreateVPCOfferingCmd cmd);
3637

38+
VpcOffering cloneVPCOffering(CloneVPCOfferingCmd cmd);
39+
3740
VpcOffering createVpcOffering(String name, String displayText, List<String> supportedServices,
3841
Map<String, List<String>> serviceProviders,
3942
Map serviceCapabilitystList, NetUtils.InternetProtocol internetProtocol,

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,7 @@ public class ApiConstants {
555555
public static final String USE_STORAGE_REPLICATION = "usestoragereplication";
556556

557557
public static final String SOURCE_CIDR_LIST = "sourcecidrlist";
558+
public static final String SOURCE_OFFERING_ID = "sourceofferingid";
558559
public static final String SOURCE_ZONE_ID = "sourcezoneid";
559560
public static final String SSL_VERIFICATION = "sslverification";
560561
public static final String START_ASN = "startasn";
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package org.apache.cloudstack.api.command.admin.backup;
18+
19+
import javax.inject.Inject;
20+
21+
import org.apache.cloudstack.acl.RoleType;
22+
import org.apache.cloudstack.api.APICommand;
23+
import org.apache.cloudstack.api.ApiConstants;
24+
import org.apache.cloudstack.api.ApiErrorCode;
25+
import org.apache.cloudstack.api.BaseAsyncCmd;
26+
import org.apache.cloudstack.api.BaseCmd;
27+
import org.apache.cloudstack.api.Parameter;
28+
import org.apache.cloudstack.api.ServerApiException;
29+
import org.apache.cloudstack.api.command.offering.DomainAndZoneIdResolver;
30+
import org.apache.cloudstack.api.response.BackupOfferingResponse;
31+
import org.apache.cloudstack.api.response.ZoneResponse;
32+
import org.apache.cloudstack.backup.BackupManager;
33+
import org.apache.cloudstack.backup.BackupOffering;
34+
import org.apache.cloudstack.context.CallContext;
35+
36+
import com.cloud.event.EventTypes;
37+
import com.cloud.exception.ConcurrentOperationException;
38+
import com.cloud.exception.InsufficientCapacityException;
39+
import com.cloud.exception.InvalidParameterValueException;
40+
import com.cloud.exception.NetworkRuleConflictException;
41+
import com.cloud.exception.ResourceAllocationException;
42+
import com.cloud.exception.ResourceUnavailableException;
43+
import com.cloud.utils.exception.CloudRuntimeException;
44+
45+
import java.util.Arrays;
46+
import java.util.List;
47+
import java.util.function.LongFunction;
48+
49+
@APICommand(name = "cloneBackupOffering",
50+
description = "Clones a backup offering from an existing offering",
51+
responseObject = BackupOfferingResponse.class, since = "4.23.0",
52+
authorized = {RoleType.Admin})
53+
public class CloneBackupOfferingCmd extends BaseAsyncCmd implements DomainAndZoneIdResolver {
54+
55+
@Inject
56+
protected BackupManager backupManager;
57+
58+
/////////////////////////////////////////////////////
59+
//////////////// API parameters /////////////////////
60+
////////////////////////////////////////////////////
61+
62+
@Parameter(name = ApiConstants.SOURCE_OFFERING_ID, type = BaseCmd.CommandType.UUID, entityType = BackupOfferingResponse.class,
63+
required = true, description = "The ID of the source backup offering to clone from")
64+
private Long sourceOfferingId;
65+
66+
@Parameter(name = ApiConstants.NAME, type = BaseCmd.CommandType.STRING, required = true,
67+
description = "The name of the cloned offering")
68+
private String name;
69+
70+
@Parameter(name = ApiConstants.DESCRIPTION, type = BaseCmd.CommandType.STRING, required = false,
71+
description = "The description of the cloned offering")
72+
private String description;
73+
74+
@Parameter(name = ApiConstants.EXTERNAL_ID, type = BaseCmd.CommandType.STRING, required = false,
75+
description = "The backup offering ID (from backup provider side)")
76+
private String externalId;
77+
78+
@Parameter(name = ApiConstants.ZONE_ID, type = BaseCmd.CommandType.UUID, entityType = ZoneResponse.class,
79+
description = "The zone ID", required = false)
80+
private Long zoneId;
81+
82+
@Parameter(name = ApiConstants.DOMAIN_ID,
83+
type = CommandType.STRING,
84+
description = "the ID of the containing domain(s) as comma separated string, public for public offerings",
85+
length = 4096)
86+
private String domainIds;
87+
88+
@Parameter(name = ApiConstants.ALLOW_USER_DRIVEN_BACKUPS, type = BaseCmd.CommandType.BOOLEAN,
89+
description = "Whether users are allowed to create adhoc backups and backup schedules", required = false)
90+
private Boolean userDrivenBackups;
91+
92+
/////////////////////////////////////////////////////
93+
/////////////////// Accessors ///////////////////////
94+
/////////////////////////////////////////////////////
95+
96+
public Long getSourceOfferingId() {
97+
return sourceOfferingId;
98+
}
99+
100+
public String getName() {
101+
return name;
102+
}
103+
104+
public String getExternalId() {
105+
return externalId;
106+
}
107+
108+
public Long getZoneId() {
109+
return zoneId;
110+
}
111+
112+
public String getDescription() {
113+
return description;
114+
}
115+
116+
public Boolean getUserDrivenBackups() {
117+
return userDrivenBackups;
118+
}
119+
120+
public List<Long> getDomainIds() {
121+
if (domainIds != null && !domainIds.isEmpty()) {
122+
return Arrays.asList(Arrays.stream(domainIds.split(",")).map(domainId -> Long.parseLong(domainId.trim())).toArray(Long[]::new));
123+
}
124+
LongFunction<List<Long>> defaultDomainsProvider = null;
125+
if (backupManager != null) {
126+
defaultDomainsProvider = backupManager::getBackupOfferingDomains;
127+
}
128+
return resolveDomainIds(domainIds, sourceOfferingId, defaultDomainsProvider, "backup offering");
129+
}
130+
131+
/////////////////////////////////////////////////////
132+
/////////////// API Implementation///////////////////
133+
/////////////////////////////////////////////////////
134+
135+
@Override
136+
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
137+
try {
138+
BackupOffering policy = backupManager.cloneBackupOffering(this);
139+
if (policy == null) {
140+
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to clone backup offering");
141+
}
142+
BackupOfferingResponse response = _responseGenerator.createBackupOfferingResponse(policy);
143+
response.setResponseName(getCommandName());
144+
setResponseObject(response);
145+
} catch (InvalidParameterValueException e) {
146+
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, e.getMessage());
147+
} catch (CloudRuntimeException e) {
148+
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
149+
}
150+
}
151+
152+
@Override
153+
public long getEntityOwnerId() {
154+
return CallContext.current().getCallingAccount().getId();
155+
}
156+
157+
@Override
158+
public String getEventType() {
159+
return EventTypes.EVENT_VM_BACKUP_OFFERING_CLONE;
160+
}
161+
162+
@Override
163+
public String getEventDescription() {
164+
return "Cloning backup offering: " + name + " from source offering: " + (sourceOfferingId == null ? "" : sourceOfferingId.toString());
165+
}
166+
}

api/src/main/java/org/apache/cloudstack/api/command/admin/backup/ImportBackupOfferingCmd.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
public class ImportBackupOfferingCmd extends BaseAsyncCmd {
5555

5656
@Inject
57-
private BackupManager backupManager;
57+
protected BackupManager backupManager;
5858

5959
/////////////////////////////////////////////////////
6060
//////////////// API parameters /////////////////////
@@ -86,7 +86,8 @@ public class ImportBackupOfferingCmd extends BaseAsyncCmd {
8686
type = CommandType.LIST,
8787
collectionType = CommandType.UUID,
8888
entityType = DomainResponse.class,
89-
description = "the ID of the containing domain(s), null for public offerings")
89+
description = "the ID of the containing domain(s), null for public offerings",
90+
since = "4.23.0")
9091
private List<Long> domainIds;
9192

9293
/////////////////////////////////////////////////////

0 commit comments

Comments
 (0)