Skip to content

Commit 4dfa38a

Browse files
nvazquezyadvr
authored andcommitted
plugins: Add Custom hypervisor minimal changes (apache#7692)
Design document: https://cwiki.apache.org/confluence/display/CLOUDSTACK/%5BDRAFT%5D+Minimal+changes+to+allow+new+dynamic+hypervisor+type%3A+Custom+Hypervisor This PR introduces the minimal changes to add a new hypervisor type (internally named Custom in the codebase, and configurable display name), allowing to write an external hypervisor plugin as a Custom Hypervisor to CloudStack The custom hypervisor name is set by the setting: 'hypervisor.custom.display.name'. The new hypervisor type does not affect the behaviour of any CloudStack operation, it simply introduces a new hypervisor type into the system. CloudStack does not have any means to dynamically add new hypervisor types. The hypervisor types are internally preset by an enum defined within the CloudStack codebase and unless a new version supports a new hypervisor it is not possible to add a host of a hypervisor that is not in part of the enum. It is possible to implement minimal changes in CloudStack to support a new hypervisor plugin that may be developed privately This PR is an initial work on allowing new dynamic hypervisor types (adds a new element to the HypervisorType enum, but allows variable display name for the hypervisor) Replace the HypervisorType from a fixed enum to an extensible registry mechanism, registered from the hypervisor plugin - The new hypervisor type is internally named 'Custom' to the CloudStack services (management server and agent services, database records). - A new global setting ‘hypervisor.custom.display.name’ allows administrators to set the display name of the hypervisor type. The display name will be shown in the CloudStack UI and API. - In case the ‘hypervisor.list’ setting contains the display name of the new hypervisor type, the setting value is automatically updated after the ‘hypervisor.custom.display.name’ setting is updated. - The new Custom hypervisor type supports: - Direct downloads (the ability to download templates into primary storage from the hypervisor hosts without using secondary storage) - Local storage (use hypervisor hosts local storage as primary storage) - Template format: RAW format (the templates to be registered on the new hypervisor type must be in RAW format) - The UI is also extended to display the new hypervisor type and the supported features listed above. - The above are the minimal changes for CloudStack to support the new hypervisor type, which can be tested by integrating the plugin codebase with this feature. This PR allows the cloud administrators to test custom hypervisor plugins implementations in CloudStack and easily integrate it into CloudStack as a new hypervisor type ("Custom"), reducing the implementation to only the hypervisor supported specific storage/networking and the hypervisor resource to communicate with the management server. - CloudStack admin should be able to create a zone for the new custom hypervisor and add clusters, hosts into the zone with normal operations - CloudStack users should be able to execute normal VMs/volumes/network/storage operations on VMs/volumes running on the custom hypervisor hosts (cherry picked from commit 8b5ba13) Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
1 parent fe50018 commit 4dfa38a

File tree

33 files changed

+271
-66
lines changed

33 files changed

+271
-66
lines changed

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public class Hypervisor {
2727
static Map<String, HypervisorType> hypervisorTypeMap;
2828
static Map<HypervisorType, ImageFormat> supportedImageFormatMap;
2929

30-
public static enum HypervisorType {
30+
public enum HypervisorType {
3131
None, //for storage hosts
3232
XenServer,
3333
KVM,
@@ -40,6 +40,7 @@ public static enum HypervisorType {
4040
Ovm,
4141
Ovm3,
4242
LXC,
43+
Custom,
4344

4445
Any; /*If you don't care about the hypervisor type*/
4546

@@ -57,6 +58,7 @@ public static enum HypervisorType {
5758
hypervisorTypeMap.put("lxc", HypervisorType.LXC);
5859
hypervisorTypeMap.put("any", HypervisorType.Any);
5960
hypervisorTypeMap.put("ovm3", HypervisorType.Ovm3);
61+
hypervisorTypeMap.put("custom", HypervisorType.Custom);
6062

6163
supportedImageFormatMap = new HashMap<>();
6264
supportedImageFormatMap.put(HypervisorType.XenServer, ImageFormat.VHD);
@@ -68,7 +70,19 @@ public static enum HypervisorType {
6870

6971
public static HypervisorType getType(String hypervisor) {
7072
return hypervisor == null ? HypervisorType.None :
71-
hypervisorTypeMap.getOrDefault(hypervisor.toLowerCase(Locale.ROOT), HypervisorType.None);
73+
(hypervisor.toLowerCase(Locale.ROOT).equalsIgnoreCase(
74+
HypervisorGuru.HypervisorCustomDisplayName.value()) ? Custom :
75+
hypervisorTypeMap.getOrDefault(hypervisor.toLowerCase(Locale.ROOT), HypervisorType.None));
76+
}
77+
78+
/**
79+
* Returns the display name of a hypervisor type in case the custom hypervisor is used,
80+
* using the 'hypervisor.custom.display.name' setting. Otherwise, returns hypervisor name
81+
*/
82+
public String getHypervisorDisplayName() {
83+
return !Hypervisor.HypervisorType.Custom.equals(this) ?
84+
this.toString() :
85+
HypervisorGuru.HypervisorCustomDisplayName.value();
7286
}
7387

7488
/**

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

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

2222
import org.apache.cloudstack.backup.Backup;
23+
import org.apache.cloudstack.framework.config.ConfigKey;
2324

2425
import com.cloud.agent.api.Command;
2526
import com.cloud.agent.api.to.NicTO;
@@ -35,6 +36,10 @@
3536

3637
public interface HypervisorGuru extends Adapter {
3738

39+
ConfigKey<String> HypervisorCustomDisplayName = new ConfigKey<>(String.class,
40+
"hypervisor.custom.display.name", ConfigKey.CATEGORY_ADVANCED, "Custom",
41+
"Display name for custom hypervisor", true, ConfigKey.Scope.Global, null);
42+
3843
HypervisorType getHypervisorType();
3944

4045
/**

api/src/main/java/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.util.List;
2424
import java.util.Map;
2525

26+
import com.cloud.hypervisor.HypervisorGuru;
2627
import org.apache.cloudstack.api.APICommand;
2728
import org.apache.cloudstack.api.ApiCommandResourceType;
2829
import org.apache.cloudstack.api.ApiConstants;
@@ -342,9 +343,11 @@ protected void validateParameters() {
342343
throw new ServerApiException(ApiErrorCode.PARAM_ERROR,
343344
"Parameter zoneids cannot combine all zones (-1) option with other zones");
344345

345-
if (isDirectDownload() && !getHypervisor().equalsIgnoreCase(Hypervisor.HypervisorType.KVM.toString())) {
346-
throw new ServerApiException(ApiErrorCode.PARAM_ERROR,
347-
"Parameter directdownload is only allowed for KVM templates");
346+
String customHypervisor = HypervisorGuru.HypervisorCustomDisplayName.value();
347+
if (isDirectDownload() && !(getHypervisor().equalsIgnoreCase(Hypervisor.HypervisorType.KVM.toString())
348+
|| getHypervisor().equalsIgnoreCase(customHypervisor))) {
349+
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, String.format("Parameter directdownload " +
350+
"is only allowed for KVM or %s templates", customHypervisor));
348351
}
349352

350353
if (!isDeployAsIs() && osTypeId == null) {

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424

2525
import com.cloud.host.Host;
2626
import com.cloud.host.Status;
27-
import com.cloud.hypervisor.Hypervisor.HypervisorType;
2827
import com.cloud.serializer.Param;
2928
import com.google.gson.annotations.SerializedName;
3029

@@ -84,7 +83,7 @@ public class HostForMigrationResponse extends BaseResponse {
8483

8584
@SerializedName(ApiConstants.HYPERVISOR)
8685
@Param(description = "the host hypervisor")
87-
private HypervisorType hypervisor;
86+
private String hypervisor;
8887

8988
@SerializedName("cpunumber")
9089
@Param(description = "the CPU number of the host")
@@ -295,7 +294,7 @@ public void setVersion(String version) {
295294
this.version = version;
296295
}
297296

298-
public void setHypervisor(HypervisorType hypervisor) {
297+
public void setHypervisor(String hypervisor) {
299298
this.hypervisor = hypervisor;
300299
}
301300

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929

3030
import com.cloud.host.Host;
3131
import com.cloud.host.Status;
32-
import com.cloud.hypervisor.Hypervisor.HypervisorType;
3332
import com.cloud.serializer.Param;
3433
import com.google.gson.annotations.SerializedName;
3534

@@ -89,7 +88,7 @@ public class HostResponse extends BaseResponseWithAnnotations {
8988

9089
@SerializedName(ApiConstants.HYPERVISOR)
9190
@Param(description = "the host hypervisor")
92-
private HypervisorType hypervisor;
91+
private String hypervisor;
9392

9493
@SerializedName("cpusockets")
9594
@Param(description = "the number of CPU sockets on the host")
@@ -335,7 +334,7 @@ public void setVersion(String version) {
335334
this.version = version;
336335
}
337336

338-
public void setHypervisor(HypervisorType hypervisor) {
337+
public void setHypervisor(String hypervisor) {
339338
this.hypervisor = hypervisor;
340339
}
341340

@@ -602,7 +601,7 @@ public String getVersion() {
602601
return version;
603602
}
604603

605-
public HypervisorType getHypervisor() {
604+
public String getHypervisor() {
606605
return hypervisor;
607606
}
608607

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import org.apache.cloudstack.api.BaseResponse;
2121
import org.apache.cloudstack.api.EntityReference;
2222

23-
import com.cloud.hypervisor.Hypervisor.HypervisorType;
2423
import com.cloud.hypervisor.HypervisorCapabilities;
2524
import com.cloud.serializer.Param;
2625
import com.google.gson.annotations.SerializedName;
@@ -37,7 +36,7 @@ public class HypervisorCapabilitiesResponse extends BaseResponse {
3736

3837
@SerializedName(ApiConstants.HYPERVISOR)
3938
@Param(description = "the hypervisor type")
40-
private HypervisorType hypervisor;
39+
private String hypervisor;
4140

4241
@SerializedName(ApiConstants.MAX_GUESTS_LIMIT)
4342
@Param(description = "the maximum number of guest vms recommended for this hypervisor")
@@ -83,11 +82,11 @@ public void setHypervisorVersion(String hypervisorVersion) {
8382
this.hypervisorVersion = hypervisorVersion;
8483
}
8584

86-
public HypervisorType getHypervisor() {
85+
public String getHypervisor() {
8786
return hypervisor;
8887
}
8988

90-
public void setHypervisor(HypervisorType hypervisor) {
89+
public void setHypervisor(String hypervisor) {
9190
this.hypervisor = hypervisor;
9291
}
9392

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import org.apache.cloudstack.api.BaseResponseWithTagInformation;
2626
import org.apache.cloudstack.api.EntityReference;
2727

28-
import com.cloud.hypervisor.Hypervisor;
2928
import com.cloud.serializer.Param;
3029
import com.cloud.vm.snapshot.VMSnapshot;
3130
import com.google.gson.annotations.SerializedName;
@@ -111,7 +110,7 @@ public class VMSnapshotResponse extends BaseResponseWithTagInformation implement
111110

112111
@SerializedName(ApiConstants.HYPERVISOR)
113112
@Param(description = "the type of hypervisor on which snapshot is stored")
114-
private Hypervisor.HypervisorType hypervisor;
113+
private String hypervisor;
115114

116115
public VMSnapshotResponse() {
117116
tags = new LinkedHashSet<ResourceTagResponse>();
@@ -266,11 +265,11 @@ public void setTags(Set<ResourceTagResponse> tags) {
266265
this.tags = tags;
267266
}
268267

269-
public Hypervisor.HypervisorType getHypervisor() {
268+
public String getHypervisor() {
270269
return hypervisor;
271270
}
272271

273-
public void setHypervisor(Hypervisor.HypervisorType hypervisor) {
272+
public void setHypervisor(String hypervisor) {
274273
this.hypervisor = hypervisor;
275274
}
276275
}

engine/schema/src/main/java/com/cloud/storage/GuestOSHypervisorVO.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import javax.persistence.Id;
2727
import javax.persistence.Table;
2828

29+
import com.cloud.hypervisor.Hypervisor;
2930
import com.cloud.utils.db.GenericDao;
3031

3132
@Entity
@@ -72,7 +73,7 @@ public String getHypervisorVersion() {
7273

7374
@Override
7475
public String getHypervisorType() {
75-
return hypervisorType;
76+
return Hypervisor.HypervisorType.getType(hypervisorType).toString();
7677
}
7778

7879
@Override

engine/storage/integration-test/src/test/resources/component.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,11 @@
121121
<property name="name" value="KVM Agent"/>
122122
</bean>
123123

124+
<bean id="CustomServerDiscoverer"
125+
class="com.cloud.hypervisor.discoverer.CustomServerDiscoverer">
126+
<property name="name" value="CustomHW Agent" />
127+
</bean>
128+
124129
<bean id="BareMetalDiscoverer" class="com.cloud.baremetal.BareMetalDiscoverer">
125130
<property name="name" value="Bare Metal Agent"/>
126131
</bean>

plugins/network-elements/dns-notifier/src/main/resources/components-example.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ under the License.
111111
<adapter name="XCP Agent" class="com.cloud.hypervisor.xenserver.discoverer.XcpServerDiscoverer"/>
112112
<adapter name="SecondaryStorage" class="com.cloud.storage.secondary.SecondaryStorageDiscoverer"/>
113113
<adapter name="KVM Agent" class="com.cloud.hypervisor.kvm.discoverer.KvmServerDiscoverer"/>
114+
<adapter name="CustomHW Agent" class="com.cloud.hypervisor.discoverer.CustomServerDiscoverer"/>
114115
<adapter name="Bare Metal Agent" class="com.cloud.baremetal.BareMetalDiscoverer"/>
115116
<adapter name="Ovm Discover" class="com.cloud.ovm.hypervisor.OvmDiscoverer" />
116117
</adapters>

0 commit comments

Comments
 (0)