Search in sources :

Example 11 with TransactionCallbackWithException

use of com.cloud.utils.db.TransactionCallbackWithException in project cloudstack by apache.

the class IpAddressManagerImpl method associateIpAddressListToAccount.

@Override
@DB
public boolean associateIpAddressListToAccount(long userId, final long accountId, final long zoneId, final Long vlanId, final Network guestNetworkFinal) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, ResourceAllocationException {
    final Account owner = _accountMgr.getActiveAccountById(accountId);
    if (guestNetworkFinal != null && guestNetworkFinal.getTrafficType() != TrafficType.Guest) {
        throw new InvalidParameterValueException("Network " + guestNetworkFinal + " is not of a type " + TrafficType.Guest);
    }
    Ternary<Boolean, List<NetworkOfferingVO>, Network> pair = null;
    try {
        pair = Transaction.execute(new TransactionCallbackWithException<Ternary<Boolean, List<NetworkOfferingVO>, Network>, Exception>() {

            @Override
            public Ternary<Boolean, List<NetworkOfferingVO>, Network> doInTransaction(TransactionStatus status) throws InsufficientCapacityException, ResourceAllocationException {
                boolean createNetwork = false;
                Network guestNetwork = guestNetworkFinal;
                if (guestNetwork == null) {
                    List<? extends Network> networks = getIsolatedNetworksWithSourceNATOwnedByAccountInZone(zoneId, owner);
                    if (networks.size() == 0) {
                        createNetwork = true;
                    } else if (networks.size() == 1) {
                        guestNetwork = networks.get(0);
                    } else {
                        throw new InvalidParameterValueException("Error, more than 1 Guest Isolated Networks with SourceNAT " + "service enabled found for this account, cannot assosiate the IP range, please provide the network ID");
                    }
                }
                // create new Virtual network (Isolated with SourceNAT) for the user if it doesn't exist
                List<NetworkOfferingVO> requiredOfferings = _networkOfferingDao.listByAvailability(Availability.Required, false);
                if (requiredOfferings.size() < 1) {
                    throw new CloudRuntimeException("Unable to find network offering with availability=" + Availability.Required + " to automatically create the network as part of createVlanIpRange");
                }
                if (createNetwork) {
                    if (requiredOfferings.get(0).getState() == NetworkOffering.State.Enabled) {
                        long physicalNetworkId = _networkModel.findPhysicalNetworkId(zoneId, requiredOfferings.get(0).getTags(), requiredOfferings.get(0).getTrafficType());
                        // Validate physical network
                        PhysicalNetwork physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId);
                        if (physicalNetwork == null) {
                            throw new InvalidParameterValueException("Unable to find physical network with id: " + physicalNetworkId + " and tag: " + requiredOfferings.get(0).getTags());
                        }
                        s_logger.debug("Creating network for account " + owner + " from the network offering id=" + requiredOfferings.get(0).getId() + " as a part of createVlanIpRange process");
                        guestNetwork = _networkMgr.createGuestNetwork(requiredOfferings.get(0).getId(), owner.getAccountName() + "-network", owner.getAccountName() + "-network", null, null, null, null, owner, null, physicalNetwork, zoneId, ACLType.Account, null, null, null, null, true, null);
                        if (guestNetwork == null) {
                            s_logger.warn("Failed to create default Virtual network for the account " + accountId + "in zone " + zoneId);
                            throw new CloudRuntimeException("Failed to create a Guest Isolated Networks with SourceNAT " + "service enabled as a part of createVlanIpRange, for the account " + accountId + "in zone " + zoneId);
                        }
                    } else {
                        throw new CloudRuntimeException("Required network offering id=" + requiredOfferings.get(0).getId() + " is not in " + NetworkOffering.State.Enabled);
                    }
                }
                // Check if there is a source nat ip address for this account; if not - we have to allocate one
                boolean allocateSourceNat = false;
                List<IPAddressVO> sourceNat = _ipAddressDao.listByAssociatedNetwork(guestNetwork.getId(), true);
                if (sourceNat.isEmpty()) {
                    allocateSourceNat = true;
                }
                // update all ips with a network id, mark them as allocated and update resourceCount/usage
                List<IPAddressVO> ips = _ipAddressDao.listByVlanId(vlanId);
                boolean isSourceNatAllocated = false;
                for (IPAddressVO addr : ips) {
                    if (addr.getState() != State.Allocated) {
                        if (!isSourceNatAllocated && allocateSourceNat) {
                            addr.setSourceNat(true);
                            isSourceNatAllocated = true;
                        } else {
                            addr.setSourceNat(false);
                        }
                        addr.setAssociatedWithNetworkId(guestNetwork.getId());
                        addr.setVpcId(guestNetwork.getVpcId());
                        addr.setAllocatedTime(new Date());
                        addr.setAllocatedInDomainId(owner.getDomainId());
                        addr.setAllocatedToAccountId(owner.getId());
                        addr.setSystem(false);
                        addr.setState(IpAddress.State.Allocating);
                        markPublicIpAsAllocated(addr);
                    }
                }
                return new Ternary<Boolean, List<NetworkOfferingVO>, Network>(createNetwork, requiredOfferings, guestNetwork);
            }
        });
    } catch (Exception e1) {
        ExceptionUtil.rethrowRuntime(e1);
        ExceptionUtil.rethrow(e1, InsufficientCapacityException.class);
        ExceptionUtil.rethrow(e1, ResourceAllocationException.class);
        throw new IllegalStateException(e1);
    }
    boolean createNetwork = pair.first();
    List<NetworkOfferingVO> requiredOfferings = pair.second();
    Network guestNetwork = pair.third();
    // if the network offering has persistent set to true, implement the network
    if (createNetwork && requiredOfferings.get(0).getIsPersistent()) {
        DataCenter zone = _dcDao.findById(zoneId);
        DeployDestination dest = new DeployDestination(zone, null, null, null);
        Account callerAccount = CallContext.current().getCallingAccount();
        UserVO callerUser = _userDao.findById(CallContext.current().getCallingUserId());
        Journal journal = new Journal.LogJournal("Implementing " + guestNetwork, s_logger);
        ReservationContext context = new ReservationContextImpl(UUID.randomUUID().toString(), journal, callerUser, callerAccount);
        s_logger.debug("Implementing network " + guestNetwork + " as a part of network provision for persistent network");
        try {
            Pair<? extends NetworkGuru, ? extends Network> implementedNetwork = _networkMgr.implementNetwork(guestNetwork.getId(), dest, context);
            if (implementedNetwork == null || implementedNetwork.first() == null) {
                s_logger.warn("Failed to implement the network " + guestNetwork);
            }
            if (implementedNetwork != null) {
                guestNetwork = implementedNetwork.second();
            }
        } catch (Exception ex) {
            s_logger.warn("Failed to implement network " + guestNetwork + " elements and resources as a part of" + " network provision due to ", ex);
            CloudRuntimeException e = new CloudRuntimeException("Failed to implement network (with specified id)" + " elements and resources as a part of network provision for persistent network");
            e.addProxyObject(guestNetwork.getUuid(), "networkId");
            throw e;
        }
    }
    return true;
}
Also used : Account(com.cloud.user.Account) TransactionStatus(com.cloud.utils.db.TransactionStatus) Journal(com.cloud.utils.Journal) ReservationContextImpl(com.cloud.vm.ReservationContextImpl) ReservationContext(com.cloud.vm.ReservationContext) InvalidParameterValueException(com.cloud.exception.InvalidParameterValueException) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) ArrayList(java.util.ArrayList) List(java.util.List) InsufficientCapacityException(com.cloud.exception.InsufficientCapacityException) ResourceAllocationException(com.cloud.exception.ResourceAllocationException) TransactionCallbackWithException(com.cloud.utils.db.TransactionCallbackWithException) Ternary(com.cloud.utils.Ternary) Date(java.util.Date) AccountLimitException(com.cloud.exception.AccountLimitException) TransactionCallbackWithException(com.cloud.utils.db.TransactionCallbackWithException) InsufficientCapacityException(com.cloud.exception.InsufficientCapacityException) InsufficientAddressCapacityException(com.cloud.exception.InsufficientAddressCapacityException) ResourceUnavailableException(com.cloud.exception.ResourceUnavailableException) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) InvalidParameterValueException(com.cloud.exception.InvalidParameterValueException) ResourceAllocationException(com.cloud.exception.ResourceAllocationException) ConcurrentOperationException(com.cloud.exception.ConcurrentOperationException) InsufficientVirtualNetworkCapacityException(com.cloud.exception.InsufficientVirtualNetworkCapacityException) PermissionDeniedException(com.cloud.exception.PermissionDeniedException) DataCenter(com.cloud.dc.DataCenter) UserVO(com.cloud.user.UserVO) DeployDestination(com.cloud.deploy.DeployDestination) NetworkOfferingVO(com.cloud.offerings.NetworkOfferingVO) IPAddressVO(com.cloud.network.dao.IPAddressVO) DB(com.cloud.utils.db.DB)

