mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	api: add ipaddress argument to disassociateIPAddress (#8222)
This PR adds argument 'ipadress' to the disassociateIpAddress api. IP address can be disassociated by directly giving the address instead of ID. Fixes: #8125
This commit is contained in:
		
							parent
							
								
									98d643efe6
								
							
						
					
					
						commit
						5c7e4b7edc
					
				| @ -114,6 +114,8 @@ public interface NetworkService { | |||||||
| 
 | 
 | ||||||
|     IpAddress getIp(long id); |     IpAddress getIp(long id); | ||||||
| 
 | 
 | ||||||
|  |     IpAddress getIp(String ipAddress); | ||||||
|  | 
 | ||||||
|     Network updateGuestNetwork(final UpdateNetworkCmd cmd); |     Network updateGuestNetwork(final UpdateNetworkCmd cmd); | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | |||||||
| @ -46,10 +46,14 @@ public class DisassociateIPAddrCmd extends BaseAsyncCmd { | |||||||
|     //////////////// API parameters ///////////////////// |     //////////////// API parameters ///////////////////// | ||||||
|     ///////////////////////////////////////////////////// |     ///////////////////////////////////////////////////// | ||||||
| 
 | 
 | ||||||
|     @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = IPAddressResponse.class, required = true, description = "the ID of the public IP address" |     @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = IPAddressResponse.class, description = "the ID of the public IP address" | ||||||
|         + " to disassociate") |         + " to disassociate. Mutually exclusive with the ipaddress parameter") | ||||||
|     private Long id; |     private Long id; | ||||||
| 
 | 
 | ||||||
|  |     @Parameter(name=ApiConstants.IP_ADDRESS, type=CommandType.STRING,  since="4.19.0", description="IP Address to be disassociated." | ||||||
|  |         +  " Mutually exclusive with the id parameter") | ||||||
|  |     private String ipAddress; | ||||||
|  | 
 | ||||||
|     // unexposed parameter needed for events logging |     // unexposed parameter needed for events logging | ||||||
|     @Parameter(name = ApiConstants.ACCOUNT_ID, type = CommandType.UUID, entityType = AccountResponse.class, expose = false) |     @Parameter(name = ApiConstants.ACCOUNT_ID, type = CommandType.UUID, entityType = AccountResponse.class, expose = false) | ||||||
|     private Long ownerId; |     private Long ownerId; | ||||||
| @ -59,7 +63,18 @@ public class DisassociateIPAddrCmd extends BaseAsyncCmd { | |||||||
|     ///////////////////////////////////////////////////// |     ///////////////////////////////////////////////////// | ||||||
| 
 | 
 | ||||||
|     public Long getIpAddressId() { |     public Long getIpAddressId() { | ||||||
|  |        if (id != null & ipAddress != null) { | ||||||
|  |            throw new InvalidParameterValueException("id parameter is mutually exclusive with ipaddress parameter"); | ||||||
|  |        } | ||||||
|  | 
 | ||||||
|  |        if (id != null) { | ||||||
|             return id; |             return id; | ||||||
|  |         } else if (ipAddress != null) { | ||||||
|  |             IpAddress ip = getIpAddressByIp(ipAddress); | ||||||
|  |             return ip.getId(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         throw new InvalidParameterValueException("Please specify either IP address or IP address ID"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ///////////////////////////////////////////////////// |     ///////////////////////////////////////////////////// | ||||||
| @ -68,12 +83,13 @@ public class DisassociateIPAddrCmd extends BaseAsyncCmd { | |||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public void execute() throws InsufficientAddressCapacityException { |     public void execute() throws InsufficientAddressCapacityException { | ||||||
|         CallContext.current().setEventDetails("IP ID: " + getIpAddressId()); |         Long ipAddressId = getIpAddressId(); | ||||||
|  |         CallContext.current().setEventDetails("IP ID: " + ipAddressId); | ||||||
|         boolean result = false; |         boolean result = false; | ||||||
|         if (!isPortable(id)) { |         if (!isPortable()) { | ||||||
|             result = _networkService.releaseIpAddress(getIpAddressId()); |             result = _networkService.releaseIpAddress(ipAddressId); | ||||||
|         } else { |         } else { | ||||||
|             result = _networkService.releasePortableIpAddress(getIpAddressId()); |             result = _networkService.releasePortableIpAddress(ipAddressId); | ||||||
|         } |         } | ||||||
|         if (result) { |         if (result) { | ||||||
|             SuccessResponse response = new SuccessResponse(getCommandName()); |             SuccessResponse response = new SuccessResponse(getCommandName()); | ||||||
| @ -85,7 +101,7 @@ public class DisassociateIPAddrCmd extends BaseAsyncCmd { | |||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public String getEventType() { |     public String getEventType() { | ||||||
|         if (!isPortable(id)) { |         if (!isPortable()) { | ||||||
|             return EventTypes.EVENT_NET_IP_RELEASE; |             return EventTypes.EVENT_NET_IP_RELEASE; | ||||||
|         } else { |         } else { | ||||||
|             return EventTypes.EVENT_PORTABLE_IP_RELEASE; |             return EventTypes.EVENT_PORTABLE_IP_RELEASE; | ||||||
| @ -100,10 +116,7 @@ public class DisassociateIPAddrCmd extends BaseAsyncCmd { | |||||||
|     @Override |     @Override | ||||||
|     public long getEntityOwnerId() { |     public long getEntityOwnerId() { | ||||||
|         if (ownerId == null) { |         if (ownerId == null) { | ||||||
|             IpAddress ip = getIpAddress(id); |             IpAddress ip = getIpAddress(); | ||||||
|             if (ip == null) { |  | ||||||
|                 throw new InvalidParameterValueException("Unable to find IP address by ID=" + id); |  | ||||||
|             } |  | ||||||
|             ownerId = ip.getAccountId(); |             ownerId = ip.getAccountId(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -120,11 +133,11 @@ public class DisassociateIPAddrCmd extends BaseAsyncCmd { | |||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public Long getSyncObjId() { |     public Long getSyncObjId() { | ||||||
|         IpAddress ip = getIpAddress(id); |         IpAddress ip = getIpAddress(); | ||||||
|         return ip.getAssociatedWithNetworkId(); |         return ip.getAssociatedWithNetworkId(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private IpAddress getIpAddress(long id) { |     private IpAddress getIpAddressById(Long id) { | ||||||
|         IpAddress ip = _entityMgr.findById(IpAddress.class, id); |         IpAddress ip = _entityMgr.findById(IpAddress.class, id); | ||||||
| 
 | 
 | ||||||
|         if (ip == null) { |         if (ip == null) { | ||||||
| @ -134,6 +147,29 @@ public class DisassociateIPAddrCmd extends BaseAsyncCmd { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     private IpAddress getIpAddressByIp(String ipAddress) { | ||||||
|  |         IpAddress ip = _networkService.getIp(ipAddress); | ||||||
|  |         if (ip == null) { | ||||||
|  |             throw new InvalidParameterValueException("Unable to find IP address by IP address=" + ipAddress); | ||||||
|  |         } else { | ||||||
|  |             return ip; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private IpAddress getIpAddress() { | ||||||
|  |         if (id != null & ipAddress != null) { | ||||||
|  |             throw new InvalidParameterValueException("id parameter is mutually exclusive with ipaddress parameter"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (id != null) { | ||||||
|  |             return getIpAddressById(id); | ||||||
|  |         } else if (ipAddress != null){ | ||||||
|  |             return getIpAddressByIp(ipAddress); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         throw new InvalidParameterValueException("Please specify either IP address or IP address ID"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     @Override |     @Override | ||||||
|     public ApiCommandResourceType getApiResourceType() { |     public ApiCommandResourceType getApiResourceType() { | ||||||
|         return ApiCommandResourceType.IpAddress; |         return ApiCommandResourceType.IpAddress; | ||||||
| @ -144,8 +180,8 @@ public class DisassociateIPAddrCmd extends BaseAsyncCmd { | |||||||
|         return getIpAddressId(); |         return getIpAddressId(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private boolean isPortable(long id) { |     private boolean isPortable() { | ||||||
|         IpAddress ip = getIpAddress(id); |         IpAddress ip = getIpAddress(); | ||||||
|         return ip.isPortable(); |         return ip.isPortable(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -2798,6 +2798,11 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C | |||||||
|         return _ipAddressDao.findById(ipAddressId); |         return _ipAddressDao.findById(ipAddressId); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @Override | ||||||
|  |     public IpAddress getIp(String ipAddress) { | ||||||
|  |         return _ipAddressDao.findByIp(ipAddress); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     protected boolean providersConfiguredForExternalNetworking(Collection<String> providers) { |     protected boolean providersConfiguredForExternalNetworking(Collection<String> providers) { | ||||||
|         for (String providerStr : providers) { |         for (String providerStr : providers) { | ||||||
|             Provider provider = Network.Provider.getProvider(providerStr); |             Provider provider = Network.Provider.getProvider(providerStr); | ||||||
|  | |||||||
| @ -275,6 +275,15 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkOrches | |||||||
|         return null; |         return null; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /* (non-Javadoc) | ||||||
|  |      * @see com.cloud.network.NetworkService#getIp(String) | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public IpAddress getIp(String ipAddress) { | ||||||
|  |         // TODO Auto-generated method stub | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     @Override |     @Override | ||||||
|     public Network updateGuestNetwork(final UpdateNetworkCmd cmd) { |     public Network updateGuestNetwork(final UpdateNetworkCmd cmd) { | ||||||
|         // TODO Auto-generated method stub |         // TODO Auto-generated method stub | ||||||
|  | |||||||
| @ -871,7 +871,7 @@ class TestReleaseIP(cloudstackTestCase): | |||||||
| 
 | 
 | ||||||
|     @attr(tags=["advanced", "advancedns", "smoke", "dvs"], required_hardware="false") |     @attr(tags=["advanced", "advancedns", "smoke", "dvs"], required_hardware="false") | ||||||
|     def test_releaseIP(self): |     def test_releaseIP(self): | ||||||
|         """Test for release public IP address""" |         """Test for release public IP address using the ID""" | ||||||
| 
 | 
 | ||||||
|         logger.debug("Deleting Public IP : %s" % self.ip_addr.id) |         logger.debug("Deleting Public IP : %s" % self.ip_addr.id) | ||||||
| 
 | 
 | ||||||
| @ -930,6 +930,66 @@ class TestReleaseIP(cloudstackTestCase): | |||||||
|             ) |             ) | ||||||
|         return |         return | ||||||
| 
 | 
 | ||||||
|  |     @attr(tags=["advanced", "advancedns", "smoke", "dvs"], required_hardware="false") | ||||||
|  |     def test_releaseIP_using_IP(self): | ||||||
|  |         """Test for release public IP address using the address""" | ||||||
|  | 
 | ||||||
|  |         logger.debug("Deleting Public IP : %s" % self.ip_addr.ipaddress) | ||||||
|  |         self.ip_address.delete_by_ip(self.apiclient) | ||||||
|  | 
 | ||||||
|  |         retriesCount = 10 | ||||||
|  |         isIpAddressDisassociated = False | ||||||
|  |         while retriesCount > 0: | ||||||
|  |             listResponse = list_publicIP( | ||||||
|  |                 self.apiclient, | ||||||
|  |                 id=self.ip_addr.id, | ||||||
|  |                 state="Allocated" | ||||||
|  |             ) | ||||||
|  |             if listResponse is None: | ||||||
|  |                 isIpAddressDisassociated = True | ||||||
|  |                 break | ||||||
|  |             retriesCount -= 1 | ||||||
|  |             time.sleep(60) | ||||||
|  |         # End while | ||||||
|  | 
 | ||||||
|  |         self.assertTrue( | ||||||
|  |             isIpAddressDisassociated, | ||||||
|  |             "Failed to disassociate IP address") | ||||||
|  | 
 | ||||||
|  |         # ListPortForwardingRules should not list | ||||||
|  |         # associated rules with Public IP address | ||||||
|  |         try: | ||||||
|  |             list_nat_rule = list_nat_rules( | ||||||
|  |                 self.apiclient, | ||||||
|  |                 id=self.nat_rule.id | ||||||
|  |             ) | ||||||
|  |             logger.debug("List NAT Rule response" + str(list_nat_rule)) | ||||||
|  |         except CloudstackAPIException: | ||||||
|  |             logger.debug("Port Forwarding Rule is deleted") | ||||||
|  | 
 | ||||||
|  |         # listLoadBalancerRules should not list | ||||||
|  |         # associated rules with Public IP address | ||||||
|  |         try: | ||||||
|  |             list_lb_rule = list_lb_rules( | ||||||
|  |                 self.apiclient, | ||||||
|  |                 id=self.lb_rule.id | ||||||
|  |             ) | ||||||
|  |             logger.debug("List LB Rule response" + str(list_lb_rule)) | ||||||
|  |         except CloudstackAPIException: | ||||||
|  |             logger.debug("Port Forwarding Rule is deleted") | ||||||
|  | 
 | ||||||
|  |         # SSH Attempt though public IP should fail | ||||||
|  |         with self.assertRaises(Exception): | ||||||
|  |             SshClient( | ||||||
|  |                 self.ip_addr.ipaddress, | ||||||
|  |                 self.services["natrule"]["publicport"], | ||||||
|  |                 self.virtual_machine.username, | ||||||
|  |                 self.virtual_machine.password, | ||||||
|  |                 retries=2, | ||||||
|  |                 delay=0 | ||||||
|  |             ) | ||||||
|  |         return | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class TestDeleteAccount(cloudstackTestCase): | class TestDeleteAccount(cloudstackTestCase): | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1879,12 +1879,19 @@ class PublicIPAddress: | |||||||
|         return PublicIPAddress(apiclient.associateIpAddress(cmd).__dict__) |         return PublicIPAddress(apiclient.associateIpAddress(cmd).__dict__) | ||||||
| 
 | 
 | ||||||
|     def delete(self, apiclient): |     def delete(self, apiclient): | ||||||
|         """Dissociate Public IP address""" |         """Dissociate Public IP address using the given ID""" | ||||||
|         cmd = disassociateIpAddress.disassociateIpAddressCmd() |         cmd = disassociateIpAddress.disassociateIpAddressCmd() | ||||||
|         cmd.id = self.ipaddress.id |         cmd.id = self.ipaddress.id | ||||||
|         apiclient.disassociateIpAddress(cmd) |         apiclient.disassociateIpAddress(cmd) | ||||||
|         return |         return | ||||||
| 
 | 
 | ||||||
|  |     def delete_by_ip(self, apiclient): | ||||||
|  |         """Dissociate Public IP address using the given IP address""" | ||||||
|  |         cmd = disassociateIpAddress.disassociateIpAddressCmd() | ||||||
|  |         cmd.ipaddress = self.ipaddress.ipaddress | ||||||
|  |         apiclient.disassociateIpAddress(cmd) | ||||||
|  |         return | ||||||
|  | 
 | ||||||
|     @classmethod |     @classmethod | ||||||
|     def list(cls, apiclient, **kwargs): |     def list(cls, apiclient, **kwargs): | ||||||
|         """List all Public IPs matching criteria""" |         """List all Public IPs matching criteria""" | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user