[
https://issues.apache.org/jira/browse/CLOUDSTACK-10199?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16700290#comment-16700290
]
ASF GitHub Bot commented on CLOUDSTACK-10199:
---------------------------------------------
GabrielBrascher closed pull request #2595: CLOUDSTACK-10199: Support requesting
a specific IPv4 address
URL: https://github.com/apache/cloudstack/pull/2595
This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:
As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):
diff --git
a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
index e4fbf322b6f..667c2b9b19c 100644
---
a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
+++
b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
@@ -231,27 +231,27 @@
@Inject
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
ConfigurationDao _configDao;
@Inject
- UserVmDao _userVmDao = null;
+ UserVmDao _userVmDao;
@Inject
AlertManager _alertMgr;
@Inject
ConfigurationManager _configMgr;
@Inject
- NetworkOfferingDao _networkOfferingDao = null;
+ NetworkOfferingDao _networkOfferingDao;
@Inject
- NetworkDao _networksDao = null;
+ NetworkDao _networksDao;
@Inject
- NicDao _nicDao = null;
+ NicDao _nicDao;
@Inject
RulesManager _rulesMgr;
@Inject
@@ -860,6 +860,11 @@ public void saveExtraDhcpOptions(final String networkUuid,
final Long nicId, fin
NicVO vo = new NicVO(guru.getName(), vm.getId(), network.getId(),
vm.getType());
+ DataCenterVO dcVo = _dcDao.findById(network.getDataCenterId());
+ if (dcVo.getNetworkType() == NetworkType.Basic) {
+ configureNicProfileBasedOnRequestedIp(requested, profile, network);
+ }
+
deviceId = applyProfileToNic(vo, profile, deviceId);
vo = _nicDao.persist(vo);
@@ -871,6 +876,85 @@ public void saveExtraDhcpOptions(final String networkUuid,
final Long nicId, fin
return new Pair<NicProfile, Integer>(vmNic, Integer.valueOf(deviceId));
}
+ /**
+ * If the requested IPv4 address from the NicProfile was configured then
it configures the IPv4 address, Netmask and Gateway to deploy the VM with the
requested IP.
+ */
+ protected void configureNicProfileBasedOnRequestedIp(NicProfile
requestedNicProfile, NicProfile nicProfile, Network network) {
+ if (requestedNicProfile == null) {
+ return;
+ }
+ String requestedIpv4Address = requestedNicProfile.getRequestedIPv4();
+ if (requestedIpv4Address == null) {
+ return;
+ }
+ if (!NetUtils.isValidIp4(requestedIpv4Address)) {
+ throw new InvalidParameterValueException(String.format("The
requested [IPv4 address='%s'] is not a valid IP address",
requestedIpv4Address));
+ }
+
+ VlanVO vlanVo = _vlanDao.findByNetworkIdAndIpv4(network.getId(),
requestedIpv4Address);
+ if (vlanVo == null) {
+ throw new InvalidParameterValueException(String.format("Trying to
configure a Nic with the requested [IPv4='%s'] but cannot find a Vlan for the
[network id='%s']",
+ requestedIpv4Address, network.getId()));
+ }
+
+ String ipv4Gateway = vlanVo.getVlanGateway();
+ String ipv4Netmask = vlanVo.getVlanNetmask();
+
+ if (!NetUtils.isValidIp4(ipv4Gateway)) {
+ throw new InvalidParameterValueException(String.format("The
[IPv4Gateway='%s'] from [VlanId='%s'] is not valid", ipv4Gateway,
vlanVo.getId()));
+ }
+ if (!NetUtils.isValidIp4Netmask(ipv4Netmask)) {
+ throw new InvalidParameterValueException(String.format("The
[IPv4Netmask='%s'] from [VlanId='%s'] is not valid", ipv4Netmask,
vlanVo.getId()));
+ }
+
+ acquireLockAndCheckIfIpv4IsFree(network, requestedIpv4Address);
+
+ nicProfile.setIPv4Address(requestedIpv4Address);
+ nicProfile.setIPv4Gateway(ipv4Gateway);
+ nicProfile.setIPv4Netmask(ipv4Netmask);
+
+ if (nicProfile.getMacAddress() == null) {
+ try {
+ String macAddress =
_networkModel.getNextAvailableMacAddressInNetwork(network.getId());
+ nicProfile.setMacAddress(macAddress);
+ } catch (InsufficientAddressCapacityException e) {
+ throw new CloudRuntimeException(String.format("Cannot get next
available mac address in [network id='%s']", network.getId()), e);
+ }
+ }
+ }
+
+ /**
+ * Acquires lock in "user_ip_address" and checks if the requested IPv4
address is Free.
+ */
+ protected void acquireLockAndCheckIfIpv4IsFree(Network network, String
requestedIpv4Address) {
+ IPAddressVO ipVO =
_ipAddressDao.findByIpAndSourceNetworkId(network.getId(), requestedIpv4Address);
+ if (ipVO == null) {
+ throw new InvalidParameterValueException(
+ String.format("Cannot find IPAddressVO for guest [IPv4
address='%s'] and [network id='%s']", requestedIpv4Address, network.getId()));
+ }
+ try {
+ IPAddressVO lockedIpVO =
_ipAddressDao.acquireInLockTable(ipVO.getId());
+ validateLockedRequestedIp(ipVO, lockedIpVO);
+ lockedIpVO.setState(IPAddressVO.State.Allocated);
+ _ipAddressDao.update(lockedIpVO.getId(), lockedIpVO);
+ } finally {
+ _ipAddressDao.releaseFromLockTable(ipVO.getId());
+ }
+ }
+
+ /**
+ * Validates the locked IP, throwing an exeption if the locked IP is null
or the locked IP is not in 'Free' state.
+ */
+ protected void validateLockedRequestedIp(IPAddressVO ipVO, IPAddressVO
lockedIpVO) {
+ if (lockedIpVO == null) {
+ throw new InvalidParameterValueException(String.format("Cannot
acquire guest [IPv4 address='%s'] as it was removed while acquiring lock",
ipVO.getAddress()));
+ }
+ if (lockedIpVO.getState() != IPAddressVO.State.Free) {
+ throw new InvalidParameterValueException(
+ String.format("Cannot acquire guest [IPv4 address='%s'];
The Ip address is in [state='%s']", ipVO.getAddress(),
lockedIpVO.getState().toString()));
+ }
+ }
+
protected Integer applyProfileToNic(final NicVO vo, final NicProfile
profile, Integer deviceId) {
if (profile.getDeviceId() != null) {
vo.setDeviceId(profile.getDeviceId());
diff --git
a/engine/orchestration/src/test/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestratorTest.java
b/engine/orchestration/src/test/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestratorTest.java
index b0283f35c1b..3450c09b263 100644
---
a/engine/orchestration/src/test/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestratorTest.java
+++
b/engine/orchestration/src/test/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestratorTest.java
@@ -23,31 +23,42 @@
import static org.mockito.Mockito.when;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Arrays;
-import com.cloud.exception.InvalidParameterValueException;
-import com.cloud.offerings.NetworkOfferingVO;
import org.apache.log4j.Logger;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.Matchers;
+import org.mockito.Mockito;
+import com.cloud.dc.Vlan;
+import com.cloud.dc.VlanVO;
+import com.cloud.dc.dao.VlanDao;
+import com.cloud.exception.InsufficientAddressCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
import com.cloud.network.Network;
import com.cloud.network.Network.GuestType;
import com.cloud.network.Network.Service;
import com.cloud.network.NetworkModel;
+import com.cloud.network.IpAddress.State;
import com.cloud.network.Networks.TrafficType;
+import com.cloud.network.dao.IPAddressDao;
+import com.cloud.network.dao.IPAddressVO;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkServiceMapDao;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.element.DhcpServiceProvider;
import com.cloud.network.guru.NetworkGuru;
+import com.cloud.offerings.NetworkOfferingVO;
+import com.cloud.utils.net.Ip;
import com.cloud.vm.Nic;
+import com.cloud.vm.NicProfile;
import com.cloud.vm.NicVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.Type;
@@ -65,11 +76,11 @@
public class NetworkOrchestratorTest extends TestCase {
static final Logger s_logger =
Logger.getLogger(NetworkOrchestratorTest.class);
- NetworkOrchestrator testOrchastrator = new NetworkOrchestrator();
+ NetworkOrchestrator testOrchastrator = Mockito.spy(new
NetworkOrchestrator());
- String guruName = "GuestNetworkGuru";
- String dhcpProvider = "VirtualRouter";
- NetworkGuru guru = mock(NetworkGuru.class);
+ private String guruName = "GuestNetworkGuru";
+ private String dhcpProvider = "VirtualRouter";
+ private NetworkGuru guru = mock(NetworkGuru.class);
NetworkOfferingVO networkOffering = mock(NetworkOfferingVO.class);
@@ -85,11 +96,13 @@ public void setUp() {
testOrchastrator._nicSecondaryIpDao = mock(NicSecondaryIpDao.class);
testOrchastrator._ntwkSrvcDao = mock(NetworkServiceMapDao.class);
testOrchastrator._nicIpAliasDao = mock(NicIpAliasDao.class);
+ testOrchastrator._ipAddressDao = mock(IPAddressDao.class);
+ testOrchastrator._vlanDao = mock(VlanDao.class);
DhcpServiceProvider provider = mock(DhcpServiceProvider.class);
Map<Network.Capability, String> capabilities = new
HashMap<Network.Capability, String>();
- Map<Network.Service,Map<Network.Capability, String>> services = new
HashMap<Network.Service,Map<Network.Capability, String>>();
- services.put(Network.Service.Dhcp,capabilities);
+ Map<Network.Service, Map<Network.Capability, String>> services = new
HashMap<Network.Service, Map<Network.Capability, String>>();
+ services.put(Network.Service.Dhcp, capabilities);
when(provider.getCapabilities()).thenReturn(services);
capabilities.put(Network.Capability.DhcpAccrossMultipleSubnets,
"true");
@@ -108,7 +121,7 @@ public void setUp() {
@Test
public void testRemoveDhcpServiceWithNic() {
// make local mocks
- VirtualMachineProfile vm = mock(VirtualMachineProfile.class);
+ VirtualMachineProfile vm = mock(VirtualMachineProfile.class);
NicVO nic = mock(NicVO.class);
NetworkVO network = mock(NetworkVO.class);
@@ -117,9 +130,8 @@ public void testRemoveDhcpServiceWithNic() {
when(testOrchastrator._networkModel.areServicesSupportedInNetwork(network.getId(),
Service.Dhcp)).thenReturn(true);
when(network.getTrafficType()).thenReturn(TrafficType.Guest);
when(network.getGuestType()).thenReturn(GuestType.Shared);
-
when(testOrchastrator._nicDao.listByNetworkIdTypeAndGatewayAndBroadcastUri(nic.getNetworkId(),
VirtualMachine.Type.User, nic.getIPv4Gateway(),
nic.getBroadcastUri())).thenReturn(new ArrayList<NicVO>());
-
-
+
when(testOrchastrator._nicDao.listByNetworkIdTypeAndGatewayAndBroadcastUri(nic.getNetworkId(),
VirtualMachine.Type.User, nic.getIPv4Gateway(), nic.getBroadcastUri()))
+ .thenReturn(new ArrayList<NicVO>());
when(network.getGuruName()).thenReturn(guruName);
when(testOrchastrator._networksDao.findById(nic.getNetworkId())).thenReturn(network);
@@ -134,7 +146,7 @@ public void testRemoveDhcpServiceWithNic() {
@Test
public void testDontRemoveDhcpServiceFromDomainRouter() {
// make local mocks
- VirtualMachineProfile vm = mock(VirtualMachineProfile.class);
+ VirtualMachineProfile vm = mock(VirtualMachineProfile.class);
NicVO nic = mock(NicVO.class);
NetworkVO network = mock(NetworkVO.class);
@@ -154,7 +166,7 @@ public void testDontRemoveDhcpServiceFromDomainRouter() {
@Test
public void testDontRemoveDhcpServiceWhenNotProvided() {
// make local mocks
- VirtualMachineProfile vm = mock(VirtualMachineProfile.class);
+ VirtualMachineProfile vm = mock(VirtualMachineProfile.class);
NicVO nic = mock(NicVO.class);
NetworkVO network = mock(NetworkVO.class);
@@ -200,4 +212,255 @@ public void
testCheckL2OfferingServicesMultipleServicesNotIncludingUserData() {
when(testOrchastrator._networkModel.areServicesSupportedByNetworkOffering(networkOfferingId,
Service.UserData)).thenReturn(false);
testOrchastrator.checkL2OfferingServices(networkOffering);
}
+
+ @Test
+ public void testConfigureNicProfileBasedOnRequestedIpTestMacNull() {
+ Network network = mock(Network.class);
+ NicProfile requestedNicProfile = new NicProfile();
+ NicProfile nicProfile = Mockito.spy(new NicProfile());
+
+ configureTestConfigureNicProfileBasedOnRequestedIpTests(nicProfile,
0l, false, IPAddressVO.State.Free, "192.168.100.1", "255.255.255.0",
"00-88-14-4D-4C-FB",
+ requestedNicProfile, null, "192.168.100.150");
+
+
testOrchastrator.configureNicProfileBasedOnRequestedIp(requestedNicProfile,
nicProfile, network);
+
+ verifyAndAssert("192.168.100.150", "192.168.100.1", "255.255.255.0",
nicProfile, 1, 1);
+ }
+
+ @Test
+ public void
testConfigureNicProfileBasedOnRequestedIpTestNicProfileMacNotNull() {
+ Network network = mock(Network.class);
+ NicProfile requestedNicProfile = new NicProfile();
+ NicProfile nicProfile = Mockito.spy(new NicProfile());
+
+ configureTestConfigureNicProfileBasedOnRequestedIpTests(nicProfile,
0l, false, IPAddressVO.State.Free, "192.168.100.1", "255.255.255.0",
"00-88-14-4D-4C-FB",
+ requestedNicProfile, "00-88-14-4D-4C-FB", "192.168.100.150");
+
+
testOrchastrator.configureNicProfileBasedOnRequestedIp(requestedNicProfile,
nicProfile, network);
+
+ verifyAndAssert("192.168.100.150", "192.168.100.1", "255.255.255.0",
nicProfile, 1, 0);
+ }
+
+ @Test
+ public void testConfigureNicProfileBasedOnRequestedIpTestRequestedIpNull()
{
+ testConfigureNicProfileBasedOnRequestedIpTestRequestedIp(null);
+ }
+
+ @Test(expected = InvalidParameterValueException.class)
+ public void
testConfigureNicProfileBasedOnRequestedIpTestRequestedIpIsBlank() {
+ testConfigureNicProfileBasedOnRequestedIpTestRequestedIp("");
+ }
+
+ @Test(expected = InvalidParameterValueException.class)
+ public void
testConfigureNicProfileBasedOnRequestedIpTestRequestedIpIsNotValid() {
+ testConfigureNicProfileBasedOnRequestedIpTestRequestedIp("123");
+ }
+
+ private void
testConfigureNicProfileBasedOnRequestedIpTestRequestedIp(String
requestedIpv4Address) {
+ Network network = mock(Network.class);
+ NicProfile requestedNicProfile = new NicProfile();
+ NicProfile nicProfile = Mockito.spy(new NicProfile());
+
+ configureTestConfigureNicProfileBasedOnRequestedIpTests(nicProfile,
0l, false, IPAddressVO.State.Free, "192.168.100.1", "255.255.255.0",
"00-88-14-4D-4C-FB",
+ requestedNicProfile, null, requestedIpv4Address);
+
testOrchastrator.configureNicProfileBasedOnRequestedIp(requestedNicProfile,
nicProfile, network);
+
+ verifyAndAssert(null, null, null, nicProfile, 0, 0);
+ }
+
+ @Test(expected = InvalidParameterValueException.class)
+ public void testConfigureNicProfileBasedOnRequestedIpTestGatewayIsBlank() {
+ testConfigureNicProfileBasedOnRequestedIpTestGateway("");
+ }
+
+ @Test(expected = InvalidParameterValueException.class)
+ public void
testConfigureNicProfileBasedOnRequestedIpTestGatewayIsNotValid() {
+ testConfigureNicProfileBasedOnRequestedIpTestGateway("123");
+ }
+
+ @Test(expected = InvalidParameterValueException.class)
+ public void testConfigureNicProfileBasedOnRequestedIpTestGatewayIsNull() {
+ testConfigureNicProfileBasedOnRequestedIpTestGateway(null);
+ }
+
+ private void testConfigureNicProfileBasedOnRequestedIpTestGateway(String
ipv4Gateway) {
+ Network network = mock(Network.class);
+ NicProfile requestedNicProfile = new NicProfile();
+ NicProfile nicProfile = Mockito.spy(new NicProfile());
+
+ configureTestConfigureNicProfileBasedOnRequestedIpTests(nicProfile,
0l, false, IPAddressVO.State.Free, ipv4Gateway, "255.255.255.0",
"00-88-14-4D-4C-FB",
+ requestedNicProfile, "00-88-14-4D-4C-FB", "192.168.100.150");
+
testOrchastrator.configureNicProfileBasedOnRequestedIp(requestedNicProfile,
nicProfile, network);
+ verifyAndAssert(null, null, null, nicProfile, 1, 0);
+ }
+
+ @Test(expected = InvalidParameterValueException.class)
+ public void testConfigureNicProfileBasedOnRequestedIpTestNetmaskIsNull() {
+ testConfigureNicProfileBasedOnRequestedIpTestNetmask(null);
+ }
+
+ @Test(expected = InvalidParameterValueException.class)
+ public void testConfigureNicProfileBasedOnRequestedIpTestNetmaskIsBlank() {
+ testConfigureNicProfileBasedOnRequestedIpTestNetmask("");
+ }
+
+ @Test(expected = InvalidParameterValueException.class)
+ public void
testConfigureNicProfileBasedOnRequestedIpTestNetmaskIsNotValid() {
+ testConfigureNicProfileBasedOnRequestedIpTestNetmask("123");
+ }
+
+ private void testConfigureNicProfileBasedOnRequestedIpTestNetmask(String
ipv4Netmask) {
+ Network network = mock(Network.class);
+ NicProfile requestedNicProfile = new NicProfile();
+ NicProfile nicProfile = Mockito.spy(new NicProfile());
+
+ configureTestConfigureNicProfileBasedOnRequestedIpTests(nicProfile,
0l, false, IPAddressVO.State.Free, "192.168.100.1", ipv4Netmask,
"00-88-14-4D-4C-FB",
+ requestedNicProfile, "00-88-14-4D-4C-FB", "192.168.100.150");
+
testOrchastrator.configureNicProfileBasedOnRequestedIp(requestedNicProfile,
nicProfile, network);
+ verifyAndAssert(null, null, null, nicProfile, 1, 0);
+ }
+
+ @Test(expected = InvalidParameterValueException.class)
+ public void testConfigureNicProfileBasedOnRequestedIpTestIPAddressVONull()
{
+ Network network = mock(Network.class);
+ NicProfile requestedNicProfile = new NicProfile();
+ NicProfile nicProfile = Mockito.spy(new NicProfile());
+
+ configureTestConfigureNicProfileBasedOnRequestedIpTests(nicProfile,
0l, false, IPAddressVO.State.Free, "192.168.100.1", "255.255.255.0",
"00-88-14-4D-4C-FB",
+ requestedNicProfile, "00-88-14-4D-4C-FB", "192.168.100.150");
+
when(testOrchastrator._vlanDao.findByNetworkIdAndIpv4(Mockito.anyLong(),
Mockito.anyString())).thenReturn(null);
+
+
testOrchastrator.configureNicProfileBasedOnRequestedIp(requestedNicProfile,
nicProfile, network);
+ verifyAndAssert(null, null, null, nicProfile, 0, 0);
+ }
+
+ private void
configureTestConfigureNicProfileBasedOnRequestedIpTests(NicProfile nicProfile,
long ipvoId, boolean ipVoIsNull, IPAddressVO.State state, String vlanGateway,
+ String vlanNetmask, String macAddress, NicProfile
requestedNicProfile, String nicProfileMacAddress, String requestedIpv4Address) {
+ IPAddressVO ipVoSpy = Mockito.spy(new IPAddressVO(new
Ip("192.168.100.100"), 0l, 0l, 0l, true));
+ ipVoSpy.setState(state);
+
+ requestedNicProfile.setRequestedIPv4(requestedIpv4Address);
+ nicProfile.setMacAddress(nicProfileMacAddress);
+
+ when(ipVoSpy.getId()).thenReturn(ipvoId);
+ when(ipVoSpy.getState()).thenReturn(state);
+
+ if (ipVoIsNull) {
+
when(testOrchastrator._ipAddressDao.findByIpAndSourceNetworkId(Mockito.anyLong(),
Mockito.anyString())).thenReturn(ipVoSpy);
+ } else {
+
when(testOrchastrator._ipAddressDao.findByIpAndSourceNetworkId(Mockito.anyLong(),
Mockito.anyString())).thenReturn(ipVoSpy);
+ }
+
+ VlanVO vlanSpy = Mockito.spy(new VlanVO(Vlan.VlanType.DirectAttached,
"vlanTag", vlanGateway, vlanNetmask, 0l, "192.168.100.100 - 192.168.100.200",
0l, new Long(0l),
+ "ip6Gateway", "ip6Cidr", "ip6Range"));
+
+ Mockito.doReturn(0l).when(vlanSpy).getId();
+
when(testOrchastrator._vlanDao.findByNetworkIdAndIpv4(Mockito.anyLong(),
Mockito.anyString())).thenReturn(vlanSpy);
+
when(testOrchastrator._ipAddressDao.acquireInLockTable(Mockito.anyLong())).thenReturn(ipVoSpy);
+ when(testOrchastrator._ipAddressDao.update(Mockito.anyLong(),
Mockito.any(IPAddressVO.class))).thenReturn(true);
+
when(testOrchastrator._ipAddressDao.releaseFromLockTable(Mockito.anyLong())).thenReturn(true);
+ try {
+
when(testOrchastrator._networkModel.getNextAvailableMacAddressInNetwork(Mockito.anyLong())).thenReturn(macAddress);
+ } catch (InsufficientAddressCapacityException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void verifyAndAssert(String requestedIpv4Address, String
ipv4Gateway, String ipv4Netmask, NicProfile nicProfile, int
acquireLockAndCheckIfIpv4IsFreeTimes,
+ int nextMacAddressTimes) {
+ verify(testOrchastrator,
times(acquireLockAndCheckIfIpv4IsFreeTimes)).acquireLockAndCheckIfIpv4IsFree(Mockito.any(Network.class),
Mockito.anyString());
+ try {
+ verify(testOrchastrator._networkModel,
times(nextMacAddressTimes)).getNextAvailableMacAddressInNetwork(Mockito.anyLong());
+ } catch (InsufficientAddressCapacityException e) {
+ e.printStackTrace();
+ }
+
+ assertEquals(requestedIpv4Address, nicProfile.getIPv4Address());
+ assertEquals(ipv4Gateway, nicProfile.getIPv4Gateway());
+ assertEquals(ipv4Netmask, nicProfile.getIPv4Netmask());
+ }
+
+ @Test(expected = InvalidParameterValueException.class)
+ public void testAcquireLockAndCheckIfIpv4IsFreeTestIpvoNull() {
+ executeTestAcquireLockAndCheckIfIpv4IsFree(IPAddressVO.State.Free,
true, 1, 0, 0, 0, 0);
+ }
+
+ @Test
+ public void testAcquireLockAndCheckIfIpv4IsFreeTestExpectedFlow() {
+ executeTestAcquireLockAndCheckIfIpv4IsFree(IPAddressVO.State.Free,
false, 1, 1, 1, 1, 1);
+ }
+
+ @Test(expected = InvalidParameterValueException.class)
+ public void testAcquireLockAndCheckIfIpv4IsFreeTestAllocatedIp() {
+
executeTestAcquireLockAndCheckIfIpv4IsFree(IPAddressVO.State.Allocated, false,
1, 1, 1, 0, 1);
+ }
+
+ @Test(expected = InvalidParameterValueException.class)
+ public void testAcquireLockAndCheckIfIpv4IsFreeTestAllocatingIp() {
+
executeTestAcquireLockAndCheckIfIpv4IsFree(IPAddressVO.State.Allocating, false,
1, 1, 1, 0, 1);
+ }
+
+ @Test(expected = InvalidParameterValueException.class)
+ public void testAcquireLockAndCheckIfIpv4IsFreeTestReleasingIp() {
+
executeTestAcquireLockAndCheckIfIpv4IsFree(IPAddressVO.State.Releasing, false,
1, 1, 1, 0, 1);
+ }
+
+ private void executeTestAcquireLockAndCheckIfIpv4IsFree(IPAddressVO.State
state, boolean isIPAddressVONull, int findByIpTimes, int acquireLockTimes, int
releaseFromLockTimes,
+ int updateTimes, int validateTimes) {
+ Network network = Mockito.spy(new NetworkVO());
+ IPAddressVO ipVoSpy = Mockito.spy(new IPAddressVO(new
Ip("192.168.100.100"), 0l, 0l, 0l, true));
+ ipVoSpy.setState(state);
+ ipVoSpy.setState(state);
+ if (isIPAddressVONull) {
+
when(testOrchastrator._ipAddressDao.findByIpAndSourceNetworkId(Mockito.anyLong(),
Mockito.anyString())).thenReturn(null);
+ } else {
+
when(testOrchastrator._ipAddressDao.findByIpAndSourceNetworkId(Mockito.anyLong(),
Mockito.anyString())).thenReturn(ipVoSpy);
+ }
+
when(testOrchastrator._ipAddressDao.acquireInLockTable(Mockito.anyLong())).thenReturn(ipVoSpy);
+
when(testOrchastrator._ipAddressDao.releaseFromLockTable(Mockito.anyLong())).thenReturn(true);
+ when(testOrchastrator._ipAddressDao.update(Mockito.anyLong(),
Mockito.any(IPAddressVO.class))).thenReturn(true);
+
+ testOrchastrator.acquireLockAndCheckIfIpv4IsFree(network,
"192.168.100.150");
+
+ verify(testOrchastrator._ipAddressDao,
Mockito.times(findByIpTimes)).findByIpAndSourceNetworkId(Mockito.anyLong(),
Mockito.anyString());
+ verify(testOrchastrator._ipAddressDao,
Mockito.times(acquireLockTimes)).acquireInLockTable(Mockito.anyLong());
+ verify(testOrchastrator._ipAddressDao,
Mockito.times(releaseFromLockTimes)).releaseFromLockTable(Mockito.anyLong());
+ verify(testOrchastrator._ipAddressDao,
Mockito.times(updateTimes)).update(Mockito.anyLong(),
Mockito.any(IPAddressVO.class));
+ verify(testOrchastrator,
Mockito.times(validateTimes)).validateLockedRequestedIp(Mockito.any(IPAddressVO.class),
Mockito.any(IPAddressVO.class));
+ }
+
+ @Test(expected = InvalidParameterValueException.class)
+ public void validateLockedRequestedIpTestNullLockedIp() {
+ IPAddressVO ipVoSpy = Mockito.spy(new IPAddressVO(new
Ip("192.168.100.100"), 0l, 0l, 0l, true));
+ testOrchastrator.validateLockedRequestedIp(ipVoSpy, null);
+ }
+
+ @Test
+ public void validateLockedRequestedIpTestNotFreeLockedIp() {
+ IPAddressVO ipVoSpy = Mockito.spy(new IPAddressVO(new
Ip("192.168.100.100"), 0l, 0l, 0l, true));
+ State[] states = State.values();
+ for(int i=0; i < states.length;i++) {
+ boolean expectedException = false;
+ if (states[i] == State.Free) {
+ continue;
+ }
+ IPAddressVO lockedIp = ipVoSpy;
+ lockedIp.setState(states[i]);
+ try {
+ testOrchastrator.validateLockedRequestedIp(ipVoSpy, lockedIp);
+ } catch (InvalidParameterValueException e) {
+ expectedException = true;
+ }
+ Assert.assertTrue(expectedException);
+ }
+ }
+
+ @Test
+ public void validateLockedRequestedIpTestFreeAndNotNullIp() {
+ IPAddressVO ipVoSpy = Mockito.spy(new IPAddressVO(new
Ip("192.168.100.100"), 0l, 0l, 0l, true));
+ IPAddressVO lockedIp = ipVoSpy;
+ lockedIp.setState(State.Free);
+ testOrchastrator.validateLockedRequestedIp(ipVoSpy, lockedIp);
+ }
+
}
diff --git a/engine/schema/src/main/java/com/cloud/dc/dao/VlanDao.java
b/engine/schema/src/main/java/com/cloud/dc/dao/VlanDao.java
index e92a5cc6f1c..a3e3c60210c 100644
--- a/engine/schema/src/main/java/com/cloud/dc/dao/VlanDao.java
+++ b/engine/schema/src/main/java/com/cloud/dc/dao/VlanDao.java
@@ -27,6 +27,8 @@
VlanVO findByZoneAndVlanId(long zoneId, String vlanId);
+ VlanVO findByNetworkIdAndIpv4(long networkId, String ipv4Address);
+
List<VlanVO> listByZone(long zoneId);
List<VlanVO> listByType(Vlan.VlanType vlanType);
diff --git a/engine/schema/src/main/java/com/cloud/dc/dao/VlanDaoImpl.java
b/engine/schema/src/main/java/com/cloud/dc/dao/VlanDaoImpl.java
index 0c5914824f4..2737beb03b4 100644
--- a/engine/schema/src/main/java/com/cloud/dc/dao/VlanDaoImpl.java
+++ b/engine/schema/src/main/java/com/cloud/dc/dao/VlanDaoImpl.java
@@ -43,6 +43,7 @@
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.TransactionLegacy;
import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.net.NetUtils;
@Component
public class VlanDaoImpl extends GenericDaoBase<VlanVO, Long> implements
VlanDao {
@@ -82,6 +83,24 @@ public VlanVO findByZoneAndVlanId(long zoneId, String
vlanId) {
return findOneBy(sc);
}
+ /**
+ * Returns a vlan by the network id and if the given IPv4 is in the
network IP range.
+ */
+ @Override
+ public VlanVO findByNetworkIdAndIpv4(long networkId, String ipv4Address) {
+ List<VlanVO> vlanVoList = listVlansByNetworkId(networkId);
+ for (VlanVO vlan : vlanVoList) {
+ String ipRange = vlan.getIpRange();
+ String[] ipRangeParts = ipRange.split("-");
+ String startIP = ipRangeParts[0];
+ String endIP = ipRangeParts[1];
+ if (NetUtils.isIpInRange(ipv4Address, startIP, endIP)) {
+ return vlan;
+ }
+ }
+ return null;
+ }
+
@Override
public List<VlanVO> listByZone(long zoneId) {
SearchCriteria<VlanVO> sc = ZoneSearch.create();
diff --git
a/server/src/main/java/com/cloud/network/guru/DirectPodBasedNetworkGuru.java
b/server/src/main/java/com/cloud/network/guru/DirectPodBasedNetworkGuru.java
index a797b24471a..01b33893b5c 100644
--- a/server/src/main/java/com/cloud/network/guru/DirectPodBasedNetworkGuru.java
+++ b/server/src/main/java/com/cloud/network/guru/DirectPodBasedNetworkGuru.java
@@ -30,8 +30,8 @@
import com.cloud.dc.Pod;
import com.cloud.dc.PodVlanMapVO;
import com.cloud.dc.Vlan;
-import com.cloud.dc.VlanVO;
import com.cloud.dc.Vlan.VlanType;
+import com.cloud.dc.VlanVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.PodVlanMapDao;
import com.cloud.dc.dao.VlanDao;
@@ -44,10 +44,10 @@
import com.cloud.network.Networks.AddressFormat;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.IsolationType;
+import com.cloud.network.PhysicalNetwork;
import com.cloud.network.addr.PublicIp;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.IPAddressVO;
-import com.cloud.network.PhysicalNetwork;
import com.cloud.offering.NetworkOffering;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.utils.db.DB;
@@ -55,7 +55,6 @@
import com.cloud.utils.db.TransactionCallbackNoReturn;
import com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn;
import com.cloud.utils.db.TransactionStatus;
-import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.Nic;
import com.cloud.vm.Nic.ReservationStrategy;
@@ -106,10 +105,6 @@ public NicProfile allocate(Network network, NicProfile
nic, VirtualMachineProfil
rsStrategy = ReservationStrategy.Create;
}
- if (nic != null && nic.getRequestedIPv4() != null) {
- throw new CloudRuntimeException("Does not support custom ip
allocation at this time: " + nic);
- }
-
if (nic == null) {
nic = new NicProfile(rsStrategy, null, null, null, null);
} else if (nic.getIPv4Address() == null) {
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 b9762fdae63..958dfc6619d 100644
--- a/utils/src/main/java/com/cloud/utils/net/NetUtils.java
+++ b/utils/src/main/java/com/cloud/utils/net/NetUtils.java
@@ -479,9 +479,23 @@ public static boolean isValidIp4(final String ip) {
return validator.isValidInet4Address(ip);
}
+ /**
+ * Returns true if the given IPv4 address is in the specific Ipv4 range
+ */
+ public static boolean isIpInRange(final String ipInRange, final String
startIP, final String endIP) {
+ if (ipInRange == null || !validIpRange(startIP, endIP))
+ return false;
+
+ final long ipInRangeLong = NetUtils.ip2Long(ipInRange);
+ final long startIPLong = NetUtils.ip2Long(startIP);
+ final long endIPLong = NetUtils.ip2Long(endIP);
+
+ return startIPLong <= ipInRangeLong && ipInRangeLong <= endIPLong;
+ }
+
public static boolean is31PrefixCidr(final String cidr) {
final boolean isValidCird = isValidIp4Cidr(cidr);
- if (isValidCird){
+ if (isValidCird) {
final String[] cidrPair = cidr.split("\\/");
final String cidrSize = cidrPair[1];
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
> Support requesting a specific IPv4 address in Basic Networking during
> Instance creation
> ---------------------------------------------------------------------------------------
>
> Key: CLOUDSTACK-10199
> URL: https://issues.apache.org/jira/browse/CLOUDSTACK-10199
> Project: CloudStack
> Issue Type: Improvement
> Security Level: Public(Anyone can view this level - this is the
> default.)
> Components: API
> Environment: CloudStack 4.10
> Reporter: Wido den Hollander
> Priority: Major
> Labels: basic-networking
>
> DirectPodBasedNetworkGuru does not support requesting a custom IP-Address
> while creating a new NIC/Instance.
> {quote}
> Error 530: Does not support custom ip allocation at this time:
> NicProfile[0-0-null-null-null
> {
> "cserrorcode": 4250,
> "errorcode": 530,
> "errortext": "Does not support custom ip allocation at this time:
> NicProfile[0-0-null-null-null",
> "uuidList": []
> }
> {quote}
> Some use-cases prefer the ability to request the IPv4 address which the
> Instance will get.
--
This message was sent by Atlassian JIRA
(v7.6.3#76005)