blob: aa44f29efcdb4c148d61170c8d9583c48ddc376e [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with 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.
package org.apache.cloudstack.network.router.deployment;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import com.cloud.dc.DataCenter;
import com.cloud.dc.Vlan;
import com.cloud.network.dao.IPAddressVO;
import com.cloud.network.element.NsxProviderVO;
import com.cloud.dc.dao.VlanDao;
import com.cloud.deploy.DataCenterDeployment;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.Network;
import com.cloud.network.PhysicalNetwork;
import com.cloud.network.PhysicalNetworkServiceProvider;
import com.cloud.network.VirtualRouterProvider.Type;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.vpc.Vpc;
import com.cloud.network.vpc.VpcManager;
import com.cloud.network.vpc.dao.VpcDao;
import com.cloud.network.vpc.dao.VpcOfferingDao;
import com.cloud.user.Account;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.VirtualMachineProfile.Param;
public class VpcRouterDeploymentDefinition extends RouterDeploymentDefinition {
protected VpcDao vpcDao;
protected VpcOfferingDao vpcOffDao;
protected PhysicalNetworkDao pNtwkDao;
protected VpcManager vpcMgr;
protected VlanDao vlanDao;
protected Vpc vpc;
protected VpcRouterDeploymentDefinition(final Network guestNetwork, final Vpc vpc, final DeployDestination dest, final Account owner,
final Map<Param, Object> params) {
super(guestNetwork, dest, owner, params);
this.vpc = vpc;
}
@Override
public Vpc getVpc() {
return vpc;
}
@Override
public boolean isVpcRouter() {
return true;
}
@Override
protected void lock() {
final Vpc vpcLock = vpcDao.acquireInLockTable(vpc.getId());
if (vpcLock == null) {
throw new ConcurrentOperationException("Unable to lock vpc " + vpc.getId());
}
tableLockId = vpcLock.getId();
}
@Override
protected void unlock() {
if (tableLockId != null) {
vpcDao.releaseFromLockTable(tableLockId);
if (logger.isDebugEnabled()) {
logger.debug("Lock is released for vpc id " + tableLockId + " as a part of router startup in " + dest);
}
}
}
@Override
protected void checkPreconditions() {
// No preconditions for Vpc
}
@Override
protected List<DeployDestination> findDestinations() {
final List<DeployDestination> destinations = new ArrayList<>();
destinations.add(dest);
return destinations;
}
/**
* @see RouterDeploymentDefinition#prepareDeployment()
*
* @return if the deployment can proceed
*/
@Override
protected boolean prepareDeployment() {
//Check if the VR is the src NAT provider...
isPublicNetwork = vpcMgr.isSrcNatIpRequired(vpc.getVpcOfferingId());
// Check if public network has to be set on VR
return true;
}
@Override
protected void findSourceNatIP() throws InsufficientAddressCapacityException, ConcurrentOperationException {
sourceNatIp = null;
DataCenter zone = dest.getDataCenter();
Long zoneId = null;
if (Objects.nonNull(zone)) {
zoneId = zone.getId();
}
NsxProviderVO nsxProvider = nsxProviderDao.findByZoneId(zoneId);
if (isPublicNetwork) {
if (Objects.isNull(nsxProvider)) {
sourceNatIp = vpcMgr.assignSourceNatIpAddressToVpc(owner, vpc);
} else {
// NSX deploys VRs with Public NIC != to the source NAT, the source NAT IP is on the NSX Public range
sourceNatIp = ipAddrMgr.assignPublicIpAddress(zoneId, getPodId(), owner, Vlan.VlanType.VirtualNetwork, null, null, false, true);
if (vpc != null) {
IPAddressVO routerPublicIp = ipAddressDao.findByIp(sourceNatIp.getAddress().toString());
routerPublicIp.setVpcId(vpc.getId());
routerPublicIp.setSourceNat(true);
ipAddressDao.persist(routerPublicIp);
}
}
}
}
@Override
protected void findOrDeployVirtualRouter() throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
final Vpc vpc = getVpc();
if (vpc != null) {
// This call will associate any existing router to the "routers" attribute.
// It's needed in order to continue with the VMs deployment.
planDeploymentRouters();
if (routers.size() == MAX_NUMBER_OF_ROUTERS) {
// If we have 2 routers already deployed, do nothing and return.
return;
}
}
super.findOrDeployVirtualRouter();
}
@Override
protected void findVirtualProvider() {
final List<? extends PhysicalNetwork> pNtwks = pNtwkDao.listByZone(vpc.getZoneId());
for (final PhysicalNetwork pNtwk : pNtwks) {
final PhysicalNetworkServiceProvider provider = physicalProviderDao.findByServiceProvider(pNtwk.getId(), Type.VPCVirtualRouter.toString());
if (provider == null) {
throw new CloudRuntimeException("Cannot find service provider " + Type.VPCVirtualRouter.toString() + " in physical network " + pNtwk.getId());
}
vrProvider = vrProviderDao.findByNspIdAndType(provider.getId(), Type.VPCVirtualRouter);
if (vrProvider != null) {
break;
}
}
}
@Override
protected void findServiceOfferingId() {
serviceOfferingId = vpcOffDao.findById(vpc.getVpcOfferingId()).getServiceOfferingId();
if (serviceOfferingId == null) {
findAccountServiceOfferingId(vpc.getAccountId());
}
if (serviceOfferingId == null) {
findDefaultServiceOfferingId();
}
}
@Override
protected void deployAllVirtualRouters() throws ConcurrentOperationException, InsufficientCapacityException,
ResourceUnavailableException {
// Implement Redundant Vpc
final int routersToDeploy = getNumberOfRoutersToDeploy();
for(int i = 0; i < routersToDeploy; i++) {
// Don't start the router as we are holding the network lock that needs to be released at the end of router allocation
final DomainRouterVO router = nwHelper.deployRouter(this, false);
if (router != null) {
routers.add(router);
}
}
}
@Override
protected void planDeploymentRouters() {
routers = routerDao.listByVpcId(vpc.getId());
}
@Override
public void generateDeploymentPlan() {
plan = new DataCenterDeployment(dest.getDataCenter().getId());
}
@Override
public boolean isRedundant() {
return vpc.isRedundant();
}
@Override
public boolean isRollingRestart() {
return vpc.isRollingRestart();
}
}