Skip to content

Commit 215ef98

Browse files
authored
Allow cleaning up of networks stuck in Implementing state (#12409)
* Allow cleaning up of networks stuck in Implementing state * extract code
1 parent 223351c commit 215ef98

1 file changed

Lines changed: 80 additions & 0 deletions

File tree

framework/jobs/src/main/java/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -957,13 +957,25 @@ public void reallyRun() {
957957
}
958958

959959
logger.trace("End cleanup expired async-jobs");
960+
961+
cleanupNetworksStuckInImplementing();
962+
960963
} catch (Throwable e) {
961964
logger.error("Unexpected exception when trying to execute queue item, ", e);
962965
}
963966
}
964967
};
965968
}
966969

970+
private void cleanupNetworksStuckInImplementing() {
971+
// Cleanup orphaned networks stuck in Implementing state without async jobs
972+
try {
973+
cleanupOrphanedNetworks();
974+
} catch (Throwable e) {
975+
logger.error("Unexpected exception when trying to cleanup orphaned networks", e);
976+
}
977+
}
978+
967979
@DB
968980
protected void expungeAsyncJob(final AsyncJobVO job) {
969981
Transaction.execute(new TransactionCallbackNoReturn() {
@@ -1272,6 +1284,74 @@ private void cleanupFailedSnapshotsCreatedWithDefaultStrategy(final long msid) {
12721284
}
12731285
}
12741286

1287+
/**
1288+
* Cleanup networks that are stuck in Implementing state without associated async jobs.
1289+
* This only processes networks that have been stuck for longer than the job expiration threshold.
1290+
*/
1291+
private void cleanupOrphanedNetworks() {
1292+
try {
1293+
SearchCriteria<NetworkVO> sc = networkDao.createSearchCriteria();
1294+
sc.addAnd("state", SearchCriteria.Op.EQ, Network.State.Implementing);
1295+
sc.addAnd("removed", SearchCriteria.Op.NULL);
1296+
List<NetworkVO> implementingNetworks = networkDao.search(sc, null);
1297+
1298+
if (implementingNetworks == null || implementingNetworks.isEmpty()) {
1299+
return;
1300+
}
1301+
1302+
logger.debug("Found {} networks in Implementing state, checking for orphaned networks", implementingNetworks.size());
1303+
1304+
final long expireMinutes = JobExpireMinutes.value();
1305+
final Date cutoffTime = new Date(System.currentTimeMillis() - (expireMinutes * 60 * 1000));
1306+
1307+
for (NetworkVO network : implementingNetworks) {
1308+
if (network.getCreated().after(cutoffTime)) {
1309+
logger.trace("Network {} in Implementing state is only {} minutes old (threshold: {} minutes), skipping cleanup",
1310+
network.getId(),
1311+
(System.currentTimeMillis() - network.getCreated().getTime()) / 60000,
1312+
expireMinutes);
1313+
continue;
1314+
}
1315+
1316+
List<AsyncJobVO> jobs = _jobDao.findInstancePendingAsyncJobs("Network", network.getAccountId());
1317+
boolean hasActiveJob = false;
1318+
for (AsyncJobVO job : jobs) {
1319+
if (job.getInstanceId() != null && job.getInstanceId().equals(network.getId())) {
1320+
hasActiveJob = true;
1321+
break;
1322+
}
1323+
}
1324+
1325+
if (hasActiveJob) {
1326+
logger.debug("Network {} in Implementing state has active async job, skipping cleanup", network.getId());
1327+
continue;
1328+
}
1329+
1330+
logger.warn("Found orphaned network {} in Implementing state without async job. " +
1331+
"Network created: {}, age: {} minutes, expiration threshold: {} minutes. Transitioning to Shutdown state.",
1332+
network.getId(), network.getCreated(),
1333+
(System.currentTimeMillis() - network.getCreated().getTime()) / 60000,
1334+
expireMinutes);
1335+
updateNetworkState(network);
1336+
1337+
}
1338+
} catch (Exception e) {
1339+
logger.error("Error while cleaning up orphaned networks", e);
1340+
}
1341+
}
1342+
1343+
private void updateNetworkState(NetworkVO network) {
1344+
try {
1345+
networkOrchestrationService.stateTransitTo(network, Network.Event.OperationFailed);
1346+
logger.info("Successfully transitioned orphaned network {} to Shutdown state using state machine", network.getId());
1347+
} catch (final NoTransitionException e) {
1348+
logger.debug("State transition failed for orphaned network {}, forcing state update", network.getId());
1349+
network.setState(Network.State.Shutdown);
1350+
networkDao.update(network.getId(), network);
1351+
logger.info("Successfully forced orphaned network {} to Shutdown state", network.getId());
1352+
}
1353+
}
1354+
12751355
@Override
12761356
public void onManagementNodeJoined(List<? extends ManagementServerHost> nodeList, long selfNodeId) {
12771357
}

0 commit comments

Comments
 (0)