Skip to content

Commit 25f556e

Browse files
harikrishna-patnaladhslove
authored andcommitted
Extensions Framework & Orchestrate Anything (apache#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 8122743 commit 25f556e

File tree

259 files changed

+22835
-1182
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

+22835
-1182
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;
@@ -505,4 +507,16 @@ public void setMetadataProductName(String metadataProductName) {
505507
public String toString() {
506508
return String.format("VM {id: \"%s\", name: \"%s\", uuid: \"%s\", type: \"%s\"}", id, name, uuid, type);
507509
}
510+
511+
public Map<String, String> getExternalDetails() {
512+
if (details == null) {
513+
return new HashMap<>();
514+
}
515+
return details.entrySet().stream()
516+
.filter(entry -> entry.getKey().startsWith(VmDetailConstants.EXTERNAL_DETAIL_PREFIX))
517+
.collect(Collectors.toMap(
518+
entry -> entry.getKey().substring(VmDetailConstants.EXTERNAL_DETAIL_PREFIX.length()),
519+
Map.Entry::getValue
520+
));
521+
}
508522
}

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

@@ -819,6 +821,7 @@ public class EventTypes {
819821
// Management Server
820822
public static final String EVENT_MANAGEMENT_SERVER_REMOVE = "MANAGEMENT.SERVER.REMOVE";
821823

824+
// VM Lease
822825
public static final String VM_LEASE_EXPIRED = "VM.LEASE.EXPIRED";
823826
public static final String VM_LEASE_DISABLED = "VM.LEASE.DISABLED";
824827
public static final String VM_LEASE_CANCELLED = "VM.LEASE.CANCELLED";
@@ -829,6 +832,19 @@ public class EventTypes {
829832
public static final String EVENT_GUI_THEME_REMOVE = "GUI.THEME.REMOVE";
830833
public static final String EVENT_GUI_THEME_UPDATE = "GUI.THEME.UPDATE";
831834

835+
// Extension
836+
public static final String EVENT_EXTENSION_CREATE = "EXTENSION.CREATE";
837+
public static final String EVENT_EXTENSION_UPDATE = "EXTENSION.UPDATE";
838+
public static final String EVENT_EXTENSION_DELETE = "EXTENSION.DELETE";
839+
public static final String EVENT_EXTENSION_RESOURCE_REGISTER = "EXTENSION.RESOURCE.REGISTER";
840+
public static final String EVENT_EXTENSION_RESOURCE_UNREGISTER = "EXTENSION.RESOURCE.UNREGISTER";
841+
public static final String EVENT_EXTENSION_CUSTOM_ACTION_ADD = "EXTENSION.CUSTOM.ACTION.ADD";
842+
public static final String EVENT_EXTENSION_CUSTOM_ACTION_UPDATE = "EXTENSION.CUSTOM.ACTION.UPDATE";
843+
public static final String EVENT_EXTENSION_CUSTOM_ACTION_DELETE = "EXTENSION.CUSTOM.ACTION.DELETE";
844+
845+
// Custom Action
846+
public static final String EVENT_CUSTOM_ACTION = "CUSTOM.ACTION";
847+
832848
static {
833849

834850
// TODO: need a way to force author adding event types to declare the entity details as well, with out braking
@@ -1344,6 +1360,16 @@ public class EventTypes {
13441360
entityEventDetails.put(EVENT_GUI_THEME_CREATE, "GuiTheme");
13451361
entityEventDetails.put(EVENT_GUI_THEME_REMOVE, "GuiTheme");
13461362
entityEventDetails.put(EVENT_GUI_THEME_UPDATE, "GuiTheme");
1363+
1364+
// Extension
1365+
entityEventDetails.put(EVENT_EXTENSION_CREATE, Extension.class);
1366+
entityEventDetails.put(EVENT_EXTENSION_UPDATE, Extension.class);
1367+
entityEventDetails.put(EVENT_EXTENSION_DELETE, Extension.class);
1368+
entityEventDetails.put(EVENT_EXTENSION_RESOURCE_REGISTER, Extension.class);
1369+
entityEventDetails.put(EVENT_EXTENSION_RESOURCE_UNREGISTER, Extension.class);
1370+
entityEventDetails.put(EVENT_EXTENSION_CUSTOM_ACTION_ADD, ExtensionCustomAction.class);
1371+
entityEventDetails.put(EVENT_EXTENSION_CUSTOM_ACTION_UPDATE, ExtensionCustomAction.class);
1372+
entityEventDetails.put(EVENT_EXTENSION_CUSTOM_ACTION_DELETE, ExtensionCustomAction.class);
13471373
}
13481374

13491375
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
@@ -309,6 +309,8 @@ default List<Long> listNetworksUsedByVm(long vmId) {
309309

310310
NicProfile getNicProfile(VirtualMachine vm, long networkId, String broadcastUri);
311311

312+
NicProfile getNicProfile(VirtualMachine vm, Nic nic, DataCenter dataCenter);
313+
312314
Set<Long> getAvailableIps(Network network, String requestedIp);
313315

314316
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
@@ -34,6 +34,7 @@ public static enum ImageFormat {
3434
OVA(true, true, true, "ova"),
3535
VHDX(true, true, true, "vhdx"),
3636
BAREMETAL(false, false, false, "BAREMETAL"),
37+
EXTERNAL(false, false, false, "EXTERNAL"),
3738
VMDK(true, true, false, "vmdk"),
3839
VDI(true, true, false, "vdi"),
3940
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)