diff --git a/server/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml b/server/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml index 6d8f32e0703..ad43fa9481b 100644 --- a/server/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml +++ b/server/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml @@ -183,6 +183,8 @@ + + diff --git a/server/src/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/com/cloud/network/vpc/VpcManagerImpl.java index e999c4b3e7a..a85b11279de 100644 --- a/server/src/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/com/cloud/network/vpc/VpcManagerImpl.java @@ -28,7 +28,10 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -213,6 +216,9 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis @Inject ConfigDepot _configDepot; + @Inject + private VpcPrivateGatewayTransactionCallable vpcTxCallable; + private final ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("VpcChecker")); private List vpcElements = null; private final List nonSupportedServices = Arrays.asList(Service.SecurityGroup, Service.Firewall); @@ -1779,37 +1785,26 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis //check if there are ips allocted in the network final long networkId = gateway.getNetworkId(); - boolean deleteNetwork = true; - final List privateIps = _privateIpDao.listByNetworkId(networkId); - if (privateIps.size() > 1 || !privateIps.get(0).getIpAddress().equalsIgnoreCase(gateway.getIp4Address())) { - s_logger.debug("Not removing network id=" + gateway.getNetworkId() + " as it has private ip addresses for other gateways"); - deleteNetwork = false; - } + vpcTxCallable.setGateway(gateway); - //TODO: Clean this up, its bad. There is a DB transaction wrapping calls to NetworkElements (destroyNetwork will - // call network elements). - final boolean deleteNetworkFinal = deleteNetwork; - Transaction.execute(new TransactionCallbackNoReturn() { - @Override - public void doInTransactionWithoutResult(final TransactionStatus status) { - final PrivateIpVO ip = _privateIpDao.findByIpAndVpcId(gateway.getVpcId(), gateway.getIp4Address()); - if (ip != null) { - _privateIpDao.remove(ip.getId()); - s_logger.debug("Deleted private ip " + ip); - } + final ExecutorService txExecutor = Executors.newSingleThreadExecutor(); + final Future futureResult = txExecutor.submit(vpcTxCallable); - if (deleteNetworkFinal) { - final User callerUser = _accountMgr.getActiveUser(CallContext.current().getCallingUserId()); - final Account owner = _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM); - final ReservationContext context = new ReservationContextImpl(null, null, callerUser, owner); - _ntwkMgr.destroyNetwork(networkId, context, false); - s_logger.debug("Deleted private network id=" + networkId); - } - - _vpcGatewayDao.remove(gateway.getId()); - s_logger.debug("Deleted private gateway " + gateway); + boolean deleteNetworkFinal; + try { + deleteNetworkFinal = futureResult.get(); + if (deleteNetworkFinal) { + final User callerUser = _accountMgr.getActiveUser(CallContext.current().getCallingUserId()); + final Account owner = _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM); + final ReservationContext context = new ReservationContextImpl(null, null, callerUser, owner); + _ntwkMgr.destroyNetwork(networkId, context, false); + s_logger.debug("Deleted private network id=" + networkId); } - }); + } catch (final InterruptedException e) { + s_logger.error("deletePrivateGatewayFromTheDB failed to delete network id " + networkId + "due to => ", e); + } catch (final ExecutionException e) { + s_logger.error("deletePrivateGatewayFromTheDB failed to delete network id " + networkId + "due to => ", e); + } return true; } @@ -2415,4 +2410,4 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis final StaticRoute route = _staticRouteDao.findById(routeId); return applyStaticRoutesForVpc(route.getVpcId()); } -} +} \ No newline at end of file diff --git a/server/src/com/cloud/network/vpc/VpcPrivateGatewayTransactionCallable.java b/server/src/com/cloud/network/vpc/VpcPrivateGatewayTransactionCallable.java new file mode 100644 index 00000000000..b23128da4eb --- /dev/null +++ b/server/src/com/cloud/network/vpc/VpcPrivateGatewayTransactionCallable.java @@ -0,0 +1,77 @@ +// 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.vpc; + +import java.util.List; +import java.util.concurrent.Callable; + +import javax.inject.Inject; + +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.network.vpc.dao.PrivateIpDao; +import com.cloud.network.vpc.dao.VpcGatewayDao; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.db.TransactionCallbackNoReturn; +import com.cloud.utils.db.TransactionStatus; + +@Component +public class VpcPrivateGatewayTransactionCallable implements Callable { + + private static final Logger s_logger = Logger.getLogger(VpcPrivateGatewayTransactionCallable.class); + + @Inject + private VpcGatewayDao _vpcGatewayDao; + @Inject + private PrivateIpDao _privateIpDao; + + private PrivateGateway gateway; + private boolean deleteNetwork = true; + + @Override + public Boolean call() throws Exception { + final long networkId = gateway.getNetworkId(); + + Transaction.execute(new TransactionCallbackNoReturn() { + @Override + public void doInTransactionWithoutResult(final TransactionStatus status) { + + final List privateIps = _privateIpDao.listByNetworkId(networkId); + if (privateIps.size() > 1 || !privateIps.get(0).getIpAddress().equalsIgnoreCase(gateway.getIp4Address())) { + s_logger.debug("Not removing network id=" + gateway.getNetworkId() + " as it has private ip addresses for other gateways"); + deleteNetwork = false; + } + + final PrivateIpVO ip = _privateIpDao.findByIpAndVpcId(gateway.getVpcId(), gateway.getIp4Address()); + if (ip != null) { + _privateIpDao.remove(ip.getId()); + s_logger.debug("Deleted private ip " + ip); + } + + _vpcGatewayDao.remove(gateway.getId()); + s_logger.debug("Deleted private gateway " + gateway); + } + }); + + return deleteNetwork; + } + + public void setGateway(final PrivateGateway gateway) { + this.gateway = gateway; + } +} \ No newline at end of file