VPC: multiple fixes:

* Separate service for NetworkACL - "NetworkACL" service
* allow having just one network supporting LB in the VPC
* perform check against VPC when upgrade network to the new network offering (the same set of checks when you add new network to the VPC)
This commit is contained in:
Alena Prokharchyk 2012-07-02 14:13:08 -07:00
parent 183633cf70
commit 40a3482f13
15 changed files with 145 additions and 83 deletions

View File

@ -117,7 +117,8 @@ public class UpdateNetworkCmd extends BaseAsyncCmd {
public void execute() throws InsufficientCapacityException, ConcurrentOperationException{
User callerUser = _accountService.getActiveUser(UserContext.current().getCallerUserId());
Account callerAccount = _accountService.getActiveAccountById(callerUser.getAccountId());
Network result = _networkService.updateGuestNetwork(getId(), getNetworkName(), getDisplayText(), callerAccount, callerUser, getNetworkDomain(), getNetworkOfferingId(), getChangeCidr());
Network result = _networkService.updateGuestNetwork(getId(), getNetworkName(), getDisplayText(), callerAccount,
callerUser, getNetworkDomain(), getNetworkOfferingId(), getChangeCidr());
if (result != null) {
NetworkResponse response = _responseGenerator.createNetworkResponse(result);
response.setResponseName(getCommandName());

View File

@ -46,7 +46,7 @@ public interface Network extends ControlledEntity {
public static final Service Dns = new Service("Dns", Capability.AllowDnsSuffixModification);
public static final Service Gateway = new Service("Gateway");
public static final Service Firewall = new Service("Firewall", Capability.SupportedProtocols,
Capability.MultipleIps, Capability.TrafficStatistics, Capability.FirewallType);
Capability.MultipleIps, Capability.TrafficStatistics);
public static final Service Lb = new Service("Lb", Capability.SupportedLBAlgorithms, Capability.SupportedLBIsolation,
Capability.SupportedProtocols, Capability.TrafficStatistics, Capability.LoadBalancingSupportedIps,
Capability.SupportedStickinessMethods, Capability.ElasticLb);
@ -55,6 +55,7 @@ public interface Network extends ControlledEntity {
public static final Service StaticNat = new Service("StaticNat", Capability.ElasticIp);
public static final Service PortForwarding = new Service("PortForwarding");
public static final Service SecurityGroup = new Service("SecurityGroup");
public static final Service NetworkACL = new Service("NetworkACL", Capability.SupportedProtocols);
private String name;
private Capability[] caps;
@ -164,7 +165,6 @@ public interface Network extends ControlledEntity {
public static final Capability RedundantRouter = new Capability("RedundantRouter");
public static final Capability ElasticIp = new Capability("ElasticIp");
public static final Capability ElasticLb = new Capability("ElasticLb");
public static final Capability FirewallType = new Capability("FirewallType");
private String name;

View File

@ -266,7 +266,6 @@ public class JuniperSRXExternalFirewallElement extends ExternalFirewallDeviceMan
firewallCapabilities.put(Capability.SupportedProtocols, "tcp,udp");
firewallCapabilities.put(Capability.MultipleIps, "true");
firewallCapabilities.put(Capability.TrafficStatistics, "per public ip");
firewallCapabilities.put(Capability.FirewallType, "perpublicip");
capabilities.put(Service.Firewall, firewallCapabilities);
// Disabling VPN for Juniper in Acton as it 1) Was never tested 2) probably just doesn't work

View File

@ -279,7 +279,6 @@ public class NetscalerElement extends ExternalLoadBalancerDeviceManagerImpl impl
firewallCapabilities.put(Capability.TrafficStatistics, "per public ip");
firewallCapabilities.put(Capability.SupportedProtocols, "tcp,udp,icmp");
firewallCapabilities.put(Capability.MultipleIps, "true");
firewallCapabilities.put(Capability.FirewallType, "perpublicip");
capabilities.put(Service.Firewall, firewallCapabilities);
return capabilities;

View File

@ -1388,6 +1388,22 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
defaultIsolatedSourceNatEnabledNetworkOfferingProviders.put(Service.StaticNat, defaultProviders);
defaultIsolatedSourceNatEnabledNetworkOfferingProviders.put(Service.PortForwarding, defaultProviders);
defaultIsolatedSourceNatEnabledNetworkOfferingProviders.put(Service.Vpn, defaultProviders);
Map<Network.Service, Set<Network.Provider>> defaultVPCOffProviders =
new HashMap<Network.Service, Set<Network.Provider>>();
defaultProviders.clear();
defaultProviders.add(Network.Provider.VirtualRouter);
defaultVPCOffProviders.put(Service.Dhcp, defaultProviders);
defaultVPCOffProviders.put(Service.Dns, defaultProviders);
defaultVPCOffProviders.put(Service.UserData, defaultProviders);
defaultVPCOffProviders.put(Service.NetworkACL, defaultProviders);
defaultVPCOffProviders.put(Service.Gateway, defaultProviders);
defaultVPCOffProviders.put(Service.Lb, defaultProviders);
defaultVPCOffProviders.put(Service.SourceNat, defaultProviders);
defaultVPCOffProviders.put(Service.StaticNat, defaultProviders);
defaultVPCOffProviders.put(Service.PortForwarding, defaultProviders);
defaultVPCOffProviders.put(Service.Vpn, defaultProviders);
Transaction txn = Transaction.currentTxn();
txn.start();
@ -1434,7 +1450,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworks) == null) {
offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworks,
"Offering for Isolated VPC networks with Source Nat service enabled", TrafficType.Guest,
null, false, Availability.Required, null, defaultIsolatedSourceNatEnabledNetworkOfferingProviders,
null, false, Availability.Required, null, defaultVPCOffProviders,
true, Network.GuestType.Isolated, false, null, false, null, false);
offering.setState(NetworkOffering.State.Enabled);
_networkOfferingDao.update(offering.getId(), offering);
@ -2828,12 +2844,11 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException {
Vpc vpc = _vpcMgr.getActiveVpc(vpcId);
//1) Validate if network can be created for VPC
_vpcMgr.validateGuestNtkwForVpc(_configMgr.getNetworkOffering(ntwkOffId), cidr, networkDomain, owner, vpc);
if (networkDomain == null) {
networkDomain = vpc.getNetworkDomain();
}
//1) Validate if network can be created for VPC
_vpcMgr.validateGuestNtkwForVpc(_configMgr.getNetworkOffering(ntwkOffId), cidr, networkDomain, owner, vpc, null);
//2) Create network
Network guestNetwork = createGuestNetwork(ntwkOffId, name, displayText, gateway, cidr, vlanId,
@ -4560,7 +4575,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
@Override
@DB
@ActionEvent(eventType = EventTypes.EVENT_NETWORK_UPDATE, eventDescription = "updating network", async = true)
public Network updateGuestNetwork(long networkId, String name, String displayText, Account callerAccount, User callerUser, String domainSuffix, Long networkOfferingId, Boolean changeCidr) {
public Network updateGuestNetwork(long networkId, String name, String displayText, Account callerAccount,
User callerUser, String domainSuffix, Long networkOfferingId, Boolean changeCidr) {
boolean restartNetwork = false;
// verify input parameters
@ -4587,7 +4603,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
if (network.getTrafficType() != Networks.TrafficType.Guest) {
throw new InvalidParameterValueException("Can't allow networks which traffic type is not " + TrafficType.Guest);
}
_accountMgr.checkAccess(callerAccount, null, true, network);
if (name != null) {
@ -4614,13 +4630,19 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
ex.addProxyObject(networkOffering, networkOfferingId, "networkOfferingId");
throw ex;
}
// network offering should be in Enabled state
if (networkOffering.getState() != NetworkOffering.State.Enabled) {
InvalidParameterValueException ex = new InvalidParameterValueException("Network offering with specified id is not in " + NetworkOffering.State.Enabled + " state, can't upgrade to it");
ex.addProxyObject(networkOffering, networkOfferingId, "networkOfferingId");
throw ex;
}
//perform below validation if the network is vpc network
if (network.getVpcId() != null) {
Vpc vpc = _vpcMgr.getVpc(network.getVpcId());
_vpcMgr.validateGuestNtkwForVpc(networkOffering, null, null, null,vpc, networkId);
}
if (networkOfferingId != oldNetworkOfferingId) {
if (networkOfferingIsConfiguredForExternalNetworking(networkOfferingId) != networkOfferingIsConfiguredForExternalNetworking(oldNetworkOfferingId)

View File

@ -559,7 +559,6 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
firewallCapabilities.put(Capability.TrafficStatistics, "per public ip");
firewallCapabilities.put(Capability.SupportedProtocols, "tcp,udp,icmp");
firewallCapabilities.put(Capability.MultipleIps, "true");
firewallCapabilities.put(Capability.FirewallType, "perpublicip");
capabilities.put(Service.Firewall, firewallCapabilities);
// Set capabilities for vpn

View File

@ -306,10 +306,14 @@ public class VpcVirtualRouterElement extends VirtualRouterElement implements Vpc
vpnCapabilities.put(Capability.VpnTypes, "s2svpn");
capabilities.put(Service.Vpn, vpnCapabilities);
Map<Capability, String> firewallCapabilities = capabilities.get(Service.Firewall);
firewallCapabilities.put(Capability.FirewallType, "networkacl");
capabilities.put(Service.Firewall, firewallCapabilities);
//remove firewall capability
capabilities.remove(Service.Firewall);
//add network ACL capability
Map<Capability, String> networkACLCapabilities = new HashMap<Capability, String>();
networkACLCapabilities.put(Capability.SupportedProtocols, "tcp,udp,icmp");
capabilities.put(Service.NetworkACL, networkACLCapabilities);
return capabilities;
}

View File

@ -370,15 +370,6 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
if (!_elbEnabled) {
caps = _networkMgr.getNetworkServiceCapabilities(network.getId(), Service.Lb);
}
} else if (purpose == Purpose.Firewall) {
caps = _networkMgr.getNetworkServiceCapabilities(network.getId(), Service.Firewall);
if (caps != null) {
String firewallType = caps.get(Capability.FirewallType);
//regular firewall rules are not supported in networks supporting network ACLs
if (firewallType.equalsIgnoreCase("networkacl")) {
throw new UnsupportedOperationException("Firewall rules are not supported in network " + network);
}
}
} else if (purpose == Purpose.PortForwarding) {
caps = _networkMgr.getNetworkServiceCapabilities(network.getId(), Service.PortForwarding);
}

View File

@ -30,7 +30,6 @@ import com.cloud.utils.db.Transaction;
public class VpcOfferingDaoImpl extends GenericDaoBase<VpcOfferingVO, Long> implements VpcOfferingDao{
final SearchBuilder<VpcOfferingVO> AllFieldsSearch;
protected VpcOfferingDaoImpl() {
super();

View File

@ -33,5 +33,7 @@ public interface VpcOfferingServiceMapDao extends GenericDao<VpcOfferingServiceM
boolean areServicesSupportedByNetworkOffering(long networkOfferingId, Service[] services);
List<String> listServicesForVpcOffering(long vpcOfferingId);
VpcOfferingServiceMapVO findByServiceProviderAndOfferingId(String service, String provider, long vpcOfferingId);
}

View File

@ -101,4 +101,15 @@ public class VpcOfferingServiceMapDaoImpl extends GenericDaoBase<VpcOfferingServ
sc.setParameters("offeringId", offId);
return customSearch(sc, null);
}
@Override
public VpcOfferingServiceMapVO findByServiceProviderAndOfferingId(String service, String provider, long vpcOfferingId) {
SearchCriteria<VpcOfferingServiceMapVO> sc = AllFieldsSearch.create();
sc.setParameters("vpcOffId", vpcOfferingId);
sc.setParameters("service", service);
sc.setParameters("provider", provider);
return findOneBy(sc);
}
}

View File

@ -138,8 +138,8 @@ public class NetworkACLManagerImpl implements Manager,NetworkACLManager{
_accountMgr.checkAccess(caller, AccessType.UseNetwork, false, network);
if (!_networkMgr.areServicesSupportedInNetwork(networkId, Service.Firewall)) {
throw new InvalidParameterValueException("Service " + Service.Firewall + " is not supported in network " + network);
if (!_networkMgr.areServicesSupportedInNetwork(networkId, Service.NetworkACL)) {
throw new InvalidParameterValueException("Service " + Service.NetworkACL + " is not supported in network " + network);
}
// icmp code and icmp type can't be passed in for any other protocol rather than icmp
@ -153,7 +153,6 @@ public class NetworkACLManagerImpl implements Manager,NetworkACLManager{
validateNetworkACL(caller, network, portStart, portEnd, protocol);
Transaction txn = Transaction.currentTxn();
txn.start();
@ -198,7 +197,7 @@ public class NetworkACLManagerImpl implements Manager,NetworkACLManager{
}
// Verify that the network guru supports the protocol specified
Map<Network.Capability, String> caps = _networkMgr.getNetworkServiceCapabilities(network.getId(), Service.Firewall);
Map<Network.Capability, String> caps = _networkMgr.getNetworkServiceCapabilities(network.getId(), Service.NetworkACL);
if (caps != null) {
@ -206,11 +205,6 @@ public class NetworkACLManagerImpl implements Manager,NetworkACLManager{
if (!supportedProtocols.contains(proto.toLowerCase())) {
throw new InvalidParameterValueException("Protocol " + proto + " is not supported by the network " + network);
}
String firewallType = caps.get(Capability.FirewallType);
if (!firewallType.equalsIgnoreCase("networkacl")) {
throw new UnsupportedOperationException("Network ACLS are not supported in network " + network);
}
} else {
throw new InvalidParameterValueException("No capabilities are found for network " + network);
}

View File

@ -70,11 +70,11 @@ public interface VpcManager extends VpcService{
* @param networkDomain
* @param networkOwner
* @param vpc TODO
* @param networkId TODO
* @return
* @throws ConcurrentOperationException
*/
void validateGuestNtkwForVpc(NetworkOffering guestNtwkOff, String cidr, String networkDomain, Account networkOwner,
Vpc vpc) throws ConcurrentOperationException;
Vpc vpc, Long networkId);
/**
* @return

View File

@ -65,6 +65,7 @@ import com.cloud.network.vpc.Dao.VpcGatewayDao;
import com.cloud.network.vpc.Dao.VpcOfferingDao;
import com.cloud.network.vpc.Dao.VpcOfferingServiceMapDao;
import com.cloud.offering.NetworkOffering;
import com.cloud.offerings.NetworkOfferingServiceMapVO;
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
import com.cloud.org.Grouping;
import com.cloud.projects.Project.ListProjectResourcesCriteria;
@ -129,6 +130,8 @@ public class VpcManagerImpl implements VpcManager, Manager{
StaticRouteDao _staticRouteDao;
@Inject
NetworkOfferingServiceMapDao _ntwkOffServiceDao ;
@Inject
VpcOfferingServiceMapDao _vpcOffServiceDao;
private final ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("VpcChecker"));
@ -150,10 +153,17 @@ public class VpcManagerImpl implements VpcManager, Manager{
s_logger.debug("Creating default VPC offering " + VpcOffering.defaultVPCOfferingName);
Map<Service, Set<Provider>> svcProviderMap = new HashMap<Service, Set<Provider>>();
Set<Provider> provider = new HashSet<Provider>();
provider.add(Provider.VPCVirtualRouter);
Set<Provider> defaultProviders = new HashSet<Provider>();
defaultProviders.add(Provider.VPCVirtualRouter);
for (Service svc : getSupportedServices()) {
svcProviderMap.put(svc, provider);
if (svc == Service.Lb) {
Set<Provider> lbProviders = new HashSet<Provider>();
lbProviders.add(Provider.VPCVirtualRouter);
lbProviders.add(Provider.Netscaler);
svcProviderMap.put(svc, lbProviders);
} else {
svcProviderMap.put(svc, defaultProviders);
}
}
createVpcOffering(VpcOffering.defaultVPCOfferingName, VpcOffering.defaultVPCOfferingName, svcProviderMap,
true, State.Enabled);
@ -218,6 +228,13 @@ public class VpcManagerImpl implements VpcManager, Manager{
throw new UnsupportedServiceException("Service " + Service.SecurityGroup.getName() + " is not supported by VPC");
}
svcProviderMap.put(service, defaultProviders);
if (service == Service.NetworkACL) {
firewallSvs = true;
}
if (service == Service.SourceNat) {
sourceNatSvc = true;
}
}
if (!sourceNatSvc) {
@ -226,8 +243,8 @@ public class VpcManagerImpl implements VpcManager, Manager{
}
if (!firewallSvs) {
s_logger.debug("Automatically adding firewall service to the list of VPC services");
svcProviderMap.put(Service.Firewall, defaultProviders);
s_logger.debug("Automatically adding network ACL service to the list of VPC services");
svcProviderMap.put(Service.NetworkACL, defaultProviders);
}
svcProviderMap.put(Service.Gateway, defaultProviders);
@ -716,7 +733,7 @@ public class VpcManagerImpl implements VpcManager, Manager{
services.add(Network.Service.Dhcp);
services.add(Network.Service.Dns);
services.add(Network.Service.UserData);
services.add(Network.Service.Firewall);
services.add(Network.Service.NetworkACL);
services.add(Network.Service.PortForwarding);
services.add(Network.Service.Lb);
services.add(Network.Service.SourceNat);
@ -814,11 +831,66 @@ public class VpcManagerImpl implements VpcManager, Manager{
@Override
@DB
public void validateGuestNtkwForVpc(NetworkOffering guestNtwkOff, String cidr, String networkDomain,
Account networkOwner, Vpc vpc) throws ConcurrentOperationException {
Account networkOwner, Vpc vpc, Long networkId) {
if (networkId == null) {
//1) Validate attributes that has to be passed in when create new guest network
validateNewVpcGuestNetwork(cidr, networkOwner, vpc, networkDomain);
}
//2) Only Isolated networks with Source nat service enabled can be added to vpc
if (!(guestNtwkOff.getGuestType() == GuestType.Isolated
&& _ntwkMgr.areServicesSupportedByNetworkOffering(guestNtwkOff.getId(), Service.SourceNat))) {
throw new InvalidParameterValueException("Only networks of type " + GuestType.Isolated + " with service "
+ Service.SourceNat +
" can be added as a part of VPC");
}
//3) No redundant router support
if (guestNtwkOff.getRedundantRouter()) {
throw new InvalidParameterValueException("No redunant router support when network belnogs to VPC");
}
//4) Conserve mode should be off
if (guestNtwkOff.isConserveMode()) {
throw new InvalidParameterValueException("Only networks with conserve mode Off can belong to VPC");
}
//5) Check services/providers against VPC providers
List<NetworkOfferingServiceMapVO> networkProviders = _ntwkOffServiceDao.listByNetworkOfferingId(guestNtwkOff.getId());
for (NetworkOfferingServiceMapVO nSvcVO : networkProviders) {
String pr = nSvcVO.getProvider();
String service = nSvcVO.getService();
if (_vpcOffServiceDao.findByServiceProviderAndOfferingId(service, pr, vpc.getVpcOfferingId()) == null) {
throw new InvalidParameterValueException("Service/provider combination " + service + "/" +
pr + " is not supported by VPC " + vpc);
}
}
//6) Only one network in the VPC can support LB
if (_ntwkMgr.areServicesSupportedByNetworkOffering(guestNtwkOff.getId(), Service.Lb)) {
List<? extends Network> networks = getVpcNetworks(vpc.getId());
for (Network network : networks) {
if (networkId != null && network.getId() == networkId.longValue()) {
//skip my own network
continue;
} else {
if (_ntwkMgr.areServicesSupportedInNetwork(network.getId(), Service.Lb)) {
throw new InvalidParameterValueException("LB service is already supported " +
"by network " + network + " in VPC " + vpc);
}
}
}
}
}
protected void validateNewVpcGuestNetwork(String cidr, Account networkOwner, Vpc vpc, String networkDomain) {
Vpc locked = _vpcDao.acquireInLockTable(vpc.getId());
if (locked == null) {
throw new ConcurrentOperationException("Unable to acquire lock on " + vpc);
throw new CloudRuntimeException("Unable to acquire lock on " + vpc);
}
try {
@ -847,45 +919,14 @@ public class VpcManagerImpl implements VpcManager, Manager{
//4) vpc and network should belong to the same owner
if (vpc.getAccountId() != networkOwner.getId()) {
throw new InvalidParameterValueException("Vpc " + vpc + " owner is different from the network owner "
+ networkOwner);
+ networkOwner);
}
//5) Only Isolated networks with Source nat service enabled can be added to vpc
if (!(guestNtwkOff.getGuestType() == GuestType.Isolated
&& _ntwkMgr.areServicesSupportedByNetworkOffering(guestNtwkOff.getId(), Service.SourceNat))) {
throw new InvalidParameterValueException("Only networks of type " + GuestType.Isolated + " with service "
+ Service.SourceNat +
" can be added as a part of VPC");
//5) network domain should be the same as VPC's
if (!networkDomain.equalsIgnoreCase(vpc.getNetworkDomain())) {
throw new InvalidParameterValueException("Network domain of the new network should match network" +
" domain of vpc " + vpc);
}
//6) Only VPC VR can be a provider for the network offering
List<Provider> ntwkOffProviders = _ntwkMgr.getNtwkOffDistinctProviders(guestNtwkOff.getId());
for (Provider provider : ntwkOffProviders) {
if (provider != Provider.VPCVirtualRouter) {
throw new InvalidParameterValueException("Only VPCVirtualRouter provider is supported in VPC network;" +
" while network offering " + guestNtwkOff + " has " + provider.getName() + " enabled.");
}
}
//7) No redundant router support
if (guestNtwkOff.getRedundantRouter()) {
throw new InvalidParameterValueException("No redunant router support when network belnogs to VPC");
}
//8) Conserve mode should be off
if (guestNtwkOff.isConserveMode()) {
throw new InvalidParameterValueException("Only networks with conserve mode Off can belong to VPC");
}
//9) list supported services should be within VPC supported services
List<String> ntwkOffServices = _ntwkOffServiceDao.listServicesForNetworkOffering(guestNtwkOff.getId());
List<String> vpcOffServices = _vpcOffSvcMapDao.listServicesForVpcOffering(vpc.getVpcOfferingId());
if (!vpcOffServices.containsAll(ntwkOffServices)) {
throw new InvalidParameterValueException("VPC doesn't support some of the services specified in the network offering");
}
} finally {
s_logger.debug("Releasing lock for " + locked);
_vpcDao.releaseFromLockTable(locked.getId());

View File

@ -1026,7 +1026,7 @@ public class ConfigurationServerImpl implements ConfigurationServer {
defaultVpcNetworkOfferingProviders.put(Service.Dhcp, Provider.VPCVirtualRouter);
defaultVpcNetworkOfferingProviders.put(Service.Dns, Provider.VPCVirtualRouter);
defaultVpcNetworkOfferingProviders.put(Service.UserData, Provider.VPCVirtualRouter);
defaultVpcNetworkOfferingProviders.put(Service.Firewall, Provider.VPCVirtualRouter);
defaultVpcNetworkOfferingProviders.put(Service.NetworkACL, Provider.VPCVirtualRouter);
defaultVpcNetworkOfferingProviders.put(Service.Gateway, Provider.VPCVirtualRouter);
defaultVpcNetworkOfferingProviders.put(Service.Lb, Provider.VPCVirtualRouter);
defaultVpcNetworkOfferingProviders.put(Service.SourceNat, Provider.VPCVirtualRouter);