Example 12 with TransactionCallbackWithException

use of com.cloud.utils.db.TransactionCallbackWithException in project cloudstack by apache.

the class ExternalLoadBalancerDeviceManagerImpl method allocateLoadBalancerForNetwork.

@DB
protected ExternalLoadBalancerDeviceVO allocateLoadBalancerForNetwork(final Network guestConfig) throws InsufficientCapacityException {
    boolean retry = true;
    boolean tryLbProvisioning = false;
    ExternalLoadBalancerDeviceVO lbDevice = null;
    long physicalNetworkId = guestConfig.getPhysicalNetworkId();
    NetworkOfferingVO offering = _networkOfferingDao.findById(guestConfig.getNetworkOfferingId());
    String provider = _ntwkSrvcProviderDao.getProviderForServiceInNetwork(guestConfig.getId(), Service.Lb);
    while (retry) {
        GlobalLock deviceMapLock = GlobalLock.getInternLock("LoadBalancerAllocLock");
        try {
            if (deviceMapLock.lock(120)) {
                try {
                    // does network offering supports a dedicated load balancer?
                    final boolean dedicatedLB = offering.getDedicatedLB();
                    try {
                        lbDevice = Transaction.execute(new TransactionCallbackWithException<ExternalLoadBalancerDeviceVO, InsufficientCapacityException>() {

                            @Override
                            public ExternalLoadBalancerDeviceVO doInTransaction(TransactionStatus status) throws InsufficientCapacityException {
                                // FIXME: should the device allocation be done during network implement phase or do a
                                // lazy allocation when first rule for the network is configured??
                                // find a load balancer device for this network as per the network offering
                                ExternalLoadBalancerDeviceVO lbDevice = findSuitableLoadBalancerForNetwork(guestConfig, dedicatedLB);
                                long lbDeviceId = lbDevice.getId();
                                // persist the load balancer device id that will be used for this network. Once a network
                                // is implemented on a LB device then later on all rules will be programmed on to same device
                                NetworkExternalLoadBalancerVO networkLB = new NetworkExternalLoadBalancerVO(guestConfig.getId(), lbDeviceId);
                                _networkExternalLBDao.persist(networkLB);
                                // mark device to be either dedicated or shared use
                                lbDevice.setAllocationState(dedicatedLB ? LBDeviceAllocationState.Dedicated : LBDeviceAllocationState.Shared);
                                _externalLoadBalancerDeviceDao.update(lbDeviceId, lbDevice);
                                return lbDevice;
                            }
                        });
                        // allocated load balancer for the network, so skip retry
                        tryLbProvisioning = false;
                        retry = false;
                    } catch (InsufficientCapacityException exception) {
                        // if already attempted to provision load balancer then throw out of capacity exception,
                        if (tryLbProvisioning) {
                            retry = false;
                            // TODO: throwing warning instead of error for now as its possible another provider can service this network
                            s_logger.warn("There are no load balancer device with the capacity for implementing this network");
                            throw exception;
                        } else {
                            // if possible provision a LB appliance in to the physical network
                            tryLbProvisioning = true;
                        }
                    }
                } finally {
                    deviceMapLock.unlock();
                }
            }
        } finally {
            deviceMapLock.releaseRef();
        }
        // there are no LB devices or there is no free capacity on the devices in the physical network so provision a new LB appliance
        if (tryLbProvisioning) {
            // check if LB appliance can be dynamically provisioned
            List<ExternalLoadBalancerDeviceVO> providerLbDevices = _externalLoadBalancerDeviceDao.listByProviderAndDeviceAllocationState(physicalNetworkId, provider, LBDeviceAllocationState.Provider);
            if ((providerLbDevices != null) && (!providerLbDevices.isEmpty())) {
                for (ExternalLoadBalancerDeviceVO lbProviderDevice : providerLbDevices) {
                    if (lbProviderDevice.getState() == LBDeviceState.Enabled) {
                        // acquire a private IP from the data center which will be used as management IP of provisioned LB appliance,
                        DataCenterIpAddressVO dcPrivateIp = _dcDao.allocatePrivateIpAddress(guestConfig.getDataCenterId(), lbProviderDevice.getUuid());
                        if (dcPrivateIp == null) {
                            throw new InsufficientNetworkCapacityException("failed to acquire a priavate IP in the zone " + guestConfig.getDataCenterId() + " needed for management IP of the load balancer appliance", DataCenter.class, guestConfig.getDataCenterId());
                        }
                        Pod pod = _podDao.findById(dcPrivateIp.getPodId());
                        String lbIP = dcPrivateIp.getIpAddress();
                        String netmask = NetUtils.getCidrNetmask(pod.getCidrSize());
                        String gateway = pod.getGateway();
                        // send CreateLoadBalancerApplianceCommand to the host capable of provisioning
                        CreateLoadBalancerApplianceCommand lbProvisionCmd = new CreateLoadBalancerApplianceCommand(lbIP, netmask, gateway);
                        CreateLoadBalancerApplianceAnswer createLbAnswer = null;
                        try {
                            createLbAnswer = (CreateLoadBalancerApplianceAnswer) _agentMgr.easySend(lbProviderDevice.getHostId(), lbProvisionCmd);
                            if (createLbAnswer == null || !createLbAnswer.getResult()) {
                                s_logger.error("Could not provision load balancer instance on the load balancer device " + lbProviderDevice.getId());
                                continue;
                            }
                        } catch (Exception agentException) {
                            s_logger.error("Could not provision load balancer instance on the load balancer device " + lbProviderDevice.getId() + " due to " + agentException.getMessage());
                            continue;
                        }
                        String username = createLbAnswer.getUsername();
                        String password = createLbAnswer.getPassword();
                        String publicIf = createLbAnswer.getPublicInterface();
                        String privateIf = createLbAnswer.getPrivateInterface();
                        // we have provisioned load balancer so add the appliance as cloudstack provisioned external load balancer
                        String dedicatedLb = offering.getDedicatedLB() ? "true" : "false";
                        String capacity = Long.toString(lbProviderDevice.getCapacity());
                        // acquire a public IP to associate with lb appliance (used as subnet IP to make the appliance part of private network)
                        PublicIp publicIp = _ipAddrMgr.assignPublicIpAddress(guestConfig.getDataCenterId(), null, _accountMgr.getSystemAccount(), VlanType.VirtualNetwork, null, null, false);
                        String publicIPNetmask = publicIp.getVlanNetmask();
                        String publicIPgateway = publicIp.getVlanGateway();
                        String publicIP = publicIp.getAddress().toString();
                        String publicIPVlanTag = "";
                        try {
                            publicIPVlanTag = BroadcastDomainType.getValue(publicIp.getVlanTag());
                        } catch (URISyntaxException e) {
                            s_logger.error("Failed to parse public ip vlan tag" + e.getMessage());
                        }
                        String url = "https://" + lbIP + "?publicinterface=" + publicIf + "&privateinterface=" + privateIf + "&lbdevicededicated=" + dedicatedLb + "&cloudmanaged=true" + "&publicip=" + publicIP + "&publicipnetmask=" + publicIPNetmask + "&lbdevicecapacity=" + capacity + "&publicipvlan=" + publicIPVlanTag + "&publicipgateway=" + publicIPgateway;
                        ExternalLoadBalancerDeviceVO lbAppliance = null;
                        try {
                            lbAppliance = addExternalLoadBalancer(physicalNetworkId, url, username, password, createLbAnswer.getDeviceName(), createLbAnswer.getServerResource(), false, false, null, null);
                        } catch (Exception e) {
                            s_logger.error("Failed to add load balancer appliance in to cloudstack due to " + e.getMessage() + ". So provisioned load balancer appliance will be destroyed.");
                        }
                        if (lbAppliance != null) {
                            // mark the load balancer as cloudstack managed and set parent host id on which lb appliance is provisioned
                            ExternalLoadBalancerDeviceVO managedLb = _externalLoadBalancerDeviceDao.findById(lbAppliance.getId());
                            managedLb.setIsManagedDevice(true);
                            managedLb.setParentHostId(lbProviderDevice.getHostId());
                            _externalLoadBalancerDeviceDao.update(lbAppliance.getId(), managedLb);
                        } else {
                            // failed to add the provisioned load balancer into cloudstack so destroy the appliance
                            DestroyLoadBalancerApplianceCommand lbDeleteCmd = new DestroyLoadBalancerApplianceCommand(lbIP);
                            DestroyLoadBalancerApplianceAnswer answer = null;
                            try {
                                answer = (DestroyLoadBalancerApplianceAnswer) _agentMgr.easySend(lbProviderDevice.getHostId(), lbDeleteCmd);
                                if (answer == null || !answer.getResult()) {
                                    s_logger.warn("Failed to destroy load balancer appliance created");
                                } else {
                                    // release the public & private IP back to dc pool, as the load balancer appliance is now destroyed
                                    _dcDao.releasePrivateIpAddress(lbIP, guestConfig.getDataCenterId(), null);
                                    _ipAddrMgr.disassociatePublicIpAddress(publicIp.getId(), _accountMgr.getSystemUser().getId(), _accountMgr.getSystemAccount());
                                }
                            } catch (Exception e) {
                                s_logger.warn("Failed to destroy load balancer appliance created for the network" + guestConfig.getId() + " due to " + e.getMessage());
                            }
                        }
                    }
                }
            }
        }
    }
    return lbDevice;
}
Also used : CreateLoadBalancerApplianceCommand(com.cloud.agent.api.routing.CreateLoadBalancerApplianceCommand) Pod(com.cloud.dc.Pod) TransactionCallbackWithException(com.cloud.utils.db.TransactionCallbackWithException) PublicIp(com.cloud.network.addr.PublicIp) DataCenterIpAddressVO(com.cloud.dc.DataCenterIpAddressVO) TransactionStatus(com.cloud.utils.db.TransactionStatus) URISyntaxException(java.net.URISyntaxException) NetworkExternalLoadBalancerVO(com.cloud.network.dao.NetworkExternalLoadBalancerVO) TransactionCallbackWithException(com.cloud.utils.db.TransactionCallbackWithException) InsufficientCapacityException(com.cloud.exception.InsufficientCapacityException) ResourceUnavailableException(com.cloud.exception.ResourceUnavailableException) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) InsufficientNetworkCapacityException(com.cloud.exception.InsufficientNetworkCapacityException) URISyntaxException(java.net.URISyntaxException) InvalidParameterValueException(com.cloud.exception.InvalidParameterValueException) ConfigurationException(javax.naming.ConfigurationException) UnableDeleteHostException(com.cloud.resource.UnableDeleteHostException) ExternalLoadBalancerDeviceVO(com.cloud.network.dao.ExternalLoadBalancerDeviceVO) GlobalLock(com.cloud.utils.db.GlobalLock) InsufficientNetworkCapacityException(com.cloud.exception.InsufficientNetworkCapacityException) DestroyLoadBalancerApplianceCommand(com.cloud.agent.api.routing.DestroyLoadBalancerApplianceCommand) CreateLoadBalancerApplianceAnswer(com.cloud.network.resource.CreateLoadBalancerApplianceAnswer) NetworkOfferingVO(com.cloud.offerings.NetworkOfferingVO) DestroyLoadBalancerApplianceAnswer(com.cloud.network.resource.DestroyLoadBalancerApplianceAnswer) InsufficientCapacityException(com.cloud.exception.InsufficientCapacityException) DB(com.cloud.utils.db.DB)

