// // 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.guru; import java.util.List; import java.util.Map; import java.util.Set; import javax.inject.Inject; import com.google.common.collect.FluentIterable; import net.nuage.vsp.acs.client.api.model.VspDhcpDomainOption; import net.nuage.vsp.acs.client.api.model.VspDhcpVMOption; import net.nuage.vsp.acs.client.api.model.VspDomain; import net.nuage.vsp.acs.client.api.model.VspNetwork; import net.nuage.vsp.acs.client.api.model.VspNic; import net.nuage.vsp.acs.client.api.model.VspStaticNat; import net.nuage.vsp.acs.client.api.model.VspVm; import org.apache.log4j.Logger; import com.google.common.base.Strings; import com.google.common.collect.Iterables; import com.google.common.collect.LinkedListMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import org.apache.cloudstack.resourcedetail.VpcDetailVO; import org.apache.cloudstack.resourcedetail.dao.VpcDetailsDao; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; import com.cloud.agent.api.guru.DeallocateVmVspCommand; import com.cloud.agent.api.guru.ImplementNetworkVspCommand; import com.cloud.agent.api.guru.ReserveVmInterfaceVspCommand; import com.cloud.agent.api.guru.TrashNetworkVspCommand; import com.cloud.agent.api.guru.UpdateDhcpOptionVspCommand; import com.cloud.configuration.ConfigurationManager; import com.cloud.dc.DataCenter; import com.cloud.dc.DataCenter.NetworkType; import com.cloud.dc.VlanVO; import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlan; import com.cloud.domain.dao.DomainDao; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InsufficientVirtualNetworkCapacityException; import com.cloud.exception.UnsupportedServiceException; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.network.Network; import com.cloud.network.Network.GuestType; import com.cloud.network.Network.State; import com.cloud.network.NetworkProfile; import com.cloud.network.Networks; import com.cloud.network.PhysicalNetwork; import com.cloud.network.PhysicalNetwork.IsolationMethod; import com.cloud.network.dao.IPAddressVO; import com.cloud.network.dao.NetworkDetailVO; import com.cloud.network.dao.NetworkDetailsDao; import com.cloud.network.dao.NetworkVO; import com.cloud.network.dao.NuageVspDao; import com.cloud.network.dao.PhysicalNetworkVO; import com.cloud.network.manager.NuageVspManager; import com.cloud.network.vpc.dao.VpcDao; import com.cloud.offering.NetworkOffering; import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.offerings.dao.NetworkOfferingServiceMapDao; import com.cloud.user.Account; import com.cloud.user.AccountVO; import com.cloud.user.dao.AccountDao; import com.cloud.util.NuageVspEntityBuilder; import com.cloud.utils.StringUtils; import com.cloud.utils.db.DB; import com.cloud.utils.net.Ip; import com.cloud.vm.Nic; import com.cloud.vm.NicProfile; import com.cloud.vm.NicVO; import com.cloud.vm.ReservationContext; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.dao.VMInstanceDao; public class NuageVspGuestNetworkGuru extends GuestNetworkGuru { public static final Logger s_logger = Logger.getLogger(NuageVspGuestNetworkGuru.class); @Inject NetworkOfferingServiceMapDao _ntwkOfferingSrvcDao; @Inject NetworkOfferingDao _ntwkOfferingDao; @Inject DomainDao _domainDao; @Inject AccountDao _accountDao; @Inject NuageVspDao _nuageVspDao; @Inject HostDao _hostDao; @Inject VpcDao _vpcDao; @Inject VMInstanceDao _vmInstanceDao; @Inject AgentManager _agentMgr; @Inject NuageVspManager _nuageVspManager; @Inject ConfigurationManager _configMgr; @Inject NuageVspEntityBuilder _nuageVspEntityBuilder; @Inject NetworkDetailsDao _networkDetailsDao; @Inject VpcDetailsDao _vpcDetailsDao; public NuageVspGuestNetworkGuru() { super(); _isolationMethods = new IsolationMethod[] {IsolationMethod.VSP}; } @Override public Network design(NetworkOffering offering, DeploymentPlan plan, Network userSpecified, Account owner) { PhysicalNetworkVO physnet = _physicalNetworkDao.findById(plan.getPhysicalNetworkId()); DataCenter dc = _dcDao.findById(plan.getDataCenterId()); if (!canHandle(offering, dc.getNetworkType(), physnet)) { if (s_logger.isDebugEnabled()) { s_logger.debug("Refusing to design network using network offering " + offering.getId() + (physnet != null ? " on physical network " + physnet.getId() : "")); } return null; } NetworkVO networkObject = (NetworkVO)super.design(offering, plan, userSpecified, owner); if (networkObject == null) { return null; } networkObject.setBroadcastDomainType(Networks.BroadcastDomainType.Vsp); return networkObject; } @Override public Network implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapacityException { long networkId = network.getId(); network = _networkDao.acquireInLockTable(network.getId(), 1200); if (network == null) { throw new ConcurrentOperationException("Unable to acquire lock on network " + networkId); } NetworkVO implemented = null; try { if (offering.getGuestType() == GuestType.Isolated && network.getState() != State.Implementing) { throw new IllegalStateException("Network " + networkId + " is not in expected state Implementing, but is in state " + network.getState()); } //Get the Account details and find the type AccountVO networksAccount = _accountDao.findById(network.getAccountId()); if (networksAccount.getType() == Account.ACCOUNT_TYPE_PROJECT) { String errorMessage = "Networks created by account " + networksAccount.getAccountName() + " of type Project (" + Account.ACCOUNT_TYPE_PROJECT + ") " + "are not yet supported by NuageVsp provider"; s_logger.error(errorMessage); throw new InsufficientVirtualNetworkCapacityException(errorMessage, Account.class, network.getAccountId()); } //We don't support a shared network with UserData and multiple IP ranges at the same time. checkMultipleSubnetsCombinedWithUseData(network); long dcId = dest.getDataCenter().getId(); //Get physical network id Long physicalNetworkId = network.getPhysicalNetworkId(); //Physical network id can be null in Guest Network in Basic zone, so locate the physical network if (physicalNetworkId == null) { physicalNetworkId = _networkModel.findPhysicalNetworkId(dcId, offering.getTags(), offering.getTrafficType()); } implemented = new NetworkVO(network.getId(), network, network.getNetworkOfferingId(), network.getGuruName(), network.getDomainId(), network.getAccountId(), network.getRelated(), network.getName(), network.getDisplayText(), network.getNetworkDomain(), network.getGuestType(), network.getDataCenterId(), physicalNetworkId, network.getAclType(), network.getSpecifyIpRanges(), network.getVpcId(), offering.getRedundantRouter()); implemented.setUuid(network.getUuid()); implemented.setState(State.Allocated); if (network.getGateway() != null) { implemented.setGateway(network.getGateway()); } if (network.getCidr() != null) { implemented.setCidr(network.getCidr()); } VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(implemented); String tenantId = context.getDomain().getName() + "-" + context.getAccount().getAccountId(); String broadcastUriStr = implemented.getUuid() + "/" + vspNetwork.getVirtualRouterIp(); implemented.setBroadcastUri(Networks.BroadcastDomainType.Vsp.toUri(broadcastUriStr)); implemented.setBroadcastDomainType(Networks.BroadcastDomainType.Vsp); if (!implement(physicalNetworkId, vspNetwork, _nuageVspEntityBuilder.buildNetworkDhcpOption(network, offering))) { return null; } if (StringUtils.isNotBlank(vspNetwork.getDomainTemplateName())) { if (network.getVpcId() != null) { VpcDetailVO vpcDetail = new VpcDetailVO(network.getVpcId(), NuageVspManager.nuageDomainTemplateDetailName, vspNetwork.getDomainTemplateName(), false); _vpcDetailsDao.persist(vpcDetail); } else { NetworkDetailVO networkDetail = new NetworkDetailVO(implemented.getId(), NuageVspManager.nuageDomainTemplateDetailName, vspNetwork.getDomainTemplateName(), false); _networkDetailsDao.persist(networkDetail); } } s_logger.info("Implemented OK, network " + implemented.getUuid() + " in tenant " + tenantId + " linked to " + implemented.getBroadcastUri()); } finally { _networkDao.releaseFromLockTable(network.getId()); } return implemented; } private boolean implement(long physicalNetworkId, VspNetwork vspNetwork, VspDhcpDomainOption vspDhcpDomainOption) { HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(physicalNetworkId); ImplementNetworkVspCommand cmd = new ImplementNetworkVspCommand(vspNetwork, vspDhcpDomainOption); Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd); if (answer == null || !answer.getResult()) { s_logger.error("ImplementNetworkVspCommand for network " + vspNetwork.getUuid() + " failed on Nuage VSD " + nuageVspHost.getDetail("hostname")); if ((null != answer) && (null != answer.getDetails())) { s_logger.error(answer.getDetails()); } return false; } return true; } @Override public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException { if (vm.getType() != VirtualMachine.Type.DomainRouter && _nuageVspEntityBuilder.usesVirtualRouter(network.getNetworkOfferingId())) { VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(network); if (nic != null && nic.getRequestedIPv4() != null && vspNetwork.getVirtualRouterIp().equals(nic.getRequestedIPv4())) { DataCenter dc = _dcDao.findById(network.getDataCenterId()); s_logger.error("Unable to acquire requested Guest IP address " + nic.getRequestedIPv4() + " because it is reserved for the VR in network " + network); throw new InsufficientVirtualNetworkCapacityException("Unable to acquire requested Guest IP address " + nic.getRequestedIPv4() + " because it is reserved " + "for the VR in network " + network, DataCenter.class,dc.getId()); } } return super.allocate(network, nic, vm); } @Override public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException { boolean lockedNetwork = lockNetworkForUserVm(network, vm); if (lockedNetwork && s_logger.isDebugEnabled()) { s_logger.debug("Locked network " + network.getId() + " for creation of user VM " + vm.getInstanceName()); } try { //We don't support a shared network with UserData and multiple IP ranges at the same time. checkMultipleSubnetsCombinedWithUseData(network); if (s_logger.isDebugEnabled()) { s_logger.debug("Handling reserve() call back to with Create a new VM or add an interface to existing VM in network " + network.getName()); } DataCenter dc = _dcDao.findById(network.getDataCenterId()); AccountVO neworkAccountDetails = _accountDao.findById(network.getAccountId()); if (neworkAccountDetails.getType() == Account.ACCOUNT_TYPE_PROJECT) { throw new InsufficientVirtualNetworkCapacityException("CS project support is not yet implemented in NuageVsp", DataCenter.class, dc.getId()); } if (Strings.isNullOrEmpty(network.getBroadcastUri().getPath()) || !network.getBroadcastUri().getPath().startsWith("/")) { throw new IllegalStateException("The broadcast URI path " + network.getBroadcastUri() + " is empty or in an incorrect format."); } HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(network.getPhysicalNetworkId()); VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(vm.getVirtualMachine().getDomainId(), network); if (vspNetwork.isShared()) { vspNetwork = _nuageVspEntityBuilder.updateVspNetworkByPublicIp(vspNetwork, network, nic.getIPv4Address()); if (VirtualMachine.Type.DomainRouter.equals(vm.getType()) && !nic.getIPv4Address().equals(vspNetwork.getVirtualRouterIp())) { if(s_logger.isDebugEnabled()) { s_logger.debug("VR got spawned with a different IP, releasing the previously allocated public IP " + nic.getIPv4Address()); } IPAddressVO oldIpAddress = _ipAddressDao.findByIpAndSourceNetworkId(network.getId(), nic.getIPv4Address()); _ipAddressDao.unassignIpAddress(oldIpAddress.getId()); _ipAddressDao.mark(network.getDataCenterId(), new Ip(vspNetwork.getVirtualRouterIp())); } else if (VirtualMachine.Type.User.equals(vm.getType()) && nic.getIPv4Address().equals(vspNetwork.getVirtualRouterIp())) { s_logger.error("Deploying a user VM with the same IP as the VR is not allowed."); throw new InsufficientVirtualNetworkCapacityException("Deploying a user VM with the same IP " + nic.getIPv4Address() + " as the VR is not allowed.", Network.class, network.getId()); } // Make sure the shared network is present NetworkOffering offering = _ntwkOfferingDao.findById(network.getNetworkOfferingId()); if (!implement(network.getPhysicalNetworkId(), vspNetwork, _nuageVspEntityBuilder.buildNetworkDhcpOption(network, offering))) { s_logger.error("Failed to implement shared network " + network.getUuid() + " under domain " + context.getDomain().getUuid()); throw new InsufficientVirtualNetworkCapacityException("Failed to implement shared network " + network.getUuid() + " under domain " + context.getDomain().getUuid(), Network.class, network.getId()); } } // Set flags for dhcp options boolean networkHasDns = networkHasDns(network); Map<Long, Boolean> networkHasDnsCache = Maps.newHashMap(); networkHasDnsCache.put(network.getId(), networkHasDns); // Determine if dhcp options of the other nics in the network need to be updated if (vm.getType() == VirtualMachine.Type.DomainRouter && network.getState() != State.Implementing) { updateDhcpOptionsForExistingVms(network, nuageVspHost, vspNetwork, networkHasDns, networkHasDnsCache); } nic.setBroadcastUri(network.getBroadcastUri()); nic.setIsolationUri(network.getBroadcastUri()); //NicProfile does not contain the NIC UUID. We need this information to set it in the VMInterface and VPort //that we create in VSP NicVO nicFromDb = _nicDao.findById(nic.getId()); IPAddressVO staticNatIp = _ipAddressDao.findByVmIdAndNetworkId(network.getId(), vm.getId()); VspVm vspVm = _nuageVspEntityBuilder.buildVspVm(vm.getVirtualMachine(), network); VspNic vspNic = _nuageVspEntityBuilder.buildVspNic(nicFromDb.getUuid(), nic); VspStaticNat vspStaticNat = null; if (staticNatIp != null) { VlanVO staticNatVlan = _vlanDao.findById(staticNatIp.getVlanId()); vspStaticNat = _nuageVspEntityBuilder.buildVspStaticNat(null, staticNatIp, staticNatVlan, null); } boolean defaultHasDns = getDefaultHasDns(networkHasDnsCache, nicFromDb); VspDhcpVMOption dhcpOption = _nuageVspEntityBuilder.buildVmDhcpOption(nicFromDb, defaultHasDns, networkHasDns); ReserveVmInterfaceVspCommand cmd = new ReserveVmInterfaceVspCommand(vspNetwork, vspVm, vspNic, vspStaticNat, dhcpOption); Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd); if (answer == null || !answer.getResult()) { s_logger.error("ReserveVmInterfaceNuageVspCommand failed for NIC " + nic.getId() + " attached to VM " + vm.getId() + " in network " + network.getId()); if ((null != answer) && (null != answer.getDetails())) { s_logger.error(answer.getDetails()); } throw new InsufficientVirtualNetworkCapacityException("Failed to reserve VM in Nuage VSP.", Network.class, network.getId()); } if (vspVm.getDomainRouter() == Boolean.TRUE) { nic.setIPv4Address(vspVm.getDomainRouterIp()); } } finally { if (network != null && lockedNetwork) { _networkDao.releaseFromLockTable(network.getId()); if (s_logger.isDebugEnabled()) { s_logger.debug("Unlocked network " + network.getId() + " for creation of user VM " + vm.getInstanceName()); } } } } private void updateDhcpOptionsForExistingVms(Network network, HostVO nuageVspHost, VspNetwork vspNetwork, boolean networkHasDns, Map<Long, Boolean> networkHasDnsCache) throws InsufficientVirtualNetworkCapacityException { // Update dhcp options if a VR is added when we are not initiating the network if(s_logger.isDebugEnabled()) { s_logger.debug(String.format("DomainRouter is added to an existing network: %s in state: %s", network.getName(), network.getState())); } List<NicVO> userNics = _nicDao.listByNetworkId(network.getId()); LinkedListMultimap<Long, VspDhcpVMOption> dhcpOptionsPerDomain = LinkedListMultimap.create(); for (NicVO userNic : userNics) { if (userNic.getVmType() == VirtualMachine.Type.DomainRouter) { continue; } VMInstanceVO userVm = _vmInstanceDao.findById(userNic.getInstanceId()); boolean defaultHasDns = getDefaultHasDns(networkHasDnsCache, userNic); VspDhcpVMOption dhcpOption = _nuageVspEntityBuilder.buildVmDhcpOption(userNic, defaultHasDns, networkHasDns); dhcpOptionsPerDomain.put(userVm.getDomainId(), dhcpOption); } for (Long domainId : dhcpOptionsPerDomain.keySet()) { VspDomain vspDomain = _nuageVspEntityBuilder.buildVspDomain(_domainDao.findById(domainId)); VspNetwork vspNetworkForDomain = new VspNetwork.Builder().fromObject(vspNetwork).domain(vspDomain).build(); List<VspDhcpVMOption> dhcpOptions = dhcpOptionsPerDomain.get(domainId); UpdateDhcpOptionVspCommand cmd = new UpdateDhcpOptionVspCommand(dhcpOptions, vspNetworkForDomain); Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd); if (answer == null || !answer.getResult()) { s_logger.error("UpdateDhcpOptionVspCommand failed at \"reserve\" for network " + vspNetwork.getName() + " under domain " + vspNetwork.getVspDomain().getName()); if ((null != answer) && (null != answer.getDetails())) { s_logger.error(answer.getDetails()); } throw new InsufficientVirtualNetworkCapacityException("Failed to reserve VM in Nuage VSP.", Network.class, network.getId()); } } } private void checkMultipleSubnetsCombinedWithUseData(Network network) { if (_ntwkOfferingSrvcDao.listServicesForNetworkOffering(network.getNetworkOfferingId()).contains(Network.Service.UserData.getName())) { List<VlanVO> vlanVOs = _vlanDao.listVlansByNetworkId(network.getId()); if (vlanVOs.size() > 1) { VlanVO vlanVoItem = vlanVOs.get(0); for (VlanVO VlanVoItem2 : FluentIterable.from(vlanVOs).skip(1)) { if (!vlanVoItem.equals(VlanVoItem2) && !VlanVoItem2.getVlanGateway().equals(vlanVoItem.getVlanGateway())) { s_logger.error("NuageVsp provider does not support multiple subnets in combination with user data. Network: " + network + ", vlans: " + vlanVOs); throw new UnsupportedServiceException("NuageVsp provider does not support multiple subnets in combination with user data."); } } } } } @Override protected boolean canHandle(NetworkOffering offering, final NetworkType networkType, final PhysicalNetwork physicalNetwork) { if (networkType == NetworkType.Advanced && isMyTrafficType(offering.getTrafficType()) && isMyIsolationMethod(physicalNetwork) && (offering.getGuestType() == Network.GuestType.Isolated || offering.getGuestType() == Network.GuestType.Shared) && hasRequiredServices(offering)) { if (_configMgr.isOfferingForVpc(offering) && !offering.getIsPersistent()) { if (s_logger.isDebugEnabled()) { s_logger.debug("NuageVsp can't handle VPC tiers which use a network offering which are not persistent"); } return false; } else if (offering.getGuestType() == GuestType.Shared) { List<String> supportedSharedNetworkServices = Lists.newArrayList(Network.Service.Connectivity.getName(), Network.Service.Dhcp.getName(), Network.Service.UserData.getName()); List<String> offeringServices = _ntwkOfferingSrvcDao.listServicesForNetworkOffering(offering.getId()); if (!supportedSharedNetworkServices.containsAll(offeringServices)) { if (s_logger.isDebugEnabled()) { s_logger.debug("We only support " + Iterables.toString(supportedSharedNetworkServices) + " services for shared networks"); } return false; } } return true; } else { if (s_logger.isTraceEnabled()) { s_logger.trace("We only take care of networks in zone of type " + NetworkType.Advanced + " without VLAN"); } return false; } } private boolean hasRequiredServices(NetworkOffering networkOffering) { final Map<Network.Service, Set<Network.Provider>> serviceProviderMap = _networkModel.getNetworkOfferingServiceProvidersMap(networkOffering.getId()); if (!serviceProviderMap.get(Network.Service.Connectivity).contains(Network.Provider.NuageVsp)) { if (s_logger.isDebugEnabled()) { s_logger.debug("NuageVsp can't handle networks which use a network offering without NuageVsp as Connectivity provider"); } return false; } if (networkOffering.getGuestType() == GuestType.Isolated && !serviceProviderMap.get(Network.Service.SourceNat).contains(Network.Provider.NuageVsp)) { if (s_logger.isDebugEnabled()) { s_logger.debug("NuageVsp can't handle networks which use a network offering without NuageVsp as SourceNat provider"); } return false; } return true; } @Override @DB public void deallocate(Network network, NicProfile nic, VirtualMachineProfile vm) { boolean lockedNetwork = lockNetworkForUserVm(network, vm); if (lockedNetwork && s_logger.isDebugEnabled()) { s_logger.debug("Locked network " + network.getId() + " for deallocation of user VM " + vm.getInstanceName()); } try { if (s_logger.isDebugEnabled()) { s_logger.debug("Handling deallocate() call back, which is called when a VM is destroyed or interface is removed, " + "to delete VM Interface with IP " + nic.getIPv4Address() + " from a VM " + vm.getInstanceName() + " with state " + vm.getVirtualMachine().getState()); } NicVO nicFromDb = _nicDao.findById(nic.getId()); VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(vm.getVirtualMachine().getDomainId(), network); VspVm vspVm = _nuageVspEntityBuilder.buildVspVm(vm.getVirtualMachine(), network); VspNic vspNic = _nuageVspEntityBuilder.buildVspNic(nicFromDb.getUuid(), nic); HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(network.getPhysicalNetworkId()); DeallocateVmVspCommand cmd = new DeallocateVmVspCommand(vspNetwork, vspVm, vspNic); Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd); if (answer == null || !answer.getResult()) { s_logger.error("DeallocateVmNuageVspCommand for VM " + vm.getUuid() + " failed on Nuage VSD " + nuageVspHost.getDetail("hostname")); if ((null != answer) && (null != answer.getDetails())) { s_logger.error(answer.getDetails()); } } // In case of shared network, when a User VM is spawned with the same IP as the VR, and it gets cleaned up, make sure we do not release the public IP // because it is still allocated for the VR. if (vspNetwork.isShared() && VirtualMachine.Type.User.equals(vm.getType()) && nic.getIPv4Address().equals(vspNetwork.getVirtualRouterIp())) { nic.deallocate(); } else { super.deallocate(network, nic, vm); } } finally { if (network != null && lockedNetwork) { _networkDao.releaseFromLockTable(network.getId()); if (s_logger.isDebugEnabled()) { s_logger.debug("Unlocked network " + network.getId() + " for deallocation of user VM " + vm.getInstanceName()); } } } } private boolean lockNetworkForUserVm(Network network, VirtualMachineProfile vm) { if (!vm.getVirtualMachine().getType().isUsedBySystem()) { long networkId = network.getId(); network = _networkDao.acquireInLockTable(network.getId(), 1200); if (network == null) { throw new ConcurrentOperationException("Unable to acquire lock on network " + networkId); } return true; } return false; } @Override public void shutdown(NetworkProfile profile, NetworkOffering offering) { super.shutdown(profile, offering); } @Override public boolean trash(Network network, NetworkOffering offering) { long networkId = network.getId(); network = _networkDao.acquireInLockTable(networkId, 1200); if (network == null) { throw new ConcurrentOperationException("Unable to acquire lock on network " + networkId); } try { if (s_logger.isDebugEnabled()) { s_logger.debug("Handling trash() call back to delete the network " + network.getName() + " with uuid " + network.getUuid() + " from VSP"); } VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(network); HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(network.getPhysicalNetworkId()); TrashNetworkVspCommand cmd = new TrashNetworkVspCommand(vspNetwork); Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd); if (answer == null || !answer.getResult()) { s_logger.error("TrashNetworkNuageVspCommand for network " + network.getUuid() + " failed"); if ((null != answer) && (null != answer.getDetails())) { s_logger.error(answer.getDetails()); } return false; } } finally { _networkDao.releaseFromLockTable(network.getId()); } return super.trash(network, offering); } private boolean networkHasDns(Network network) { if (network != null) { List<String> dnsProviders = _ntwkOfferingSrvcDao.listProvidersForServiceForNetworkOffering(network.getNetworkOfferingId(), Network.Service.Dns); return dnsProviders.contains(Network.Provider.VirtualRouter.getName()) || dnsProviders.contains(Network.Provider.VPCVirtualRouter.getName()); } return false; } private boolean getDefaultHasDns(Map<Long, Boolean> cache, Nic nic) { Long networkId = nic.isDefaultNic() ? Long.valueOf(nic.getNetworkId()) : getDefaultNetwork(nic.getInstanceId()); Boolean hasDns = cache.get(networkId); if (hasDns == null) { hasDns = networkHasDns(_networkDao.findById(networkId)); cache.put(networkId, hasDns); } return hasDns; } private Long getDefaultNetwork(long vmId) { NicVO defaultNic = _nicDao.findDefaultNicForVM(vmId); if (defaultNic != null) return defaultNic.getNetworkId(); return null; } }