You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by GitBox <gi...@apache.org> on 2018/05/09 16:03:14 UTC

[GitHub] rhtyd closed pull request #2615: config-drive: support user data on L2 networks

rhtyd closed pull request #2615: config-drive: support user data on L2 networks
URL: https://github.com/apache/cloudstack/pull/2615
 
 
   

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/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
index cec2e5926c1..f9d63676f8c 100644
--- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
+++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
@@ -2290,13 +2290,14 @@ public Network createGuestNetwork(final long networkOfferingId, final String nam
         final boolean cidrRequired = zone.getNetworkType() == NetworkType.Advanced
                 && ntwkOff.getTrafficType() == TrafficType.Guest
                 && (ntwkOff.getGuestType() == GuestType.Shared || (ntwkOff.getGuestType() == GuestType.Isolated
-                && !_networkModel.areServicesSupportedByNetworkOffering(ntwkOff.getId(), Service.SourceNat))
-                || ntwkOff.getGuestType() == GuestType.L2 && !_networkModel.listNetworkOfferingServices(ntwkOff.getId()).isEmpty());
+                && !_networkModel.areServicesSupportedByNetworkOffering(ntwkOff.getId(), Service.SourceNat)));
         if (cidr == null && ip6Cidr == null && cidrRequired) {
             throw new InvalidParameterValueException("StartIp/endIp/gateway/netmask are required when create network of" + " type " + Network.GuestType.Shared
                     + " and network of type " + GuestType.Isolated + " with service " + Service.SourceNat.getName() + " disabled");
         }
 
