Skip to content

Commit 5a48a69

Browse files
abh1sardhslove
authored andcommitted
UI support for extraconfig in deploy and update instance (apache#11719)
1 parent 7072045 commit 5a48a69

9 files changed

Lines changed: 63 additions & 4 deletions

File tree

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public class ApiConstants {
2727
public static final String ACTIVATION_RULE = "activationrule";
2828
public static final String ACTIVITY = "activity";
2929
public static final String ADAPTER_TYPE = "adaptertype";
30+
public static final String ADDITONAL_CONFIG_ENABLED = "additionalconfigenabled";
3031
public static final String ADDRESS = "address";
3132
public static final String ALGORITHM = "algorithm";
3233
public static final String ALIAS = "alias";

api/src/main/java/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ public void execute() {
8383
response.setInstanceLeaseEnabled((Boolean) capabilities.get(ApiConstants.INSTANCE_LEASE_ENABLED));
8484
response.setExtensionsPath((String)capabilities.get(ApiConstants.EXTENSIONS_PATH));
8585
response.setDynamicScalingEnabled((Boolean) capabilities.get(ApiConstants.DYNAMIC_SCALING_ENABLED));
86+
response.setAdditionalConfigEnabled((Boolean) capabilities.get(ApiConstants.ADDITONAL_CONFIG_ENABLED));
8687
response.setObjectName("capability");
8788
response.setResponseName(getCommandName());
8889
this.setResponseObject(response);

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,10 @@ public class CapabilitiesResponse extends BaseResponse {
181181
@Param(description = "true if dynamically scaling for instances is enabled", since = "4.21.0")
182182
private Boolean dynamicScalingEnabled;
183183

184+
@SerializedName(ApiConstants.ADDITONAL_CONFIG_ENABLED)
185+
@Param(description = "true if additional configurations or extraconfig can be passed to Instances", since = "4.20.2")
186+
private Boolean additionalConfigEnabled;
187+
184188
public void setSecurityGroupsEnabled(boolean securityGroupsEnabled) {
185189
this.securityGroupsEnabled = securityGroupsEnabled;
186190
}
@@ -335,4 +339,8 @@ public void setExtensionsPath(String extensionsPath) {
335339
public void setDynamicScalingEnabled(Boolean dynamicScalingEnabled) {
336340
this.dynamicScalingEnabled = dynamicScalingEnabled;
337341
}
342+
343+
public void setAdditionalConfigEnabled(Boolean additionalConfigEnabled) {
344+
this.additionalConfigEnabled = additionalConfigEnabled;
345+
}
338346
}

server/src/main/java/com/cloud/server/ManagementServerImpl.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5164,6 +5164,8 @@ public Map<String, Object> listCapabilities(final ListCapabilitiesCmd cmd) {
51645164
if (isCallerAdmin) {
51655165
capabilities.put(ApiConstants.EXTENSIONS_PATH, extensionsManager.getExtensionsPath());
51665166
}
5167+
capabilities.put(ApiConstants.ADDITONAL_CONFIG_ENABLED, UserVmManager.EnableAdditionalVmConfig.valueIn(caller.getId()));
5168+
51675169

51685170
return capabilities;
51695171
}

server/src/main/java/com/cloud/vm/UserVmManager.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,15 @@ public interface UserVmManager extends UserVmService {
8585
ConfigKey<Boolean> EnableVmNetwokFilterAllowAllTraffic = new ConfigKey<Boolean>("Advanced", Boolean.class, "enable.vm.network.filter.allow.all.traffic", "true",
8686
"If true, the network security feature is enabled when creating a virtual machine, tag: <filterref filter='allow-all-traffic'/> item is enabled.", true);
8787

88+
ConfigKey<Boolean> EnableAdditionalVmConfig = new ConfigKey<>(
89+
"Advanced",
90+
Boolean.class,
91+
"enable.additional.vm.configuration",
92+
"false",
93+
"allow additional arbitrary configuration to vm",
94+
true,
95+
ConfigKey.Scope.Account);
96+
8897
static final int MAX_USER_DATA_LENGTH_BYTES = 2048;
8998

9099
public static final String CKS_NODE = "cksnode";

server/src/main/java/com/cloud/vm/UserVmManagerImpl.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6765,7 +6765,7 @@ private void checkIfVolumeTemplateIsTheSameAsTheProvided(VolumeInfo volume, Long
67656765
protected void persistExtraConfigVmware(String decodedUrl, UserVm vm) {
67666766
boolean isValidConfig = isValidKeyValuePair(decodedUrl);
67676767
if (isValidConfig) {
6768-
String[] extraConfigs = decodedUrl.split("\\r?\\n");
6768+
String[] extraConfigs = decodedUrl.split("\\r?\\n+");
67696769
for (String cfg : extraConfigs) {
67706770
// Validate cfg against unsupported operations set by admin here
67716771
String[] allowedKeyList = VmwareAdditionalConfigAllowList.value().split(",");
@@ -6793,7 +6793,7 @@ protected void persistExtraConfigVmware(String decodedUrl, UserVm vm) {
67936793
protected void persistExtraConfigXenServer(String decodedUrl, UserVm vm) {
67946794
boolean isValidConfig = isValidKeyValuePair(decodedUrl);
67956795
if (isValidConfig) {
6796-
String[] extraConfigs = decodedUrl.split("\\r?\\n");
6796+
String[] extraConfigs = decodedUrl.split("\\r?\\n+");
67976797
int i = 1;
67986798
String extraConfigKey = ApiConstants.EXTRA_CONFIG + "-";
67996799
for (String cfg : extraConfigs) {
@@ -6873,8 +6873,8 @@ protected void persistExtraConfigKvm(String decodedUrl, UserVm vm) {
68736873
// validate config against denied cfg commands
68746874
validateKvmExtraConfig(decodedUrl, vm.getAccountId());
68756875
String[] extraConfigs = decodedUrl.split("\n\n");
6876+
int i = 1;
68766877
for (String cfg : extraConfigs) {
6877-
int i = 1;
68786878
String[] cfgParts = cfg.split("\n");
68796879
String extraConfigKey = ApiConstants.EXTRA_CONFIG;
68806880
String extraConfigValue;

ui/public/locales/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,8 @@
10731073
"label.externalid": "External Id",
10741074
"label.externalloadbalanceripaddress": "External load balancer IP address.",
10751075
"label.extra": "Extra arguments",
1076+
"label.extraconfig": "Additional Configuration",
1077+
"label.extraconfig.tooltip": "Additional configuration parameters (extraconfig) to pass to the instance in plain text",
10761078
"label.f5": "F5",
10771079
"label.f5.ip.loadbalancer": "F5 BIG-IP load balancer.",
10781080
"label.failed": "Failed",

ui/src/views/compute/DeployVM.vue

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,12 @@
762762
</div>
763763
</a-card>
764764
</a-form-item>
765+
<a-form-item v-if="extraConfigEnabled" name="extraconfig" ref="extraconfig">
766+
<template #label>
767+
<tooltip-label :title="$t('label.extraconfig')" :tooltip="$t('label.extraconfig.tooltip')"/>
768+
</template>
769+
<a-textarea v-model:value="form.extraconfig"/>
770+
</a-form-item>
765771
<a-form-item :label="$t('label.affinity.groups')">
766772
<affinity-group-selection
767773
:items="options.affinityGroups"
@@ -1510,6 +1516,9 @@ export default {
15101516
dynamicScalingVmConfigValue () {
15111517
return this.$store.getters.features.dynamicscalingenabled
15121518
},
1519+
extraConfigEnabled () {
1520+
return this.$store.getters.features.additionalconfigenabled
1521+
},
15131522
isCustomizedDiskIOPS () {
15141523
return this.diskSelected?.iscustomizediops || false
15151524
},
@@ -2323,6 +2332,9 @@ export default {
23232332
if (isUserdataAllowed && values.userdata && values.userdata.length > 0) {
23242333
deployVmData.userdata = this.$toBase64AndURIEncoded(values.userdata)
23252334
}
2335+
if (values.extraconfig && values.extraconfig.length > 0) {
2336+
deployVmData.extraconfig = encodeURIComponent(values.extraconfig)
2337+
}
23262338
// step 2: select template/iso
23272339
if (this.imageType === 'templateid') {
23282340
deployVmData.templateid = values.templateid

ui/src/views/compute/EditVM.vue

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@
9292
</a-textarea>
9393
</a-form-item>
9494
<a-form-item ref="securitygroupids" name="securitygroupids" :label="$t('label.security.groups')" v-if="securityGroupNetworkProviderUseThisVM">
95+
<a-form-item v-if="extraConfigEnabled">
96+
<template #label>
97+
<tooltip-label :title="$t('label.extraconfig')" :tooltip="$t('label.extraconfig.tooltip')"/>
98+
</template>
99+
<a-textarea v-model:value="form.extraconfig"/>
100+
</a-form-item>
101+
<a-form-item ref="securitygroupids" name="securitygroupids" :label="$t('label.security.groups')" v-if="securityGroupsEnabled">
95102
<a-select
96103
mode="multiple"
97104
v-model:value="form.securitygroupids"
@@ -204,6 +211,19 @@ export default {
204211
}
205212
}
206213
},
214+
computed: {
215+
extraConfigEnabled () {
216+
return this.$store.getters.features.additionalconfigenabled
217+
},
218+
combinedExtraConfig () {
219+
if (!this.extraConfigEnabled || !this.resource.details) return ''
220+
const configs = Object.keys(this.resource.details)
221+
.filter(key => key.startsWith('extraconfig-'))
222+
.map(key => this.resource.details[key] || '')
223+
.filter(val => val.trim())
224+
return configs.join('\n\n')
225+
}
226+
},
207227
beforeCreate () {
208228
this.apiParams = this.$getApiParams('updateVirtualMachine')
209229
},
@@ -224,7 +244,8 @@ export default {
224244
userdata: '',
225245
haenable: this.resource.haenable,
226246
leaseduration: this.resource.leaseduration,
227-
leaseexpiryaction: this.resource.leaseexpiryaction
247+
leaseexpiryaction: this.resource.leaseexpiryaction,
248+
extraconfig: this.combinedExtraConfig
228249
})
229250
this.rules = reactive({
230251
leaseduration: [this.naturalNumberRule]
@@ -404,6 +425,9 @@ export default {
404425
if (values.leaseexpiryaction !== undefined) {
405426
params.leaseexpiryaction = values.leaseexpiryaction
406427
}
428+
}
429+
if (values.extraconfig && values.extraconfig.length > 0) {
430+
params.extraconfig = encodeURIComponent(values.extraconfig)
407431
}
408432
this.loading = true
409433

0 commit comments

Comments
 (0)