This commit is contained in:
nvazquez 2026-01-27 02:00:20 -03:00
parent 5ade2b303f
commit 3fd969bc41
No known key found for this signature in database
GPG Key ID: 656E1BCC8CB54F84
6 changed files with 71 additions and 23 deletions

View File

@ -87,5 +87,3 @@ CALL `cloud`.`INSERT_EXTENSION_DETAIL_IF_NOT_EXISTS`('MaaS', 'orchestratorrequir
CALL `cloud`.`IDEMPOTENT_DROP_UNIQUE_KEY`('counter', 'uc_counter__provider__source__value');
CALL `cloud`.`IDEMPOTENT_ADD_UNIQUE_KEY`('cloud.counter', 'uc_counter__provider__source__value__removed', '(provider, source, value, removed)');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.vpc_offerings','conserve_mode', 'tinyint(1) unsigned NULL DEFAULT 1');

View File

@ -49,3 +49,6 @@ CREATE TABLE IF NOT EXISTS `cloud`.`webhook_filter` (
INDEX `i_webhook_filter__webhook_id`(`webhook_id`),
CONSTRAINT `fk_webhook_filter__webhook_id` FOREIGN KEY(`webhook_id`) REFERENCES `webhook`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.vpc_offerings','conserve_mode', 'tinyint(1) unsigned NULL DEFAULT 0');
UPDATE `cloud`.`vpc_offerings` SET conserve_mode=1 WHERE name='Default VPC offering';

View File

@ -30,6 +30,8 @@ import java.util.Set;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.network.vpc.VpcOfferingVO;
import com.cloud.network.vpc.dao.VpcOfferingDao;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Component;
@ -159,6 +161,8 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService,
IpAddressManager _ipAddrMgr;
@Inject
RoutedIpv4Manager routedIpv4Manager;
@Inject
VpcOfferingDao vpcOfferingDao;
private boolean _elbEnabled = false;
static Boolean rulesContinueOnErrFlag = true;
@ -400,6 +404,11 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService,
throw new InvalidParameterValueException("Unable to create firewall rule as cannot find network by id=" + newRule.getNetworkId());
}
boolean isNewRuleOnVpcNetwork = newRuleNetwork.getVpcId() != null;
boolean isVpcConserveModeEnabled = false;
if (isNewRuleOnVpcNetwork) {
VpcOfferingVO vpcOffering = vpcOfferingDao.findById(newRuleNetwork.getVpcId());
isVpcConserveModeEnabled = vpcOffering != null && vpcOffering.isConserveMode();
}
for (FirewallRuleVO rule : rules) {
if (rule.getId() == newRule.getId()) {
@ -448,9 +457,15 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService,
}
}
// Checking if the rule applied is to the same network that is passed in the rule. (except for VPC networks)
if (!isNewRuleOnVpcNetwork && rule.getNetworkId() != newRule.getNetworkId() && rule.getState() != State.Revoke) {
throw new NetworkRuleConflictException("New rule is for a different network than what's specified in rule " + rule.getXid());
// Checking if the rule applied is to the same network that is passed in the rule.
// (except for VPCs with conserve mode = true)
if ((!isNewRuleOnVpcNetwork || !isVpcConserveModeEnabled)
&& rule.getNetworkId() != newRule.getNetworkId() && rule.getState() != State.Revoke) {
String errMsg = String.format("New rule is for a different network than what's specified in rule %s", rule.getXid());
if (isNewRuleOnVpcNetwork) {
errMsg += String.format(" - VPC id=%s is not using conserve mode", newRuleNetwork.getVpcId());
}
throw new NetworkRuleConflictException(errMsg);
}
//Check for the ICMP protocol. This has to be done separately from other protocols as we need to check the ICMP codes and ICMP type also.

View File

@ -97,7 +97,7 @@
{{ $t('label.add') }}
</a-button>
</div>
<div class="form__item" v-else-if="newRule.autoscale === 'yes' && ('vpcid' in this.resource)">
<div class="form__item" v-else-if="newRule.autoscale === 'yes' && ('vpcid' in this.resource && !this.associatednetworkid)">
<div class="form__label" style="white-space: nowrap;">{{ $t('label.select.tier') }}</div>
<a-button :disabled="!('createLoadBalancerRule' in $store.getters.apis)" type="primary" @click="handleOpenAddNetworkModal">
{{ $t('label.add') }}
@ -487,10 +487,10 @@
>
<div @keyup.ctrl.enter="handleAddNewRule">
<span
v-if="'vpcid' in resource">
v-if="'vpcid' in resource && (!('associatednetworkid' in resource) || this.vpcConserveMode)">
<strong>{{ $t('label.select.tier') }} </strong>
<a-select
v-focus="'vpcid' in resource"
v-focus="'vpcid' in resource && (!('associatednetworkid' in resource) || this.vpcConserveMode)"
v-model:value="selectedTier"
@change="fetchVirtualMachines()"
:placeholder="$t('label.select.tier')"
@ -1022,7 +1022,8 @@ export default {
urlpath: '/'
},
healthMonitorLoading: false,
isNetrisZone: false
isNetrisZone: false,
vpcConserveMode: false
}
},
computed: {
@ -1079,10 +1080,24 @@ export default {
})
},
fetchData () {
this.fetchVpc()
this.fetchListTiers()
this.fetchLBRules()
this.fetchZone()
},
fetchVpc () {
if (!this.resource.vpcid) {
return
}
this.vpcConserveMode = false
getAPI('listVPCs', {
id: this.resource.vpcid
}).then(json => {
this.vpcConserveMode = json.listvpcsresponse?.vpc?.[0].vpcofferingconservemode || false
}).catch(error => {
this.$notifyError(error)
})
},
fetchListTiers () {
this.tiers.loading = true
@ -1830,7 +1845,7 @@ export default {
getAPI('listNics', {
virtualmachineid: e.target.value,
networkid: ('vpcid' in this.resource) ? this.selectedTier : this.resource.associatednetworkid
networkid: ('vpcid' in this.resource && (!('associatednetworkid' in this.resource) || this.vpcConserveMode)) ? this.selectedTier : this.resource.associatednetworkid
}).then(response => {
if (!response || !response.listnicsresponse || !response.listnicsresponse.nic[0]) return
const newItem = []
@ -1850,7 +1865,7 @@ export default {
this.vmCount = 0
this.vms = []
this.addVmModalLoading = true
const networkId = ('vpcid' in this.resource) ? this.selectedTier : this.resource.associatednetworkid
const networkId = ('vpcid' in this.resource && (!('associatednetworkid' in this.resource) || this.vpcConserveMode)) ? this.selectedTier : this.resource.associatednetworkid
if (!networkId) {
this.addVmModalLoading = false
return
@ -1999,7 +2014,7 @@ export default {
}
const networkId = this.selectedTierForAutoScaling != null ? this.selectedTierForAutoScaling
: ('vpcid' in this.resource) ? this.selectedTier : this.resource.associatednetworkid
: ('vpcid' in this.resource && !('associatednetworkid' in this.resource)) ? this.selectedTier : this.resource.associatednetworkid
postAPI('createLoadBalancerRule', {
openfirewall: false,
networkid: networkId,

View File

@ -216,10 +216,10 @@
@cancel="closeModal">
<div v-ctrl-enter="addRule">
<span
v-if="'vpcid' in resource">
v-if="'vpcid' in resource && (!('associatednetworkid' in resource) || this.vpcConserveMode)">
<strong>{{ $t('label.select.tier') }} </strong>
<a-select
:v-focus="'vpcid' in resource"
:v-focus="'vpcid' in resource && (!('associatednetworkid' in resource) || this.vpcConserveMode)"
v-model:value="selectedTier"
@change="fetchVirtualMachines()"
:placeholder="$t('label.select.tier')"
@ -467,7 +467,8 @@ export default {
vmPageSize: 10,
vmCount: 0,
searchQuery: null,
cidrlist: ''
cidrlist: '',
vpcConserveMode: false
}
},
computed: {
@ -504,9 +505,23 @@ export default {
})
},
fetchData () {
this.fetchVpc()
this.fetchListTiers()
this.fetchPFRules()
},
fetchVpc () {
if (!this.resource.vpcid) {
return
}
this.vpcConserveMode = false
getAPI('listVPCs', {
id: this.resource.vpcid
}).then(json => {
this.vpcConserveMode = json.listvpcsresponse?.vpc?.[0].vpcofferingconservemode || false
}).catch(error => {
this.$notifyError(error)
})
},
fetchListTiers () {
this.selectedTier = null
this.tiers.loading = true
@ -627,7 +642,7 @@ export default {
if (this.loading) return
this.loading = true
this.addVmModalVisible = false
const networkId = ('vpcid' in this.resource) ? this.selectedTier : this.resource.associatednetworkid
const networkId = ('vpcid' in this.resource && (!('associatednetworkid' in this.resource || this.vpcConserveMode))) ? this.selectedTier : this.resource.associatednetworkid
postAPI('createPortForwardingRule', {
...this.newRule,
ipaddressid: this.resource.id,
@ -785,7 +800,7 @@ export default {
this.newRule.virtualmachineid = e.target.value
getAPI('listNics', {
virtualmachineid: e.target.value,
networkId: ('vpcid' in this.resource) ? this.selectedTier : this.resource.associatednetworkid
networkId: ('vpcid' in this.resource && (!('associatednetworkid' in this.resource) || this.vpcConserveMode)) ? this.selectedTier : this.resource.associatednetworkid
}).then(response => {
if (!response.listnicsresponse.nic || response.listnicsresponse.nic.length < 1) return
const nic = response.listnicsresponse.nic[0]
@ -805,7 +820,7 @@ export default {
this.vmCount = 0
this.vms = []
this.addVmModalLoading = true
const networkId = ('vpcid' in this.resource) ? this.selectedTier : this.resource.associatednetworkid
const networkId = ('vpcid' in this.resource && (!('associatednetworkid' in this.resource) || this.vpcConserveMode)) ? this.selectedTier : this.resource.associatednetworkid
if (!networkId) {
this.addVmModalLoading = false
return

View File

@ -147,13 +147,15 @@ export default {
let tabs = this.$route.meta.tabs.filter(tab => tab.name !== 'firewall')
const network = await this.fetchNetwork()
if ((network && network.networkofferingconservemode) || !network && this.resource.issourcenat) {
if (network && network.networkofferingconservemode) {
this.tabs = tabs
return
} else if (this.resource.issourcenat) {
// VPC IPs with Source Nat have only VPN when conserve_mode = false
this.tabs = this.defaultTabs.concat(this.$route.meta.tabs.filter(tab => tab.name === 'vpn'))
return
} else {
// VPC IPs with source nat have only VPN when conserve mode = false
if (this.resource.issourcenat) {
this.tabs = this.defaultTabs.concat(this.$route.meta.tabs.filter(tab => tab.name === 'vpn'))
return
}
}
this.portFWRuleCount = await this.fetchPortFWRule()