This is an automated email from the ASF dual-hosted git repository. pearl11594 pushed a commit to branch cks-enhancements-part2 in repository https://gitbox.apache.org/repos/asf/cloudstack.git
commit ac53e4b32247ae0dc6f4baa8980c005ece0ba68b Author: Nicolas Vazquez <[email protected]> AuthorDate: Tue Jan 28 17:21:17 2025 -0300 Add option to select DNS or VR IP as resolver on VPC creation * Add API param and UI to select option * Add column on vpc and pass the value on the databags for CsDhcp.py to fix accordingly --- api/src/main/java/com/cloud/network/vpc/Vpc.java | 2 ++ api/src/main/java/com/cloud/network/vpc/VpcService.java | 8 ++++---- .../java/org/apache/cloudstack/api/ApiConstants.java | 1 + .../cloudstack/api/command/user/vpc/CreateVPCCmd.java | 9 +++++++++ .../src/main/java/com/cloud/network/vpc/VpcVO.java | 12 ++++++++++++ .../main/resources/META-INF/db/schema-42010to42100.sql | 3 +++ .../com/cloud/network/NetworkMigrationManagerImpl.java | 2 +- .../router/VirtualNetworkApplianceManagerImpl.java | 16 ++++++++++++++++ .../main/java/com/cloud/network/vpc/VpcManagerImpl.java | 5 +++-- .../java/com/cloud/network/vpc/VpcManagerImplTest.java | 10 +++++----- systemvm/debian/opt/cloud/bin/cs/CsConfig.py | 10 +++++++--- systemvm/debian/opt/cloud/bin/cs/CsDatabag.py | 5 +++++ systemvm/debian/opt/cloud/bin/cs/CsGuestNetwork.py | 3 +++ ui/public/locales/en.json | 1 + ui/src/views/network/CreateVpc.vue | 16 ++++++++++++++-- 15 files changed, 86 insertions(+), 17 deletions(-) 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<Long> bgpPeerIds) - throws ResourceAllocationException; + Long asNumber, List<Long> 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<VirtualMachine.State, VirtualMachine.Event, VirtualM * service, we need to override the DHCP response to return DNS server * rather than virtual router itself. */ + boolean useRouterIpResolver = getUseRouterIpAsResolver(router); if (dnsProvided || dhcpProvided) { if (defaultDns1 != null) { buf.append(" dns1=").append(defaultDns1); @@ -2093,6 +2094,9 @@ Configurable, StateListener<VirtualMachine.State, VirtualMachine.Event, VirtualM if (useExtDns) { buf.append(" useextdns=true"); } + if (useRouterIpResolver) { + buf.append(" userouteripresolver=true"); + } } if (Boolean.TRUE.equals(ExposeDnsAndBootpServer.valueIn(dc.getId()))) { @@ -2132,6 +2136,18 @@ Configurable, StateListener<VirtualMachine.State, VirtualMachine.Event, VirtualM return true; } + private boolean getUseRouterIpAsResolver(DomainRouterVO router) { + if (router == null || router.getVpcId() == null) { + return false; + } + Vpc vpc = _vpcDao.findById(router.getVpcId()); + if (vpc == null) { + s_logger.warn(String.format("Cannot find VPC with ID %s from router %s", router.getVpcId(), router.getName())); + return false; + } + return vpc.useRouterIpAsResolver(); + } + /** * @param routerLogrotateFrequency The string to be checked if matches with any acceptable values. * Checks if the value in the global configuration is an acceptable value to be informed to the Virtual Router. 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 dc6b6cd3d40..7a2e789996f 100644 --- a/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java @@ -1145,7 +1145,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis @ActionEvent(eventType = EventTypes.EVENT_VPC_CREATE, eventDescription = "creating vpc", create = true) public Vpc createVpc(final long zoneId, final long vpcOffId, final long vpcOwnerId, final String vpcName, final String displayText, final String cidr, String networkDomain, final String ip4Dns1, final String ip4Dns2, final String ip6Dns1, final String ip6Dns2, final Boolean displayVpc, Integer publicMtu, - final Integer cidrSize, final Long asNumber, final List<Long> bgpPeerIds) throws ResourceAllocationException { + final Integer cidrSize, final Long asNumber, final List<Long> 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<Long> 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": "<code><b>kubectl</b></code> and <code><b>kubeconfig</b></code> 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 @@ <div style="color: red" v-if="errorPublicMtu" v-html="errorPublicMtu"></div> </a-form-item> </div> - <a-row :gutter="12" v-if="selectedVpcOfferingSupportsDns"> + <div v-if="isNsxNetwork"> + <a-form-item name="userouteripresolver" ref="userouteripresolver"> + <template #label> + <tooltip-label :title="$t('label.use.router.ip.resolver')" :tooltip="apiParams.userouteripresolver.description"/> + </template> + <a-switch v-model:checked="useRouterIpResolver" /> + </a-form-item> + </div> + <a-row :gutter="12" v-if="selectedVpcOfferingSupportsDns && !useRouterIpResolver"> <a-col :md="12" :lg="12"> <a-form-item v-if="'dns1' in apiParams" name="dns1" ref="dns1"> <template #label> @@ -240,7 +248,8 @@ export default { isNsxNetwork: false, asNumberLoading: false, asNumbersZone: [], - selectedAsNumber: 0 + selectedAsNumber: 0, + useRouterIpResolver: false } }, beforeCreate () { @@ -459,6 +468,9 @@ export default { if ('asnumber' in values && this.isASNumberRequired()) { params.asnumber = values.asnumber } + if (this.useRouterIpResolver) { + params.userouteripresolver = true + } this.loading = true const title = this.$t('label.add.vpc') const description = this.$t('message.success.add.vpc')
