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