diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiServerService.java b/api/src/main/java/org/apache/cloudstack/api/ApiServerService.java index 1f6d3d50375..54fda7e36b8 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiServerService.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiServerService.java @@ -42,6 +42,4 @@ public interface ApiServerService { public String handleRequest(Map params, String responseType, StringBuilder auditTrailSb) throws ServerApiException; public Class getCmdClass(String cmdName); - - public boolean isValidApiName(String apiName); } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/ImportRoleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/ImportRoleCmd.java index 3afac9fbea0..c5d9c3f99e6 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/ImportRoleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/ImportRoleCmd.java @@ -94,9 +94,6 @@ public class ImportRoleCmd extends RoleCmd { if (Strings.isNullOrEmpty(rule)) { throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Empty rule provided in rules param"); } - if (!rule.contains("*") && !_apiServer.isValidApiName(rule)) { - throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Invalid api name: " + rule + " provided in rules param"); - } ruleDetails.put(ApiConstants.RULE, new Rule(rule)); String permission = detail.get(ApiConstants.PERMISSION); diff --git a/engine/storage/src/main/java/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java b/engine/storage/src/main/java/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java index ac2c93567c3..08a3a3924d7 100644 --- a/engine/storage/src/main/java/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java +++ b/engine/storage/src/main/java/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java @@ -173,6 +173,7 @@ public class PrimaryDataStoreHelper { public DataStore attachZone(DataStore store) { StoragePoolVO pool = this.dataStoreDao.findById(store.getId()); + storageMgr.createCapacityEntry(pool.getId()); pool.setScope(ScopeType.ZONE); pool.setStatus(StoragePoolStatus.Up); this.dataStoreDao.update(pool.getId(), pool); @@ -181,6 +182,7 @@ public class PrimaryDataStoreHelper { public DataStore attachZone(DataStore store, HypervisorType hypervisor) { StoragePoolVO pool = this.dataStoreDao.findById(store.getId()); + storageMgr.createCapacityEntry(pool.getId()); pool.setScope(ScopeType.ZONE); pool.setHypervisor(hypervisor); pool.setStatus(StoragePoolStatus.Up); diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index fb2af6f57a5..42a1d30e9c3 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -2072,7 +2072,13 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa // Setup ROOT/DATA disk devices // for (DiskTO vol : sortedDisks) { - if (vol.getType() == Volume.Type.ISO || deployAsIs && vol.getType() == Volume.Type.ROOT) { + if (vol.getType() == Volume.Type.ISO) { + continue; + } + + if (deployAsIs && vol.getType() == Volume.Type.ROOT) { + rootDiskTO = vol; + resizeRootDiskOnVMStart(vmMo, rootDiskTO, hyperHost, context); continue; } diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java index b715f09d7b8..c771cf34561 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java @@ -31,6 +31,7 @@ import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.command.user.firewall.CreateFirewallRuleCmd; import org.apache.cloudstack.api.command.user.vm.StartVMCmd; +import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd; import org.apache.commons.codec.binary.Base64; import org.apache.commons.collections.CollectionUtils; import org.apache.log4j.Level; @@ -70,6 +71,10 @@ import com.cloud.network.rules.RulesService; import com.cloud.network.rules.dao.PortForwardingRulesDao; import com.cloud.offering.ServiceOffering; import com.cloud.resource.ResourceManager; +import com.cloud.storage.Volume; +import com.cloud.storage.VolumeApiService; +import com.cloud.storage.VolumeVO; +import com.cloud.storage.dao.VolumeDao; import com.cloud.user.Account; import com.cloud.user.SSHKeyPairVO; import com.cloud.uservm.UserVm; @@ -118,6 +123,10 @@ public class KubernetesClusterResourceModifierActionWorker extends KubernetesClu protected VMInstanceDao vmInstanceDao; @Inject protected UserVmManager userVmManager; + @Inject + protected VolumeApiService volumeService; + @Inject + protected VolumeDao volumeDao; protected String kubernetesClusterNodeNamePrefix; @@ -268,6 +277,29 @@ public class KubernetesClusterResourceModifierActionWorker extends KubernetesClu return plan(kubernetesCluster.getTotalNodeCount(), zone, offering); } + protected void resizeNodeVolume(final UserVm vm) throws ManagementServerException { + try { + if (vm.getHypervisorType() == Hypervisor.HypervisorType.VMware && templateDao.findById(vm.getTemplateId()).isDeployAsIs()) { + List vmVols = volumeDao.findByInstance(vm.getId()); + for (VolumeVO volumeVO : vmVols) { + if (volumeVO.getVolumeType() == Volume.Type.ROOT) { + ResizeVolumeCmd resizeVolumeCmd = new ResizeVolumeCmd(); + resizeVolumeCmd = ComponentContext.inject(resizeVolumeCmd); + Field f = resizeVolumeCmd.getClass().getDeclaredField("size"); + Field f1 = resizeVolumeCmd.getClass().getDeclaredField("id"); + f.setAccessible(true); + f1.setAccessible(true); + f1.set(resizeVolumeCmd, volumeVO.getId()); + f.set(resizeVolumeCmd, kubernetesCluster.getNodeRootDiskSize()); + volumeService.resizeVolume(resizeVolumeCmd); + } + } + } + } catch (IllegalAccessException | NoSuchFieldException e) { + throw new ManagementServerException(String.format("Failed to resize volume of VM in the Kubernetes cluster : %s", kubernetesCluster.getName()), e); + } + } + protected void startKubernetesVM(final UserVm vm) throws ManagementServerException { try { StartVMCmd startVm = new StartVMCmd(); @@ -275,6 +307,7 @@ public class KubernetesClusterResourceModifierActionWorker extends KubernetesClu Field f = startVm.getClass().getDeclaredField("id"); f.setAccessible(true); f.set(startVm, vm.getId()); + resizeNodeVolume(vm); userVmService.startVirtualMachine(startVm); if (LOGGER.isInfoEnabled()) { LOGGER.info(String.format("Started VM : %s in the Kubernetes cluster : %s", vm.getDisplayName(), kubernetesCluster.getName())); @@ -296,6 +329,7 @@ public class KubernetesClusterResourceModifierActionWorker extends KubernetesClu for (int i = offset + 1; i <= nodeCount; i++) { UserVm vm = createKubernetesNode(publicIpAddress, i); addKubernetesClusterVm(kubernetesCluster.getId(), vm.getId()); + resizeNodeVolume(vm); startKubernetesVM(vm); vm = userVmDao.findById(vm.getId()); if (vm == null) { diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java index 855c264d690..5855319ae67 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java @@ -277,6 +277,7 @@ public class KubernetesClusterStartWorker extends KubernetesClusterResourceModif UserVm k8sMasterVM = null; k8sMasterVM = createKubernetesMaster(network, publicIpAddress); addKubernetesClusterVm(kubernetesCluster.getId(), k8sMasterVM.getId()); + resizeNodeVolume(k8sMasterVM); startKubernetesVM(k8sMasterVM); k8sMasterVM = userVmDao.findById(k8sMasterVM.getId()); if (k8sMasterVM == null) { @@ -296,6 +297,7 @@ public class KubernetesClusterStartWorker extends KubernetesClusterResourceModif UserVm vm = null; vm = createKubernetesAdditionalMaster(publicIpAddress, i); addKubernetesClusterVm(kubernetesCluster.getId(), vm.getId()); + resizeNodeVolume(vm); startKubernetesVM(vm); vm = userVmDao.findById(vm.getId()); if (vm == null) { diff --git a/server/src/main/java/com/cloud/api/ApiServer.java b/server/src/main/java/com/cloud/api/ApiServer.java index 586d80b4745..cf0891fb606 100644 --- a/server/src/main/java/com/cloud/api/ApiServer.java +++ b/server/src/main/java/com/cloud/api/ApiServer.java @@ -1208,17 +1208,6 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer } } - @Override - public boolean isValidApiName(String apiName) { - if (apiName == null || apiName.isEmpty()) - return false; - - if (!s_apiNameCmdClassMap.containsKey(apiName)) - return false; - - return true; - } - // FIXME: rather than isError, we might was to pass in the status code to give more flexibility private void writeResponse(final HttpResponse resp, final String responseText, final int statusCode, final String responseType, final String reasonPhrase) { try { diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java index 6f362a7720f..a7be48f074e 100644 --- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java @@ -962,8 +962,15 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic } // if we are to use the existing disk offering + ImageFormat format = null; if (newDiskOffering == null) { - if (volume.getVolumeType().equals(Volume.Type.ROOT) && diskOffering.getDiskSize() > 0) { + Long templateId = volume.getTemplateId(); + if (templateId != null) { + VMTemplateVO template = _templateDao.findById(templateId); + format = template.getFormat(); + } + + if (volume.getVolumeType().equals(Volume.Type.ROOT) && diskOffering.getDiskSize() > 0 && format != null && format != ImageFormat.ISO) { throw new InvalidParameterValueException( "Failed to resize Root volume. The service offering of this Volume has been configured with a root disk size; " + "on such case a Root Volume can only be resized when changing to another Service Offering with a Root disk size. " diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index a3f818ad626..09b15bf5a81 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -145,6 +145,8 @@ import com.cloud.agent.api.to.deployasis.OVFPropertyTO; import com.cloud.agent.manager.Commands; import com.cloud.alert.AlertManager; import com.cloud.api.ApiDBUtils; +import com.cloud.api.query.dao.ServiceOfferingJoinDao; +import com.cloud.api.query.vo.ServiceOfferingJoinVO; import com.cloud.capacity.Capacity; import com.cloud.capacity.CapacityManager; import com.cloud.configuration.Config; @@ -512,7 +514,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir @Inject private UserVmDeployAsIsDetailsDao userVmDeployAsIsDetailsDao; @Inject - private StorageManager _storageManager; + private StorageManager storageManager; + @Inject + private ServiceOfferingJoinDao serviceOfferingJoinDao; private ScheduledExecutorService _executor = null; private ScheduledExecutorService _vmIpFetchExecutor = null; @@ -2051,7 +2055,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir if (poolType == StoragePoolType.PowerFlex) { // Get volume stats from the pool directly instead of sending cmd to host // Added support for ScaleIO/PowerFlex pool only - answer = _storageManager.getVolumeStats(storagePool, cmd); + answer = storageManager.getVolumeStats(storagePool, cmd); } else { if (timeout > 0) { cmd.setWait(timeout/1000); @@ -5313,9 +5317,21 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir throw new InvalidParameterValueException("Unable to use template " + templateId); } - // Bootmode and boottype are not supported on VMWare dpeloy-as-is templates (since 4.15) - if (template.isDeployAsIs() && (cmd.getBootMode() != null || cmd.getBootType() != null)) { - throw new InvalidParameterValueException("Boot type and boot mode are not supported on VMware, as we honour what is defined in the template."); + ServiceOfferingJoinVO svcOffering = serviceOfferingJoinDao.findById(serviceOfferingId); + + if (template.isDeployAsIs()) { + if (svcOffering != null && svcOffering.getRootDiskSize() != null && svcOffering.getRootDiskSize() > 0) { + throw new InvalidParameterValueException("Failed to deploy Virtual Machine as a service offering with root disk size specified cannot be used with a deploy as-is template"); + } + + if (cmd.getDetails().get("rootdisksize") != null) { + throw new InvalidParameterValueException("Overriding root disk size isn't supported for VMs deployed from defploy as-is templates"); + } + + // Bootmode and boottype are not supported on VMWare dpeloy-as-is templates (since 4.15) + if ((cmd.getBootMode() != null || cmd.getBootType() != null)) { + throw new InvalidParameterValueException("Boot type and boot mode are not supported on VMware, as we honour what is defined in the template."); + } } Long diskOfferingId = cmd.getDiskOfferingId(); @@ -6349,7 +6365,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir HypervisorType hypervisorType = _volsDao.getHypervisorType(volume.getId()); if (hypervisorType.equals(HypervisorType.VMware)) { try { - boolean isStoragePoolStoragepolicyComplaince = _storageManager.isStoragePoolComplaintWithStoragePolicy(Arrays.asList(volume), pool); + boolean isStoragePoolStoragepolicyComplaince = storageManager.isStoragePoolComplaintWithStoragePolicy(Arrays.asList(volume), pool); if (!isStoragePoolStoragepolicyComplaince) { throw new CloudRuntimeException(String.format("Storage pool %s is not storage policy compliance with the volume %s", pool.getUuid(), volume.getUuid())); } diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 80c3319f12d..28e99b0c141 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -2692,6 +2692,7 @@ "message.delete.vpn.customer.gateway": "Please confirm that you want to delete this VPN Customer Gateway", "message.delete.vpn.gateway": "Please confirm that you want to delete this VPN Gateway", "message.deleting.vm": "Deleting VM", +"message.deployasis": "Selected template is Deploy As-Is i.e., the VM is deployed by importing an OVA with vApps directly into vCenter. Root disk(s) resize is allowed only on stopped VMs for such templates.", "message.desc.add.new.lb.sticky.rule": "Add new LB sticky rule", "message.desc.advanced.zone": "For more sophisticated network topologies. This network model provides the most flexibility in defining guest networks and providing custom network offerings such as firewall, VPN, or load balancer support.", "message.desc.basic.zone": "Provide a single network where each VM instance is assigned an IP directly from the network. Guest isolation can be provided through layer-3 means such as security groups (IP address source filtering).", diff --git a/ui/src/components/view/ListResourceTable.vue b/ui/src/components/view/ListResourceTable.vue index c498d16e583..dea774c63e5 100644 --- a/ui/src/components/view/ListResourceTable.vue +++ b/ui/src/components/view/ListResourceTable.vue @@ -22,7 +22,8 @@ style="width: 25vw;float: right;margin-bottom: 10px; z-index: 8" :placeholder="$t('label.search')" v-model="filter" - @search="handleSearch" /> + @search="handleSearch" + autoFocus /> - - {{ $t('label.submit') }} - +
+ + {{ $t('label.cancel') }} + + + {{ $t('label.submit') }} + +
@@ -183,6 +188,9 @@ export default { this.selectedAccount = null this.fetchNetworks() }, + closeAction () { + this.$emit('close-action') + }, submitData () { let variableKey = '' let variableValue = '' @@ -255,6 +263,10 @@ export default { .submit-btn { margin-top: 10px; align-self: flex-end; + + button { + margin-left: 10px; + } } .required { diff --git a/ui/src/views/compute/AttachIso.vue b/ui/src/views/compute/AttachIso.vue index 947201171df..3c62c4cea21 100644 --- a/ui/src/views/compute/AttachIso.vue +++ b/ui/src/views/compute/AttachIso.vue @@ -26,7 +26,8 @@ v-decorator="['id', { initialValue: this.selectedIso, rules: [{ required: true, message: `${this.$t('label.required')}`}] - }]" > + }]" + autoFocus> {{ iso.displaytext || iso.name }} diff --git a/ui/src/views/compute/ChangeAffinity.vue b/ui/src/views/compute/ChangeAffinity.vue index 9482ccf15a7..d6bdc1b9cd1 100644 --- a/ui/src/views/compute/ChangeAffinity.vue +++ b/ui/src/views/compute/ChangeAffinity.vue @@ -29,7 +29,8 @@ style="margin-bottom: 10px;" :placeholder="$t('label.search')" v-model="filter" - @search="handleSearch" /> + @search="handleSearch" + autoFocus />
diff --git a/ui/src/views/compute/CreateKubernetesCluster.vue b/ui/src/views/compute/CreateKubernetesCluster.vue index 9759a5d9055..660505f22b8 100644 --- a/ui/src/views/compute/CreateKubernetesCluster.vue +++ b/ui/src/views/compute/CreateKubernetesCluster.vue @@ -33,7 +33,8 @@ v-decorator="['name', { rules: [{ required: true, message: $t('message.error.kubecluster.name') }] }]" - :placeholder="apiParams.name.description"/> + :placeholder="apiParams.name.description" + autoFocus /> diff --git a/ui/src/views/compute/CreateSSHKeyPair.vue b/ui/src/views/compute/CreateSSHKeyPair.vue index ba58a0ee79d..62a2bdf475c 100644 --- a/ui/src/views/compute/CreateSSHKeyPair.vue +++ b/ui/src/views/compute/CreateSSHKeyPair.vue @@ -28,7 +28,8 @@ v-decorator="['name', { rules: [{ required: true, message: $t('message.error.name') }] }]" - :placeholder="apiParams.name.description"/> + :placeholder="apiParams.name.description" + autoFocus /> + :placeholder="apiParams.volumeid.description" + autoFocus> diff --git a/ui/src/views/compute/DeployVM.vue b/ui/src/views/compute/DeployVM.vue index b2a5fee8bcb..ae8593a9ca3 100644 --- a/ui/src/views/compute/DeployVM.vue +++ b/ui/src/views/compute/DeployVM.vue @@ -41,6 +41,7 @@ :options="zoneSelectOptions" @change="onSelectZoneId" :loading="loading.zones" + autoFocus > {{ $t('label.override.rootdisk.size') }} - + +
{{ this.$t('message.deployasis') }}
@@ -543,6 +547,9 @@ :options="keyboardSelectOptions" > + + +
@@ -663,6 +670,7 @@ export default { podId: null, clusterId: null, zoneSelected: false, + startvm: true, vm: { name: null, zoneid: null, @@ -1419,6 +1427,9 @@ export default { if (values.hypervisor && values.hypervisor.length > 0) { deployVmData.hypervisor = values.hypervisor } + + deployVmData.startvm = values.startvm + // step 3: select service offering deployVmData.serviceofferingid = values.computeofferingid if (this.serviceOffering && this.serviceOffering.iscustomized) { diff --git a/ui/src/views/compute/DestroyVM.vue b/ui/src/views/compute/DestroyVM.vue index 638097d2947..f0dedee059d 100644 --- a/ui/src/views/compute/DestroyVM.vue +++ b/ui/src/views/compute/DestroyVM.vue @@ -44,7 +44,8 @@ v-decorator="['volumeids']" :placeholder="$t('label.delete.volumes')" mode="multiple" - :loading="loading"> + :loading="loading" + :autoFocus="$store.getters.userInfo.roletype !== 'Admin' && !$store.getters.features.allowuserexpungerecovervm"> {{ volume.name }} diff --git a/ui/src/views/compute/EditVM.vue b/ui/src/views/compute/EditVM.vue index ece9061f19e..c9f342ba392 100644 --- a/ui/src/views/compute/EditVM.vue +++ b/ui/src/views/compute/EditVM.vue @@ -30,7 +30,8 @@ + v-decorator="['name', { initialValue: resource.name || '' }]" + autoFocus /> diff --git a/ui/src/views/compute/InstanceTab.vue b/ui/src/views/compute/InstanceTab.vue index fd11d762c44..29a5cdedebd 100644 --- a/ui/src/views/compute/InstanceTab.vue +++ b/ui/src/views/compute/InstanceTab.vue @@ -165,7 +165,7 @@ {{ $t('message.network.addvm.desc') }} @@ -218,7 +220,7 @@ {{ $t('message.network.secondaryip') }}

- +
{{ $t('label.add.secondary.ip') }} {{ $t('label.close') }} diff --git a/ui/src/views/compute/MigrateWizard.vue b/ui/src/views/compute/MigrateWizard.vue index f34a778fe1c..3b28972ae5c 100644 --- a/ui/src/views/compute/MigrateWizard.vue +++ b/ui/src/views/compute/MigrateWizard.vue @@ -21,7 +21,8 @@ :placeholder="$t('label.search')" v-model="searchQuery" style="margin-bottom: 10px;" - @search="fetchData" /> + @search="fetchData" + autoFocus /> + :placeholder="apiParams.size.description" + autoFocus /> diff --git a/ui/src/views/compute/StartVirtualMachine.vue b/ui/src/views/compute/StartVirtualMachine.vue index 4fec9913cc9..5be132ac808 100644 --- a/ui/src/views/compute/StartVirtualMachine.vue +++ b/ui/src/views/compute/StartVirtualMachine.vue @@ -43,7 +43,8 @@ }" :loading="podsLoading" :placeholder="apiParams.podid.description" - @change="handlePodChange"> + @change="handlePodChange" + :autoFocus="this.$store.getters.userInfo.roletype === 'Admin'"> {{ pod.name }} diff --git a/ui/src/views/compute/UpgradeKubernetesCluster.vue b/ui/src/views/compute/UpgradeKubernetesCluster.vue index 18b51b21ca1..9d94e59919a 100644 --- a/ui/src/views/compute/UpgradeKubernetesCluster.vue +++ b/ui/src/views/compute/UpgradeKubernetesCluster.vue @@ -44,7 +44,8 @@ return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0 }" :loading="kubernetesVersionLoading" - :placeholder="apiParams.kubernetesversionid.description"> + :placeholder="apiParams.kubernetesversionid.description" + autoFocus > {{ opt.name || opt.description }} diff --git a/ui/src/views/compute/backup/FormSchedule.vue b/ui/src/views/compute/backup/FormSchedule.vue index c30b3e24158..e61efc8dfbb 100644 --- a/ui/src/views/compute/backup/FormSchedule.vue +++ b/ui/src/views/compute/backup/FormSchedule.vue @@ -61,7 +61,8 @@ rules: [{required: true, message: $t('message.error.required.input')}] }]" :min="1" - :max="59"/> + :max="59" + autoFocus /> diff --git a/ui/src/views/compute/wizard/ComputeOfferingSelection.vue b/ui/src/views/compute/wizard/ComputeOfferingSelection.vue index c372b821aef..117a7c062cd 100644 --- a/ui/src/views/compute/wizard/ComputeOfferingSelection.vue +++ b/ui/src/views/compute/wizard/ComputeOfferingSelection.vue @@ -21,7 +21,8 @@ style="width: 25vw;float: right;margin-bottom: 10px; z-index: 8" :placeholder="$t('label.search')" v-model="filter" - @search="handleSearch" /> + @search="handleSearch" + autoFocus /> [] }, + selectedTemplate: { + type: Object, + default: () => {} + }, rowCount: { type: Number, default: () => 0 @@ -161,6 +166,9 @@ export default { (item.iscustomized === true && maxMemory < this.minimumMemory))) { disabled = true } + if (this.selectedTemplate && this.selectedTemplate.hypervisor === 'VMware' && this.selectedTemplate.deployasis && item.rootdisksize) { + disabled = true + } return { key: item.id, name: item.name, @@ -238,6 +246,9 @@ export default { return { on: { click: () => { + if (record.disabled) { + return + } this.selectedRowKeys = [record.key] this.$emit('select-compute-item', record.key) } diff --git a/ui/src/views/compute/wizard/ComputeSelection.vue b/ui/src/views/compute/wizard/ComputeSelection.vue index 46a9f73dd9c..df178a8922d 100644 --- a/ui/src/views/compute/wizard/ComputeSelection.vue +++ b/ui/src/views/compute/wizard/ComputeSelection.vue @@ -35,6 +35,7 @@ @@ -48,6 +49,7 @@ :validate-status="errors.cpuspeed.status" :help="errors.cpuspeed.message"> diff --git a/ui/src/views/compute/wizard/DiskSizeSelection.vue b/ui/src/views/compute/wizard/DiskSizeSelection.vue index dcea64026f2..57e8e89b7f4 100644 --- a/ui/src/views/compute/wizard/DiskSizeSelection.vue +++ b/ui/src/views/compute/wizard/DiskSizeSelection.vue @@ -23,6 +23,7 @@ diff --git a/ui/src/views/compute/wizard/MultiDiskSelection.vue b/ui/src/views/compute/wizard/MultiDiskSelection.vue index 998fdbe7d3b..630d3b4652b 100644 --- a/ui/src/views/compute/wizard/MultiDiskSelection.vue +++ b/ui/src/views/compute/wizard/MultiDiskSelection.vue @@ -28,6 +28,7 @@ diff --git a/ui/src/views/compute/wizard/NetworkConfiguration.vue b/ui/src/views/compute/wizard/NetworkConfiguration.vue index 7bd17f4b69b..5a9c7ed0d1d 100644 --- a/ui/src/views/compute/wizard/NetworkConfiguration.vue +++ b/ui/src/views/compute/wizard/NetworkConfiguration.vue @@ -30,9 +30,10 @@
{{ text }}
{{ $t('label.cidr') + ': ' + record.cidr }} -