cloudstack-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "ASF GitHub Bot (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (CLOUDSTACK-10199) Support requesting a specific IPv4 address in Basic Networking during Instance creation
Date Tue, 27 Nov 2018 11:40:00 GMT

    [ 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:
users@infra.apache.org


> 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)

Mime
View raw message