Skip to content

Commit

Permalink
CLOUDSTACK-10047: DVSwitch fixes and improvements (#2293)
Browse files Browse the repository at this point in the history
Allow security policies to apply on port groups:
- Accepts security policies while creating network offering
- Deployed network will have security policies from the network offering
  applied on the port group (in vmware environment)
- Global settings as fallback when security policies are not defined for a network
  offering
- Default promiscuous mode security policy set to REJECT as it's the default
  for standard/default vswitch

Portgroup vlan-trunking options for dvswitch: This allows admins to define
a network with comma separated vlan id and vlan
range such as vlan://200-400,21,30-50 and use the provided vlan range to
configure vlan-trunking for a portgroup in dvswitch based environment.

VLAN overlap checks are performed for:
- isolated network against existing shared and isolated networks
- dedicated vlan ranges for the physical/public network for the zone
- shared network against existing isolated network

Allow shared networks to bypass vlan overlap checks: This allows admins
to create shared networks with a `bypassvlanoverlapcheck` API flag
which when set to 'true' will create a shared network without
performing vlan overlap checks against isolated network and against
the vlans allocated to the datacenter's physical network (vlan ranges).

Notes:
- No vlan-range overlap checks are performed when creating shared networks
- Multiple vlan id/ranges should include the vlan:// scheme prefix

Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
  • Loading branch information
rohityadavcloud committed Oct 25, 2017
1 parent 4d19373 commit 41fdb88
Show file tree
Hide file tree
Showing 33 changed files with 736 additions and 190 deletions.
12 changes: 12 additions & 0 deletions api/src/com/cloud/agent/api/to/NicTO.java
Expand Up @@ -16,7 +16,10 @@
// under the License.
package com.cloud.agent.api.to;

import com.cloud.offering.NetworkOffering;

import java.util.List;
import java.util.Map;

public class NicTO extends NetworkTO {
int deviceId;
Expand All @@ -26,6 +29,7 @@ public class NicTO extends NetworkTO {
boolean pxeDisable;
String nicUuid;
List<String> nicSecIps;
Map<NetworkOffering.Detail, String> details;

public NicTO() {
super();
Expand Down Expand Up @@ -97,4 +101,12 @@ public String getNetworkUuid() {
public void setNetworkUuid(String uuid) {
super.setUuid(uuid);
}

public Map<NetworkOffering.Detail, String> getDetails() {
return details;
}

public void setDetails(final Map<NetworkOffering.Detail, String> details) {
this.details = details;
}
}
4 changes: 4 additions & 0 deletions api/src/com/cloud/network/Networks.java
Expand Up @@ -75,6 +75,10 @@ public <T> URI toUri(T value) {
throw new CloudRuntimeException("Unable to convert to broadcast URI: " + value);
}
}
@Override
public String getValueFrom(URI uri) {
return uri.getAuthority();
}
},
Vswitch("vs", String.class), LinkLocal(null, null), Vnet("vnet", Long.class), Storage("storage", Integer.class), Lswitch("lswitch", String.class) {
@Override
Expand Down
2 changes: 1 addition & 1 deletion api/src/com/cloud/offering/NetworkOffering.java
Expand Up @@ -38,7 +38,7 @@ public enum State {
}

public enum Detail {
InternalLbProvider, PublicLbProvider, servicepackageuuid, servicepackagedescription
InternalLbProvider, PublicLbProvider, servicepackageuuid, servicepackagedescription, PromiscuousMode, MacAddressChanges, ForgedTransmits
}

public final static String SystemPublicNetwork = "System-Public-Network";
Expand Down
1 change: 1 addition & 0 deletions api/src/org/apache/cloudstack/api/ApiConstants.java
Expand Up @@ -38,6 +38,7 @@ public class ApiConstants {
public static final String BIND_PASSWORD = "bindpass";
public static final String BYTES_READ_RATE = "bytesreadrate";
public static final String BYTES_WRITE_RATE = "byteswriterate";
public static final String BYPASS_VLAN_OVERLAP_CHECK = "bypassvlanoverlapcheck";
public static final String CATEGORY = "category";
public static final String CAN_REVERT = "canrevert";
public static final String CA_CERTIFICATES = "cacertificates";
Expand Down
Expand Up @@ -40,6 +40,9 @@ public class CreateNetworkCmdByAdmin extends CreateNetworkCmd {
@Parameter(name=ApiConstants.VLAN, type=CommandType.STRING, description="the ID or VID of the network")
private String vlan;

@Parameter(name=ApiConstants.BYPASS_VLAN_OVERLAP_CHECK, type=CommandType.BOOLEAN, description="when true bypasses VLAN id/range overlap check during network creation for shared networks")
private Boolean bypassVlanOverlapCheck;

/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
Expand All @@ -48,6 +51,13 @@ public String getVlan() {
return vlan;
}

public Boolean getBypassVlanOverlapCheck() {
if (bypassVlanOverlapCheck != null) {
return bypassVlanOverlapCheck;
}
return false;
}

/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
Expand Down
Expand Up @@ -113,7 +113,8 @@ public class CreateNetworkOfferingCmd extends BaseCmd {
private Boolean isPersistent;

@Parameter(name = ApiConstants.DETAILS, type = CommandType.MAP, since = "4.2.0", description = "Network offering details in key/value pairs."
+ " Supported keys are internallbprovider/publiclbprovider with service provider as a value")
+ " Supported keys are internallbprovider/publiclbprovider with service provider as a value, and"
+ " promiscuousmode/macaddresschanges/forgedtransmits with true/false as value to accept/reject the security settings if available for a nic/portgroup")
protected Map details;

@Parameter(name = ApiConstants.EGRESS_DEFAULT_POLICY,
Expand Down
19 changes: 13 additions & 6 deletions api/test/com/cloud/network/NetworksTest.java
Expand Up @@ -16,16 +16,16 @@
// under the License.
package com.cloud.network;

import java.net.URISyntaxException;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import com.cloud.dc.Vlan;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.IsolationType;
import com.cloud.utils.exception.CloudRuntimeException;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.net.URI;
import java.net.URISyntaxException;

/**
* @author dhoogland
Expand All @@ -43,6 +43,13 @@ public void emptyBroadcastDomainTypeTest() throws URISyntaxException {
Assert.assertEquals("an empty uri should mean a broadcasttype of undecided", BroadcastDomainType.UnDecided, type);
}

@Test
public void vlanCommaSeparatedTest() throws URISyntaxException {
Assert.assertEquals(BroadcastDomainType.getValue(new URI("vlan://100")), "100");
Assert.assertEquals(BroadcastDomainType.getValue(new URI("vlan://100-200")), "100-200");
Assert.assertEquals(BroadcastDomainType.getValue(new URI("vlan://10-50,12,11,112-170")), "10-50,12,11,112-170");
}

@Test
public void vlanBroadcastDomainTypeTest() throws URISyntaxException {
String uri1 = "vlan://1";
Expand Down
Expand Up @@ -77,6 +77,15 @@ public interface NetworkOrchestrationService {
ConfigKey<Integer> NetworkThrottlingRate = new ConfigKey<Integer>("Network", Integer.class, NetworkThrottlingRateCK, "200",
"Default data transfer rate in megabits per second allowed in network.", true, ConfigKey.Scope.Zone);

ConfigKey<Boolean> PromiscuousMode = new ConfigKey<Boolean>("Advanced", Boolean.class, "network.promiscuous.mode", "false",
"Whether to allow or deny promiscuous mode on nics for applicable network elements such as for vswitch/dvswitch portgroups.", true);

ConfigKey<Boolean> MacAddressChanges = new ConfigKey<Boolean>("Advanced", Boolean.class, "network.mac.address.changes", "true",
"Whether to allow or deny mac address changes on nics for applicable network elements such as for vswitch/dvswitch porgroups.", true);

ConfigKey<Boolean> ForgedTransmits = new ConfigKey<Boolean>("Advanced", Boolean.class, "network.forged.transmits", "true",
"Whether to allow or deny forged transmits on nics for applicable network elements such as for vswitch/dvswitch portgroups.", true);

List<? extends Network> setupNetwork(Account owner, NetworkOffering offering, DeploymentPlan plan, String name, String displayText, boolean isDefault)
throws ConcurrentOperationException;

Expand Down Expand Up @@ -136,9 +145,9 @@ void prepare(VirtualMachineProfile profile, DeployDestination dest, ReservationC

boolean destroyNetwork(long networkId, ReservationContext context, boolean forced);

Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway, String cidr, String vlanId, String networkDomain, Account owner,
Long domainId, PhysicalNetwork physicalNetwork, long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, String ip6Gateway, String ip6Cidr,
Boolean displayNetworkEnabled, String isolatedPvlan) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException;
Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway, String cidr, String vlanId, boolean bypassVlanOverlapCheck, String networkDomain, Account owner,
Long domainId, PhysicalNetwork physicalNetwork, long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, String ip6Gateway, String ip6Cidr,
Boolean displayNetworkEnabled, String isolatedPvlan) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException;

UserDataServiceProvider getPasswordResetProvider(Network network);

Expand Down
Expand Up @@ -214,7 +214,7 @@ NetworkOfferingVO createNetworkOffering(String name, String displayText, Traffic
Map<NetworkOffering.Detail, String> details, boolean egressDefaultPolicy, Integer maxconn, boolean enableKeepAlive);

Vlan createVlanAndPublicIpRange(long zoneId, long networkId, long physicalNetworkId, boolean forVirtualNetwork, Long podId, String startIP, String endIP,
String vlanGateway, String vlanNetmask, String vlanId, Domain domain, Account vlanOwner, String startIPv6, String endIPv6, String vlanIp6Gateway, String vlanIp6Cidr)
String vlanGateway, String vlanNetmask, String vlanId, boolean bypassVlanOverlapCheck, Domain domain, Account vlanOwner, String startIPv6, String endIPv6, String vlanIp6Gateway, String vlanIp6Cidr)
throws InsufficientCapacityException, ConcurrentOperationException, InvalidParameterValueException;

void createDefaultSystemNetworks(long zoneId) throws ConcurrentOperationException;
Expand Down
Expand Up @@ -32,18 +32,10 @@
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import javax.inject.Inject;
import javax.naming.ConfigurationException;

import com.cloud.network.dao.NetworkDetailsDao;
import com.cloud.network.dao.RemoteAccessVpnDao;
import com.cloud.network.dao.RemoteAccessVpnVO;
import com.cloud.network.dao.VpnUserDao;
import com.cloud.network.element.RedundantResource;
import com.cloud.network.router.VirtualRouter;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.dao.DomainRouterDao;
import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.cloud.entity.api.db.VMNetworkMapVO;
Expand All @@ -58,6 +50,8 @@
import org.apache.cloudstack.framework.messagebus.PublishScope;
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.cloudstack.region.PortableIpDao;
import org.apache.log4j.Logger;

import com.cloud.agent.AgentManager;
import com.cloud.agent.Listener;
import com.cloud.agent.api.AgentControlAnswer;
Expand Down Expand Up @@ -129,6 +123,7 @@
import com.cloud.network.dao.NetworkAccountDao;
import com.cloud.network.dao.NetworkAccountVO;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkDetailsDao;
import com.cloud.network.dao.NetworkDomainDao;
import com.cloud.network.dao.NetworkDomainVO;
import com.cloud.network.dao.NetworkServiceMapDao;
Expand All @@ -139,17 +134,22 @@
import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao;
import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO;
import com.cloud.network.dao.PhysicalNetworkVO;
import com.cloud.network.dao.RemoteAccessVpnDao;
import com.cloud.network.dao.RemoteAccessVpnVO;
import com.cloud.network.dao.VpnUserDao;
import com.cloud.network.element.AggregatedCommandExecutor;
import com.cloud.network.element.DhcpServiceProvider;
import com.cloud.network.element.DnsServiceProvider;
import com.cloud.network.element.IpDeployer;
import com.cloud.network.element.LoadBalancingServiceProvider;
import com.cloud.network.element.NetworkElement;
import com.cloud.network.element.RedundantResource;
import com.cloud.network.element.StaticNatServiceProvider;
import com.cloud.network.element.UserDataServiceProvider;
import com.cloud.network.guru.NetworkGuru;
import com.cloud.network.guru.NetworkGuruAdditionalFunctions;
import com.cloud.network.lb.LoadBalancingRulesManager;
import com.cloud.network.router.VirtualRouter;
import com.cloud.network.rules.FirewallManager;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.FirewallRule.Purpose;
Expand Down Expand Up @@ -197,6 +197,7 @@
import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.utils.fsm.StateMachine2;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.Nic;
import com.cloud.vm.Nic.ReservationStrategy;
import com.cloud.vm.NicIpAlias;
Expand All @@ -209,6 +210,7 @@
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.Type;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.NicIpAliasDao;
import com.cloud.vm.dao.NicIpAliasVO;
Expand Down Expand Up @@ -2017,9 +2019,9 @@ public void expungeNics(final VirtualMachineProfile vm) {
@Override
@DB
public Network createGuestNetwork(final long networkOfferingId, final String name, final String displayText, final String gateway, final String cidr, String vlanId,
String networkDomain, final Account owner, final Long domainId, final PhysicalNetwork pNtwk, final long zoneId, final ACLType aclType, Boolean subdomainAccess,
final Long vpcId, final String ip6Gateway, final String ip6Cidr, final Boolean isDisplayNetworkEnabled, final String isolatedPvlan)
throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException {
boolean bypassVlanOverlapCheck, String networkDomain, final Account owner, final Long domainId, final PhysicalNetwork pNtwk,
final long zoneId, final ACLType aclType, Boolean subdomainAccess, final Long vpcId, final String ip6Gateway, final String ip6Cidr,
final Boolean isDisplayNetworkEnabled, final String isolatedPvlan) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException {

final NetworkOfferingVO ntwkOff = _networkOfferingDao.findById(networkOfferingId);
// this method supports only guest network creation
Expand Down Expand Up @@ -2136,19 +2138,19 @@ public Network createGuestNetwork(final long networkOfferingId, final String nam
}

if (vlanSpecified) {
URI uri = BroadcastDomainType.fromString(vlanId);
//don't allow to specify vlan tag used by physical network for dynamic vlan allocation
if (_dcDao.findVnet(zoneId, pNtwk.getId(), vlanId).size() > 0) {
if (!(bypassVlanOverlapCheck && ntwkOff.getGuestType() == GuestType.Shared) && _dcDao.findVnet(zoneId, pNtwk.getId(), BroadcastDomainType.getValue(uri)).size() > 0) {
throw new InvalidParameterValueException("The VLAN tag " + vlanId + " is already being used for dynamic vlan allocation for the guest network in zone "
+ zone.getName());
}
if (! UuidUtils.validateUUID(vlanId)){
final String uri = BroadcastDomainType.fromString(vlanId).toString();
// For Isolated networks, don't allow to create network with vlan that already exists in the zone
if (ntwkOff.getGuestType() == GuestType.Isolated) {
if (_networksDao.countByZoneAndUri(zoneId, uri) > 0) {
throw new InvalidParameterValueException("Network with vlan " + vlanId + " already exists in zone " + zoneId);
if (_networksDao.listByZoneAndUriAndGuestType(zoneId, uri.toString(), null).size() > 0) {
throw new InvalidParameterValueException("Network with vlan " + vlanId + " already exists or overlaps with other network vlans in zone " + zoneId);
} else {
final List<DataCenterVnetVO> dcVnets = _datacenterVnetDao.findVnet(zoneId, vlanId.toString());
final List<DataCenterVnetVO> dcVnets = _datacenterVnetDao.findVnet(zoneId, BroadcastDomainType.getValue(uri));
//for the network that is created as part of private gateway,
//the vnet is not coming from the data center vnet table, so the list can be empty
if (!dcVnets.isEmpty()) {
Expand Down Expand Up @@ -2177,8 +2179,8 @@ public Network createGuestNetwork(final long networkOfferingId, final String nam
} else {
// don't allow to creating shared network with given Vlan ID, if there already exists a isolated network or
// shared network with same Vlan ID in the zone
if (_networksDao.countByZoneUriAndGuestType(zoneId, uri, GuestType.Isolated) > 0 ) {
throw new InvalidParameterValueException("There is a isolated/shared network with vlan id: " + vlanId + " already exists " + "in zone " + zoneId);
if (!bypassVlanOverlapCheck && _networksDao.listByZoneAndUriAndGuestType(zoneId, uri.toString(), GuestType.Isolated).size() > 0 ) {
throw new InvalidParameterValueException("There is an existing isolated/shared network that overlaps with vlan id:" + vlanId + " in zone " + zoneId);
}
}
}
Expand Down Expand Up @@ -3663,6 +3665,8 @@ public String getConfigComponentName() {

@Override
public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey<?>[] {NetworkGcWait, NetworkGcInterval, NetworkLockTimeout, GuestDomainSuffix, NetworkThrottlingRate, MinVRVersion};
return new ConfigKey<?>[] {NetworkGcWait, NetworkGcInterval, NetworkLockTimeout,
GuestDomainSuffix, NetworkThrottlingRate, MinVRVersion,
PromiscuousMode, MacAddressChanges, ForgedTransmits};
}
}
4 changes: 2 additions & 2 deletions engine/schema/src/com/cloud/dc/dao/DataCenterVnetDao.java
Expand Up @@ -27,10 +27,10 @@ public interface DataCenterVnetDao extends GenericDao<DataCenterVnetVO, Long> {

public List<DataCenterVnetVO> listAllocatedVnetsInRange(long dcId, long physicalNetworkId, Integer start, Integer end);

public List<DataCenterVnetVO> findVnet(long dcId, String vnet);

public int countZoneVlans(long dcId, boolean onlyCountAllocated);

public List<DataCenterVnetVO> findVnet(long dcId, String vnet);

public List<DataCenterVnetVO> findVnet(long dcId, long physicalNetworkId, String vnet);

public void add(long dcId, long physicalNetworkId, List<String> vnets);
Expand Down

0 comments on commit 41fdb88

Please sign in to comment.