protected boolean cleanupAccount()

in server/src/main/java/com/cloud/user/AccountManagerImpl.java [887:1188]


    protected boolean cleanupAccount(AccountVO account, long callerUserId, Account caller) {
        long accountId = account.getId();
        boolean accountCleanupNeeded = false;

        try {
            // cleanup the users from the account
            List<UserVO> users = _userDao.listByAccount(accountId);
            for (UserVO user : users) {
                if (!_userDao.remove(user.getId())) {
                    logger.error("Unable to delete user: " + user + " as a part of account " + account + " cleanup");
                    accountCleanupNeeded = true;
                }
            }

            // delete autoscaling VM groups
            if (!_autoscaleMgr.deleteAutoScaleVmGroupsByAccount(account)) {
                accountCleanupNeeded = true;
            }


            // delete global load balancer rules for the account.
            List<org.apache.cloudstack.region.gslb.GlobalLoadBalancerRuleVO> gslbRules = _gslbRuleDao.listByAccount(accountId);
            if (gslbRules != null && !gslbRules.isEmpty()) {
                _gslbService.revokeAllGslbRulesForAccount(caller, account);
            }

            // delete the account from project accounts
            _projectAccountDao.removeAccountFromProjects(accountId);

            // Delete account's network permissions
            networkPermissionDao.removeAccountPermissions(accountId);

            if (account.getType() != Account.Type.PROJECT) {
                // delete the account from group
                _messageBus.publish(_name, MESSAGE_REMOVE_ACCOUNT_EVENT, PublishScope.LOCAL, accountId);
            }

            // delete all vm groups belonging to account
            List<InstanceGroupVO> groups = _vmGroupDao.listByAccountId(accountId);
            for (InstanceGroupVO group : groups) {
                if (!_vmMgr.deleteVmGroup(group.getId())) {
                    logger.error("Unable to delete group: {}", group);
                    accountCleanupNeeded = true;
                }
            }

            // Delete the snapshots dir for the account. Have to do this before destroying the VMs.
            boolean success = _snapMgr.deleteSnapshotDirsForAccount(account);
            if (success) {
                logger.debug("Successfully deleted snapshots directories for all volumes under account {} across all zones", account);
            }

            // clean up templates
            List<VMTemplateVO> userTemplates = _templateDao.listByAccountId(accountId);
            boolean allTemplatesDeleted = true;
            for (VMTemplateVO template : userTemplates) {
                if (template.getRemoved() == null) {
                    try {
                        allTemplatesDeleted = _tmpltMgr.delete(callerUserId, template.getId(), null);
                    } catch (Exception e) {
                        logger.warn("Failed to delete template {} while removing account {} due to: ", template, account, e);
                        allTemplatesDeleted = false;
                    }
                }
            }

            if (!allTemplatesDeleted) {
                logger.warn("Failed to delete templates while removing account {}", account);
                accountCleanupNeeded = true;
            }

            // Destroy VM Snapshots
            List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.listByAccountId(Long.valueOf(accountId));
            for (VMSnapshot vmSnapshot : vmSnapshots) {
                try {
                    _vmSnapshotMgr.deleteVMSnapshot(vmSnapshot.getId());
                } catch (Exception e) {
                    logger.debug("Failed to cleanup vm snapshot {} due to {}", vmSnapshot, e.toString());
                }
            }

            // Destroy the account's VMs
            List<UserVmVO> vms = _userVmDao.listByAccountId(accountId);
            if (logger.isDebugEnabled()) {
                logger.debug("Expunging # of vms (account={}): {}", account, vms.size());
            }

            for (UserVmVO vm : vms) {
                if (vm.getState() != VirtualMachine.State.Destroyed && vm.getState() != VirtualMachine.State.Expunging) {
                    try {
                        _vmMgr.destroyVm(vm.getId(), false);
                    } catch (Exception e) {
                        e.printStackTrace();
                        logger.warn("Failed destroying instance {} as part of account deletion.", vm);
                    }
                }
                // no need to catch exception at this place as expunging vm
                // should pass in order to perform further cleanup
                if (!_vmMgr.expunge(vm)) {
                    logger.error("Unable to expunge vm: {}", vm);
                    accountCleanupNeeded = true;
                }
            }

            // Mark the account's volumes as destroyed
            List<VolumeVO> volumes = _volumeDao.findDetachedByAccount(accountId);
            for (VolumeVO volume : volumes) {
                try {
                    volumeService.deleteVolume(volume.getId(), caller);
                } catch (Exception ex) {
                    logger.warn("Failed to cleanup volumes as a part of account {} cleanup due to Exception: ", account, ex);
                    accountCleanupNeeded = true;
                }
            }

            // delete remote access vpns and associated users
            List<RemoteAccessVpnVO> remoteAccessVpns = _remoteAccessVpnDao.findByAccount(accountId);
            List<VpnUserVO> vpnUsers = _vpnUser.listByAccount(accountId);

            for (VpnUserVO vpnUser : vpnUsers) {
                _remoteAccessVpnMgr.removeVpnUser(account, vpnUser.getUsername(), caller);
            }

            try {
                for (RemoteAccessVpnVO vpn : remoteAccessVpns) {
                    _remoteAccessVpnMgr.destroyRemoteAccessVpnForIp(vpn.getServerAddressId(), caller, false);
                }
            } catch (ResourceUnavailableException ex) {
                logger.warn("Failed to cleanup remote access vpn resources as a part of account {} cleanup due to Exception: ", account, ex);
                accountCleanupNeeded = true;
            }

            // Cleanup tungsten security groups
            List<SecurityGroupVO> securityGroupList = _securityGroupDao.listByAccountId(accountId);
            for(SecurityGroupVO securityGroupVO : securityGroupList) {
                _messageBus.publish(_name, SecurityGroupService.MESSAGE_DELETE_TUNGSTEN_SECURITY_GROUP_EVENT, PublishScope.LOCAL, securityGroupVO);
            }

            // Cleanup security groups
            int numRemoved = _securityGroupDao.removeByAccountId(accountId);
            logger.info("deleteAccount: Deleted {} network groups for account {}", numRemoved, account);

            // Cleanup affinity groups
            int numAGRemoved = _affinityGroupDao.removeByAccountId(accountId);
            logger.info("deleteAccount: Deleted {} affinity groups for account {}", numAGRemoved, account);

            // Delete all the networks
            boolean networksDeleted = true;
            logger.debug("Deleting networks for account {}", account);
            List<NetworkVO> networks = _networkDao.listByOwner(accountId);
            if (networks != null) {
                Collections.sort(networks, new Comparator<>() {
                    @Override
                    public int compare(NetworkVO network1, NetworkVO network2) {
                        if (network1.getGuestType() != network2.getGuestType() && Network.GuestType.Isolated.equals(network2.getGuestType())) {
                            return -1;
                        }
                        return 1;
                    }
                });
                for (NetworkVO network : networks) {
                    if (_networkModel.isPrivateGateway(network.getId())) {
                        continue;
                    }

                    ReservationContext context = new ReservationContextImpl(null, null, getActiveUser(callerUserId), caller);

                    if (!_networkMgr.destroyNetwork(network.getId(), context, false)) {
                        logger.warn("Unable to destroy network {} as a part of account {} cleanup.", network, account);
                        accountCleanupNeeded = true;
                        networksDeleted = false;
                    } else {
                        logger.debug("Network {} successfully deleted as a part of account {} cleanup.", network, account);
                    }
                }
            }

            // Delete all VPCs
            boolean vpcsDeleted = true;
            logger.debug("Deleting vpcs for account {}", account);
            List<? extends Vpc> vpcs = _vpcMgr.getVpcsForAccount(account.getId());
            for (Vpc vpc : vpcs) {

                if (!_vpcMgr.destroyVpc(vpc, caller, callerUserId)) {
                    logger.warn("Unable to destroy VPC {} as a part of account {} cleanup.", vpc, account);
                    accountCleanupNeeded = true;
                    vpcsDeleted = false;
                } else {
                    logger.debug("VPC {} successfully deleted as a part of account {} cleanup.", vpc, account);
                }
            }

            if (networksDeleted && vpcsDeleted) {
                // release ip addresses belonging to the account
                List<? extends IpAddress> ipsToRelease = _ipAddressDao.listByAccount(accountId);
                for (IpAddress ip : ipsToRelease) {
                    logger.debug("Releasing ip {} as a part of account {} cleanup", ip, account);
                    if (!_ipAddrMgr.disassociatePublicIpAddress(ip, callerUserId, caller)) {
                        logger.warn("Failed to release ip address {} as a part of account {} cleanup", ip, account);
                        accountCleanupNeeded = true;
                    }
                }
            }

            // Delete Site 2 Site VPN customer gateway
            logger.debug("Deleting site-to-site VPN customer gateways for account {}", account);
            if (!_vpnMgr.deleteCustomerGatewayByAccount(accountId)) {
                logger.warn("Fail to delete site-to-site VPN customer gateways for account {}", account);
            }

            // Delete autoscale resources if any
            try {
                _autoscaleMgr.cleanUpAutoScaleResources(account);
            } catch (CloudRuntimeException ex) {
                logger.warn("Failed to cleanup AutoScale resources as a part of account {} cleanup due to exception:", account, ex);
                accountCleanupNeeded = true;
            }

            // release account specific Virtual vlans (belong to system Public Network) - only when networks are cleaned
            // up successfully
            if (networksDeleted) {
                if (!_configMgr.releaseAccountSpecificVirtualRanges(account)) {
                    accountCleanupNeeded = true;
                } else {
                    logger.debug("Account specific Virtual IP ranges are successfully released as a part of account {} cleanup.", account);
                }
            }

            // remove dedicated IPv4 subnets
            routedIpv4Manager.removeIpv4SubnetsForZoneByAccountId(accountId);

            // remove dedicated BGP peers
            routedIpv4Manager.removeBgpPeersByAccountId(accountId);

            // release account specific guest vlans
            List<AccountGuestVlanMapVO> maps = _accountGuestVlanMapDao.listAccountGuestVlanMapsByAccount(accountId);
            for (AccountGuestVlanMapVO map : maps) {
                _dataCenterVnetDao.releaseDedicatedGuestVlans(map.getId());
            }
            int vlansReleased = _accountGuestVlanMapDao.removeByAccountId(accountId);
            logger.info("deleteAccount: Released {} dedicated guest vlan ranges from account {}", vlansReleased, account);

            // release account specific acquired portable IP's. Since all the portable IP's must have been already
            // disassociated with VPC/guest network (due to deletion), so just mark portable IP as free.
            List<? extends IpAddress> ipsToRelease = _ipAddressDao.listByAccount(accountId);
            for (IpAddress ip : ipsToRelease) {
                if (ip.isPortable()) {
                    logger.debug("Releasing portable ip {} as a part of account {} cleanup", ip, account);
                    _ipAddrMgr.releasePortableIpAddress(ip.getId());
                }
            }

            // release dedication if any
            List<DedicatedResourceVO> dedicatedResources = _dedicatedDao.listByAccountId(accountId);
            if (dedicatedResources != null && !dedicatedResources.isEmpty()) {
                logger.debug("Releasing dedicated resources for account {}", account);
                for (DedicatedResourceVO dr : dedicatedResources) {
                    if (!_dedicatedDao.remove(dr.getId())) {
                        logger.warn("Fail to release dedicated resources for account {}", account);
                    }
                }
            }

            // Updating and deleting the resourceLimit and resourceCount should be the last step in cleanupAccount
// process.
            // Update resource count for this account and for parent domains.
            List<ResourceCountVO> resourceCounts = _resourceCountDao.listByOwnerId(accountId, ResourceOwnerType.Account);
            for (ResourceCountVO resourceCount : resourceCounts) {
                _resourceLimitMgr.decrementResourceCount(accountId, resourceCount.getType(), resourceCount.getCount());
            }

            // Delete resource count and resource limits entries set for this account (if there are any).
            _resourceCountDao.removeEntriesByOwner(accountId, ResourceOwnerType.Account);
            _resourceLimitDao.removeEntriesByOwner(accountId, ResourceOwnerType.Account);

            // Delete ssh keypairs
            List<SSHKeyPairVO> sshkeypairs = _sshKeyPairDao.listKeyPairs(accountId, account.getDomainId());
            for (SSHKeyPairVO keypair : sshkeypairs) {
                _sshKeyPairDao.remove(keypair.getId());
            }

            // Delete registered UserData
            userDataDao.removeByAccountId(accountId);

            // Delete Webhooks
            deleteWebhooksForAccount(accountId);

            return true;
        } catch (Exception ex) {
            logger.warn("Failed to cleanup account " + account + " due to ", ex);
            accountCleanupNeeded = true;
            return true;
        } finally {
            logger.info("Cleanup for account {} {}", account, accountCleanupNeeded ? "is needed." : "is not needed.");
            if (accountCleanupNeeded) {
                _accountDao.markForCleanup(accountId);
            } else {
                account.setNeedsCleanup(false);
                _accountDao.update(accountId, account);
            }
        }
    }