mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
3110 lines
145 KiB
Java
Executable File
3110 lines
145 KiB
Java
Executable File
// 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.net.URI;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.Collections;
|
|
import java.util.Comparator;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.LinkedHashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.UUID;
|
|
import java.util.concurrent.Executors;
|
|
import java.util.concurrent.ScheduledExecutorService;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
import javax.ejb.Local;
|
|
import javax.inject.Inject;
|
|
import javax.naming.ConfigurationException;
|
|
|
|
import org.apache.log4j.Logger;
|
|
import org.springframework.stereotype.Component;
|
|
|
|
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
|
import org.apache.cloudstack.context.CallContext;
|
|
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
|
import org.apache.cloudstack.region.PortableIpDao;
|
|
|
|
import com.cloud.agent.AgentManager;
|
|
import com.cloud.agent.Listener;
|
|
import com.cloud.agent.api.AgentControlAnswer;
|
|
import com.cloud.agent.api.AgentControlCommand;
|
|
import com.cloud.agent.api.Answer;
|
|
import com.cloud.agent.api.CheckNetworkAnswer;
|
|
import com.cloud.agent.api.CheckNetworkCommand;
|
|
import com.cloud.agent.api.Command;
|
|
import com.cloud.agent.api.StartupCommand;
|
|
import com.cloud.agent.api.StartupRoutingCommand;
|
|
import com.cloud.agent.api.to.NicTO;
|
|
import com.cloud.alert.AlertManager;
|
|
import com.cloud.api.ApiDBUtils;
|
|
import com.cloud.configuration.Config;
|
|
import com.cloud.configuration.ConfigurationManager;
|
|
import com.cloud.configuration.Resource.ResourceType;
|
|
import com.cloud.dc.DataCenter;
|
|
import com.cloud.dc.DataCenter.NetworkType;
|
|
import com.cloud.dc.DataCenterVO;
|
|
import com.cloud.dc.DataCenterVnetVO;
|
|
import com.cloud.dc.PodVlanMapVO;
|
|
import com.cloud.dc.Vlan;
|
|
import com.cloud.dc.VlanVO;
|
|
import com.cloud.dc.dao.AccountVlanMapDao;
|
|
import com.cloud.dc.dao.DataCenterDao;
|
|
import com.cloud.dc.dao.DataCenterVnetDao;
|
|
import com.cloud.dc.dao.PodVlanMapDao;
|
|
import com.cloud.dc.dao.VlanDao;
|
|
import com.cloud.deploy.DataCenterDeployment;
|
|
import com.cloud.deploy.DeployDestination;
|
|
import com.cloud.deploy.DeploymentPlan;
|
|
import com.cloud.domain.Domain;
|
|
import com.cloud.domain.dao.DomainDao;
|
|
import com.cloud.event.dao.UsageEventDao;
|
|
import com.cloud.exception.ConcurrentOperationException;
|
|
import com.cloud.exception.ConnectionException;
|
|
import com.cloud.exception.InsufficientAddressCapacityException;
|
|
import com.cloud.exception.InsufficientCapacityException;
|
|
import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
|
|
import com.cloud.exception.InvalidParameterValueException;
|
|
import com.cloud.exception.ResourceAllocationException;
|
|
import com.cloud.exception.ResourceUnavailableException;
|
|
import com.cloud.exception.UnsupportedServiceException;
|
|
import com.cloud.host.Host;
|
|
import com.cloud.host.Status;
|
|
import com.cloud.host.dao.HostDao;
|
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
|
import com.cloud.network.IpAddress.State;
|
|
import com.cloud.network.Network.Capability;
|
|
import com.cloud.network.Network.Event;
|
|
import com.cloud.network.Network.GuestType;
|
|
import com.cloud.network.Network.Provider;
|
|
import com.cloud.network.Network.Service;
|
|
import com.cloud.network.Networks.BroadcastDomainType;
|
|
import com.cloud.network.Networks.TrafficType;
|
|
import com.cloud.network.addr.PublicIp;
|
|
import com.cloud.network.dao.AccountGuestVlanMapDao;
|
|
import com.cloud.network.dao.AccountGuestVlanMapVO;
|
|
import com.cloud.network.dao.FirewallRulesDao;
|
|
import com.cloud.network.dao.IPAddressDao;
|
|
import com.cloud.network.dao.IPAddressVO;
|
|
import com.cloud.network.dao.LoadBalancerDao;
|
|
import com.cloud.network.dao.NetworkAccountDao;
|
|
import com.cloud.network.dao.NetworkAccountVO;
|
|
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.PhysicalNetworkTrafficTypeDao;
|
|
import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO;
|
|
import com.cloud.network.dao.PhysicalNetworkVO;
|
|
import com.cloud.network.dao.UserIpv6AddressDao;
|
|
import com.cloud.network.element.DhcpServiceProvider;
|
|
import com.cloud.network.element.IpDeployer;
|
|
import com.cloud.network.element.LoadBalancingServiceProvider;
|
|
import com.cloud.network.element.NetworkElement;
|
|
import com.cloud.network.element.StaticNatServiceProvider;
|
|
import com.cloud.network.element.UserDataServiceProvider;
|
|
import com.cloud.network.guru.NetworkGuru;
|
|
import com.cloud.network.lb.LoadBalancingRulesManager;
|
|
import com.cloud.network.rules.FirewallManager;
|
|
import com.cloud.network.rules.FirewallRule;
|
|
import com.cloud.network.rules.FirewallRule.Purpose;
|
|
import com.cloud.network.rules.FirewallRuleVO;
|
|
import com.cloud.network.rules.LoadBalancerContainer.Scheme;
|
|
import com.cloud.network.rules.PortForwardingRuleVO;
|
|
import com.cloud.network.rules.RulesManager;
|
|
import com.cloud.network.rules.StaticNatRule;
|
|
import com.cloud.network.rules.StaticNatRuleImpl;
|
|
import com.cloud.network.rules.dao.PortForwardingRulesDao;
|
|
import com.cloud.network.vpc.NetworkACLManager;
|
|
import com.cloud.network.vpc.VpcManager;
|
|
import com.cloud.network.vpc.dao.PrivateIpDao;
|
|
import com.cloud.network.vpn.RemoteAccessVpnService;
|
|
import com.cloud.offering.NetworkOffering;
|
|
import com.cloud.offering.NetworkOffering.Availability;
|
|
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.server.ConfigurationServer;
|
|
import com.cloud.user.Account;
|
|
import com.cloud.user.AccountManager;
|
|
import com.cloud.user.ResourceLimitService;
|
|
import com.cloud.user.User;
|
|
import com.cloud.user.dao.AccountDao;
|
|
import com.cloud.user.dao.UserDao;
|
|
import com.cloud.utils.NumbersUtil;
|
|
import com.cloud.utils.Pair;
|
|
import com.cloud.utils.component.AdapterBase;
|
|
import com.cloud.utils.component.ManagerBase;
|
|
import com.cloud.utils.concurrency.NamedThreadFactory;
|
|
import com.cloud.utils.db.DB;
|
|
import com.cloud.utils.db.GlobalLock;
|
|
import com.cloud.utils.db.JoinBuilder.JoinType;
|
|
import com.cloud.utils.db.SearchBuilder;
|
|
import com.cloud.utils.db.SearchCriteria.Op;
|
|
import com.cloud.utils.db.Transaction;
|
|
import com.cloud.utils.exception.CloudRuntimeException;
|
|
import com.cloud.utils.fsm.NoTransitionException;
|
|
import com.cloud.utils.fsm.StateMachine2;
|
|
import com.cloud.utils.net.NetUtils;
|
|
import com.cloud.vm.Nic;
|
|
import com.cloud.vm.Nic.ReservationStrategy;
|
|
import com.cloud.vm.NicIpAlias;
|
|
import com.cloud.vm.NicProfile;
|
|
import com.cloud.vm.NicVO;
|
|
import com.cloud.vm.ReservationContext;
|
|
import com.cloud.vm.ReservationContextImpl;
|
|
import com.cloud.vm.UserVmVO;
|
|
import com.cloud.vm.VMInstanceVO;
|
|
import com.cloud.vm.VirtualMachine;
|
|
import com.cloud.vm.VirtualMachine.Type;
|
|
import com.cloud.vm.VirtualMachineProfile;
|
|
import com.cloud.vm.dao.NicDao;
|
|
import com.cloud.vm.dao.NicIpAliasDao;
|
|
import com.cloud.vm.dao.NicIpAliasVO;
|
|
import com.cloud.vm.dao.NicSecondaryIpDao;
|
|
import com.cloud.vm.dao.NicSecondaryIpVO;
|
|
import com.cloud.vm.dao.UserVmDao;
|
|
import com.cloud.vm.dao.VMInstanceDao;
|
|
|
|
/**
|
|
* NetworkManagerImpl implements NetworkManager.
|
|
*/
|
|
@Component
|
|
@Local(value = { NetworkManager.class})
|
|
public class NetworkManagerImpl extends ManagerBase implements NetworkManager, Listener {
|
|
static final Logger s_logger = Logger.getLogger(NetworkManagerImpl.class);
|
|
|
|
@Inject
|
|
DataCenterDao _dcDao = null;
|
|
@Inject
|
|
VlanDao _vlanDao = null;
|
|
@Inject
|
|
IPAddressDao _ipAddressDao = null;
|
|
@Inject
|
|
AccountDao _accountDao = null;
|
|
@Inject
|
|
DomainDao _domainDao = null;
|
|
@Inject
|
|
UserDao _userDao = null;
|
|
@Inject
|
|
ConfigurationDao _configDao;
|
|
@Inject
|
|
UserVmDao _userVmDao = null;
|
|
@Inject
|
|
AlertManager _alertMgr;
|
|
@Inject
|
|
AccountManager _accountMgr;
|
|
@Inject
|
|
ConfigurationManager _configMgr;
|
|
@Inject
|
|
AccountVlanMapDao _accountVlanMapDao;
|
|
@Inject
|
|
NetworkOfferingDao _networkOfferingDao = null;
|
|
@Inject
|
|
NetworkDao _networksDao = null;
|
|
@Inject
|
|
NicDao _nicDao = null;
|
|
@Inject
|
|
RulesManager _rulesMgr;
|
|
@Inject
|
|
LoadBalancingRulesManager _lbMgr;
|
|
@Inject
|
|
RemoteAccessVpnService _vpnMgr;
|
|
@Inject
|
|
PodVlanMapDao _podVlanMapDao;
|
|
@Inject
|
|
NetworkOfferingDetailsDao _ntwkOffDetailsDao;
|
|
@Inject
|
|
ConfigurationServer _configServer;
|
|
@Inject
|
|
AccountGuestVlanMapDao _accountGuestVlanMapDao;
|
|
@Inject
|
|
DataCenterVnetDao _datacenterVnetDao;
|
|
@Inject
|
|
NetworkAccountDao _networkAccountDao;
|
|
@Inject
|
|
protected NicIpAliasDao _nicIpAliasDao;
|
|
@Inject
|
|
protected IPAddressDao _publicIpAddressDao;
|
|
@Inject
|
|
protected IpAddressManager _ipAddrMgr;
|
|
|
|
List<NetworkGuru> _networkGurus;
|
|
public List<NetworkGuru> getNetworkGurus() {
|
|
return _networkGurus;
|
|
}
|
|
public void setNetworkGurus(List<NetworkGuru> _networkGurus) {
|
|
this._networkGurus = _networkGurus;
|
|
}
|
|
|
|
List<NetworkElement> _networkElements;
|
|
public List<NetworkElement> getNetworkElements() {
|
|
return _networkElements;
|
|
}
|
|
public void setNetworkElements(List<NetworkElement> _networkElements) {
|
|
this._networkElements = _networkElements;
|
|
}
|
|
|
|
@Inject NetworkDomainDao _networkDomainDao;
|
|
|
|
List<IpDeployer> _ipDeployers;
|
|
public List<IpDeployer> getIpDeployers() {
|
|
return _ipDeployers;
|
|
}
|
|
public void setIpDeployers(List<IpDeployer> _ipDeployers) {
|
|
this._ipDeployers = _ipDeployers;
|
|
}
|
|
|
|
List<DhcpServiceProvider> _dhcpProviders;
|
|
public List<DhcpServiceProvider> getDhcpProviders() {
|
|
return _dhcpProviders;
|
|
}
|
|
public void setDhcpProviders(List<DhcpServiceProvider> _dhcpProviders) {
|
|
this._dhcpProviders = _dhcpProviders;
|
|
}
|
|
|
|
@Inject
|
|
VMInstanceDao _vmDao;
|
|
@Inject
|
|
FirewallManager _firewallMgr;
|
|
@Inject
|
|
FirewallRulesDao _firewallDao;
|
|
@Inject
|
|
ResourceLimitService _resourceLimitMgr;
|
|
|
|
@Inject
|
|
NetworkOfferingServiceMapDao _ntwkOfferingSrvcDao;
|
|
@Inject
|
|
PhysicalNetworkDao _physicalNetworkDao;
|
|
@Inject
|
|
PhysicalNetworkServiceProviderDao _pNSPDao;
|
|
@Inject
|
|
PortForwardingRulesDao _portForwardingRulesDao;
|
|
@Inject
|
|
LoadBalancerDao _lbDao;
|
|
@Inject
|
|
PhysicalNetworkTrafficTypeDao _pNTrafficTypeDao;
|
|
@Inject
|
|
AgentManager _agentMgr;
|
|
@Inject
|
|
HostDao _hostDao;
|
|
@Inject
|
|
NetworkServiceMapDao _ntwkSrvcDao;
|
|
@Inject
|
|
StorageNetworkManager _stnwMgr;
|
|
@Inject
|
|
VpcManager _vpcMgr;
|
|
@Inject
|
|
PrivateIpDao _privateIpDao;
|
|
@Inject
|
|
NetworkACLManager _networkACLMgr;
|
|
@Inject
|
|
UsageEventDao _usageEventDao;
|
|
@Inject
|
|
NetworkModel _networkModel;
|
|
@Inject
|
|
NicSecondaryIpDao _nicSecondaryIpDao;
|
|
@Inject
|
|
UserIpv6AddressDao _ipv6Dao;
|
|
@Inject
|
|
Ipv6AddressManager _ipv6Mgr;
|
|
@Inject
|
|
PortableIpDao _portableIpDao;
|
|
|
|
protected StateMachine2<Network.State, Network.Event, Network> _stateMachine;
|
|
ScheduledExecutorService _executor;
|
|
|
|
SearchBuilder<IPAddressVO> AssignIpAddressSearch;
|
|
SearchBuilder<IPAddressVO> AssignIpAddressFromPodVlanSearch;
|
|
|
|
int _networkGcWait;
|
|
int _networkGcInterval;
|
|
int _networkLockTimeout;
|
|
|
|
private Map<String, String> _configs;
|
|
|
|
HashMap<Long, Long> _lastNetworkIdsToFree = new HashMap<Long, Long>();
|
|
|
|
|
|
|
|
|
|
@Override
|
|
@DB
|
|
public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
|
|
_configs = _configDao.getConfiguration("AgentManager", params);
|
|
_networkGcWait = NumbersUtil.parseInt(_configs.get(Config.NetworkGcWait.key()), 600);
|
|
_networkGcInterval = NumbersUtil.parseInt(_configs.get(Config.NetworkGcInterval.key()), 600);
|
|
|
|
_configs = _configDao.getConfiguration("Network", params);
|
|
|
|
_networkLockTimeout = NumbersUtil.parseInt(_configs.get(Config.NetworkLockTimeout.key()), 600);
|
|
|
|
// populate providers
|
|
Map<Network.Service, Set<Network.Provider>> defaultSharedNetworkOfferingProviders = new HashMap<Network.Service, Set<Network.Provider>>();
|
|
Set<Network.Provider> defaultProviders = new HashSet<Network.Provider>();
|
|
|
|
defaultProviders.add(Network.Provider.VirtualRouter);
|
|
defaultSharedNetworkOfferingProviders.put(Service.Dhcp, defaultProviders);
|
|
defaultSharedNetworkOfferingProviders.put(Service.Dns, defaultProviders);
|
|
defaultSharedNetworkOfferingProviders.put(Service.UserData, defaultProviders);
|
|
|
|
Map<Network.Service, Set<Network.Provider>> defaultIsolatedNetworkOfferingProviders = defaultSharedNetworkOfferingProviders;
|
|
defaultIsolatedNetworkOfferingProviders.put(Service.Dhcp, defaultProviders);
|
|
defaultIsolatedNetworkOfferingProviders.put(Service.Dns, defaultProviders);
|
|
defaultIsolatedNetworkOfferingProviders.put(Service.UserData, defaultProviders);
|
|
defaultIsolatedNetworkOfferingProviders.put(Service.Firewall, defaultProviders);
|
|
defaultIsolatedNetworkOfferingProviders.put(Service.Gateway, defaultProviders);
|
|
defaultIsolatedNetworkOfferingProviders.put(Service.Lb, defaultProviders);
|
|
defaultIsolatedNetworkOfferingProviders.put(Service.StaticNat, defaultProviders);
|
|
defaultIsolatedNetworkOfferingProviders.put(Service.PortForwarding, defaultProviders);
|
|
defaultIsolatedNetworkOfferingProviders.put(Service.Vpn, defaultProviders);
|
|
|
|
Map<Network.Service, Set<Network.Provider>> defaultSharedSGEnabledNetworkOfferingProviders = new HashMap<Network.Service, Set<Network.Provider>>();
|
|
defaultSharedSGEnabledNetworkOfferingProviders.put(Service.Dhcp, defaultProviders);
|
|
defaultSharedSGEnabledNetworkOfferingProviders.put(Service.Dns, defaultProviders);
|
|
defaultSharedSGEnabledNetworkOfferingProviders.put(Service.UserData, defaultProviders);
|
|
Set<Provider> sgProviders = new HashSet<Provider>();
|
|
sgProviders.add(Provider.SecurityGroupProvider);
|
|
defaultSharedSGEnabledNetworkOfferingProviders.put(Service.SecurityGroup, sgProviders);
|
|
|
|
Map<Network.Service, Set<Network.Provider>> defaultIsolatedSourceNatEnabledNetworkOfferingProviders =
|
|
new HashMap<Network.Service, Set<Network.Provider>>();
|
|
defaultProviders.clear();
|
|
defaultProviders.add(Network.Provider.VirtualRouter);
|
|
defaultIsolatedSourceNatEnabledNetworkOfferingProviders.put(Service.Dhcp, defaultProviders);
|
|
defaultIsolatedSourceNatEnabledNetworkOfferingProviders.put(Service.Dns, defaultProviders);
|
|
defaultIsolatedSourceNatEnabledNetworkOfferingProviders.put(Service.UserData, defaultProviders);
|
|
defaultIsolatedSourceNatEnabledNetworkOfferingProviders.put(Service.Firewall, defaultProviders);
|
|
defaultIsolatedSourceNatEnabledNetworkOfferingProviders.put(Service.Gateway, defaultProviders);
|
|
defaultIsolatedSourceNatEnabledNetworkOfferingProviders.put(Service.Lb, defaultProviders);
|
|
defaultIsolatedSourceNatEnabledNetworkOfferingProviders.put(Service.SourceNat, defaultProviders);
|
|
defaultIsolatedSourceNatEnabledNetworkOfferingProviders.put(Service.StaticNat, defaultProviders);
|
|
defaultIsolatedSourceNatEnabledNetworkOfferingProviders.put(Service.PortForwarding, defaultProviders);
|
|
defaultIsolatedSourceNatEnabledNetworkOfferingProviders.put(Service.Vpn, defaultProviders);
|
|
|
|
|
|
Map<Network.Service, Set<Network.Provider>> defaultVPCOffProviders =
|
|
new HashMap<Network.Service, Set<Network.Provider>>();
|
|
defaultProviders.clear();
|
|
defaultProviders.add(Network.Provider.VirtualRouter);
|
|
defaultVPCOffProviders.put(Service.Dhcp, defaultProviders);
|
|
defaultVPCOffProviders.put(Service.Dns, defaultProviders);
|
|
defaultVPCOffProviders.put(Service.UserData, defaultProviders);
|
|
defaultVPCOffProviders.put(Service.NetworkACL, defaultProviders);
|
|
defaultVPCOffProviders.put(Service.Gateway, defaultProviders);
|
|
defaultVPCOffProviders.put(Service.Lb, defaultProviders);
|
|
defaultVPCOffProviders.put(Service.SourceNat, defaultProviders);
|
|
defaultVPCOffProviders.put(Service.StaticNat, defaultProviders);
|
|
defaultVPCOffProviders.put(Service.PortForwarding, defaultProviders);
|
|
defaultVPCOffProviders.put(Service.Vpn, defaultProviders);
|
|
|
|
Transaction txn = Transaction.currentTxn();
|
|
txn.start();
|
|
|
|
NetworkOfferingVO offering = null;
|
|
//#1 - quick cloud network offering
|
|
if (_networkOfferingDao.findByUniqueName(NetworkOffering.QuickCloudNoServices) == null) {
|
|
offering =
|
|
_configMgr.createNetworkOffering(NetworkOffering.QuickCloudNoServices,
|
|
"Offering for QuickCloud with no services", TrafficType.Guest, null, true,
|
|
Availability.Optional, null, new HashMap<Network.Service, Set<Network.Provider>>(), true,
|
|
Network.GuestType.Shared, false, null, true, null, true, false, null, false, null);
|
|
offering.setState(NetworkOffering.State.Enabled);
|
|
_networkOfferingDao.update(offering.getId(), offering);
|
|
}
|
|
|
|
//#2 - SG enabled network offering
|
|
if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultSharedNetworkOfferingWithSGService) == null) {
|
|
offering =
|
|
_configMgr.createNetworkOffering(NetworkOffering.DefaultSharedNetworkOfferingWithSGService,
|
|
"Offering for Shared Security group enabled networks", TrafficType.Guest, null, true,
|
|
Availability.Optional, null, defaultSharedNetworkOfferingProviders, true,
|
|
Network.GuestType.Shared, false, null, true, null, true, false, null, false, null);
|
|
offering.setState(NetworkOffering.State.Enabled);
|
|
_networkOfferingDao.update(offering.getId(), offering);
|
|
}
|
|
|
|
//#3 - shared network offering with no SG service
|
|
if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultSharedNetworkOffering) == null) {
|
|
offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultSharedNetworkOffering, "Offering for Shared networks", TrafficType.Guest, null, true, Availability.Optional, null,
|
|
defaultSharedNetworkOfferingProviders, true, Network.GuestType.Shared, false, null, true, null, true, false, null, false, null);
|
|
offering.setState(NetworkOffering.State.Enabled);
|
|
_networkOfferingDao.update(offering.getId(), offering);
|
|
}
|
|
|
|
|
|
//#4 - default isolated offering with Source nat service
|
|
if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultIsolatedNetworkOfferingWithSourceNatService) == null) {
|
|
offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOfferingWithSourceNatService,
|
|
"Offering for Isolated networks with Source Nat service enabled", TrafficType.Guest,
|
|
null, false, Availability.Required, null, defaultIsolatedSourceNatEnabledNetworkOfferingProviders,
|
|
true, Network.GuestType.Isolated, false, null, true, null, false, false, null, false, null);
|
|
|
|
offering.setState(NetworkOffering.State.Enabled);
|
|
_networkOfferingDao.update(offering.getId(), offering);
|
|
}
|
|
|
|
//#5 - default vpc offering with LB service
|
|
if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworks) == null) {
|
|
offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworks,
|
|
"Offering for Isolated VPC networks with Source Nat service enabled", TrafficType.Guest,
|
|
null, false, Availability.Optional, null, defaultVPCOffProviders,
|
|
true, Network.GuestType.Isolated, false, null, false, null, false, false, null,false, null);
|
|
offering.setState(NetworkOffering.State.Enabled);
|
|
_networkOfferingDao.update(offering.getId(), offering);
|
|
}
|
|
|
|
//#6 - default vpc offering with no LB service
|
|
if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworksNoLB) == null) {
|
|
//remove LB service
|
|
defaultVPCOffProviders.remove(Service.Lb);
|
|
offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworksNoLB,
|
|
"Offering for Isolated VPC networks with Source Nat service enabled and LB service disabled", TrafficType.Guest,
|
|
null, false, Availability.Optional, null, defaultVPCOffProviders,
|
|
true, Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null);
|
|
offering.setState(NetworkOffering.State.Enabled);
|
|
_networkOfferingDao.update(offering.getId(), offering);
|
|
}
|
|
|
|
//#7 - isolated offering with source nat disabled
|
|
if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultIsolatedNetworkOffering) == null) {
|
|
offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOffering,
|
|
"Offering for Isolated networks with no Source Nat service", TrafficType.Guest, null, true,
|
|
Availability.Optional, null, defaultIsolatedNetworkOfferingProviders, true, Network.GuestType.Isolated,
|
|
false, null, true, null, true, false, null, false, null);
|
|
offering.setState(NetworkOffering.State.Enabled);
|
|
_networkOfferingDao.update(offering.getId(), offering);
|
|
}
|
|
|
|
//#8 - network offering with internal lb service
|
|
Map<Network.Service, Set<Network.Provider>> internalLbOffProviders =
|
|
new HashMap<Network.Service, Set<Network.Provider>>();
|
|
Set<Network.Provider> defaultVpcProvider = new HashSet<Network.Provider>();
|
|
defaultVpcProvider.add(Network.Provider.VPCVirtualRouter);
|
|
|
|
Set<Network.Provider> defaultInternalLbProvider = new HashSet<Network.Provider>();
|
|
defaultInternalLbProvider.add(Network.Provider.InternalLbVm);
|
|
|
|
internalLbOffProviders.put(Service.Dhcp, defaultVpcProvider);
|
|
internalLbOffProviders.put(Service.Dns, defaultVpcProvider);
|
|
internalLbOffProviders.put(Service.UserData, defaultVpcProvider);
|
|
internalLbOffProviders.put(Service.NetworkACL, defaultVpcProvider);
|
|
internalLbOffProviders.put(Service.Gateway, defaultVpcProvider);
|
|
internalLbOffProviders.put(Service.Lb, defaultInternalLbProvider);
|
|
internalLbOffProviders.put(Service.SourceNat, defaultVpcProvider);
|
|
|
|
if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworksWithInternalLB) == null) {
|
|
offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworksWithInternalLB,
|
|
"Offering for Isolated VPC networks with Internal Lb support", TrafficType.Guest,
|
|
null, false, Availability.Optional, null, internalLbOffProviders,
|
|
true, Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null);
|
|
offering.setState(NetworkOffering.State.Enabled);
|
|
offering.setInternalLb(true);
|
|
offering.setPublicLb(false);
|
|
_networkOfferingDao.update(offering.getId(), offering);
|
|
}
|
|
|
|
Map<Network.Service, Set<Network.Provider>> netscalerServiceProviders = new HashMap<Network.Service, Set<Network.Provider>>();
|
|
Set<Network.Provider> vrProvider = new HashSet<Network.Provider>();
|
|
vrProvider.add(Provider.VirtualRouter);
|
|
Set<Network.Provider> sgProvider = new HashSet<Network.Provider>();
|
|
sgProvider.add(Provider.SecurityGroupProvider);
|
|
Set<Network.Provider> nsProvider = new HashSet<Network.Provider>();
|
|
nsProvider.add(Provider.Netscaler);
|
|
netscalerServiceProviders.put(Service.Dhcp, vrProvider);
|
|
netscalerServiceProviders.put(Service.Dns, vrProvider);
|
|
netscalerServiceProviders.put(Service.UserData, vrProvider);
|
|
netscalerServiceProviders.put(Service.SecurityGroup, sgProvider);
|
|
netscalerServiceProviders.put(Service.StaticNat, nsProvider);
|
|
netscalerServiceProviders.put(Service.Lb, nsProvider);
|
|
|
|
Map<Service, Map<Capability, String>> serviceCapabilityMap = new HashMap<Service, Map<Capability, String>>();
|
|
Map<Capability, String> elb = new HashMap<Capability, String>();
|
|
elb.put(Capability.ElasticLb, "true");
|
|
Map<Capability, String> eip = new HashMap<Capability, String>();
|
|
eip.put(Capability.ElasticIp, "true");
|
|
serviceCapabilityMap.put(Service.Lb, elb);
|
|
serviceCapabilityMap.put(Service.StaticNat, eip);
|
|
|
|
if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultSharedEIPandELBNetworkOffering) == null) {
|
|
offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultSharedEIPandELBNetworkOffering, "Offering for Shared networks with Elastic IP and Elastic LB capabilities", TrafficType.Guest, null, true,
|
|
Availability.Optional, null, netscalerServiceProviders, true, Network.GuestType.Shared, false, null, true, serviceCapabilityMap, true, false, null, false, null);
|
|
offering.setState(NetworkOffering.State.Enabled);
|
|
offering.setDedicatedLB(false);
|
|
_networkOfferingDao.update(offering.getId(), offering);
|
|
}
|
|
|
|
txn.commit();
|
|
|
|
|
|
AssignIpAddressSearch = _ipAddressDao.createSearchBuilder();
|
|
AssignIpAddressSearch.and("dc", AssignIpAddressSearch.entity().getDataCenterId(), Op.EQ);
|
|
AssignIpAddressSearch.and("allocated", AssignIpAddressSearch.entity().getAllocatedTime(), Op.NULL);
|
|
AssignIpAddressSearch.and("vlanId", AssignIpAddressSearch.entity().getVlanId(), Op.IN);
|
|
SearchBuilder<VlanVO> vlanSearch = _vlanDao.createSearchBuilder();
|
|
vlanSearch.and("type", vlanSearch.entity().getVlanType(), Op.EQ);
|
|
vlanSearch.and("networkId", vlanSearch.entity().getNetworkId(), Op.EQ);
|
|
AssignIpAddressSearch.join("vlan", vlanSearch, vlanSearch.entity().getId(), AssignIpAddressSearch.entity().getVlanId(), JoinType.INNER);
|
|
AssignIpAddressSearch.done();
|
|
|
|
AssignIpAddressFromPodVlanSearch = _ipAddressDao.createSearchBuilder();
|
|
AssignIpAddressFromPodVlanSearch.and("dc", AssignIpAddressFromPodVlanSearch.entity().getDataCenterId(), Op.EQ);
|
|
AssignIpAddressFromPodVlanSearch.and("allocated", AssignIpAddressFromPodVlanSearch.entity().getAllocatedTime(), Op.NULL);
|
|
SearchBuilder<VlanVO> podVlanSearch = _vlanDao.createSearchBuilder();
|
|
podVlanSearch.and("type", podVlanSearch.entity().getVlanType(), Op.EQ);
|
|
podVlanSearch.and("networkId", podVlanSearch.entity().getNetworkId(), Op.EQ);
|
|
SearchBuilder<PodVlanMapVO> podVlanMapSB = _podVlanMapDao.createSearchBuilder();
|
|
podVlanMapSB.and("podId", podVlanMapSB.entity().getPodId(), Op.EQ);
|
|
AssignIpAddressFromPodVlanSearch.join("podVlanMapSB", podVlanMapSB, podVlanMapSB.entity().getVlanDbId(), AssignIpAddressFromPodVlanSearch.entity().getVlanId(), JoinType.INNER);
|
|
AssignIpAddressFromPodVlanSearch.join("vlan", podVlanSearch, podVlanSearch.entity().getId(), AssignIpAddressFromPodVlanSearch.entity().getVlanId(), JoinType.INNER);
|
|
AssignIpAddressFromPodVlanSearch.done();
|
|
|
|
_executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("Network-Scavenger"));
|
|
|
|
_agentMgr.registerForHostEvents(this, true, false, true);
|
|
|
|
Network.State.getStateMachine().registerListener(new NetworkStateListener(_usageEventDao, _networksDao));
|
|
|
|
s_logger.info("Network Manager is configured.");
|
|
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean start() {
|
|
_executor.scheduleWithFixedDelay(new NetworkGarbageCollector(), _networkGcInterval, _networkGcInterval, TimeUnit.SECONDS);
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean stop() {
|
|
return true;
|
|
}
|
|
|
|
protected NetworkManagerImpl() {
|
|
setStateMachine();
|
|
}
|
|
|
|
@Override
|
|
public List<? extends Network> setupNetwork(Account owner, NetworkOffering offering, DeploymentPlan plan, String name,
|
|
String displayText, boolean isDefault)
|
|
throws ConcurrentOperationException {
|
|
return setupNetwork(owner, offering, null, plan, name, displayText, false, null, null, null, null, true);
|
|
}
|
|
|
|
@Override
|
|
@DB
|
|
public List<? extends Network> setupNetwork(Account owner, NetworkOffering offering, Network predefined, DeploymentPlan
|
|
plan, String name, String displayText, boolean errorIfAlreadySetup, Long domainId,
|
|
ACLType aclType, Boolean subdomainAccess, Long vpcId, Boolean isDisplayNetworkEnabled) throws ConcurrentOperationException {
|
|
|
|
Account locked = _accountDao.acquireInLockTable(owner.getId());
|
|
if (locked == null) {
|
|
throw new ConcurrentOperationException("Unable to acquire lock on " + owner);
|
|
}
|
|
|
|
try {
|
|
if (predefined == null
|
|
|| (offering.getTrafficType() != TrafficType.Guest && predefined.getCidr() == null && predefined.getBroadcastUri() == null &&
|
|
!(predefined.getBroadcastDomainType() == BroadcastDomainType.Vlan || predefined.getBroadcastDomainType() == BroadcastDomainType.Lswitch))) {
|
|
List<NetworkVO> configs = _networksDao.listBy(owner.getId(), offering.getId(), plan.getDataCenterId());
|
|
if (configs.size() > 0) {
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Found existing network configuration for offering " + offering + ": " + configs.get(0));
|
|
}
|
|
|
|
if (errorIfAlreadySetup) {
|
|
InvalidParameterValueException ex = new InvalidParameterValueException("Found existing network configuration (with specified id) for offering (with specified id)");
|
|
ex.addProxyObject(offering.getUuid(), "offeringId");
|
|
ex.addProxyObject(configs.get(0).getUuid(), "networkConfigId");
|
|
throw ex;
|
|
} else {
|
|
return configs;
|
|
}
|
|
}
|
|
}
|
|
|
|
List<NetworkVO> networks = new ArrayList<NetworkVO>();
|
|
|
|
long related = -1;
|
|
|
|
for (NetworkGuru guru : _networkGurus) {
|
|
Network network = guru.design(offering, plan, predefined, owner);
|
|
if (network == null) {
|
|
continue;
|
|
}
|
|
|
|
if (network.getId() != -1) {
|
|
if (network instanceof NetworkVO) {
|
|
networks.add((NetworkVO) network);
|
|
} else {
|
|
networks.add(_networksDao.findById(network.getId()));
|
|
}
|
|
continue;
|
|
}
|
|
|
|
long id = _networksDao.getNextInSequence(Long.class, "id");
|
|
if (related == -1) {
|
|
related = id;
|
|
}
|
|
|
|
Transaction txn = Transaction.currentTxn();
|
|
txn.start();
|
|
|
|
NetworkVO vo = new NetworkVO(id, network, offering.getId(), guru.getName(), owner.getDomainId(), owner.getId(),
|
|
related, name, displayText, predefined.getNetworkDomain(), offering.getGuestType(),
|
|
plan.getDataCenterId(), plan.getPhysicalNetworkId(), aclType, offering.getSpecifyIpRanges(), vpcId);
|
|
vo.setDisplayNetwork(isDisplayNetworkEnabled == null ? true : isDisplayNetworkEnabled);
|
|
networks.add(_networksDao.persist(vo, vo.getGuestType() == Network.GuestType.Isolated,
|
|
finalizeServicesAndProvidersForNetwork(offering, plan.getPhysicalNetworkId())));
|
|
|
|
if (domainId != null && aclType == ACLType.Domain) {
|
|
if (subdomainAccess == null ) {
|
|
subdomainAccess = true;
|
|
}
|
|
_networksDao.addDomainToNetwork(id, domainId, subdomainAccess);
|
|
}
|
|
|
|
txn.commit();
|
|
}
|
|
|
|
if (networks.size() < 1) {
|
|
// see networkOfferingVO.java
|
|
CloudRuntimeException ex = new CloudRuntimeException("Unable to convert network offering with specified id to network profile");
|
|
ex.addProxyObject(offering.getUuid(), "offeringId");
|
|
throw ex;
|
|
}
|
|
|
|
return networks;
|
|
} finally {
|
|
s_logger.debug("Releasing lock for " + locked);
|
|
_accountDao.releaseFromLockTable(locked.getId());
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
@DB
|
|
public void allocate(VirtualMachineProfile vm, LinkedHashMap<? extends Network, ? extends NicProfile> networks)
|
|
throws InsufficientCapacityException, ConcurrentOperationException {
|
|
Transaction txn = Transaction.currentTxn();
|
|
txn.start();
|
|
|
|
int deviceId = 0;
|
|
|
|
boolean[] deviceIds = new boolean[networks.size()];
|
|
Arrays.fill(deviceIds, false);
|
|
|
|
List<NicProfile> nics = new ArrayList<NicProfile>(networks.size());
|
|
NicProfile defaultNic = null;
|
|
|
|
for (Map.Entry<? extends Network, ? extends NicProfile> network : networks.entrySet()) {
|
|
Network config = network.getKey();
|
|
NicProfile requested = network.getValue();
|
|
|
|
Boolean isDefaultNic = false;
|
|
if (vm != null && (requested != null && requested.isDefaultNic())) {
|
|
isDefaultNic = true;
|
|
}
|
|
|
|
while (deviceIds[deviceId] && deviceId < deviceIds.length) {
|
|
deviceId++;
|
|
}
|
|
|
|
Pair<NicProfile,Integer> vmNicPair = allocateNic(requested, config, isDefaultNic,
|
|
deviceId, vm);
|
|
|
|
NicProfile vmNic = vmNicPair.first();
|
|
if (vmNic == null) {
|
|
continue;
|
|
}
|
|
|
|
deviceId = vmNicPair.second();
|
|
|
|
int devId = vmNic.getDeviceId();
|
|
if (devId > deviceIds.length) {
|
|
throw new IllegalArgumentException("Device id for nic is too large: " + vmNic);
|
|
}
|
|
if (deviceIds[devId]) {
|
|
throw new IllegalArgumentException("Conflicting device id for two different nics: " + vmNic);
|
|
}
|
|
|
|
deviceIds[devId] = true;
|
|
|
|
if (vmNic.isDefaultNic()) {
|
|
if (defaultNic != null) {
|
|
throw new IllegalArgumentException("You cannot specify two nics as default nics: nic 1 = " +
|
|
defaultNic + "; nic 2 = " + vmNic);
|
|
}
|
|
defaultNic = vmNic;
|
|
}
|
|
|
|
nics.add(vmNic);
|
|
vm.addNic(vmNic);
|
|
|
|
}
|
|
|
|
if (nics.size() != networks.size()) {
|
|
s_logger.warn("Number of nics " + nics.size() + " doesn't match number of requested networks " + networks.size());
|
|
throw new CloudRuntimeException("Number of nics " + nics.size() + " doesn't match number of requested networks " + networks.size());
|
|
}
|
|
|
|
if (nics.size() == 1) {
|
|
nics.get(0).setDefaultNic(true);
|
|
}
|
|
|
|
txn.commit();
|
|
}
|
|
|
|
|
|
@DB
|
|
@Override
|
|
public Pair<NicProfile,Integer> allocateNic(NicProfile requested, Network network, Boolean isDefaultNic,
|
|
int deviceId, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapcityException,
|
|
InsufficientAddressCapacityException, ConcurrentOperationException{
|
|
|
|
NetworkVO ntwkVO = _networksDao.findById(network.getId());
|
|
s_logger.debug("Allocating nic for vm " + vm.getVirtualMachine() + " in network " + network + " with requested profile " + requested);
|
|
NetworkGuru guru = AdapterBase.getAdapterByName(_networkGurus, ntwkVO.getGuruName());
|
|
|
|
if (requested != null && requested.getMode() == null) {
|
|
requested.setMode(network.getMode());
|
|
}
|
|
NicProfile profile = guru.allocate(network, requested, vm);
|
|
if (isDefaultNic != null) {
|
|
profile.setDefaultNic(isDefaultNic);
|
|
}
|
|
|
|
if (profile == null) {
|
|
return null;
|
|
}
|
|
|
|
if (requested != null && requested.getMode() == null) {
|
|
profile.setMode(requested.getMode());
|
|
} else {
|
|
profile.setMode(network.getMode());
|
|
}
|
|
|
|
NicVO vo = new NicVO(guru.getName(), vm.getId(), network.getId(), vm.getType());
|
|
|
|
deviceId = applyProfileToNic(vo, profile, deviceId);
|
|
|
|
vo = _nicDao.persist(vo);
|
|
|
|
Integer networkRate = _networkModel.getNetworkRate(network.getId(), vm.getId());
|
|
NicProfile vmNic = new NicProfile(vo, network, vo.getBroadcastUri(), vo.getIsolationUri(), networkRate,
|
|
_networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag(vm.getHypervisorType(),
|
|
network));
|
|
|
|
return new Pair<NicProfile,Integer>(vmNic, Integer.valueOf(deviceId));
|
|
}
|
|
|
|
protected Integer applyProfileToNic(NicVO vo, NicProfile profile, Integer deviceId) {
|
|
if (profile.getDeviceId() != null) {
|
|
vo.setDeviceId(profile.getDeviceId());
|
|
} else if (deviceId != null) {
|
|
vo.setDeviceId(deviceId++);
|
|
}
|
|
|
|
if (profile.getReservationStrategy() != null) {
|
|
vo.setReservationStrategy(profile.getReservationStrategy());
|
|
}
|
|
|
|
vo.setDefaultNic(profile.isDefaultNic());
|
|
|
|
vo.setIp4Address(profile.getIp4Address());
|
|
vo.setAddressFormat(profile.getFormat());
|
|
|
|
if (profile.getMacAddress() != null) {
|
|
vo.setMacAddress(profile.getMacAddress());
|
|
}
|
|
|
|
vo.setMode(profile.getMode());
|
|
vo.setNetmask(profile.getNetmask());
|
|
vo.setGateway(profile.getGateway());
|
|
|
|
if (profile.getBroadCastUri() != null) {
|
|
vo.setBroadcastUri(profile.getBroadCastUri());
|
|
}
|
|
|
|
if (profile.getIsolationUri() != null) {
|
|
vo.setIsolationUri(profile.getIsolationUri());
|
|
}
|
|
|
|
vo.setState(Nic.State.Allocated);
|
|
|
|
vo.setIp6Address(profile.getIp6Address());
|
|
vo.setIp6Gateway(profile.getIp6Gateway());
|
|
vo.setIp6Cidr(profile.getIp6Cidr());
|
|
|
|
return deviceId;
|
|
}
|
|
|
|
protected void applyProfileToNicForRelease(NicVO vo, NicProfile profile) {
|
|
vo.setGateway(profile.getGateway());
|
|
vo.setAddressFormat(profile.getFormat());
|
|
vo.setIp4Address(profile.getIp4Address());
|
|
vo.setIp6Address(profile.getIp6Address());
|
|
vo.setMacAddress(profile.getMacAddress());
|
|
if (profile.getReservationStrategy() != null) {
|
|
vo.setReservationStrategy(profile.getReservationStrategy());
|
|
}
|
|
vo.setBroadcastUri(profile.getBroadCastUri());
|
|
vo.setIsolationUri(profile.getIsolationUri());
|
|
vo.setNetmask(profile.getNetmask());
|
|
}
|
|
|
|
protected void applyProfileToNetwork(NetworkVO network, NetworkProfile profile) {
|
|
network.setBroadcastUri(profile.getBroadcastUri());
|
|
network.setDns1(profile.getDns1());
|
|
network.setDns2(profile.getDns2());
|
|
network.setPhysicalNetworkId(profile.getPhysicalNetworkId());
|
|
}
|
|
|
|
protected NicTO toNicTO(NicVO nic, NicProfile profile, NetworkVO config) {
|
|
NicTO to = new NicTO();
|
|
to.setDeviceId(nic.getDeviceId());
|
|
to.setBroadcastType(config.getBroadcastDomainType());
|
|
to.setType(config.getTrafficType());
|
|
to.setIp(nic.getIp4Address());
|
|
to.setNetmask(nic.getNetmask());
|
|
to.setMac(nic.getMacAddress());
|
|
to.setDns1(profile.getDns1());
|
|
to.setDns2(profile.getDns2());
|
|
if (nic.getGateway() != null) {
|
|
to.setGateway(nic.getGateway());
|
|
} else {
|
|
to.setGateway(config.getGateway());
|
|
}
|
|
to.setDefaultNic(nic.isDefaultNic());
|
|
to.setBroadcastUri(nic.getBroadcastUri());
|
|
to.setIsolationuri(nic.getIsolationUri());
|
|
if (profile != null) {
|
|
to.setDns1(profile.getDns1());
|
|
to.setDns2(profile.getDns2());
|
|
}
|
|
|
|
Integer networkRate = _networkModel.getNetworkRate(config.getId(), null);
|
|
to.setNetworkRateMbps(networkRate);
|
|
|
|
to.setUuid(config.getUuid());
|
|
|
|
return to;
|
|
}
|
|
|
|
@Override
|
|
@DB
|
|
public Pair<NetworkGuru, NetworkVO> implementNetwork(long networkId, DeployDestination dest, ReservationContext context)
|
|
throws ConcurrentOperationException, ResourceUnavailableException,
|
|
InsufficientCapacityException {
|
|
Transaction.currentTxn();
|
|
Pair<NetworkGuru, NetworkVO> implemented = new Pair<NetworkGuru, NetworkVO>(null, null);
|
|
|
|
NetworkVO network = _networksDao.acquireInLockTable(networkId, _networkLockTimeout);
|
|
if (network == null) {
|
|
// see NetworkVO.java
|
|
ConcurrentOperationException ex = new ConcurrentOperationException("Unable to acquire network configuration");
|
|
ex.addProxyObject(ApiDBUtils.findNetworkById(networkId).getUuid());
|
|
throw ex;
|
|
}
|
|
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Lock is acquired for network id " + networkId + " as a part of network implement");
|
|
}
|
|
|
|
try {
|
|
NetworkGuru guru = AdapterBase.getAdapterByName(_networkGurus, network.getGuruName());
|
|
Network.State state = network.getState();
|
|
if (state == Network.State.Implemented || state == Network.State.Implementing) {
|
|
s_logger.debug("Network id=" + networkId + " is already implemented");
|
|
implemented.set(guru, network);
|
|
return implemented;
|
|
}
|
|
|
|
if (state == Network.State.Setup) {
|
|
DataCenterVO zone = _dcDao.findById(network.getDataCenterId());
|
|
if (!isSharedNetworkOfferingWithServices(network.getNetworkOfferingId()) || (zone.getNetworkType() == NetworkType.Basic)) {
|
|
s_logger.debug("Network id=" + networkId + " is already implemented");
|
|
implemented.set(guru, network);
|
|
return implemented;
|
|
}
|
|
}
|
|
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Asking " + guru.getName() + " to implement " + network);
|
|
}
|
|
|
|
NetworkOfferingVO offering = _networkOfferingDao.findById(network.getNetworkOfferingId());
|
|
|
|
network.setReservationId(context.getReservationId());
|
|
if (isSharedNetworkWithServices(network)) {
|
|
network.setState(Network.State.Implementing);
|
|
} else {
|
|
stateTransitTo(network, Event.ImplementNetwork);
|
|
}
|
|
|
|
Network result = guru.implement(network, offering, dest, context);
|
|
network.setCidr(result.getCidr());
|
|
network.setBroadcastUri(result.getBroadcastUri());
|
|
network.setGateway(result.getGateway());
|
|
network.setMode(result.getMode());
|
|
network.setPhysicalNetworkId(result.getPhysicalNetworkId());
|
|
_networksDao.update(networkId, network);
|
|
|
|
// implement network elements and re-apply all the network rules
|
|
implementNetworkElementsAndResources(dest, context, network, offering);
|
|
|
|
if (isSharedNetworkWithServices(network)) {
|
|
network.setState(Network.State.Implemented);
|
|
} else {
|
|
stateTransitTo(network,Event.OperationSucceeded);
|
|
}
|
|
|
|
network.setRestartRequired(false);
|
|
_networksDao.update(network.getId(), network);
|
|
implemented.set(guru, network);
|
|
return implemented;
|
|
} catch (NoTransitionException e) {
|
|
s_logger.error(e.getMessage());
|
|
return null;
|
|
} finally {
|
|
if (implemented.first() == null) {
|
|
s_logger.debug("Cleaning up because we're unable to implement the network " + network);
|
|
try {
|
|
if (isSharedNetworkWithServices(network)) {
|
|
network.setState(Network.State.Shutdown);
|
|
_networksDao.update(networkId, network);
|
|
} else {
|
|
stateTransitTo(network,Event.OperationFailed);
|
|
}
|
|
} catch (NoTransitionException e) {
|
|
s_logger.error(e.getMessage());
|
|
}
|
|
|
|
shutdownNetwork(networkId, context, false);
|
|
}
|
|
|
|
_networksDao.releaseFromLockTable(networkId);
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Lock is released for network id " + networkId + " as a part of network implement");
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object o) {
|
|
return super.equals(o); //To change body of overridden methods use File | Settings | File Templates.
|
|
}
|
|
|
|
@Override
|
|
public void implementNetworkElementsAndResources(DeployDestination dest, ReservationContext context,
|
|
Network network, NetworkOffering offering)
|
|
throws ConcurrentOperationException, InsufficientAddressCapacityException, ResourceUnavailableException, InsufficientCapacityException {
|
|
|
|
// Associate a source NAT IP (if one isn't already associated with the network) if this is a
|
|
// 1) 'Isolated' or 'Shared' guest virtual network in the advance zone
|
|
// 2) network has sourceNat service
|
|
// 3) network offering does not support a shared source NAT rule
|
|
|
|
boolean sharedSourceNat = offering.getSharedSourceNat();
|
|
DataCenter zone = _dcDao.findById(network.getDataCenterId());
|
|
|
|
if (!sharedSourceNat && _networkModel.areServicesSupportedInNetwork(network.getId(), Service.SourceNat)
|
|
&& (network.getGuestType() == Network.GuestType.Isolated ||
|
|
(network.getGuestType() == Network.GuestType.Shared && zone.getNetworkType() == NetworkType.Advanced))) {
|
|
|
|
List<IPAddressVO> ips = null;
|
|
if (network.getVpcId() != null) {
|
|
ips = _ipAddressDao.listByAssociatedVpc(network.getVpcId(), true);
|
|
if (ips.isEmpty()) {
|
|
throw new CloudRuntimeException("Vpc is not implemented; there is no source nat ip");
|
|
}
|
|
} else {
|
|
ips = _ipAddressDao.listByAssociatedNetwork(network.getId(), true);
|
|
}
|
|
|
|
if (ips.isEmpty()) {
|
|
s_logger.debug("Creating a source nat ip for network " + network);
|
|
Account owner = _accountMgr.getAccount(network.getAccountId());
|
|
_ipAddrMgr.assignSourceNatIpAddressToGuestNetwork(owner, network);
|
|
}
|
|
}
|
|
|
|
// get providers to implement
|
|
List<Provider> providersToImplement = getNetworkProviders(network.getId());
|
|
for (NetworkElement element : _networkElements) {
|
|
if (providersToImplement.contains(element.getProvider())) {
|
|
if (!_networkModel.isProviderEnabledInPhysicalNetwork(_networkModel.getPhysicalNetworkId(network), element.getProvider().getName())) {
|
|
// The physicalNetworkId will not get translated into a uuid by the reponse serializer,
|
|
// because the serializer would look up the NetworkVO class's table and retrieve the
|
|
// network id instead of the physical network id.
|
|
// So just throw this exception as is. We may need to TBD by changing the serializer.
|
|
throw new CloudRuntimeException("Service provider " + element.getProvider().getName() +
|
|
" either doesn't exist or is not enabled in physical network id: " + network.getPhysicalNetworkId());
|
|
}
|
|
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Asking " + element.getName() + " to implemenet " + network);
|
|
}
|
|
|
|
if (!element.implement(network, offering, dest, context)) {
|
|
CloudRuntimeException ex = new CloudRuntimeException("Failed to implement provider " + element.getProvider().getName() + " for network with specified id");
|
|
ex.addProxyObject(network.getUuid(), "networkId");
|
|
throw ex;
|
|
}
|
|
}
|
|
}
|
|
|
|
// reapply all the firewall/staticNat/lb rules
|
|
s_logger.debug("Reprogramming network " + network + " as a part of network implement");
|
|
if (!reprogramNetworkRules(network.getId(), CallContext.current().getCallingAccount(), network)) {
|
|
s_logger.warn("Failed to re-program the network as a part of network " + network + " implement");
|
|
// see DataCenterVO.java
|
|
ResourceUnavailableException ex = new ResourceUnavailableException("Unable to apply network rules as a part of network " + network + " implement", DataCenter.class, network.getDataCenterId());
|
|
ex.addProxyObject(ApiDBUtils.findZoneById(network.getDataCenterId()).getUuid());
|
|
throw ex;
|
|
}
|
|
}
|
|
|
|
// This method re-programs the rules/ips for existing network
|
|
protected boolean reprogramNetworkRules(long networkId, Account caller, Network network) throws ResourceUnavailableException {
|
|
boolean success = true;
|
|
// associate all ip addresses
|
|
if (!_ipAddrMgr.applyIpAssociations(network, false)) {
|
|
s_logger.warn("Failed to apply ip addresses as a part of network id" + networkId + " restart");
|
|
success = false;
|
|
}
|
|
|
|
// apply static nat
|
|
if (!_rulesMgr.applyStaticNatsForNetwork(networkId, false, caller)) {
|
|
s_logger.warn("Failed to apply static nats a part of network id" + networkId + " restart");
|
|
success = false;
|
|
}
|
|
|
|
// apply firewall rules
|
|
List<FirewallRuleVO> firewallIngressRulesToApply = _firewallDao.listByNetworkPurposeTrafficType(networkId, Purpose.Firewall, FirewallRule.TrafficType.Ingress);
|
|
if (!_firewallMgr.applyFirewallRules(firewallIngressRulesToApply, false, caller)) {
|
|
s_logger.warn("Failed to reapply Ingress firewall rule(s) as a part of network id=" + networkId + " restart");
|
|
success = false;
|
|
}
|
|
|
|
List<FirewallRuleVO> firewallEgressRulesToApply = _firewallDao.listByNetworkPurposeTrafficType(networkId, Purpose.Firewall, FirewallRule.TrafficType.Egress);
|
|
if (firewallEgressRulesToApply.size() == 0) {
|
|
NetworkOfferingVO offering = _networkOfferingDao.findById(network.getNetworkOfferingId());
|
|
//there are no egress rules then apply the default egress rule
|
|
DataCenter zone = _dcDao.findById(network.getDataCenterId());
|
|
if (offering.getEgressDefaultPolicy() && _networkModel.areServicesSupportedInNetwork(network.getId(), Service.Firewall) &&
|
|
(network.getGuestType() == Network.GuestType.Isolated || (network.getGuestType() == Network.GuestType.Shared && zone.getNetworkType() == NetworkType.Advanced))) {
|
|
// add default egress rule to accept the traffic
|
|
_firewallMgr.applyDefaultEgressFirewallRule(network.getId(), true);
|
|
}
|
|
} else {
|
|
if (!_firewallMgr.applyFirewallRules(firewallEgressRulesToApply, false, caller)) {
|
|
s_logger.warn("Failed to reapply firewall Egress rule(s) as a part of network id=" + networkId + " restart");
|
|
success = false;
|
|
}
|
|
}
|
|
|
|
// apply port forwarding rules
|
|
if (!_rulesMgr.applyPortForwardingRulesForNetwork(networkId, false, caller)) {
|
|
s_logger.warn("Failed to reapply port forwarding rule(s) as a part of network id=" + networkId + " restart");
|
|
success = false;
|
|
}
|
|
|
|
// apply static nat rules
|
|
if (!_rulesMgr.applyStaticNatRulesForNetwork(networkId, false, caller)) {
|
|
s_logger.warn("Failed to reapply static nat rule(s) as a part of network id=" + networkId + " restart");
|
|
success = false;
|
|
}
|
|
|
|
// apply public load balancer rules
|
|
if (!_lbMgr.applyLoadBalancersForNetwork(networkId, Scheme.Public)) {
|
|
s_logger.warn("Failed to reapply Public load balancer rules as a part of network id=" + networkId + " restart");
|
|
success = false;
|
|
}
|
|
|
|
// apply internal load balancer rules
|
|
if (!_lbMgr.applyLoadBalancersForNetwork(networkId, Scheme.Internal)) {
|
|
s_logger.warn("Failed to reapply internal load balancer rules as a part of network id=" + networkId + " restart");
|
|
success = false;
|
|
}
|
|
|
|
// apply vpn rules
|
|
List<? extends RemoteAccessVpn> vpnsToReapply = _vpnMgr.listRemoteAccessVpns(networkId);
|
|
if (vpnsToReapply != null) {
|
|
for (RemoteAccessVpn vpn : vpnsToReapply) {
|
|
// Start remote access vpn per ip
|
|
if (_vpnMgr.startRemoteAccessVpn(vpn.getServerAddressId(), false) == null) {
|
|
s_logger.warn("Failed to reapply vpn rules as a part of network id=" + networkId + " restart");
|
|
success = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
//apply network ACLs
|
|
if (!_networkACLMgr.applyACLToNetwork(networkId)) {
|
|
s_logger.warn("Failed to reapply network ACLs as a part of of network id=" + networkId + " restart");
|
|
success = false;
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
protected boolean prepareElement(NetworkElement element, Network network,
|
|
NicProfile profile, VirtualMachineProfile vmProfile,
|
|
DeployDestination dest, ReservationContext context) throws InsufficientCapacityException,
|
|
ConcurrentOperationException, ResourceUnavailableException {
|
|
element.prepare(network, profile, vmProfile, dest, context);
|
|
if (vmProfile.getType() == Type.User && element.getProvider() != null) {
|
|
if (_networkModel.areServicesSupportedInNetwork(network.getId(), Service.Dhcp) &&
|
|
_networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.Dhcp, element.getProvider()) &&
|
|
element instanceof DhcpServiceProvider ) {
|
|
DhcpServiceProvider sp = (DhcpServiceProvider) element;
|
|
Map <Capability, String> dhcpCapabilities = element.getCapabilities().get(Service.Dhcp);
|
|
String supportsMultipleSubnets = dhcpCapabilities.get(Capability.DhcpAccrossMultipleSubnets);
|
|
if ((supportsMultipleSubnets != null && Boolean.valueOf(supportsMultipleSubnets)) && profile.getIp6Address() == null) {
|
|
if (!sp.configDhcpSupportForSubnet(network, profile, vmProfile, dest, context)) {
|
|
return false;
|
|
}
|
|
}
|
|
sp.addDhcpEntry(network, profile, vmProfile, dest, context);
|
|
}
|
|
if (_networkModel.areServicesSupportedInNetwork(network.getId(), Service.UserData) &&
|
|
_networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.UserData, element.getProvider()) &&
|
|
element instanceof UserDataServiceProvider) {
|
|
UserDataServiceProvider sp = (UserDataServiceProvider) element;
|
|
sp.addPasswordAndUserdata(network, profile, vmProfile, dest, context);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@DB
|
|
protected void updateNic(NicVO nic, long networkId, int count) {
|
|
Transaction txn = Transaction.currentTxn();
|
|
txn.start();
|
|
_nicDao.update(nic.getId(), nic);
|
|
|
|
if (nic.getVmType() == VirtualMachine.Type.User) {
|
|
s_logger.debug("Changing active number of nics for network id=" + networkId + " on " + count);
|
|
_networksDao.changeActiveNicsBy(networkId, count);
|
|
}
|
|
|
|
if (nic.getVmType() == VirtualMachine.Type.User || (nic.getVmType() == VirtualMachine.Type.DomainRouter && _networksDao.findById(networkId).getTrafficType() == TrafficType.Guest)) {
|
|
_networksDao.setCheckForGc(networkId);
|
|
}
|
|
|
|
txn.commit();
|
|
}
|
|
|
|
@Override
|
|
public void prepare(VirtualMachineProfile vmProfile, DeployDestination dest, ReservationContext context) throws InsufficientCapacityException,
|
|
ConcurrentOperationException, ResourceUnavailableException {
|
|
List<NicVO> nics = _nicDao.listByVmId(vmProfile.getId());
|
|
|
|
// we have to implement default nics first - to ensure that default network elements start up first in multiple
|
|
//nics case
|
|
// (need for setting DNS on Dhcp to domR's Ip4 address)
|
|
Collections.sort(nics, new Comparator<NicVO>() {
|
|
|
|
@Override
|
|
public int compare(NicVO nic1, NicVO nic2) {
|
|
boolean isDefault1 = nic1.isDefaultNic();
|
|
boolean isDefault2 = nic2.isDefaultNic();
|
|
|
|
return (isDefault1 ^ isDefault2) ? ((isDefault1 ^ true) ? 1 : -1) : 0;
|
|
}
|
|
});
|
|
|
|
for (NicVO nic : nics) {
|
|
Pair<NetworkGuru, NetworkVO> implemented = implementNetwork(nic.getNetworkId(), dest, context);
|
|
if (implemented.first() == null) {
|
|
s_logger.warn("Failed to implement network id=" + nic.getNetworkId() + " as a part of preparing nic id=" + nic.getId());
|
|
throw new CloudRuntimeException("Failed to implement network id=" + nic.getNetworkId() + " as a part preparing nic id=" +nic.getId());
|
|
}
|
|
|
|
NetworkVO network = implemented.second();
|
|
NicProfile profile = prepareNic(vmProfile, dest, context, nic.getId(), network);
|
|
vmProfile.addNic(profile);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public NicProfile prepareNic(VirtualMachineProfile vmProfile, DeployDestination
|
|
dest, ReservationContext context, long nicId, Network network)
|
|
throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException,
|
|
ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
|
|
|
|
Integer networkRate = _networkModel.getNetworkRate(network.getId(), vmProfile.getId());
|
|
NetworkGuru guru = AdapterBase.getAdapterByName(_networkGurus, network.getGuruName());
|
|
NicVO nic = _nicDao.findById(nicId);
|
|
|
|
NicProfile profile = null;
|
|
if (nic.getReservationStrategy() == Nic.ReservationStrategy.Start) {
|
|
nic.setState(Nic.State.Reserving);
|
|
nic.setReservationId(context.getReservationId());
|
|
_nicDao.update(nic.getId(), nic);
|
|
URI broadcastUri = nic.getBroadcastUri();
|
|
if (broadcastUri == null) {
|
|
broadcastUri = network.getBroadcastUri();
|
|
}
|
|
|
|
URI isolationUri = nic.getIsolationUri();
|
|
|
|
profile = new NicProfile(nic, network, broadcastUri, isolationUri,
|
|
|
|
networkRate, _networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag(vmProfile.getHypervisorType(), network));
|
|
guru.reserve(profile, network, vmProfile, dest, context);
|
|
nic.setIp4Address(profile.getIp4Address());
|
|
nic.setAddressFormat(profile.getFormat());
|
|
nic.setIp6Address(profile.getIp6Address());
|
|
nic.setMacAddress(profile.getMacAddress());
|
|
nic.setIsolationUri(profile.getIsolationUri());
|
|
nic.setBroadcastUri(profile.getBroadCastUri());
|
|
nic.setReserver(guru.getName());
|
|
nic.setState(Nic.State.Reserved);
|
|
nic.setNetmask(profile.getNetmask());
|
|
nic.setGateway(profile.getGateway());
|
|
|
|
if (profile.getStrategy() != null) {
|
|
nic.setReservationStrategy(profile.getStrategy());
|
|
}
|
|
|
|
updateNic(nic, network.getId(), 1);
|
|
} else {
|
|
profile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(),
|
|
networkRate, _networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag(vmProfile.getHypervisorType(), network));
|
|
guru.updateNicProfile(profile, network);
|
|
nic.setState(Nic.State.Reserved);
|
|
updateNic(nic, network.getId(), 1);
|
|
}
|
|
|
|
for (NetworkElement element : _networkElements) {
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Asking " + element.getName() + " to prepare for " + nic);
|
|
}
|
|
if(!prepareElement(element, network, profile, vmProfile, dest, context)) {
|
|
throw new InsufficientAddressCapacityException("unable to configure the dhcp service, due to insufficiant address capacity",Network.class, network.getId());
|
|
}
|
|
}
|
|
|
|
profile.setSecurityGroupEnabled(_networkModel.isSecurityGroupSupportedInNetwork(network));
|
|
guru.updateNicProfile(profile, network);
|
|
return profile;
|
|
}
|
|
|
|
@Override
|
|
public void prepareNicForMigration(VirtualMachineProfile vm, DeployDestination dest) {
|
|
List<NicVO> nics = _nicDao.listByVmId(vm.getId());
|
|
ReservationContext context = new ReservationContextImpl(UUID.randomUUID().toString(), null, null);
|
|
for (NicVO nic : nics) {
|
|
NetworkVO network = _networksDao.findById(nic.getNetworkId());
|
|
Integer networkRate = _networkModel.getNetworkRate(network.getId(), vm.getId());
|
|
|
|
NetworkGuru guru = AdapterBase.getAdapterByName(_networkGurus, network.getGuruName());
|
|
NicProfile profile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), networkRate,
|
|
_networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag(vm.getHypervisorType(), network));
|
|
if(guru instanceof NetworkMigrationResponder){
|
|
if(!((NetworkMigrationResponder) guru).prepareMigration(profile, network, vm, dest, context)){
|
|
s_logger.error("NetworkGuru "+guru+" prepareForMigration failed."); // XXX: Transaction error
|
|
}
|
|
}
|
|
for (NetworkElement element : _networkElements) {
|
|
if(element instanceof NetworkMigrationResponder){
|
|
if(!((NetworkMigrationResponder) element).prepareMigration(profile, network, vm, dest, context)){
|
|
s_logger.error("NetworkElement "+element+" prepareForMigration failed."); // XXX: Transaction error
|
|
}
|
|
}
|
|
}
|
|
guru.updateNicProfile(profile, network);
|
|
vm.addNic(profile);
|
|
}
|
|
}
|
|
|
|
private NicProfile findNicProfileById(VirtualMachineProfile vm, long id){
|
|
for(NicProfile nic: vm.getNics()){
|
|
if(nic.getId() == id){
|
|
return nic;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public void commitNicForMigration(
|
|
VirtualMachineProfile src,
|
|
VirtualMachineProfile dst) {
|
|
for(NicProfile nicSrc: src.getNics()){
|
|
NetworkVO network = _networksDao.findById(nicSrc.getNetworkId());
|
|
NetworkGuru guru = AdapterBase.getAdapterByName(_networkGurus, network.getGuruName());
|
|
NicProfile nicDst = findNicProfileById(dst, nicSrc.getId());
|
|
ReservationContext src_context = new ReservationContextImpl(nicSrc.getReservationId(), null, null);
|
|
ReservationContext dst_context = new ReservationContextImpl(nicDst.getReservationId(), null, null);
|
|
|
|
if(guru instanceof NetworkMigrationResponder){
|
|
((NetworkMigrationResponder) guru).commitMigration(nicSrc, network, src, src_context, dst_context);
|
|
}
|
|
for (NetworkElement element : _networkElements) {
|
|
if(element instanceof NetworkMigrationResponder){
|
|
((NetworkMigrationResponder) element).commitMigration(nicSrc, network, src, src_context, dst_context);
|
|
}
|
|
}
|
|
// update the reservation id
|
|
NicVO nicVo = _nicDao.findById(nicDst.getId());
|
|
nicVo.setReservationId(nicDst.getReservationId());
|
|
_nicDao.persist(nicVo);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void rollbackNicForMigration(
|
|
VirtualMachineProfile src,
|
|
VirtualMachineProfile dst) {
|
|
for(NicProfile nicDst: dst.getNics()){
|
|
NetworkVO network = _networksDao.findById(nicDst.getNetworkId());
|
|
NetworkGuru guru = AdapterBase.getAdapterByName(_networkGurus, network.getGuruName());
|
|
NicProfile nicSrc = findNicProfileById(src, nicDst.getId());
|
|
ReservationContext src_context = new ReservationContextImpl(nicSrc.getReservationId(), null, null);
|
|
ReservationContext dst_context = new ReservationContextImpl(nicDst.getReservationId(), null, null);
|
|
|
|
if(guru instanceof NetworkMigrationResponder){
|
|
((NetworkMigrationResponder) guru).rollbackMigration(nicDst, network, dst, src_context, dst_context);
|
|
}
|
|
for (NetworkElement element : _networkElements) {
|
|
if(element instanceof NetworkMigrationResponder){
|
|
((NetworkMigrationResponder) element).rollbackMigration(nicDst, network, dst, src_context, dst_context);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
@DB
|
|
public void release(VirtualMachineProfile vmProfile, boolean forced) throws
|
|
ConcurrentOperationException, ResourceUnavailableException {
|
|
List<NicVO> nics = _nicDao.listByVmId(vmProfile.getId());
|
|
for (NicVO nic : nics) {
|
|
releaseNic(vmProfile, nic.getId());
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@DB
|
|
public void releaseNic(VirtualMachineProfile vmProfile, Nic nic)
|
|
throws ConcurrentOperationException, ResourceUnavailableException {
|
|
releaseNic(vmProfile, nic.getId());
|
|
}
|
|
|
|
@DB
|
|
protected void releaseNic(VirtualMachineProfile vmProfile, long nicId)
|
|
throws ConcurrentOperationException, ResourceUnavailableException {
|
|
//lock the nic
|
|
Transaction txn = Transaction.currentTxn();
|
|
txn.start();
|
|
|
|
NicVO nic = _nicDao.lockRow(nicId, true);
|
|
if (nic == null) {
|
|
throw new ConcurrentOperationException("Unable to acquire lock on nic " + nic);
|
|
}
|
|
|
|
Nic.State originalState = nic.getState();
|
|
NetworkVO network = _networksDao.findById(nic.getNetworkId());
|
|
|
|
if (originalState == Nic.State.Reserved || originalState == Nic.State.Reserving) {
|
|
if (nic.getReservationStrategy() == Nic.ReservationStrategy.Start) {
|
|
NetworkGuru guru = AdapterBase.getAdapterByName(_networkGurus, network.getGuruName());
|
|
nic.setState(Nic.State.Releasing);
|
|
_nicDao.update(nic.getId(), nic);
|
|
NicProfile profile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), null,
|
|
_networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag(vmProfile.getHypervisorType(), network));
|
|
if (guru.release(profile, vmProfile, nic.getReservationId())) {
|
|
applyProfileToNicForRelease(nic, profile);
|
|
nic.setState(Nic.State.Allocated);
|
|
if (originalState == Nic.State.Reserved) {
|
|
updateNic(nic, network.getId(), -1);
|
|
} else {
|
|
_nicDao.update(nic.getId(), nic);
|
|
}
|
|
}
|
|
//commit the transaction before proceeding releasing nic profile on the network elements
|
|
txn.commit();
|
|
|
|
// Perform release on network elements
|
|
for (NetworkElement element : _networkElements) {
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Asking " + element.getName() + " to release " + nic);
|
|
}
|
|
//NOTE: Context appear to never be used in release method
|
|
//implementations. Consider removing it from interface Element
|
|
element.release(network, profile, vmProfile, null);
|
|
}
|
|
|
|
} else {
|
|
nic.setState(Nic.State.Allocated);
|
|
updateNic(nic, network.getId(), -1);
|
|
txn.commit();
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void cleanupNics(VirtualMachineProfile vm) {
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Cleaning network for vm: " + vm.getId());
|
|
}
|
|
|
|
List<NicVO> nics = _nicDao.listByVmId(vm.getId());
|
|
for (NicVO nic : nics) {
|
|
removeNic(vm, nic);
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
public void removeNic(VirtualMachineProfile vm, Nic nic) {
|
|
removeNic(vm, _nicDao.findById(nic.getId()));
|
|
}
|
|
|
|
|
|
protected void removeNic(VirtualMachineProfile vm, NicVO nic) {
|
|
nic.setState(Nic.State.Deallocating);
|
|
_nicDao.update(nic.getId(), nic);
|
|
NetworkVO network = _networksDao.findById(nic.getNetworkId());
|
|
NicProfile profile = new NicProfile(nic, network, null, null, null,
|
|
_networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag(vm.getHypervisorType(), network));
|
|
|
|
/*
|
|
* We need to release the nics with a Create ReservationStrategy here
|
|
* because the nic is now being removed.
|
|
*/
|
|
if (nic.getReservationStrategy() == Nic.ReservationStrategy.Create) {
|
|
for (NetworkElement element : _networkElements) {
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Asking " + element.getName() + " to release " + nic);
|
|
}
|
|
try {
|
|
element.release(network, profile, vm, null);
|
|
} catch (ConcurrentOperationException ex) {
|
|
s_logger.warn("release failed during the nic " + nic.toString() + " removeNic due to ", ex);
|
|
} catch (ResourceUnavailableException ex) {
|
|
s_logger.warn("release failed during the nic " + nic.toString() + " removeNic due to ", ex);
|
|
}
|
|
}
|
|
}
|
|
|
|
// remove the dhcpservice ip if this is the last nic in subnet.
|
|
if (vm.getType() == Type.User && isDhcpAccrossMultipleSubnetsSupported(network) && isLastNicInSubnet(nic) &&
|
|
network.getTrafficType() == TrafficType.Guest && network.getGuestType() == GuestType.Shared) {
|
|
removeDhcpServiceInSubnet(nic);
|
|
}
|
|
NetworkGuru guru = AdapterBase.getAdapterByName(_networkGurus, network.getGuruName());
|
|
guru.deallocate(network, profile, vm);
|
|
_nicDao.remove(nic.getId());
|
|
s_logger.debug("Removed nic id=" + nic.getId());
|
|
//remove the secondary ip addresses corresponding to to this nic
|
|
if (!removeVmSecondaryIpsOfNic(nic.getId())) {
|
|
s_logger.debug("Removing nic " + nic.getId() + " secondary ip addreses failed");
|
|
}
|
|
}
|
|
|
|
public boolean isDhcpAccrossMultipleSubnetsSupported(Network network) {
|
|
DhcpServiceProvider dhcpServiceProvider = getDhcpServiceProvider(network);
|
|
Map <Network.Capability, String> capabilities = dhcpServiceProvider.getCapabilities().get(Network.Service.Dhcp);
|
|
String supportsMultipleSubnets = capabilities.get(Network.Capability.DhcpAccrossMultipleSubnets);
|
|
if (supportsMultipleSubnets != null && Boolean.valueOf(supportsMultipleSubnets)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private boolean isLastNicInSubnet(NicVO nic) {
|
|
if (_nicDao.listByNetworkIdTypeAndGatewayAndBroadcastUri(nic.getNetworkId(), VirtualMachine.Type.User, nic.getGateway(), nic.getBroadcastUri()).size() > 1) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@DB
|
|
@Override
|
|
public void removeDhcpServiceInSubnet(Nic nic) {
|
|
Network network = _networksDao.findById(nic.getNetworkId());
|
|
DhcpServiceProvider dhcpServiceProvider = getDhcpServiceProvider(network);
|
|
try {
|
|
NicIpAliasVO ipAlias = _nicIpAliasDao.findByGatewayAndNetworkIdAndState(nic.getGateway(), network.getId(), NicIpAlias.state.active);
|
|
if (ipAlias != null) {
|
|
ipAlias.setState(NicIpAlias.state.revoked);
|
|
Transaction txn = Transaction.currentTxn();
|
|
txn.start();
|
|
_nicIpAliasDao.update(ipAlias.getId(),ipAlias);
|
|
IPAddressVO aliasIpaddressVo = _publicIpAddressDao.findByIpAndSourceNetworkId(ipAlias.getNetworkId(), ipAlias.getIp4Address());
|
|
_publicIpAddressDao.unassignIpAddress(aliasIpaddressVo.getId());
|
|
txn.commit();
|
|
if (!dhcpServiceProvider.removeDhcpSupportForSubnet(network)) {
|
|
s_logger.warn("Failed to remove the ip alias on the router, marking it as removed in db and freed the allocated ip " + ipAlias.getIp4Address());
|
|
}
|
|
}
|
|
}
|
|
catch (ResourceUnavailableException e) {
|
|
//failed to remove the dhcpconfig on the router.
|
|
s_logger.info ("Unable to delete the ip alias due to unable to contact the virtualrouter.");
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
public void expungeNics(VirtualMachineProfile vm) {
|
|
List<NicVO> nics = _nicDao.listByVmIdIncludingRemoved(vm.getId());
|
|
for (NicVO nic : nics) {
|
|
_nicDao.expunge(nic.getId());
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
@DB
|
|
public Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway,
|
|
String cidr, String vlanId, String networkDomain, Account owner, Long domainId,
|
|
PhysicalNetwork pNtwk, long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, String ip6Gateway, String ip6Cidr,
|
|
Boolean isDisplayNetworkEnabled, String isolatedPvlan)
|
|
throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException {
|
|
|
|
NetworkOfferingVO ntwkOff = _networkOfferingDao.findById(networkOfferingId);
|
|
// this method supports only guest network creation
|
|
if (ntwkOff.getTrafficType() != TrafficType.Guest) {
|
|
s_logger.warn("Only guest networks can be created using this method");
|
|
return null;
|
|
}
|
|
|
|
boolean updateResourceCount = resourceCountNeedsUpdate(ntwkOff, aclType);
|
|
//check resource limits
|
|
if (updateResourceCount) {
|
|
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.network);
|
|
}
|
|
|
|
// Validate network offering
|
|
if (ntwkOff.getState() != NetworkOffering.State.Enabled) {
|
|
// see NetworkOfferingVO
|
|
InvalidParameterValueException ex = new InvalidParameterValueException("Can't use specified network offering id as its stat is not " + NetworkOffering.State.Enabled);
|
|
ex.addProxyObject(ntwkOff.getUuid(), "networkOfferingId");
|
|
throw ex;
|
|
}
|
|
|
|
// Validate physical network
|
|
if (pNtwk.getState() != PhysicalNetwork.State.Enabled) {
|
|
// see PhysicalNetworkVO.java
|
|
InvalidParameterValueException ex = new InvalidParameterValueException("Specified physical network id is" +
|
|
" in incorrect state:" + pNtwk.getState());
|
|
ex.addProxyObject(pNtwk.getUuid(), "physicalNetworkId");
|
|
throw ex;
|
|
}
|
|
|
|
boolean ipv6 = false;
|
|
|
|
if (ip6Gateway != null && ip6Cidr != null) {
|
|
ipv6 = true;
|
|
}
|
|
// Validate zone
|
|
DataCenterVO zone = _dcDao.findById(zoneId);
|
|
if (zone.getNetworkType() == NetworkType.Basic) {
|
|
if (ipv6) {
|
|
throw new InvalidParameterValueException("IPv6 is not supported in Basic zone");
|
|
}
|
|
|
|
// In Basic zone the network should have aclType=Domain, domainId=1, subdomainAccess=true
|
|
if (aclType == null || aclType != ACLType.Domain) {
|
|
throw new InvalidParameterValueException("Only AclType=Domain can be specified for network creation in Basic zone");
|
|
}
|
|
|
|
// Only one guest network is supported in Basic zone
|
|
List<NetworkVO> guestNetworks = _networksDao.listByZoneAndTrafficType(zone.getId(), TrafficType.Guest);
|
|
if (!guestNetworks.isEmpty()) {
|
|
throw new InvalidParameterValueException("Can't have more than one Guest network in zone with network type "
|
|
+ NetworkType.Basic);
|
|
}
|
|
|
|
// if zone is basic, only Shared network offerings w/o source nat service are allowed
|
|
if (!(ntwkOff.getGuestType() == GuestType.Shared &&
|
|
!_networkModel.areServicesSupportedByNetworkOffering(ntwkOff.getId(), Service.SourceNat))) {
|
|
throw new InvalidParameterValueException("For zone of type " + NetworkType.Basic + " only offerings of " +
|
|
"guestType " + GuestType.Shared + " with disabled " + Service.SourceNat.getName()
|
|
+ " service are allowed");
|
|
}
|
|
|
|
if (domainId == null || domainId != Domain.ROOT_DOMAIN) {
|
|
throw new InvalidParameterValueException("Guest network in Basic zone should be dedicated to ROOT domain");
|
|
}
|
|
|
|
if (subdomainAccess == null) {
|
|
subdomainAccess = true;
|
|
} else if (!subdomainAccess) {
|
|
throw new InvalidParameterValueException("Subdomain access should be set to true for the" +
|
|
" guest network in the Basic zone");
|
|
}
|
|
|
|
if (vlanId == null) {
|
|
vlanId = Vlan.UNTAGGED;
|
|
} else {
|
|
if (!vlanId.equalsIgnoreCase(Vlan.UNTAGGED)) {
|
|
throw new InvalidParameterValueException("Only vlan " + Vlan.UNTAGGED + " can be created in " +
|
|
"the zone of type " + NetworkType.Basic);
|
|
}
|
|
}
|
|
|
|
} else if (zone.getNetworkType() == NetworkType.Advanced) {
|
|
if (zone.isSecurityGroupEnabled()) {
|
|
if (ipv6) {
|
|
throw new InvalidParameterValueException("IPv6 is not supported with security group!");
|
|
}
|
|
if (isolatedPvlan != null) {
|
|
throw new InvalidParameterValueException("Isolated Private VLAN is not supported with security group!");
|
|
}
|
|
// Only Account specific Isolated network with sourceNat service disabled are allowed in security group
|
|
// enabled zone
|
|
if ( ntwkOff.getGuestType() != GuestType.Shared ){
|
|
throw new InvalidParameterValueException("Only shared guest network can be created in security group enabled zone");
|
|
}
|
|
if ( _networkModel.areServicesSupportedByNetworkOffering(ntwkOff.getId(), Service.SourceNat)) {
|
|
throw new InvalidParameterValueException("Service SourceNat is not allowed in security group enabled zone");
|
|
}
|
|
if (!( _networkModel.areServicesSupportedByNetworkOffering(ntwkOff.getId(), Service.SecurityGroup))) {
|
|
throw new InvalidParameterValueException("network must have SecurityGroup provider in security group enabled zone");
|
|
}
|
|
}
|
|
|
|
//don't allow eip/elb networks in Advance zone
|
|
if (ntwkOff.getElasticIp() || ntwkOff.getElasticLb()) {
|
|
throw new InvalidParameterValueException("Elastic IP and Elastic LB services are supported in zone of type " + NetworkType.Basic);
|
|
}
|
|
}
|
|
|
|
// VlanId can be specified only when network offering supports it
|
|
boolean vlanSpecified = (vlanId != null);
|
|
if (vlanSpecified != ntwkOff.getSpecifyVlan()) {
|
|
if (vlanSpecified) {
|
|
throw new InvalidParameterValueException("Can't specify vlan; corresponding offering says specifyVlan=false");
|
|
} else {
|
|
throw new InvalidParameterValueException("Vlan has to be specified; corresponding offering says specifyVlan=true");
|
|
}
|
|
}
|
|
|
|
if (vlanSpecified) {
|
|
//don't allow to specify vlan tag used by physical network for dynamic vlan allocation
|
|
if (_dcDao.findVnet(zoneId, pNtwk.getId(), vlanId).size() > 0) {
|
|
throw new InvalidParameterValueException("The VLAN tag " + vlanId
|
|
+ " is already being used for dynamic vlan allocation for the guest network in zone " + zone.getName());
|
|
}
|
|
|
|
String uri = "vlan://" + vlanId;
|
|
// For Isolated networks, don't allow to create network with vlan that already exists in the zone
|
|
if (ntwkOff.getGuestType() == GuestType.Isolated) {
|
|
if (_networksDao.countByZoneAndUri(zoneId, uri) > 0) {
|
|
throw new InvalidParameterValueException("Network with vlan " + vlanId + " already exists in zone " + zoneId);
|
|
} else {
|
|
List<DataCenterVnetVO> dcVnets = _datacenterVnetDao.findVnet(zoneId, vlanId.toString());
|
|
//for the network that is created as part of private gateway,
|
|
//the vnet is not coming from the data center vnet table, so the list can be empty
|
|
if (!dcVnets.isEmpty()) {
|
|
DataCenterVnetVO dcVnet = dcVnets.get(0);
|
|
// Fail network creation if specified vlan is dedicated to a different account
|
|
if (dcVnet.getAccountGuestVlanMapId() != null) {
|
|
Long accountGuestVlanMapId = dcVnet.getAccountGuestVlanMapId();
|
|
AccountGuestVlanMapVO map = _accountGuestVlanMapDao.findById(accountGuestVlanMapId);
|
|
if (map.getAccountId() != owner.getAccountId()) {
|
|
throw new InvalidParameterValueException("Vlan " + vlanId + " is dedicated to a different account");
|
|
}
|
|
// Fail network creation if owner has a dedicated range of vlans but the specified vlan belongs to the system pool
|
|
} else {
|
|
List<AccountGuestVlanMapVO> maps = _accountGuestVlanMapDao.listAccountGuestVlanMapsByAccount(owner.getAccountId());
|
|
if (maps != null && !maps.isEmpty()) {
|
|
int vnetsAllocatedToAccount = _datacenterVnetDao.countVnetsAllocatedToAccount(zoneId, owner.getAccountId());
|
|
int vnetsDedicatedToAccount = _datacenterVnetDao.countVnetsDedicatedToAccount(zoneId, owner.getAccountId());
|
|
if (vnetsAllocatedToAccount < vnetsDedicatedToAccount) {
|
|
throw new InvalidParameterValueException("Specified vlan " + vlanId + " doesn't belong" +
|
|
" to the vlan range dedicated to the owner "+ owner.getAccountName());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// don't allow to creating shared network with given Vlan ID, if there already exists a isolated network or
|
|
// shared network with same Vlan ID in the zone
|
|
if (_networksDao.countByZoneUriAndGuestType(zoneId, uri, GuestType.Isolated) > 0 ||
|
|
_networksDao.countByZoneUriAndGuestType(zoneId, uri, GuestType.Shared) > 0) {
|
|
throw new InvalidParameterValueException("There is a isolated/shared network with vlan id: " +
|
|
vlanId + " already exists " + "in zone " + zoneId);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
// If networkDomain is not specified, take it from the global configuration
|
|
if (_networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.Dns)) {
|
|
Map<Network.Capability, String> dnsCapabilities = _networkModel.getNetworkOfferingServiceCapabilities
|
|
(_configMgr.getNetworkOffering(networkOfferingId), Service.Dns);
|
|
String isUpdateDnsSupported = dnsCapabilities.get(Capability.AllowDnsSuffixModification);
|
|
if (isUpdateDnsSupported == null || !Boolean.valueOf(isUpdateDnsSupported)) {
|
|
if (networkDomain != null) {
|
|
// TBD: NetworkOfferingId and zoneId. Send uuids instead.
|
|
throw new InvalidParameterValueException("Domain name change is not supported by network offering id="
|
|
+ networkOfferingId + " in zone id=" + zoneId);
|
|
}
|
|
} else {
|
|
if (networkDomain == null) {
|
|
// 1) Get networkDomain from the corresponding account/domain/zone
|
|
if (aclType == ACLType.Domain) {
|
|
networkDomain = _networkModel.getDomainNetworkDomain(domainId, zoneId);
|
|
} else if (aclType == ACLType.Account) {
|
|
networkDomain = _networkModel.getAccountNetworkDomain(owner.getId(), zoneId);
|
|
}
|
|
|
|
// 2) If null, generate networkDomain using domain suffix from the global config variables
|
|
if (networkDomain == null) {
|
|
networkDomain = "cs" + Long.toHexString(owner.getId()) + _configServer.getConfigValue(Config.GuestDomainSuffix.key(), Config.ConfigurationParameterScope.zone.toString(), zoneId);
|
|
}
|
|
|
|
} else {
|
|
// validate network domain
|
|
if (!NetUtils.verifyDomainName(networkDomain)) {
|
|
throw new InvalidParameterValueException(
|
|
"Invalid network domain. Total length shouldn't exceed 190 chars. Each domain " +
|
|
"label must be between 1 and 63 characters long, can contain ASCII letters 'a' through 'z', the digits '0' through '9', "
|
|
+ "and the hyphen ('-'); can't start or end with \"-\"");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// In Advance zone Cidr for Shared networks and Isolated networks w/o source nat service can't be NULL - 2.2.x
|
|
// limitation, remove after we introduce support for multiple ip ranges
|
|
// with different Cidrs for the same Shared network
|
|
boolean cidrRequired = zone.getNetworkType() == NetworkType.Advanced && ntwkOff.getTrafficType() == TrafficType.Guest
|
|
&& (ntwkOff.getGuestType() == GuestType.Shared || (ntwkOff.getGuestType() == GuestType.Isolated
|
|
&& !_networkModel.areServicesSupportedByNetworkOffering(ntwkOff.getId(), Service.SourceNat)));
|
|
if (cidr == null && ip6Cidr == null && cidrRequired) {
|
|
throw new InvalidParameterValueException("StartIp/endIp/gateway/netmask are required when create network of" +
|
|
" type " + Network.GuestType.Shared + " and network of type " + GuestType.Isolated + " with service "
|
|
+ Service.SourceNat.getName() + " disabled");
|
|
}
|
|
|
|
// No cidr can be specified in Basic zone
|
|
if (zone.getNetworkType() == NetworkType.Basic && cidr != null) {
|
|
throw new InvalidParameterValueException("StartIp/endIp/gateway/netmask can't be specified for zone of type " + NetworkType.Basic);
|
|
}
|
|
|
|
// Check if cidr is RFC1918 compliant if the network is Guest Isolated for IPv4
|
|
if (cidr != null && ntwkOff.getGuestType() == Network.GuestType.Isolated && ntwkOff.getTrafficType() == TrafficType.Guest) {
|
|
if (!NetUtils.validateGuestCidr(cidr)) {
|
|
throw new InvalidParameterValueException("Virtual Guest Cidr " + cidr + " is not RFC1918 compliant");
|
|
}
|
|
}
|
|
|
|
Transaction txn = Transaction.currentTxn();
|
|
txn.start();
|
|
|
|
Long physicalNetworkId = null;
|
|
if (pNtwk != null) {
|
|
physicalNetworkId = pNtwk.getId();
|
|
}
|
|
DataCenterDeployment plan = new DataCenterDeployment(zoneId, null, null, null, null, physicalNetworkId);
|
|
NetworkVO userNetwork = new NetworkVO();
|
|
userNetwork.setNetworkDomain(networkDomain);
|
|
|
|
if (cidr != null && gateway != null) {
|
|
userNetwork.setCidr(cidr);
|
|
userNetwork.setGateway(gateway);
|
|
}
|
|
|
|
if (ip6Cidr != null && ip6Gateway != null) {
|
|
userNetwork.setIp6Cidr(ip6Cidr);
|
|
userNetwork.setIp6Gateway(ip6Gateway);
|
|
}
|
|
|
|
if (vlanId != null) {
|
|
if (isolatedPvlan == null) {
|
|
userNetwork.setBroadcastUri(URI.create("vlan://" + vlanId));
|
|
if (!vlanId.equalsIgnoreCase(Vlan.UNTAGGED)) {
|
|
userNetwork.setBroadcastDomainType(BroadcastDomainType.Vlan);
|
|
} else {
|
|
userNetwork.setBroadcastDomainType(BroadcastDomainType.Native);
|
|
}
|
|
} else {
|
|
if (vlanId.equalsIgnoreCase(Vlan.UNTAGGED)) {
|
|
throw new InvalidParameterValueException("Cannot support pvlan with untagged primary vlan!");
|
|
}
|
|
userNetwork.setBroadcastUri(NetUtils.generateUriForPvlan(vlanId, isolatedPvlan));
|
|
userNetwork.setBroadcastDomainType(BroadcastDomainType.Pvlan);
|
|
}
|
|
}
|
|
|
|
List<? extends Network> networks = setupNetwork(owner, ntwkOff, userNetwork, plan, name, displayText, true, domainId, aclType, subdomainAccess, vpcId,
|
|
isDisplayNetworkEnabled);
|
|
|
|
Network network = null;
|
|
if (networks == null || networks.isEmpty()) {
|
|
throw new CloudRuntimeException("Fail to create a network");
|
|
} else {
|
|
if (networks.size() > 0 && networks.get(0).getGuestType() == Network.GuestType.Isolated &&
|
|
networks.get(0).getTrafficType() == TrafficType.Guest) {
|
|
Network defaultGuestNetwork = networks.get(0);
|
|
for (Network nw : networks) {
|
|
if (nw.getCidr() != null && nw.getCidr().equals(zone.getGuestNetworkCidr())) {
|
|
defaultGuestNetwork = nw;
|
|
}
|
|
}
|
|
network = defaultGuestNetwork;
|
|
} else {
|
|
// For shared network
|
|
network = networks.get(0);
|
|
}
|
|
}
|
|
|
|
if (updateResourceCount) {
|
|
_resourceLimitMgr.incrementResourceCount(owner.getId(), ResourceType.network);
|
|
}
|
|
|
|
txn.commit();
|
|
CallContext.current().setEventDetails("Network Id: " + network.getId());
|
|
return network;
|
|
}
|
|
|
|
@Override
|
|
@DB
|
|
public boolean shutdownNetwork(long networkId, ReservationContext context, boolean cleanupElements) {
|
|
boolean result = false;
|
|
NetworkVO network = null;
|
|
try {
|
|
//do global lock for the network
|
|
network = _networksDao.acquireInLockTable(networkId, getNetworkLockTimeout());
|
|
if (network == null) {
|
|
s_logger.warn("Unable to acquire lock for the network " + network + " as a part of network shutdown");
|
|
return false;
|
|
}
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Lock is acquired for network " + network + " as a part of network shutdown");
|
|
}
|
|
|
|
if (network.getState() == Network.State.Allocated) {
|
|
s_logger.debug("Network is already shutdown: " + network);
|
|
return true;
|
|
}
|
|
|
|
if (network.getState() != Network.State.Implemented && network.getState() != Network.State.Shutdown) {
|
|
s_logger.debug("Network is not implemented: " + network);
|
|
return false;
|
|
}
|
|
|
|
if (isSharedNetworkWithServices(network)) {
|
|
network.setState(Network.State.Shutdown);
|
|
_networksDao.update(network.getId(), network);
|
|
} else {
|
|
try {
|
|
stateTransitTo(network, Event.DestroyNetwork);
|
|
} catch (NoTransitionException e) {
|
|
network.setState(Network.State.Shutdown);
|
|
_networksDao.update(network.getId(), network);
|
|
}
|
|
}
|
|
|
|
|
|
boolean success = shutdownNetworkElementsAndResources(context, cleanupElements, network);
|
|
|
|
Transaction txn = Transaction.currentTxn();
|
|
txn.start();
|
|
if (success) {
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Network id=" + networkId + " is shutdown successfully, cleaning up corresponding resources now.");
|
|
}
|
|
NetworkGuru guru = AdapterBase.getAdapterByName(_networkGurus, network.getGuruName());
|
|
NetworkProfile profile = convertNetworkToNetworkProfile(network.getId());
|
|
guru.shutdown(profile, _networkOfferingDao.findById(network.getNetworkOfferingId()));
|
|
|
|
applyProfileToNetwork(network, profile);
|
|
DataCenterVO zone = _dcDao.findById(network.getDataCenterId());
|
|
if (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId()) && (zone.getNetworkType() == NetworkType.Advanced)) {
|
|
network.setState(Network.State.Setup);
|
|
} else {
|
|
try {
|
|
stateTransitTo(network, Event.OperationSucceeded);
|
|
} catch (NoTransitionException e) {
|
|
network.setState(Network.State.Allocated);
|
|
network.setRestartRequired(false);
|
|
}
|
|
}
|
|
_networksDao.update(network.getId(), network);
|
|
_networksDao.clearCheckForGc(networkId);
|
|
result = true;
|
|
} else {
|
|
try {
|
|
stateTransitTo(network, Event.OperationFailed);
|
|
} catch (NoTransitionException e) {
|
|
network.setState(Network.State.Implemented);
|
|
_networksDao.update(network.getId(), network);
|
|
}
|
|
result = false;
|
|
}
|
|
txn.commit();
|
|
return result;
|
|
} finally {
|
|
if (network != null) {
|
|
_networksDao.releaseFromLockTable(network.getId());
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Lock is released for network " + network + " as a part of network shutdown");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean shutdownNetworkElementsAndResources(ReservationContext context, boolean cleanupElements, Network network) {
|
|
// 1) Cleanup all the rules for the network. If it fails, just log the failure and proceed with shutting down
|
|
// the elements
|
|
boolean cleanupResult = true;
|
|
try {
|
|
cleanupResult = shutdownNetworkResources(network.getId(), context.getAccount(), context.getCaller().getId());
|
|
} catch (Exception ex) {
|
|
s_logger.warn("shutdownNetworkRules failed during the network " + network + " shutdown due to ", ex);
|
|
} finally {
|
|
// just warn the administrator that the network elements failed to shutdown
|
|
if (!cleanupResult) {
|
|
s_logger.warn("Failed to cleanup network id=" + network.getId() + " resources as a part of shutdownNetwork");
|
|
}
|
|
}
|
|
|
|
// 2) Shutdown all the network elements
|
|
// get providers to shutdown
|
|
List<Provider> providersToShutdown = getNetworkProviders(network.getId());
|
|
boolean success = true;
|
|
for (NetworkElement element : _networkElements) {
|
|
if (providersToShutdown.contains(element.getProvider())) {
|
|
try {
|
|
if (!_networkModel.isProviderEnabledInPhysicalNetwork(_networkModel.getPhysicalNetworkId(network), element.getProvider().getName())) {
|
|
s_logger.warn("Unable to complete shutdown of the network elements due to element: " + element.getName() + " either doesn't exist or not enabled in the physical network "
|
|
+ _networkModel.getPhysicalNetworkId(network));
|
|
success = false;
|
|
}
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Sending network shutdown to " + element.getName());
|
|
}
|
|
if (!element.shutdown(network, context, cleanupElements)) {
|
|
s_logger.warn("Unable to complete shutdown of the network elements due to element: " + element.getName());
|
|
success = false;
|
|
}
|
|
} catch (ResourceUnavailableException e) {
|
|
s_logger.warn("Unable to complete shutdown of the network elements due to element: " + element.getName(), e);
|
|
success = false;
|
|
} catch (ConcurrentOperationException e) {
|
|
s_logger.warn("Unable to complete shutdown of the network elements due to element: " + element.getName(), e);
|
|
success = false;
|
|
} catch (Exception e) {
|
|
s_logger.warn("Unable to complete shutdown of the network elements due to element: " + element.getName(), e);
|
|
success = false;
|
|
}
|
|
}
|
|
}
|
|
return success;
|
|
}
|
|
|
|
@Override
|
|
@DB
|
|
public boolean destroyNetwork(long networkId, ReservationContext context) {
|
|
Account callerAccount = _accountMgr.getAccount(context.getCaller().getAccountId());
|
|
|
|
NetworkVO network = _networksDao.findById(networkId);
|
|
if (network == null) {
|
|
s_logger.debug("Unable to find network with id: " + networkId);
|
|
return false;
|
|
}
|
|
|
|
// Make sure that there are no user vms in the network that are not Expunged/Error
|
|
List<UserVmVO> userVms = _userVmDao.listByNetworkIdAndStates(networkId);
|
|
|
|
for (UserVmVO vm : userVms) {
|
|
if (!(vm.getState() == VirtualMachine.State.Expunging && vm.getRemoved() != null)) {
|
|
s_logger.warn("Can't delete the network, not all user vms are expunged. Vm " + vm + " is in " + vm.getState() + " state");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Don't allow to delete network via api call when it has vms assigned to it
|
|
int nicCount = getActiveNicsInNetwork(networkId);
|
|
if (nicCount > 0) {
|
|
s_logger.debug("The network id=" + networkId + " has active Nics, but shouldn't.");
|
|
// at this point we have already determined that there are no active user vms in network
|
|
// if the op_networks table shows active nics, it's a bug in releasing nics updating op_networks
|
|
_networksDao.changeActiveNicsBy(networkId, (-1 * nicCount));
|
|
}
|
|
|
|
//In Basic zone, make sure that there are no non-removed console proxies and SSVMs using the network
|
|
DataCenter zone = _configMgr.getZone(network.getDataCenterId());
|
|
if (zone.getNetworkType() == NetworkType.Basic) {
|
|
List<VMInstanceVO> systemVms = _vmDao.listNonRemovedVmsByTypeAndNetwork(network.getId(),
|
|
Type.ConsoleProxy, Type.SecondaryStorageVm);
|
|
if (systemVms != null && !systemVms.isEmpty()) {
|
|
s_logger.warn("Can't delete the network, not all consoleProxy/secondaryStorage vms are expunged");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Shutdown network first
|
|
shutdownNetwork(networkId, context, false);
|
|
|
|
// get updated state for the network
|
|
network = _networksDao.findById(networkId);
|
|
if (network.getState() != Network.State.Allocated && network.getState() != Network.State.Setup) {
|
|
s_logger.debug("Network is not not in the correct state to be destroyed: " + network.getState());
|
|
return false;
|
|
}
|
|
|
|
boolean success = true;
|
|
if (!cleanupNetworkResources(networkId, callerAccount, context.getCaller().getId())) {
|
|
s_logger.warn("Unable to delete network id=" + networkId + ": failed to cleanup network resources");
|
|
return false;
|
|
}
|
|
|
|
// get providers to destroy
|
|
List<Provider> providersToDestroy = getNetworkProviders(network.getId());
|
|
for (NetworkElement element : _networkElements) {
|
|
if (providersToDestroy.contains(element.getProvider())) {
|
|
try {
|
|
if (!_networkModel.isProviderEnabledInPhysicalNetwork(_networkModel.getPhysicalNetworkId(network), element.getProvider().getName())) {
|
|
s_logger.warn("Unable to complete destroy of the network elements due to element: " + element.getName() + " either doesn't exist or not enabled in the physical network "
|
|
+ _networkModel.getPhysicalNetworkId(network));
|
|
success = false;
|
|
}
|
|
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Sending destroy to " + element);
|
|
}
|
|
|
|
if (!element.destroy(network, context)) {
|
|
success = false;
|
|
s_logger.warn("Unable to complete destroy of the network: failed to destroy network element " + element.getName());
|
|
}
|
|
} catch (ResourceUnavailableException e) {
|
|
s_logger.warn("Unable to complete destroy of the network due to element: " + element.getName(), e);
|
|
success = false;
|
|
} catch (ConcurrentOperationException e) {
|
|
s_logger.warn("Unable to complete destroy of the network due to element: " + element.getName(), e);
|
|
success = false;
|
|
} catch (Exception e) {
|
|
s_logger.warn("Unable to complete destroy of the network due to element: " + element.getName(), e);
|
|
success = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (success) {
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Network id=" + networkId + " is destroyed successfully, cleaning up corresponding resources now.");
|
|
}
|
|
NetworkGuru guru = AdapterBase.getAdapterByName(_networkGurus, network.getGuruName());
|
|
Account owner = _accountMgr.getAccount(network.getAccountId());
|
|
|
|
Transaction txn = Transaction.currentTxn();
|
|
txn.start();
|
|
guru.trash(network, _networkOfferingDao.findById(network.getNetworkOfferingId()), owner);
|
|
|
|
if (!deleteVlansInNetwork(network.getId(), context.getCaller().getId(), callerAccount)) {
|
|
success = false;
|
|
s_logger.warn("Failed to delete network " + network + "; was unable to cleanup corresponding ip ranges");
|
|
} else {
|
|
// commit transaction only when ips and vlans for the network are released successfully
|
|
try {
|
|
stateTransitTo(network, Event.DestroyNetwork);
|
|
} catch (NoTransitionException e) {
|
|
s_logger.debug(e.getMessage());
|
|
}
|
|
if (_networksDao.remove(network.getId())) {
|
|
NetworkDomainVO networkDomain = _networkDomainDao.getDomainNetworkMapByNetworkId(network.getId());
|
|
if (networkDomain != null)
|
|
_networkDomainDao.remove(networkDomain.getId());
|
|
|
|
NetworkAccountVO networkAccount = _networkAccountDao.getAccountNetworkMapByNetworkId(network.getId());
|
|
if (networkAccount != null)
|
|
_networkAccountDao.remove(networkAccount.getId());
|
|
}
|
|
|
|
NetworkOffering ntwkOff = _configMgr.getNetworkOffering(network.getNetworkOfferingId());
|
|
boolean updateResourceCount = resourceCountNeedsUpdate(ntwkOff, network.getAclType());
|
|
if (updateResourceCount) {
|
|
_resourceLimitMgr.decrementResourceCount(owner.getId(), ResourceType.network);
|
|
}
|
|
txn.commit();
|
|
}
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
private boolean resourceCountNeedsUpdate(NetworkOffering ntwkOff, ACLType aclType) {
|
|
//Update resource count only for Isolated account specific non-system networks
|
|
boolean updateResourceCount = (ntwkOff.getGuestType() == GuestType.Isolated &&
|
|
!ntwkOff.isSystemOnly() && aclType == ACLType.Account);
|
|
return updateResourceCount;
|
|
}
|
|
|
|
protected boolean deleteVlansInNetwork(long networkId, long userId, Account callerAccount) {
|
|
|
|
//cleanup Public vlans
|
|
List<VlanVO> publicVlans = _vlanDao.listVlansByNetworkId(networkId);
|
|
boolean result = true;
|
|
for (VlanVO vlan : publicVlans) {
|
|
if (!_configMgr.deleteVlanAndPublicIpRange(_accountMgr.getSystemUser().getId(), vlan.getId(), callerAccount)) {
|
|
s_logger.warn("Failed to delete vlan " + vlan.getId() + ");");
|
|
result = false;
|
|
}
|
|
}
|
|
|
|
//cleanup private vlans
|
|
int privateIpAllocCount = _privateIpDao.countAllocatedByNetworkId(networkId);
|
|
if (privateIpAllocCount > 0) {
|
|
s_logger.warn("Can't delete Private ip range for network " + networkId + " as it has allocated ip addresses");
|
|
result = false;
|
|
} else {
|
|
_privateIpDao.deleteByNetworkId(networkId);
|
|
s_logger.debug("Deleted ip range for private network id=" + networkId);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public class NetworkGarbageCollector implements Runnable {
|
|
@Override
|
|
public void run() {
|
|
GlobalLock gcLock = GlobalLock.getInternLock("Network.GC.Lock");
|
|
try {
|
|
if(gcLock.lock(3)) {
|
|
try {
|
|
reallyRun();
|
|
} finally {
|
|
gcLock.unlock();
|
|
}
|
|
}
|
|
} finally {
|
|
gcLock.releaseRef();
|
|
}
|
|
}
|
|
|
|
public void reallyRun() {
|
|
try {
|
|
List<Long> shutdownList = new ArrayList<Long>();
|
|
long currentTime = System.currentTimeMillis() / 1000 ;
|
|
HashMap<Long, Long> stillFree = new HashMap<Long, Long>();
|
|
|
|
List<Long> networkIds = _networksDao.findNetworksToGarbageCollect();
|
|
for (Long networkId : networkIds) {
|
|
|
|
if (!_networkModel.isNetworkReadyForGc(networkId)) {
|
|
continue;
|
|
}
|
|
|
|
Long time = _lastNetworkIdsToFree.remove(networkId);
|
|
if (time == null) {
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("We found network " + networkId + " to be free for the first time. Adding it to the list: " + currentTime);
|
|
}
|
|
stillFree.put(networkId, currentTime);
|
|
} else if (time > (currentTime - _networkGcWait)) {
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Network " + networkId + " is still free but it's not time to shutdown yet: " + time);
|
|
}
|
|
stillFree.put(networkId, time);
|
|
} else {
|
|
shutdownList.add(networkId);
|
|
}
|
|
}
|
|
|
|
_lastNetworkIdsToFree = stillFree;
|
|
|
|
for (Long networkId : shutdownList) {
|
|
|
|
// If network is removed, unset gc flag for it
|
|
if (_networksDao.findById(networkId) == null) {
|
|
s_logger.debug("Network id=" + networkId + " is removed, so clearing up corresponding gc check");
|
|
_networksDao.clearCheckForGc(networkId);
|
|
} else {
|
|
try {
|
|
|
|
User caller = _accountMgr.getSystemUser();
|
|
Account owner = _accountMgr.getAccount(_networksDao.findById(networkId).getAccountId());
|
|
|
|
ReservationContext context = new ReservationContextImpl(null, null, caller, owner);
|
|
|
|
shutdownNetwork(networkId, context, false);
|
|
} catch (Exception e) {
|
|
s_logger.warn("Unable to shutdown network: " + networkId);
|
|
}
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
s_logger.warn("Caught exception while running network gc: ", e);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
public boolean startNetwork(long networkId, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
|
|
|
|
// Check if network exists
|
|
NetworkVO network = _networksDao.findById(networkId);
|
|
if (network == null) {
|
|
InvalidParameterValueException ex = new InvalidParameterValueException("Network with specified id doesn't exist");
|
|
ex.addProxyObject(String.valueOf(networkId), "networkId");
|
|
throw ex;
|
|
}
|
|
|
|
// implement the network
|
|
s_logger.debug("Starting network " + network + "...");
|
|
Pair<NetworkGuru, NetworkVO> implementedNetwork = implementNetwork(networkId, dest, context);
|
|
if (implementedNetwork.first() == null) {
|
|
s_logger.warn("Failed to start the network " + network);
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean restartNetwork(Long networkId, Account callerAccount, User callerUser, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
|
|
|
|
NetworkVO network = _networksDao.findById(networkId);
|
|
|
|
s_logger.debug("Restarting network " + networkId + "...");
|
|
|
|
ReservationContext context = new ReservationContextImpl(null, null, callerUser, callerAccount);
|
|
|
|
if (cleanup) {
|
|
// shutdown the network
|
|
s_logger.debug("Shutting down the network id=" + networkId + " as a part of network restart");
|
|
|
|
if (!shutdownNetworkElementsAndResources(context, true, network)) {
|
|
s_logger.debug("Failed to shutdown the network elements and resources as a part of network restart: " + network.getState());
|
|
setRestartRequired(network, true);
|
|
return false;
|
|
}
|
|
} else {
|
|
s_logger.debug("Skip the shutting down of network id=" + networkId);
|
|
}
|
|
|
|
// implement the network elements and rules again
|
|
DeployDestination dest = new DeployDestination(_dcDao.findById(network.getDataCenterId()), null, null, null);
|
|
|
|
s_logger.debug("Implementing the network " + network + " elements and resources as a part of network restart");
|
|
NetworkOfferingVO offering = _networkOfferingDao.findById(network.getNetworkOfferingId());
|
|
|
|
try {
|
|
implementNetworkElementsAndResources(dest, context, network, offering);
|
|
setRestartRequired(network, true);
|
|
} catch (Exception ex) {
|
|
s_logger.warn("Failed to implement network " + network + " elements and resources as a part of network restart due to ", ex);
|
|
return false;
|
|
}
|
|
setRestartRequired(network, false);
|
|
return true;
|
|
}
|
|
|
|
private void setRestartRequired(NetworkVO network, boolean restartRequired) {
|
|
s_logger.debug("Marking network " + network + " with restartRequired=" + restartRequired);
|
|
network.setRestartRequired(restartRequired);
|
|
_networksDao.update(network.getId(), network);
|
|
}
|
|
|
|
protected int getActiveNicsInNetwork(long networkId) {
|
|
return _networksDao.getActiveNicsIn(networkId);
|
|
}
|
|
|
|
|
|
@Override
|
|
public NetworkProfile convertNetworkToNetworkProfile(long networkId) {
|
|
NetworkVO network = _networksDao.findById(networkId);
|
|
NetworkGuru guru = AdapterBase.getAdapterByName(_networkGurus, network.getGuruName());
|
|
NetworkProfile profile = new NetworkProfile(network);
|
|
guru.updateNetworkProfile(profile);
|
|
|
|
return profile;
|
|
}
|
|
|
|
@Override
|
|
public UserDataServiceProvider getPasswordResetProvider(Network network) {
|
|
String passwordProvider = _ntwkSrvcDao.getProviderForServiceInNetwork(network.getId(), Service.UserData);
|
|
|
|
if (passwordProvider == null) {
|
|
s_logger.debug("Network " + network + " doesn't support service " + Service.UserData.getName());
|
|
return null;
|
|
}
|
|
|
|
return (UserDataServiceProvider)_networkModel.getElementImplementingProvider(passwordProvider);
|
|
}
|
|
|
|
@Override
|
|
public UserDataServiceProvider getSSHKeyResetProvider(Network network) {
|
|
String SSHKeyProvider = _ntwkSrvcDao.getProviderForServiceInNetwork(network.getId(), Service.UserData);
|
|
|
|
if (SSHKeyProvider == null) {
|
|
s_logger.debug("Network " + network + " doesn't support service " + Service.UserData.getName());
|
|
return null;
|
|
}
|
|
|
|
return (UserDataServiceProvider)_networkModel.getElementImplementingProvider(SSHKeyProvider);
|
|
}
|
|
|
|
@Override
|
|
public DhcpServiceProvider getDhcpServiceProvider(Network network) {
|
|
String DhcpProvider = _ntwkSrvcDao.getProviderForServiceInNetwork(network.getId(), Service.Dhcp);
|
|
|
|
if (DhcpProvider == null) {
|
|
s_logger.debug("Network " + network + " doesn't support service " + Service.Dhcp.getName());
|
|
return null;
|
|
}
|
|
|
|
return (DhcpServiceProvider)_networkModel.getElementImplementingProvider(DhcpProvider);
|
|
|
|
}
|
|
|
|
|
|
protected boolean isSharedNetworkWithServices(Network network) {
|
|
assert(network != null);
|
|
DataCenter zone = _configMgr.getZone(network.getDataCenterId());
|
|
if (network.getGuestType() == Network.GuestType.Shared &&
|
|
zone.getNetworkType() == NetworkType.Advanced &&
|
|
isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
protected boolean isSharedNetworkOfferingWithServices(long networkOfferingId) {
|
|
NetworkOfferingVO networkOffering = _networkOfferingDao.findById(networkOfferingId);
|
|
if ( (networkOffering.getGuestType() == Network.GuestType.Shared) && (
|
|
_networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.SourceNat) ||
|
|
_networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.StaticNat) ||
|
|
_networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.Firewall) ||
|
|
_networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.PortForwarding) ||
|
|
_networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.Lb))) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
@Override
|
|
public List<? extends Nic> listVmNics(Long vmId, Long nicId) {
|
|
List<NicVO> result = null;
|
|
if (nicId == null) {
|
|
result = _nicDao.listByVmId(vmId);
|
|
} else {
|
|
result = _nicDao.listByVmIdAndNicId(vmId, nicId);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
|
|
@DB
|
|
@Override
|
|
public boolean reallocate(VirtualMachineProfile vm, DataCenterDeployment dest) throws InsufficientCapacityException, ConcurrentOperationException {
|
|
VMInstanceVO vmInstance = _vmDao.findById(vm.getId());
|
|
DataCenterVO dc = _dcDao.findById(vmInstance.getDataCenterId());
|
|
if (dc.getNetworkType() == NetworkType.Basic) {
|
|
List<NicVO> nics = _nicDao.listByVmId(vmInstance.getId());
|
|
NetworkVO network = _networksDao.findById(nics.get(0).getNetworkId());
|
|
LinkedHashMap<Network, NicProfile> profiles = new LinkedHashMap<Network, NicProfile>();
|
|
profiles.put(network, null);
|
|
|
|
Transaction txn = Transaction.currentTxn();
|
|
txn.start();
|
|
|
|
try {
|
|
cleanupNics(vm);
|
|
allocate(vm, profiles);
|
|
} finally {
|
|
txn.commit();
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private boolean cleanupNetworkResources(long networkId, Account caller, long callerUserId) {
|
|
boolean success = true;
|
|
Network network = _networksDao.findById(networkId);
|
|
|
|
//remove all PF/Static Nat rules for the network
|
|
try {
|
|
if (_rulesMgr.revokeAllPFStaticNatRulesForNetwork(networkId, callerUserId, caller)) {
|
|
s_logger.debug("Successfully cleaned up portForwarding/staticNat rules for network id=" + networkId);
|
|
} else {
|
|
success = false;
|
|
s_logger.warn("Failed to release portForwarding/StaticNat rules as a part of network id=" + networkId + " cleanup");
|
|
}
|
|
} catch (ResourceUnavailableException ex) {
|
|
success = false;
|
|
// shouldn't even come here as network is being cleaned up after all network elements are shutdown
|
|
s_logger.warn("Failed to release portForwarding/StaticNat rules as a part of network id=" + networkId + " cleanup due to resourceUnavailable ", ex);
|
|
}
|
|
|
|
//remove all LB rules for the network
|
|
if (_lbMgr.removeAllLoadBalanacersForNetwork(networkId, caller, callerUserId)) {
|
|
s_logger.debug("Successfully cleaned up load balancing rules for network id=" + networkId);
|
|
} else {
|
|
// shouldn't even come here as network is being cleaned up after all network elements are shutdown
|
|
success = false;
|
|
s_logger.warn("Failed to cleanup LB rules as a part of network id=" + networkId + " cleanup");
|
|
}
|
|
|
|
//revoke all firewall rules for the network
|
|
try {
|
|
if (_firewallMgr.revokeAllFirewallRulesForNetwork(networkId, callerUserId, caller)) {
|
|
s_logger.debug("Successfully cleaned up firewallRules rules for network id=" + networkId);
|
|
} else {
|
|
success = false;
|
|
s_logger.warn("Failed to cleanup Firewall rules as a part of network id=" + networkId + " cleanup");
|
|
}
|
|
} catch (ResourceUnavailableException ex) {
|
|
success = false;
|
|
// shouldn't even come here as network is being cleaned up after all network elements are shutdown
|
|
s_logger.warn("Failed to cleanup Firewall rules as a part of network id=" + networkId + " cleanup due to resourceUnavailable ", ex);
|
|
}
|
|
|
|
//revoke all network ACLs for network
|
|
try {
|
|
if (_networkACLMgr.revokeACLItemsForNetwork(networkId)) {
|
|
s_logger.debug("Successfully cleaned up NetworkACLs for network id=" + networkId);
|
|
} else {
|
|
success = false;
|
|
s_logger.warn("Failed to cleanup NetworkACLs as a part of network id=" + networkId + " cleanup");
|
|
}
|
|
} catch (ResourceUnavailableException ex) {
|
|
success = false;
|
|
s_logger.warn("Failed to cleanup Network ACLs as a part of network id=" + networkId +
|
|
" cleanup due to resourceUnavailable ", ex);
|
|
}
|
|
|
|
//release all ip addresses
|
|
List<IPAddressVO> ipsToRelease = _ipAddressDao.listByAssociatedNetwork(networkId, null);
|
|
for (IPAddressVO ipToRelease : ipsToRelease) {
|
|
if (ipToRelease.getVpcId() == null) {
|
|
if (!ipToRelease.isPortable()) {
|
|
IPAddressVO ip = _ipAddrMgr.markIpAsUnavailable(ipToRelease.getId());
|
|
assert (ip != null) : "Unable to mark the ip address id=" + ipToRelease.getId() + " as unavailable.";
|
|
} else {
|
|
// portable IP address are associated with owner, until explicitly requested to be disassociated
|
|
// so as part of network clean up just break IP association with guest network
|
|
ipToRelease.setAssociatedWithNetworkId(null);
|
|
_ipAddressDao.update(ipToRelease.getId(), ipToRelease);
|
|
s_logger.debug("Portable IP address " + ipToRelease + " is no longer associated with any network");
|
|
}
|
|
} else {
|
|
_vpcMgr.unassignIPFromVpcNetwork(ipToRelease.getId(), network.getId());
|
|
}
|
|
}
|
|
|
|
try {
|
|
if (!_ipAddrMgr.applyIpAssociations(network, true)) {
|
|
s_logger.warn("Unable to apply ip address associations for " + network);
|
|
success = false;
|
|
}
|
|
} catch (ResourceUnavailableException e) {
|
|
throw new CloudRuntimeException("We should never get to here because we used true when applyIpAssociations", e);
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
private boolean shutdownNetworkResources(long networkId, Account caller, long callerUserId) {
|
|
// This method cleans up network rules on the backend w/o touching them in the DB
|
|
boolean success = true;
|
|
Network network = _networksDao.findById(networkId);
|
|
|
|
// Mark all PF rules as revoked and apply them on the backend (not in the DB)
|
|
List<PortForwardingRuleVO> pfRules = _portForwardingRulesDao.listByNetwork(networkId);
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Releasing " + pfRules.size() + " port forwarding rules for network id=" + networkId + " as a part of shutdownNetworkRules");
|
|
}
|
|
|
|
for (PortForwardingRuleVO pfRule : pfRules) {
|
|
s_logger.trace("Marking pf rule " + pfRule + " with Revoke state");
|
|
pfRule.setState(FirewallRule.State.Revoke);
|
|
}
|
|
|
|
try {
|
|
if (!_firewallMgr.applyRules(pfRules, true, false)) {
|
|
s_logger.warn("Failed to cleanup pf rules as a part of shutdownNetworkRules");
|
|
success = false;
|
|
}
|
|
} catch (ResourceUnavailableException ex) {
|
|
s_logger.warn("Failed to cleanup pf rules as a part of shutdownNetworkRules due to ", ex);
|
|
success = false;
|
|
}
|
|
|
|
// Mark all static rules as revoked and apply them on the backend (not in the DB)
|
|
List<FirewallRuleVO> firewallStaticNatRules = _firewallDao.listByNetworkAndPurpose(networkId, Purpose.StaticNat);
|
|
List<StaticNatRule> staticNatRules = new ArrayList<StaticNatRule>();
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Releasing " + firewallStaticNatRules.size() + " static nat rules for network id=" + networkId + " as a part of shutdownNetworkRules");
|
|
}
|
|
|
|
for (FirewallRuleVO firewallStaticNatRule : firewallStaticNatRules) {
|
|
s_logger.trace("Marking static nat rule " + firewallStaticNatRule + " with Revoke state");
|
|
IpAddress ip = _ipAddressDao.findById(firewallStaticNatRule.getSourceIpAddressId());
|
|
FirewallRuleVO ruleVO = _firewallDao.findById(firewallStaticNatRule.getId());
|
|
|
|
if (ip == null || !ip.isOneToOneNat() || ip.getAssociatedWithVmId() == null) {
|
|
throw new InvalidParameterValueException("Source ip address of the rule id=" + firewallStaticNatRule.getId() + " is not static nat enabled");
|
|
}
|
|
|
|
//String dstIp = _networkModel.getIpInNetwork(ip.getAssociatedWithVmId(), firewallStaticNatRule.getNetworkId());
|
|
ruleVO.setState(FirewallRule.State.Revoke);
|
|
staticNatRules.add(new StaticNatRuleImpl(ruleVO, ip.getVmIp()));
|
|
}
|
|
|
|
try {
|
|
if (!_firewallMgr.applyRules(staticNatRules, true, false)) {
|
|
s_logger.warn("Failed to cleanup static nat rules as a part of shutdownNetworkRules");
|
|
success = false;
|
|
}
|
|
} catch (ResourceUnavailableException ex) {
|
|
s_logger.warn("Failed to cleanup static nat rules as a part of shutdownNetworkRules due to ", ex);
|
|
success = false;
|
|
}
|
|
|
|
try {
|
|
if (!_lbMgr.revokeLoadBalancersForNetwork(networkId, Scheme.Public)) {
|
|
s_logger.warn("Failed to cleanup public lb rules as a part of shutdownNetworkRules");
|
|
success = false;
|
|
}
|
|
} catch (ResourceUnavailableException ex) {
|
|
s_logger.warn("Failed to cleanup public lb rules as a part of shutdownNetworkRules due to ", ex);
|
|
success = false;
|
|
}
|
|
|
|
try {
|
|
if (!_lbMgr.revokeLoadBalancersForNetwork(networkId, Scheme.Internal)) {
|
|
s_logger.warn("Failed to cleanup internal lb rules as a part of shutdownNetworkRules");
|
|
success = false;
|
|
}
|
|
} catch (ResourceUnavailableException ex) {
|
|
s_logger.warn("Failed to cleanup public lb rules as a part of shutdownNetworkRules due to ", ex);
|
|
success = false;
|
|
}
|
|
|
|
// revoke all firewall rules for the network w/o applying them on the DB
|
|
List<FirewallRuleVO> firewallRules = _firewallDao.listByNetworkPurposeTrafficType(networkId, Purpose.Firewall, FirewallRule.TrafficType.Ingress);
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Releasing " + firewallRules.size() + " firewall ingress rules for network id=" + networkId + " as a part of shutdownNetworkRules");
|
|
}
|
|
|
|
for (FirewallRuleVO firewallRule : firewallRules) {
|
|
s_logger.trace("Marking firewall ingress rule " + firewallRule + " with Revoke state");
|
|
firewallRule.setState(FirewallRule.State.Revoke);
|
|
}
|
|
|
|
try {
|
|
if (!_firewallMgr.applyRules(firewallRules, true, false)) {
|
|
s_logger.warn("Failed to cleanup firewall ingress rules as a part of shutdownNetworkRules");
|
|
success = false;
|
|
}
|
|
} catch (ResourceUnavailableException ex) {
|
|
s_logger.warn("Failed to cleanup firewall ingress rules as a part of shutdownNetworkRules due to ", ex);
|
|
success = false;
|
|
}
|
|
|
|
List<FirewallRuleVO> firewallEgressRules = _firewallDao.listByNetworkPurposeTrafficType(networkId, Purpose.Firewall, FirewallRule.TrafficType.Egress);
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Releasing " + firewallEgressRules.size() + " firewall egress rules for network id=" + networkId + " as a part of shutdownNetworkRules");
|
|
}
|
|
|
|
for (FirewallRuleVO firewallRule : firewallEgressRules) {
|
|
s_logger.trace("Marking firewall egress rule " + firewallRule + " with Revoke state");
|
|
firewallRule.setState(FirewallRule.State.Revoke);
|
|
}
|
|
|
|
try {
|
|
if (!_firewallMgr.applyRules(firewallEgressRules, true, false)) {
|
|
s_logger.warn("Failed to cleanup firewall egress rules as a part of shutdownNetworkRules");
|
|
success = false;
|
|
}
|
|
} catch (ResourceUnavailableException ex) {
|
|
s_logger.warn("Failed to cleanup firewall egress rules as a part of shutdownNetworkRules due to ", ex);
|
|
success = false;
|
|
}
|
|
|
|
if(network.getVpcId() != null){
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Releasing Network ACL Items for network id=" + networkId +
|
|
" as a part of shutdownNetworkRules");
|
|
}
|
|
|
|
try {
|
|
//revoke all Network ACLs for the network w/o applying them in the DB
|
|
if (!_networkACLMgr.revokeACLItemsForNetwork(networkId)) {
|
|
s_logger.warn("Failed to cleanup network ACLs as a part of shutdownNetworkRules");
|
|
success = false;
|
|
}
|
|
} catch (ResourceUnavailableException ex) {
|
|
s_logger.warn("Failed to cleanup network ACLs as a part of shutdownNetworkRules due to ", ex);
|
|
success = false;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//release all static nats for the network
|
|
if (!_rulesMgr.applyStaticNatForNetwork(networkId, false, caller, true)) {
|
|
s_logger.warn("Failed to disable static nats as part of shutdownNetworkRules for network id " + networkId);
|
|
success = false;
|
|
}
|
|
|
|
// Get all ip addresses, mark as releasing and release them on the backend
|
|
List<IPAddressVO> userIps = _ipAddressDao.listByAssociatedNetwork(networkId, null);
|
|
List<PublicIp> publicIpsToRelease = new ArrayList<PublicIp>();
|
|
if (userIps != null && !userIps.isEmpty()) {
|
|
for (IPAddressVO userIp : userIps) {
|
|
userIp.setState(State.Releasing);
|
|
PublicIp publicIp = PublicIp.createFromAddrAndVlan(userIp, _vlanDao.findById(userIp.getVlanId()));
|
|
publicIpsToRelease.add(publicIp);
|
|
}
|
|
}
|
|
|
|
try {
|
|
if (!_ipAddrMgr.applyIpAssociations(network, true, true, publicIpsToRelease)) {
|
|
s_logger.warn("Unable to apply ip address associations for " + network + " as a part of shutdownNetworkRules");
|
|
success = false;
|
|
}
|
|
} catch (ResourceUnavailableException e) {
|
|
throw new CloudRuntimeException("We should never get to here because we used true when applyIpAssociations", e);
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
@Override
|
|
public boolean processAnswers(long agentId, long seq, Answer[] answers) {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean processCommands(long agentId, long seq, Command[] commands) {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public AgentControlAnswer processControlCommand(long agentId, AgentControlCommand cmd) {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) throws ConnectionException {
|
|
if (!(cmd instanceof StartupRoutingCommand)) {
|
|
return;
|
|
}
|
|
long hostId = host.getId();
|
|
StartupRoutingCommand startup = (StartupRoutingCommand) cmd;
|
|
|
|
String dataCenter = startup.getDataCenter();
|
|
|
|
long dcId = -1;
|
|
DataCenterVO dc = _dcDao.findByName(dataCenter);
|
|
if (dc == null) {
|
|
try {
|
|
dcId = Long.parseLong(dataCenter);
|
|
dc = _dcDao.findById(dcId);
|
|
} catch (final NumberFormatException e) {
|
|
}
|
|
}
|
|
if (dc == null) {
|
|
throw new IllegalArgumentException("Host " + startup.getPrivateIpAddress() + " sent incorrect data center: " + dataCenter);
|
|
}
|
|
dcId = dc.getId();
|
|
HypervisorType hypervisorType = startup.getHypervisorType();
|
|
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Host's hypervisorType is: " + hypervisorType);
|
|
}
|
|
|
|
List<PhysicalNetworkSetupInfo> networkInfoList = new ArrayList<PhysicalNetworkSetupInfo>();
|
|
|
|
// list all physicalnetworks in the zone & for each get the network names
|
|
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._networkModel.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);
|
|
}
|
|
|
|
// send the names to the agent
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Sending CheckNetworkCommand to check the Network is setup correctly on Agent");
|
|
}
|
|
CheckNetworkCommand nwCmd = new CheckNetworkCommand(networkInfoList);
|
|
|
|
CheckNetworkAnswer answer = (CheckNetworkAnswer) _agentMgr.easySend(hostId, nwCmd);
|
|
|
|
if (answer == null) {
|
|
s_logger.warn("Unable to get an answer to the CheckNetworkCommand from agent:" + host.getId());
|
|
throw new ConnectionException(true, "Unable to get an answer to the CheckNetworkCommand from agent: " + host.getId());
|
|
}
|
|
|
|
if (!answer.getResult()) {
|
|
s_logger.warn("Unable to setup agent " + hostId + " due to " + ((answer != null) ? answer.getDetails() : "return null"));
|
|
String msg = "Incorrect Network setup on agent, Reinitialize agent after network names are setup, details : " + answer.getDetails();
|
|
_alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, dcId, host.getPodId(), msg, msg);
|
|
throw new ConnectionException(true, msg);
|
|
} else {
|
|
if (answer.needReconnect()) {
|
|
throw new ConnectionException(false, "Reinitialize agent after network setup.");
|
|
}
|
|
if (s_logger.isDebugEnabled()) {
|
|
s_logger.debug("Network setup is correct on Agent");
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean processDisconnect(long agentId, Status state) {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean isRecurring() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public int getTimeout() {
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public boolean processTimeout(long agentId, long seq) {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public Map<String, String> finalizeServicesAndProvidersForNetwork(NetworkOffering offering, Long physicalNetworkId) {
|
|
Map<String, String> svcProviders = new HashMap<String, String>();
|
|
Map<String, List<String>> providerSvcs = new HashMap<String, List<String>>();
|
|
List<NetworkOfferingServiceMapVO> servicesMap = _ntwkOfferingSrvcDao.listByNetworkOfferingId(offering.getId());
|
|
|
|
boolean checkPhysicalNetwork = (physicalNetworkId != null) ? true : false;
|
|
|
|
for (NetworkOfferingServiceMapVO serviceMap : servicesMap) {
|
|
if (svcProviders.containsKey(serviceMap.getService())) {
|
|
// FIXME - right now we pick up the first provider from the list, need to add more logic based on
|
|
// provider load, etc
|
|
continue;
|
|
}
|
|
|
|
String service = serviceMap.getService();
|
|
String provider = serviceMap.getProvider();
|
|
|
|
if (provider == null) {
|
|
provider = _networkModel.getDefaultUniqueProviderForService(service).getName();
|
|
}
|
|
|
|
// check that provider is supported
|
|
if (checkPhysicalNetwork) {
|
|
if (!_pNSPDao.isServiceProviderEnabled(physicalNetworkId, provider, service)) {
|
|
throw new UnsupportedServiceException("Provider " + provider + " is either not enabled or doesn't " +
|
|
"support service " + service + " in physical network id=" + physicalNetworkId);
|
|
}
|
|
}
|
|
|
|
svcProviders.put(service, provider);
|
|
List<String> l = providerSvcs.get(provider);
|
|
if (l == null) {
|
|
providerSvcs.put(provider, l = new ArrayList<String>());
|
|
}
|
|
l.add(service);
|
|
}
|
|
|
|
return svcProviders;
|
|
}
|
|
|
|
private List<Provider> getNetworkProviders(long networkId) {
|
|
List<String> providerNames = _ntwkSrvcDao.getDistinctProviders(networkId);
|
|
List<Provider> providers = new ArrayList<Provider>();
|
|
for (String providerName : providerNames) {
|
|
providers.add(Network.Provider.getProvider(providerName));
|
|
}
|
|
|
|
return providers;
|
|
}
|
|
|
|
@Override
|
|
public boolean setupDns(Network network, Provider provider) {
|
|
boolean dnsProvided = _networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.Dns, provider );
|
|
boolean dhcpProvided =_networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.Dhcp,
|
|
provider);
|
|
|
|
boolean setupDns = dnsProvided || dhcpProvided;
|
|
return setupDns;
|
|
}
|
|
|
|
|
|
protected NicProfile getNicProfileForVm(Network network, NicProfile requested, VirtualMachine vm) {
|
|
NicProfile nic = null;
|
|
if (requested != null && requested.getBroadCastUri() != null) {
|
|
String broadcastUri = requested.getBroadCastUri().toString();
|
|
String ipAddress = requested.getIp4Address();
|
|
NicVO nicVO = _nicDao.findByNetworkIdInstanceIdAndBroadcastUri(network.getId(), vm.getId(), broadcastUri);
|
|
if (nicVO != null) {
|
|
if (ipAddress == null || nicVO.getIp4Address().equals(ipAddress)) {
|
|
nic = _networkModel.getNicProfile(vm, network.getId(), broadcastUri);
|
|
}
|
|
}
|
|
} else {
|
|
NicVO nicVO = _nicDao.findByNtwkIdAndInstanceId(network.getId(), vm.getId());
|
|
if (nicVO != null) {
|
|
nic = _networkModel.getNicProfile(vm, network.getId(), null);
|
|
}
|
|
}
|
|
return nic;
|
|
}
|
|
|
|
@Override
|
|
public NicProfile createNicForVm(Network network, NicProfile requested, ReservationContext context, VirtualMachineProfile vmProfile, boolean prepare)
|
|
throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException,
|
|
ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
|
|
|
|
VirtualMachine vm = vmProfile.getVirtualMachine();
|
|
DataCenter dc = _configMgr.getZone(network.getDataCenterId());
|
|
Host host = _hostDao.findById(vm.getHostId());
|
|
DeployDestination dest = new DeployDestination(dc, null, null, host);
|
|
|
|
NicProfile nic = getNicProfileForVm(network, requested, vm);
|
|
|
|
//1) allocate nic (if needed) Always allocate if it is a user vm
|
|
if (nic == null || (vmProfile.getType() == VirtualMachine.Type.User)) {
|
|
int deviceId = _nicDao.countNics(vm.getId());
|
|
|
|
nic = allocateNic(requested, network, false,
|
|
deviceId, vmProfile).first();
|
|
|
|
if (nic == null) {
|
|
throw new CloudRuntimeException("Failed to allocate nic for vm " + vm + " in network " + network);
|
|
}
|
|
|
|
s_logger.debug("Nic is allocated successfully for vm " + vm + " in network " + network);
|
|
}
|
|
|
|
//2) prepare nic
|
|
if (prepare) {
|
|
Pair<NetworkGuru, NetworkVO> implemented = implementNetwork(nic.getNetworkId(), dest, context);
|
|
nic = prepareNic(vmProfile, dest, context, nic.getId(), implemented.second());
|
|
s_logger.debug("Nic is prepared successfully for vm " + vm + " in network " + network);
|
|
}
|
|
|
|
return nic;
|
|
}
|
|
|
|
|
|
@Override
|
|
public List<NicProfile> getNicProfiles(VirtualMachine vm) {
|
|
List<NicVO> nics = _nicDao.listByVmId(vm.getId());
|
|
List<NicProfile> profiles = new ArrayList<NicProfile>();
|
|
|
|
if (nics != null) {
|
|
for (Nic nic : nics) {
|
|
NetworkVO network = _networksDao.findById(nic.getNetworkId());
|
|
Integer networkRate = _networkModel.getNetworkRate(network.getId(), vm.getId());
|
|
|
|
NetworkGuru guru = AdapterBase.getAdapterByName(_networkGurus, network.getGuruName());
|
|
NicProfile profile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(),
|
|
networkRate, _networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag(vm.getHypervisorType(), network));
|
|
guru.updateNicProfile(profile, network);
|
|
profiles.add(profile);
|
|
}
|
|
}
|
|
return profiles;
|
|
}
|
|
|
|
|
|
@Override
|
|
public int getNetworkLockTimeout() {
|
|
return _networkLockTimeout;
|
|
}
|
|
|
|
|
|
protected boolean stateTransitTo(NetworkVO network, Network.Event e) throws NoTransitionException {
|
|
return _stateMachine.transitTo(network, e, null, _networksDao);
|
|
}
|
|
|
|
private void setStateMachine() {
|
|
_stateMachine = Network.State.getStateMachine();
|
|
}
|
|
|
|
private 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;
|
|
}
|
|
|
|
|
|
@Override
|
|
public List<Provider> getProvidersForServiceInNetwork(Network network, Service service) {
|
|
Map<Service, Set<Provider>> service2ProviderMap = getServiceProvidersMap(network.getId());
|
|
if (service2ProviderMap.get(service) != null) {
|
|
List<Provider> providers = new ArrayList<Provider>(service2ProviderMap.get(service));
|
|
return providers;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
|
|
protected List<NetworkElement> getElementForServiceInNetwork(Network network, Service service) {
|
|
List<NetworkElement> elements = new ArrayList<NetworkElement>();
|
|
List<Provider> providers = getProvidersForServiceInNetwork(network, service);
|
|
//Only support one provider now
|
|
if (providers == null) {
|
|
s_logger.error("Cannot find " + service.getName() + " provider for network " + network.getId());
|
|
return null;
|
|
}
|
|
if (providers.size() != 1 && service != Service.Lb) {
|
|
//support more than one LB providers only
|
|
s_logger.error("Found " + providers.size() + " " + service.getName() + " providers for network!" + network.getId());
|
|
return null;
|
|
}
|
|
|
|
for (Provider provider : providers) {
|
|
NetworkElement element = _networkModel.getElementImplementingProvider(provider.getName());
|
|
s_logger.info("Let " + element.getName() + " handle " + service.getName() + " in network " + network.getId());
|
|
elements.add(element);
|
|
}
|
|
return elements;
|
|
}
|
|
|
|
|
|
@Override
|
|
public StaticNatServiceProvider getStaticNatProviderForNetwork(Network network) {
|
|
//only one provider per Static nat service is supoprted
|
|
NetworkElement element = getElementForServiceInNetwork(network, Service.StaticNat).get(0);
|
|
assert element instanceof StaticNatServiceProvider;
|
|
return (StaticNatServiceProvider)element;
|
|
}
|
|
|
|
|
|
@Override
|
|
public LoadBalancingServiceProvider getLoadBalancingProviderForNetwork(Network network, Scheme lbScheme) {
|
|
List<NetworkElement> lbElements = getElementForServiceInNetwork(network, Service.Lb);
|
|
NetworkElement lbElement = null;
|
|
if (lbElements.size() > 1) {
|
|
String providerName = null;
|
|
//get network offering details
|
|
NetworkOffering off = _configMgr.getNetworkOffering(network.getNetworkOfferingId());
|
|
if (lbScheme == Scheme.Public) {
|
|
providerName = _ntwkOffDetailsDao.getDetail(off.getId(), NetworkOffering.Detail.PublicLbProvider);
|
|
} else {
|
|
providerName = _ntwkOffDetailsDao.getDetail(off.getId(), NetworkOffering.Detail.InternalLbProvider);
|
|
}
|
|
if (providerName == null) {
|
|
throw new InvalidParameterValueException("Can't find Lb provider supporting scheme " + lbScheme.toString() + " in network " + network);
|
|
}
|
|
lbElement = _networkModel.getElementImplementingProvider(providerName);
|
|
} else if (lbElements.size() == 1){
|
|
lbElement = lbElements.get(0);
|
|
}
|
|
|
|
assert lbElement != null;
|
|
assert lbElement instanceof LoadBalancingServiceProvider;
|
|
return (LoadBalancingServiceProvider)lbElement;
|
|
}
|
|
|
|
|
|
@Override
|
|
public boolean isNetworkInlineMode(Network network) {
|
|
NetworkOfferingVO offering = _networkOfferingDao.findById(network.getNetworkOfferingId());
|
|
return offering.isInline();
|
|
}
|
|
|
|
@Override
|
|
public boolean isSecondaryIpSetForNic(long nicId) {
|
|
NicVO nic = _nicDao.findById(nicId);
|
|
return nic.getSecondaryIp();
|
|
}
|
|
|
|
|
|
private boolean removeVmSecondaryIpsOfNic(long nicId) {
|
|
Transaction txn = Transaction.currentTxn();
|
|
txn.start();
|
|
List <NicSecondaryIpVO> ipList = _nicSecondaryIpDao.listByNicId(nicId);
|
|
if (ipList != null) {
|
|
for (NicSecondaryIpVO ip: ipList) {
|
|
_nicSecondaryIpDao.remove(ip.getId());
|
|
}
|
|
s_logger.debug("Revoving nic secondary ip entry ...");
|
|
}
|
|
txn.commit();
|
|
return true;
|
|
}
|
|
|
|
|
|
@Override
|
|
public NicVO savePlaceholderNic(Network network, String ip4Address, String ip6Address, Type vmType) {
|
|
NicVO nic = new NicVO(null, null, network.getId(), null);
|
|
nic.setIp4Address(ip4Address);
|
|
nic.setIp6Address(ip6Address);
|
|
nic.setReservationStrategy(ReservationStrategy.PlaceHolder);
|
|
nic.setState(Nic.State.Reserved);
|
|
nic.setVmType(vmType);
|
|
return _nicDao.persist(nic);
|
|
}
|
|
}
|