blob: 3eb1d432a8593a1eccd72affd4ef1addf9a7391e [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 com.cloud.network.router;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.apache.cloudstack.network.router.deployment.RouterDeploymentDefinition;
import com.cloud.dc.dao.VlanDao;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.IpAddress;
import com.cloud.network.Network;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.IsolationType;
import com.cloud.network.addr.PublicIp;
import com.cloud.network.dao.IPAddressVO;
import com.cloud.network.vpc.PrivateGateway;
import com.cloud.network.vpc.VpcManager;
import com.cloud.offering.NetworkOffering;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.vm.NicProfile;
public class VpcNetworkHelperImpl extends NetworkHelperImpl {
private static final Logger s_logger = Logger.getLogger(VpcNetworkHelperImpl.class);
@Inject
private VlanDao _vlanDao;
@Inject
protected VpcManager vpcMgr;
@Inject
protected NicProfileHelper nicProfileHelper;
protected String noHypervisorsErrMsgDetails;
@PostConstruct
protected void setupNoHypervisorsErrMsgDetails() {
noHypervisorsErrMsgDetails = StringUtils.join(vpcMgr.getSupportedVpcHypervisors(), ',');
noHypervisorsErrMsgDetails += " are the only supported Hypervisors";
}
@Override
protected String getNoHypervisorsErrMsgDetails() {
return noHypervisorsErrMsgDetails;
}
@Override
protected void filterSupportedHypervisors(final List<HypervisorType> hypervisors) {
hypervisors.retainAll(vpcMgr.getSupportedVpcHypervisors());
}
@Override
public void reallocateRouterNetworks(final RouterDeploymentDefinition vpcRouterDeploymentDefinition, final VirtualRouter router, final VMTemplateVO template, final HypervisorType hType)
throws ConcurrentOperationException, InsufficientCapacityException {
final TreeSet<String> publicVlans = new TreeSet<String>();
if (vpcRouterDeploymentDefinition.isPublicNetwork()) {
publicVlans.add(vpcRouterDeploymentDefinition.getSourceNatIP()
.getVlanTag());
}
//1) allocate nic for control and source nat public ip
final LinkedHashMap<Network, List<? extends NicProfile>> networks = configureDefaultNics(vpcRouterDeploymentDefinition);
final Long vpcId = vpcRouterDeploymentDefinition.getVpc().getId();
//2) allocate nic for private gateways if needed
final List<PrivateGateway> privateGateways = vpcMgr.getVpcPrivateGateways(vpcId);
if (privateGateways != null && !privateGateways.isEmpty()) {
for (final PrivateGateway privateGateway : privateGateways) {
final NicProfile privateNic = nicProfileHelper.createPrivateNicProfileForGateway(privateGateway, router);
final Network privateNetwork = _networkModel.getNetwork(privateGateway.getNetworkId());
networks.put(privateNetwork, new ArrayList<NicProfile>(Arrays.asList(privateNic)));
}
}
//3) allocate nic for guest gateway if needed
final List<? extends Network> guestNetworks = vpcMgr.getVpcNetworks(vpcId);
for (final Network guestNetwork : guestNetworks) {
if (_networkModel.isPrivateGateway(guestNetwork.getId())) {
continue;
}
if (guestNetwork.getState() == Network.State.Implemented || guestNetwork.getState() == Network.State.Setup) {
final NicProfile guestNic = nicProfileHelper.createGuestNicProfileForVpcRouter(vpcRouterDeploymentDefinition, guestNetwork);
networks.put(guestNetwork, new ArrayList<NicProfile>(Arrays.asList(guestNic)));
}
}
//4) allocate nic for additional public network(s)
final List<IPAddressVO> ips = _ipAddressDao.listByAssociatedVpc(vpcId, false);
final List<NicProfile> publicNics = new ArrayList<NicProfile>();
Network publicNetwork = null;
final Map<Network.Service, Set<Network.Provider>> vpcOffSvcProvidersMap = vpcMgr.getVpcOffSvcProvidersMap(vpcRouterDeploymentDefinition.getVpc().getVpcOfferingId());
boolean vpcIsStaticNatProvider = vpcOffSvcProvidersMap.get(Network.Service.StaticNat) != null &&
vpcOffSvcProvidersMap.get(Network.Service.StaticNat).contains(Network.Provider.VPCVirtualRouter);
final ServiceOfferingVO routerOffering = _serviceOfferingDao.findById(vpcRouterDeploymentDefinition.getServiceOfferingId());
for (final IPAddressVO ip : ips) {
if (vpcIsStaticNatProvider || !ip.isOneToOneNat()) {
final PublicIp publicIp = PublicIp.createFromAddrAndVlan(ip, _vlanDao.findById(ip.getVlanId()));
if ((ip.getState() == IpAddress.State.Allocated || ip.getState() == IpAddress.State.Allocating)
&& vpcMgr.isIpAllocatedToVpc(ip)
&& !publicVlans.contains(publicIp.getVlanTag())) {
s_logger.debug("Allocating nic for router in vlan " + publicIp.getVlanTag());
final NicProfile publicNic = new NicProfile();
publicNic.setDefaultNic(false);
publicNic.setIPv4Address(publicIp.getAddress()
.addr());
publicNic.setIPv4Gateway(publicIp.getGateway());
publicNic.setIPv4Netmask(publicIp.getNetmask());
publicNic.setMacAddress(publicIp.getMacAddress());
publicNic.setBroadcastType(BroadcastDomainType.Vlan);
publicNic.setBroadcastUri(BroadcastDomainType.Vlan.toUri(publicIp.getVlanTag()));
publicNic.setIsolationUri(IsolationType.Vlan.toUri(publicIp.getVlanTag()));
final NetworkOffering publicOffering = _networkModel.getSystemAccountNetworkOfferings(NetworkOffering.SystemPublicNetwork)
.get(0);
if (publicNetwork == null) {
final List<? extends Network> publicNetworks = _networkMgr.setupNetwork(s_systemAccount, publicOffering, vpcRouterDeploymentDefinition.getPlan(), null, null, false);
publicNetwork = publicNetworks.get(0);
}
publicNics.add(publicNic);
publicVlans.add(publicIp.getVlanTag());
}
}
}
if (publicNetwork != null) {
if (networks.get(publicNetwork) != null) {
@SuppressWarnings("unchecked")
final List<NicProfile> publicNicProfiles = (List<NicProfile>)networks.get(publicNetwork);
publicNicProfiles.addAll(publicNics);
networks.put(publicNetwork, publicNicProfiles);
} else {
networks.put(publicNetwork, publicNics);
}
}
_itMgr.allocate(router.getInstanceName(), template, routerOffering, networks, vpcRouterDeploymentDefinition.getPlan(), hType);
}
@Override
public LinkedHashMap<Network, List<? extends NicProfile>> configureDefaultNics(final RouterDeploymentDefinition routerDeploymentDefinition) throws ConcurrentOperationException, InsufficientAddressCapacityException {
final LinkedHashMap<Network, List<? extends NicProfile>> networks = new LinkedHashMap<Network, List<? extends NicProfile>>(3);
// 1) Control network
final LinkedHashMap<Network, List<? extends NicProfile>> controlNic = configureControlNic(routerDeploymentDefinition);
networks.putAll(controlNic);
// 2) Public network
final LinkedHashMap<Network, List<? extends NicProfile>> publicNic = configurePublicNic(routerDeploymentDefinition, false);
networks.putAll(publicNic);
// 3) Guest Network
final LinkedHashMap<Network, List<? extends NicProfile>> guestNic = configureGuestNic(routerDeploymentDefinition);
networks.putAll(guestNic);
return networks;
}
}