+        checkL2OfferingServices(ntwkOff);
+
         // No cidr can be specified in Basic zone
         if (zone.getNetworkType() == NetworkType.Basic && cidr != null) {
             throw new InvalidParameterValueException("StartIp/endIp/gateway/netmask can't be specified for zone of type " + NetworkType.Basic);
@@ -2395,6 +2396,21 @@ public Network doInTransaction(final TransactionStatus status) {
         return network;
     }
 
+    /**
+     * Checks for L2 network offering services. Only 2 cases allowed:
+     * - No services
+     * - User Data service only, provided by ConfigDrive
+     * @param ntwkOff network offering
+     */
+    protected void checkL2OfferingServices(NetworkOfferingVO ntwkOff) {
+        if (ntwkOff.getGuestType() == GuestType.L2 && !_networkModel.listNetworkOfferingServices(ntwkOff.getId()).isEmpty() &&
+                (!_networkModel.areServicesSupportedByNetworkOffering(ntwkOff.getId(), Service.UserData) ||
+                        (_networkModel.areServicesSupportedByNetworkOffering(ntwkOff.getId(), Service.UserData) &&
+                                _networkModel.listNetworkOfferingServices(ntwkOff.getId()).size() > 1))) {
+            throw new InvalidParameterValueException("For L2 networks, only UserData service is allowed");
+        }
+    }
+
     @Override
     @DB
     public boolean shutdownNetwork(final long networkId, final ReservationContext context, final boolean cleanupElements) {
diff --git a/engine/orchestration/test/org/apache/cloudstack/engine/orchestration/NetworkOrchestratorTest.java b/engine/orchestration/test/org/apache/cloudstack/engine/orchestration/NetworkOrchestratorTest.java
index 2d15403a865..b0283f35c1b 100644
--- a/engine/orchestration/test/org/apache/cloudstack/engine/orchestration/NetworkOrchestratorTest.java
+++ b/engine/orchestration/test/org/apache/cloudstack/engine/orchestration/NetworkOrchestratorTest.java
@@ -26,10 +26,15 @@
 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.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
 import org.mockito.Matchers;
 
 import com.cloud.network.Network;
@@ -56,6 +61,7 @@
 /**
  * NetworkManagerImpl implements NetworkManager.
  */
+@RunWith(JUnit4.class)
 public class NetworkOrchestratorTest extends TestCase {
     static final Logger s_logger = Logger.getLogger(NetworkOrchestratorTest.class);
 
@@ -65,6 +71,10 @@
     String dhcpProvider = "VirtualRouter";
     NetworkGuru guru = mock(NetworkGuru.class);
 
+    NetworkOfferingVO networkOffering = mock(NetworkOfferingVO.class);
+
+    private static final long networkOfferingId = 1l;
+
     @Override
     @Before
     public void setUp() {
@@ -90,6 +100,9 @@ public void setUp() {
         List<NetworkGuru> networkGurus = new ArrayList<NetworkGuru>();
         networkGurus.add(guru);
         testOrchastrator.networkGurus = networkGurus;
+
+        when(networkOffering.getGuestType()).thenReturn(GuestType.L2);
+        when(networkOffering.getId()).thenReturn(networkOfferingId);
     }
 
     @Test
@@ -159,4 +172,32 @@ public void testDontRemoveDhcpServiceWhenNotProvided() {
         verify(testOrchastrator._ntwkSrvcDao, never()).getProviderForServiceInNetwork(network.getId(), Service.Dhcp);
         verify(testOrchastrator._networksDao, times(1)).findById(nic.getNetworkId());
     }
+
+    @Test
+    public void testCheckL2OfferingServicesEmptyServices() {
+        when(testOrchastrator._networkModel.listNetworkOfferingServices(networkOfferingId)).thenReturn(new ArrayList<>());
+        when(testOrchastrator._networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.UserData)).thenReturn(false);
+        testOrchastrator.checkL2OfferingServices(networkOffering);
+    }
+
+    @Test
+    public void testCheckL2OfferingServicesUserDataOnly() {
+        when(testOrchastrator._networkModel.listNetworkOfferingServices(networkOfferingId)).thenReturn(Arrays.asList(Service.UserData));
+        when(testOrchastrator._networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.UserData)).thenReturn(true);
+        testOrchastrator.checkL2OfferingServices(networkOffering);
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void testCheckL2OfferingServicesMultipleServicesIncludingUserData() {
+        when(testOrchastrator._networkModel.listNetworkOfferingServices(networkOfferingId)).thenReturn(Arrays.asList(Service.UserData, Service.Dhcp));
+        when(testOrchastrator._networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.UserData)).thenReturn(true);
+        testOrchastrator.checkL2OfferingServices(networkOffering);
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void testCheckL2OfferingServicesMultipleServicesNotIncludingUserData() {
+        when(testOrchastrator._networkModel.listNetworkOfferingServices(networkOfferingId)).thenReturn(Arrays.asList(Service.Dns, Service.Dhcp));
+        when(testOrchastrator._networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.UserData)).thenReturn(false);
+        testOrchastrator.checkL2OfferingServices(networkOffering);
+    }
 }
diff --git a/server/src/com/cloud/network/NetworkModelImpl.java b/server/src/com/cloud/network/NetworkModelImpl.java
index 5edd2288231..60b21c382eb 100644
--- a/server/src/com/cloud/network/NetworkModelImpl.java
+++ b/server/src/com/cloud/network/NetworkModelImpl.java
@@ -580,7 +580,7 @@ public boolean canUseForDeploy(Network network) {
         if (network.getTrafficType() != TrafficType.Guest) {
             return false;
         }
-        if (listNetworkOfferingServices(network.getNetworkOfferingId()).isEmpty()) {
+        if (network.getGuestType() == GuestType.L2 || listNetworkOfferingServices(network.getNetworkOfferingId()).isEmpty()) {
             return true; // do not check free IPs if there is no service in the network
         }
         boolean hasFreeIps = true;
diff --git a/server/src/com/cloud/network/guru/GuestNetworkGuru.java b/server/src/com/cloud/network/guru/GuestNetworkGuru.java
index c7e6aca22b8..3f6562e0eee 100644
--- a/server/src/com/cloud/network/guru/GuestNetworkGuru.java
+++ b/server/src/com/cloud/network/guru/GuestNetworkGuru.java
@@ -200,7 +200,7 @@ public Network design(final NetworkOffering offering, final DeploymentPlan plan,
             if (userSpecified.getCidr() != null) {
                 network.setCidr(userSpecified.getCidr());
                 network.setGateway(userSpecified.getGateway());
-            } else if (offering.getGuestType() == GuestType.Shared || !_networkModel.listNetworkOfferingServices(offering.getId()).isEmpty()) {
+            } else if (offering.getGuestType() != GuestType.L2 && (offering.getGuestType() == GuestType.Shared || !_networkModel.listNetworkOfferingServices(offering.getId()).isEmpty())) {
                 final String guestNetworkCidr = dc.getGuestNetworkCidr();
                 if (guestNetworkCidr != null) {
                     final String[] cidrTuple = guestNetworkCidr.split("\\/");
@@ -370,7 +370,7 @@ public NicProfile allocate(final Network network, NicProfile nic, final VirtualM
                     guestIp = network.getGateway();
                 } else {
                     guestIp = _ipAddrMgr.acquireGuestIpAddress(network, nic.getRequestedIPv4());
-                    if (guestIp == null && !_networkModel.listNetworkOfferingServices(network.getNetworkOfferingId()).isEmpty()) {
+                    if (guestIp == null && network.getGuestType() != GuestType.L2 && !_networkModel.listNetworkOfferingServices(network.getNetworkOfferingId()).isEmpty()) {
                         throw new InsufficientVirtualNetworkCapacityException("Unable to acquire Guest IP" + " address for network " + network, DataCenter.class,
                                 dc.getId());
                     }
diff --git a/ui/scripts/configuration.js b/ui/scripts/configuration.js
index 79916f5e411..2eee7bbeae0 100644
--- a/ui/scripts/configuration.js
+++ b/ui/scripts/configuration.js
@@ -2404,8 +2404,10 @@
                                         var $useVpc = args.$form.find('.form-item[rel=\"useVpc\"]');
                                         var $useVpcCb = $useVpc.find("input[type=checkbox]");
                                         var $supportedServices = args.$form.find('.form-item[rel=\"supportedServices\"]');
+                                        var $userDataL2 = args.$form.find('.form-item[rel=\"userDataL2\"]');
                                         if ($guestTypeField.val() == 'Shared') { //Shared network offering
                                             $useVpc.hide();
+                                            $userDataL2.hide();
                                             $supportedServices.css('display', 'inline-block');
                                             if ($useVpcCb.is(':checked')) { //if useVpc is checked,
                                                 $useVpcCb.removeAttr("checked"); //remove "checked" attribute in useVpc
@@ -2413,9 +2415,11 @@
                                         } else if ($guestTypeField.val() == 'Isolated') { //Isolated network offering
                                             $useVpc.css('display', 'inline-block');
                                             $supportedServices.css('display', 'inline-block');
+                                            $userDataL2.hide();
                                         } else if ($guestTypeField.val() == 'L2') {
                                             $useVpc.hide();
                                             $supportedServices.hide();
+                                            $userDataL2.css('display', 'inline-block');
                                         }
                                         var $providers = $useVpcCb.closest('form').find('.dynamic-input select[name!="service.Connectivity.provider"]');
                                         var $optionsOfProviders = $providers.find('option');
@@ -2803,6 +2807,13 @@
                                         isBoolean: true
                                     },
 
+                                    userDataL2: {
+                                        label: 'label.user.data',
+                                        docID: 'helpL2UserData',
+                                        isBoolean: true,
+                                        isHidden: true
+                                    },
+
                                     lbType: { //only shown when VPC is checked and LB service is checked
                                         label: 'label.load.balancer.type',
                                         isHidden: true,
@@ -3384,6 +3395,14 @@
                                     } else { //specifyVlan checkbox is unchecked
                                         delete inputData.specifyVlan; //if specifyVlan checkbox is unchecked, do not pass specifyVlan parameter to API call since we need to keep API call's size as small as possible (p.s. specifyVlan is defaulted as false at server-side)
                                     }
+
+                                    if (inputData['userDataL2'] == 'on') {
+                                        inputData['serviceProviderList[0].service'] = 'UserData';
+                                        inputData['serviceProviderList[0].provider'] = 'ConfigDrive';
+                                        inputData['supportedServices'] = 'UserData';
+                                    } else {
+                                        delete inputData.serviceProviderList;
+                                    }
                                 }
 
                                 if (inputData['forvpc'] == 'on') {
diff --git a/ui/scripts/docs.js b/ui/scripts/docs.js
index 583db58bb45..bbe8f3e64b4 100755
--- a/ui/scripts/docs.js
+++ b/ui/scripts/docs.js
@@ -1351,5 +1351,9 @@ cloudStack.docs = {
     },
     helpSetReservationSystemVms: {
         desc: 'If enabled, IP range reservation is set for SSVM & CPVM. Global setting "system.vm.public.ip.reservation.mode.strictness" is used to control whether reservation is strict or not (preferred)'
+    },
+    helpL2UserData: {
+        desc: 'Pass user and meta data to VMs (via ConfigDrive)',
+        externalLink: ''
     }
 };


 

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


With regards,
Apache Git Services