diff --git a/api/src/main/java/com/cloud/network/vpc/Vpc.java b/api/src/main/java/com/cloud/network/vpc/Vpc.java index e9a831c9d83..b94089d2d43 100644 --- a/api/src/main/java/com/cloud/network/vpc/Vpc.java +++ b/api/src/main/java/com/cloud/network/vpc/Vpc.java @@ -105,4 +105,6 @@ public interface Vpc extends ControlledEntity, Identity, InternalIdentity { String getIp6Dns1(); String getIp6Dns2(); + + boolean useRouterIpAsResolver(); } diff --git a/api/src/main/java/com/cloud/network/vpc/VpcService.java b/api/src/main/java/com/cloud/network/vpc/VpcService.java index af2a9847a62..9b7a83c29c1 100644 --- a/api/src/main/java/com/cloud/network/vpc/VpcService.java +++ b/api/src/main/java/com/cloud/network/vpc/VpcService.java @@ -48,17 +48,17 @@ public interface VpcService { * @param vpcName * @param displayText * @param cidr - * @param networkDomain TODO + * @param networkDomain TODO * @param ip4Dns1 * @param ip4Dns2 - * @param displayVpc TODO + * @param displayVpc TODO + * @param useVrIpResolver * @return * @throws ResourceAllocationException TODO */ Vpc createVpc(long zoneId, long vpcOffId, long vpcOwnerId, String vpcName, String displayText, String cidr, String networkDomain, String ip4Dns1, String ip4Dns2, String ip6Dns1, String ip6Dns2, Boolean displayVpc, Integer publicMtu, Integer cidrSize, - Long asNumber, List bgpPeerIds) - throws ResourceAllocationException; + Long asNumber, List bgpPeerIds, Boolean useVrIpResolver) throws ResourceAllocationException; /** * Persists VPC record in the database diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java index b87467e8c76..cfb19a826b8 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -548,6 +548,7 @@ public class ApiConstants { public static final String USER_SECURITY_GROUP_LIST = "usersecuritygrouplist"; public static final String USER_SECRET_KEY = "usersecretkey"; public static final String USE_VIRTUAL_NETWORK = "usevirtualnetwork"; + public static final String USE_VIRTUAL_ROUTER_IP_RESOLVER = "userouteripresolver"; public static final String UPDATE_IN_SEQUENCE = "updateinsequence"; public static final String VALUE = "value"; public static final String VIRTUAL_MACHINE_ID = "virtualmachineid"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java index 2f62d0d7210..08b7b9911b1 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java @@ -16,6 +16,7 @@ // under the License. package org.apache.cloudstack.api.command.user.vpc; +import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.apache.cloudstack.acl.RoleType; @@ -125,6 +126,10 @@ public class CreateVPCCmd extends BaseAsyncCreateCmd implements UserCmd { @Parameter(name=ApiConstants.AS_NUMBER, type=CommandType.LONG, since = "4.20.0", description="the AS Number of the VPC tiers") private Long asNumber; + @Parameter(name=ApiConstants.USE_VIRTUAL_ROUTER_IP_RESOLVER, type=CommandType.BOOLEAN, + description="(optional) for NSX based VPCs: when set to true, use the VR IP as nameserver, otherwise use DNS1 and DNS2") + private Boolean useVrIpResolver; + // /////////////////////////////////////////////////// // ///////////////// Accessors /////////////////////// // /////////////////////////////////////////////////// @@ -205,6 +210,10 @@ public class CreateVPCCmd extends BaseAsyncCreateCmd implements UserCmd { return asNumber; } + public boolean getUseVrIpResolver() { + return BooleanUtils.toBoolean(useVrIpResolver); + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/engine/schema/src/main/java/com/cloud/network/vpc/VpcVO.java b/engine/schema/src/main/java/com/cloud/network/vpc/VpcVO.java index e8ccc2ebcf1..e942eadb8ff 100644 --- a/engine/schema/src/main/java/com/cloud/network/vpc/VpcVO.java +++ b/engine/schema/src/main/java/com/cloud/network/vpc/VpcVO.java @@ -105,6 +105,9 @@ public class VpcVO implements Vpc { @Column(name = "ip6Dns2") String ip6Dns2; + @Column(name = "use_router_ip_resolver") + boolean useRouterIpResolver = false; + @Transient boolean rollingRestart = false; @@ -309,4 +312,13 @@ public class VpcVO implements Vpc { public String getIp6Dns2() { return ip6Dns2; } + + @Override + public boolean useRouterIpAsResolver() { + return useRouterIpResolver; + } + + public void setUseRouterIpResolver(boolean useRouterIpResolver) { + this.useRouterIpResolver = useRouterIpResolver; + } } diff --git a/engine/schema/src/main/resources/META-INF/db/schema-42010to42100.sql b/engine/schema/src/main/resources/META-INF/db/schema-42010to42100.sql index ec20cb3fdd2..fe746c9884a 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-42010to42100.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-42010to42100.sql @@ -68,6 +68,9 @@ ALTER TABLE `cloud`.`kubernetes_cluster` ADD CONSTRAINT `fk_cluster__etcd_templa -- Add for_cks column to the user_data table to represent CNI Configuration stored as userdata CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.user_data','for_cks', 'int(1) unsigned DEFAULT "0" COMMENT "if true, the userdata represent CNI configuration meant for CKS use only"'); + +-- Add use VR IP as resolver option on VPC +CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.vpc','use_router_ip_resolver', 'tinyint(1) DEFAULT 0 COMMENT "use router ip as resolver instead of dns options"'); ----------------------------------------------------------- -- END - CKS Enhancements ----------------------------------------------------------- diff --git a/server/src/main/java/com/cloud/network/NetworkMigrationManagerImpl.java b/server/src/main/java/com/cloud/network/NetworkMigrationManagerImpl.java index 91e4fddb69c..450f08c46e3 100644 --- a/server/src/main/java/com/cloud/network/NetworkMigrationManagerImpl.java +++ b/server/src/main/java/com/cloud/network/NetworkMigrationManagerImpl.java @@ -301,7 +301,7 @@ public class NetworkMigrationManagerImpl implements NetworkMigrationManager { copyOfVpc = _vpcService.createVpc(vpc.getZoneId(), vpcOfferingId, vpc.getAccountId(), vpc.getName(), vpc.getDisplayText(), vpc.getCidr(), vpc.getNetworkDomain(), vpc.getIp4Dns1(), vpc.getIp4Dns2(), - vpc.getIp6Dns1(), vpc.getIp6Dns2(), vpc.isDisplay(), vpc.getPublicMtu(), null, null, null); + vpc.getIp6Dns1(), vpc.getIp6Dns2(), vpc.isDisplay(), vpc.getPublicMtu(), null, null, null, vpc.useRouterIpAsResolver()); copyOfVpcId = copyOfVpc.getId(); //on resume of migration the uuid will be swapped already. So the copy will have the value of the original vpcid. diff --git a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index e171b68399b..09c1aa47f70 100644 --- a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -2072,6 +2072,7 @@ Configurable, StateListener bgpPeerIds) throws ResourceAllocationException { + final Integer cidrSize, final Long asNumber, final List bgpPeerIds, Boolean useVrIpResolver) throws ResourceAllocationException { final Account caller = CallContext.current().getCallingAccount(); final Account owner = _accountMgr.getAccount(vpcOwnerId); @@ -1247,6 +1247,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis vpcOff.isRedundantRouter(), ip4Dns1, ip4Dns2, ip6Dns1, ip6Dns2); vpc.setPublicMtu(publicMtu); vpc.setDisplay(Boolean.TRUE.equals(displayVpc)); + vpc.setUseRouterIpResolver(Boolean.TRUE.equals(useVrIpResolver)); if (vpc.getCidr() == null && cidrSize != null) { // Allocate a CIDR for VPC @@ -1305,7 +1306,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis List bgpPeerIds = (cmd instanceof CreateVPCCmdByAdmin) ? ((CreateVPCCmdByAdmin)cmd).getBgpPeerIds() : null; Vpc vpc = createVpc(cmd.getZoneId(), cmd.getVpcOffering(), cmd.getEntityOwnerId(), cmd.getVpcName(), cmd.getDisplayText(), cmd.getCidr(), cmd.getNetworkDomain(), cmd.getIp4Dns1(), cmd.getIp4Dns2(), cmd.getIp6Dns1(), - cmd.getIp6Dns2(), cmd.isDisplay(), cmd.getPublicMtu(), cmd.getCidrSize(), cmd.getAsNumber(), bgpPeerIds); + cmd.getIp6Dns2(), cmd.isDisplay(), cmd.getPublicMtu(), cmd.getCidrSize(), cmd.getAsNumber(), bgpPeerIds, cmd.getUseVrIpResolver()); String sourceNatIP = cmd.getSourceNatIP(); boolean forNsx = isVpcForNsx(vpc); diff --git a/server/src/test/java/com/cloud/network/vpc/VpcManagerImplTest.java b/server/src/test/java/com/cloud/network/vpc/VpcManagerImplTest.java index ee56a092dd1..8d513619805 100644 --- a/server/src/test/java/com/cloud/network/vpc/VpcManagerImplTest.java +++ b/server/src/test/java/com/cloud/network/vpc/VpcManagerImplTest.java @@ -492,7 +492,7 @@ public class VpcManagerImplTest { try { doNothing().when(resourceLimitService).checkResourceLimit(account, Resource.ResourceType.vpc); manager.createVpc(zoneId, vpcOfferingId, vpcOwnerId, vpcName, vpcName, ip4Cidr, vpcDomain, - ip4Dns[0], null, null, null, true, 1500, null, null, null); + ip4Dns[0], null, null, null, true, 1500, null, null, null, false); } catch (ResourceAllocationException e) { Assert.fail(String.format("failure with exception: %s", e.getMessage())); } @@ -504,7 +504,7 @@ public class VpcManagerImplTest { try { doNothing().when(resourceLimitService).checkResourceLimit(account, Resource.ResourceType.vpc); manager.createVpc(zoneId, vpcOfferingId, vpcOwnerId, vpcName, vpcName, ip4Cidr, vpcDomain, - ip4Dns[0], ip4Dns[1], ip6Dns[0], null, true, 1500, null, null, null); + ip4Dns[0], ip4Dns[1], ip6Dns[0], null, true, 1500, null, null, null, false); } catch (ResourceAllocationException e) { Assert.fail(String.format("failure with exception: %s", e.getMessage())); } @@ -519,7 +519,7 @@ public class VpcManagerImplTest { try { doNothing().when(resourceLimitService).checkResourceLimit(account, Resource.ResourceType.vpc); manager.createVpc(zoneId, vpcOfferingId, vpcOwnerId, vpcName, vpcName, ip4Cidr, vpcDomain, - ip4Dns[0], ip4Dns[1], null, null, true, 1500, null, null, null); + ip4Dns[0], ip4Dns[1], null, null, true, 1500, null, null, null, false); } catch (ResourceAllocationException e) { Assert.fail(String.format("failure with exception: %s", e.getMessage())); } @@ -536,7 +536,7 @@ public class VpcManagerImplTest { try { doNothing().when(resourceLimitService).checkResourceLimit(account, Resource.ResourceType.vpc); manager.createVpc(zoneId, vpcOfferingId, vpcOwnerId, vpcName, vpcName, ip4Cidr, vpcDomain, - ip4Dns[0], ip4Dns[1], null, null, true, 1500, null, null, null); + ip4Dns[0], ip4Dns[1], null, null, true, 1500, null, null, null, false); } catch (ResourceAllocationException e) { Assert.fail(String.format("failure with exception: %s", e.getMessage())); } @@ -559,7 +559,7 @@ public class VpcManagerImplTest { try { doNothing().when(resourceLimitService).checkResourceLimit(account, Resource.ResourceType.vpc); manager.createVpc(zoneId, vpcOfferingId, vpcOwnerId, vpcName, vpcName, null, vpcDomain, - ip4Dns[0], ip4Dns[1], null, null, true, 1500, 24, null, bgpPeerIds); + ip4Dns[0], ip4Dns[1], null, null, true, 1500, 24, null, bgpPeerIds, false); } catch (ResourceAllocationException e) { Assert.fail(String.format("failure with exception: %s", e.getMessage())); } diff --git a/systemvm/debian/opt/cloud/bin/cs/CsConfig.py b/systemvm/debian/opt/cloud/bin/cs/CsConfig.py index a17f6ac4aa5..1ad7e34db57 100755 --- a/systemvm/debian/opt/cloud/bin/cs/CsConfig.py +++ b/systemvm/debian/opt/cloud/bin/cs/CsConfig.py @@ -114,6 +114,9 @@ class CsConfig(object): def expose_dns(self): return self.cmdline().idata().get('exposedns', 'false') == 'true' + def use_router_ip_as_resolver(self): + return self.cl.get_use_router_ip_as_resolver() + def get_dns(self): conf = self.cmdline().idata() dns = [] @@ -123,9 +126,10 @@ class CsConfig(object): else: dns.append(self.address().get_guest_ip()) - for name in ('dns1', 'dns2'): - if name in conf: - dns.append(conf[name]) + if not 'userouteripresolver' in conf: + for name in ('dns1', 'dns2'): + if name in conf: + dns.append(conf[name]) return dns def get_format(self): diff --git a/systemvm/debian/opt/cloud/bin/cs/CsDatabag.py b/systemvm/debian/opt/cloud/bin/cs/CsDatabag.py index abbf23b4cdf..4c6b61240b8 100755 --- a/systemvm/debian/opt/cloud/bin/cs/CsDatabag.py +++ b/systemvm/debian/opt/cloud/bin/cs/CsDatabag.py @@ -176,6 +176,11 @@ class CsCmdLine(CsDataBag): return self.idata()['useextdns'] return False + def get_use_router_ip_as_resolver(self): + if "userouteripresolver" in self.idata(): + return self.idata()['userouteripresolver'] + return False + def get_advert_int(self): if 'advert_int' in self.idata(): return self.idata()['advert_int'] diff --git a/systemvm/debian/opt/cloud/bin/cs/CsGuestNetwork.py b/systemvm/debian/opt/cloud/bin/cs/CsGuestNetwork.py index fe8737208c4..65200fb8796 100755 --- a/systemvm/debian/opt/cloud/bin/cs/CsGuestNetwork.py +++ b/systemvm/debian/opt/cloud/bin/cs/CsGuestNetwork.py @@ -38,6 +38,9 @@ class CsGuestNetwork: if not self.guest: return self.config.get_dns() + if self.config.use_router_ip_as_resolver(): + return [self.data['router_guest_ip']] + dns = [] if 'router_guest_gateway' in self.data and not self.config.use_extdns() and ('is_vr_guest_gateway' not in self.data or not self.data['is_vr_guest_gateway']): dns.append(self.data['router_guest_gateway']) diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index f3e7c88fdd2..6b91200e810 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -2488,6 +2488,7 @@ "label.usagetypedescription": "Usage description", "label.use.kubectl.access.cluster": "kubectl and kubeconfig file to access cluster", "label.use.local.timezone": "Use local timezone", +"label.use.router.ip.resolver": "Use Virtual Router IP as resolver", "label.used": "Used", "label.usehttps": "Use HTTPS", "label.usenewdiskoffering": "Replace disk offering?", diff --git a/ui/src/views/network/CreateVpc.vue b/ui/src/views/network/CreateVpc.vue index d239d04e143..6ede446fb44 100644 --- a/ui/src/views/network/CreateVpc.vue +++ b/ui/src/views/network/CreateVpc.vue @@ -142,7 +142,15 @@
- +
+ + + + +
+