Skip to content

Commit cca8b2f

Browse files
Extensions Framework & Orchestrate Anything (#9752)
The Extensions Framework in Apache CloudStack is designed to provide a flexible and standardised mechanism for integrating external systems and custom workflows into CloudStack’s orchestration process. By defining structured hook points during key operations—such as virtual machine deployment, resource preparation, and lifecycle events—the framework allows administrators and developers to extend CloudStack’s behaviour without modifying its core codebase.
1 parent 217ff27 commit cca8b2f

File tree

259 files changed

+22833
-1175
lines changed

Some content is hidden

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

259 files changed

+22833
-1175
lines changed

.github/workflows/ci.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,10 @@ jobs:
8989
smoke/test_nested_virtualization
9090
smoke/test_set_sourcenat
9191
smoke/test_webhook_lifecycle
92-
smoke/test_purge_expunged_vms",
92+
smoke/test_purge_expunged_vms
93+
smoke/test_extension_lifecycle
94+
smoke/test_extension_custom_action_lifecycle
95+
smoke/test_extension_custom",
9396
"smoke/test_network
9497
smoke/test_network_acl
9598
smoke/test_network_ipv6

api/src/main/java/com/cloud/agent/api/Command.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@
1919
import java.util.HashMap;
2020
import java.util.Map;
2121

22-
import com.cloud.agent.api.LogLevel.Log4jLevel;
23-
import org.apache.logging.log4j.Logger;
2422
import org.apache.logging.log4j.LogManager;
23+
import org.apache.logging.log4j.Logger;
24+
25+
import com.cloud.agent.api.LogLevel.Log4jLevel;
2526

2627
/**
2728
* implemented by classes that extends the Command class. Command specifies
@@ -60,6 +61,7 @@ public enum State {
6061
private int wait; //in second
6162
private boolean bypassHostMaintenance = false;
6263
private transient long requestSequence = 0L;
64+
protected Map<String, Map<String, String>> externalDetails;
6365

6466
protected Command() {
6567
this.wait = 0;
@@ -128,6 +130,14 @@ public void setRequestSequence(long requestSequence) {
128130
this.requestSequence = requestSequence;
129131
}
130132

133+
public void setExternalDetails(Map<String, Map<String, String>> externalDetails) {
134+
this.externalDetails = externalDetails;
135+
}
136+
137+
public Map<String, Map<String, String>> getExternalDetails() {
138+
return externalDetails;
139+
}
140+
131141
@Override
132142
public boolean equals(Object o) {
133143
if (this == o) return true;

api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@
1919
import java.util.List;
2020
import java.util.Map;
2121
import java.util.HashMap;
22+
import java.util.stream.Collectors;
2223

2324
import com.cloud.agent.api.LogLevel;
2425
import com.cloud.network.element.NetworkElement;
2526
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
2627
import com.cloud.vm.VirtualMachine;
2728
import com.cloud.vm.VirtualMachine.Type;
29+
import com.cloud.vm.VmDetailConstants;
2830

2931
public class VirtualMachineTO {
3032
private long id;
@@ -496,4 +498,16 @@ public void setMetadataProductName(String metadataProductName) {
496498
public String toString() {
497499
return String.format("VM {id: \"%s\", name: \"%s\", uuid: \"%s\", type: \"%s\"}", id, name, uuid, type);
498500
}
501+
502+
public Map<String, String> getExternalDetails() {
503+
if (details == null) {
504+
return new HashMap<>();
505+
}
506+
return details.entrySet().stream()
507+
.filter(entry -> entry.getKey().startsWith(VmDetailConstants.EXTERNAL_DETAIL_PREFIX))
508+
.collect(Collectors.toMap(
509+
entry -> entry.getKey().substring(VmDetailConstants.EXTERNAL_DETAIL_PREFIX.length()),
510+
Map.Entry::getValue
511+
));
512+
}
499513
}

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

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,15 @@
2929
import org.apache.cloudstack.api.response.ZoneResponse;
3030
import org.apache.cloudstack.config.Configuration;
3131
import org.apache.cloudstack.datacenter.DataCenterIpv4GuestSubnet;
32+
import org.apache.cloudstack.extension.Extension;
33+
import org.apache.cloudstack.extension.ExtensionCustomAction;
3234
import org.apache.cloudstack.ha.HAConfig;
3335
import org.apache.cloudstack.network.BgpPeer;
3436
import org.apache.cloudstack.network.Ipv4GuestSubnetNetworkMap;
3537
import org.apache.cloudstack.quota.QuotaTariff;
36-
import org.apache.cloudstack.storage.sharedfs.SharedFS;
3738
import org.apache.cloudstack.storage.object.Bucket;
3839
import org.apache.cloudstack.storage.object.ObjectStore;
40+
import org.apache.cloudstack.storage.sharedfs.SharedFS;
3941
import org.apache.cloudstack.usage.Usage;
4042
import org.apache.cloudstack.vm.schedule.VMSchedule;
4143

@@ -806,6 +808,7 @@ public class EventTypes {
806808
// Management Server
807809
public static final String EVENT_MANAGEMENT_SERVER_REMOVE = "MANAGEMENT.SERVER.REMOVE";
808810

811+
// VM Lease
809812
public static final String VM_LEASE_EXPIRED = "VM.LEASE.EXPIRED";
810813
public static final String VM_LEASE_DISABLED = "VM.LEASE.DISABLED";
811814
public static final String VM_LEASE_CANCELLED = "VM.LEASE.CANCELLED";
@@ -816,6 +819,19 @@ public class EventTypes {
816819
public static final String EVENT_GUI_THEME_REMOVE = "GUI.THEME.REMOVE";
817820
public static final String EVENT_GUI_THEME_UPDATE = "GUI.THEME.UPDATE";
818821

822+
// Extension
823+
public static final String EVENT_EXTENSION_CREATE = "EXTENSION.CREATE";
824+
public static final String EVENT_EXTENSION_UPDATE = "EXTENSION.UPDATE";
825+
public static final String EVENT_EXTENSION_DELETE = "EXTENSION.DELETE";
826+
public static final String EVENT_EXTENSION_RESOURCE_REGISTER = "EXTENSION.RESOURCE.REGISTER";
827+
public static final String EVENT_EXTENSION_RESOURCE_UNREGISTER = "EXTENSION.RESOURCE.UNREGISTER";
828+
public static final String EVENT_EXTENSION_CUSTOM_ACTION_ADD = "EXTENSION.CUSTOM.ACTION.ADD";
829+
public static final String EVENT_EXTENSION_CUSTOM_ACTION_UPDATE = "EXTENSION.CUSTOM.ACTION.UPDATE";
830+
public static final String EVENT_EXTENSION_CUSTOM_ACTION_DELETE = "EXTENSION.CUSTOM.ACTION.DELETE";
831+
832+
// Custom Action
833+
public static final String EVENT_CUSTOM_ACTION = "CUSTOM.ACTION";
834+
819835
static {
820836

821837
// TODO: need a way to force author adding event types to declare the entity details as well, with out braking
@@ -1324,6 +1340,16 @@ public class EventTypes {
13241340
entityEventDetails.put(EVENT_GUI_THEME_CREATE, "GuiTheme");
13251341
entityEventDetails.put(EVENT_GUI_THEME_REMOVE, "GuiTheme");
13261342
entityEventDetails.put(EVENT_GUI_THEME_UPDATE, "GuiTheme");
1343+
1344+
// Extension
1345+
entityEventDetails.put(EVENT_EXTENSION_CREATE, Extension.class);
1346+
entityEventDetails.put(EVENT_EXTENSION_UPDATE, Extension.class);
1347+
entityEventDetails.put(EVENT_EXTENSION_DELETE, Extension.class);
1348+
entityEventDetails.put(EVENT_EXTENSION_RESOURCE_REGISTER, Extension.class);
1349+
entityEventDetails.put(EVENT_EXTENSION_RESOURCE_UNREGISTER, Extension.class);
1350+
entityEventDetails.put(EVENT_EXTENSION_CUSTOM_ACTION_ADD, ExtensionCustomAction.class);
1351+
entityEventDetails.put(EVENT_EXTENSION_CUSTOM_ACTION_UPDATE, ExtensionCustomAction.class);
1352+
entityEventDetails.put(EVENT_EXTENSION_CUSTOM_ACTION_DELETE, ExtensionCustomAction.class);
13271353
}
13281354

13291355
public static boolean isNetworkEvent(String eventType) {

api/src/main/java/com/cloud/hypervisor/Hypervisor.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public enum Functionality {
5454
public static final HypervisorType Ovm3 = new HypervisorType("Ovm3", ImageFormat.RAW);
5555
public static final HypervisorType LXC = new HypervisorType("LXC");
5656
public static final HypervisorType Custom = new HypervisorType("Custom", null, EnumSet.of(RootDiskSizeOverride));
57+
public static final HypervisorType External = new HypervisorType("External", null, EnumSet.of(RootDiskSizeOverride));
5758
public static final HypervisorType Any = new HypervisorType("Any"); /*If you don't care about the hypervisor type*/
5859
private final String name;
5960
private final ImageFormat imageFormat;

api/src/main/java/com/cloud/network/NetworkModel.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,8 @@ public interface NetworkModel {
305305

306306
NicProfile getNicProfile(VirtualMachine vm, long networkId, String broadcastUri);
307307

308+
NicProfile getNicProfile(VirtualMachine vm, Nic nic, DataCenter dataCenter);
309+
308310
Set<Long> getAvailableIps(Network network, String requestedIp);
309311

310312
String getDomainNetworkDomain(long domainId, long zoneId);

api/src/main/java/com/cloud/network/NetworkService.java

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

22-
import com.cloud.dc.DataCenter;
2322
import org.apache.cloudstack.acl.ControlledEntity;
2423
import org.apache.cloudstack.api.command.admin.address.ReleasePodIpCmdByAdmin;
2524
import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd;
@@ -39,13 +38,16 @@
3938
import org.apache.cloudstack.api.command.user.vm.ListNicsCmd;
4039
import org.apache.cloudstack.api.response.AcquirePodIpCmdResponse;
4140
import org.apache.cloudstack.framework.config.ConfigKey;
41+
import org.apache.cloudstack.network.element.InternalLoadBalancerElementService;
4242

43+
import com.cloud.agent.api.to.NicTO;
44+
import com.cloud.dc.DataCenter;
4345
import com.cloud.exception.ConcurrentOperationException;
4446
import com.cloud.exception.InsufficientAddressCapacityException;
4547
import com.cloud.exception.InsufficientCapacityException;
48+
import com.cloud.exception.InvalidParameterValueException;
4649
import com.cloud.exception.ResourceAllocationException;
4750
import com.cloud.exception.ResourceUnavailableException;
48-
import com.cloud.exception.InvalidParameterValueException;
4951
import com.cloud.network.Network.IpAddresses;
5052
import com.cloud.network.Network.Service;
5153
import com.cloud.network.Networks.TrafficType;
@@ -57,7 +59,6 @@
5759
import com.cloud.utils.exception.CloudRuntimeException;
5860
import com.cloud.vm.Nic;
5961
import com.cloud.vm.NicSecondaryIp;
60-
import org.apache.cloudstack.network.element.InternalLoadBalancerElementService;
6162

6263
/**
6364
* The NetworkService interface is the "public" api to entities that make requests to the orchestration engine
@@ -270,4 +271,6 @@ Network createPrivateNetwork(String networkName, String displayText, long physic
270271
List<InternalLoadBalancerElementService> getInternalLoadBalancerElements();
271272

272273
boolean handleCksIsoOnNetworkVirtualRouter(Long virtualRouterId, boolean mount) throws ResourceUnavailableException;
274+
275+
String getNicVlanValueForExternalVm(NicTO nic);
273276
}

api/src/main/java/com/cloud/network/nsx/NsxService.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@
1616
// under the License.
1717
package com.cloud.network.nsx;
1818

19+
import org.apache.cloudstack.framework.config.ConfigKey;
20+
1921
import com.cloud.network.IpAddress;
2022
import com.cloud.network.vpc.Vpc;
21-
import org.apache.cloudstack.framework.config.ConfigKey;
2223

2324
public interface NsxService {
2425

@@ -33,4 +34,5 @@ public interface NsxService {
3334

3435
boolean createVpcNetwork(Long zoneId, long accountId, long domainId, Long vpcId, String vpcName, boolean sourceNatEnabled);
3536
boolean updateVpcSourceNatIp(Vpc vpc, IpAddress address);
37+
String getSegmentId(long domainId, long accountId, long zoneId, Long vpcId, long networkId);
3638
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public static enum ImageFormat {
3030
OVA(true, true, true, "ova"),
3131
VHDX(true, true, true, "vhdx"),
3232
BAREMETAL(false, false, false, "BAREMETAL"),
33+
EXTERNAL(false, false, false, "EXTERNAL"),
3334
VMDK(true, true, false, "vmdk"),
3435
VDI(true, true, false, "vdi"),
3536
TAR(false, false, false, "tar"),

api/src/main/java/com/cloud/template/VirtualMachineTemplate.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,4 +153,6 @@ public enum TemplateFilter {
153153

154154
CPU.CPUArch getArch();
155155

156+
Long getExtensionId();
157+
156158
}

0 commit comments

Comments
 (0)