mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	Conflicts: server/src/com/cloud/network/NetworkManagerImpl.java server/src/com/cloud/network/vpc/VpcManagerImpl.java
		
			
				
	
	
		
			1585 lines
		
	
	
		
			66 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			1585 lines
		
	
	
		
			66 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| // Copyright 2012 Citrix Systems, Inc. Licensed under the
 | |
| // Apache License, Version 2.0 (the "License"); you may not use this
 | |
| // file except in compliance with the License.  Citrix Systems, Inc.
 | |
| // reserves all rights not expressly granted by 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.
 | |
| // 
 | |
| // Automatically generated by addcopyright.py at 04/03/2012
 | |
| package com.cloud.network.vpc;
 | |
| 
 | |
| import java.util.ArrayList;
 | |
| import java.util.HashMap;
 | |
| import java.util.HashSet;
 | |
| import java.util.List;
 | |
| import java.util.Map;
 | |
| import java.util.Set;
 | |
| import java.util.concurrent.Executors;
 | |
| import java.util.concurrent.ScheduledExecutorService;
 | |
| import java.util.concurrent.TimeUnit;
 | |
| 
 | |
| import javax.ejb.Local;
 | |
| import javax.naming.ConfigurationException;
 | |
| 
 | |
| import org.apache.log4j.Logger;
 | |
| 
 | |
| import com.cloud.api.commands.ListPrivateGatewaysCmd;
 | |
| import com.cloud.api.commands.ListStaticRoutesCmd;
 | |
| import com.cloud.configuration.Config;
 | |
| import com.cloud.configuration.ConfigurationManager;
 | |
| import com.cloud.configuration.dao.ConfigurationDao;
 | |
| import com.cloud.dc.DataCenter;
 | |
| import com.cloud.deploy.DeployDestination;
 | |
| import com.cloud.event.ActionEvent;
 | |
| import com.cloud.event.EventTypes;
 | |
| import com.cloud.exception.ConcurrentOperationException;
 | |
| import com.cloud.exception.InsufficientCapacityException;
 | |
| import com.cloud.exception.InvalidParameterValueException;
 | |
| import com.cloud.exception.NetworkRuleConflictException;
 | |
| import com.cloud.exception.PermissionDeniedException;
 | |
| import com.cloud.exception.ResourceAllocationException;
 | |
| import com.cloud.exception.ResourceUnavailableException;
 | |
| import com.cloud.exception.UnsupportedServiceException;
 | |
| import com.cloud.network.IPAddressVO;
 | |
| import com.cloud.network.Network;
 | |
| import com.cloud.network.Network.GuestType;
 | |
| import com.cloud.network.Network.Provider;
 | |
| import com.cloud.network.Network.Service;
 | |
| import com.cloud.network.NetworkManager;
 | |
| import com.cloud.network.NetworkVO;
 | |
| import com.cloud.network.Networks.BroadcastDomainType;
 | |
| import com.cloud.network.Networks.TrafficType;
 | |
| import com.cloud.network.PhysicalNetwork;
 | |
| import com.cloud.network.dao.IPAddressDao;
 | |
| import com.cloud.network.dao.NetworkDao;
 | |
| import com.cloud.network.dao.PhysicalNetworkDao;
 | |
| import com.cloud.network.element.VpcProvider;
 | |
| import com.cloud.network.vpc.VpcOffering.State;
 | |
| 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.offering.NetworkOffering;
 | |
| import com.cloud.offerings.NetworkOfferingServiceMapVO;
 | |
| import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
 | |
| import com.cloud.org.Grouping;
 | |
| import com.cloud.projects.Project.ListProjectResourcesCriteria;
 | |
| import com.cloud.user.Account;
 | |
| import com.cloud.user.AccountManager;
 | |
| import com.cloud.user.User;
 | |
| import com.cloud.user.UserContext;
 | |
| import com.cloud.utils.NumbersUtil;
 | |
| import com.cloud.utils.Ternary;
 | |
| import com.cloud.utils.component.ComponentLocator;
 | |
| import com.cloud.utils.component.Inject;
 | |
| import com.cloud.utils.component.Manager;
 | |
| import com.cloud.utils.concurrency.NamedThreadFactory;
 | |
| import com.cloud.utils.db.DB;
 | |
| import com.cloud.utils.db.Filter;
 | |
| import com.cloud.utils.db.GlobalLock;
 | |
| import com.cloud.utils.db.JoinBuilder;
 | |
| import com.cloud.utils.db.SearchBuilder;
 | |
| import com.cloud.utils.db.SearchCriteria;
 | |
| import com.cloud.utils.db.SearchCriteria.Op;
 | |
| import com.cloud.utils.db.Transaction;
 | |
| import com.cloud.utils.exception.CloudRuntimeException;
 | |
| import com.cloud.utils.net.NetUtils;
 | |
| import com.cloud.vm.DomainRouterVO;
 | |
| import com.cloud.vm.ReservationContext;
 | |
| import com.cloud.vm.ReservationContextImpl;
 | |
| import com.cloud.vm.dao.DomainRouterDao;
 | |
| 
 | |
| 
 | |
| @Local(value = { VpcManager.class, VpcService.class })
 | |
| public class VpcManagerImpl implements VpcManager, Manager{
 | |
|     private static final Logger s_logger = Logger.getLogger(VpcManagerImpl.class);
 | |
|     @Inject
 | |
|     VpcOfferingDao _vpcOffDao;
 | |
|     @Inject
 | |
|     VpcOfferingServiceMapDao _vpcOffSvcMapDao;
 | |
|     @Inject
 | |
|     VpcDao _vpcDao;
 | |
|     @Inject
 | |
|     ConfigurationDao _configDao;
 | |
|     @Inject
 | |
|     ConfigurationManager _configMgr;
 | |
|     @Inject
 | |
|     AccountManager _accountMgr;
 | |
|     @Inject
 | |
|     NetworkDao _ntwkDao;
 | |
|     @Inject
 | |
|     NetworkManager _ntwkMgr;
 | |
|     @Inject
 | |
|     IPAddressDao _ipAddressDao;
 | |
|     @Inject
 | |
|     DomainRouterDao _routerDao;
 | |
|     @Inject
 | |
|     VpcGatewayDao _vpcGatewayDao;
 | |
|     @Inject
 | |
|     PrivateIpDao _privateIpDao;
 | |
|     @Inject
 | |
|     StaticRouteDao _staticRouteDao;
 | |
|     @Inject
 | |
|     NetworkOfferingServiceMapDao _ntwkOffServiceDao ;
 | |
|     @Inject
 | |
|     VpcOfferingServiceMapDao _vpcOffServiceDao;
 | |
|     @Inject
 | |
|     PhysicalNetworkDao _pNtwkDao;
 | |
|     
 | |
|     private final ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("VpcChecker"));
 | |
|     
 | |
|     private VpcProvider vpcElement = null;
 | |
|     
 | |
|     String _name;
 | |
|     int _cleanupInterval;
 | |
| 
 | |
|     @Override
 | |
|     @DB
 | |
|     public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
 | |
|         _name = name;
 | |
|         
 | |
|         //configure default vpc offering
 | |
|         Transaction txn = Transaction.currentTxn();
 | |
|         txn.start();
 | |
|         
 | |
|         if (_vpcOffDao.findByUniqueName(VpcOffering.defaultVPCOfferingName) == null) {
 | |
|             s_logger.debug("Creating default VPC offering " + VpcOffering.defaultVPCOfferingName);
 | |
|             
 | |
|             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.VPCVirtualRouter);
 | |
|                     lbProviders.add(Provider.Netscaler);
 | |
|                     svcProviderMap.put(svc, lbProviders);
 | |
|                 } else {
 | |
|                     svcProviderMap.put(svc, defaultProviders);
 | |
|                 }
 | |
|             }
 | |
|             createVpcOffering(VpcOffering.defaultVPCOfferingName, VpcOffering.defaultVPCOfferingName, svcProviderMap, 
 | |
|                     true, State.Enabled);
 | |
|         }
 | |
|                 
 | |
|         txn.commit();
 | |
|         
 | |
|         ComponentLocator locator = ComponentLocator.getCurrentLocator();
 | |
|         ConfigurationDao configDao = locator.getDao(ConfigurationDao.class);
 | |
|         Map<String, String> configs = configDao.getConfiguration(params);
 | |
|         String value = configs.get(Config.VpcCleanupInterval.key());
 | |
|         _cleanupInterval = NumbersUtil.parseInt(value, 60 * 60); // 1 hour
 | |
