diff --git a/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java index bcf2c6176efe..f46b946d50c1 100644 --- a/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java @@ -1079,6 +1079,11 @@ private void applyResolvedValuesToCommand(CloneVPCOfferingCmd cmd, VpcOfferingVO ConfigurationManagerImpl.setField(cmd, "specifyAsNumber", sourceOffering.isSpecifyAsNumber()); } + Boolean conserveModeFieldValue = getRawFieldValue(cmd, "conserveMode", Boolean.class); + if (conserveModeFieldValue == null) { + ConfigurationManagerImpl.setField(cmd, "conserveMode", sourceOffering.isConserveMode()); + } + if (cmd.getInternetProtocol() == null) { String internetProtocol = vpcOfferingDetailsDao.getDetail(sourceOffering.getId(), ApiConstants.INTERNET_PROTOCOL); if (internetProtocol != null) { diff --git a/ui/src/views/offering/CloneNetworkOffering.vue b/ui/src/views/offering/CloneNetworkOffering.vue index 0cd5e733b24f..4b4343a823d5 100644 --- a/ui/src/views/offering/CloneNetworkOffering.vue +++ b/ui/src/views/offering/CloneNetworkOffering.vue @@ -1228,12 +1228,7 @@ export default { }, handleSupportedServiceChange (service, checked, provider) { if (checked) { - const correctProvider = this.serviceProviderMap[service] - if (correctProvider && provider !== correctProvider) { - this.selectedServiceProviderMap[service] = correctProvider - } else { - this.selectedServiceProviderMap[service] = provider - } + this.selectedServiceProviderMap[service] = provider } else { delete this.selectedServiceProviderMap[service] } @@ -1294,6 +1289,10 @@ export default { params.guestiptype = values.guestiptype } + if (values.forvpc === true) { + params.forvpc = true + } + // Use composable for service capability params if (this.selectedServiceProviderMap != null) { buildServiceCapabilityParams(params, values, this.selectedServiceProviderMap, this.registeredServicePackages) diff --git a/ui/src/views/offering/CloneVpcOffering.vue b/ui/src/views/offering/CloneVpcOffering.vue index 6adbfafad611..67ea30856397 100644 --- a/ui/src/views/offering/CloneVpcOffering.vue +++ b/ui/src/views/offering/CloneVpcOffering.vue @@ -212,6 +212,12 @@ + + + + @@ -308,7 +314,6 @@ export default { return { selectedDomains: [], selectedZones: [], - isConserveMode: true, internetProtocolValue: 'ipv4', domains: [], domainLoading: false, @@ -405,7 +410,7 @@ export default { this.fetchZoneData() this.fetchIpv6NetworkOfferingConfiguration() this.fetchRoutedNetworkConfiguration() - this.fetchSupportedServiceData() + this.fetchSupportedServiceData(true) }, isAdmin () { return isAdmin() @@ -455,7 +460,7 @@ export default { this.zoneLoading = false }) }, - fetchSupportedServiceData () { + fetchSupportedServiceData (isInitialLoad = false) { this.supportedServiceLoading = true getAPI('listSupportedNetworkServices', {}).then(json => { const networkServices = json.listsupportednetworkservicesresponse.networkservice || [] @@ -491,7 +496,11 @@ export default { this.supportedServiceLoading = false this.$nextTick(() => { - this.populateFormFromResource() + if (isInitialLoad) { + this.populateFormFromResource() + } else { + this.syncServiceSelectionsForCurrentMode() + } }) }) }, @@ -656,6 +665,45 @@ export default { this.form.nsxsupportlb = Boolean(this.serviceProviderMap.Lb) } }, + syncServiceSelectionsForCurrentMode () { + const updatedServices = this.supportedServices.map(svc => { + const serviceCopy = { ...svc, provider: [...svc.provider] } + const providerName = this.selectedServiceProviderMap[serviceCopy.name] + + if (providerName) { + const providerIndex = serviceCopy.provider.findIndex(p => p.name === providerName) + if (providerIndex > 0) { + const targetProvider = serviceCopy.provider[providerIndex] + serviceCopy.provider.splice(providerIndex, 1) + serviceCopy.provider.unshift(targetProvider) + } + serviceCopy.defaultChecked = true + serviceCopy.selectedProvider = providerName + } else { + serviceCopy.defaultChecked = false + serviceCopy.selectedProvider = null + } + return serviceCopy + }) + this.supportedServices = updatedServices + + const availableNames = new Set(updatedServices.map(svc => svc.name)) + Object.keys(this.selectedServiceProviderMap).forEach(name => { + if (!availableNames.has(name)) { + delete this.selectedServiceProviderMap[name] + } + }) + + this.connectivityServiceChecked = Boolean(this.selectedServiceProviderMap.Connectivity) + this.sourceNatServiceChecked = Boolean(this.selectedServiceProviderMap.SourceNat) + + this.$nextTick(() => { + this.servicesReady = true + this.$nextTick(() => { + this.checkVpcVirtualRouterForServices() + }) + }) + }, async handleProviderChange (value) { this.provider = value if (this.provider === 'NSX') { @@ -682,12 +730,7 @@ export default { }, handleSupportedServiceChange (service, checked, provider) { if (checked) { - const correctProvider = this.serviceProviderMap[service] - if (correctProvider && provider !== correctProvider) { - this.selectedServiceProviderMap[service] = correctProvider - } else { - this.selectedServiceProviderMap[service] = provider - } + this.selectedServiceProviderMap[service] = provider } else { delete this.selectedServiceProviderMap[service] } @@ -818,6 +861,10 @@ export default { params.enable = values.enable } + if (values.conservemode !== undefined) { + params.conservemode = values.conservemode + } + this.loading = true postAPI('cloneVPCOffering', params).then(json => { this.$message.success(`${this.$t('message.success.clone.vpc.offering')} ${values.name}`)