// 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 javax.ejb.Local; import javax.naming.ConfigurationException; import org.apache.log4j.Logger; 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.PermissionDeniedException; 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.dao.IPAddressDao; import com.cloud.network.dao.NetworkDao; import com.cloud.network.element.VpcProvider; import com.cloud.network.vpc.VpcOffering.State; import com.cloud.network.vpc.Dao.VpcDao; import com.cloud.network.vpc.Dao.VpcOfferingDao; import com.cloud.network.vpc.Dao.VpcOfferingServiceMapDao; import com.cloud.offering.NetworkOffering; 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.Ternary; import com.cloud.utils.component.Inject; import com.cloud.utils.component.Manager; import com.cloud.utils.db.DB; import com.cloud.utils.db.Filter; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; import com.cloud.utils.net.NetUtils; import com.cloud.vm.ReservationContext; import com.cloud.vm.ReservationContextImpl; /** * @author Alena Prokharchyk */ @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; private VpcProvider vpcElement = null; String _name; @Override @DB public boolean configure(String name, Map 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> svcProviderMap = new HashMap>(); Set provider = new HashSet(); provider.add(Provider.VPCVirtualRouter); for (Service svc : getSupportedServices()) { svcProviderMap.put(svc, provider); } createVpcOffering(VpcOffering.defaultVPCOfferingName, VpcOffering.defaultVPCOfferingName, svcProviderMap, true, State.Enabled); } txn.commit(); return true; } @Override public boolean start() { return true; } @Override public boolean stop() { return true; } @Override public String getName() { return _name; } @Override public List 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") public VpcOffering createVpcOffering(String name, String displayText, List supportedServices) { Map> svcProviderMap = new HashMap>(); Set defaultProviders = new HashSet(); 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 (!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 firewall service to the list of VPC services"); svcProviderMap.put(Service.Firewall, defaultProviders); } svcProviderMap.put(Service.Gateway, defaultProviders); return createVpcOffering(name, displayText, svcProviderMap, false, null); } @Override @DB public VpcOffering createVpcOffering(String name, String displayText, Map> 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 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.findById(vpcId); } @Override public Map> getVpcOffSvcProvidersMap(long vpcOffId) { Map> serviceProviderMap = new HashMap>(); List map = _vpcOffSvcMapDao.listByVpcOffId(vpcOffId); for (VpcOfferingServiceMapVO instance : map) { String service = instance.getService(); Set providers; providers = serviceProviderMap.get(service); if (providers == null) { providers = new HashSet(); } providers.add(Provider.getProvider(instance.getProvider())); serviceProviderMap.put(Service.getService(service), providers); } return serviceProviderMap; } @Override public List listVpcOfferings(Long id, String name, String displayText, List supportedServicesStr, Boolean isDefault, String keyword, String state, Long startIndex, Long pageSizeVal) { Filter searchFilter = new Filter(VpcOfferingVO.class, "created", false, startIndex, pageSizeVal); SearchCriteria sc = _vpcOffDao.createSearchCriteria(); if (keyword != null) { SearchCriteria 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 offerings = _vpcOffDao.search(sc, searchFilter); // filter by supported services boolean listBySupportedServices = (supportedServicesStr != null && !supportedServicesStr.isEmpty() && !offerings.isEmpty()); if (listBySupportedServices) { List supportedOfferings = new ArrayList(); 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") 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) { //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 \"-\""); } 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.Disabled + " as a part of vpc delete"); VpcVO vpcVO = _vpcDao.findById(vpc.getId()); vpcVO.setState(Vpc.State.Disabled); _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; } if (_vpcDao.remove(vpc.getId())) { 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 listVpcs(Long id, String vpcName, String displayText, List 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 permittedAccounts = new ArrayList(); Ternary domainIdRecursiveListProject = new Ternary(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 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); // now set the SC criteria... SearchCriteria sc = sb.create(); _accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); if (keyword != null) { SearchCriteria 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 (restartRequired != null) { sc.addAnd("restartRequired", SearchCriteria.Op.EQ, restartRequired); } List vpcs = _vpcDao.search(sc, searchFilter); // filter by supported services boolean listBySupportedServices = (supportedServicesStr != null && !supportedServicesStr.isEmpty() && !vpcs.isEmpty()); if (listBySupportedServices) { List supportedVpcs = new ArrayList(); 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 getSupportedServices() { List services = new ArrayList(); services.add(Network.Service.Dhcp); services.add(Network.Service.Dns); services.add(Network.Service.UserData); services.add(Network.Service.Firewall); 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) 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) { throw new InvalidParameterValueException("Unable to find Enabled vpc by id " + vpcId); } //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) { 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) throws ConcurrentOperationException { Vpc locked = _vpcDao.acquireInLockTable(vpc.getId()); if (locked == null) { throw new ConcurrentOperationException("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 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) 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"); } //6) Only VPC VR can be a provider for the network offering List 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"); } } 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 getVpcsForAccount(long accountId) { return _vpcDao.listByAccountId(accountId); } public boolean cleanupVpcResources(long vpcId, Account caller, long callerUserId) { s_logger.debug("Cleaning up resources for vpc id=" + vpcId); boolean success = true; // release all ip addresses List 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.releasePublicIpAddress(ipToRelease.getId(), callerUserId, caller); if (!success) { s_logger.warn("Failed to cleanup ip " + ipToRelease + " as a part of vpc id=" + vpcId + " 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 VpcVO vpc = _vpcDao.findById(vpcId); if (vpc == null) { throw new InvalidParameterValueException("Unable to find vpc offering " + vpcId); } _accountMgr.checkAccess(caller, null, false, vpc); s_logger.debug("Restarting VPC " + vpc); boolean restartRequired = false; try { s_logger.debug("Shuttign 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)) { 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); vpc.setRestartRequired(restartRequired); _vpcDao.update(vpc.getId(), vpc); } } }