cloudstack/server/src/com/cloud/network/vpc/VpcManagerImpl.java
Alena Prokharchyk 9debd3a5df 1) Added start logic to the VPC
2) VirtualRouterManagerImpl - refactored deployVirtualRouter method
3) Added vpcId to domain_router/user_ip_address tables and corresponding vo objects

Conflicts:

	server/src/com/cloud/network/IPAddressVO.java
2012-06-15 13:56:05 -07:00

647 lines
25 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 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.Network;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.NetworkManager;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.element.NetworkElement;
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.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.exception.CloudRuntimeException;
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;
String _name;
@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> provider = new HashSet<Provider>();
provider.add(Provider.VirtualRouter);
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<Network> getVpcNetworks(long vpcId) {
// TODO Auto-generated method stub
return null;
}
@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<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.VirtualRouter);
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<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 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")
public Vpc createVpc(long zoneId, long vpcOffId, long vpcOwnerId, String vpcName, String displayText, String cidr) {
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;
}
//validate cidr
return createVpc(zoneId, vpcOffId, owner, vpcName, displayText, cidr);
}
@Override
public Vpc createVpc(long zoneId, long vpcOffId, Account vpcOwner, String vpcName, String displayText, String cidr) {
if (!NetUtils.isValidCIDR(cidr)) {
throw new InvalidParameterValueException("Invalid CIDR specified " + cidr);
}
VpcVO vpc = new VpcVO (zoneId, vpcName, displayText, vpcOwner.getId(), vpcOwner.getDomainId(), vpcOffId, cidr);
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) {
UserContext.current().setEventDetails(" Id: " + vpcId);
// Verify vpc id
VpcVO vpc = _vpcDao.findById(vpcId);
if (vpc == null) {
throw new InvalidParameterValueException("unable to find VPC id=" + vpcId);
}
// don't allow to delete vpc if it's in use by existing networks
int networksCount = _ntwkDao.getNetworkCountByVpcId(vpcId);
if (networksCount > 0) {
throw new InvalidParameterValueException("Can't delete VPC " + vpcId + " as its used by " + networksCount + " networks");
}
if (_vpcDao.remove(vpcId)) {
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);
// Verify input parameters
VpcVO vpcToUpdate = _vpcDao.findById(vpcId);
if (vpcToUpdate == null) {
throw new InvalidParameterValueException("Unable to find vpc offering " + vpcId);
}
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) {
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);
// 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);
}
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.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 Vpc 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 = getVpc(vpcId);
if (vpc == null) {
throw new InvalidParameterValueException("Unable to find 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()));
//deploy provider
if (((VpcProvider)_ntwkMgr.getElementImplementingProvider(Provider.VirtualRouter.getName())).startVpc(vpc, dest, context)) {
s_logger.debug("Vpc " + vpc + " has started succesfully");
return getVpc(vpc.getId());
} else {
throw new CloudRuntimeException("Failed to start vpc " + vpc);
//FIXME - add cleanup logic here
}
}
}