You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ra...@apache.org on 2018/09/11 15:03:25 UTC
[cloudstack] branch master updated: Support IPv6 address in
addIpToNic (#2773)
This is an automated email from the ASF dual-hosted git repository.
rafael pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/master by this push:
new fbf4884 Support IPv6 address in addIpToNic (#2773)
fbf4884 is described below
commit fbf488497fb863c13fc0908281e3f4f86906df43
Author: Gabriel Beims Bräscher <ga...@gmail.com>
AuthorDate: Tue Sep 11 12:03:19 2018 -0300
Support IPv6 address in addIpToNic (#2773)
The admin will manually need to add the address to the Instance, but the
Security Grouping should allow it.
---
.../main/java/com/cloud/network/NetworkModel.java | 2 +-
.../java/com/cloud/network/NetworkService.java | 20 +-
.../api/command/user/vm/AddIpToVmNicCmd.java | 29 +--
.../api/command/user/vm/RemoveIpFromVmNicCmd.java | 7 +-
.../api/command/test/AddIpToVmNicTest.java | 4 +-
.../java/com/cloud/network/IpAddressManager.java | 18 +-
.../java/com/cloud/vm/dao/NicIpAliasDaoImpl.java | 1 +
.../java/com/cloud/vm/dao/NicSecondaryIpDao.java | 6 +-
.../com/cloud/vm/dao/NicSecondaryIpDaoImpl.java | 15 +-
.../main/java/com/cloud/api/ApiResponseHelper.java | 17 +-
.../com/cloud/api/query/dao/UserVmJoinDaoImpl.java | 8 +-
.../com/cloud/network/IpAddressManagerImpl.java | 44 ++--
.../java/com/cloud/network/Ipv6AddressManager.java | 7 +
.../com/cloud/network/Ipv6AddressManagerImpl.java | 118 ++++++++++-
.../java/com/cloud/network/NetworkModelImpl.java | 4 +-
.../java/com/cloud/network/NetworkServiceImpl.java | 78 ++++---
.../com/cloud/network/guru/DirectNetworkGuru.java | 20 +-
.../java/com/cloud/api/ApiResponseHelperTest.java | 32 +++
.../com/cloud/network/IpAddressManagerTest.java | 87 +++++++-
.../com/cloud/network/Ipv6AddressManagerTest.java | 229 +++++++++++++++++++++
.../com/cloud/network/MockNetworkModelImpl.java | 2 +-
.../java/com/cloud/vpc/MockNetworkManagerImpl.java | 3 +-
.../java/com/cloud/vpc/MockNetworkModelImpl.java | 2 +-
ui/lib/jquery.validate.additional-methods.js | 10 +
ui/scripts/network.js | 2 +-
.../main/java/com/cloud/utils/net/NetUtils.java | 18 +-
.../java/com/cloud/utils/net/NetUtilsTest.java | 16 ++
27 files changed, 671 insertions(+), 128 deletions(-)
diff --git a/api/src/main/java/com/cloud/network/NetworkModel.java b/api/src/main/java/com/cloud/network/NetworkModel.java
index a5bf5e4..002271a 100644
--- a/api/src/main/java/com/cloud/network/NetworkModel.java
+++ b/api/src/main/java/com/cloud/network/NetworkModel.java
@@ -282,7 +282,7 @@ public interface NetworkModel {
boolean isNetworkInlineMode(Network network);
- boolean isIP6AddressAvailableInNetwork(long networkId);
+ boolean areThereIPv6AddressAvailableInNetwork(long networkId);
boolean isIP6AddressAvailableInVlan(long vlanId);
diff --git a/api/src/main/java/com/cloud/network/NetworkService.java b/api/src/main/java/com/cloud/network/NetworkService.java
index d76d659..aa33def 100644
--- a/api/src/main/java/com/cloud/network/NetworkService.java
+++ b/api/src/main/java/com/cloud/network/NetworkService.java
@@ -34,6 +34,7 @@ import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.Network.IpAddresses;
import com.cloud.network.Network.Service;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.vpc.Vpc;
@@ -155,15 +156,6 @@ public interface NetworkService {
List<? extends Network> getIsolatedNetworksWithSourceNATOwnedByAccountInZone(long zoneId, Account owner);
- /**
- * @param networkId
- * @param entityId
- * @return
- * @throws ConcurrentOperationException
- * @throws ResourceUnavailableException
- * @throws ResourceAllocationException
- * @throws InsufficientAddressCapacityException
- */
IpAddress associateIPToNetwork(long ipId, long networkId) throws InsufficientAddressCapacityException, ResourceAllocationException, ResourceUnavailableException,
ConcurrentOperationException;
@@ -189,12 +181,16 @@ public interface NetworkService {
String netmask, long networkOwnerId, Long vpcId, Boolean sourceNat, Long networkOfferingId) throws ResourceAllocationException, ConcurrentOperationException,
InsufficientCapacityException;
- /* Requests an IP address for the guest nic */
- NicSecondaryIp allocateSecondaryGuestIP(long nicId, String ipaddress) throws InsufficientAddressCapacityException;
+ /**
+ * Requests an IP address for the guest NIC
+ */
+ NicSecondaryIp allocateSecondaryGuestIP(long nicId, IpAddresses requestedIpPair) throws InsufficientAddressCapacityException;
boolean releaseSecondaryIpFromNic(long ipAddressId);
- /* lists the nic informaton */
+ /**
+ * lists the NIC information
+ */
List<? extends Nic> listNics(ListNicsCmd listNicsCmd);
Map<Network.Capability, String> getNetworkOfferingServiceCapabilities(NetworkOffering offering, Service service);
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 009c4fd..ba465ad 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
@@ -29,7 +29,6 @@ import org.apache.cloudstack.context.CallContext;
import org.apache.log4j.Logger;
import com.cloud.dc.DataCenter;
-import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.event.EventTypes;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientAddressCapacityException;
@@ -38,6 +37,7 @@ import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.Network;
+import com.cloud.network.Network.IpAddresses;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.Nic;
import com.cloud.vm.NicSecondaryIp;
@@ -78,20 +78,6 @@ public class AddIpToVmNicCmd extends BaseAsyncCreateCmd {
return nicId;
}
- private String getIpaddress() {
- if (ipAddr != null) {
- return ipAddr;
- } else {
- return null;
- }
- }
-
- private NetworkType getNetworkType() {
- Network ntwk = _entityMgr.findById(Network.class, getNetworkId());
- DataCenter dc = _entityMgr.findById(DataCenter.class, ntwk.getDataCenterId());
- return dc.getNetworkType();
- }
-
private boolean isZoneSGEnabled() {
Network ntwk = _entityMgr.findById(Network.class, getNetworkId());
DataCenter dc = _entityMgr.findById(DataCenter.class, ntwk.getDataCenterId());
@@ -144,7 +130,6 @@ public class AddIpToVmNicCmd extends BaseAsyncCreateCmd {
}
}
-
@Override
public Long getSyncObjId() {
return getNetworkId();
@@ -169,17 +154,15 @@ public class AddIpToVmNicCmd extends BaseAsyncCreateCmd {
@Override
public void create() throws ResourceAllocationException {
- String ip;
NicSecondaryIp result;
- String secondaryIp = null;
- if ((ip = getIpaddress()) != null) {
- if (!NetUtils.isValidIp4(ip)) {
- throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Invalid ip address " + ip);
- }
+
+ IpAddresses requestedIpPair = new IpAddresses(ipAddr, null);
+ if (!NetUtils.isIpv4(ipAddr)) {
+ requestedIpPair = new IpAddresses(null, ipAddr);
}
try {
- result = _networkService.allocateSecondaryGuestIP(getNicId(), getIpaddress());
+ result = _networkService.allocateSecondaryGuestIP(getNicId(), requestedIpPair);
if (result != null) {
setEntityId(result.getId());
setEntityUuid(result.getUuid());
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RemoveIpFromVmNicCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RemoveIpFromVmNicCmd.java
index 19da39a..db84dc9 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RemoveIpFromVmNicCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RemoveIpFromVmNicCmd.java
@@ -147,10 +147,15 @@ public class RemoveIpFromVmNicCmd extends BaseAsyncCmd {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Invalid IP id is passed");
}
+ String secIp = nicSecIp.getIp4Address();
+ if (secIp == null) {
+ secIp = nicSecIp.getIp6Address();
+ }
+
if (isZoneSGEnabled()) {
//remove the security group rules for this secondary ip
boolean success = false;
- success = _securityGroupService.securityGroupRulesForVmSecIp(nicSecIp.getNicId(), nicSecIp.getIp4Address(), false);
+ success = _securityGroupService.securityGroupRulesForVmSecIp(nicSecIp.getNicId(), secIp, false);
if (success == false) {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to set security group rules for the secondary ip");
}
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 4139543..8a28305 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
@@ -61,7 +61,7 @@ public class AddIpToVmNicTest extends TestCase {
NicSecondaryIp secIp = Mockito.mock(NicSecondaryIp.class);
Mockito.when(
- networkService.allocateSecondaryGuestIP(Matchers.anyLong(), Matchers.anyString()))
+ networkService.allocateSecondaryGuestIP(Matchers.anyLong(), Matchers.any()))
.thenReturn(secIp);
ipTonicCmd._networkService = networkService;
@@ -81,7 +81,7 @@ public class AddIpToVmNicTest extends TestCase {
AddIpToVmNicCmd ipTonicCmd = Mockito.mock(AddIpToVmNicCmd.class);
Mockito.when(
- networkService.allocateSecondaryGuestIP(Matchers.anyLong(), Matchers.anyString()))
+ networkService.allocateSecondaryGuestIP(Matchers.anyLong(), Matchers.any()))
.thenReturn(null);
ipTonicCmd._networkService = networkService;
diff --git a/engine/components-api/src/main/java/com/cloud/network/IpAddressManager.java b/engine/components-api/src/main/java/com/cloud/network/IpAddressManager.java
index 256f026..a551278 100644
--- a/engine/components-api/src/main/java/com/cloud/network/IpAddressManager.java
+++ b/engine/components-api/src/main/java/com/cloud/network/IpAddressManager.java
@@ -166,18 +166,18 @@ public interface IpAddressManager {
* @throws ConcurrentOperationException
* @throws InsufficientAddressCapacityException
*/
- PublicIp assignDedicateIpAddress(Account owner, Long guestNtwkId, Long vpcId, long dcId, boolean isSourceNat) throws ConcurrentOperationException,
- InsufficientAddressCapacityException;
+ PublicIp assignDedicateIpAddress(Account owner, Long guestNtwkId, Long vpcId, long dcId, boolean isSourceNat)
+ throws ConcurrentOperationException, InsufficientAddressCapacityException;
- IpAddress allocateIp(Account ipOwner, boolean isSystem, Account caller, long callerId, DataCenter zone, Boolean displayIp) throws ConcurrentOperationException,
- ResourceAllocationException, InsufficientAddressCapacityException;
+ IpAddress allocateIp(Account ipOwner, boolean isSystem, Account caller, long callerId, DataCenter zone, Boolean displayIp)
+ throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException;
- PublicIp assignPublicIpAddressFromVlans(long dcId, Long podId, Account owner, VlanType type, List<Long> vlanDbIds, Long networkId, String requestedIp,
- boolean isSystem) throws InsufficientAddressCapacityException;
+ PublicIp assignPublicIpAddressFromVlans(long dcId, Long podId, Account owner, VlanType type, List<Long> vlanDbIds, Long networkId, String requestedIp, boolean isSystem)
+ throws InsufficientAddressCapacityException;
@DB
- void allocateNicValues(NicProfile nic, DataCenter dc, VirtualMachineProfile vm, Network network, String requestedIpv4,
- String requestedIpv6) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException;
+ void allocateNicValues(NicProfile nic, DataCenter dc, VirtualMachineProfile vm, Network network, String requestedIpv4, String requestedIpv6)
+ throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException;
int getRuleCountForIp(Long addressId, FirewallRule.Purpose purpose, FirewallRule.State state);
@@ -187,6 +187,8 @@ public interface IpAddressManager {
AcquirePodIpCmdResponse allocatePodIp(String zoneId, String podId) throws ConcurrentOperationException, ResourceAllocationException;
+ public boolean isIpEqualsGatewayOrNetworkOfferingsEmpty(Network network, String requestedIp);
+
void releasePodIp(Long id) throws CloudRuntimeException;
}
diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/NicIpAliasDaoImpl.java b/engine/schema/src/main/java/com/cloud/vm/dao/NicIpAliasDaoImpl.java
index d1453aa..887b3d7 100644
--- a/engine/schema/src/main/java/com/cloud/vm/dao/NicIpAliasDaoImpl.java
+++ b/engine/schema/src/main/java/com/cloud/vm/dao/NicIpAliasDaoImpl.java
@@ -113,6 +113,7 @@ public class NicIpAliasDaoImpl extends GenericDaoBase<NicIpAliasVO, Long> implem
List<String> ips = new ArrayList<String>(results.size());
for (NicIpAliasVO result : results) {
ips.add(result.getIp4Address());
+ ips.add(result.getIp6Address());
}
return ips;
}
diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/NicSecondaryIpDao.java b/engine/schema/src/main/java/com/cloud/vm/dao/NicSecondaryIpDao.java
index 96b80b8..cbb52e5 100644
--- a/engine/schema/src/main/java/com/cloud/vm/dao/NicSecondaryIpDao.java
+++ b/engine/schema/src/main/java/com/cloud/vm/dao/NicSecondaryIpDao.java
@@ -34,11 +34,7 @@ public interface NicSecondaryIpDao extends GenericDao<NicSecondaryIpVO, Long> {
NicSecondaryIpVO findByIp4AddressAndNetworkId(String ip4Address, long networkId);
- /**
- * @param networkId
- * @param instanceId
- * @return
- */
+ NicSecondaryIpVO findByIp6AddressAndNetworkId(String ip6Address, long networkId);
List<NicSecondaryIpVO> getSecondaryIpAddressesForVm(long vmId);
diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/NicSecondaryIpDaoImpl.java b/engine/schema/src/main/java/com/cloud/vm/dao/NicSecondaryIpDaoImpl.java
index 01f53bc..ba3a5c7 100644
--- a/engine/schema/src/main/java/com/cloud/vm/dao/NicSecondaryIpDaoImpl.java
+++ b/engine/schema/src/main/java/com/cloud/vm/dao/NicSecondaryIpDaoImpl.java
@@ -19,10 +19,9 @@ package com.cloud.vm.dao;
import java.util.ArrayList;
import java.util.List;
-
-import com.cloud.utils.StringUtils;
import org.springframework.stereotype.Component;
+import com.cloud.utils.StringUtils;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.SearchBuilder;
@@ -32,16 +31,18 @@ import com.cloud.utils.db.SearchCriteria.Op;
@Component
public class NicSecondaryIpDaoImpl extends GenericDaoBase<NicSecondaryIpVO, Long> implements NicSecondaryIpDao {
+
private final SearchBuilder<NicSecondaryIpVO> AllFieldsSearch;
private final GenericSearchBuilder<NicSecondaryIpVO, String> IpSearch;
protected GenericSearchBuilder<NicSecondaryIpVO, Long> CountByNicId;
- protected NicSecondaryIpDaoImpl() {
+ public NicSecondaryIpDaoImpl() {
super();
AllFieldsSearch = createSearchBuilder();
AllFieldsSearch.and("instanceId", AllFieldsSearch.entity().getVmId(), Op.EQ);
AllFieldsSearch.and("network", AllFieldsSearch.entity().getNetworkId(), Op.EQ);
AllFieldsSearch.and("address", AllFieldsSearch.entity().getIp4Address(), Op.LIKE);
+ AllFieldsSearch.and("ip6address", AllFieldsSearch.entity().getIp6Address(), Op.LIKE);
AllFieldsSearch.and("nicId", AllFieldsSearch.entity().getNicId(), Op.EQ);
AllFieldsSearch.done();
@@ -133,6 +134,14 @@ public class NicSecondaryIpDaoImpl extends GenericDaoBase<NicSecondaryIpVO, Long
}
@Override
+ public NicSecondaryIpVO findByIp6AddressAndNetworkId(String ip6Address, long networkId) {
+ SearchCriteria<NicSecondaryIpVO> sc = AllFieldsSearch.create();
+ sc.setParameters("network", networkId);
+ sc.setParameters("ip6address", ip6Address);
+ return findOneBy(sc);
+ }
+
+ @Override
public NicSecondaryIpVO findByIp4AddressAndNicId(String ip4Address, long nicId) {
SearchCriteria<NicSecondaryIpVO> sc = AllFieldsSearch.create();
sc.setParameters("address", ip4Address);
diff --git a/server/src/main/java/com/cloud/api/ApiResponseHelper.java b/server/src/main/java/com/cloud/api/ApiResponseHelper.java
index ba3d5c3..1bf1f45 100644
--- a/server/src/main/java/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/main/java/com/cloud/api/ApiResponseHelper.java
@@ -471,7 +471,7 @@ public class ApiResponseHelper implements ResponseGenerator {
cfgResponse.setCategory(cfg.getCategory());
cfgResponse.setDescription(cfg.getDescription());
cfgResponse.setName(cfg.getName());
- if(cfg.isEncrypted()) {
+ if (cfg.isEncrypted()) {
cfgResponse.setValue(DBEncryptionUtil.encrypt(cfg.getValue()));
} else {
cfgResponse.setValue(cfg.getValue());
@@ -3623,7 +3623,7 @@ public class ApiResponseHelper implements ResponseGenerator {
NicVO nic = _entityMgr.findById(NicVO.class, result.getNicId());
NetworkVO network = _entityMgr.findById(NetworkVO.class, result.getNetworkId());
response.setId(result.getUuid());
- response.setIpAddr(result.getIp4Address());
+ setResponseIpAddress(result, response);
response.setNicId(nic.getUuid());
response.setNwId(network.getUuid());
response.setObjectName("nicsecondaryip");
@@ -3631,6 +3631,17 @@ public class ApiResponseHelper implements ResponseGenerator {
}
/**
+ * Set the NicSecondaryIpResponse object with the IP address that is not null (IPv4 or IPv6)
+ */
+ public static void setResponseIpAddress(NicSecondaryIp result, NicSecondaryIpResponse response) {
+ if (result.getIp4Address() != null) {
+ response.setIpAddr(result.getIp4Address());
+ } else if (result.getIp6Address() != null) {
+ response.setIpAddr(result.getIp6Address());
+ }
+ }
+
+ /**
* The resulting Response attempts to be in line with what is returned from
* @see com.cloud.api.query.dao.UserVmJoinDaoImpl#setUserVmResponse(ResponseView, UserVmResponse, UserVmJoinVO)
*/
@@ -3706,7 +3717,7 @@ public class ApiResponseHelper implements ResponseGenerator {
for (NicSecondaryIpVO ip : secondaryIps) {
NicSecondaryIpResponse ipRes = new NicSecondaryIpResponse();
ipRes.setId(ip.getUuid());
- ipRes.setIpAddr(ip.getIp4Address());
+ setResponseIpAddress(ip, ipRes);
ipList.add(ipRes);
}
response.setSecondaryIps(ipList);
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 00ec61a..58d5e49 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
@@ -41,6 +41,7 @@ import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.cloud.api.ApiDBUtils;
+import com.cloud.api.ApiResponseHelper;
import com.cloud.api.query.vo.UserVmJoinVO;
import com.cloud.gpu.GPU;
import com.cloud.service.ServiceOfferingDetailsVO;
@@ -267,15 +268,14 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
for (NicSecondaryIpVO ip : secondaryIps) {
NicSecondaryIpResponse ipRes = new NicSecondaryIpResponse();
ipRes.setId(ip.getUuid());
- ipRes.setIpAddr(ip.getIp4Address());
+ ApiResponseHelper.setResponseIpAddress(ip, ipRes);
ipList.add(ipRes);
}
nicResponse.setSecondaryIps(ipList);
}
nicResponse.setObjectName("nic");
- List<NicExtraDhcpOptionResponse> nicExtraDhcpOptionResponses = _nicExtraDhcpOptionDao.listByNicId(nic_id)
- .stream()
+ List<NicExtraDhcpOptionResponse> nicExtraDhcpOptionResponses = _nicExtraDhcpOptionDao.listByNicId(nic_id).stream()
.map(vo -> new NicExtraDhcpOptionResponse(Dhcp.DhcpOptionCode.valueOfInt(vo.getCode()).getName(), vo.getCode(), vo.getValue()))
.collect(Collectors.toList());
nicResponse.setExtraDhcpOptions(nicExtraDhcpOptionResponses);
@@ -400,7 +400,7 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
for (NicSecondaryIpVO ip : secondaryIps) {
NicSecondaryIpResponse ipRes = new NicSecondaryIpResponse();
ipRes.setId(ip.getUuid());
- ipRes.setIpAddr(ip.getIp4Address());
+ ApiResponseHelper.setResponseIpAddress(ip, ipRes);
ipList.add(ipRes);
}
nicResponse.setSecondaryIps(ipList);
diff --git a/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java b/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java
index 71acc83..ec7adfd 100644
--- a/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java
+++ b/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java
@@ -179,25 +179,25 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
private static final Logger s_logger = Logger.getLogger(IpAddressManagerImpl.class);
@Inject
- NetworkOrchestrationService _networkMgr = null;
+ NetworkOrchestrationService _networkMgr;
@Inject
- EntityManager _entityMgr = null;
+ EntityManager _entityMgr;
@Inject
- DataCenterDao _dcDao = null;
+ DataCenterDao _dcDao;
@Inject
- VlanDao _vlanDao = null;
+ VlanDao _vlanDao;
@Inject
- IPAddressDao _ipAddressDao = null;
+ IPAddressDao _ipAddressDao;
@Inject
- AccountDao _accountDao = null;
+ AccountDao _accountDao;
@Inject
- DomainDao _domainDao = null;
+ DomainDao _domainDao;
@Inject
- UserDao _userDao = null;
+ UserDao _userDao;
@Inject
ConfigurationDao _configDao;
@Inject
- UserVmDao _userVmDao = null;
+ UserVmDao _userVmDao;
@Inject
AlertManager _alertMgr;
@Inject
@@ -209,11 +209,11 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
@Inject
DomainVlanMapDao _domainVlanMapDao;
@Inject
- NetworkOfferingDao _networkOfferingDao = null;
+ NetworkOfferingDao _networkOfferingDao;
@Inject
- NetworkDao _networksDao = null;
+ NetworkDao _networksDao;
@Inject
- NicDao _nicDao = null;
+ NicDao _nicDao;
@Inject
RulesManager _rulesMgr;
@Inject
@@ -300,6 +300,8 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
Boolean.class, "system.vm.public.ip.reservation.mode.strictness", "false",
"If enabled, the use of System VMs public IP reservation is strict, preferred if not.", false, ConfigKey.Scope.Global);
+ private Random rand = new Random(System.currentTimeMillis());
+
@Override
public boolean configure(String name, Map<String, Object> params) {
// populate providers
@@ -1840,11 +1842,9 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
return requestedIp;
}
- return NetUtils.long2Ip(array[_rand.nextInt(array.length)]);
+ return NetUtils.long2Ip(array[rand.nextInt(array.length)]);
}
- Random _rand = new Random(System.currentTimeMillis());
-
/**
* Get the list of public IPs that need to be applied for a static NAT enable/disable operation.
* Manipulating only these ips prevents concurrency issues when disabling static nat at the same time.
@@ -2184,4 +2184,18 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey<?>[] {UseSystemPublicIps, RulesContinueOnError, SystemVmPublicIpReservationModeStrictness};
}
+
+ /**
+ * Returns true if the given IP address is equals the gateway or there is no network offerrings for the given network
+ */
+ @Override
+ public boolean isIpEqualsGatewayOrNetworkOfferingsEmpty(Network network, String requestedIp) {
+ if (requestedIp.equals(network.getGateway()) || requestedIp.equals(network.getIp6Gateway())) {
+ return true;
+ }
+ if (_networkModel.listNetworkOfferingServices(network.getNetworkOfferingId()).isEmpty() && network.getCidr() == null) {
+ return true;
+ }
+ return false;
+ }
}
diff --git a/server/src/main/java/com/cloud/network/Ipv6AddressManager.java b/server/src/main/java/com/cloud/network/Ipv6AddressManager.java
index 8a7049b..4db3ec1 100644
--- a/server/src/main/java/com/cloud/network/Ipv6AddressManager.java
+++ b/server/src/main/java/com/cloud/network/Ipv6AddressManager.java
@@ -26,4 +26,11 @@ public interface Ipv6AddressManager extends Manager {
public UserIpv6Address assignDirectIp6Address(long dcId, Account owner, Long networkId, String requestedIp6) throws InsufficientAddressCapacityException;
public void revokeDirectIpv6Address(long networkId, String ip6Address);
+
+ public String allocateGuestIpv6(Network network, String requestedIpv6) throws InsufficientAddressCapacityException;
+
+ public String allocatePublicIp6ForGuestNic(Network network, Long podId, Account ipOwner, String requestedIp) throws InsufficientAddressCapacityException;
+
+ public String acquireGuestIpv6Address(Network network, String requestedIpv6) throws InsufficientAddressCapacityException;
+
}
diff --git a/server/src/main/java/com/cloud/network/Ipv6AddressManagerImpl.java b/server/src/main/java/com/cloud/network/Ipv6AddressManagerImpl.java
index 53fb25c..1cb432e 100644
--- a/server/src/main/java/com/cloud/network/Ipv6AddressManagerImpl.java
+++ b/server/src/main/java/com/cloud/network/Ipv6AddressManagerImpl.java
@@ -23,9 +23,8 @@ import java.util.Map;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
-import org.apache.log4j.Logger;
-
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.log4j.Logger;
import com.cloud.configuration.Config;
import com.cloud.dc.DataCenter;
@@ -35,13 +34,21 @@ import com.cloud.dc.VlanVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.VlanDao;
import com.cloud.exception.InsufficientAddressCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.network.IpAddress.State;
+import com.cloud.network.Network.IpAddresses;
+import com.cloud.network.dao.IPAddressDao;
+import com.cloud.network.dao.IPAddressVO;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.UserIpv6AddressDao;
import com.cloud.user.Account;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.component.ManagerBase;
+import com.cloud.utils.db.DB;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
+import com.cloud.vm.dao.NicSecondaryIpDao;
+import com.cloud.vm.dao.NicSecondaryIpVO;
public class Ipv6AddressManagerImpl extends ManagerBase implements Ipv6AddressManager {
public static final Logger s_logger = Logger.getLogger(Ipv6AddressManagerImpl.class.getName());
@@ -61,6 +68,12 @@ public class Ipv6AddressManagerImpl extends ManagerBase implements Ipv6AddressMa
NetworkDao _networkDao;
@Inject
ConfigurationDao _configDao;
+ @Inject
+ IpAddressManager ipAddressManager;
+ @Inject
+ NicSecondaryIpDao nicSecondaryIpDao;
+ @Inject
+ IPAddressDao ipAddressDao;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
@@ -84,7 +97,7 @@ public class Ipv6AddressManagerImpl extends ManagerBase implements Ipv6AddressMa
String ip = null;
Vlan ipVlan = null;
if (requestedIp6 == null) {
- if (!_networkModel.isIP6AddressAvailableInNetwork(networkId)) {
+ if (!_networkModel.areThereIPv6AddressAvailableInNetwork(networkId)) {
throw new InsufficientAddressCapacityException("There is no more address available in the network " + network.getName(), DataCenter.class,
network.getDataCenterId());
}
@@ -132,7 +145,7 @@ public class Ipv6AddressManagerImpl extends ManagerBase implements Ipv6AddressMa
dc.setMacAddress(nextMac);
_dcDao.update(dc.getId(), dc);
- String macAddress = NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(mac,NetworkModel.MACIdentifier.value()));
+ String macAddress = NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(mac, NetworkModel.MACIdentifier.value()));
UserIpv6AddressVO ipVO = new UserIpv6AddressVO(ip, dcId, macAddress, ipVlan.getId());
ipVO.setPhysicalNetworkId(network.getPhysicalNetworkId());
ipVO.setSourceNetworkId(networkId);
@@ -150,4 +163,101 @@ public class Ipv6AddressManagerImpl extends ManagerBase implements Ipv6AddressMa
_ipv6Dao.remove(ip.getId());
}
}
+
+ /**
+ * Executes method {@link #acquireGuestIpv6Address(Network, String)} and returns the requested IPv6 (String) in case of successfully allocating the guest IPv6 address.
+ */
+ @Override
+ public String allocateGuestIpv6(Network network, String requestedIpv6) throws InsufficientAddressCapacityException {
+ return acquireGuestIpv6Address(network, requestedIpv6);
+ }
+
+ /**
+ * Allocates a guest IPv6 address for the guest NIC. It will throw exceptions in the following cases:
+ * <ul>
+ * <li>there is no IPv6 address available in the network;</li>
+ * <li>IPv6 address is equals to the Gateway;</li>
+ * <li>the network offering is empty;</li>
+ * <li>the IPv6 address is not in the network;</li>
+ * <li>the requested IPv6 address is already in use in the network.</li>
+ * </ul>
+ */
+ @Override
+ @DB
+ public String acquireGuestIpv6Address(Network network, String requestedIpv6) throws InsufficientAddressCapacityException {
+ if (!_networkModel.areThereIPv6AddressAvailableInNetwork(network.getId())) {
+ throw new InsufficientAddressCapacityException(
+ String.format("There is no IPv6 address available in the network [name=%s, network id=%s]", network.getName(), network.getId()), DataCenter.class,
+ network.getDataCenterId());
+ }
+
+ checkIfCanAllocateIpv6Address(network, requestedIpv6);
+
+ IpAddresses requestedIpPair = new IpAddresses(null, requestedIpv6);
+ _networkModel.checkRequestedIpAddresses(network.getId(), requestedIpPair);
+
+ IPAddressVO ip = ipAddressDao.findByIpAndSourceNetworkId(network.getId(), requestedIpv6);
+ if (ip != null) {
+ State ipState = ip.getState();
+ if (ipState != State.Free) {
+ throw new InsufficientAddressCapacityException(String.format("Requested ip address [%s] is not free [ip state=%]", requestedIpv6, ipState), DataCenter.class,
+ network.getDataCenterId());
+ }
+ }
+ return requestedIpv6;
+ }
+
+ /**
+ * Allocates a public IPv6 address for the guest NIC. It will throw exceptions in the following cases:
+ * <ul>
+ * <li>the the requested IPv6 address is already in use in the network;</li>
+ * <li>IPv6 address is equals to the Gateway;</li>
+ * <li>the network offering is empty;</li>
+ * <li>the IPv6 address is not in the network.</li>
+ * </ul>
+ */
+ @Override
+ public String allocatePublicIp6ForGuestNic(Network network, Long podId, Account owner, String requestedIpv6) throws InsufficientAddressCapacityException {
+ checkIfCanAllocateIpv6Address(network, requestedIpv6);
+
+ return requestedIpv6;
+ }
+
+ /**
+ * Performs some checks on the given IPv6 address. It will throw exceptions in the following cases:
+ * <ul>
+ * <li>the the requested IPv6 address is already in use in the network;</li>
+ * <li>IPv6 address is equals to the Gateway;</li>
+ * <li>the network offering is empty;</li>
+ * <li>the IPv6 address is not in the network.</li>
+ * </ul>
+ */
+ protected void checkIfCanAllocateIpv6Address(Network network, String ipv6) throws InsufficientAddressCapacityException {
+ if (isIp6Taken(network, ipv6)) {
+ throw new InsufficientAddressCapacityException(
+ String.format("The IPv6 address [%s] is already in use in the network [id=%s, name=%s]", ipv6, network.getId(), network.getName()), Network.class,
+ network.getId());
+ }
+
+ if (ipAddressManager.isIpEqualsGatewayOrNetworkOfferingsEmpty(network, ipv6)) {
+ throw new InvalidParameterValueException(
+ String.format("The network [id=%s] offering is empty or the requested IP address [%s] is equals to the Gateway", network.getId(), ipv6));
+ }
+
+ String networkIp6Cidr = network.getIp6Cidr();
+ if (!NetUtils.isIp6InNetwork(ipv6, networkIp6Cidr)) {
+ throw new InvalidParameterValueException(
+ String.format("The IPv6 address [%s] is not in the network [id=%s, name=%s, ipv6cidr=%s]", ipv6, network.getId(), network.getName(), network.getIp6Cidr()));
+ }
+ }
+
+ /**
+ * Returns false if the requested ipv6 address is taken by some VM, checking on the 'user_ipv6_address' table or 'nic_secondary_ips' table.
+ */
+ protected boolean isIp6Taken(Network network, String requestedIpv6) {
+ UserIpv6AddressVO ip6Vo = _ipv6Dao.findByNetworkIdAndIp(network.getId(), requestedIpv6);
+ NicSecondaryIpVO nicSecondaryIpVO = nicSecondaryIpDao.findByIp6AddressAndNetworkId(requestedIpv6, network.getId());
+ return ip6Vo != null || nicSecondaryIpVO != null;
+ }
+
}
diff --git a/server/src/main/java/com/cloud/network/NetworkModelImpl.java b/server/src/main/java/com/cloud/network/NetworkModelImpl.java
index bb1a181..c23de72 100644
--- a/server/src/main/java/com/cloud/network/NetworkModelImpl.java
+++ b/server/src/main/java/com/cloud/network/NetworkModelImpl.java
@@ -592,7 +592,7 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel, Confi
return false;
}
if (network.getIp6Gateway() != null) {
- hasFreeIps = isIP6AddressAvailableInNetwork(network.getId());
+ hasFreeIps = areThereIPv6AddressAvailableInNetwork(network.getId());
}
} else {
if (network.getCidr() == null) {
@@ -606,7 +606,7 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel, Confi
}
@Override
- public boolean isIP6AddressAvailableInNetwork(long networkId) {
+ public boolean areThereIPv6AddressAvailableInNetwork(long networkId) {
Network network = _networksDao.findById(networkId);
if (network == null) {
return false;
diff --git a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java
index f1397a1..a8932a8 100644
--- a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java
+++ b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java
@@ -34,11 +34,10 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
+
import javax.inject.Inject;
import javax.naming.ConfigurationException;
-import org.apache.log4j.Logger;
-
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.api.ApiConstants;
@@ -58,6 +57,7 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.framework.messagebus.MessageBus;
import org.apache.cloudstack.framework.messagebus.PublishScope;
import org.apache.cloudstack.network.element.InternalLoadBalancerElementService;
+import org.apache.log4j.Logger;
import com.cloud.api.ApiDBUtils;
import com.cloud.configuration.Config;
@@ -91,6 +91,7 @@ import com.cloud.host.dao.HostDao;
import com.cloud.network.IpAddress.State;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.GuestType;
+import com.cloud.network.Network.IpAddresses;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.Networks.BroadcastDomainType;
@@ -293,6 +294,8 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
@Inject
IpAddressManager _ipAddrMgr;
@Inject
+ Ipv6AddressManager ipv6AddrMgr;
+ @Inject
EntityManager _entityMgr;
@Inject
public SecurityGroupService _securityGroupService;
@@ -642,13 +645,16 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
}
@Override
- @ActionEvent(eventType = EventTypes.EVENT_NIC_SECONDARY_IP_CONFIGURE, eventDescription = "Configuring secondary ip " +
- "rules", async = true)
+ @ActionEvent(eventType = EventTypes.EVENT_NIC_SECONDARY_IP_CONFIGURE, eventDescription = "Configuring secondary ip " + "rules", async = true)
public boolean configureNicSecondaryIp(NicSecondaryIp secIp, boolean isZoneSgEnabled) {
boolean success = false;
+ String secondaryIp = secIp.getIp4Address();
+ if (secIp.getIp4Address() == null) {
+ secondaryIp = secIp.getIp6Address();
+ }
if (isZoneSgEnabled) {
- success = _securityGroupService.securityGroupRulesForVmSecIp(secIp.getNicId(), secIp.getIp4Address(), true);
+ success = _securityGroupService.securityGroupRulesForVmSecIp(secIp.getNicId(), secondaryIp, true);
s_logger.info("Associated ip address to NIC : " + secIp.getIp4Address());
} else {
success = true;
@@ -656,11 +662,16 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
return success;
}
+ /**
+ * It allocates a secondary IP alias on the NIC. It can be either an Ipv4 or an Ipv6 or even both, according to the the given IpAddresses object.
+ */
@Override
@ActionEvent(eventType = EventTypes.EVENT_NIC_SECONDARY_IP_ASSIGN, eventDescription = "assigning secondary ip to nic", create = true)
- public NicSecondaryIp allocateSecondaryGuestIP(final long nicId, String requestedIp) throws InsufficientAddressCapacityException {
+ public NicSecondaryIp allocateSecondaryGuestIP(final long nicId, IpAddresses requestedIpPair) throws InsufficientAddressCapacityException {
Account caller = CallContext.current().getCallingAccount();
+ String ipv4Address = requestedIpPair.getIp4Address();
+ String ipv6Address = requestedIpPair.getIp6Address();
//check whether the nic belongs to user vm.
final NicVO nicVO = _nicDao.findById(nicId);
@@ -690,18 +701,23 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
int maxAllowedIpsPerNic = NumbersUtil.parseInt(_configDao.getValue(Config.MaxNumberOfSecondaryIPsPerNIC.key()), 10);
Long nicWiseIpCount = _nicSecondaryIpDao.countByNicId(nicId);
- if(nicWiseIpCount.intValue() >= maxAllowedIpsPerNic) {
- s_logger.error("Maximum Number of Ips \"vm.network.nic.max.secondary.ipaddresses = \"" + maxAllowedIpsPerNic + " per Nic has been crossed for the nic " + nicId + ".");
+ if (nicWiseIpCount.intValue() >= maxAllowedIpsPerNic) {
+ s_logger.error("Maximum Number of Ips \"vm.network.nic.max.secondary.ipaddresses = \"" + maxAllowedIpsPerNic + " per Nic has been crossed for the nic " + nicId + ".");
throw new InsufficientAddressCapacityException("Maximum Number of Ips per Nic has been crossed.", Nic.class, nicId);
}
-
s_logger.debug("Calling the ip allocation ...");
String ipaddr = null;
+ String ip6addr = null;
//Isolated network can exist in Basic zone only, so no need to verify the zone type
if (network.getGuestType() == Network.GuestType.Isolated) {
try {
- ipaddr = _ipAddrMgr.allocateGuestIP(network, requestedIp);
+ if (ipv4Address != null) {
+ ipaddr = _ipAddrMgr.allocateGuestIP(network, ipv4Address);
+ }
+ if (ipv6Address != null) {
+ ip6addr = ipv6AddrMgr.allocateGuestIpv6(network, ipv6Address);
+ }
} catch (InsufficientAddressCapacityException e) {
throw new InvalidParameterValueException("Allocating guest ip for nic failed");
}
@@ -711,16 +727,21 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
DataCenter dc = _dcDao.findById(network.getDataCenterId());
if (dc.getNetworkType() == NetworkType.Basic) {
- VMInstanceVO vmi = (VMInstanceVO)vm;
+ VMInstanceVO vmi = (VMInstanceVO)vm;
podId = vmi.getPodIdToDeployIn();
- if (podId == null) {
+ if (podId == null) {
throw new InvalidParameterValueException("vm pod id is null in Basic zone; can't decide the range for ip allocation");
- }
+ }
}
try {
- ipaddr = _ipAddrMgr.allocatePublicIpForGuestNic(network, podId, ipOwner, requestedIp);
- if (ipaddr == null) {
+ if (ipv4Address != null) {
+ ipaddr = _ipAddrMgr.allocatePublicIpForGuestNic(network, podId, ipOwner, ipv4Address);
+ }
+ if (ipv6Address != null) {
+ ip6addr = ipv6AddrMgr.allocatePublicIp6ForGuestNic(network, podId, ipOwner, ipv6Address);
+ }
+ if (ipaddr == null && ipv6Address == null) {
throw new InvalidParameterValueException("Allocating ip to guest nic " + nicId + " failed");
}
} catch (InsufficientAddressCapacityException e) {
@@ -732,29 +753,30 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
return null;
}
- if (ipaddr != null) {
+ if (ipaddr != null || ip6addr != null) {
// we got the ip addr so up the nics table and secodary ip
- final String addrFinal = ipaddr;
+ final String ip4AddrFinal = ipaddr;
+ final String ip6AddrFinal = ip6addr;
long id = Transaction.execute(new TransactionCallback<Long>() {
@Override
public Long doInTransaction(TransactionStatus status) {
- boolean nicSecondaryIpSet = nicVO.getSecondaryIp();
- if (!nicSecondaryIpSet) {
- nicVO.setSecondaryIp(true);
- // commit when previously set ??
- s_logger.debug("Setting nics table ...");
- _nicDao.update(nicId, nicVO);
- }
+ boolean nicSecondaryIpSet = nicVO.getSecondaryIp();
+ if (!nicSecondaryIpSet) {
+ nicVO.setSecondaryIp(true);
+ // commit when previously set ??
+ s_logger.debug("Setting nics table ...");
+ _nicDao.update(nicId, nicVO);
+ }
- s_logger.debug("Setting nic_secondary_ip table ...");
+ s_logger.debug("Setting nic_secondary_ip table ...");
Long vmId = nicVO.getInstanceId();
- NicSecondaryIpVO secondaryIpVO = new NicSecondaryIpVO(nicId, addrFinal, vmId, ipOwner.getId(), ipOwner.getDomainId(), networkId);
- _nicSecondaryIpDao.persist(secondaryIpVO);
+ NicSecondaryIpVO secondaryIpVO = new NicSecondaryIpVO(nicId, ip4AddrFinal, ip6AddrFinal, vmId, ipOwner.getId(), ipOwner.getDomainId(), networkId);
+ _nicSecondaryIpDao.persist(secondaryIpVO);
return secondaryIpVO.getId();
}
});
- return getNicSecondaryIp(id);
+ return getNicSecondaryIp(id);
} else {
return null;
}
diff --git a/server/src/main/java/com/cloud/network/guru/DirectNetworkGuru.java b/server/src/main/java/com/cloud/network/guru/DirectNetworkGuru.java
index 3edc8d2..5150ad7 100644
--- a/server/src/main/java/com/cloud/network/guru/DirectNetworkGuru.java
+++ b/server/src/main/java/com/cloud/network/guru/DirectNetworkGuru.java
@@ -45,6 +45,7 @@ import com.cloud.network.Network.Service;
import com.cloud.network.Network.State;
import com.cloud.network.NetworkModel;
import com.cloud.network.NetworkProfile;
+import com.cloud.network.NetworkService;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.Mode;
import com.cloud.network.Networks.TrafficType;
@@ -65,6 +66,7 @@ import com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn;
import com.cloud.utils.db.TransactionStatus;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.ExceptionUtil;
+import com.cloud.utils.net.NetUtils;
import com.cloud.vm.Nic;
import com.cloud.vm.Nic.ReservationStrategy;
import com.cloud.vm.NicProfile;
@@ -74,6 +76,7 @@ import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.NicSecondaryIpDao;
+import com.cloud.vm.dao.NicSecondaryIpVO;
public class DirectNetworkGuru extends AdapterBase implements NetworkGuru {
@@ -105,6 +108,10 @@ public class DirectNetworkGuru extends AdapterBase implements NetworkGuru {
NetworkOfferingServiceMapDao _ntwkOfferingSrvcDao;
@Inject
PhysicalNetworkDao _physicalNetworkDao;
+ @Inject
+ private NetworkService networkService;
+ @Inject
+ private NicSecondaryIpDao nicSecondaryIpDao;
private static final TrafficType[] TrafficTypes = {TrafficType.Guest};
protected IsolationMethod[] _isolationMethods;
@@ -338,9 +345,16 @@ public class DirectNetworkGuru extends AdapterBase implements NetworkGuru {
List<String> nicSecIps = null;
nicSecIps = _nicSecondaryIpDao.getSecondaryIpAddressesForNic(nic.getId());
for (String secIp : nicSecIps) {
- IPAddressVO pubIp = _ipAddressDao.findByIpAndSourceNetworkId(nic.getNetworkId(), secIp);
- _ipAddrMgr.markIpAsUnavailable(pubIp.getId());
- _ipAddressDao.unassignIpAddress(pubIp.getId());
+ if (NetUtils.isValidIp4(secIp)) {
+ IPAddressVO pubIp = _ipAddressDao.findByIpAndSourceNetworkId(nic.getNetworkId(), secIp);
+ _ipAddrMgr.markIpAsUnavailable(pubIp.getId());
+ _ipAddressDao.unassignIpAddress(pubIp.getId());
+ } else {
+ NicSecondaryIpVO nicSecIp = nicSecondaryIpDao.findByIp6AddressAndNetworkId(secIp, nic.getNetworkId());
+ if (nicSecIp != null) {
+ networkService.releaseSecondaryIpFromNic(nicSecIp.getId());
+ }
+ }
}
}
});
diff --git a/server/src/test/java/com/cloud/api/ApiResponseHelperTest.java b/server/src/test/java/com/cloud/api/ApiResponseHelperTest.java
index eda7ca4..2809005 100644
--- a/server/src/test/java/com/cloud/api/ApiResponseHelperTest.java
+++ b/server/src/test/java/com/cloud/api/ApiResponseHelperTest.java
@@ -19,6 +19,9 @@ package com.cloud.api;
import com.cloud.domain.DomainVO;
import com.cloud.usage.UsageVO;
import com.cloud.user.AccountVO;
+import com.cloud.vm.NicSecondaryIp;
+
+import org.apache.cloudstack.api.response.NicSecondaryIpResponse;
import org.apache.cloudstack.api.response.UsageRecordResponse;
import org.apache.cloudstack.usage.UsageService;
import org.junit.Before;
@@ -37,6 +40,7 @@ import java.util.Date;
import java.util.TimeZone;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Mockito.when;
@@ -109,4 +113,32 @@ public class ApiResponseHelperTest {
UsageRecordResponse MockResponse = helper.createUsageResponse(usage);
assertEquals("DomainName",MockResponse.getDomainName());
}
+
+ @Test
+ public void setResponseIpAddressTestIpv4() {
+ NicSecondaryIp result = Mockito.mock(NicSecondaryIp.class);
+ NicSecondaryIpResponse response = new NicSecondaryIpResponse();
+ setResult(result, "ipv4", "ipv6");
+
+ ApiResponseHelper.setResponseIpAddress(result, response);
+
+ assertTrue(response.getIpAddr().equals("ipv4"));
+ }
+
+ private void setResult(NicSecondaryIp result, String ipv4, String ipv6) {
+ when(result.getIp4Address()).thenReturn(ipv4);
+ when(result.getIp6Address()).thenReturn(ipv6);
+ }
+
+ @Test
+ public void setResponseIpAddressTestIpv6() {
+ NicSecondaryIp result = Mockito.mock(NicSecondaryIp.class);
+ NicSecondaryIpResponse response = new NicSecondaryIpResponse();
+ setResult(result, null, "ipv6");
+
+ ApiResponseHelper.setResponseIpAddress(result, response);
+
+ assertTrue(response.getIpAddr().equals("ipv6"));
+ }
+
}
diff --git a/server/src/test/java/com/cloud/network/IpAddressManagerTest.java b/server/src/test/java/com/cloud/network/IpAddressManagerTest.java
index 0bf92ee..2bf989c 100644
--- a/server/src/test/java/com/cloud/network/IpAddressManagerTest.java
+++ b/server/src/test/java/com/cloud/network/IpAddressManagerTest.java
@@ -17,27 +17,29 @@
package com.cloud.network;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import com.cloud.network.Network.Service;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.IPAddressVO;
import com.cloud.network.rules.StaticNat;
import com.cloud.network.rules.StaticNatImpl;
import com.cloud.utils.net.Ip;
-import static org.mockito.Mockito.when;
-
-import java.util.Collections;
-import java.util.List;
-
-import static org.mockito.Mockito.anyLong;
-import static org.mockito.Mockito.mock;
-
public class IpAddressManagerTest {
@Mock
@@ -46,6 +48,9 @@ public class IpAddressManagerTest {
@InjectMocks
IpAddressManagerImpl _ipManager;
+ @InjectMocks
+ NetworkModelImpl networkModel = Mockito.spy(new NetworkModelImpl());
+
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
@@ -68,4 +73,68 @@ public class IpAddressManagerTest {
IPAddressVO returnedVO = ips.get(0);
Assert.assertEquals(vo, returnedVO);
}
-}
+
+ @Test
+ public void isIpEqualsGatewayOrNetworkOfferingsEmptyTestRequestedIpEqualsIp6Gateway() {
+ Network network = setTestIsIpEqualsGatewayOrNetworkOfferingsEmpty(0l, "gateway", "ip6Gateway", null, new ArrayList<Service>());
+
+ boolean result = _ipManager.isIpEqualsGatewayOrNetworkOfferingsEmpty(network, "ip6Gateway");
+
+ Mockito.verify(networkModel, Mockito.times(0)).listNetworkOfferingServices(Mockito.anyLong());
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void isIpEqualsGatewayOrNetworkOfferingsEmptyTestRequestedIpEqualsGateway() {
+ Network network = setTestIsIpEqualsGatewayOrNetworkOfferingsEmpty(0l, "gateway", "ip6Gateway", null, new ArrayList<Service>());
+
+ boolean result = _ipManager.isIpEqualsGatewayOrNetworkOfferingsEmpty(network, "gateway");
+
+ Mockito.verify(networkModel, Mockito.times(0)).listNetworkOfferingServices(Mockito.anyLong());
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void isIpEqualsGatewayOrNetworkOfferingsEmptyTestExpectFalseServicesNotEmpty() {
+ List<Service> services = new ArrayList<Service>();
+ Service serviceGateway = new Service("Gateway");
+ services.add(serviceGateway);
+ Network network = setTestIsIpEqualsGatewayOrNetworkOfferingsEmpty(0l, "gateway", "ip6Gateway", null, services);
+
+ boolean result = _ipManager.isIpEqualsGatewayOrNetworkOfferingsEmpty(network, "requestedIp");
+
+ Mockito.verify(networkModel).listNetworkOfferingServices(Mockito.anyLong());
+ Assert.assertFalse(result);
+ }
+
+ @Test
+ public void isIpEqualsGatewayOrNetworkOfferingsEmptyTestExpectFalseServicesCidrNotNull() {
+ Network network = setTestIsIpEqualsGatewayOrNetworkOfferingsEmpty(0l, "gateway", "ip6Gateway", "cidr", new ArrayList<Service>());
+
+ boolean result = _ipManager.isIpEqualsGatewayOrNetworkOfferingsEmpty(network, "requestedIp");
+
+ Mockito.verify(networkModel).listNetworkOfferingServices(Mockito.anyLong());
+ Assert.assertFalse(result);
+ }
+
+ @Test
+ public void isIpEqualsGatewayOrNetworkOfferingsEmptyTestNetworkOfferingsEmptyAndCidrNull() {
+ Network network = setTestIsIpEqualsGatewayOrNetworkOfferingsEmpty(0l, "gateway", "ip6Gateway", null, new ArrayList<Service>());
+
+ boolean result = _ipManager.isIpEqualsGatewayOrNetworkOfferingsEmpty(network, "requestedIp");
+
+ Mockito.verify(networkModel).listNetworkOfferingServices(Mockito.anyLong());
+ Assert.assertTrue(result);
+ }
+
+ private Network setTestIsIpEqualsGatewayOrNetworkOfferingsEmpty(long networkOfferingId, String gateway, String ip6Gateway, String cidr, List<Service> services) {
+ Network network = mock(Network.class);
+ Mockito.when(network.getNetworkOfferingId()).thenReturn(networkOfferingId);
+ Mockito.when(network.getGateway()).thenReturn(gateway);
+ Mockito.when(network.getIp6Gateway()).thenReturn(ip6Gateway);
+ Mockito.when(network.getCidr()).thenReturn(cidr);
+ Mockito.doReturn(services).when(networkModel).listNetworkOfferingServices(Mockito.anyLong());
+ return network;
+ }
+
+}
\ No newline at end of file
diff --git a/server/src/test/java/com/cloud/network/Ipv6AddressManagerTest.java b/server/src/test/java/com/cloud/network/Ipv6AddressManagerTest.java
new file mode 100644
index 0000000..26ca8f4
--- /dev/null
+++ b/server/src/test/java/com/cloud/network/Ipv6AddressManagerTest.java
@@ -0,0 +1,229 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package com.cloud.network;
+
+import static org.mockito.Mockito.mock;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import com.cloud.exception.InsufficientAddressCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.network.IpAddress.State;
+import com.cloud.network.Network.IpAddresses;
+import com.cloud.network.dao.IPAddressDaoImpl;
+import com.cloud.network.dao.IPAddressVO;
+import com.cloud.network.dao.UserIpv6AddressDaoImpl;
+import com.cloud.user.Account;
+import com.cloud.utils.net.NetUtils;
+import com.cloud.vm.dao.NicSecondaryIpDaoImpl;
+import com.cloud.vm.dao.NicSecondaryIpVO;
+
+public class Ipv6AddressManagerTest {
+
+ @InjectMocks
+ Ipv6AddressManagerImpl ip6Manager = Mockito.spy(new Ipv6AddressManagerImpl());
+
+ @InjectMocks
+ NicSecondaryIpDaoImpl nicSecondaryIpDao = Mockito.spy(new NicSecondaryIpDaoImpl());
+
+ @InjectMocks
+ UserIpv6AddressDaoImpl ipv6Dao = Mockito.spy(new UserIpv6AddressDaoImpl());
+
+ @InjectMocks
+ IpAddressManagerImpl ipAddressManager = Mockito.spy(new IpAddressManagerImpl());
+
+ @InjectMocks
+ NetworkModelImpl networkModel = Mockito.mock(NetworkModelImpl.class);// = Mockito.spy(new NetworkModelImpl());
+
+ @InjectMocks
+ IPAddressDaoImpl ipAddressDao = Mockito.spy(new IPAddressDaoImpl());
+
+ private Network network = mockNetwork();
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void isIp6TakenTestNoNull() {
+ setIsIp6TakenTest(new UserIpv6AddressVO(), new NicSecondaryIpVO(0l, "ipaddr", 0l, 0l, 0l, 0l));
+ boolean result = ip6Manager.isIp6Taken(network, "requestedIpv6");
+ assertAndVerifyIsIp6Taken(true, result);
+ }
+
+ @Test
+ public void isIp6TakenTestSecIpNull() {
+ setIsIp6TakenTest(new UserIpv6AddressVO(), null);
+ boolean result = ip6Manager.isIp6Taken(network, "requestedIpv6");
+ assertAndVerifyIsIp6Taken(true, result);
+ }
+
+ @Test
+ public void isIp6TakenTestUserIpv6AddressNull() {
+ setIsIp6TakenTest(null, new NicSecondaryIpVO(0l, "ipaddr", 0l, 0l, 0l, 0l));
+ boolean result = ip6Manager.isIp6Taken(network, "requestedIpv6");
+ assertAndVerifyIsIp6Taken(true, result);
+ }
+
+ @Test
+ public void isIp6TakenTestAllNull() {
+ setIsIp6TakenTest(null, null);
+ boolean result = ip6Manager.isIp6Taken(network, "requestedIpv6");
+ assertAndVerifyIsIp6Taken(false, result);
+ }
+
+ private void assertAndVerifyIsIp6Taken(boolean expected, boolean result) {
+ Assert.assertEquals(expected, result);
+ Mockito.verify(ipv6Dao).findByNetworkIdAndIp(Mockito.anyLong(), Mockito.anyString());
+ Mockito.verify(nicSecondaryIpDao).findByIp6AddressAndNetworkId(Mockito.anyString(), Mockito.anyLong());
+ }
+
+ private void setIsIp6TakenTest(UserIpv6AddressVO userIpv6, NicSecondaryIpVO nicSecondaryIp) {
+ Mockito.doReturn(userIpv6).when(ipv6Dao).findByNetworkIdAndIp(Mockito.anyLong(), Mockito.anyString());
+ Mockito.doReturn(nicSecondaryIp).when(nicSecondaryIpDao).findByIp6AddressAndNetworkId(Mockito.anyString(), Mockito.anyLong());
+ }
+
+ private Network mockNetwork() {
+ Network network = mock(Network.class);
+ Mockito.when(network.getId()).thenReturn(0l);
+ Mockito.when(network.getIp6Cidr()).thenReturn("2001:db8::/32");
+ return network;
+ }
+
+ @Test
+ public void allocatePublicIp6ForGuestNicTestNoException() throws InsufficientAddressCapacityException {
+ Account owner = Mockito.mock(Account.class);
+ String requestedIpv6 = setCheckIfCanAllocateIpv6AddresscTest("2001:db8::10", false, false);
+
+ String returnedIp = ip6Manager.allocatePublicIp6ForGuestNic(network, 0l, owner, requestedIpv6);
+
+ Mockito.verify(ip6Manager).checkIfCanAllocateIpv6Address(network, requestedIpv6);
+ Assert.assertEquals(requestedIpv6, returnedIp);
+ }
+
+ @Test(expected = InsufficientAddressCapacityException.class)
+ public void checkIfCanAllocateIpv6AddressTestIp6IsTaken() throws InsufficientAddressCapacityException {
+ String requestedIpv6 = setCheckIfCanAllocateIpv6AddresscTest("2001:db8::10", true, false);
+
+ ip6Manager.checkIfCanAllocateIpv6Address(network, requestedIpv6);
+
+ verifyCheckIfCanAllocateIpv6AddressTest(network, requestedIpv6, 1, 0);
+ }
+
+ @Test(expected = InvalidParameterValueException.class)
+ public void checkIfCanAllocateIpv6AddressTestIpIsIpEqualsGatewayOrNetworkOfferingsEmpty() throws InsufficientAddressCapacityException {
+ String requestedIpv6 = setCheckIfCanAllocateIpv6AddresscTest("2001:db8::10", false, true);
+
+ ip6Manager.checkIfCanAllocateIpv6Address(network, requestedIpv6);
+
+ verifyCheckIfCanAllocateIpv6AddressTest(network, requestedIpv6, 1, 1);
+ }
+
+ @Test(expected = InvalidParameterValueException.class)
+ public void checkIfCanAllocateIpv6AddressTestIpINotInTheNetwork() throws InsufficientAddressCapacityException {
+ String requestedIpv6 = "2002:db8::10";
+ setCheckIfCanAllocateIpv6AddresscTest(requestedIpv6, false, false);
+
+ ip6Manager.checkIfCanAllocateIpv6Address(network, requestedIpv6);
+
+ verifyCheckIfCanAllocateIpv6AddressTest(network, requestedIpv6, 1, 1);
+ }
+
+ private void verifyCheckIfCanAllocateIpv6AddressTest(Network network, String requestedIpv6, int isIp6TakenTimes, int isIpEqualsGatewayTimes) {
+ Mockito.verify(ip6Manager, Mockito.times(isIp6TakenTimes)).isIp6Taken(network, requestedIpv6);
+ Mockito.verify(ipAddressManager, Mockito.times(isIpEqualsGatewayTimes)).isIpEqualsGatewayOrNetworkOfferingsEmpty(network, requestedIpv6);
+ }
+
+ private String setCheckIfCanAllocateIpv6AddresscTest(String requestedIpv6, boolean isIp6Taken, boolean isIpEqualsGatewayOrNetworkOfferingsEmpty) {
+ Mockito.doReturn(isIp6Taken).when(ip6Manager).isIp6Taken(Mockito.eq(network), Mockito.anyString());
+ Mockito.doReturn(isIpEqualsGatewayOrNetworkOfferingsEmpty).when(ipAddressManager).isIpEqualsGatewayOrNetworkOfferingsEmpty(network, requestedIpv6);
+ NetUtils.isIp6InNetwork(requestedIpv6, network.getIp6Cidr());
+ return requestedIpv6;
+ }
+
+ @Test
+ public void acquireGuestIpv6AddressTest() throws InsufficientAddressCapacityException {
+ setAcquireGuestIpv6AddressTest(true, State.Free);
+ String requestedIpv6 = setCheckIfCanAllocateIpv6AddresscTest("2001:db8::10", false, false);
+
+ ip6Manager.acquireGuestIpv6Address(network, requestedIpv6);
+
+ verifyAcquireGuestIpv6AddressTest();
+ }
+
+ private void verifyAcquireGuestIpv6AddressTest() {
+ Mockito.verify(networkModel).areThereIPv6AddressAvailableInNetwork(Mockito.anyLong());
+ Mockito.verify(networkModel).checkRequestedIpAddresses(Mockito.anyLong(), Mockito.any(IpAddresses.class));
+ Mockito.verify(ipAddressDao).findByIpAndSourceNetworkId(Mockito.anyLong(), Mockito.anyString());
+ }
+
+ @Test(expected = InsufficientAddressCapacityException.class)
+ public void acquireGuestIpv6AddressTestUnavailableIp() throws InsufficientAddressCapacityException {
+ setAcquireGuestIpv6AddressTest(false, State.Free);
+ String requestedIpv6 = setCheckIfCanAllocateIpv6AddresscTest("2001:db8::10", false, false);
+
+ ip6Manager.acquireGuestIpv6Address(network, requestedIpv6);
+
+ verifyAcquireGuestIpv6AddressTest();
+ }
+
+ @Test(expected = InsufficientAddressCapacityException.class)
+ public void acquireGuestIpv6AddressTestStateAllocating() throws InsufficientAddressCapacityException {
+ setAcquireGuestIpv6AddressTest(false, State.Allocating);
+ String requestedIpv6 = setCheckIfCanAllocateIpv6AddresscTest("2001:db8::10", false, false);
+
+ ip6Manager.acquireGuestIpv6Address(network, requestedIpv6);
+
+ verifyAcquireGuestIpv6AddressTest();
+ }
+
+ @Test(expected = InsufficientAddressCapacityException.class)
+ public void acquireGuestIpv6AddressTestStateAllocated() throws InsufficientAddressCapacityException {
+ setAcquireGuestIpv6AddressTest(false, State.Allocated);
+ String requestedIpv6 = setCheckIfCanAllocateIpv6AddresscTest("2001:db8::10", false, false);
+
+ ip6Manager.acquireGuestIpv6Address(network, requestedIpv6);
+
+ verifyAcquireGuestIpv6AddressTest();
+ }
+
+ @Test(expected = InsufficientAddressCapacityException.class)
+ public void acquireGuestIpv6AddressTestStateReleasing() throws InsufficientAddressCapacityException {
+ setAcquireGuestIpv6AddressTest(false, State.Releasing);
+ String requestedIpv6 = setCheckIfCanAllocateIpv6AddresscTest("2001:db8::10", false, false);
+
+ ip6Manager.acquireGuestIpv6Address(network, requestedIpv6);
+
+ verifyAcquireGuestIpv6AddressTest();
+ }
+
+ private void setAcquireGuestIpv6AddressTest(boolean isIPAvailable, State state) {
+ mockNetwork();
+ IPAddressVO ipVo = Mockito.mock(IPAddressVO.class);
+ Mockito.doReturn(isIPAvailable).when(networkModel).areThereIPv6AddressAvailableInNetwork(Mockito.anyLong());
+ Mockito.doReturn(ipVo).when(ipAddressDao).findByIpAndSourceNetworkId(Mockito.anyLong(), Mockito.anyString());
+ Mockito.when(ipVo.getState()).thenReturn(state);
+ }
+
+}
diff --git a/server/src/test/java/com/cloud/network/MockNetworkModelImpl.java b/server/src/test/java/com/cloud/network/MockNetworkModelImpl.java
index d142554..a35cec5 100644
--- a/server/src/test/java/com/cloud/network/MockNetworkModelImpl.java
+++ b/server/src/test/java/com/cloud/network/MockNetworkModelImpl.java
@@ -813,7 +813,7 @@ public class MockNetworkModelImpl extends ManagerBase implements NetworkModel {
}
@Override
- public boolean isIP6AddressAvailableInNetwork(long networkId) {
+ public boolean areThereIPv6AddressAvailableInNetwork(long networkId) {
// TODO Auto-generated method stub
return false;
}
diff --git a/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java b/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java
index 8cbf30c..57ecbd1 100644
--- a/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java
+++ b/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java
@@ -51,6 +51,7 @@ import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.GuestVlan;
import com.cloud.network.IpAddress;
import com.cloud.network.Network;
+import com.cloud.network.Network.IpAddresses;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.NetworkProfile;
@@ -827,7 +828,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkOrches
}
@Override
- public NicSecondaryIp allocateSecondaryGuestIP(long nicId, String ipaddress) {
+ public NicSecondaryIp allocateSecondaryGuestIP(long nicId, IpAddresses requestedIpPair) {
// TODO Auto-generated method stub
return null;
}
diff --git a/server/src/test/java/com/cloud/vpc/MockNetworkModelImpl.java b/server/src/test/java/com/cloud/vpc/MockNetworkModelImpl.java
index 33192a7..56670d2 100644
--- a/server/src/test/java/com/cloud/vpc/MockNetworkModelImpl.java
+++ b/server/src/test/java/com/cloud/vpc/MockNetworkModelImpl.java
@@ -829,7 +829,7 @@ public class MockNetworkModelImpl extends ManagerBase implements NetworkModel {
}
@Override
- public boolean isIP6AddressAvailableInNetwork(long networkId) {
+ public boolean areThereIPv6AddressAvailableInNetwork(long networkId) {
// TODO Auto-generated method stub
return false;
}
diff --git a/ui/lib/jquery.validate.additional-methods.js b/ui/lib/jquery.validate.additional-methods.js
index 811b4f7..2de65d3 100644
--- a/ui/lib/jquery.validate.additional-methods.js
+++ b/ui/lib/jquery.validate.additional-methods.js
@@ -503,6 +503,16 @@ $.validator.addMethod("ipv6", function(value, element) {
return this.optional(element) || /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|( [...]
}, "Please enter a valid IP v6 address.");
+$.validator.addMethod("ipv46address", function(value, element) {
+ if (this.optional(element) && value.length == 0)
+ return true;
+
+ if ($.validator.methods.ipv4.call(this, value, element) || $.validator.methods.ipv6.call(this, value, element))
+ return true;
+
+ return false;
+}, "Please enter a valid IPv4/IPv6 address.");
+
$.validator.addMethod("lettersonly", function(value, element) {
return this.optional(element) || /^[a-z]+$/i.test(value);
}, "Letters only please");
diff --git a/ui/scripts/network.js b/ui/scripts/network.js
index 22ddb10..1cbacb6 100644
--- a/ui/scripts/network.js
+++ b/ui/scripts/network.js
@@ -1782,7 +1782,7 @@
label: 'label.ip.address',
validation: {
required: false,
- ipv4: true
+ ipv46address: true
}
}
}
diff --git a/utils/src/main/java/com/cloud/utils/net/NetUtils.java b/utils/src/main/java/com/cloud/utils/net/NetUtils.java
index 1bd08a3..9a88249 100644
--- a/utils/src/main/java/com/cloud/utils/net/NetUtils.java
+++ b/utils/src/main/java/com/cloud/utils/net/NetUtils.java
@@ -23,9 +23,9 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;
-import java.net.InetAddress;
import java.net.Inet4Address;
import java.net.Inet6Address;
+import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
@@ -1547,4 +1547,20 @@ public class NetUtils {
return EUI64Address(IPv6Network.LINK_LOCAL_NETWORK, macAddress);
}
+ /**
+ * Returns true if the given IP address is IPv4 or false if it is an IPv6. If it is an invalid IP address it throws an exception.
+ */
+ public static boolean isIpv4(String ipAddr) {
+ boolean isIpv4 = true;
+ if (ipAddr != null) {
+ if (!NetUtils.isValidIp4(ipAddr)) {
+ isIpv4 = false;
+ }
+ if (!NetUtils.isValidIp6(ipAddr) && !isIpv4) {
+ throw new IllegalArgumentException("Invalid ip address " + ipAddr);
+ }
+ }
+ return isIpv4;
+ }
+
}
diff --git a/utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java b/utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java
index bec2209..4abb87a 100644
--- a/utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java
+++ b/utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java
@@ -678,4 +678,20 @@ public class NetUtilsTest {
assertFalse(NetUtils.isValidPort(-1));
assertFalse(NetUtils.isValidPort(65536));
}
+
+ @Test
+ public void testIsIpv4() {
+ assertTrue(NetUtils.isIpv4("192.168.1.1"));
+ assertFalse(NetUtils.isIpv4("2a01:4f8:130:2192::2"));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testIsIpv4ExpectException() {
+ NetUtils.isIpv4("test");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testIsIpv4ExpectException2() {
+ NetUtils.isIpv4("2001:db8:300::/64");
+ }
}