|         
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public boolean start() {
 | |
|         _executor.scheduleAtFixedRate(new VpcCleanupTask(), _cleanupInterval, _cleanupInterval, TimeUnit.SECONDS);
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public boolean stop() {
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public String getName() {
 | |
|         return _name;
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public List<? extends Network> getVpcNetworks(long vpcId) {
 | |
|         return _ntwkDao.listByVpc(vpcId);
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public VpcOffering getVpcOffering(long vpcOffId) {
 | |
|         return _vpcOffDao.findById(vpcOffId);
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     @ActionEvent(eventType = EventTypes.EVENT_VPC_OFFERING_CREATE, eventDescription = "creating vpc offering", create=true)
 | |
|     public VpcOffering createVpcOffering(String name, String displayText, List<String> supportedServices) {
 | |
|         Map<Network.Service, Set<Network.Provider>> svcProviderMap = new HashMap<Network.Service, Set<Network.Provider>>();
 | |
|         Set<Network.Provider> defaultProviders = new HashSet<Network.Provider>();
 | |
|         defaultProviders.add(Provider.VPCVirtualRouter);
 | |
| 
 | |
|         boolean sourceNatSvc = false;
 | |
|         boolean firewallSvs = false;
 | |
|         // populate the services first
 | |
|         for (String serviceName : supportedServices) {
 | |
|             // validate if the service is supported
 | |
|             Service service = Network.Service.getService(serviceName);
 | |
|             if (service == null || service == Service.Gateway) {
 | |
|                 throw new InvalidParameterValueException("Invalid service " + serviceName);
 | |
|             }
 | |
| 
 | |
|             //don't allow security group service for vpc
 | |
|             if (service == Service.SecurityGroup) {
 | |
|                 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) {
 | |
|             s_logger.debug("Automatically adding source nat service to the list of VPC services");
 | |
|             svcProviderMap.put(Service.SourceNat, defaultProviders);
 | |
|         }
 | |
|         
 | |
|         if (!firewallSvs) {
 | |
|             s_logger.debug("Automatically adding network ACL service to the list of VPC services");
 | |
|             svcProviderMap.put(Service.NetworkACL, defaultProviders);
 | |
|         }
 | |
|         
 | |
|         svcProviderMap.put(Service.Gateway, defaultProviders);
 | |
|                
 | |
|         return createVpcOffering(name, displayText, svcProviderMap, false, null);
 | |
|     }
 | |
|     
 | |
|     
 | |
|     @Override
 | |
|     @DB
 | |
|     public VpcOffering createVpcOffering(String name, String displayText, Map<Network.Service, 
 | |
|             Set<Network.Provider>> svcProviderMap, boolean isDefault, State state) {
 | |
|         Transaction txn = Transaction.currentTxn();
 | |
|         txn.start();
 | |
|         // create vpc offering object
 | |
|         VpcOfferingVO offering  = new VpcOfferingVO(name, displayText, isDefault, null);
 | |
|         
 | |
|         if (state != null) {
 | |
|             offering.setState(state);
 | |
|         }
 | |
|         s_logger.debug("Adding vpc offering " + offering);
 | |
|         offering = _vpcOffDao.persist(offering);
 | |
|         // populate services and providers
 | |
|         if (svcProviderMap != null) {
 | |
|             for (Network.Service service : svcProviderMap.keySet()) {
 | |
|                 Set<Provider> providers = svcProviderMap.get(service);
 | |
|                 if (providers != null && !providers.isEmpty()) {
 | |
|                     for (Network.Provider provider : providers) {
 | |
|                         VpcOfferingServiceMapVO offService = new VpcOfferingServiceMapVO(offering.getId(), service, provider);
 | |
|                         _vpcOffSvcMapDao.persist(offService);
 | |
|                         s_logger.trace("Added service for the vpc offering: " + offService + " with provider " + provider.getName());
 | |
|                     }
 | |
|                 } else {
 | |
|                     throw new InvalidParameterValueException("Provider is missing for the VPC offering service " + service.getName());
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         txn.commit();
 | |
| 
 | |
|         UserContext.current().setEventDetails(" Id: " + offering.getId() + " Name: " + name);
 | |
|         return offering;
 | |
|     }
 | |
|     
 | |
|     @Override
 | |
|     public Vpc getVpc(long vpcId) {
 | |
|         return _vpcDao.findById(vpcId);
 | |
|     }
 | |
|     
 | |
|     @Override
 | |
|     public Vpc getActiveVpc(long vpcId) {
 | |
|         return _vpcDao.getActiveVpcById(vpcId);
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public Map<Service, Set<Provider>> getVpcOffSvcProvidersMap(long vpcOffId) {
 | |
|         Map<Service, Set<Provider>> serviceProviderMap = new HashMap<Service, Set<Provider>>();
 | |
|         List<VpcOfferingServiceMapVO> map = _vpcOffSvcMapDao.listByVpcOffId(vpcOffId);
 | |
| 
 | |
|         for (VpcOfferingServiceMapVO instance : map) {
 | |
|             String service = instance.getService();
 | |
|             Set<Provider> providers;
 | |
|             providers = serviceProviderMap.get(service);
 | |
|             if (providers == null) {
 | |
|                 providers = new HashSet<Provider>();
 | |
|             }
 | |
|             providers.add(Provider.getProvider(instance.getProvider()));
 | |
|             serviceProviderMap.put(Service.getService(service), providers);
 | |
|         }
 | |
| 
 | |
|         return serviceProviderMap;
 | |
|     }
 | |
|     
 | |
|     
 | |
|     @Override
 | |
|     public List<? extends VpcOffering> listVpcOfferings(Long id, String name, String displayText, List<String> supportedServicesStr,
 | |
|             Boolean isDefault, String keyword, String state, Long startIndex, Long pageSizeVal) {
 | |
|         Filter searchFilter = new Filter(VpcOfferingVO.class, "created", false, startIndex, pageSizeVal);
 | |
|         SearchCriteria<VpcOfferingVO> sc = _vpcOffDao.createSearchCriteria();
 | |
| 
 | |
|         if (keyword != null) {
 | |
|             SearchCriteria<VpcOfferingVO> ssc = _vpcOffDao.createSearchCriteria();
 | |
|             ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
 | |
|             ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
 | |
| 
 | |
|             sc.addAnd("name", SearchCriteria.Op.SC, ssc);
 | |
|         }
 | |
| 
 | |
|         if (name != null) {
 | |
|             sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
 | |
|         }
 | |
| 
 | |
|         if (displayText != null) {
 | |
|             sc.addAnd("displayText", SearchCriteria.Op.LIKE, "%" + displayText + "%");
 | |
|         }
 | |
| 
 | |
|         if (isDefault != null) {
 | |
|             sc.addAnd("isDefault", SearchCriteria.Op.EQ, isDefault);
 | |
|         }
 | |
| 
 | |
|         if (state != null) {
 | |
|             sc.addAnd("state", SearchCriteria.Op.EQ, state);
 | |
|         }
 | |
| 
 | |
|         if (id != null) {
 | |
|             sc.addAnd("id", SearchCriteria.Op.EQ, id);
 | |
|         }
 | |
| 
 | |
| 
 | |
|         List<VpcOfferingVO> offerings = _vpcOffDao.search(sc, searchFilter);
 | |
| 
 | |
|         // filter by supported services
 | |
|         boolean listBySupportedServices = (supportedServicesStr != null && !supportedServicesStr.isEmpty() && !offerings.isEmpty());
 | |
|         
 | |
|         if (listBySupportedServices) {
 | |
|             List<VpcOfferingVO> supportedOfferings = new ArrayList<VpcOfferingVO>();
 | |
|             Service[] supportedServices = null;
 | |
| 
 | |
|             if (listBySupportedServices) {
 | |
|                 supportedServices = new Service[supportedServicesStr.size()];
 | |
|                 int i = 0;
 | |
|                 for (String supportedServiceStr : supportedServicesStr) {
 | |
|                     Service service = Service.getService(supportedServiceStr);
 | |
|                     if (service == null) {
 | |
|                         throw new InvalidParameterValueException("Invalid service specified " + supportedServiceStr);
 | |
|                     } else {
 | |
|                         supportedServices[i] = service;
 | |
|                     }
 | |
|                     i++;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             for (VpcOfferingVO offering : offerings) {
 | |
|                 if (areServicesSupportedByVpcOffering(offering.getId(), supportedServices)) {
 | |
|                     supportedOfferings.add(offering);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             return supportedOfferings;
 | |
|         } else {
 | |
|             return offerings;
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     @Override
 | |
|     public boolean areServicesSupportedByVpcOffering(long vpcOffId, Service... services) {
 | |
|         return (_vpcOffSvcMapDao.areServicesSupportedByNetworkOffering(vpcOffId, services));
 | |
|     }
 | |
| 
 | |
|     
 | |
|     @Override
 | |
|     @ActionEvent(eventType = EventTypes.EVENT_VPC_OFFERING_DELETE, eventDescription = "deleting vpc offering")
 | |
|     public boolean deleteVpcOffering(long offId) {
 | |
|         UserContext.current().setEventDetails(" Id: " + offId);
 | |
| 
 | |
|         // Verify vpc offering id
 | |
|         VpcOfferingVO offering = _vpcOffDao.findById(offId);
 | |
|         if (offering == null) {
 | |
|             throw new InvalidParameterValueException("unable to find vpc offering " + offId);
 | |
|         } 
 | |
| 
 | |
|         // Don't allow to delete default vpc offerings
 | |
|         if (offering.isDefault() == true) {
 | |
|             throw new InvalidParameterValueException("Default network offering can't be deleted");
 | |
|         }
 | |
| 
 | |
|         // don't allow to delete vpc offering if it's in use by existing vpcs (the offering can be disabled though)
 | |
|         int vpcCount = _vpcDao.getVpcCountByOfferingId(offId);
 | |
|         if (vpcCount > 0) {
 | |
|             throw new InvalidParameterValueException("Can't delete vpc offering " + offId + " as its used by " + vpcCount + " vpcs. " +
 | |
|                     "To make the network offering unavaiable, disable it");
 | |
|         }
 | |
| 
 | |
|         if (_vpcOffDao.remove(offId)) {
 | |
|             return true;
 | |
|         } else {
 | |
|             return false;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     @ActionEvent(eventType = EventTypes.EVENT_VPC_OFFERING_UPDATE, eventDescription = "updating vpc offering")
 | |
|     public VpcOffering updateVpcOffering(long vpcOffId, String vpcOfferingName, String displayText, String state) {
 | |
|         UserContext.current().setEventDetails(" Id: " + vpcOffId);
 | |
| 
 | |
|         // Verify input parameters
 | |
|         VpcOfferingVO offeringToUpdate = _vpcOffDao.findById(vpcOffId);
 | |
|         if (offeringToUpdate == null) {
 | |
|             throw new InvalidParameterValueException("Unable to find vpc offering " + vpcOffId);
 | |
|         }
 | |
| 
 | |
|         VpcOfferingVO offering = _vpcOffDao.createForUpdate(vpcOffId);
 | |
| 
 | |
|         if (vpcOfferingName != null) {
 | |
|             offering.setName(vpcOfferingName);
 | |
|         }
 | |
| 
 | |
|         if (displayText != null) {
 | |
|             offering.setDisplayText(displayText);
 | |
|         }
 | |
| 
 | |
|         if (state != null) {
 | |
|             boolean validState = false;
 | |
|             for (VpcOffering.State st : VpcOffering.State.values()) {
 | |
|                 if (st.name().equalsIgnoreCase(state)) {
 | |
|                     validState = true;
 | |
|                     offering.setState(st);
 | |
|                 }
 | |
|             }
 | |
|             if (!validState) {
 | |
|                 throw new InvalidParameterValueException("Incorrect state value: " + state);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (_vpcOffDao.update(vpcOffId, offering)) {
 | |
|             s_logger.debug("Updated VPC offeirng id=" + vpcOffId);
 | |
|             return _vpcOffDao.findById(vpcOffId);
 | |
|         } else {
 | |
|             return null;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     @ActionEvent(eventType = EventTypes.EVENT_VPC_CREATE, eventDescription = "creating vpc", create=true)
 | |
|     public Vpc createVpc(long zoneId, long vpcOffId, long vpcOwnerId, String vpcName, String displayText, String cidr, 
 | |
|             String networkDomain) {
 | |
|         Account caller = UserContext.current().getCaller();
 | |
|         Account owner = _accountMgr.getAccount(vpcOwnerId);
 | |
|         
 | |
|         //Verify that caller can perform actions in behalf of vpc owner
 | |
|         _accountMgr.checkAccess(caller, null, false, owner);
 | |
|         
 | |
|         // Validate vpc offering
 | |
|         VpcOfferingVO vpcOff = _vpcOffDao.findById(vpcOffId);
 | |
|         if (vpcOff == null) {
 | |
|             InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find vpc offering by specified id");
 | |
|             ex.addProxyObject("vpc_offerings", vpcOffId, "vpcOfferingId");
 | |
|             throw ex;
 | |
|         }
 | |
|        
 | |
|         //Validate zone
 | |
|         DataCenter zone = _configMgr.getZone(zoneId);
 | |
|         if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType())) {
 | |
|             // See DataCenterVO.java
 | |
|             PermissionDeniedException ex = new PermissionDeniedException("Cannot perform this operation since specified Zone is currently disabled");
 | |
|             ex.addProxyObject("data_center", zone.getId(), "zoneId");
 | |
|             throw ex;
 | |
|         }
 | |
|         
 | |
|         if (networkDomain == null) {
 | |
|             // 1) Get networkDomain from the corresponding account
 | |
|             networkDomain = _ntwkMgr.getAccountNetworkDomain(owner.getId(), zoneId);
 | |
| 
 | |
| 
 | |
|             // 2) If null, generate networkDomain using domain suffix from the global config variables
 | |
|             if (networkDomain == null) {
 | |
|                 networkDomain = "cs" + Long.toHexString(owner.getId()) + _ntwkMgr.getDefaultNetworkDomain();
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         return createVpc(zoneId, vpcOffId, owner, vpcName, displayText, cidr, networkDomain);
 | |
|     }
 | |
|     
 | |
|     @Override
 | |
|     public Vpc createVpc(long zoneId, long vpcOffId, Account vpcOwner, String vpcName, String displayText, String cidr, 
 | |
|             String networkDomain) {
 | |
|         
 | |
|         //the provider has to be enabled at least in one network in the zone
 | |
|         boolean providerEnabled = false;
 | |
|         for (PhysicalNetwork pNtwk : _pNtwkDao.listByZone(zoneId)) {
 | |
|             if (_ntwkMgr.isProviderEnabledInPhysicalNetwork(pNtwk.getId(), Provider.VPCVirtualRouter.getName())) {
 | |
|                 providerEnabled = true;
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         if (!providerEnabled) {
 | |
|             throw new InvalidParameterValueException("Provider " + Provider.VPCVirtualRouter.getName() +
 | |
|                     " should be enabled in at least one physical network of the zone specified");
 | |
|         }
 | |
|         
 | |
|         //Validate CIDR
 | |
|         if (!NetUtils.isValidCIDR(cidr)) {
 | |
|             throw new InvalidParameterValueException("Invalid CIDR specified " + cidr);
 | |
|         }
 | |
| 
 | |
|         // validate network domain
 | |
|         if (!NetUtils.verifyDomainName(networkDomain)) {
 | |
|             throw new InvalidParameterValueException(
 | |
|                     "Invalid network domain. Total length shouldn't exceed 190 chars. Each domain " +
 | |
|                     "label must be between 1 and 63 characters long, can contain ASCII letters 'a' through 'z', " +
 | |
|                     "the digits '0' through '9', "
 | |
|                             + "and the hyphen ('-'); can't start or end with \"-\"");
 | |
|         }
 | |
|         
 | |
|         
 | |
|         //don't allow overlapping CIDRS for the VPCs of the same account
 | |
|         List<? extends Vpc> vpcs = getVpcsForAccount(vpcOwner.getId());
 | |
|         for (Vpc vpc : vpcs) {
 | |
|             if (NetUtils.isNetworksOverlap(cidr, vpc.getCidr())) {
 | |
|                 throw new InvalidParameterValueException("Account already has vpc with cidr " + vpc.getCidr() + 
 | |
|                         " that overlaps the cidr specified: " + cidr);
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         VpcVO vpc = new VpcVO (zoneId, vpcName, displayText, vpcOwner.getId(), vpcOwner.getDomainId(), vpcOffId, cidr, 
 | |
|                 networkDomain);
 | |
|         vpc = _vpcDao.persist(vpc);
 | |
|         
 | |
|         if (vpc != null) {
 | |
|             s_logger.debug("Created VPC " + vpc);
 | |
|         } else {
 | |
|             s_logger.debug("Failed to create VPC");
 | |
|         }
 | |
|         return vpc; 
 | |
|     }
 | |
|     
 | |
|     @Override
 | |
|     @ActionEvent(eventType = EventTypes.EVENT_VPC_DELETE, eventDescription = "deleting VPC")
 | |
|     public boolean deleteVpc(long vpcId) throws ConcurrentOperationException, ResourceUnavailableException {
 | |
|         UserContext.current().setEventDetails(" Id: " + vpcId);
 | |
|         Account caller = UserContext.current().getCaller();
 | |
| 
 | |
|         // Verify vpc id
 | |
|         Vpc vpc = getVpc(vpcId);
 | |
|         if (vpc == null) {
 | |
|             throw new InvalidParameterValueException("unable to find VPC id=" + vpcId);
 | |
|         }
 | |
|         
 | |
|         //verify permissions
 | |
|         _accountMgr.checkAccess(caller, null, false, vpc);
 | |
|         
 | |
|         return destroyVpc(vpc);
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public boolean destroyVpc(Vpc vpc) throws ConcurrentOperationException, ResourceUnavailableException {
 | |
|         UserContext ctx = UserContext.current();
 | |
|         
 | |
|         //don't allow to delete vpc if it's in use by existing networks
 | |
|         int networksCount = _ntwkDao.getNetworkCountByVpcId(vpc.getId());
 | |
|         if (networksCount > 0) {
 | |
|             throw new InvalidParameterValueException("Can't delete VPC " + vpc + " as its used by " + networksCount + " networks");
 | |
|         }
 | |
|         
 | |
|         //mark VPC as disabled
 | |
|         s_logger.debug("Updating VPC " + vpc + " with state " + Vpc.State.Inactive + " as a part of vpc delete");
 | |
|         VpcVO vpcVO = _vpcDao.findById(vpc.getId());
 | |
|         vpcVO.setState(Vpc.State.Inactive);
 | |
|         _vpcDao.update(vpc.getId(), vpcVO);
 | |
| 
 | |
|         //shutdown VPC
 | |
|         if (!shutdownVpc(vpc.getId())) {
 | |
|             s_logger.warn("Failed to shutdown vpc " + vpc + " as a part of vpc destroy process");
 | |
|             return false;
 | |
|         }
 | |
|         
 | |
|         //cleanup vpc resources
 | |
|         if (!cleanupVpcResources(vpc.getId(), ctx.getCaller(), ctx.getCallerUserId())) {
 | |
|             s_logger.warn("Failed to cleanup resources for vpc " + vpc);
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         //update the instance with removed flag only when the cleanup is executed successfully
 | |
|         if (_vpcDao.remove(vpc.getId())) {
 | |
|             s_logger.debug("Vpc " + vpc + " is removed succesfully");
 | |
|             return true;
 | |
|         } else {
 | |
|             return false;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     @ActionEvent(eventType = EventTypes.EVENT_VPC_UPDATE, eventDescription = "updating vpc")
 | |
|     public Vpc updateVpc(long vpcId, String vpcName, String displayText) {
 | |
|         UserContext.current().setEventDetails(" Id: " + vpcId);
 | |
|         Account caller = UserContext.current().getCaller();
 | |
| 
 | |
|         // Verify input parameters
 | |
|         VpcVO vpcToUpdate = _vpcDao.findById(vpcId);
 | |
|         if (vpcToUpdate == null) {
 | |
|             throw new InvalidParameterValueException("Unable to find vpc offering " + vpcId);
 | |
|         }
 | |
|         
 | |
|         _accountMgr.checkAccess(caller, null, false, vpcToUpdate);
 | |
| 
 | |
|         VpcVO vpc = _vpcDao.createForUpdate(vpcId);
 | |
| 
 | |
|         if (vpcName != null) {
 | |
|             vpc.setName(vpcName);
 | |
|         }
 | |
| 
 | |
|         if (displayText != null) {
 | |
|             vpc.setDisplayText(displayText);
 | |
|         }
 | |
| 
 | |
|         if (_vpcDao.update(vpcId, vpc)) {
 | |
|             s_logger.debug("Updated VPC id=" + vpcId);
 | |
|             return _vpcDao.findById(vpcId);
 | |
|         } else {
 | |
|             return null;
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     @Override
 | |
|     public List<? extends Vpc> listVpcs(Long id, String vpcName, String displayText, List<String> supportedServicesStr, 
 | |
|             String cidr, Long vpcOffId, String state, String accountName, Long domainId, String keyword,
 | |
|             Long startIndex, Long pageSizeVal, Long zoneId, Boolean isRecursive, Boolean listAll, Boolean restartRequired) {
 | |
|         Account caller = UserContext.current().getCaller();
 | |
|         List<Long> permittedAccounts = new ArrayList<Long>();
 | |
|         
 | |
|         Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, 
 | |
|                 ListProjectResourcesCriteria>(domainId, isRecursive, null);
 | |
|         _accountMgr.buildACLSearchParameters(caller, id, accountName, null, permittedAccounts, domainIdRecursiveListProject,
 | |
|                 listAll, false);
 | |
|         domainId = domainIdRecursiveListProject.first();
 | |
|         isRecursive = domainIdRecursiveListProject.second();
 | |
|         ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third();
 | |
|         Filter searchFilter = new Filter(VpcVO.class, "created", false, startIndex, pageSizeVal);
 | |
| 
 | |
|         SearchBuilder<VpcVO> sb = _vpcDao.createSearchBuilder();
 | |
|         _accountMgr.buildACLSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);
 | |
| 
 | |
|         sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
 | |
|         sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
 | |
|         sb.and("displayText", sb.entity().getDisplayText(), SearchCriteria.Op.LIKE);
 | |
|         sb.and("vpcOfferingId", sb.entity().getVpcOfferingId(), SearchCriteria.Op.EQ);
 | |
|         sb.and("zoneId", sb.entity().getZoneId(), SearchCriteria.Op.EQ);
 | |
|         sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
 | |
|         sb.and("restartRequired", sb.entity().isRestartRequired(), SearchCriteria.Op.EQ);
 | |
|         sb.and("cidr", sb.entity().getCidr(), SearchCriteria.Op.EQ);
 | |
|         
 | |
|         // now set the SC criteria...
 | |
|         SearchCriteria<VpcVO> sc = sb.create();
 | |
|         _accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);  
 | |
| 
 | |
|         if (keyword != null) {
 | |
|             SearchCriteria<VpcVO> ssc = _vpcDao.createSearchCriteria();
 | |
|             ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
 | |
|             ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
 | |
|             sc.addAnd("name", SearchCriteria.Op.SC, ssc);
 | |
|         }
 | |
| 
 | |
|         if (vpcName != null) {
 | |
|             sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + vpcName + "%");
 | |
|         }
 | |
| 
 | |
|         if (displayText != null) {
 | |
|             sc.addAnd("displayText", SearchCriteria.Op.LIKE, "%" + displayText + "%");
 | |
|         }
 | |
| 
 | |
|         if (id != null) {
 | |
|             sc.addAnd("id", SearchCriteria.Op.EQ, id);
 | |
|         }
 | |
|         
 | |
|         if (vpcOffId != null) {
 | |
|             sc.addAnd("vpcOfferingId", SearchCriteria.Op.EQ, vpcOffId);
 | |
|         }
 | |
|         
 | |
|         if (zoneId != null) {
 | |
|             sc.addAnd("zoneId", SearchCriteria.Op.EQ, zoneId);
 | |
|         }
 | |
|         
 | |
|         if (state != null) {
 | |
|             sc.addAnd("state", SearchCriteria.Op.EQ, state);
 | |
|         }
 | |
|         
 | |
|         if (cidr != null) {
 | |
|             sc.addAnd("cidr", SearchCriteria.Op.EQ, cidr);
 | |
|         }
 | |
|         
 | |
|         if (restartRequired != null) {
 | |
|             sc.addAnd("restartRequired", SearchCriteria.Op.EQ, restartRequired);
 | |
|         }
 | |
| 
 | |
|         List<VpcVO> vpcs = _vpcDao.search(sc, searchFilter);
 | |
| 
 | |
|         // filter by supported services
 | |
|         boolean listBySupportedServices = (supportedServicesStr != null && !supportedServicesStr.isEmpty() && !vpcs.isEmpty());
 | |
|         
 | |
|         if (listBySupportedServices) {
 | |
|             List<VpcVO> supportedVpcs = new ArrayList<VpcVO>();
 | |
|             Service[] supportedServices = null;
 | |
| 
 | |
|             if (listBySupportedServices) {
 | |
|                 supportedServices = new Service[supportedServicesStr.size()];
 | |
|                 int i = 0;
 | |
|                 for (String supportedServiceStr : supportedServicesStr) {
 | |
|                     Service service = Service.getService(supportedServiceStr);
 | |
|                     if (service == null) {
 | |
|                         throw new InvalidParameterValueException("Invalid service specified " + supportedServiceStr);
 | |
|                     } else {
 | |
|                         supportedServices[i] = service;
 | |
|                     }
 | |
|                     i++;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             for (VpcVO vpc : vpcs) {
 | |
|                 if (areServicesSupportedByVpcOffering(vpc.getVpcOfferingId(), supportedServices)) {
 | |
|                     supportedVpcs.add(vpc);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             return supportedVpcs;
 | |
|         } else {
 | |
|             return vpcs;
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     @Override
 | |
|     public List<Service> getSupportedServices() {
 | |
|        List<Service> services = new ArrayList<Service>();
 | |
|        services.add(Network.Service.Dhcp);
 | |
|        services.add(Network.Service.Dns);
 | |
|        services.add(Network.Service.UserData);
 | |
|        services.add(Network.Service.NetworkACL);
 | |
|        services.add(Network.Service.PortForwarding);
 | |
|        services.add(Network.Service.Lb);
 | |
|        services.add(Network.Service.SourceNat);
 | |
|        services.add(Network.Service.StaticNat);
 | |
|        services.add(Network.Service.Gateway);
 | |
|        services.add(Network.Service.Vpn);
 | |
|        return services;
 | |
|     }
 | |
|     
 | |
|     @Override
 | |
|     public boolean startVpc(long vpcId, boolean destroyOnFailure) throws ConcurrentOperationException, ResourceUnavailableException, 
 | |
|     InsufficientCapacityException {
 | |
|         UserContext ctx = UserContext.current();
 | |
|         Account caller = ctx.getCaller();
 | |
|         User callerUser = _accountMgr.getActiveUser(ctx.getCallerUserId());
 | |
|         
 | |
|         //check if vpc exists
 | |
|         Vpc vpc = getActiveVpc(vpcId);
 | |
|         if (vpc == null) {
 | |
|             InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find Enabled VPC by id specified");
 | |
|             ex.addProxyObject("vpc", vpcId, "VPC");
 | |
|             throw ex;
 | |
|         }
 | |
|         
 | |
|         //permission check
 | |
|         _accountMgr.checkAccess(caller, null, false, vpc);
 | |
|         
 | |
|         DataCenter dc = _configMgr.getZone(vpc.getZoneId());
 | |
|      
 | |
|         DeployDestination dest = new DeployDestination(dc, null, null, null);
 | |
|         ReservationContext context = new ReservationContextImpl(null, null, callerUser, 
 | |
|                 _accountMgr.getAccount(vpc.getAccountId()));
 | |
|         
 | |
|         boolean result = true;
 | |
|         try {
 | |
|             if (!startVpc(vpc, dest, context)) {
 | |
|                 s_logger.warn("Failed to start vpc " + vpc);
 | |
|                 result = false;
 | |
|             }
 | |
|         } catch (Exception ex) {
 | |
|             s_logger.warn("Failed to start vpc " + vpc + " due to ", ex);
 | |
|             result = false;
 | |
|         } finally {
 | |
|             //do cleanup
 | |
|             if (!result && destroyOnFailure) {
 | |
|                 s_logger.debug("Destroying vpc " + vpc + " that failed to start");
 | |
|                 if (destroyVpc(vpc)) {
 | |
|                     s_logger.warn("Successfully destroyed vpc " + vpc + " that failed to start");
 | |
|                 } else {
 | |
|                     s_logger.warn("Failed to destroy vpc " + vpc + " that failed to start");
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     protected boolean startVpc(Vpc vpc, DeployDestination dest, ReservationContext context) 
 | |
|             throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
 | |
|         //deploy provider
 | |
|         if (getVpcElement().implementVpc(vpc, dest, context)) {
 | |
|             s_logger.debug("Vpc " + vpc + " has started succesfully");
 | |
|             return true;
 | |
|         } else {
 | |
|             s_logger.warn("Vpc " + vpc + " failed to start");
 | |
|             return false;
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     @Override
 | |
|     public boolean shutdownVpc(long vpcId) throws ConcurrentOperationException, ResourceUnavailableException {
 | |
|         UserContext ctx = UserContext.current();
 | |
|         Account caller = ctx.getCaller();
 | |
|         
 | |
|         //check if vpc exists
 | |
|         Vpc vpc = getVpc(vpcId);
 | |
|         if (vpc == null) {
 | |
|             throw new InvalidParameterValueException("Unable to find vpc by id " + vpcId);
 | |
|         }
 | |
|         
 | |
|         //permission check
 | |
|         _accountMgr.checkAccess(caller, null, false, vpc);
 | |
| 
 | |
|         //shutdown provider
 | |
|         boolean success = getVpcElement().shutdownVpc(vpc);
 | |
|         
 | |
|         //FIXME - once more features are added to vpc (gateway/firewall rules, etc - cleanup them here)
 | |
|         if (success) {
 | |
|             s_logger.debug("Vpc " + vpc + " has been shutdown succesfully");
 | |
|         } else {
 | |
|             s_logger.warn("Vpc " + vpc + " failed to shutdown");
 | |
|         }
 | |
|         return success;
 | |
|     }
 | |
|     
 | |
|     @Override
 | |
|     @DB
 | |
|     public void validateGuestNtkwForVpc(NetworkOffering guestNtwkOff, String cidr, String networkDomain, 
 | |
|             Account networkOwner, Vpc vpc, Long networkId, String gateway) {
 | |
| 
 | |
|         if (networkId == null) {
 | |
|             //1) Validate attributes that has to be passed in when create new guest network
 | |
|             validateNewVpcGuestNetwork(cidr, gateway, 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, String gateway, Account networkOwner, Vpc vpc, String networkDomain) {
 | |
|         Vpc locked = _vpcDao.acquireInLockTable(vpc.getId());
 | |
|         if (locked == null) {
 | |
|             throw new CloudRuntimeException("Unable to acquire lock on " + vpc);
 | |
|         }
 | |
|         
 | |
|         try {
 | |
|             //1) CIDR is required
 | |
|             if (cidr == null) {
 | |
|                 throw new InvalidParameterValueException("Gateway/netmask are required when create network for VPC");
 | |
|             }
 | |
|             
 | |
|             //2) Network cidr should be within vpcCidr
 | |
|             if (!NetUtils.isNetworkAWithinNetworkB(cidr, vpc.getCidr())) {
 | |
|                 throw new InvalidParameterValueException("Network cidr " + cidr + " is not within vpc " + vpc + " cidr");
 | |
|             }
 | |
|             
 | |
|             //3) Network cidr shouldn't cross the cidr of other vpc network cidrs
 | |
|             List<? extends Network> ntwks = _ntwkDao.listByVpc(vpc.getId());
 | |
|             for (Network ntwk : ntwks) {
 | |
|                 assert (cidr != null) : "Why the network cidr is null when it belongs to vpc?";
 | |
|                 
 | |
|                 if (NetUtils.isNetworkAWithinNetworkB(ntwk.getCidr(), vpc.getCidr()) 
 | |
|                         || NetUtils.isNetworkAWithinNetworkB(vpc.getCidr(), ntwk.getCidr())) {
 | |
|                     throw new InvalidParameterValueException("Network cidr " + cidr + " crosses other network cidr " + ntwk + 
 | |
|                             " belonging to the same vpc " + vpc);
 | |
|                 }
 | |
|             }
 | |
|             
 | |
|             //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);
 | |
|             }
 | |
|             
 | |
|             //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) gateway should never be equal to the cidr subnet
 | |
|             if (NetUtils.getCidrSubNet(cidr).equalsIgnoreCase(gateway)) {
 | |
|                 throw new InvalidParameterValueException("Invalid gateway specified. It should never be equal to the cidr subnet value");
 | |
|             }
 | |
|             
 | |
|         } finally {
 | |
|             s_logger.debug("Releasing lock for " + locked);
 | |
|             _vpcDao.releaseFromLockTable(locked.getId());
 | |
|         }
 | |
|     }
 | |
|      
 | |
|     @Override
 | |
|     public VpcProvider getVpcElement() {
 | |
|         if (vpcElement == null) {
 | |
|             vpcElement = ((VpcProvider)_ntwkMgr.getElementImplementingProvider(Provider.VPCVirtualRouter.getName()));
 | |
|         }
 | |
|         
 | |
|         return vpcElement;
 | |
|     }
 | |
|     
 | |
|     @Override
 | |
|     public List<? extends Vpc> getVpcsForAccount(long accountId) {
 | |
|         return _vpcDao.listByAccountId(accountId);
 | |
|     }
 | |
|     
 | |
|     public boolean cleanupVpcResources(long vpcId, Account caller, long callerUserId) 
 | |
|             throws ResourceUnavailableException, ConcurrentOperationException {
 | |
|         s_logger.debug("Cleaning up resources for vpc id=" + vpcId);
 | |
|         boolean success = true;
 | |
|         
 | |
|         //1) release all ip addresses
 | |
|         List<IPAddressVO> ipsToRelease = _ipAddressDao.listByAssociatedVpc(vpcId, null);
 | |
|         s_logger.debug("Releasing ips for vpc id=" + vpcId + " as a part of vpc cleanup");
 | |
|         for (IPAddressVO ipToRelease : ipsToRelease) {
 | |
|             success = success && _ntwkMgr.disassociatePublicIpAddress(ipToRelease.getId(), callerUserId, caller);
 | |
|             if (!success) {
 | |
|                 s_logger.warn("Failed to cleanup ip " + ipToRelease + " as a part of vpc id=" + vpcId + " cleanup");
 | |
|             }
 | |
|         } 
 | |
|         
 | |
|         if (success) {
 | |
|             s_logger.debug("Released ip addresses for vpc id=" + vpcId + " as a part of cleanup vpc process");
 | |
|         } else {
 | |
|             s_logger.warn("Failed to release ip addresses for vpc id=" + vpcId + " as a part of cleanup vpc process");
 | |
|             //although it failed, proceed to the next cleanup step as it doesn't depend on the public ip release
 | |
|         }
 | |
|         
 | |
|         //2) Delete all static route rules
 | |
|         if (!revokeStaticRoutesForVpc(vpcId, caller)) {
 | |
|             s_logger.warn("Failed to revoke static routes for vpc " + vpcId + " as a part of cleanup vpc process");
 | |
|             return false;
 | |
|         }
 | |
|         
 | |
|         //3) Delete private gateway
 | |
|         VpcGateway gateway = getPrivateGatewayForVpc(vpcId);
 | |
|         if (gateway != null) {
 | |
|             s_logger.debug("Deleting private gateway " + gateway + " as a part of vpc " + vpcId + " resources cleanup");
 | |
|             if (!deleteVpcPrivateGateway(gateway.getId())) {
 | |
|                 success = false;
 | |
|                 s_logger.debug("Failed to delete private gateway " + gateway + " as a part of vpc " + vpcId + " resources cleanup");
 | |
|             } else {
 | |
|                 s_logger.debug("Deleted private gateway " + gateway + " as a part of vpc " + vpcId + " resources cleanup");
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         return success;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     @Override
 | |
|     @ActionEvent(eventType = EventTypes.EVENT_VPC_RESTART, eventDescription = "restarting vpc")
 | |
|     public boolean restartVpc(long vpcId) throws ConcurrentOperationException, ResourceUnavailableException, 
 | |
|                                         InsufficientCapacityException {
 | |
|         Account caller = UserContext.current().getCaller();
 | |
| 
 | |
|         // Verify input parameters
 | |
|         Vpc vpc = getActiveVpc(vpcId);
 | |
|         if (vpc == null) {
 | |
|             InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find Enabled VPC by id specified");
 | |
|             ex.addProxyObject("vpc", vpcId, "VPC");
 | |
|             throw ex;
 | |
|         }
 | |
|         
 | |
|         _accountMgr.checkAccess(caller, null, false, vpc);
 | |
|         
 | |
|         s_logger.debug("Restarting VPC " + vpc);
 | |
|         boolean restartRequired = false;
 | |
|         try {
 | |
|             s_logger.debug("Shutting down VPC " + vpc + " as a part of VPC restart process");
 | |
|             if (!shutdownVpc(vpcId)) {
 | |
|                 s_logger.warn("Failed to shutdown vpc as a part of VPC " + vpc + " restart process");
 | |
|                 restartRequired = true;
 | |
|                 return false;
 | |
|             }
 | |
|             
 | |
|             s_logger.debug("Starting VPC " + vpc + " as a part of VPC restart process");
 | |
|             if (!startVpc(vpcId, false)) {
 | |
|                 s_logger.warn("Failed to start vpc as a part of VPC " + vpc + " restart process");
 | |
|                 restartRequired = true;
 | |
|                 return false;
 | |
|             }
 | |
|             s_logger.debug("VPC " + vpc + " was restarted successfully");
 | |
|             return true;
 | |
|         } finally {
 | |
|             s_logger.debug("Updating VPC " + vpc + " with restartRequired=" + restartRequired);
 | |
|             VpcVO vo = _vpcDao.findById(vpcId);
 | |
|             vo.setRestartRequired(restartRequired);
 | |
|             _vpcDao.update(vpc.getId(), vo);
 | |
|         }  
 | |
|     }
 | |
|     
 | |
|     @Override
 | |
|     public List<DomainRouterVO> getVpcRouters(long vpcId) {
 | |
|         return _routerDao.listByVpcId(vpcId);
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public PrivateGateway getVpcPrivateGateway(long id) {
 | |
|         VpcGateway gateway = _vpcGatewayDao.findById(id);
 | |
| 
 | |
|         if (gateway == null || gateway.getType() != VpcGateway.Type.Private) {
 | |
|             return null;
 | |
|         }
 | |
|         return getPrivateGatewayProfile(gateway);
 | |
|     }
 | |
|     
 | |
|     @Override
 | |
|     public VpcGateway getVpcGateway(long id) {
 | |
|         return _vpcGatewayDao.findById(id);
 | |
|     }
 | |
| 
 | |
|     protected PrivateGateway getPrivateGatewayProfile(VpcGateway gateway) {
 | |
|         Network network = _ntwkMgr.getNetwork(gateway.getNetworkId());
 | |
|         return new PrivateGatewayProfile(gateway, network.getPhysicalNetworkId());
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     @DB
 | |
|     @ActionEvent(eventType = EventTypes.EVENT_PRIVATE_GATEWAY_CREATE, eventDescription = "creating vpc private gateway", create=true)
 | |
|     public PrivateGateway createVpcPrivateGateway(long vpcId, Long physicalNetworkId, String vlan, String ipAddress, 
 | |
|             String gateway, String netmask, long gatewayOwnerId) throws ResourceAllocationException, 
 | |
|             ConcurrentOperationException, InsufficientCapacityException {
 | |
|         
 | |
|         //Validate parameters
 | |
|         Vpc vpc = getActiveVpc(vpcId);
 | |
|         if (vpc == null) {
 | |
|             InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find Enabled VPC by id specified");
 | |
|             ex.addProxyObject("vpc", vpcId, "VPC");
 | |
|             throw ex;
 | |
|         }
 | |
|         
 | |
|         //allow only one private gateway per vpc
 | |
|         VpcGatewayVO gatewayVO = _vpcGatewayDao.getPrivateGatewayForVpc(vpcId);
 | |
|         if (gatewayVO != null) {
 | |
|             throw new InvalidParameterValueException("Private ip address already exists for vpc " + vpc);
 | |
|         }
 | |
|         
 | |
|         //Validate physical network
 | |
|         if (physicalNetworkId == null) {
 | |
|             List<? extends PhysicalNetwork> pNtwks = _ntwkMgr.getPhysicalNtwksSupportingTrafficType(vpc.getZoneId(), TrafficType.Guest);
 | |
|             if (pNtwks.isEmpty() || pNtwks.size() != 1) {
 | |
|                 throw new InvalidParameterValueException("Physical network can't be determined; pass physical network id");
 | |
|             }
 | |
|             physicalNetworkId = pNtwks.get(0).getId();
 | |
|         }
 | |
|         
 | |
|         Transaction txn = Transaction.currentTxn();
 | |
|         txn.start();
 | |
|         s_logger.debug("Creating Private gateway for VPC " + vpc);
 | |
|         //1) create private network
 | |
|         String networkName = "vpc-" + vpc.getName() + "-privateNetwork";
 | |
|         Network privateNtwk = _ntwkMgr.createPrivateNetwork(networkName, networkName, physicalNetworkId, 
 | |
|                 vlan, ipAddress, null, gateway, netmask, gatewayOwnerId, vpcId);
 | |
|         
 | |
|         //2) create gateway entry
 | |
|         gatewayVO = new VpcGatewayVO(ipAddress, VpcGateway.Type.Private, vpcId, privateNtwk.getDataCenterId(),
 | |
|                 privateNtwk.getId(), vlan, gateway, netmask, vpc.getAccountId(), vpc.getDomainId());
 | |
|         _vpcGatewayDao.persist(gatewayVO);
 | |
|         
 | |
|         s_logger.debug("Created vpc gateway entry " + gatewayVO);
 | |
|         
 | |
|         txn.commit();
 | |
|         
 | |
|         return getVpcPrivateGateway(gatewayVO.getId());     
 | |
|     }
 | |
| 
 | |
| 
 | |
|     @Override
 | |
|     @DB
 | |
|     public PrivateGateway applyVpcPrivateGateway(Long gatewayId) throws ConcurrentOperationException, ResourceUnavailableException {
 | |
|         VpcGatewayVO vo = _vpcGatewayDao.acquireInLockTable(gatewayId);
 | |
|         if (vo == null) {
 | |
|             throw new ConcurrentOperationException("Unable to lock gateway " + gatewayId);
 | |
|         }
 | |
|         
 | |
|         try {
 | |
|             PrivateGateway gateway = getVpcPrivateGateway(gatewayId);
 | |
|             if (getVpcElement().createPrivateGateway(gateway)) {
 | |
|                 s_logger.debug("Private gateway " + gateway + " was applied succesfully on the backend");
 | |
|                 if (vo.getState() != VpcGateway.State.Ready) {
 | |
|                     vo.setState(VpcGateway.State.Ready);
 | |
|                     _vpcGatewayDao.update(vo.getId(), vo);
 | |
|                     s_logger.debug("Marke gateway " + gateway + " with state " + VpcGateway.State.Ready);
 | |
|                 }
 | |
|                 return getVpcPrivateGateway(gatewayId);
 | |
|             } else {
 | |
|                 s_logger.warn("Private gateway " + gateway + " failed to apply on the backend");
 | |
|                 return null;
 | |
|             }
 | |
|         } finally {
 | |
|             if (vo != null) {
 | |
|                 _vpcGatewayDao.releaseFromLockTable(gatewayId);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     @ActionEvent(eventType = EventTypes.EVENT_PRIVATE_GATEWAY_DELETE, eventDescription = "deleting private gateway")
 | |
|     @DB
 | |
|     public boolean deleteVpcPrivateGateway(Long gatewayId) throws ConcurrentOperationException, ResourceUnavailableException {
 | |
|         VpcGatewayVO gatewayVO = _vpcGatewayDao.acquireInLockTable(gatewayId);
 | |
|         if (gatewayVO == null || gatewayVO.getType() != VpcGateway.Type.Private) {
 | |
|             throw new ConcurrentOperationException("Unable to lock gateway " + gatewayId);
 | |
|         }
 | |
|         
 | |
|         try {
 | |
|             _vpcGatewayDao.update(gatewayVO.getId(), gatewayVO);
 | |
|             s_logger.debug("Marked gateway " + gatewayVO + " with state " + VpcGateway.State.Deleting);
 | |
|             //don't allow to remove gateway when there are static routes associated with it
 | |
|             long routeCount = _staticRouteDao.countRoutesByGateway(gatewayVO.getId());
 | |
|             if (routeCount > 0) {
 | |
|                 throw new CloudRuntimeException("Can't delete private gateway " + gatewayVO + " as it has " + routeCount +
 | |
|                         " static routes applied. Remove the routes first");
 | |
|             }
 | |
|             
 | |
|             gatewayVO.setState(VpcGateway.State.Deleting);
 | |
|             
 | |
|             //1) delete the gateway on the backend
 | |
|             PrivateGateway gateway = getVpcPrivateGateway(gatewayId);
 | |
|             if (getVpcElement().deletePrivateGateway(gateway)) {
 | |
|                 s_logger.debug("Private gateway " + gateway + " was applied succesfully on the backend");
 | |
|             } else {
 | |
|                 s_logger.warn("Private gateway " + gateway + " failed to apply on the backend");
 | |
|                 return false;
 | |
|             }
 | |
|             
 | |
|             //2) Delete private gateway from the DB
 | |
|             return deletePrivateGatewayFromTheDB(gateway);
 | |
|             
 | |
|         } finally {
 | |
|             if (gatewayVO != null) {
 | |
|                 _vpcGatewayDao.releaseFromLockTable(gatewayId);
 | |
|             }
 | |
|         } 
 | |
|     }
 | |
|     
 | |
|     @DB
 | |
|     protected boolean deletePrivateGatewayFromTheDB(PrivateGateway gateway) {
 | |
|         //check if there are ips allocted in the network
 | |
|         long networkId = gateway.getNetworkId();
 | |
|         
 | |
|         boolean deleteNetwork = true;
 | |
|         List<PrivateIpVO> privateIps = _privateIpDao.listByNetworkId(networkId);
 | |
|         if (privateIps.size() > 1 || !privateIps.get(0).getIpAddress().equalsIgnoreCase(gateway.getIp4Address())) {
 | |
|             s_logger.debug("Not removing network id=" + gateway.getNetworkId() + " as it has private ip addresses for other gateways");
 | |
|             deleteNetwork = false;
 | |
|         }
 | |
|         
 | |
|         Transaction txn = Transaction.currentTxn();
 | |
|         txn.start();
 | |
|         
 | |
|         PrivateIpVO ip = _privateIpDao.findByIpAndVpcId(gateway.getVpcId(), gateway.getIp4Address());
 | |
|         if (ip != null) {
 | |
|             _privateIpDao.remove(ip.getId());
 | |
|             s_logger.debug("Deleted private ip " + ip);
 | |
|         }
 | |
|         
 | |
|         if (deleteNetwork) {
 | |
|             User callerUser = _accountMgr.getActiveUser(UserContext.current().getCallerUserId());
 | |
|             Account owner = _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM);
 | |
|             ReservationContext context = new ReservationContextImpl(null, null, callerUser, owner);
 | |
|             _ntwkMgr.destroyNetwork(networkId, context);
 | |
|             s_logger.debug("Deleted private network id=" + networkId);
 | |
|         }
 | |
|         
 | |
|         _vpcGatewayDao.remove(gateway.getId());
 | |
|         s_logger.debug("Deleted private gateway " + gateway);
 | |
|         
 | |
|         txn.commit();
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public List<PrivateGateway> listPrivateGateway(ListPrivateGatewaysCmd cmd) {
 | |
|         String ipAddress = cmd.getIpAddress();
 | |
|         String vlan = cmd.getVlan();
 | |
|         Long vpcId = cmd.getVpcId();
 | |
|         Long id = cmd.getId();
 | |
|         Boolean isRecursive = cmd.isRecursive();
 | |
|         Boolean listAll = cmd.listAll();
 | |
|         Long domainId = cmd.getDomainId();
 | |
|         String accountName = cmd.getAccountName();
 | |
|         Account caller = UserContext.current().getCaller();
 | |
|         List<Long> permittedAccounts = new ArrayList<Long>();
 | |
|         String state = cmd.getState();
 | |
|         
 | |
|         Filter searchFilter = new Filter(VpcGatewayVO.class, "id", false, cmd.getStartIndex(), cmd.getPageSizeVal());
 | |
|         Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, 
 | |
|                 ListProjectResourcesCriteria>(domainId, isRecursive, null);
 | |
|         _accountMgr.buildACLSearchParameters(caller, null, accountName, null, permittedAccounts, domainIdRecursiveListProject,
 | |
|                 listAll, false);
 | |
|         domainId = domainIdRecursiveListProject.first();
 | |
|         isRecursive = domainIdRecursiveListProject.second();
 | |
|         ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third();
 | |
| 
 | |
|         SearchBuilder<VpcGatewayVO> sb = _vpcGatewayDao.createSearchBuilder();
 | |
|         _accountMgr.buildACLSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);
 | |
|         
 | |
|         if (vlan != null) {
 | |
|             SearchBuilder<NetworkVO> ntwkSearch = _ntwkDao.createSearchBuilder();
 | |
|             ntwkSearch.and("vlan", ntwkSearch.entity().getBroadcastUri(), SearchCriteria.Op.EQ);
 | |
|             sb.join("networkSearch", ntwkSearch, sb.entity().getNetworkId(), ntwkSearch.entity().getId(), JoinBuilder.JoinType.INNER);
 | |
|         }
 | |
|         
 | |
|         SearchCriteria<VpcGatewayVO> sc = sb.create();
 | |
|         _accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);  
 | |
|         
 | |
|         if (id != null) {
 | |
|             sc.addAnd("id", Op.EQ, id);
 | |
|         }
 | |
|         
 | |
|         if (ipAddress != null) {
 | |
|             sc.addAnd("ip4Address", Op.EQ, ipAddress);
 | |
|         }
 | |
|         
 | |
|         if (state != null) {
 | |
|             sc.addAnd("state", Op.EQ, state);
 | |
|         }
 | |
|         
 | |
|         if (vpcId != null) {
 | |
|             sc.addAnd("vpcId", Op.EQ, vpcId);
 | |
|         }
 | |
|         
 | |
|         if (vlan != null) {
 | |
|             sc.setJoinParameters("networkSearch", "vlan", BroadcastDomainType.Vlan.toUri(vlan));
 | |
|         }
 | |
|        
 | |
|         List<VpcGatewayVO> vos = _vpcGatewayDao.search(sc, searchFilter);
 | |
|         List<PrivateGateway> privateGtws = new ArrayList<PrivateGateway>(vos.size());
 | |
|         for (VpcGateway vo : vos) {
 | |
|             privateGtws.add(getPrivateGatewayProfile(vo));
 | |
|         }
 | |
|         
 | |
|         return privateGtws;
 | |
|     }
 | |
|     
 | |
|     @Override
 | |
|     public StaticRoute getStaticRoute(long routeId) {
 | |
|         return _staticRouteDao.findById(routeId);
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public boolean applyStaticRoutes(long vpcId) throws ResourceUnavailableException {
 | |
|         Account caller = UserContext.current().getCaller();
 | |
|         List<? extends StaticRoute> routes = _staticRouteDao.listByVpcId(vpcId);
 | |
|         return applyStaticRoutes(routes, caller, true);
 | |
|     }
 | |
| 
 | |
|     protected boolean applyStaticRoutes(List<? extends StaticRoute> routes, Account caller, boolean updateRoutesInDB) throws ResourceUnavailableException {
 | |
|         boolean success = true;
 | |
|         List<StaticRouteProfile> staticRouteProfiles = new ArrayList<StaticRouteProfile>(routes.size());
 | |
|         Map<Long, VpcGateway> gatewayMap = new HashMap<Long, VpcGateway>();
 | |
|         for (StaticRoute route : routes) {
 | |
|             VpcGateway gateway = gatewayMap.get(route.getVpcGatewayId());
 | |
|             if (gateway == null) {
 | |
|                 gateway = _vpcGatewayDao.findById(route.getVpcGatewayId());
 | |
|                 gatewayMap.put(gateway.getId(), gateway);
 | |
|             }
 | |
|             staticRouteProfiles.add(new StaticRouteProfile(route, gateway));
 | |
|         }
 | |
|         if (!applyStaticRoutes(staticRouteProfiles)) {
 | |
|             s_logger.warn("Routes are not completely applied");
 | |
|             return false;
 | |
|         } else {
 | |
|             if (updateRoutesInDB) {
 | |
|                 for (StaticRoute route : routes) {
 | |
|                     if (route.getState() == StaticRoute.State.Revoke) {
 | |
|                         _staticRouteDao.remove(route.getId());
 | |
|                         s_logger.debug("Removed route " + route + " from the DB");
 | |
|                     } else if (route.getState() == StaticRoute.State.Add) {
 | |
|                         StaticRouteVO ruleVO = _staticRouteDao.findById(route.getId());
 | |
|                         ruleVO.setState(StaticRoute.State.Active);
 | |
|                         _staticRouteDao.update(ruleVO.getId(), ruleVO);
 | |
|                         s_logger.debug("Marked route " + route + " with state " + StaticRoute.State.Active);
 | |
|                     }
 | |
|                 }
 | |
|             }            
 | |
|         }
 | |
| 
 | |
|         return success;
 | |
|     }   
 | |
|     
 | |
|     protected boolean applyStaticRoutes(List<StaticRouteProfile> routes) throws ResourceUnavailableException{
 | |
|         if (routes.isEmpty()) {
 | |
|             s_logger.debug("No static routes to apply");
 | |
|             return true;
 | |
|         }
 | |
|         Vpc vpc = getVpc(routes.get(0).getVpcId());
 | |
|         
 | |
|         s_logger.debug("Applying static routes for vpc " + vpc);
 | |
|         if (getVpcElement().applyStaticRoutes(vpc, routes)) {
 | |
|             s_logger.debug("Applied static routes for vpc " + vpc);
 | |
|         } else {
 | |
|             s_logger.warn("Failed to apply static routes for vpc " + vpc);
 | |
|             return false;
 | |
|         }
 | |
|         
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     @ActionEvent(eventType = EventTypes.EVENT_STATIC_ROUTE_DELETE, eventDescription = "deleting static route")
 | |
|     public boolean revokeStaticRoute(long routeId) throws ResourceUnavailableException {
 | |
|         Account caller = UserContext.current().getCaller();
 | |
|         
 | |
|         StaticRouteVO route = _staticRouteDao.findById(routeId);
 | |
|         if (route == null) {
 | |
|             throw new InvalidParameterValueException("Unable to find static route by id");
 | |
|         }
 | |
|         
 | |
|         _accountMgr.checkAccess(caller, null, false, route);
 | |
| 
 | |
|         markStaticRouteForRevoke(route, caller);
 | |
| 
 | |
|         return applyStaticRoutes(route.getVpcId());
 | |
|     }
 | |
|     
 | |
|     @DB
 | |
|     protected boolean revokeStaticRoutesForVpc(long vpcId, Account caller) throws ResourceUnavailableException {
 | |
|         //get all static routes for the vpc
 | |
|         List<StaticRouteVO> routes = _staticRouteDao.listByVpcId(vpcId);
 | |
|         s_logger.debug("Found " + routes.size() + " to revoke for the vpc " + vpcId);
 | |
|         if (!routes.isEmpty()) {
 | |
|             //mark all of them as revoke
 | |
|             Transaction txn = Transaction.currentTxn();
 | |
|             txn.start();
 | |
|             for (StaticRouteVO route : routes) {
 | |
|                 markStaticRouteForRevoke(route, caller);
 | |
|             }
 | |
|             txn.commit();
 | |
|             return applyStaticRoutes(vpcId);
 | |
|         }
 | |
|         
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     @DB
 | |
|     @ActionEvent(eventType = EventTypes.EVENT_STATIC_ROUTE_CREATE, eventDescription = "creating static route", create=true)
 | |
|     public StaticRoute createStaticRoute(long gatewayId, String cidr) throws NetworkRuleConflictException {
 | |
|         Account caller = UserContext.current().getCaller();
 | |
|         
 | |
|         //parameters validation
 | |
|         VpcGateway gateway = _vpcGatewayDao.findById(gatewayId);
 | |
|         if (gateway == null) {
 | |
|             throw new InvalidParameterValueException("Invalid gateway id is given");
 | |
|         }
 | |
|         
 | |
|         if (gateway.getState() != VpcGateway.State.Ready) {
 | |
|             throw new InvalidParameterValueException("Gateway is not in the " + VpcGateway.State.Ready + " state: " + gateway.getState());
 | |
|         }
 | |
|         
 | |
|         Vpc vpc = getActiveVpc(gateway.getVpcId());
 | |
|         if (vpc == null) {
 | |
|             throw new InvalidParameterValueException("Can't add static route to VPC that is being deleted");
 | |
|         }
 | |
|         _accountMgr.checkAccess(caller, null, false, vpc);
 | |
|         
 | |
|         if (!NetUtils.isValidCIDR(cidr)){
 | |
|             throw new InvalidParameterValueException("Invalid format for cidr " + cidr);
 | |
|         }
 | |
|         
 | |
|         //TODO - check cidr for the conflicts
 | |
|         Transaction txn = Transaction.currentTxn();
 | |
|         txn.start();
 | |
|         
 | |
|         StaticRouteVO newRoute = new StaticRouteVO(gateway.getId(), cidr, vpc.getId(), vpc.getAccountId(), vpc.getDomainId());
 | |
|         s_logger.debug("Adding static route " + newRoute);
 | |
|         newRoute = _staticRouteDao.persist(newRoute);
 | |
|         
 | |
|         detectRoutesConflict(newRoute);
 | |
| 
 | |
|         if (!_staticRouteDao.setStateToAdd(newRoute)) {
 | |
|             throw new CloudRuntimeException("Unable to update the state to add for " + newRoute);
 | |
|         }
 | |
|         UserContext.current().setEventDetails("Static route Id: " + newRoute.getId());
 | |
|         
 | |
|         txn.commit();
 | |
| 
 | |
|         return newRoute;
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public List<? extends StaticRoute> listStaticRoutes(ListStaticRoutesCmd cmd) {
 | |
|         Long id = cmd.getId();
 | |
|         Long gatewayId = cmd.getGatewayId();
 | |
|         Long vpcId = cmd.getVpcId();
 | |
|         Long domainId = cmd.getDomainId();
 | |
|         Boolean isRecursive = cmd.isRecursive();
 | |
|         Boolean listAll = cmd.listAll();
 | |
|         String accountName = cmd.getAccountName();
 | |
|         Account caller = UserContext.current().getCaller();
 | |
|         List<Long> permittedAccounts = new ArrayList<Long>();
 | |
|         
 | |
|         Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, 
 | |
|                 ListProjectResourcesCriteria>(domainId, isRecursive, null);
 | |
|         _accountMgr.buildACLSearchParameters(caller, id, accountName, null, permittedAccounts, domainIdRecursiveListProject,
 | |
|                 listAll, false);
 | |
|         domainId = domainIdRecursiveListProject.first();
 | |
|         isRecursive = domainIdRecursiveListProject.second();
 | |
|         ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third();
 | |
|         Filter searchFilter = new Filter(StaticRouteVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
 | |
| 
 | |
|         SearchBuilder<StaticRouteVO> sb = _staticRouteDao.createSearchBuilder();
 | |
|         _accountMgr.buildACLSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);
 | |
| 
 | |
|         sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
 | |
|         sb.and("vpcId", sb.entity().getVpcId(), SearchCriteria.Op.EQ);
 | |
|         sb.and("vpcGatewayId", sb.entity().getVpcGatewayId(), SearchCriteria.Op.EQ);
 | |
|         
 | |
|         SearchCriteria<StaticRouteVO> sc = sb.create();
 | |
|         _accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);  
 | |
|         
 | |
|         if (id != null) {
 | |
|             sc.addAnd("id", Op.EQ, id);
 | |
|         }
 | |
|         
 | |
|         if (vpcId != null) {
 | |
|             sc.addAnd("vpcId", Op.EQ, vpcId);
 | |
|         }
 | |
|         
 | |
|         if (gatewayId != null) {
 | |
|             sc.addAnd("vpcGatewayId", Op.EQ, gatewayId);
 | |
|         }
 | |
|         
 | |
|         return _staticRouteDao.search(sc, searchFilter);
 | |
|     }
 | |
|     
 | |
|     protected void detectRoutesConflict(StaticRoute newRoute) throws NetworkRuleConflictException {
 | |
|         List<? extends StaticRoute> routes = _staticRouteDao.listByGatewayIdAndNotRevoked(newRoute.getVpcGatewayId());
 | |
|         assert (routes.size() >= 1) : "For static routes, we now always first persist the route and then check for " +
 | |
|                 "network conflicts so we should at least have one rule at this point.";
 | |
|         
 | |
|         for (StaticRoute route : routes) {
 | |
|             if (route.getId() == newRoute.getId()) {
 | |
|                 continue; // Skips my own route.
 | |
|             }
 | |
|             
 | |
|             if (NetUtils.isNetworksOverlap(route.getCidr(), newRoute.getCidr())) {
 | |
|                 throw new NetworkRuleConflictException("New static route cidr conflicts with existing route " + route);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     protected void markStaticRouteForRevoke(StaticRouteVO route, Account caller) {
 | |
|         s_logger.debug("Revoking static route " + route);
 | |
|         if (caller != null) {
 | |
|             _accountMgr.checkAccess(caller, null, false, route);
 | |
|         }
 | |
| 
 | |
|         if (route.getState() == StaticRoute.State.Staged) {
 | |
|             if (s_logger.isDebugEnabled()) {
 | |
|                 s_logger.debug("Found a static route that is still in stage state so just removing it: " + route);
 | |
|             }
 | |
|             _staticRouteDao.remove(route.getId());
 | |
|         } else if (route.getState() == StaticRoute.State.Add || route.getState() == StaticRoute.State.Active) {
 | |
|             route.setState(StaticRoute.State.Revoke);
 | |
|             _staticRouteDao.update(route.getId(), route);
 | |
|             s_logger.debug("Marked static route " + route + " with state " + StaticRoute.State.Revoke);
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     protected class VpcCleanupTask implements Runnable {
 | |
|         @Override
 | |
|         public void run() {
 | |
|             try {
 | |
|                 GlobalLock lock = GlobalLock.getInternLock("VpcCleanup");
 | |
|                 if (lock == null) {
 | |
|                     s_logger.debug("Couldn't get the global lock");
 | |
|                     return;
 | |
|                 }
 | |
| 
 | |
|                 if (!lock.lock(30)) {
 | |
|                     s_logger.debug("Couldn't lock the db");
 | |
|                     return;
 | |
|                 }
 | |
| 
 | |
|                 Transaction txn = null;
 | |
|                 try {
 | |
|                     txn = Transaction.open(Transaction.CLOUD_DB);
 | |
| 
 | |
|                     // Cleanup inactive VPCs
 | |
|                     List<VpcVO> inactiveVpcs = _vpcDao.listInactiveVpcs();
 | |
|                     s_logger.info("Found " + inactiveVpcs.size() + " removed VPCs to cleanup");
 | |
|                     for (VpcVO vpc : inactiveVpcs) {
 | |
|                         s_logger.debug("Cleaning up " + vpc);
 | |
|                         destroyVpc(vpc); 
 | |
|                     }
 | |
|                 } catch (Exception e) {
 | |
|                     s_logger.error("Exception ", e);
 | |
|                 } finally {
 | |
|                     if (txn != null) {
 | |
|                         txn.close();
 | |
|                     }
 | |
|                     lock.unlock();
 | |
|                 }
 | |
|             } catch (Exception e) {
 | |
|                 s_logger.error("Exception ", e);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     @Override
 | |
|     public VpcGateway getPrivateGatewayForVpc(long vpcId) {
 | |
|         return _vpcGatewayDao.getPrivateGatewayForVpc(vpcId);
 | |
|     }
 | |
| }
 |