mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
UI support for extraconfig in deploy and update instance (#11719)
This commit is contained in:
parent
30cb8c7a82
commit
70af55e848
@ -26,6 +26,7 @@ public class ApiConstants {
|
|||||||
public static final String ACTIVATION_RULE = "activationrule";
|
public static final String ACTIVATION_RULE = "activationrule";
|
||||||
public static final String ACTIVITY = "activity";
|
public static final String ACTIVITY = "activity";
|
||||||
public static final String ADAPTER_TYPE = "adaptertype";
|
public static final String ADAPTER_TYPE = "adaptertype";
|
||||||
|
public static final String ADDITONAL_CONFIG_ENABLED = "additionalconfigenabled";
|
||||||
public static final String ADDRESS = "address";
|
public static final String ADDRESS = "address";
|
||||||
public static final String ALGORITHM = "algorithm";
|
public static final String ALGORITHM = "algorithm";
|
||||||
public static final String ALIAS = "alias";
|
public static final String ALIAS = "alias";
|
||||||
|
|||||||
@ -73,6 +73,7 @@ public class ListCapabilitiesCmd extends BaseCmd {
|
|||||||
response.setSharedFsVmMinCpuCount((Integer)capabilities.get(ApiConstants.SHAREDFSVM_MIN_CPU_COUNT));
|
response.setSharedFsVmMinCpuCount((Integer)capabilities.get(ApiConstants.SHAREDFSVM_MIN_CPU_COUNT));
|
||||||
response.setSharedFsVmMinRamSize((Integer)capabilities.get(ApiConstants.SHAREDFSVM_MIN_RAM_SIZE));
|
response.setSharedFsVmMinRamSize((Integer)capabilities.get(ApiConstants.SHAREDFSVM_MIN_RAM_SIZE));
|
||||||
response.setDynamicScalingEnabled((Boolean) capabilities.get(ApiConstants.DYNAMIC_SCALING_ENABLED));
|
response.setDynamicScalingEnabled((Boolean) capabilities.get(ApiConstants.DYNAMIC_SCALING_ENABLED));
|
||||||
|
response.setAdditionalConfigEnabled((Boolean) capabilities.get(ApiConstants.ADDITONAL_CONFIG_ENABLED));
|
||||||
response.setObjectName("capability");
|
response.setObjectName("capability");
|
||||||
response.setResponseName(getCommandName());
|
response.setResponseName(getCommandName());
|
||||||
this.setResponseObject(response);
|
this.setResponseObject(response);
|
||||||
|
|||||||
@ -140,6 +140,10 @@ public class CapabilitiesResponse extends BaseResponse {
|
|||||||
@Param(description = "true if dynamically scaling for instances is enabled", since = "4.21.0")
|
@Param(description = "true if dynamically scaling for instances is enabled", since = "4.21.0")
|
||||||
private Boolean dynamicScalingEnabled;
|
private Boolean dynamicScalingEnabled;
|
||||||
|
|
||||||
|
@SerializedName(ApiConstants.ADDITONAL_CONFIG_ENABLED)
|
||||||
|
@Param(description = "true if additional configurations or extraconfig can be passed to Instances", since = "4.20.2")
|
||||||
|
private Boolean additionalConfigEnabled;
|
||||||
|
|
||||||
public void setSecurityGroupsEnabled(boolean securityGroupsEnabled) {
|
public void setSecurityGroupsEnabled(boolean securityGroupsEnabled) {
|
||||||
this.securityGroupsEnabled = securityGroupsEnabled;
|
this.securityGroupsEnabled = securityGroupsEnabled;
|
||||||
}
|
}
|
||||||
@ -255,4 +259,8 @@ public class CapabilitiesResponse extends BaseResponse {
|
|||||||
public void setDynamicScalingEnabled(Boolean dynamicScalingEnabled) {
|
public void setDynamicScalingEnabled(Boolean dynamicScalingEnabled) {
|
||||||
this.dynamicScalingEnabled = dynamicScalingEnabled;
|
this.dynamicScalingEnabled = dynamicScalingEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setAdditionalConfigEnabled(Boolean additionalConfigEnabled) {
|
||||||
|
this.additionalConfigEnabled = additionalConfigEnabled;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4535,6 +4535,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
|||||||
}
|
}
|
||||||
capabilities.put(ApiConstants.SHAREDFSVM_MIN_CPU_COUNT, fsVmMinCpu);
|
capabilities.put(ApiConstants.SHAREDFSVM_MIN_CPU_COUNT, fsVmMinCpu);
|
||||||
capabilities.put(ApiConstants.SHAREDFSVM_MIN_RAM_SIZE, fsVmMinRam);
|
capabilities.put(ApiConstants.SHAREDFSVM_MIN_RAM_SIZE, fsVmMinRam);
|
||||||
|
capabilities.put(ApiConstants.ADDITONAL_CONFIG_ENABLED, UserVmManager.EnableAdditionalVmConfig.valueIn(caller.getId()));
|
||||||
|
|
||||||
|
|
||||||
return capabilities;
|
return capabilities;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -83,6 +83,15 @@ public interface UserVmManager extends UserVmService {
|
|||||||
"If set to true, tags specified in `resource.limit.host.tags` are also included in vm.strict.host.tags.",
|
"If set to true, tags specified in `resource.limit.host.tags` are also included in vm.strict.host.tags.",
|
||||||
true);
|
true);
|
||||||
|
|
||||||
|
ConfigKey<Boolean> EnableAdditionalVmConfig = new ConfigKey<>(
|
||||||
|
"Advanced",
|
||||||
|
Boolean.class,
|
||||||
|
"enable.additional.vm.configuration",
|
||||||
|
"false",
|
||||||
|
"allow additional arbitrary configuration to vm",
|
||||||
|
true,
|
||||||
|
ConfigKey.Scope.Account);
|
||||||
|
|
||||||
static final int MAX_USER_DATA_LENGTH_BYTES = 2048;
|
static final int MAX_USER_DATA_LENGTH_BYTES = 2048;
|
||||||
|
|
||||||
public static final String CKS_NODE = "cksnode";
|
public static final String CKS_NODE = "cksnode";
|
||||||
|
|||||||
@ -670,9 +670,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
private static final ConfigKey<Boolean> AllowDeployVmIfGivenHostFails = new ConfigKey<Boolean>("Advanced", Boolean.class, "allow.deploy.vm.if.deploy.on.given.host.fails", "false",
|
private static final ConfigKey<Boolean> AllowDeployVmIfGivenHostFails = new ConfigKey<Boolean>("Advanced", Boolean.class, "allow.deploy.vm.if.deploy.on.given.host.fails", "false",
|
||||||
"allow vm to deploy on different host if vm fails to deploy on the given host ", true);
|
"allow vm to deploy on different host if vm fails to deploy on the given host ", true);
|
||||||
|
|
||||||
private static final ConfigKey<Boolean> EnableAdditionalVmConfig = new ConfigKey<>("Advanced", Boolean.class,
|
|
||||||
"enable.additional.vm.configuration", "false", "allow additional arbitrary configuration to vm", true, ConfigKey.Scope.Account);
|
|
||||||
|
|
||||||
private static final ConfigKey<String> KvmAdditionalConfigAllowList = new ConfigKey<>(String.class,
|
private static final ConfigKey<String> KvmAdditionalConfigAllowList = new ConfigKey<>(String.class,
|
||||||
"allow.additional.vm.configuration.list.kvm", "Advanced", "", "Comma separated list of allowed additional configuration options.", true, ConfigKey.Scope.Account, null, null, EnableAdditionalVmConfig.key(), null, null, ConfigKey.Kind.CSV, null);
|
"allow.additional.vm.configuration.list.kvm", "Advanced", "", "Comma separated list of allowed additional configuration options.", true, ConfigKey.Scope.Account, null, null, EnableAdditionalVmConfig.key(), null, null, ConfigKey.Kind.CSV, null);
|
||||||
|
|
||||||
@ -6280,7 +6277,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
protected void persistExtraConfigVmware(String decodedUrl, UserVm vm) {
|
protected void persistExtraConfigVmware(String decodedUrl, UserVm vm) {
|
||||||
boolean isValidConfig = isValidKeyValuePair(decodedUrl);
|
boolean isValidConfig = isValidKeyValuePair(decodedUrl);
|
||||||
if (isValidConfig) {
|
if (isValidConfig) {
|
||||||
String[] extraConfigs = decodedUrl.split("\\r?\\n");
|
String[] extraConfigs = decodedUrl.split("\\r?\\n+");
|
||||||
for (String cfg : extraConfigs) {
|
for (String cfg : extraConfigs) {
|
||||||
// Validate cfg against unsupported operations set by admin here
|
// Validate cfg against unsupported operations set by admin here
|
||||||
String[] allowedKeyList = VmwareAdditionalConfigAllowList.value().split(",");
|
String[] allowedKeyList = VmwareAdditionalConfigAllowList.value().split(",");
|
||||||
@ -6308,7 +6305,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
protected void persistExtraConfigXenServer(String decodedUrl, UserVm vm) {
|
protected void persistExtraConfigXenServer(String decodedUrl, UserVm vm) {
|
||||||
boolean isValidConfig = isValidKeyValuePair(decodedUrl);
|
boolean isValidConfig = isValidKeyValuePair(decodedUrl);
|
||||||
if (isValidConfig) {
|
if (isValidConfig) {
|
||||||
String[] extraConfigs = decodedUrl.split("\\r?\\n");
|
String[] extraConfigs = decodedUrl.split("\\r?\\n+");
|
||||||
int i = 1;
|
int i = 1;
|
||||||
String extraConfigKey = ApiConstants.EXTRA_CONFIG + "-";
|
String extraConfigKey = ApiConstants.EXTRA_CONFIG + "-";
|
||||||
for (String cfg : extraConfigs) {
|
for (String cfg : extraConfigs) {
|
||||||
@ -6388,8 +6385,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
// validate config against denied cfg commands
|
// validate config against denied cfg commands
|
||||||
validateKvmExtraConfig(decodedUrl, vm.getAccountId());
|
validateKvmExtraConfig(decodedUrl, vm.getAccountId());
|
||||||
String[] extraConfigs = decodedUrl.split("\n\n");
|
String[] extraConfigs = decodedUrl.split("\n\n");
|
||||||
for (String cfg : extraConfigs) {
|
|
||||||
int i = 1;
|
int i = 1;
|
||||||
|
for (String cfg : extraConfigs) {
|
||||||
String[] cfgParts = cfg.split("\n");
|
String[] cfgParts = cfg.split("\n");
|
||||||
String extraConfigKey = ApiConstants.EXTRA_CONFIG;
|
String extraConfigKey = ApiConstants.EXTRA_CONFIG;
|
||||||
String extraConfigValue;
|
String extraConfigValue;
|
||||||
|
|||||||
@ -975,6 +975,8 @@
|
|||||||
"label.externalid": "External Id",
|
"label.externalid": "External Id",
|
||||||
"label.externalloadbalanceripaddress": "External load balancer IP address.",
|
"label.externalloadbalanceripaddress": "External load balancer IP address.",
|
||||||
"label.extra": "Extra arguments",
|
"label.extra": "Extra arguments",
|
||||||
|
"label.extraconfig": "Additional Configuration",
|
||||||
|
"label.extraconfig.tooltip": "Additional configuration parameters (extraconfig) to pass to the instance in plain text",
|
||||||
"label.f5": "F5",
|
"label.f5": "F5",
|
||||||
"label.f5.ip.loadbalancer": "F5 BIG-IP load balancer.",
|
"label.f5.ip.loadbalancer": "F5 BIG-IP load balancer.",
|
||||||
"label.failed": "Failed",
|
"label.failed": "Failed",
|
||||||
|
|||||||
@ -724,6 +724,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</a-card>
|
</a-card>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item v-if="extraConfigEnabled" name="extraconfig" ref="extraconfig">
|
||||||
|
<template #label>
|
||||||
|
<tooltip-label :title="$t('label.extraconfig')" :tooltip="$t('label.extraconfig.tooltip')"/>
|
||||||
|
</template>
|
||||||
|
<a-textarea v-model:value="form.extraconfig"/>
|
||||||
|
</a-form-item>
|
||||||
<a-form-item :label="$t('label.affinity.groups')">
|
<a-form-item :label="$t('label.affinity.groups')">
|
||||||
<affinity-group-selection
|
<affinity-group-selection
|
||||||
:items="options.affinityGroups"
|
:items="options.affinityGroups"
|
||||||
@ -1418,6 +1424,9 @@ export default {
|
|||||||
dynamicScalingVmConfigValue () {
|
dynamicScalingVmConfigValue () {
|
||||||
return this.$store.getters.features.dynamicscalingenabled
|
return this.$store.getters.features.dynamicscalingenabled
|
||||||
},
|
},
|
||||||
|
extraConfigEnabled () {
|
||||||
|
return this.$store.getters.features.additionalconfigenabled
|
||||||
|
},
|
||||||
isCustomizedDiskIOPS () {
|
isCustomizedDiskIOPS () {
|
||||||
return this.diskSelected?.iscustomizediops || false
|
return this.diskSelected?.iscustomizediops || false
|
||||||
},
|
},
|
||||||
@ -2054,6 +2063,9 @@ export default {
|
|||||||
if (isUserdataAllowed && values.userdata && values.userdata.length > 0) {
|
if (isUserdataAllowed && values.userdata && values.userdata.length > 0) {
|
||||||
deployVmData.userdata = this.$toBase64AndURIEncoded(values.userdata)
|
deployVmData.userdata = this.$toBase64AndURIEncoded(values.userdata)
|
||||||
}
|
}
|
||||||
|
if (values.extraconfig && values.extraconfig.length > 0) {
|
||||||
|
deployVmData.extraconfig = encodeURIComponent(values.extraconfig)
|
||||||
|
}
|
||||||
// step 2: select template/iso
|
// step 2: select template/iso
|
||||||
if (this.tabKey === 'templateid') {
|
if (this.tabKey === 'templateid') {
|
||||||
deployVmData.templateid = values.templateid
|
deployVmData.templateid = values.templateid
|
||||||
|
|||||||
@ -91,6 +91,12 @@
|
|||||||
<a-textarea v-model:value="form.userdata">
|
<a-textarea v-model:value="form.userdata">
|
||||||
</a-textarea>
|
</a-textarea>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item v-if="extraConfigEnabled">
|
||||||
|
<template #label>
|
||||||
|
<tooltip-label :title="$t('label.extraconfig')" :tooltip="$t('label.extraconfig.tooltip')"/>
|
||||||
|
</template>
|
||||||
|
<a-textarea v-model:value="form.extraconfig"/>
|
||||||
|
</a-form-item>
|
||||||
<a-form-item ref="securitygroupids" name="securitygroupids" :label="$t('label.security.groups')" v-if="securityGroupsEnabled">
|
<a-form-item ref="securitygroupids" name="securitygroupids" :label="$t('label.security.groups')" v-if="securityGroupsEnabled">
|
||||||
<a-select
|
<a-select
|
||||||
mode="multiple"
|
mode="multiple"
|
||||||
@ -167,6 +173,19 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
extraConfigEnabled () {
|
||||||
|
return this.$store.getters.features.additionalconfigenabled
|
||||||
|
},
|
||||||
|
combinedExtraConfig () {
|
||||||
|
if (!this.extraConfigEnabled || !this.resource.details) return ''
|
||||||
|
const configs = Object.keys(this.resource.details)
|
||||||
|
.filter(key => key.startsWith('extraconfig-'))
|
||||||
|
.map(key => this.resource.details[key] || '')
|
||||||
|
.filter(val => val.trim())
|
||||||
|
return configs.join('\n\n')
|
||||||
|
}
|
||||||
|
},
|
||||||
beforeCreate () {
|
beforeCreate () {
|
||||||
this.apiParams = this.$getApiParams('updateVirtualMachine')
|
this.apiParams = this.$getApiParams('updateVirtualMachine')
|
||||||
},
|
},
|
||||||
@ -185,7 +204,8 @@ export default {
|
|||||||
deleteprotection: this.resource.deleteprotection,
|
deleteprotection: this.resource.deleteprotection,
|
||||||
group: this.resource.group,
|
group: this.resource.group,
|
||||||
userdata: '',
|
userdata: '',
|
||||||
haenable: this.resource.haenable
|
haenable: this.resource.haenable,
|
||||||
|
extraconfig: this.combinedExtraConfig
|
||||||
})
|
})
|
||||||
this.rules = reactive({})
|
this.rules = reactive({})
|
||||||
},
|
},
|
||||||
@ -342,6 +362,9 @@ export default {
|
|||||||
if (values.userdata && values.userdata.length > 0) {
|
if (values.userdata && values.userdata.length > 0) {
|
||||||
params.userdata = this.$toBase64AndURIEncoded(values.userdata)
|
params.userdata = this.$toBase64AndURIEncoded(values.userdata)
|
||||||
}
|
}
|
||||||
|
if (values.extraconfig && values.extraconfig.length > 0) {
|
||||||
|
params.extraconfig = encodeURIComponent(values.extraconfig)
|
||||||
|
}
|
||||||
this.loading = true
|
this.loading = true
|
||||||
|
|
||||||
api('updateVirtualMachine', {}, 'POST', params).then(json => {
|
api('updateVirtualMachine', {}, 'POST', params).then(json => {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user