From bedd77fe8b8a0cc18b8cd63137fd456803ed3194 Mon Sep 17 00:00:00 2001 From: erikbocks Date: Thu, 19 Mar 2026 13:00:09 -0300 Subject: [PATCH] Addition of description field for NIC's secondary IP addresses --- .../java/com/cloud/network/NetworkService.java | 2 +- .../main/java/com/cloud/vm/NicSecondaryIp.java | 2 ++ .../api/command/user/vm/AddIpToVmNicCmd.java | 5 ++++- .../api/response/NicSecondaryIpResponse.java | 12 ++++++++++++ .../api/command/test/AddIpToVmNicTest.java | 4 ++-- .../java/com/cloud/vm/dao/NicSecondaryIpVO.java | 15 ++++++++++++++- .../resources/META-INF/db/schema-42210to42300.sql | 3 +++ .../java/com/cloud/api/ApiResponseHelper.java | 2 ++ .../cloud/api/query/dao/UserVmJoinDaoImpl.java | 1 + .../com/cloud/network/NetworkServiceImpl.java | 4 ++-- .../com/cloud/network/rules/RulesManagerImpl.java | 2 +- .../com/cloud/vpc/MockNetworkManagerImpl.java | 2 +- ui/public/locales/en.json | 2 ++ ui/public/locales/pt_BR.json | 2 ++ ui/src/views/network/NicsTab.vue | 9 +++++++++ ui/src/views/network/NicsTable.vue | 2 +- 16 files changed, 59 insertions(+), 10 deletions(-) diff --git a/api/src/main/java/com/cloud/network/NetworkService.java b/api/src/main/java/com/cloud/network/NetworkService.java index 53692f932a4e..c32bb711c0f2 100644 --- a/api/src/main/java/com/cloud/network/NetworkService.java +++ b/api/src/main/java/com/cloud/network/NetworkService.java @@ -232,7 +232,7 @@ Network createPrivateNetwork(String networkName, String displayText, long physic /** * Requests an IP address for the guest NIC */ - NicSecondaryIp allocateSecondaryGuestIP(long nicId, IpAddresses requestedIpPair) throws InsufficientAddressCapacityException; + NicSecondaryIp allocateSecondaryGuestIP(long nicId, IpAddresses requestedIpPair, String description) throws InsufficientAddressCapacityException; boolean releaseSecondaryIpFromNic(long ipAddressId); diff --git a/api/src/main/java/com/cloud/vm/NicSecondaryIp.java b/api/src/main/java/com/cloud/vm/NicSecondaryIp.java index 2856e0aea756..d25627c1782d 100644 --- a/api/src/main/java/com/cloud/vm/NicSecondaryIp.java +++ b/api/src/main/java/com/cloud/vm/NicSecondaryIp.java @@ -38,6 +38,8 @@ public interface NicSecondaryIp extends ControlledEntity, Identity, InternalIden String getIp6Address(); + String getDescription(); + long getNetworkId(); long getVmId(); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/AddIpToVmNicCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/AddIpToVmNicCmd.java index 6274e7e14963..1d0b51c97a6b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/AddIpToVmNicCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/AddIpToVmNicCmd.java @@ -56,6 +56,9 @@ public class AddIpToVmNicCmd extends BaseAsyncCreateCmd { @Parameter(name = ApiConstants.IP_ADDRESS, type = CommandType.STRING, required = false, description = "Secondary IP Address") private String ipAddr; + @Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, required = false, description = "Description") + private String description; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -160,7 +163,7 @@ public void create() throws ResourceAllocationException { } try { - result = _networkService.allocateSecondaryGuestIP(getNicId(), requestedIpPair); + result = _networkService.allocateSecondaryGuestIP(getNicId(), requestedIpPair, description); if (result != null) { setEntityId(result.getId()); setEntityUuid(result.getUuid()); diff --git a/api/src/main/java/org/apache/cloudstack/api/response/NicSecondaryIpResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/NicSecondaryIpResponse.java index eba00da25cfe..f664b1e07856 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/NicSecondaryIpResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/NicSecondaryIpResponse.java @@ -53,6 +53,10 @@ public class NicSecondaryIpResponse extends BaseResponse { @Param(description = "The ID of the Instance") private String vmId; + @SerializedName(ApiConstants.DESCRIPTION) + @Param(description = "description") + private String description; + @Override public String getObjectId() { return this.getId(); @@ -98,6 +102,14 @@ public void setId(String id) { this.id = id; } + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + public List getSecondaryIpsList() { return secondaryIpsList; } diff --git a/api/src/test/java/org/apache/cloudstack/api/command/test/AddIpToVmNicTest.java b/api/src/test/java/org/apache/cloudstack/api/command/test/AddIpToVmNicTest.java index 9ea3a6446e8e..71c6d54c7a8c 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/test/AddIpToVmNicTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/test/AddIpToVmNicTest.java @@ -59,7 +59,7 @@ public void testCreateSuccess() throws ResourceAllocationException, ResourceUnav NicSecondaryIp secIp = Mockito.mock(NicSecondaryIp.class); Mockito.when( - networkService.allocateSecondaryGuestIP(ArgumentMatchers.anyLong(), ArgumentMatchers.any())) + networkService.allocateSecondaryGuestIP(ArgumentMatchers.anyLong(), ArgumentMatchers.any(), ArgumentMatchers.anyString())) .thenReturn(secIp); ipTonicCmd._networkService = networkService; @@ -79,7 +79,7 @@ public void testCreateFailure() throws ResourceAllocationException, ResourceUnav AddIpToVmNicCmd ipTonicCmd = Mockito.mock(AddIpToVmNicCmd.class); Mockito.when( - networkService.allocateSecondaryGuestIP(ArgumentMatchers.anyLong(), ArgumentMatchers.any())) + networkService.allocateSecondaryGuestIP(ArgumentMatchers.anyLong(), ArgumentMatchers.any(), ArgumentMatchers.anyString())) .thenReturn(null); ipTonicCmd._networkService = networkService; diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/NicSecondaryIpVO.java b/engine/schema/src/main/java/com/cloud/vm/dao/NicSecondaryIpVO.java index 4c8208b4be84..baa331d81f67 100644 --- a/engine/schema/src/main/java/com/cloud/vm/dao/NicSecondaryIpVO.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/NicSecondaryIpVO.java @@ -43,7 +43,7 @@ public NicSecondaryIpVO(long nicId, String ipaddr, long vmId, long accountId, lo this.networkId = networkId; } - public NicSecondaryIpVO(long nicId, String ip4Address, String ip6Address, long vmId, long accountId, long domainId, long networkId) { + public NicSecondaryIpVO(long nicId, String ip4Address, String ip6Address, long vmId, long accountId, long domainId, long networkId, String description) { this.nicId = nicId; this.vmId = vmId; this.ip4Address = ip4Address; @@ -51,6 +51,7 @@ public NicSecondaryIpVO(long nicId, String ip4Address, String ip6Address, long v this.accountId = accountId; this.domainId = domainId; this.networkId = networkId; + this.description = description; } protected NicSecondaryIpVO() { @@ -88,6 +89,18 @@ protected NicSecondaryIpVO() { @Column(name = "vmId") long vmId; + @Column(name = "description") + String description; + + @Override + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + @Override public String toString() { return String.format("NicSecondaryIp %s", diff --git a/engine/schema/src/main/resources/META-INF/db/schema-42210to42300.sql b/engine/schema/src/main/resources/META-INF/db/schema-42210to42300.sql index d69b524b85d9..2e50fc0a1fe1 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-42210to42300.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-42210to42300.sql @@ -114,3 +114,6 @@ CALL `cloud`.`IDEMPOTENT_UPDATE_API_PERMISSION`('Resource Admin', 'deleteUserKey -- Add conserve mode for VPC offerings CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.vpc_offerings','conserve_mode', 'tinyint(1) unsigned NULL DEFAULT 0 COMMENT ''True if the VPC offering is IP conserve mode enabled, allowing public IP services to be used across multiple VPC tiers'' '); + +-- Add description for secondary IP addresses +CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.nic_secondary_ips','description', 'varchar(2048) DEFAULT NULL'); \ No newline at end of file diff --git a/server/src/main/java/com/cloud/api/ApiResponseHelper.java b/server/src/main/java/com/cloud/api/ApiResponseHelper.java index cf98df0da243..fdcee07c7343 100644 --- a/server/src/main/java/com/cloud/api/ApiResponseHelper.java +++ b/server/src/main/java/com/cloud/api/ApiResponseHelper.java @@ -4729,6 +4729,7 @@ public NicSecondaryIpResponse createSecondaryIPToNicResponse(NicSecondaryIp resu setResponseIpAddress(result, response); response.setNicId(nic.getUuid()); response.setNwId(network.getUuid()); + response.setDescription(result.getDescription()); response.setObjectName("nicsecondaryip"); return response; } @@ -4815,6 +4816,7 @@ public NicResponse createNicResponse(Nic result) { for (NicSecondaryIpVO ip : secondaryIps) { NicSecondaryIpResponse ipRes = new NicSecondaryIpResponse(); ipRes.setId(ip.getUuid()); + ipRes.setDescription(ip.getDescription()); setResponseIpAddress(ip, ipRes); ipList.add(ipRes); } diff --git a/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDaoImpl.java index 93dca8cc07a1..f4ca890e0de2 100644 --- a/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDaoImpl.java +++ b/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDaoImpl.java @@ -384,6 +384,7 @@ public UserVmResponse newUserVmResponse(ResponseView view, String objectName, Us for (NicSecondaryIpVO ip : secondaryIps) { NicSecondaryIpResponse ipRes = new NicSecondaryIpResponse(); ipRes.setId(ip.getUuid()); + ipRes.setDescription(ip.getDescription()); ApiResponseHelper.setResponseIpAddress(ip, ipRes); ipList.add(ipRes); } diff --git a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java index 0a2e679b723e..b6622413d2e0 100644 --- a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java @@ -887,7 +887,7 @@ public boolean configureNicSecondaryIp(NicSecondaryIp secIp, boolean isZoneSgEna */ @Override @ActionEvent(eventType = EventTypes.EVENT_NIC_SECONDARY_IP_ASSIGN, eventDescription = "Assigning secondary IP to NIC", create = true) - public NicSecondaryIp allocateSecondaryGuestIP(final long nicId, IpAddresses requestedIpPair) throws InsufficientAddressCapacityException { + public NicSecondaryIp allocateSecondaryGuestIP(final long nicId, IpAddresses requestedIpPair, String description) throws InsufficientAddressCapacityException { Account caller = CallContext.current().getCallingAccount(); String ipv4Address = requestedIpPair.getIp4Address(); @@ -985,7 +985,7 @@ public Long doInTransaction(TransactionStatus status) { logger.debug("Setting nic_secondary_ip table ..."); Long vmId = nicVO.getInstanceId(); - NicSecondaryIpVO secondaryIpVO = new NicSecondaryIpVO(nicId, ip4AddrFinal, ip6AddrFinal, vmId, ipOwner.getId(), ipOwner.getDomainId(), networkId); + NicSecondaryIpVO secondaryIpVO = new NicSecondaryIpVO(nicId, ip4AddrFinal, ip6AddrFinal, vmId, ipOwner.getId(), ipOwner.getDomainId(), networkId, description); _nicSecondaryIpDao.persist(secondaryIpVO); return secondaryIpVO.getId(); } diff --git a/server/src/main/java/com/cloud/network/rules/RulesManagerImpl.java b/server/src/main/java/com/cloud/network/rules/RulesManagerImpl.java index bb3ee8d76248..d73c097a6e9e 100644 --- a/server/src/main/java/com/cloud/network/rules/RulesManagerImpl.java +++ b/server/src/main/java/com/cloud/network/rules/RulesManagerImpl.java @@ -467,7 +467,7 @@ private boolean enableStaticNat(long ipId, long vmId, long networkId, boolean is boolean isOneToOneNat = ipAddress.isOneToOneNat(); Long associatedWithVmId = ipAddress.getAssociatedWithVmId(); Nic guestNic; - NicSecondaryIpVO nicSecIp = null; + wNicSecondaryIpVO nicSecIp = null; String dstIp = null; Network network = _networkModel.getNetwork(networkId); diff --git a/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java b/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java index de768388b449..e410c72fe512 100644 --- a/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java @@ -896,7 +896,7 @@ public boolean isSecondaryIpSetForNic(long nicId) { } @Override - public NicSecondaryIp allocateSecondaryGuestIP(long nicId, IpAddresses requestedIpPair) { + public NicSecondaryIp allocateSecondaryGuestIP(long nicId, IpAddresses requestedIpPair, String description) { // TODO Auto-generated method stub return null; } diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 513dfcdaa368..4c9a810e1e99 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -1735,6 +1735,7 @@ "label.new.password": "New password", "label.new.project": "New Project", "label.new.secondaryip.description": "Enter new secondary IP address", +"label.new.secondaryip.description.description": "Enter a new description for the secondary IP address", "label.new.tag": "New tag", "label.new.vm": "New Instance", "label.new.version.available": "New version available", @@ -2242,6 +2243,7 @@ "label.secondary.storage": "Secondary Storage", "label.secondary.storage.vm": "Secondary Storage VM", "label.secondaryips": "Secondary IPs", +"label.secondaryip.description": "Description:", "label.secondarystoragelimit": "Secondary Storage limits (GiB)", "label.secretkey": "Secret key", "label.secured": "Secured", diff --git a/ui/public/locales/pt_BR.json b/ui/public/locales/pt_BR.json index 59123a5e45c3..f04919973e6d 100644 --- a/ui/public/locales/pt_BR.json +++ b/ui/public/locales/pt_BR.json @@ -1112,6 +1112,7 @@ "label.new.password": "Nova senha", "label.new.project": "Novo projeto", "label.new.secondaryip.description": "Insira um novo endere\u00e7o IP secund\u00e1rio", +"label.new.secondaryip.description.description": "Insira uma nova descri\u00e7\u00e3o ao endere\u00e7o IP secund\u00e1rio", "label.new.tag": "Nova etiqueta", "label.new.vm": "Nova VM", "label.newdiskoffering": "Nova oferta", @@ -1450,6 +1451,7 @@ "label.secondary.storage": "Armazenamento secund\u00e1rio", "label.secondary.storage.vm": "VM de armazenamento secund\u00e1rio", "label.secondaryips": "IPs secund\u00e1rios", +"label.secondaryip.description": "Descri\u00e7\u00e3o:", "label.secondarystoragelimit": "Limites do armazenamento secund\u00e1rio (GiB)", "label.secretkey": "Chave secreta", "label.secured": "Protegido", diff --git a/ui/src/views/network/NicsTab.vue b/ui/src/views/network/NicsTab.vue index 9c16865e0c6e..1e4179d1d598 100644 --- a/ui/src/views/network/NicsTab.vue +++ b/ui/src/views/network/NicsTab.vue @@ -215,6 +215,11 @@ :placeholder="$t('label.new.secondaryip.description')" v-model:value="newSecondaryIp" v-focus="editNicResource.type!=='Shared'"> + +
@@ -292,6 +297,7 @@ export default { secondaryIPs: [], selectedNicId: '', newSecondaryIp: '', + newSecondaryIpDescription: '', editNicResource: {}, listIps: { loading: false, @@ -366,6 +372,7 @@ export default { this.addNetworkData.makedefault = false this.editIpAddressValue = '' this.newSecondaryIp = '' + this.newSecondaryIpDescription = '' }, onChangeIPAddress (record) { this.editNicResource = record.nic @@ -549,6 +556,7 @@ export default { if (this.newSecondaryIp) { params.ipaddress = this.newSecondaryIp } + params.description = this.newSecondaryIpDescription postAPI('addIpToNic', params).then(response => { this.$pollJob({ @@ -576,6 +584,7 @@ export default { this.loadingNic = false }).finally(() => { this.newSecondaryIp = null + this.newSecondaryIpDescription = null this.fetchPublicIps(this.editNetworkId) }) }, diff --git a/ui/src/views/network/NicsTable.vue b/ui/src/views/network/NicsTable.vue index a31925a6b374..98d8cbff337f 100644 --- a/ui/src/views/network/NicsTable.vue +++ b/ui/src/views/network/NicsTable.vue @@ -39,7 +39,7 @@ {{ record.traffictype }} - {{ record.secondaryip.map(x => x.ipaddress).join(', ') }} + {{ record.secondaryip.map(x => x.ipaddress + ': ' + x.description ).join(', ') }} {{ record.ip6address }}