cloudstack/server/src/com/cloud/network/NetworkModelImpl.java
Nicolas Vazquez 13c325aad4 CLOUDSTACK-10102: New network type L2 (#2281)
This feature allows CloudStack administrators to create layer 2 networks on CloudStack. As these networks are purely layer 2, they don't require IP addresses or Virtual Router, only VLAN is necessary (provided by administrator or assigned by CloudStack). Also, network services should be handled externally, e.g. DNS, DHCP, as they are not provided by L2 networks.
As a consequence, a new Guest Network type is created within CloudStack: L2

Description:
Network offerings and networks support new guest type: L2.
L2 Network offering creation allows administrator to select Specify VLAN or let CloudStack assign it dynamically.
L2 Network creation allows administrator to specify VLAN tag (if network offerings allows it) or simply create network.
VM deployments on L2 networks:
VMs should not IP addresses or any network service
No Virtual Router deployed on network
If Specify VLAN = true for network offering, network gets implemented using a dynamically assigned VLAN
UI changes

A new button is added on Networks tab, available for admins, to allow L2 networks creation
2017-12-20 17:07:39 +05:30

2407 lines
102 KiB
Java

// 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;
import java.math.BigInteger;
import java.security.InvalidParameterException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.Collections;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDao;
import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import com.cloud.api.ApiDBUtils;
import com.cloud.configuration.Config;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.dc.DataCenter;
import com.cloud.dc.PodVlanMapVO;
import com.cloud.dc.Vlan;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.PodVlanMapDao;
import com.cloud.dc.dao.VlanDao;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.UnsupportedServiceException;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.IpAddress.State;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.GuestType;
import com.cloud.network.Network.IpAddresses;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.addr.PublicIp;
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.IPAddressVO;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkDomainDao;
import com.cloud.network.dao.NetworkDomainVO;
import com.cloud.network.dao.NetworkServiceMapDao;
import com.cloud.network.dao.NetworkServiceMapVO;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao;
import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO;
import com.cloud.network.dao.PhysicalNetworkVO;
import com.cloud.network.dao.UserIpv6AddressDao;
import com.cloud.network.element.IpDeployer;
import com.cloud.network.element.IpDeployingRequester;
import com.cloud.network.element.NetworkElement;
import com.cloud.network.element.UserDataServiceProvider;
import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.network.rules.FirewallRuleVO;
import com.cloud.network.rules.dao.PortForwardingRulesDao;
import com.cloud.network.vpc.dao.PrivateIpDao;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.NetworkOffering.Detail;
import com.cloud.offerings.NetworkOfferingServiceMapVO;
import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.offerings.dao.NetworkOfferingDetailsDao;
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
import com.cloud.projects.dao.ProjectAccountDao;
import com.cloud.server.ConfigurationServer;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.DomainManager;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.StringUtils;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.EntityManager;
import com.cloud.utils.db.JoinBuilder;
import com.cloud.utils.db.JoinBuilder.JoinType;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.Nic;
import com.cloud.vm.NicProfile;
import com.cloud.vm.NicVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.Type;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.NicSecondaryIpDao;
import com.cloud.vm.dao.VMInstanceDao;
public class NetworkModelImpl extends ManagerBase implements NetworkModel, Configurable {
static final Logger s_logger = Logger.getLogger(NetworkModelImpl.class);
@Inject
EntityManager _entityMgr;
@Inject
DataCenterDao _dcDao = null;
@Inject
VlanDao _vlanDao = null;
@Inject
IPAddressDao _ipAddressDao = null;
@Inject
AccountDao _accountDao = null;
@Inject
DomainDao _domainDao = null;
@Inject
AccountManager _accountMgr;
@Inject
ConfigurationDao _configDao;
@Inject
ConfigurationManager _configMgr;
@Inject
NetworkOfferingDao _networkOfferingDao = null;
@Inject
NetworkDao _networksDao = null;
@Inject
NicDao _nicDao = null;
@Inject
PodVlanMapDao _podVlanMapDao;
@Inject
ConfigurationServer _configServer;
List<NetworkElement> networkElements;
public List<NetworkElement> getNetworkElements() {
return networkElements;
}
public void setNetworkElements(List<NetworkElement> networkElements) {
this.networkElements = networkElements;
}
@Inject
NetworkDomainDao _networkDomainDao;
@Inject
VMInstanceDao _vmDao;
@Inject
FirewallRulesDao _firewallDao;
@Inject
DomainManager _domainMgr;
@Inject
NetworkOfferingServiceMapDao _ntwkOfferingSrvcDao;
@Inject
PhysicalNetworkDao _physicalNetworkDao;
@Inject
PhysicalNetworkServiceProviderDao _pNSPDao;
@Inject
PortForwardingRulesDao _portForwardingRulesDao;
@Inject
PhysicalNetworkTrafficTypeDao _pNTrafficTypeDao;
@Inject
NetworkServiceMapDao _ntwkSrvcDao;
@Inject
PrivateIpDao _privateIpDao;
@Inject
UserIpv6AddressDao _ipv6Dao;
@Inject
NicSecondaryIpDao _nicSecondaryIpDao;
@Inject
ApplicationLoadBalancerRuleDao _appLbRuleDao;
@Inject
private ProjectAccountDao _projectAccountDao;
@Inject
NetworkOfferingDetailsDao _ntwkOffDetailsDao;
private final HashMap<String, NetworkOfferingVO> _systemNetworks = new HashMap<String, NetworkOfferingVO>(5);
static Long s_privateOfferingId = null;
SearchBuilder<IPAddressVO> IpAddressSearch;
SearchBuilder<NicVO> NicForTrafficTypeSearch;
private boolean _allowSubdomainNetworkAccess;
private Map<String, String> _configs;
protected boolean _executeInSequenceNtwkElmtCmd;
HashMap<Long, Long> _lastNetworkIdsToFree = new HashMap<Long, Long>();
static HashMap<Service, List<Provider>> s_serviceToImplementedProvidersMap = new HashMap<Service, List<Provider>>();
static HashMap<String, String> s_providerToNetworkElementMap = new HashMap<String, String>();
/**
*
*/
public NetworkModelImpl() {
super();
}
@Override
public NetworkElement getElementImplementingProvider(String providerName) {
String elementName = s_providerToNetworkElementMap.get(providerName);
NetworkElement element = AdapterBase.getAdapterByName(networkElements, elementName);
return element;
}
@Override
public List<Service> getElementServices(Provider provider) {
NetworkElement element = getElementImplementingProvider(provider.getName());
if (element == null) {
throw new InvalidParameterValueException("Unable to find the Network Element implementing the Service Provider '" + provider.getName() + "'");
}
return new ArrayList<Service>(element.getCapabilities().keySet());
}
@Override
public boolean canElementEnableIndividualServices(Provider provider) {
NetworkElement element = getElementImplementingProvider(provider.getName());
if (element == null) {
throw new InvalidParameterValueException("Unable to find the Network Element implementing the Service Provider '" + provider.getName() + "'");
}
return element.canEnableIndividualServices();
}
Set<Purpose> getPublicIpPurposeInRules(PublicIpAddress ip, boolean includeRevoked, boolean includingFirewall) {
Set<Purpose> result = new HashSet<Purpose>();
List<FirewallRuleVO> rules = null;
if (includeRevoked) {
rules = _firewallDao.listByIp(ip.getId());
} else {
rules = _firewallDao.listByIpAndNotRevoked(ip.getId());
}
if (rules == null || rules.isEmpty()) {
return null;
}
for (FirewallRuleVO rule : rules) {
if (rule.getPurpose() != Purpose.Firewall || includingFirewall) {
result.add(rule.getPurpose());
}
}
return result;
}
@Override
public Map<PublicIpAddress, Set<Service>> getIpToServices(List<? extends PublicIpAddress> publicIps, boolean postApplyRules, boolean includingFirewall) {
Map<PublicIpAddress, Set<Service>> ipToServices = new HashMap<PublicIpAddress, Set<Service>>();
if (publicIps != null && !publicIps.isEmpty()) {
Set<Long> networkSNAT = new HashSet<Long>();
for (PublicIpAddress ip : publicIps) {
Set<Service> services = ipToServices.get(ip);
if (services == null) {
services = new HashSet<Service>();
}
if (ip.isSourceNat()) {
if (!networkSNAT.contains(ip.getAssociatedWithNetworkId())) {
services.add(Service.SourceNat);
networkSNAT.add(ip.getAssociatedWithNetworkId());
} else {
CloudRuntimeException ex = new CloudRuntimeException("Multiple generic soure NAT IPs provided for network");
// see the IPAddressVO.java class.
IPAddressVO ipAddr = ApiDBUtils.findIpAddressById(ip.getAssociatedWithNetworkId());
String ipAddrUuid = ip.getAssociatedWithNetworkId().toString();
if (ipAddr != null) {
ipAddrUuid = ipAddr.getUuid();
}
ex.addProxyObject(ipAddrUuid, "networkId");
throw ex;
}
}
ipToServices.put(ip, services);
// if IP in allocating state then it will not have any rules attached so skip IPAssoc to network service
// provider
if (ip.getState() == State.Allocating) {
continue;
}
// check if any active rules are applied on the public IP
Set<Purpose> purposes = getPublicIpPurposeInRules(ip, false, includingFirewall);
// Firewall rules didn't cover static NAT
if (ip.isOneToOneNat() && ip.getAssociatedWithVmId() != null) {
if (purposes == null) {
purposes = new HashSet<Purpose>();
}
purposes.add(Purpose.StaticNat);
}
if (purposes == null || purposes.isEmpty()) {
// since no active rules are there check if any rules are applied on the public IP but are in
// revoking state
purposes = getPublicIpPurposeInRules(ip, true, includingFirewall);
if (ip.isOneToOneNat()) {
if (purposes == null) {
purposes = new HashSet<Purpose>();
}
purposes.add(Purpose.StaticNat);
}
if (purposes == null || purposes.isEmpty()) {
// IP is not being used for any purpose so skip IPAssoc to network service provider
continue;
} else {
if (postApplyRules) {
// no active rules/revoked rules are associated with this public IP, so remove the
// association with the provider
if (ip.isSourceNat()) {
s_logger.debug("Not releasing ip " + ip.getAddress().addr() + " as it is in use for SourceNat");
} else {
ip.setState(State.Releasing);
}
} else {
if (ip.getState() == State.Releasing) {
// rules are not revoked yet, so don't let the network service provider revoke the IP
// association
// mark IP is allocated so that IP association will not be removed from the provider
ip.setState(State.Allocated);
}
}
}
}
if (purposes.contains(Purpose.StaticNat)) {
services.add(Service.StaticNat);
}
if (purposes.contains(Purpose.LoadBalancing)) {
services.add(Service.Lb);
}
if (purposes.contains(Purpose.PortForwarding)) {
services.add(Service.PortForwarding);
}
if (purposes.contains(Purpose.Vpn)) {
services.add(Service.Vpn);
}
if (purposes.contains(Purpose.Firewall)) {
services.add(Service.Firewall);
}
if (services.isEmpty()) {
continue;
}
ipToServices.put(ip, services);
}
}
return ipToServices;
}
public boolean canIpUsedForNonConserveService(PublicIp ip, Service service) {
// If it's non-conserve mode, then the new ip should not be used by any other services
List<PublicIpAddress> ipList = new ArrayList<PublicIpAddress>();
ipList.add(ip);
Map<PublicIpAddress, Set<Service>> ipToServices = getIpToServices(ipList, false, false);
Set<Service> services = ipToServices.get(ip);
// Not used currently, safe
if (services == null || services.isEmpty()) {
return true;
}
// Since it's non-conserve mode, only one service should used for IP
if (services.size() != 1) {
throw new InvalidParameterException("There are multiple services used ip " + ip.getAddress() + ".");
}
if (service != null && !((Service)services.toArray()[0] == service || service.equals(Service.Firewall))) {
throw new InvalidParameterException("The IP " + ip.getAddress() + " is already used as " + ((Service)services.toArray()[0]).getName() + " rather than " +
service.getName());
}
return true;
}
Map<Service, Set<Provider>> getServiceProvidersMap(long networkId) {
Map<Service, Set<Provider>> map = new HashMap<Service, Set<Provider>>();
List<NetworkServiceMapVO> nsms = _ntwkSrvcDao.getServicesInNetwork(networkId);
for (NetworkServiceMapVO nsm : nsms) {
Set<Provider> providers = map.get(Service.getService(nsm.getService()));
if (providers == null) {
providers = new HashSet<Provider>();
}
providers.add(Provider.getProvider(nsm.getProvider()));
map.put(Service.getService(nsm.getService()), providers);
}
return map;
}
public boolean canIpUsedForService(PublicIp publicIp, Service service, Long networkId) {
List<PublicIpAddress> ipList = new ArrayList<PublicIpAddress>();
ipList.add(publicIp);
Map<PublicIpAddress, Set<Service>> ipToServices = getIpToServices(ipList, false, true);
Set<Service> services = ipToServices.get(publicIp);
if (services == null || services.isEmpty()) {
return true;
}
if (networkId == null) {
networkId = publicIp.getAssociatedWithNetworkId();
}
// We only support one provider for one service now
Map<Service, Set<Provider>> serviceToProviders = getServiceProvidersMap(networkId);
// Since IP already has service to bind with, the oldProvider can't be null
Set<Provider> newProviders = serviceToProviders.get(service);
if (newProviders == null || newProviders.isEmpty()) {
throw new InvalidParameterException("There is no new provider for IP " + publicIp.getAddress() + " of service " + service.getName() + "!");
}
Provider newProvider = (Provider)newProviders.toArray()[0];
Set<Provider> oldProviders = serviceToProviders.get(services.toArray()[0]);
Provider oldProvider = (Provider)oldProviders.toArray()[0];
Network network = _networksDao.findById(networkId);
NetworkElement oldElement = getElementImplementingProvider(oldProvider.getName());
NetworkElement newElement = getElementImplementingProvider(newProvider.getName());
if (oldElement instanceof IpDeployingRequester && newElement instanceof IpDeployingRequester) {
IpDeployer oldIpDeployer = ((IpDeployingRequester)oldElement).getIpDeployer(network);
IpDeployer newIpDeployer = ((IpDeployingRequester)newElement).getIpDeployer(network);
// FIXME: I ignored this check
} else {
throw new InvalidParameterException("Ip cannot be applied for new provider!");
}
return true;
}
Map<Provider, Set<Service>> getProviderServicesMap(long networkId) {
Map<Provider, Set<Service>> map = new HashMap<Provider, Set<Service>>();
List<NetworkServiceMapVO> nsms = _ntwkSrvcDao.getServicesInNetwork(networkId);
for (NetworkServiceMapVO nsm : nsms) {
Set<Service> services = map.get(Provider.getProvider(nsm.getProvider()));
if (services == null) {
services = new HashSet<Service>();
}
services.add(Service.getService(nsm.getService()));
map.put(Provider.getProvider(nsm.getProvider()), services);
}
return map;
}
@Override
public Map<Provider, ArrayList<PublicIpAddress>> getProviderToIpList(Network network, Map<PublicIpAddress, Set<Service>> ipToServices) {
NetworkOffering offering = _networkOfferingDao.findById(network.getNetworkOfferingId());
if (!offering.isConserveMode()) {
for (PublicIpAddress ip : ipToServices.keySet()) {
Set<Service> services = new HashSet<Service>();
services.addAll(ipToServices.get(ip));
if (services != null && services.contains(Service.Firewall)) {
services.remove(Service.Firewall);
}
if (services != null && services.size() > 1) {
throw new CloudRuntimeException("Ip " + ip.getAddress() + " is used by multiple services!");
}
}
}
Map<Service, Set<PublicIpAddress>> serviceToIps = new HashMap<Service, Set<PublicIpAddress>>();
for (PublicIpAddress ip : ipToServices.keySet()) {
for (Service service : ipToServices.get(ip)) {
Set<PublicIpAddress> ips = serviceToIps.get(service);
if (ips == null) {
ips = new HashSet<PublicIpAddress>();
}
ips.add(ip);
serviceToIps.put(service, ips);
}
}
// TODO Check different provider for same IP
Map<Provider, Set<Service>> providerToServices = getProviderServicesMap(network.getId());
Map<Provider, ArrayList<PublicIpAddress>> providerToIpList = new HashMap<Provider, ArrayList<PublicIpAddress>>();
for (Provider provider : providerToServices.keySet()) {
if (!(getElementImplementingProvider(provider.getName()) instanceof IpDeployingRequester)) {
continue;
}
Set<Service> services = providerToServices.get(provider);
ArrayList<PublicIpAddress> ipList = new ArrayList<PublicIpAddress>();
Set<PublicIpAddress> ipSet = new HashSet<PublicIpAddress>();
for (Service service : services) {
Set<PublicIpAddress> serviceIps = serviceToIps.get(service);
if (serviceIps == null || serviceIps.isEmpty()) {
continue;
}
ipSet.addAll(serviceIps);
}
Set<PublicIpAddress> sourceNatIps = serviceToIps.get(Service.SourceNat);
if (sourceNatIps != null && !sourceNatIps.isEmpty()) {
ipList.addAll(0, sourceNatIps);
ipSet.removeAll(sourceNatIps);
}
ipList.addAll(ipSet);
providerToIpList.put(provider, ipList);
}
return providerToIpList;
}
@Override
public List<IPAddressVO> listPublicIpsAssignedToGuestNtwk(long accountId, long associatedNetworkId, Boolean sourceNat) {
SearchCriteria<IPAddressVO> sc = IpAddressSearch.create();
sc.setParameters("accountId", accountId);
sc.setParameters("associatedWithNetworkId", associatedNetworkId);
if (sourceNat != null) {
sc.addAnd("sourceNat", SearchCriteria.Op.EQ, sourceNat);
}
sc.setJoinParameters("virtualNetworkVlanSB", "vlanType", VlanType.VirtualNetwork);
return _ipAddressDao.search(sc, null);
}
@Override
public List<IPAddressVO> listPublicIpsAssignedToGuestNtwk(long associatedNetworkId, Boolean sourceNat) {
SearchCriteria<IPAddressVO> sc = IpAddressSearch.create();
sc.setParameters("associatedWithNetworkId", associatedNetworkId);
if (sourceNat != null) {
sc.addAnd("sourceNat", SearchCriteria.Op.EQ, sourceNat);
}
sc.setJoinParameters("virtualNetworkVlanSB", "vlanType", VlanType.VirtualNetwork);
return _ipAddressDao.search(sc, null);
}
@Override
public List<IPAddressVO> listPublicIpsAssignedToAccount(long accountId, long dcId, Boolean sourceNat) {
SearchCriteria<IPAddressVO> sc = IpAddressSearch.create();
sc.setParameters("accountId", accountId);
sc.setParameters("dataCenterId", dcId);
if (sourceNat != null) {
sc.addAnd("sourceNat", SearchCriteria.Op.EQ, sourceNat);
}
sc.setJoinParameters("virtualNetworkVlanSB", "vlanType", VlanType.VirtualNetwork);
return _ipAddressDao.search(sc, null);
}
@Override
public List<? extends Nic> getNics(long vmId) {
return _nicDao.listByVmId(vmId);
}
@Override
public String getNextAvailableMacAddressInNetwork(long networkId) throws InsufficientAddressCapacityException {
NetworkVO network = _networksDao.findById(networkId);
String mac = _networksDao.getNextAvailableMacAddress(networkId, MACIdentifier.value());
if (mac == null) {
throw new InsufficientAddressCapacityException("Unable to create another mac address", Network.class, networkId);
}
return mac;
}
@Override
@DB
public Network getNetwork(long id) {
return _networksDao.findById(id);
}
@Override
public boolean canUseForDeploy(Network network) {
if (network.getTrafficType() != TrafficType.Guest) {
return false;
}
if (listNetworkOfferingServices(network.getNetworkOfferingId()).isEmpty()) {
return true; // do not check free IPs if there is no service in the network
}
boolean hasFreeIps = true;
if (network.getGuestType() == GuestType.Shared) {
if (network.getGateway() != null) {
hasFreeIps = _ipAddressDao.countFreeIPsInNetwork(network.getId()) > 0;
}
if (!hasFreeIps) {
return false;
}
if (network.getIp6Gateway() != null) {
hasFreeIps = isIP6AddressAvailableInNetwork(network.getId());
}
} else {
if (network.getCidr() == null) {
s_logger.debug("Network - " + network.getId() + " has NULL CIDR.");
return false;
}
hasFreeIps = (getAvailableIps(network, null)).size() > 0;
}
return hasFreeIps;
}
@Override
public boolean isIP6AddressAvailableInNetwork(long networkId) {
Network network = _networksDao.findById(networkId);
if (network == null) {
return false;
}
if (network.getIp6Gateway() == null) {
return false;
}
List<VlanVO> vlans = _vlanDao.listVlansByNetworkId(networkId);
for (Vlan vlan : vlans) {
if (isIP6AddressAvailableInVlan(vlan.getId())) {
return true;
}
}
return false;
}
@Override
public boolean isIP6AddressAvailableInVlan(long vlanId) {
VlanVO vlan = _vlanDao.findById(vlanId);
if (vlan.getIp6Range() == null) {
return false;
}
long existedCount = _ipv6Dao.countExistedIpsInVlan(vlanId);
BigInteger existedInt = BigInteger.valueOf(existedCount);
BigInteger rangeInt = NetUtils.countIp6InRange(vlan.getIp6Range());
return (existedInt.compareTo(rangeInt) < 0);
}
@Override
public Map<Service, Map<Capability, String>> getNetworkCapabilities(long networkId) {
Map<Service, Map<Capability, String>> networkCapabilities = new HashMap<Service, Map<Capability, String>>();
// list all services of this networkOffering
List<NetworkServiceMapVO> servicesMap = _ntwkSrvcDao.getServicesInNetwork(networkId);
for (NetworkServiceMapVO instance : servicesMap) {
Service service = Service.getService(instance.getService());
NetworkElement element = getElementImplementingProvider(instance.getProvider());
if (element != null) {
Map<Service, Map<Capability, String>> elementCapabilities = element.getCapabilities();
if (elementCapabilities != null) {
networkCapabilities.put(service, elementCapabilities.get(service));
}
}
}
return networkCapabilities;
}
@Override
public Map<Capability, String> getNetworkServiceCapabilities(long networkId, Service service) {
if (!areServicesSupportedInNetwork(networkId, service)) {
// TBD: networkId to uuid. No VO object being passed. So we will need to call
// addProxyObject with hardcoded tablename. Or we should probably look up the correct dao proxy object.
throw new UnsupportedServiceException("Service " + service.getName() + " is not supported in the network id=" + networkId);
}
Map<Capability, String> serviceCapabilities = new HashMap<Capability, String>();
// get the Provider for this Service for this offering
String provider = _ntwkSrvcDao.getProviderForServiceInNetwork(networkId, service);
NetworkElement element = getElementImplementingProvider(provider);
if (element != null) {
Map<Service, Map<Capability, String>> elementCapabilities = element.getCapabilities();
;
if (elementCapabilities == null || !elementCapabilities.containsKey(service)) {
throw new UnsupportedServiceException("Service " + service.getName() + " is not supported by the element=" + element.getName() +
" implementing Provider=" + provider);
}
serviceCapabilities = elementCapabilities.get(service);
}
return serviceCapabilities;
}
@Override
public Map<Capability, String> getNetworkOfferingServiceCapabilities(NetworkOffering offering, Service service) {
if (!areServicesSupportedByNetworkOffering(offering.getId(), service)) {
// TBD: We should be sending networkOfferingId and not the offering object itself.
throw new UnsupportedServiceException("Service " + service.getName() + " is not supported by the network offering " + offering);
}
Map<Capability, String> serviceCapabilities = new HashMap<Capability, String>();
// get the Provider for this Service for this offering
List<String> providers = _ntwkOfferingSrvcDao.listProvidersForServiceForNetworkOffering(offering.getId(), service);
if (providers.isEmpty()) {
// TBD: We should be sending networkOfferingId and not the offering object itself.
throw new InvalidParameterValueException("Service " + service.getName() + " is not supported by the network offering " + offering);
}
// FIXME - in post 3.0 we are going to support multiple providers for the same service per network offering, so
// we have to calculate capabilities for all of them
String provider = providers.get(0);
// FIXME we return the capabilities of the first provider of the service - what if we have multiple providers
// for same Service?
NetworkElement element = getElementImplementingProvider(provider);
if (element != null) {
Map<Service, Map<Capability, String>> elementCapabilities = element.getCapabilities();
;
if (elementCapabilities == null || !elementCapabilities.containsKey(service)) {
// TBD: We should be sending providerId and not the offering object itself.
throw new UnsupportedServiceException("Service " + service.getName() + " is not supported by the element=" + element.getName() +
" implementing Provider=" + provider);
}
serviceCapabilities = elementCapabilities.get(service);
}
return serviceCapabilities;
}
@Override
public NetworkVO getSystemNetworkByZoneAndTrafficType(long zoneId, TrafficType trafficType) {
// find system public network offering
Long networkOfferingId = null;
List<NetworkOfferingVO> offerings = _networkOfferingDao.listSystemNetworkOfferings();
for (NetworkOfferingVO offering : offerings) {
if (offering.getTrafficType() == trafficType) {
networkOfferingId = offering.getId();
break;
}
}
if (networkOfferingId == null) {
throw new InvalidParameterValueException("Unable to find system network offering with traffic type " + trafficType);
}
List<NetworkVO> networks = _networksDao.listBy(Account.ACCOUNT_ID_SYSTEM, networkOfferingId, zoneId);
if (networks == null || networks.isEmpty()) {
// TBD: send uuid instead of zoneId. Hardcode tablename in call to addProxyObject().
throw new InvalidParameterValueException("Unable to find network with traffic type " + trafficType + " in zone " + zoneId);
}
return networks.get(0);
}
@Override
public NetworkVO getNetworkWithSGWithFreeIPs(Long zoneId) {
List<NetworkVO> networks = _networksDao.listByZoneSecurityGroup(zoneId);
if (networks == null || networks.isEmpty()) {
return null;
}
NetworkVO ret_network = null;
for (NetworkVO nw : networks) {
List<VlanVO> vlans = _vlanDao.listVlansByNetworkId(nw.getId());
for (VlanVO vlan : vlans) {
if (_ipAddressDao.countFreeIpsInVlan(vlan.getId()) > 0) {
ret_network = nw;
break;
}
}
if (ret_network != null) {
break;
}
}
if (ret_network == null) {
s_logger.debug("Can not find network with security group enabled with free IPs");
}
return ret_network;
}
@Override
public NetworkVO getNetworkWithSecurityGroupEnabled(Long zoneId) {
List<NetworkVO> networks = _networksDao.listByZoneSecurityGroup(zoneId);
if (networks == null || networks.isEmpty()) {
return null;
}
if (networks.size() > 1) {
s_logger.debug("There are multiple network with security group enabled? select one of them...");
}
return networks.get(0);
}
@Override
public PublicIpAddress getPublicIpAddress(long ipAddressId) {
IPAddressVO addr = _ipAddressDao.findById(ipAddressId);
if (addr == null) {
return null;
}
return PublicIp.createFromAddrAndVlan(addr, _vlanDao.findById(addr.getVlanId()));
}
@Override
public List<VlanVO> listPodVlans(long podId) {
List<VlanVO> vlans = _vlanDao.listVlansForPodByType(podId, VlanType.DirectAttached);
return vlans;
}
@Override
public List<NetworkVO> listNetworksUsedByVm(long vmId, boolean isSystem) {
List<NetworkVO> networks = new ArrayList<NetworkVO>();
List<NicVO> nics = _nicDao.listByVmId(vmId);
if (nics != null) {
for (Nic nic : nics) {
NetworkVO network = _networksDao.findByIdIncludingRemoved(nic.getNetworkId());
if (isNetworkSystem(network) == isSystem) {
networks.add(network);
}
}
}
return networks;
}
@Override
public Nic getNicInNetwork(long vmId, long networkId) {
return _nicDao.findByNtwkIdAndInstanceId(networkId, vmId);
}
@Override
public String getIpInNetwork(long vmId, long networkId) {
Nic guestNic = getNicInNetwork(vmId, networkId);
assert (guestNic != null && guestNic.getIPv4Address() != null) : "Vm doesn't belong to network associated with " + "ipAddress or ip4 address is null";
return guestNic.getIPv4Address();
}
@Override
public String getIpInNetworkIncludingRemoved(long vmId, long networkId) {
Nic guestNic = getNicInNetworkIncludingRemoved(vmId, networkId);
assert (guestNic != null && guestNic.getIPv4Address() != null) : "Vm doesn't belong to network associated with " + "ipAddress or ip4 address is null";
return guestNic.getIPv4Address();
}
@Override
public List<NicVO> getNicsForTraffic(long vmId, TrafficType type) {
SearchCriteria<NicVO> sc = NicForTrafficTypeSearch.create();
sc.setParameters("instance", vmId);
sc.setJoinParameters("network", "traffictype", type);
return _nicDao.search(sc, null);
}
@Override
public IpAddress getIp(long ipAddressId) {
return _ipAddressDao.findById(ipAddressId);
}
@Override
public Network getDefaultNetworkForVm(long vmId) {
Nic defaultNic = getDefaultNic(vmId);
if (defaultNic == null) {
return null;
} else {
return _networksDao.findById(defaultNic.getNetworkId());
}
}
@Override
public Nic getDefaultNic(long vmId) {
List<NicVO> nics = _nicDao.listByVmId(vmId);
Nic defaultNic = null;
if (nics != null) {
for (Nic nic : nics) {
if (nic.isDefaultNic()) {
defaultNic = nic;
break;
}
}
} else {
s_logger.debug("Unable to find default network for the vm; vm doesn't have any nics");
return null;
}
if (defaultNic == null) {
s_logger.debug("Unable to find default network for the vm; vm doesn't have default nic");
}
return defaultNic;
}
@Override
public UserDataServiceProvider getUserDataUpdateProvider(Network network) {
String userDataProvider = _ntwkSrvcDao.getProviderForServiceInNetwork(network.getId(), Service.UserData);
if (userDataProvider == null) {
s_logger.debug("Network " + network + " doesn't support service " + Service.UserData.getName());
return null;
}
return (UserDataServiceProvider)getElementImplementingProvider(userDataProvider);
}
@Override
public boolean isSharedNetworkWithoutServices (long networkId) {
Network network = _networksDao.findById(networkId);
if (network != null && network.getGuestType() != GuestType.Shared) {
return false;
}
List<Service> services = listNetworkOfferingServices(network.getNetworkOfferingId());
if (services == null || services.isEmpty()) {
return true;
}
return false;
}
@Override
public boolean areServicesSupportedByNetworkOffering(long networkOfferingId, Service... services) {
return (_ntwkOfferingSrvcDao.areServicesSupportedByNetworkOffering(networkOfferingId, services));
}
@Override
public boolean areServicesSupportedInNetwork(long networkId, Service... services) {
return (_ntwkSrvcDao.areServicesSupportedInNetwork(networkId, services));
}
@Override
public String getIpOfNetworkElementInVirtualNetwork(long accountId, long dataCenterId) {
List<NetworkVO> virtualNetworks = _networksDao.listByZoneAndGuestType(accountId, dataCenterId, Network.GuestType.Isolated, false);
if (virtualNetworks.isEmpty()) {
s_logger.trace("Unable to find default Virtual network account id=" + accountId);
return null;
}
NetworkVO virtualNetwork = virtualNetworks.get(0);
NicVO networkElementNic = _nicDao.findByNetworkIdAndType(virtualNetwork.getId(), Type.DomainRouter);
if (networkElementNic != null) {
return networkElementNic.getIPv4Address();
} else {
s_logger.warn("Unable to set find network element for the network id=" + virtualNetwork.getId());
return null;
}
}
@Override
public List<NetworkVO> listNetworksForAccount(long accountId, long zoneId, Network.GuestType type) {
List<NetworkVO> accountNetworks = new ArrayList<NetworkVO>();
List<NetworkVO> zoneNetworks = _networksDao.listByZone(zoneId);
for (NetworkVO network : zoneNetworks) {
if (!isNetworkSystem(network)) {
if (network.getGuestType() == Network.GuestType.Shared || !_networksDao.listBy(accountId, network.getId()).isEmpty()) {
if (type == null || type == network.getGuestType()) {
accountNetworks.add(network);
}
}
}
}
return accountNetworks;
}
@Override
public List<NetworkVO> listAllNetworksInAllZonesByType(Network.GuestType type) {
List<NetworkVO> networks = new ArrayList<NetworkVO>();
for (NetworkVO network : _networksDao.listAll()) {
if (!isNetworkSystem(network)) {
networks.add(network);
}
}
return networks;
}
@Override
public Long getDedicatedNetworkDomain(long networkId) {
NetworkDomainVO networkMaps = _networkDomainDao.getDomainNetworkMapByNetworkId(networkId);
if (networkMaps != null) {
return networkMaps.getDomainId();
} else {
return null;
}
}
@Override
public Integer getNetworkRate(long networkId, Long vmId) {
VMInstanceVO vm = null;
if (vmId != null) {
vm = _vmDao.findById(vmId);
}
Network network = getNetwork(networkId);
NetworkOffering ntwkOff = _entityMgr.findById(NetworkOffering.class, network.getNetworkOfferingId());
// For default userVm Default network and domR guest/public network, get rate information from the service
// offering; for other situations get information
// from the network offering
boolean isUserVmsDefaultNetwork = false;
boolean isDomRGuestOrPublicNetwork = false;
boolean isSystemVmNetwork = false;
if (vm != null) {
Nic nic = _nicDao.findByNtwkIdAndInstanceId(networkId, vmId);
if (vm.getType() == Type.User && nic != null && nic.isDefaultNic()) {
isUserVmsDefaultNetwork = true;
} else if (vm.getType() == Type.DomainRouter && ntwkOff != null &&
(ntwkOff.getTrafficType() == TrafficType.Public || ntwkOff.getTrafficType() == TrafficType.Guest)) {
isDomRGuestOrPublicNetwork = true;
} else if (vm.getType() == Type.ConsoleProxy || vm.getType() == Type.SecondaryStorageVm) {
isSystemVmNetwork = true;
}
}
if (isUserVmsDefaultNetwork || isDomRGuestOrPublicNetwork) {
return _configMgr.getServiceOfferingNetworkRate(vm.getServiceOfferingId(), network.getDataCenterId());
} else if (isSystemVmNetwork) {
return -1;
} else {
return _configMgr.getNetworkOfferingNetworkRate(ntwkOff.getId(), network.getDataCenterId());
}
}
@Override
public String getAccountNetworkDomain(long accountId, long zoneId) {
String networkDomain = _accountDao.findById(accountId).getNetworkDomain();
if (networkDomain == null) {
// get domain level network domain
return getDomainNetworkDomain(_accountDao.findById(accountId).getDomainId(), zoneId);
}
return networkDomain;
}
@Override
public String getStartIpAddress(long networkId) {
List<VlanVO> vlans = _vlanDao.listVlansByNetworkId(networkId);
if (vlans.isEmpty()) {
return null;
}
String startIP = vlans.get(0).getIpRange().split("-")[0];
for (VlanVO vlan : vlans) {
String startIP1 = vlan.getIpRange().split("-")[0];
long startIPLong = NetUtils.ip2Long(startIP);
long startIPLong1 = NetUtils.ip2Long(startIP1);
if (startIPLong1 < startIPLong) {
startIP = startIP1;
}
}
return startIP;
}
@Override
public Long getPodIdForVlan(long vlanDbId) {
PodVlanMapVO podVlanMaps = _podVlanMapDao.listPodVlanMapsByVlan(vlanDbId);
if (podVlanMaps == null) {
return null;
} else {
return podVlanMaps.getPodId();
}
}
@Override
public Map<Service, Set<Provider>> getNetworkOfferingServiceProvidersMap(long networkOfferingId) {
Map<Service, Set<Provider>> serviceProviderMap = new HashMap<Service, Set<Provider>>();
List<NetworkOfferingServiceMapVO> map = _ntwkOfferingSrvcDao.listByNetworkOfferingId(networkOfferingId);
for (NetworkOfferingServiceMapVO instance : map) {
String service = instance.getService();
Set<Provider> providers;
providers = serviceProviderMap.get(Service.getService(service));
if (providers == null) {
providers = new HashSet<Provider>();
}
providers.add(Provider.getProvider(instance.getProvider()));
serviceProviderMap.put(Service.getService(service), providers);
}
return serviceProviderMap;
}
@Override
public boolean isProviderSupportServiceInNetwork(long networkId, Service service, Provider provider) {
return _ntwkSrvcDao.canProviderSupportServiceInNetwork(networkId, service, provider);
}
@Override
public List<? extends Provider> listSupportedNetworkServiceProviders(String serviceName) {
Network.Service service = null;
if (serviceName != null) {
service = Network.Service.getService(serviceName);
if (service == null) {
throw new InvalidParameterValueException("Invalid Network Service=" + serviceName);
}
}
Set<Provider> supportedProviders = new HashSet<Provider>();
if (service != null) {
List<Provider> providers = s_serviceToImplementedProvidersMap.get(service);
if (providers != null && !providers.isEmpty()) {
supportedProviders.addAll(providers);
}
} else {
for (List<Provider> pList : s_serviceToImplementedProvidersMap.values()) {
supportedProviders.addAll(pList);
}
}
return new ArrayList<Provider>(supportedProviders);
}
@Override
public Provider getDefaultUniqueProviderForService(String serviceName) {
List<? extends Provider> providers = listSupportedNetworkServiceProviders(serviceName);
if (providers.isEmpty()) {
throw new CloudRuntimeException("No providers supporting service " + serviceName + " found in cloudStack");
}
if (providers.size() > 1) {
throw new CloudRuntimeException("More than 1 provider supporting service " + serviceName + " found in cloudStack");
}
return providers.get(0);
}
@Override
public long findPhysicalNetworkId(long zoneId, String tag, TrafficType trafficType) {
List<PhysicalNetworkVO> pNtwks = new ArrayList<PhysicalNetworkVO>();
if (trafficType != null) {
pNtwks = _physicalNetworkDao.listByZoneAndTrafficType(zoneId, trafficType);
} else {
pNtwks = _physicalNetworkDao.listByZone(zoneId);
}
if (pNtwks.isEmpty()) {
throw new InvalidParameterValueException("Unable to find physical network in zone id=" + zoneId);
}
if (pNtwks.size() > 1) {
if (tag == null) {
throw new InvalidParameterValueException("More than one physical networks exist in zone id=" + zoneId +
" and no tags are specified in order to make a choice");
}
Long pNtwkId = null;
for (PhysicalNetwork pNtwk : pNtwks) {
if (pNtwk.getTags().contains(tag)) {
s_logger.debug("Found physical network id=" + pNtwk.getId() + " based on requested tags " + tag);
pNtwkId = pNtwk.getId();
break;
}
}
if (pNtwkId == null) {
throw new InvalidParameterValueException("Unable to find physical network which match the tags " + tag);
}
return pNtwkId;
} else {
return pNtwks.get(0).getId();
}
}
@Override
public List<Long> listNetworkOfferingsForUpgrade(long networkId) {
List<Long> offeringsToReturn = new ArrayList<Long>();
NetworkOffering originalOffering = _entityMgr.findById(NetworkOffering.class, getNetwork(networkId).getNetworkOfferingId());
boolean securityGroupSupportedByOriginalOff = areServicesSupportedByNetworkOffering(originalOffering.getId(), Service.SecurityGroup);
// security group supported property should be the same
List<Long> offerings = _networkOfferingDao.getOfferingIdsToUpgradeFrom(originalOffering);
for (Long offeringId : offerings) {
if (areServicesSupportedByNetworkOffering(offeringId, Service.SecurityGroup) == securityGroupSupportedByOriginalOff) {
offeringsToReturn.add(offeringId);
}
}
return offeringsToReturn;
}
@Override
public boolean isSecurityGroupSupportedInNetwork(Network network) {
if (network.getTrafficType() != TrafficType.Guest) {
s_logger.trace("Security group can be enabled for Guest networks only; and network " + network + " has a diff traffic type");
return false;
}
Long physicalNetworkId = network.getPhysicalNetworkId();
// physical network id can be null in Guest Network in Basic zone, so locate the physical network
if (physicalNetworkId == null) {
physicalNetworkId = findPhysicalNetworkId(network.getDataCenterId(), null, null);
}
return isServiceEnabledInNetwork(physicalNetworkId, network.getId(), Service.SecurityGroup);
}
@Override
public PhysicalNetwork getDefaultPhysicalNetworkByZoneAndTrafficType(long zoneId, TrafficType trafficType) {
List<PhysicalNetworkVO> networkList = _physicalNetworkDao.listByZoneAndTrafficType(zoneId, trafficType);
DataCenter dc = ApiDBUtils.findZoneById(zoneId);
String dcUuid = String.valueOf(zoneId);
if (dc != null) {
dcUuid = dc.getUuid();
}
if (networkList.isEmpty()) {
InvalidParameterValueException ex =
new InvalidParameterValueException("Unable to find the default physical network with traffic=" + trafficType + " in the specified zone id");
ex.addProxyObject(dcUuid, "zoneId");
throw ex;
}
if (networkList.size() > 1) {
InvalidParameterValueException ex =
new InvalidParameterValueException("More than one physical networks exist in zone id=" + zoneId + " with traffic type=" + trafficType);
ex.addProxyObject(dcUuid, "zoneId");
throw ex;
}
return networkList.get(0);
}
@Override
public String getDefaultManagementTrafficLabel(long zoneId, HypervisorType hypervisorType) {
try {
PhysicalNetwork mgmtPhyNetwork = getDefaultPhysicalNetworkByZoneAndTrafficType(zoneId, TrafficType.Management);
PhysicalNetworkTrafficTypeVO mgmtTraffic = _pNTrafficTypeDao.findBy(mgmtPhyNetwork.getId(), TrafficType.Management);
if (mgmtTraffic != null) {
String label = null;
switch (hypervisorType) {
case XenServer:
label = mgmtTraffic.getXenNetworkLabel();
break;
case KVM:
label = mgmtTraffic.getKvmNetworkLabel();
break;
case VMware:
label = mgmtTraffic.getVmwareNetworkLabel();
break;
case Hyperv:
label = mgmtTraffic.getHypervNetworkLabel();
break;
case Ovm3:
label = mgmtTraffic.getOvm3NetworkLabel();
break;
}
return label;
}
} catch (Exception ex) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Failed to retrive the default label for management traffic:" + "zone: " + zoneId + " hypervisor: " + hypervisorType + " due to:" +
ex.getMessage());
}
}
return null;
}
@Override
public String getDefaultStorageTrafficLabel(long zoneId, HypervisorType hypervisorType) {
try {
PhysicalNetwork storagePhyNetwork = getDefaultPhysicalNetworkByZoneAndTrafficType(zoneId, TrafficType.Storage);
PhysicalNetworkTrafficTypeVO storageTraffic = _pNTrafficTypeDao.findBy(storagePhyNetwork.getId(), TrafficType.Storage);
if (storageTraffic != null) {
String label = null;
switch (hypervisorType) {
case XenServer:
label = storageTraffic.getXenNetworkLabel();
break;
case KVM:
label = storageTraffic.getKvmNetworkLabel();
break;
case VMware:
label = storageTraffic.getVmwareNetworkLabel();
break;
case Hyperv:
label = storageTraffic.getHypervNetworkLabel();
break;
case Ovm3:
label = storageTraffic.getOvm3NetworkLabel();
break;
}
return label;
}
} catch (Exception ex) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Failed to retrive the default label for storage traffic:" + "zone: " + zoneId + " hypervisor: " + hypervisorType + " due to:" +
ex.getMessage());
}
}
return null;
}
@Override
public List<PhysicalNetworkSetupInfo> getPhysicalNetworkInfo(long dcId, HypervisorType hypervisorType) {
List<PhysicalNetworkSetupInfo> networkInfoList = new ArrayList<PhysicalNetworkSetupInfo>();
List<PhysicalNetworkVO> physicalNtwkList = _physicalNetworkDao.listByZone(dcId);
for (PhysicalNetworkVO pNtwk : physicalNtwkList) {
String publicName = _pNTrafficTypeDao.getNetworkTag(pNtwk.getId(), TrafficType.Public, hypervisorType);
String privateName = _pNTrafficTypeDao.getNetworkTag(pNtwk.getId(), TrafficType.Management, hypervisorType);
String guestName = _pNTrafficTypeDao.getNetworkTag(pNtwk.getId(), TrafficType.Guest, hypervisorType);
String storageName = _pNTrafficTypeDao.getNetworkTag(pNtwk.getId(), TrafficType.Storage, hypervisorType);
// String controlName = _pNTrafficTypeDao.getNetworkTag(pNtwk.getId(), TrafficType.Control, hypervisorType);
PhysicalNetworkSetupInfo info = new PhysicalNetworkSetupInfo();
info.setPhysicalNetworkId(pNtwk.getId());
info.setGuestNetworkName(guestName);
info.setPrivateNetworkName(privateName);
info.setPublicNetworkName(publicName);
info.setStorageNetworkName(storageName);
PhysicalNetworkTrafficTypeVO mgmtTraffic = _pNTrafficTypeDao.findBy(pNtwk.getId(), TrafficType.Management);
if (mgmtTraffic != null) {
String vlan = mgmtTraffic.getVlan();
info.setMgmtVlan(vlan);
}
networkInfoList.add(info);
}
return networkInfoList;
}
@Override
public boolean isProviderEnabledInPhysicalNetwork(long physicalNetowrkId, String providerName) {
PhysicalNetworkServiceProviderVO ntwkSvcProvider = _pNSPDao.findByServiceProvider(physicalNetowrkId, providerName);
if (ntwkSvcProvider == null) {
s_logger.warn("Unable to find provider " + providerName + " in physical network id=" + physicalNetowrkId);
return false;
}
return isProviderEnabled(ntwkSvcProvider);
}
@Override
public boolean isProviderEnabledInZone(long zoneId, String provider) {
//the provider has to be enabled at least in one network in the zone
for (PhysicalNetwork pNtwk : _physicalNetworkDao.listByZone(zoneId)) {
if (isProviderEnabledInPhysicalNetwork(pNtwk.getId(), provider)) {
return true;
}
}
return false;
}
@Override
public String getNetworkTag(HypervisorType hType, Network network) {
// no network tag for control traffic type
TrafficType effectiveTrafficType = network.getTrafficType();
if (hType == HypervisorType.VMware && effectiveTrafficType == TrafficType.Control)
effectiveTrafficType = TrafficType.Management;
if (effectiveTrafficType == TrafficType.Control) {
return null;
}
Long physicalNetworkId = null;
if (effectiveTrafficType != TrafficType.Guest) {
physicalNetworkId = getNonGuestNetworkPhysicalNetworkId(network, effectiveTrafficType);
} else {
NetworkOffering offering = _entityMgr.findById(NetworkOffering.class, network.getNetworkOfferingId());
physicalNetworkId = network.getPhysicalNetworkId();
if (physicalNetworkId == null) {
physicalNetworkId = findPhysicalNetworkId(network.getDataCenterId(), offering.getTags(), offering.getTrafficType());
}
}
if (physicalNetworkId == null) {
assert (false) : "Can't get the physical network";
s_logger.warn("Can't get the physical network");
return null;
}
return _pNTrafficTypeDao.getNetworkTag(physicalNetworkId, effectiveTrafficType, hType);
}
@Override
public NetworkVO getExclusiveGuestNetwork(long zoneId) {
List<NetworkVO> networks = _networksDao.listBy(Account.ACCOUNT_ID_SYSTEM, zoneId, GuestType.Shared, TrafficType.Guest);
if (networks == null || networks.isEmpty()) {
throw new InvalidParameterValueException("Unable to find network with trafficType " + TrafficType.Guest + " and guestType " + GuestType.Shared + " in zone " +
zoneId);
}
if (networks.size() > 1) {
throw new InvalidParameterValueException("Found more than 1 network with trafficType " + TrafficType.Guest + " and guestType " + GuestType.Shared +
" in zone " + zoneId);
}
return networks.get(0);
}
@Override
public boolean isNetworkSystem(Network network) {
NetworkOffering no = _networkOfferingDao.findByIdIncludingRemoved(network.getNetworkOfferingId());
if (no.isSystemOnly()) {
return true;
} else {
return false;
}
}
@Override
public Long getPhysicalNetworkId(Network network) {
if (network.getTrafficType() != TrafficType.Guest) {
return getNonGuestNetworkPhysicalNetworkId(network);
}
Long physicalNetworkId = network.getPhysicalNetworkId();
NetworkOffering offering = _entityMgr.findById(NetworkOffering.class, network.getNetworkOfferingId());
if (physicalNetworkId == null) {
physicalNetworkId = findPhysicalNetworkId(network.getDataCenterId(), offering.getTags(), offering.getTrafficType());
}
return physicalNetworkId;
}
@Override
public boolean getAllowSubdomainAccessGlobal() {
return _allowSubdomainNetworkAccess;
}
@Override
public boolean isProviderForNetwork(Provider provider, long networkId) {
if (_ntwkSrvcDao.isProviderForNetwork(networkId, provider) != null) {
return true;
} else {
return false;
}
}
@Override
public boolean isProviderForNetworkOffering(Provider provider, long networkOfferingId) {
if (_ntwkOfferingSrvcDao.isProviderForNetworkOffering(networkOfferingId, provider)) {
return true;
} else {
return false;
}
}
@Override
public void canProviderSupportServices(Map<Provider, Set<Service>> providersMap) {
for (Provider provider : providersMap.keySet()) {
// check if services can be turned off
NetworkElement element = getElementImplementingProvider(provider.getName());
if (element == null) {
throw new InvalidParameterValueException("Unable to find the Network Element implementing the Service Provider '" + provider.getName() + "'");
}
Set<Service> enabledServices = new HashSet<Service>();
enabledServices.addAll(providersMap.get(provider));
if (enabledServices != null && !enabledServices.isEmpty()) {
if (!element.canEnableIndividualServices()) {
Set<Service> requiredServices = new HashSet<Service>();
requiredServices.addAll(element.getCapabilities().keySet());
if (requiredServices.contains(Network.Service.Gateway)) {
requiredServices.remove(Network.Service.Gateway);
}
if (requiredServices.contains(Network.Service.Firewall)) {
requiredServices.remove(Network.Service.Firewall);
}
if (enabledServices.contains(Network.Service.Firewall)) {
enabledServices.remove(Network.Service.Firewall);
}
// exclude gateway service
if (enabledServices.size() != requiredServices.size()) {
StringBuilder servicesSet = new StringBuilder();
for (Service requiredService : requiredServices) {
// skip gateway service as we don't allow setting it via API
if (requiredService == Service.Gateway) {
continue;
}
servicesSet.append(requiredService.getName() + ", ");
}
servicesSet.delete(servicesSet.toString().length() - 2, servicesSet.toString().length());
throw new InvalidParameterValueException("Cannot enable subset of Services, Please specify the complete list of Services: " +
servicesSet.toString() + " for Service Provider " + provider.getName());
}
}
List<String> serviceList = new ArrayList<String>();
for (Service service : enabledServices) {
// check if the service is provided by this Provider
if (!element.getCapabilities().containsKey(service)) {
throw new UnsupportedServiceException(provider.getName() + " Provider cannot provide service " + service.getName());
}
serviceList.add(service.getName());
}
if (!element.verifyServicesCombination(enabledServices)) {
throw new UnsupportedServiceException("Provider " + provider.getName() + " doesn't support services combination: " + serviceList);
}
}
}
}
@Override
public boolean canAddDefaultSecurityGroup() {
String defaultAdding = _configDao.getValue(Config.SecurityGroupDefaultAdding.key());
return (defaultAdding != null && defaultAdding.equalsIgnoreCase("true"));
}
@Override
public List<Service> listNetworkOfferingServices(long networkOfferingId) {
List<Service> services = new ArrayList<Service>();
List<String> servicesStr = _ntwkOfferingSrvcDao.listServicesForNetworkOffering(networkOfferingId);
for (String serviceStr : servicesStr) {
services.add(Service.getService(serviceStr));
}
return services;
}
@Override
public boolean areServicesEnabledInZone(long zoneId, NetworkOffering offering, List<Service> services) {
long physicalNtwkId = findPhysicalNetworkId(zoneId, offering.getTags(), offering.getTrafficType());
boolean result = true;
List<String> checkedProvider = new ArrayList<String>();
for (Service service : services) {
// get all the providers, and check if each provider is enabled
List<String> providerNames = _ntwkOfferingSrvcDao.listProvidersForServiceForNetworkOffering(offering.getId(), service);
for (String providerName : providerNames) {
if (!checkedProvider.contains(providerName)) {
result = result && isProviderEnabledInPhysicalNetwork(physicalNtwkId, providerName);
}
}
}
return result;
}
@Override
public boolean checkIpForService(IpAddress userIp, Service service, Long networkId) {
if (networkId == null) {
networkId = userIp.getAssociatedWithNetworkId();
}
NetworkVO network = _networksDao.findById(networkId);
NetworkOfferingVO offering = _networkOfferingDao.findById(network.getNetworkOfferingId());
if (offering.getGuestType() != GuestType.Isolated) {
return true;
}
IPAddressVO ipVO = _ipAddressDao.findById(userIp.getId());
PublicIp publicIp = PublicIp.createFromAddrAndVlan(ipVO, _vlanDao.findById(userIp.getVlanId()));
if (!canIpUsedForService(publicIp, service, networkId)) {
return false;
}
if (!offering.isConserveMode()) {
return canIpUsedForNonConserveService(publicIp, service);
}
return true;
}
@Override
public boolean providerSupportsCapability(Set<Provider> providers, Service service, Capability cap) {
for (Provider provider : providers) {
NetworkElement element = getElementImplementingProvider(provider.getName());
if (element != null) {
Map<Service, Map<Capability, String>> elementCapabilities = element.getCapabilities();
if (elementCapabilities == null || !elementCapabilities.containsKey(service)) {
throw new UnsupportedServiceException("Service " + service.getName() + " is not supported by the element=" + element.getName() +
" implementing Provider=" + provider.getName());
}
Map<Capability, String> serviceCapabilities = elementCapabilities.get(service);
if (serviceCapabilities == null || serviceCapabilities.isEmpty()) {
throw new UnsupportedServiceException("Service " + service.getName() + " doesn't have capabilites for element=" + element.getName() +
" implementing Provider=" + provider.getName());
}
if (serviceCapabilities.containsKey(cap)) {
return true;
}
} else {
throw new UnsupportedServiceException("Unable to find network element for provider " + provider.getName());
}
}
return false;
}
@Override
public void checkCapabilityForProvider(Set<Provider> providers, Service service, Capability cap, String capValue) {
for (Provider provider : providers) {
NetworkElement element = getElementImplementingProvider(provider.getName());
if (element != null) {
Map<Service, Map<Capability, String>> elementCapabilities = element.getCapabilities();
if (elementCapabilities == null || !elementCapabilities.containsKey(service)) {
throw new UnsupportedServiceException("Service " + service.getName() + " is not supported by the element=" + element.getName() +
" implementing Provider=" + provider.getName());
}
Map<Capability, String> serviceCapabilities = elementCapabilities.get(service);
if (serviceCapabilities == null || serviceCapabilities.isEmpty()) {
throw new UnsupportedServiceException("Service " + service.getName() + " doesn't have capabilities for element=" + element.getName() +
" implementing Provider=" + provider.getName());
}
String value = serviceCapabilities.get(cap);
if (value == null || value.isEmpty()) {
throw new UnsupportedServiceException("Service " + service.getName() + " doesn't have capability " + cap.getName() + " for element=" +
element.getName() + " implementing Provider=" + provider.getName());
}
if (!value.toLowerCase().contains(capValue.toLowerCase())) {
throw new UnsupportedServiceException("Service " + service.getName() + " doesn't support value " + capValue + " for capability " + cap.getName() +
" for element=" + element.getName() + " implementing Provider=" + provider.getName());
}
} else {
throw new UnsupportedServiceException("Unable to find network element for provider " + provider.getName());
}
}
}
@Override
public void checkNetworkPermissions(Account owner, Network network) {
// dahn 20140310: I was thinking of making this an assert but
// as we hardly ever test with asserts I think
// we better make sure at runtime.
if (network == null) {
throw new CloudRuntimeException("cannot check permissions on (Network) <null>");
}
// Perform account permission check
if (network.getGuestType() != Network.GuestType.Shared || (network.getGuestType() == Network.GuestType.Shared && network.getAclType() == ACLType.Account)) {
AccountVO networkOwner = _accountDao.findById(network.getAccountId());
if (networkOwner == null)
throw new PermissionDeniedException("Unable to use network with id= " + ((NetworkVO)network).getUuid() +
", network does not have an owner");
if (owner.getType() != Account.ACCOUNT_TYPE_PROJECT && networkOwner.getType() == Account.ACCOUNT_TYPE_PROJECT) {
if (!_projectAccountDao.canAccessProjectAccount(owner.getAccountId(), network.getAccountId())) {
throw new PermissionDeniedException("Unable to use network with id= " + ((NetworkVO)network).getUuid() +
", permission denied");
}
} else {
List<NetworkVO> networkMap = _networksDao.listBy(owner.getId(), network.getId());
if (networkMap == null || networkMap.isEmpty()) {
throw new PermissionDeniedException("Unable to use network with id= " + ((NetworkVO)network).getUuid() +
", permission denied");
}
}
} else {
if (!isNetworkAvailableInDomain(network.getId(), owner.getDomainId())) {
DomainVO ownerDomain = _domainDao.findById(owner.getDomainId());
if (ownerDomain == null) {
throw new CloudRuntimeException("cannot check permission on account " + owner.getAccountName() + " whose domain does not exist");
}
throw new PermissionDeniedException("Shared network id=" + ((NetworkVO)network).getUuid() + " is not available in domain id=" +
ownerDomain.getUuid());
}
}
}
@Override
public String getDefaultPublicTrafficLabel(long dcId, HypervisorType hypervisorType) {
try {
PhysicalNetwork publicPhyNetwork = getOnePhysicalNetworkByZoneAndTrafficType(dcId, TrafficType.Public);
PhysicalNetworkTrafficTypeVO publicTraffic = _pNTrafficTypeDao.findBy(publicPhyNetwork.getId(), TrafficType.Public);
if (publicTraffic != null) {
String label = null;
switch (hypervisorType) {
case XenServer:
label = publicTraffic.getXenNetworkLabel();
break;
case KVM:
label = publicTraffic.getKvmNetworkLabel();
break;
case VMware:
label = publicTraffic.getVmwareNetworkLabel();
break;
case Hyperv:
label = publicTraffic.getHypervNetworkLabel();
break;
case Ovm3:
label = publicTraffic.getOvm3NetworkLabel();
break;
}
return label;
}
} catch (Exception ex) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Failed to retrieve the default label for public traffic." + "zone: " + dcId + " hypervisor: " + hypervisorType + " due to: " +
ex.getMessage());
}
}
return null;
}
@Override
public String getDefaultGuestTrafficLabel(long dcId, HypervisorType hypervisorType) {
try {
PhysicalNetwork guestPhyNetwork = getOnePhysicalNetworkByZoneAndTrafficType(dcId, TrafficType.Guest);
PhysicalNetworkTrafficTypeVO guestTraffic = _pNTrafficTypeDao.findBy(guestPhyNetwork.getId(), TrafficType.Guest);
if (guestTraffic != null) {
String label = null;
switch (hypervisorType) {
case XenServer:
label = guestTraffic.getXenNetworkLabel();
break;
case KVM:
label = guestTraffic.getKvmNetworkLabel();
break;
case VMware:
label = guestTraffic.getVmwareNetworkLabel();
break;
case Hyperv:
label = guestTraffic.getHypervNetworkLabel();
break;
case Ovm3:
label = guestTraffic.getOvm3NetworkLabel();
break;
}
return label;
}
} catch (Exception ex) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Failed to retrive the default label for management traffic:" + "zone: " + dcId + " hypervisor: " + hypervisorType + " due to:" +
ex.getMessage());
}
}
return null;
}
@Override
public List<? extends Network> listNetworksByVpc(long vpcId) {
return _networksDao.listByVpc(vpcId);
}
@Override
public List<Provider> getNtwkOffDistinctProviders(long ntkwOffId) {
List<String> providerNames = _ntwkOfferingSrvcDao.getDistinctProviders(ntkwOffId);
List<Provider> providers = new ArrayList<Provider>();
for (String providerName : providerNames) {
providers.add(Network.Provider.getProvider(providerName));
}
return providers;
}
@Override
public boolean isVmPartOfNetwork(long vmId, long ntwkId) {
if (_nicDao.findNonReleasedByInstanceIdAndNetworkId(ntwkId, vmId) != null) {
return true;
}
return false;
}
@Override
public List<? extends PhysicalNetwork> getPhysicalNtwksSupportingTrafficType(long zoneId, TrafficType trafficType) {
List<? extends PhysicalNetwork> pNtwks = _physicalNetworkDao.listByZone(zoneId);
Iterator<? extends PhysicalNetwork> it = pNtwks.iterator();
while (it.hasNext()) {
PhysicalNetwork pNtwk = it.next();
if (!_pNTrafficTypeDao.isTrafficTypeSupported(pNtwk.getId(), trafficType)) {
it.remove();
}
}
return pNtwks;
}
@Override
public boolean isPrivateGateway(long ntwkId) {
Network network = getNetwork(ntwkId);
if (network.getTrafficType() != TrafficType.Guest || network.getNetworkOfferingId() != s_privateOfferingId.longValue()) {
return false;
}
return true;
}
@Override
public List<NetworkOfferingVO> getSystemAccountNetworkOfferings(String... offeringNames) {
List<NetworkOfferingVO> offerings = new ArrayList<NetworkOfferingVO>(offeringNames.length);
for (String offeringName : offeringNames) {
NetworkOfferingVO network = _systemNetworks.get(offeringName);
if (network == null) {
throw new CloudRuntimeException("Unable to find system network profile for " + offeringName);
}
offerings.add(network);
}
return offerings;
}
@Override
public boolean isNetworkAvailableInDomain(long networkId, long domainId) {
Long networkDomainId = null;
Network network = getNetwork(networkId);
if (network.getGuestType() != Network.GuestType.Shared) {
s_logger.trace("Network id=" + networkId + " is not shared");
return false;
}
NetworkDomainVO networkDomainMap = _networkDomainDao.getDomainNetworkMapByNetworkId(networkId);
if (networkDomainMap == null) {
s_logger.trace("Network id=" + networkId + " is shared, but not domain specific");
return true;
} else {
networkDomainId = networkDomainMap.getDomainId();
}
if (domainId == networkDomainId.longValue()) {
return true;
}
if (networkDomainMap.subdomainAccess) {
Set<Long> parentDomains = _domainMgr.getDomainParentIds(domainId);
if (parentDomains.contains(networkDomainId)) {
return true;
}
}
return false;
}
@Override
public Set<Long> getAvailableIps(Network network, String requestedIp) {
if (network.getCidr() == null) {
return Collections.emptySet();
}
String[] cidr = network.getCidr().split("/");
List<String> ips = getUsedIpsInNetwork(network);
Set<Long> usedIps = new TreeSet<Long>();
for (String ip : ips) {
if (requestedIp != null && requestedIp.equals(ip)) {
s_logger.warn("Requested ip address " + requestedIp + " is already in use in network" + network);
return null;
}
usedIps.add(NetUtils.ip2Long(ip));
}
Set<Long> allPossibleIps = NetUtils.getAllIpsFromCidr(cidr[0], Integer.parseInt(cidr[1]), usedIps);
String gateway = network.getGateway();
if ((gateway != null) && (allPossibleIps.contains(NetUtils.ip2Long(gateway))))
allPossibleIps.remove(NetUtils.ip2Long(gateway));
return allPossibleIps;
}
@Override
public List<String> getUsedIpsInNetwork(Network network) {
//Get all ips used by vms nics
List<String> ips = _nicDao.listIpAddressInNetwork(network.getId());
//Get all secondary ips for nics
List<String> secondaryIps = _nicSecondaryIpDao.listSecondaryIpAddressInNetwork(network.getId());
ips.addAll(secondaryIps);
//Get ips used by load balancers
List<String> lbIps = _appLbRuleDao.listLbIpsBySourceIpNetworkId(network.getId());
ips.addAll(lbIps);
return ips;
}
@Override
public String getDomainNetworkDomain(long domainId, long zoneId) {
String networkDomain = null;
Long searchDomainId = domainId;
while (searchDomainId != null) {
DomainVO domain = _domainDao.findById(searchDomainId);
if (domain.getNetworkDomain() != null) {
networkDomain = domain.getNetworkDomain();
break;
}
searchDomainId = domain.getParent();
}
if (networkDomain == null) {
return getZoneNetworkDomain(zoneId);
}
return networkDomain;
}
boolean isProviderEnabled(PhysicalNetworkServiceProvider provider) {
if (provider == null || provider.getState() != PhysicalNetworkServiceProvider.State.Enabled) { // TODO: check
// for other states: Shutdown?
return false;
}
return true;
}
boolean isServiceEnabledInNetwork(long physicalNetworkId, long networkId, Service service) {
// check if the service is supported in the network
if (!areServicesSupportedInNetwork(networkId, service)) {
s_logger.debug("Service " + service.getName() + " is not supported in the network id=" + networkId);
return false;
}
// get provider for the service and check if all of them are supported
String provider = _ntwkSrvcDao.getProviderForServiceInNetwork(networkId, service);
if (!isProviderEnabledInPhysicalNetwork(physicalNetworkId, provider)) {
s_logger.debug("Provider " + provider + " is not enabled in physical network id=" + physicalNetworkId);
return false;
}
return true;
}
@Override
public Nic getNicInNetworkIncludingRemoved(long vmId, long networkId) {
return _nicDao.findByInstanceIdAndNetworkIdIncludingRemoved(networkId, vmId);
}
String getZoneNetworkDomain(long zoneId) {
return _dcDao.findById(zoneId).getDomain();
}
PhysicalNetwork getOnePhysicalNetworkByZoneAndTrafficType(long zoneId, TrafficType trafficType) {
List<PhysicalNetworkVO> networkList = _physicalNetworkDao.listByZoneAndTrafficType(zoneId, trafficType);
if (networkList.isEmpty()) {
throw new InvalidParameterValueException("Unable to find the default physical network with traffic=" + trafficType + " in zone id=" + zoneId + ". ");
}
if (networkList.size() > 1) {
s_logger.info("More than one physical networks exist in zone id=" + zoneId + " with traffic type=" + trafficType + ". ");
}
return networkList.get(0);
}
protected Long getNonGuestNetworkPhysicalNetworkId(Network network, TrafficType trafficType) {
// VMware control network is management network
// we need to retrieve traffic label information through physical network
Long physicalNetworkId = network.getPhysicalNetworkId();
if (physicalNetworkId == null) {
List<PhysicalNetworkVO> pNtwks = _physicalNetworkDao.listByZone(network.getDataCenterId());
if (pNtwks.size() == 1) {
physicalNetworkId = pNtwks.get(0).getId();
} else {
// locate physicalNetwork with supported traffic type
// We can make this assumptions based on the fact that Public/Management/Control traffic types are
// supported only in one physical network in the zone in 3.0
for (PhysicalNetworkVO pNtwk : pNtwks) {
if (_pNTrafficTypeDao.isTrafficTypeSupported(pNtwk.getId(), trafficType)) {
physicalNetworkId = pNtwk.getId();
break;
}
}
}
}
return physicalNetworkId;
}
protected Long getNonGuestNetworkPhysicalNetworkId(Network network) {
// no physical network for control traffic type
// have to remove this sanity check as VMware control network is management network
// we need to retrieve traffic label information through physical network
/*
if (network.getTrafficType() == TrafficType.Control) {
return null;
}
*/
Long physicalNetworkId = network.getPhysicalNetworkId();
if (physicalNetworkId == null) {
List<PhysicalNetworkVO> pNtwks = _physicalNetworkDao.listByZone(network.getDataCenterId());
if (pNtwks.size() == 1) {
physicalNetworkId = pNtwks.get(0).getId();
} else {
// locate physicalNetwork with supported traffic type
// We can make this assumptions based on the fact that Public/Management/Control traffic types are
// supported only in one physical network in the zone in 3.0
for (PhysicalNetworkVO pNtwk : pNtwks) {
if (_pNTrafficTypeDao.isTrafficTypeSupported(pNtwk.getId(), network.getTrafficType())) {
physicalNetworkId = pNtwk.getId();
break;
}
}
}
}
return physicalNetworkId;
}
@Override
public NicProfile getNicProfile(VirtualMachine vm, long networkId, String broadcastUri) {
NicVO nic = null;
if (broadcastUri != null) {
nic = _nicDao.findByNetworkIdInstanceIdAndBroadcastUri(networkId, vm.getId(), broadcastUri);
} else {
nic = _nicDao.findByNtwkIdAndInstanceId(networkId, vm.getId());
}
if (nic == null) {
return null;
}
NetworkVO network = _networksDao.findById(networkId);
Integer networkRate = getNetworkRate(network.getId(), vm.getId());
// NetworkGuru guru = _networkGurus.get(network.getGuruName());
NicProfile profile =
new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), networkRate, isSecurityGroupSupportedInNetwork(network), getNetworkTag(
vm.getHypervisorType(), network));
// guru.updateNicProfile(profile, network);
return profile;
}
@Override
public boolean networkIsConfiguredForExternalNetworking(long zoneId, long networkId) {
List<Provider> networkProviders = getNetworkProviders(networkId);
for (Provider provider : networkProviders) {
if (provider.isExternal()) {
return true;
}
}
return false;
}
private List<Provider> getNetworkProviders(long networkId) {
List<String> providerNames = _ntwkSrvcDao.getDistinctProviders(networkId);
Map<String, Provider> providers = new HashMap<String, Provider>();
for (String providerName : providerNames) {
if (!providers.containsKey(providerName)) {
providers.put(providerName, Network.Provider.getProvider(providerName));
}
}
return new ArrayList<Provider>(providers.values());
}
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
_configs = _configDao.getConfiguration("Network", params);
_allowSubdomainNetworkAccess = Boolean.valueOf(_configs.get(Config.SubDomainNetworkAccess.key()));
_executeInSequenceNtwkElmtCmd = Boolean.valueOf(_configs.get(Config.ExecuteInSequenceNetworkElementCommands.key()));
NetworkOfferingVO publicNetworkOffering = new NetworkOfferingVO(NetworkOffering.SystemPublicNetwork, TrafficType.Public, true);
publicNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(publicNetworkOffering);
_systemNetworks.put(NetworkOffering.SystemPublicNetwork, publicNetworkOffering);
NetworkOfferingVO managementNetworkOffering = new NetworkOfferingVO(NetworkOffering.SystemManagementNetwork, TrafficType.Management, false);
managementNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(managementNetworkOffering);
_systemNetworks.put(NetworkOffering.SystemManagementNetwork, managementNetworkOffering);
NetworkOfferingVO controlNetworkOffering = new NetworkOfferingVO(NetworkOffering.SystemControlNetwork, TrafficType.Control, false);
controlNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(controlNetworkOffering);
_systemNetworks.put(NetworkOffering.SystemControlNetwork, controlNetworkOffering);
NetworkOfferingVO storageNetworkOffering = new NetworkOfferingVO(NetworkOffering.SystemStorageNetwork, TrafficType.Storage, true);
storageNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(storageNetworkOffering);
_systemNetworks.put(NetworkOffering.SystemStorageNetwork, storageNetworkOffering);
NetworkOfferingVO privateGatewayNetworkOffering = new NetworkOfferingVO(NetworkOffering.SystemPrivateGatewayNetworkOffering, GuestType.Isolated);
privateGatewayNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(privateGatewayNetworkOffering);
_systemNetworks.put(NetworkOffering.SystemPrivateGatewayNetworkOffering, privateGatewayNetworkOffering);
s_privateOfferingId = privateGatewayNetworkOffering.getId();
IpAddressSearch = _ipAddressDao.createSearchBuilder();
IpAddressSearch.and("accountId", IpAddressSearch.entity().getAllocatedToAccountId(), Op.EQ);
IpAddressSearch.and("dataCenterId", IpAddressSearch.entity().getDataCenterId(), Op.EQ);
IpAddressSearch.and("vpcId", IpAddressSearch.entity().getVpcId(), Op.EQ);
IpAddressSearch.and("associatedWithNetworkId", IpAddressSearch.entity().getAssociatedWithNetworkId(), Op.EQ);
SearchBuilder<VlanVO> virtualNetworkVlanSB = _vlanDao.createSearchBuilder();
virtualNetworkVlanSB.and("vlanType", virtualNetworkVlanSB.entity().getVlanType(), Op.EQ);
IpAddressSearch.join("virtualNetworkVlanSB", virtualNetworkVlanSB, IpAddressSearch.entity().getVlanId(), virtualNetworkVlanSB.entity().getId(),
JoinBuilder.JoinType.INNER);
IpAddressSearch.done();
NicForTrafficTypeSearch = _nicDao.createSearchBuilder();
SearchBuilder<NetworkVO> networkSearch = _networksDao.createSearchBuilder();
NicForTrafficTypeSearch.join("network", networkSearch, networkSearch.entity().getId(), NicForTrafficTypeSearch.entity().getNetworkId(), JoinType.INNER);
NicForTrafficTypeSearch.and("instance", NicForTrafficTypeSearch.entity().getInstanceId(), Op.EQ);
networkSearch.and("traffictype", networkSearch.entity().getTrafficType(), Op.EQ);
NicForTrafficTypeSearch.done();
s_logger.info("Network Model is configured.");
return true;
}
@Override
public boolean start() {
// populate s_serviceToImplementedProvidersMap & s_providerToNetworkElementMap with current _networkElements
// Need to do this in start() since _networkElements are not completely configured until then.
for (NetworkElement element : networkElements) {
Map<Service, Map<Capability, String>> capabilities = element.getCapabilities();
Provider implementedProvider = element.getProvider();
if (implementedProvider != null) {
if (s_providerToNetworkElementMap.containsKey(implementedProvider.getName())) {
s_logger.error("Cannot start NetworkModel: Provider <-> NetworkElement must be a one-to-one map, " + "multiple NetworkElements found for Provider: " +
implementedProvider.getName());
continue;
}
s_logger.info("Add provider <-> element map entry. " + implementedProvider.getName() + "-" + element.getName() + "-" + element.getClass().getSimpleName());
s_providerToNetworkElementMap.put(implementedProvider.getName(), element.getName());
}
if (capabilities != null && implementedProvider != null) {
for (Service service : capabilities.keySet()) {
if (s_serviceToImplementedProvidersMap.containsKey(service)) {
List<Provider> providers = s_serviceToImplementedProvidersMap.get(service);
providers.add(implementedProvider);
} else {
List<Provider> providers = new ArrayList<Provider>();
providers.add(implementedProvider);
s_serviceToImplementedProvidersMap.put(service, providers);
}
}
}
}
s_logger.info("Started Network Model");
return true;
}
@Override
public boolean stop() {
return true;
}
@Override
public PublicIpAddress getSourceNatIpAddressForGuestNetwork(Account owner, Network guestNetwork) {
List<? extends IpAddress> addrs = listPublicIpsAssignedToGuestNtwk(owner.getId(), guestNetwork.getId(), true);
IPAddressVO sourceNatIp = null;
if (addrs.isEmpty()) {
return null;
} else {
for (IpAddress addr : addrs) {
if (addr.isSourceNat()) {
sourceNatIp = _ipAddressDao.findById(addr.getId());
return PublicIp.createFromAddrAndVlan(sourceNatIp, _vlanDao.findById(sourceNatIp.getVlanId()));
}
}
}
return null;
}
@Override
public boolean isNetworkInlineMode(Network network) {
NetworkOfferingVO offering = _networkOfferingDao.findById(network.getNetworkOfferingId());
return offering.isInline();
}
@Override
public void checkIp6Parameters(String startIPv6, String endIPv6, String ip6Gateway, String ip6Cidr) throws InvalidParameterValueException {
if (!NetUtils.isValidIpv6(startIPv6)) {
throw new InvalidParameterValueException("Invalid format for the startIPv6 parameter");
}
if (!NetUtils.isValidIpv6(endIPv6)) {
throw new InvalidParameterValueException("Invalid format for the endIPv6 parameter");
}
if (!(ip6Gateway != null && ip6Cidr != null)) {
throw new InvalidParameterValueException("ip6Gateway and ip6Cidr should be defined when startIPv6/endIPv6 are passed in");
}
if (!NetUtils.isValidIpv6(ip6Gateway)) {
throw new InvalidParameterValueException("Invalid ip6Gateway");
}
if (!NetUtils.isValidIp6Cidr(ip6Cidr)) {
throw new InvalidParameterValueException("Invalid ip6cidr");
}
if (!NetUtils.isIp6InNetwork(startIPv6, ip6Cidr)) {
throw new InvalidParameterValueException("startIPv6 is not in ip6cidr indicated network!");
}
if (!NetUtils.isIp6InNetwork(endIPv6, ip6Cidr)) {
throw new InvalidParameterValueException("endIPv6 is not in ip6cidr indicated network!");
}
if (!NetUtils.isIp6InNetwork(ip6Gateway, ip6Cidr)) {
throw new InvalidParameterValueException("ip6Gateway is not in ip6cidr indicated network!");
}
int cidrSize = NetUtils.getIp6CidrSize(ip6Cidr);
// we only support cidr == 64
if (cidrSize != 64) {
throw new InvalidParameterValueException("The cidr size of IPv6 network must be 64 bits!");
}
}
@Override
public void checkRequestedIpAddresses(long networkId, IpAddresses ips) throws InvalidParameterValueException {
String ip4 = ips.getIp4Address();
String ip6 = ips.getIp6Address();
String mac = ips.getMacAddress();
if (ip4 != null) {
if (!NetUtils.isValidIp(ip4)) {
throw new InvalidParameterValueException("Invalid specified IPv4 address " + ip4);
}
//Other checks for ipv4 are done in assignPublicIpAddress()
}
if (ip6 != null) {
if (!NetUtils.isValidIpv6(ip6)) {
throw new InvalidParameterValueException("Invalid specified IPv6 address " + ip6);
}
if (_ipv6Dao.findByNetworkIdAndIp(networkId, ip6) != null) {
throw new InvalidParameterValueException("The requested IP is already taken!");
}
List<VlanVO> vlans = _vlanDao.listVlansByNetworkId(networkId);
if (vlans == null) {
throw new CloudRuntimeException("Cannot find related vlan attached to network " + networkId);
}
Vlan ipVlan = null;
for (Vlan vlan : vlans) {
if (NetUtils.isIp6InRange(ip6, vlan.getIp6Range())) {
ipVlan = vlan;
break;
}
}
if (ipVlan == null) {
throw new InvalidParameterValueException("Requested IPv6 is not in the predefined range!");
}
}
if (mac != null) {
if(!NetUtils.isValidMac(mac)) {
throw new InvalidParameterValueException("Invalid specified MAC address " + mac);
}
if (_nicDao.findByNetworkIdAndMacAddress(networkId, mac) != null) {
throw new InvalidParameterValueException("The requested Mac address is already taken! " + mac);
}
}
}
@Override
public String getStartIpv6Address(long networkId) {
List<VlanVO> vlans = _vlanDao.listVlansByNetworkId(networkId);
if (vlans == null) {
return null;
}
String startIpv6 = null;
// Get the start ip of first create vlan(not the lowest, because if you add a lower vlan, lowest vlan would change)
for (Vlan vlan : vlans) {
if (vlan.getIp6Range() != null) {
startIpv6 = vlan.getIp6Range().split("-")[0];
break;
}
}
return startIpv6;
}
@Override
public NicVO getPlaceholderNicForRouter(Network network, Long podId) {
List<NicVO> nics = _nicDao.listPlaceholderNicsByNetworkIdAndVmType(network.getId(), VirtualMachine.Type.DomainRouter);
List<? extends Vlan> vlans = new ArrayList<VlanVO>();
if (podId != null) {
vlans = _vlanDao.listVlansForPod(podId);
}
for (NicVO nic : nics) {
if (nic.getReserver() == null && (nic.getIPv4Address() != null || nic.getIPv6Address() != null)) {
if (podId == null) {
return nic;
} else {
IpAddress ip = null;
UserIpv6AddressVO ipv6 = null;
if (nic.getIPv4Address() != null) {
ip = _ipAddressDao.findByIpAndSourceNetworkId(network.getId(), nic.getIPv4Address());
} else {
ipv6 = _ipv6Dao.findByNetworkIdAndIp(network.getId(), nic.getIPv6Address());
}
//return nic only when its ip address belong to the pod range (for the Basic zone case)
for (Vlan vlan : vlans) {
if (ip != null && ip.getVlanId() == vlan.getId()) {
return nic;
} else if (ipv6 != null && ipv6.getVlanId() == vlan.getId()) {
return nic;
}
}
}
}
}
return null;
}
@Override
public IpAddress getPublicIpAddress(String ipAddress, long zoneId) {
List<? extends Network> networks = _networksDao.listByZoneAndTrafficType(zoneId, TrafficType.Public);
if (networks.isEmpty() || networks.size() > 1) {
throw new CloudRuntimeException("Can't find public network in the zone specified");
}
return _ipAddressDao.findByIpAndSourceNetworkId(networks.get(0).getId(), ipAddress);
}
@Override
public Map<Detail, String> getNtwkOffDetails(long offId) {
return _ntwkOffDetailsDao.getNtwkOffDetails(offId);
}
@Override
public Networks.IsolationType[] listNetworkIsolationMethods() {
return Networks.IsolationType.values();
}
@Override
public boolean getExecuteInSeqNtwkElmtCmd() {
return _executeInSequenceNtwkElmtCmd;
}
@Override
public boolean isNetworkReadyForGc(long networkId) {
Network network = getNetwork(networkId);
List<Long> networkIds = _networksDao.findNetworksToGarbageCollect();
List<String> secondaryIps = _nicSecondaryIpDao.listSecondaryIpAddressInNetwork(networkId);
if (!networkIds.contains(networkId)) {
return false;
}
// add an exception for networks that use external networking devices and has secondary guest IP's allocated.
// On network GC, when network goes through implement phase a new vlan is allocated, based on the acquired VLAN
// id cidr of the network is decided in case of external networking case. While NIC uses reservation strategy 'Start'
// which ensures that new primary ip is allocated for the NiC from the new CIDR. Secondary IP's have hardcoded IP's in
// network rules. So prevent network GC.
if (secondaryIps != null && !secondaryIps.isEmpty() && networkIsConfiguredForExternalNetworking(network.getDataCenterId(), networkId)) {
return false;
}
//if the network has vms in Starting state (nics for those might not be allocated yet as Starting state also used when vm is being Created)
//don't GC
if (_nicDao.countNicsForStartingVms(networkId) > 0) {
s_logger.debug("Network id=" + networkId + " is not ready for GC as it has vms that are Starting at the moment");
return false;
}
return true;
}
@Override
public boolean getNetworkEgressDefaultPolicy(Long networkId) {
NetworkVO network = _networksDao.findById(networkId);
if (network != null) {
NetworkOfferingVO offering = _networkOfferingDao.findById(network.getNetworkOfferingId());
return offering.getEgressDefaultPolicy();
} else {
InvalidParameterValueException ex = new InvalidParameterValueException("network with network id does not exist");
throw ex;
}
}
@Override
public List<String[]> generateVmData(String userData, String serviceOffering, String zoneName,
String vmName, long vmId, String publicKey, String password, Boolean isWindows) {
final List<String[]> vmData = new ArrayList<String[]>();
if (userData != null) {
vmData.add(new String[]{"userdata", "user-data", new String(Base64.decodeBase64(userData),StringUtils.getPreferredCharset())});
}
vmData.add(new String[]{"metadata", "service-offering", StringUtils.unicodeEscape(serviceOffering)});
vmData.add(new String[]{"metadata", "availability-zone", StringUtils.unicodeEscape(zoneName)});
vmData.add(new String[]{"metadata", "local-hostname", StringUtils.unicodeEscape(vmName)});
vmData.add(new String[]{"metadata", "instance-id", vmName});
vmData.add(new String[]{"metadata", "vm-id", String.valueOf(vmId)});
vmData.add(new String[]{"metadata", "public-keys", publicKey});
String cloudIdentifier = _configDao.getValue("cloud.identifier");
if (cloudIdentifier == null) {
cloudIdentifier = "";
} else {
cloudIdentifier = "CloudStack-{" + cloudIdentifier + "}";
}
vmData.add(new String[]{"metadata", "cloud-identifier", cloudIdentifier});
if (password != null && !password.isEmpty() && !password.equals("saved_password")) {
// Here we are calculating MD5 checksum to reduce the over head of calculating MD5 checksum
// in windows VM in password reset script.
if (isWindows) {
MessageDigest md5 = null;
try {
md5 = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
s_logger.error("Unexpected exception " + e.getMessage(), e);
throw new CloudRuntimeException("Unable to get MD5 MessageDigest", e);
}
md5.reset();
md5.update(password.getBytes(StringUtils.getPreferredCharset()));
byte[] digest = md5.digest();
BigInteger bigInt = new BigInteger(1, digest);
String hashtext = bigInt.toString(16);
vmData.add(new String[]{"password", "vm-password-md5checksum", hashtext});
}
vmData.add(new String[]{"password", "vm-password", password});
}
return vmData;
}
@Override
public String getConfigComponentName() {
return NetworkModel.class.getSimpleName();
}
@Override
public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey<?>[] {MACIdentifier};
}
@Override
public String getValidNetworkCidr(Network guestNetwork) {
String networkCidr = guestNetwork.getNetworkCidr();
return networkCidr == null ? guestNetwork.getCidr() : networkCidr;
}
}