This is an automated email from the ASF dual-hosted git repository.
rohit pushed a commit to branch 4.11
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/4.11 by this push:
new bd89760 config-drive: support user data on L2 networks (#2615)
bd89760 is described below
commit bd8976010835acaa690c85775d0504a4ff8df894
Author: Nicolas Vazquez <[email protected]>
AuthorDate: Wed May 9 13:03:11 2018 -0300
config-drive: support user data on L2 networks (#2615)
Supporting ConfigDrive user data on L2 networks.
Add UI checkbox to create L2 network offering with config drive.
Signed-off-by: Rohit Yadav <[email protected]>
---
.../engine/orchestration/NetworkOrchestrator.java | 20 +++++++++--
.../orchestration/NetworkOrchestratorTest.java | 41 ++++++++++++++++++++++
server/src/com/cloud/network/NetworkModelImpl.java | 2 +-
.../com/cloud/network/guru/GuestNetworkGuru.java | 4 +--
ui/scripts/configuration.js | 19 ++++++++++
ui/scripts/docs.js | 4 +++
6 files changed, 85 insertions(+), 5 deletions(-)
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 1b707c3..5508472 100644
---
a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
+++
b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
@@ -2291,13 +2291,14 @@ public class NetworkOrchestrator extends ManagerBase
implements NetworkOrchestra
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);
@@ -2396,6 +2397,21 @@ public class NetworkOrchestrator extends ManagerBase
implements NetworkOrchestra
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 2d15403..b0283f3 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.ArrayList;
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 @@ import junit.framework.TestCase;
/**
* NetworkManagerImpl implements NetworkManager.
*/
+@RunWith(JUnit4.class)
public class NetworkOrchestratorTest extends TestCase {
static final Logger s_logger =
Logger.getLogger(NetworkOrchestratorTest.class);
@@ -65,6 +71,10 @@ public class NetworkOrchestratorTest extends TestCase {
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 class NetworkOrchestratorTest extends TestCase {
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 class NetworkOrchestratorTest extends TestCase {
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 5edd228..60b21c3 100644
--- a/server/src/com/cloud/network/NetworkModelImpl.java
+++ b/server/src/com/cloud/network/NetworkModelImpl.java
@@ -580,7 +580,7 @@ public class NetworkModelImpl extends ManagerBase
implements NetworkModel, Confi
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 c7e6aca..3f6562e 100644
--- a/server/src/com/cloud/network/guru/GuestNetworkGuru.java
+++ b/server/src/com/cloud/network/guru/GuestNetworkGuru.java
@@ -200,7 +200,7 @@ public abstract class GuestNetworkGuru extends AdapterBase
implements NetworkGur
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 abstract class GuestNetworkGuru extends AdapterBase
implements NetworkGur
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 79916f5..2eee7bb 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 583db58..bbe8f3e 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: ''
}
};
--
To stop receiving notification emails like this one, please contact
[email protected].