Skip to content
Draft
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,7 @@ public boolean configure(final String name, final Map<String, Object> params) th
defaultVPCOffProviders.put(Service.StaticNat, defaultProviders);
defaultVPCOffProviders.put(Service.PortForwarding, defaultProviders);
defaultVPCOffProviders.put(Service.Vpn, defaultProviders);
defaultVPCOffProviders.put(Service.Firewall, defaultProviders);

Transaction.execute(new TransactionCallbackNoReturn() {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,15 @@
package com.cloud.upgrade.dao;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;

import com.cloud.network.vpc.VpcOffering;
import com.cloud.offering.NetworkOffering;
import com.cloud.utils.exception.CloudRuntimeException;

public class Upgrade42210to42300 extends DbUpgradeAbstractImpl implements DbUpgrade, DbUpgradeSystemVmTemplate {
Expand All @@ -42,4 +50,129 @@ public InputStream[] getPrepareScripts() {

return new InputStream[] {script};
}

@Override
public void performDataMigration(Connection conn) {
updateNetworkDefaultOfferingsForVPCWithFirewallService(conn);
updateVpcOfferingsWithFirewallService(conn);
}

private void updateNetworkDefaultOfferingsForVPCWithFirewallService(Connection conn) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if we should update the existing service offerings. IMO, it would be better to add new service offerings. This will change the behavior of a network after a network restart with cleanup.

logger.debug("Updating default Network offerings for VPC to add Firewall service with VpcVirtualRouter provider");

final List<String> defaultVpcOfferingUniqueNames = Arrays.asList(
NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworks,
NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworksNoLB,
NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworksWithInternalLB,
NetworkOffering.DEFAULT_NAT_NSX_OFFERING_FOR_VPC,
NetworkOffering.DEFAULT_ROUTED_NSX_OFFERING_FOR_VPC,
NetworkOffering.DEFAULT_NAT_NSX_OFFERING_FOR_VPC_WITH_ILB,
NetworkOffering.DEFAULT_ROUTED_NETRIS_OFFERING_FOR_VPC,
NetworkOffering.DEFAULT_NAT_NETRIS_OFFERING_FOR_VPC
);

try {
for (String uniqueName : defaultVpcOfferingUniqueNames) {
PreparedStatement pstmt = conn.prepareStatement("SELECT id FROM `cloud`.`network_offerings` WHERE unique_name = ?");
pstmt.setString(1, uniqueName);

ResultSet rs = pstmt.executeQuery();
if (!rs.next()) {
continue;
}

long offeringId = rs.getLong(1);
rs.close();
pstmt.close();

// Insert into ntwk_offering_service_map
pstmt = conn.prepareStatement("INSERT IGNORE INTO `cloud`.`ntwk_offering_service_map` " +
"(network_offering_id, service, provider, created) " +
"VALUES (?, 'Firewall', 'VpcVirtualRouter', now())");
pstmt.setLong(1, offeringId);
pstmt.executeUpdate();
pstmt.close();

// Update existing networks (ntwk_service_map)
pstmt = conn.prepareStatement("SELECT id FROM `cloud`.`networks` WHERE network_offering_id = ?");
pstmt.setLong(1, offeringId);

rs = pstmt.executeQuery();
while (rs.next()) {
long networkId = rs.getLong(1);
PreparedStatement insertService = conn.prepareStatement("INSERT INGORE INTO `cloud`.`ntwk_service_map` " +
"(network_id, service, provider, created) " +
"VALUES (?, 'Firewall', 'VpcVirtualRouter', now())");
insertService.setLong(1, networkId);
insertService.executeUpdate();
insertService.close();
}

rs.close();
pstmt.close();
}

} catch (SQLException e) {
logger.warn("Exception while updating VPC default offerings with Firewall service: " + e.getMessage(), e);
}
}

private void updateVpcOfferingsWithFirewallService(Connection conn) {
logger.debug("Updating default VPC offerings to add Firewall service with VpcVirtualRouter provider");

final List<String> vpcOfferingUniqueNames = Arrays.asList(
VpcOffering.defaultVPCOfferingName,
VpcOffering.defaultVPCNSOfferingName,
VpcOffering.redundantVPCOfferingName,
VpcOffering.DEFAULT_VPC_NAT_NSX_OFFERING_NAME,
VpcOffering.DEFAULT_VPC_ROUTE_NSX_OFFERING_NAME,
VpcOffering.DEFAULT_VPC_ROUTE_NETRIS_OFFERING_NAME,
VpcOffering.DEFAULT_VPC_NAT_NETRIS_OFFERING_NAME
);

try {
for (String uniqueName : vpcOfferingUniqueNames) {
PreparedStatement pstmt = conn.prepareStatement("SELECT id FROM `cloud`.`vpc_offerings` WHERE unique_name = ?");
pstmt.setString(1, uniqueName);

ResultSet rs = pstmt.executeQuery();
if (!rs.next()) {
continue;
}

long vpcOfferingId = rs.getLong(1);
rs.close();
pstmt.close();

// Insert into vpc_offering_service_map
pstmt = conn.prepareStatement("INSERT IGNORE INTO `cloud`.`vpc_offering_service_map` " +
"(vpc_offering_id, service, provider, created) " +
"VALUES (?, 'Firewall', 'VpcVirtualRouter', now())");
pstmt.setLong(1, vpcOfferingId);
pstmt.executeUpdate();
pstmt.close();

// Update existing VPCs
pstmt = conn.prepareStatement("SELECT id FROM `cloud`.`vpcs` WHERE vpc_offering_id = ?");
pstmt.setLong(1, vpcOfferingId);

rs = pstmt.executeQuery();
while (rs.next()) {
long vpcId = rs.getLong(1);
PreparedStatement insertService = conn.prepareStatement("INSERT IGNORE INTO `cloud`.`vpc_service_map` " +
"(vpc_id, service, provider, created) " +
"VALUES (?, 'Firewall', 'VpcVirtualRouter', now())");
insertService.setLong(1, vpcId);
insertService.executeUpdate();
insertService.close();
}

rs.close();
pstmt.close();
}

} catch (SQLException e) {
logger.warn("Exception while updating VPC offerings with Firewall service: " + e.getMessage(), e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2713,9 +2713,8 @@ private void createNetworkOfferingForKubernetes(String offeringName, String offe
defaultKubernetesServiceNetworkOfferingProviders.put(Service.UserData, provider);
if (forVpc) {
defaultKubernetesServiceNetworkOfferingProviders.put(Service.NetworkACL, forNsx ? Network.Provider.Nsx : provider);
} else {
defaultKubernetesServiceNetworkOfferingProviders.put(Service.Firewall, forNsx ? Network.Provider.Nsx : provider);
}
defaultKubernetesServiceNetworkOfferingProviders.put(Service.Firewall, Network.Provider.VPCVirtualRouter);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
defaultKubernetesServiceNetworkOfferingProviders.put(Service.Firewall, Network.Provider.VPCVirtualRouter);
defaultKubernetesServiceNetworkOfferingProviders.put(Service.Firewall, forNsx ? Network.Provider.Nsx : provider);

defaultKubernetesServiceNetworkOfferingProviders.put(Service.Lb, forNsx ? Network.Provider.Nsx : provider);
defaultKubernetesServiceNetworkOfferingProviders.put(Service.SourceNat, forNsx ? Network.Provider.Nsx : provider);
defaultKubernetesServiceNetworkOfferingProviders.put(Service.StaticNat, forNsx ? Network.Provider.Nsx : provider);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6727,7 +6727,7 @@ public NetworkOffering createNetworkOffering(final CreateNetworkOfferingCmd cmd)
}

if (forVpc == null) {
if (service == Service.SecurityGroup || service == Service.Firewall) {
if (service == Service.SecurityGroup) {
forVpc = false;
} else if (service == Service.NetworkACL) {
forVpc = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -412,10 +412,6 @@ private static Map<Service, Map<Capability, String>> setCapabilities() {
vpnCapabilities.putAll(capabilities.get(Service.Vpn));
vpnCapabilities.put(Capability.VpnTypes, "s2svpn");
capabilities.put(Service.Vpn, vpnCapabilities);

// remove firewall capability
capabilities.remove(Service.Firewall);

// add network ACL capability
final Map<Capability, String> networkACLCapabilities = new HashMap<Capability, String>();
networkACLCapabilities.put(Capability.SupportedProtocols, "tcp,udp,icmp");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis

private final ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("VpcChecker"));
private List<VpcProvider> vpcElements = null;
private final List<Service> nonSupportedServices = Arrays.asList(Service.SecurityGroup, Service.Firewall);
private final List<Service> nonSupportedServices = Arrays.asList(Service.SecurityGroup);
private final List<Provider> supportedProviders = Arrays.asList(Provider.VPCVirtualRouter, Provider.NiciraNvp, Provider.InternalLbVm, Provider.Netscaler,
Provider.JuniperContrailVpcRouter, Provider.Ovs, Provider.BigSwitchBcf, Provider.ConfigDrive, Provider.Nsx, Provider.Netris);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1134,6 +1134,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
defaultVpcNetworkOfferingProviders.put(Service.StaticNat, Provider.VPCVirtualRouter);
defaultVpcNetworkOfferingProviders.put(Service.PortForwarding, Provider.VPCVirtualRouter);
defaultVpcNetworkOfferingProviders.put(Service.Vpn, Provider.VPCVirtualRouter);
defaultVpcNetworkOfferingProviders.put(Service.Firewall, Provider.VPCVirtualRouter);

for (Map.Entry<Service,Provider> entry : defaultVpcNetworkOfferingProviders.entrySet()) {
NetworkOfferingServiceMapVO offService =
Expand Down Expand Up @@ -1161,6 +1162,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
defaultVpcNetworkOfferingProvidersNoLB.put(Service.StaticNat, Provider.VPCVirtualRouter);
defaultVpcNetworkOfferingProvidersNoLB.put(Service.PortForwarding, Provider.VPCVirtualRouter);
defaultVpcNetworkOfferingProvidersNoLB.put(Service.Vpn, Provider.VPCVirtualRouter);
defaultVpcNetworkOfferingProvidersNoLB.put(Service.Firewall, Provider.VPCVirtualRouter);

for (Map.Entry<Service,Provider> entry : defaultVpcNetworkOfferingProvidersNoLB.entrySet()) {
NetworkOfferingServiceMapVO offService =
Expand All @@ -1186,6 +1188,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
internalLbOffProviders.put(Service.Gateway, Provider.VPCVirtualRouter);
internalLbOffProviders.put(Service.Lb, Provider.InternalLbVm);
internalLbOffProviders.put(Service.SourceNat, Provider.VPCVirtualRouter);
internalLbOffProviders.put(Service.Firewall, Provider.VPCVirtualRouter);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about this. But if the LB is internal, the firewall will work only on public traffic for VPC Virtual router. Is this change required here?


for (Service service : internalLbOffProviders.keySet()) {
NetworkOfferingServiceMapVO offService = new NetworkOfferingServiceMapVO(internalLbOff.getId(), service, internalLbOffProviders.get(service));
Expand Down Expand Up @@ -1256,7 +1259,6 @@ private Map<Service, Provider> getServicesAndProvidersForProviderNetwork(Network
serviceProviderMap.put(Service.UserData, routerProvider);
if (forVpc) {
serviceProviderMap.put(Service.NetworkACL, provider);
} else {
serviceProviderMap.put(Service.Firewall, provider);
}
if (networkMode == NetworkOffering.NetworkMode.NATTED) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -989,15 +989,13 @@ public boolean applyRoutingFirewallRule(long id) {
@Override
public boolean isVirtualRouterGateway(Network network) {
return isRoutedNetwork(network)
&& (networkServiceMapDao.canProviderSupportServiceInNetwork(network.getId(), Service.Gateway, Provider.VirtualRouter))
|| networkServiceMapDao.canProviderSupportServiceInNetwork(network.getId(), Service.Gateway, Provider.VPCVirtualRouter);
&& (networkServiceMapDao.canProviderSupportServiceInNetwork(network.getId(), Service.Gateway, Provider.VirtualRouter));
}

@Override
public boolean isVirtualRouterGateway(NetworkOffering networkOffering) {
return NetworkOffering.NetworkMode.ROUTED.equals(networkOffering.getNetworkMode())
&& networkOfferingServiceMapDao.canProviderSupportServiceInNetworkOffering(networkOffering.getId(), Service.Gateway, Provider.VirtualRouter)
|| networkOfferingServiceMapDao.canProviderSupportServiceInNetworkOffering(networkOffering.getId(), Service.Gateway, Provider.VPCVirtualRouter);
&& networkOfferingServiceMapDao.canProviderSupportServiceInNetworkOffering(networkOffering.getId(), Service.Gateway, Provider.VirtualRouter);
}

@Override
Expand Down
4 changes: 2 additions & 2 deletions systemvm/debian/opt/cloud/bin/configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -705,8 +705,8 @@ def process(self):

for item in self.dbag:
if item == "id":
continue
if self.config.is_vpc():
continue
if self.config.is_vpc() and not ("purpose" in self.dbag[item] and self.dbag[item]["purpose"] == "Firewall"):
Comment on lines +708 to +709
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
continue
if self.config.is_vpc() and not ("purpose" in self.dbag[item] and self.dbag[item]["purpose"] == "Firewall"):
continue
if self.config.is_vpc() and not ("purpose" in self.dbag[item] and self.dbag[item]["purpose"] == "Firewall"):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not exactly sure about this change.

self.AclDevice(self.dbag[item], self.config).create()
else:
self.AclIP(self.dbag[item], self.config).create()
Expand Down
12 changes: 12 additions & 0 deletions systemvm/debian/opt/cloud/bin/cs/CsAddress.py
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,18 @@ def fw_vpcrouter(self):
(self.address['network'], self.address['network'])])

if self.get_type() in ["public"]:
# Add PREROUTING firewall chain jump for public IP
self.fw.append(["mangle", "front",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We seem to be adding this for all the VPC Offerings which might not have firewall as a supported service.

"-A PREROUTING " +
"-d %s/32 -j FIREWALL_%s" % (self.address['public_ip'], self.address['public_ip'])])

# Add the firewall chain with default DROP policy
self.fw.append(["mangle", "front",
"-A FIREWALL_%s " % self.address['public_ip'] +
"-m state --state RELATED,ESTABLISHED -j RETURN"])
self.fw.append(["mangle", "",
"-A FIREWALL_%s -j DROP" % self.address['public_ip']])

self.fw.append(
["mangle", "", "-A FORWARD -j VPN_STATS_%s" % self.dev])
self.fw.append(
Expand Down
18 changes: 10 additions & 8 deletions ui/src/views/network/PublicIpResource.vue
Original file line number Diff line number Diff line change
Expand Up @@ -135,22 +135,24 @@ export default {
return
}
if (this.resource && this.resource.vpcid) {
// VPC IPs with source nat have only VPN
// VPC IPs with source nat have VPN and Firewall
if (this.resource.issourcenat) {
this.tabs = this.defaultTabs.concat(this.$route.meta.tabs.filter(tab => tab.name === 'vpn'))
this.tabs = this.defaultTabs.concat(this.$route.meta.tabs.filter(tab => ['vpn', 'firewall'].includes(tab.name)))
return
}

// VPC IPs with static nat have nothing
// VPC IPs with static nat have firewall
if (this.resource.isstaticnat) {
if (this.resource.virtualmachinetype === 'DomainRouter') {
this.tabs = this.defaultTabs.concat(this.$route.meta.tabs.filter(tab => tab.name === 'vpn'))
this.tabs = this.defaultTabs.concat(this.$route.meta.tabs.filter(tab => ['vpn', 'firewall'].includes(tab.name)))
} else {
this.tabs = this.defaultTabs.concat(this.$route.meta.tabs.filter(tab => tab.name === 'firewall'))
}
return
}

// VPC IPs don't have firewall
let tabs = this.$route.meta.tabs.filter(tab => tab.name !== 'firewall')
// VPC IPs now have firewall support
let tabs = this.$route.meta.tabs

const network = await this.fetchNetwork()
if (network && network.networkofferingconservemode) {
Expand All @@ -161,12 +163,12 @@ export default {
this.portFWRuleCount = await this.fetchPortFWRule()
this.loadBalancerRuleCount = await this.fetchLoadBalancerRule()

// VPC IPs with PF only have PF
// VPC IPs with PF only have PF (and firewall)
if (this.portFWRuleCount > 0) {
tabs = tabs.filter(tab => tab.name !== 'loadbalancing')
}

// VPC IPs with LB rules only have LB
// VPC IPs with LB rules only have LB (and firewall)
if (this.loadBalancerRuleCount > 0) {
tabs = tabs.filter(tab => tab.name !== 'portforwarding')
}
Expand Down
6 changes: 6 additions & 0 deletions ui/src/views/offering/AddVpcOffering.vue
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,12 @@ export default {
{ name: 'ConfigDrive' }
]
})
services.push({
name: 'Firewall',
provider: [
{ name: 'VpcVirtualRouter' }
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if we can add providers (NSX, etc.) other than VpcVirtualRouter here.

]
})
Comment on lines +528 to +533
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Firewall is only added to the services list for the non-NSX/non-Netris path. Since the backend changes add Firewall support to VPC offerings (including NSX/Netris VPC offerings via VpcVirtualRouter), the UI should also include the Firewall service in the NSX and Netris branches; otherwise those offerings can’t be configured with Firewall from the UI.

Copilot uses AI. Check for mistakes.
services.push({
name: 'Lb',
provider: [
Expand Down
Loading