CLOUDSTACK-869 nTier Apps 2.0 : Support NetScalar as external LB provider

This commit is contained in:
Rajesh Battala 2013-05-08 18:46:51 +05:30 committed by Murali Reddy
parent 2e1877af33
commit 2e21060028
8 changed files with 406 additions and 23 deletions

View File

@ -26,6 +26,7 @@ public interface VpcOffering extends InternalIdentity, Identity {
}
public static final String defaultVPCOfferingName = "Default VPC offering";
public static final String defaultVPCNSOfferingName = "Default VPC offering with Netscaler";
/**
*

View File

@ -61,6 +61,9 @@ import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.network.rules.LbStickinessMethod;
import com.cloud.network.rules.LbStickinessMethod.StickinessMethodType;
import com.cloud.network.rules.StaticNat;
import com.cloud.network.vpc.PrivateGateway;
import com.cloud.network.vpc.StaticRouteProfile;
import com.cloud.network.vpc.Vpc;
import com.cloud.offering.NetworkOffering;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.db.DB;
@ -85,7 +88,7 @@ import java.util.*;
@Local(value = {NetworkElement.class, StaticNatServiceProvider.class, LoadBalancingServiceProvider.class, GslbServiceProvider.class})
public class NetscalerElement extends ExternalLoadBalancerDeviceManagerImpl implements LoadBalancingServiceProvider,
NetscalerLoadBalancerElementService, ExternalLoadBalancerDeviceManager, IpDeployer, StaticNatServiceProvider,
GslbServiceProvider {
GslbServiceProvider, VpcProvider {
private static final Logger s_logger = Logger.getLogger(NetscalerElement.class);
public static final AutoScaleCounterType AutoScaleCounterSnmp = new AutoScaleCounterType("snmp");
@ -957,4 +960,33 @@ public class NetscalerElement extends ExternalLoadBalancerDeviceManagerImpl impl
}
return null;
}
@Override
public boolean implementVpc(Vpc vpc, DeployDestination dest, ReservationContext context)
throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
return true;
}
@Override
public boolean shutdownVpc(Vpc vpc, ReservationContext context) throws ConcurrentOperationException,
ResourceUnavailableException {
return true;
}
@Override
public boolean createPrivateGateway(PrivateGateway gateway) throws ConcurrentOperationException,
ResourceUnavailableException {
return true;
}
@Override
public boolean deletePrivateGateway(PrivateGateway privateGateway) throws ConcurrentOperationException,
ResourceUnavailableException {
return true;
}
@Override
public boolean applyStaticRoutes(Vpc vpc, List<StaticRouteProfile> routes) throws ResourceUnavailableException {
return true;
}
}

View File

@ -154,7 +154,9 @@
<exclude>com/cloud/network/vpn/RemoteAccessVpnTest.java</exclude>
<exclude>com/cloud/network/security/SecurityGroupManagerImpl2Test.java</exclude>
<exclude>com/cloud/network/security/SecurityGroupManagerImpl2Test.java</exclude>
<exclude>com/cloud/vpc/*</exclude>
<exclude>com/cloud/vpc/VpcTestConfiguration.java</exclude>
<exclude>com/cloud/vpc/VpcApiUnitTest.java</exclude>
<exclude>com/cloud/vpc/VpcManagerTest.java</exclude>
</excludes>
</configuration>
</plugin>

View File

@ -1121,7 +1121,11 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
// validate if CIDR specified overlaps with any of the CIDR's allocated for isolated networks and shared networks in the zone
checkSharedNetworkCidrOverlap(zoneId, pNtwk.getId(), cidr);
} else {
throw new InvalidParameterValueException("Cannot specify CIDR when using network offering with external devices!");
// if the guest network is for the VPC, if any External Provider are supported in VPC
// cidr will not be null as it is generated from the super cidr of vpc.
// if cidr is not null and network is not part of vpc then throw the exception
if (vpcId == null)
throw new InvalidParameterValueException("Cannot specify CIDR when using network offering with external devices!");
}
}

View File

@ -118,7 +118,7 @@ public class ExternalGuestNetworkGuru extends GuestNetworkGuru {
if (Boolean.parseBoolean(_configDao.getValue(Config.OvsTunnelNetwork.key()))) {
return null;
}
if (!_networkModel.networkIsConfiguredForExternalNetworking(config.getDataCenterId(), config.getId())) {
return super.implement(config, offering, dest, context);
}
@ -145,25 +145,31 @@ public class ExternalGuestNetworkGuru extends GuestNetworkGuru {
implemented.setBroadcastUri(config.getBroadcastUri());
}
// Determine the offset from the lowest vlan tag
int offset = getVlanOffset(config.getPhysicalNetworkId(), vlanTag);
// Determine the new gateway and CIDR
String[] oldCidr = config.getCidr().split("/");
String oldCidrAddress = oldCidr[0];
int cidrSize = getGloballyConfiguredCidrSize();
// If the offset has more bits than there is room for, return null
long bitsInOffset = 32 - Integer.numberOfLeadingZeros(offset);
if (bitsInOffset > (cidrSize - 8)) {
throw new CloudRuntimeException("The offset " + offset + " needs " + bitsInOffset + " bits, but only have " + (cidrSize - 8) + " bits to work with.");
int cidrSize = Integer.parseInt(oldCidr[1]);
long newCidrAddress = (NetUtils.ip2Long(oldCidrAddress));
// if the implementing network is for vpc, no need to generate newcidr, use the cidr that came from super cidr
if (config.getVpcId() != null) {
implemented.setGateway(config.getGateway());
implemented.setCidr(config.getCidr());
implemented.setState(State.Implemented);
} else {
// Determine the offset from the lowest vlan tag
int offset = getVlanOffset(config.getPhysicalNetworkId(), vlanTag);
cidrSize = getGloballyConfiguredCidrSize();
// If the offset has more bits than there is room for, return null
long bitsInOffset = 32 - Integer.numberOfLeadingZeros(offset);
if (bitsInOffset > (cidrSize - 8)) {
throw new CloudRuntimeException("The offset " + offset + " needs " + bitsInOffset + " bits, but only have " + (cidrSize - 8) + " bits to work with.");
}
newCidrAddress = (NetUtils.ip2Long(oldCidrAddress) & 0xff000000) | (offset << (32 - cidrSize));
implemented.setGateway(NetUtils.long2Ip(newCidrAddress + 1));
implemented.setCidr(NetUtils.long2Ip(newCidrAddress) + "/" + cidrSize);
implemented.setState(State.Implemented);
}
long newCidrAddress = (NetUtils.ip2Long(oldCidrAddress) & 0xff000000) | (offset << (32 - cidrSize));
implemented.setGateway(NetUtils.long2Ip(newCidrAddress + 1));
implemented.setCidr(NetUtils.long2Ip(newCidrAddress) + "/" + cidrSize);
implemented.setState(State.Implemented);
// Mask the Ipv4 address of all nics that use this network with the new guest VLAN offset
List<NicVO> nicsInNetwork = _nicDao.listByNetworkId(config.getId());
for (NicVO nic : nicsInNetwork) {
@ -172,8 +178,8 @@ public class ExternalGuestNetworkGuru extends GuestNetworkGuru {
nic.setIp4Address(NetUtils.long2Ip(newCidrAddress | ipMask));
_nicDao.persist(nic);
}
}
}
// Mask the destination address of all port forwarding rules in this network with the new guest VLAN offset
List<PortForwardingRuleVO> pfRulesInNetwork = _pfRulesDao.listByNetwork(config.getId());
for (PortForwardingRuleVO pfRule : pfRulesInNetwork) {

View File

@ -184,8 +184,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
private final ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("VpcChecker"));
private List<VpcProvider> vpcElements = null;
private final List<Service> nonSupportedServices = Arrays.asList(Service.SecurityGroup, Service.Firewall);
private final List<Provider> supportedProviders = Arrays.asList(Provider.VPCVirtualRouter, Provider.NiciraNvp);
private final List<Provider> supportedProviders = Arrays.asList(Provider.VPCVirtualRouter, Provider.NiciraNvp, Provider.Netscaler);
int _cleanupInterval;
int _maxNetworks;
SearchBuilder<IPAddressVO> IpAddressSearch;
@ -215,7 +214,27 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
createVpcOffering(VpcOffering.defaultVPCOfferingName, VpcOffering.defaultVPCOfferingName, svcProviderMap,
true, State.Enabled);
}
//configure default vpc offering with Netscaler as LB Provider
if (_vpcOffDao.findByUniqueName(VpcOffering.defaultVPCNSOfferingName ) == null) {
s_logger.debug("Creating default VPC offering with Netscaler as LB Provider" + VpcOffering.defaultVPCNSOfferingName);
Map<Service, Set<Provider>> svcProviderMap = new HashMap<Service, Set<Provider>>();
Set<Provider> defaultProviders = new HashSet<Provider>();
defaultProviders.add(Provider.VPCVirtualRouter);
for (Service svc : getSupportedServices()) {
if (svc == Service.Lb) {
Set<Provider> lbProviders = new HashSet<Provider>();
lbProviders.add(Provider.Netscaler);
lbProviders.add(Provider.VPCVirtualRouter);
svcProviderMap.put(svc, lbProviders);
} else {
svcProviderMap.put(svc, defaultProviders);
}
}
createVpcOffering(VpcOffering.defaultVPCNSOfferingName, VpcOffering.defaultVPCNSOfferingName,
svcProviderMap, false, State.Enabled);
}
txn.commit();
Map<String, String> configs = _configDao.getConfiguration(params);
@ -1084,6 +1103,12 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
if (guestNtwkOff.isConserveMode()) {
throw new InvalidParameterValueException("Only networks with conserve mode Off can belong to VPC");
}
//5) If Netscaler is LB provider make sure it is in dedicated mode
if ( providers.contains(Provider.Netscaler) && !guestNtwkOff.getDedicatedLB() ) {
throw new InvalidParameterValueException("Netscaler only with Dedicated LB can belong to VPC");
}
return ;
}
@DB
@ -1155,6 +1180,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
if (vpcElements == null) {
vpcElements = new ArrayList<VpcProvider>();
vpcElements.add((VpcProvider)_ntwkModel.getElementImplementingProvider(Provider.VPCVirtualRouter.getName()));
vpcElements.add((VpcProvider)_ntwkModel.getElementImplementingProvider(Provider.Netscaler.getName()));
}
if (vpcElements == null) {

View File

@ -0,0 +1,269 @@
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.cloud.vpc;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.VlanDao;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkModel;
import com.cloud.network.NetworkService;
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.dao.Site2SiteVpnGatewayDao;
import com.cloud.network.vpc.*;
import com.cloud.network.vpc.dao.PrivateIpDao;
import com.cloud.network.vpc.dao.StaticRouteDao;
import com.cloud.network.vpc.dao.VpcDao;
import com.cloud.network.vpc.dao.VpcGatewayDao;
import com.cloud.network.vpc.dao.VpcOfferingDao;
import com.cloud.network.vpc.dao.VpcOfferingServiceMapDao;
import com.cloud.network.vpc.dao.VpcServiceMapDao;
import com.cloud.network.vpn.Site2SiteVpnManager;
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
import com.cloud.server.ConfigurationServer;
import com.cloud.tags.dao.ResourceTagDao;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.ResourceLimitService;
import com.cloud.user.UserContext;
import com.cloud.utils.component.ComponentContext;
import com.cloud.vm.dao.DomainRouterDao;
import junit.framework.TestCase;
import org.apache.cloudstack.api.command.user.network.CreateNetworkACLCmd;
import org.apache.cloudstack.api.command.user.vpc.CreateVPCCmd;
import org.apache.cloudstack.test.utils.SpringUtils;
import org.apache.log4j.Logger;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import javax.inject.Inject;
import java.io.IOException;
import java.util.UUID;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public class VpcTest extends TestCase {
@Inject
VpcService _vpcService;
@Inject
AccountManager _accountMgr;
@Inject
VpcManager _vpcMgr;
@Inject
VpcDao _vpcDao;
@Inject
VpcOfferingDao _vpcOfferinDao;
private VpcVO vpc;
private static final Logger s_logger = Logger.getLogger(VpcTest.class);
@Before
public void setUp() {
ComponentContext.initComponentsLifeCycle();
Account account = new AccountVO("testaccount", 1, "testdomain", (short) 0, UUID.randomUUID().toString());
UserContext.registerContext(1, account, null, true);
vpc = new VpcVO(1, "myvpc", "myvpc", 2, 1, 1, "10.0.1.0/16", "mydomain");
}
@Test
public void testCreateVpc() throws Exception {
Mockito.when(
_vpcMgr.createVpc(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString(),
Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn(vpc);
Mockito.when(_vpcOfferinDao.persist(Mockito.any(VpcOfferingVO.class))).thenReturn(
new VpcOfferingVO("test", "test", 1L));
Vpc vpc1 = _vpcMgr.createVpc(1, 1, 1, "myVpc", "my Vpc", "10.0.0.0/16", "test");
assertNotNull("Vpc is created", vpc1);
}
@Configuration
@ComponentScan(basePackageClasses = { VpcManager.class }, includeFilters = { @ComponentScan.Filter(value = VpcTestConfiguration.Library.class, type = FilterType.CUSTOM) }, useDefaultFilters = false)
public static class VpcTestConfiguration extends SpringUtils.CloudStackTestConfiguration {
@Bean
public AccountManager accountManager() {
return Mockito.mock(AccountManager.class);
}
@Bean
public NetworkManager networkManager() {
return Mockito.mock(NetworkManager.class);
}
@Bean
public NetworkModel networkModel() {
return Mockito.mock(NetworkModel.class);
}
@Bean
public VpcManager vpcManager() {
return Mockito.mock(VpcManager.class);
}
@Bean
public ResourceTagDao resourceTagDao() {
return Mockito.mock(ResourceTagDao.class);
}
@Bean
public VpcDao VpcDao() {
return Mockito.mock(VpcDao.class);
}
@Bean
public VpcOfferingDao vpcOfferingDao() {
return Mockito.mock(VpcOfferingDao.class);
}
@Bean
public VpcOfferingServiceMapDao vpcOfferingServiceMapDao() {
return Mockito.mock(VpcOfferingServiceMapDao.class);
}
@Bean
public ConfigurationDao configurationDao() {
return Mockito.mock(ConfigurationDao.class);
}
@Bean
public ConfigurationManager configurationManager() {
return Mockito.mock(ConfigurationManager.class);
}
@Bean
public NetworkDao networkDao() {
return Mockito.mock(NetworkDao.class);
}
@Bean
public NetworkACLManager networkACLManager() {
return Mockito.mock(NetworkACLManager.class);
}
@Bean
public IPAddressDao ipAddressDao() {
return Mockito.mock(IPAddressDao.class);
}
@Bean
public DomainRouterDao domainRouterDao() {
return Mockito.mock(DomainRouterDao.class);
}
@Bean
public VpcGatewayDao vpcGatewayDao() {
return Mockito.mock(VpcGatewayDao.class);
}
@Bean
public PrivateIpDao privateIpDao() {
return Mockito.mock(PrivateIpDao.class);
}
@Bean
public StaticRouteDao staticRouteDao() {
return Mockito.mock(StaticRouteDao.class);
}
@Bean
public NetworkOfferingServiceMapDao networkOfferingServiceMapDao() {
return Mockito.mock(NetworkOfferingServiceMapDao.class);
}
@Bean
public PhysicalNetworkDao physicalNetworkDao() {
return Mockito.mock(PhysicalNetworkDao.class);
}
@Bean
public FirewallRulesDao firewallRulesDao() {
return Mockito.mock(FirewallRulesDao.class);
}
@Bean
public Site2SiteVpnGatewayDao site2SiteVpnGatewayDao() {
return Mockito.mock(Site2SiteVpnGatewayDao.class);
}
@Bean
public Site2SiteVpnManager site2SiteVpnManager() {
return Mockito.mock(Site2SiteVpnManager.class);
}
@Bean
public VlanDao vlanDao() {
return Mockito.mock(VlanDao.class);
}
@Bean
public ResourceLimitService resourceLimitService() {
return Mockito.mock(ResourceLimitService.class);
}
@Bean
public VpcServiceMapDao vpcServiceMapDao() {
return Mockito.mock(VpcServiceMapDao.class);
}
@Bean
public NetworkService networkService() {
return Mockito.mock(NetworkService.class);
}
@Bean
public DataCenterDao dataCenterDao() {
return Mockito.mock(DataCenterDao.class);
}
@Bean
public ConfigurationServer configurationServer() {
return Mockito.mock(ConfigurationServer.class);
}
public static class Library implements TypeFilter {
@Override
public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException {
mdr.getClassMetadata().getClassName();
ComponentScan cs = VpcTestConfiguration.class.getAnnotation(ComponentScan.class);
return SpringUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs);
}
}
}
}

View File

@ -41,6 +41,7 @@ import com.cloud.network.Network;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.vpc.VpcManager;
import com.cloud.offering.NetworkOffering.Availability;
import com.cloud.offerings.NetworkOfferingServiceMapVO;
import com.cloud.offerings.NetworkOfferingVO;
@ -72,6 +73,9 @@ public class CreateNetworkOfferingTest extends TestCase{
@Inject
AccountManager accountMgr;
@Inject
VpcManager vpcMgr;
@Before
public void setUp() {
ComponentContext.initComponentsLifeCycle();
@ -180,4 +184,43 @@ public class CreateNetworkOfferingTest extends TestCase{
assertNotNull("Isolated network offering with specifyIpRanges=true and with no sourceNatService, failed to create", off);
}
@Test
public void createVpcNtwkOff() {
Map<Service, Set<Provider>> serviceProviderMap = new HashMap<Network.Service, Set<Network.Provider>>();
Set<Network.Provider> vrProvider = new HashSet<Network.Provider>();
vrProvider.add(Provider.VPCVirtualRouter);
serviceProviderMap.put(Network.Service.Dhcp , vrProvider);
serviceProviderMap.put(Network.Service.Dns , vrProvider);
serviceProviderMap.put(Network.Service.Lb , vrProvider);
serviceProviderMap.put(Network.Service.SourceNat , vrProvider);
serviceProviderMap.put(Network.Service.Gateway , vrProvider);
serviceProviderMap.put(Network.Service.Lb , vrProvider);
NetworkOfferingVO off = configMgr.createNetworkOffering("isolated", "isolated", TrafficType.Guest, null, true,
Availability.Optional, 200, serviceProviderMap, false, Network.GuestType.Isolated, false,
null, false, null, false, false);
// System.out.println("Creating Vpc Network Offering");
assertNotNull("Vpc Isolated network offering with Vpc provider ", off);
}
@Test
public void createVpcNtwkOffWithNetscaler() {
Map<Service, Set<Provider>> serviceProviderMap = new HashMap<Network.Service, Set<Network.Provider>>();
Set<Network.Provider> vrProvider = new HashSet<Network.Provider>();
Set<Network.Provider> lbProvider = new HashSet<Network.Provider>();
vrProvider.add(Provider.VPCVirtualRouter);
lbProvider.add(Provider.Netscaler);
serviceProviderMap.put(Network.Service.Dhcp, vrProvider);
serviceProviderMap.put(Network.Service.Dns, vrProvider);
serviceProviderMap.put(Network.Service.Lb, vrProvider);
serviceProviderMap.put(Network.Service.SourceNat, vrProvider);
serviceProviderMap.put(Network.Service.Gateway, vrProvider);
serviceProviderMap.put(Network.Service.Lb, lbProvider);
NetworkOfferingVO off = configMgr.createNetworkOffering("isolated", "isolated", TrafficType.Guest, null, true,
Availability.Optional, 200, serviceProviderMap, false, Network.GuestType.Isolated, false, null, false,
null, false, false);
// System.out.println("Creating Vpc Network Offering");
assertNotNull("Vpc Isolated network offering with Vpc and Netscaler provider ", off);
}
}