Aggregations

TransactionCallbackWithException (com.cloud.utils.db.TransactionCallbackWithException)12 TransactionStatus (com.cloud.utils.db.TransactionStatus)12 DB (com.cloud.utils.db.DB)11 InsufficientAddressCapacityException (com.cloud.exception.InsufficientAddressCapacityException)10 InvalidParameterValueException (com.cloud.exception.InvalidParameterValueException)9 CloudRuntimeException (com.cloud.utils.exception.CloudRuntimeException)9 ResourceUnavailableException (com.cloud.exception.ResourceUnavailableException)8 Account (com.cloud.user.Account)7 ConcurrentOperationException (com.cloud.exception.ConcurrentOperationException)6 PermissionDeniedException (com.cloud.exception.PermissionDeniedException)6 IPAddressVO (com.cloud.network.dao.IPAddressVO)6 InsufficientCapacityException (com.cloud.exception.InsufficientCapacityException)5 NetworkRuleConflictException (com.cloud.exception.NetworkRuleConflictException)5 PublicIp (com.cloud.network.addr.PublicIp)5 ResourceAllocationException (com.cloud.exception.ResourceAllocationException)4 Network (com.cloud.network.Network)4 Ip (com.cloud.utils.net.Ip)4 ConfigurationException (javax.naming.ConfigurationException)4 ActionEvent (com.cloud.event.ActionEvent)3 UnsupportedServiceException (com.cloud.exception.UnsupportedServiceException)3