@Override @DB public RemoteAccessVpnVO startRemoteAccessVpn(long vpnId, boolean openFirewall) throws ResourceUnavailableException { Account caller = UserContext.current().getCaller(); RemoteAccessVpnVO vpn = _remoteAccessVpnDao.findById(vpnId); if (vpn == null) { throw new InvalidParameterValueException("Unable to find your vpn: " + vpnId); } _accountMgr.checkAccess(caller, null, true, vpn); Network network = _networkMgr.getNetwork(vpn.getNetworkId()); boolean started = false; try { boolean firewallOpened = true; if (openFirewall) { firewallOpened = _firewallMgr.applyIngressFirewallRules(vpn.getServerAddressId(), caller); } if (firewallOpened) { for (RemoteAccessVPNServiceProvider element : _vpnServiceProviders) { if (element.startVpn(network, vpn)) { started = true; break; } } } return vpn; } finally { if (started) { Transaction txn = Transaction.currentTxn(); txn.start(); vpn.setState(RemoteAccessVpn.State.Running); _remoteAccessVpnDao.update(vpn.getServerAddressId(), vpn); // Start billing of existing VPN users in ADD and Active state List<VpnUserVO> vpnUsers = _vpnUsersDao.listByAccount(vpn.getAccountId()); for (VpnUserVO user : vpnUsers) { if (user.getState() != VpnUser.State.Revoke) { UsageEventUtils.publishUsageEvent( EventTypes.EVENT_VPN_USER_ADD, user.getAccountId(), 0, user.getId(), user.getUsername(), user.getClass().getName(), user.getUuid()); } } txn.commit(); } } }
@Override @ActionEvent( eventType = EventTypes.EVENT_REMOTE_ACCESS_VPN_UPDATE, eventDescription = "updating remote access vpn", async = true) public RemoteAccessVpn updateRemoteAccessVpn(long id, String customId, Boolean forDisplay) { final RemoteAccessVpnVO vpn = _remoteAccessVpnDao.findById(id); if (vpn == null) { throw new InvalidParameterValueException("Can't find remote access vpn by id " + id); } _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, vpn); if (customId != null) { vpn.setUuid(customId); } if (forDisplay != null) { vpn.setDisplay(forDisplay); } _remoteAccessVpnDao.update(vpn.getId(), vpn); return _remoteAccessVpnDao.findById(id); }
@Override @DB @ActionEvent( eventType = EventTypes.EVENT_REMOTE_ACCESS_VPN_DESTROY, eventDescription = "removing remote access vpn", async = true) public boolean destroyRemoteAccessVpnForIp(long ipId, Account caller, final boolean forceCleanup) throws ResourceUnavailableException { final RemoteAccessVpnVO vpn = _remoteAccessVpnDao.findByPublicIpAddress(ipId); if (vpn == null) { s_logger.debug("there are no Remote access vpns for public ip address id=" + ipId); return true; } _accountMgr.checkAccess(caller, AccessType.OperateEntry, true, vpn); RemoteAccessVpn.State prevState = vpn.getState(); vpn.setState(RemoteAccessVpn.State.Removed); _remoteAccessVpnDao.update(vpn.getId(), vpn); boolean success = false; try { for (RemoteAccessVPNServiceProvider element : _vpnServiceProviders) { if (element.stopVpn(vpn)) { success = true; break; } } } catch (ResourceUnavailableException ex) { vpn.setState(prevState); _remoteAccessVpnDao.update(vpn.getId(), vpn); s_logger.debug( "Failed to stop the vpn " + vpn.getId() + " , so reverted state to " + RemoteAccessVpn.State.Running); success = false; } finally { if (success || forceCleanup) { // Cleanup corresponding ports final List<? extends FirewallRule> vpnFwRules = _rulesDao.listByIpAndPurpose(ipId, Purpose.Vpn); boolean applyFirewall = false; final List<FirewallRuleVO> fwRules = new ArrayList<FirewallRuleVO>(); // if related firewall rule is created for the first vpn port, it would be created for the 2 // other ports as well, so need to cleanup the backend if (vpnFwRules.size() != 0 && _rulesDao.findByRelatedId(vpnFwRules.get(0).getId()) != null) { applyFirewall = true; } if (applyFirewall) { Transaction.execute( new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { for (FirewallRule vpnFwRule : vpnFwRules) { // don't apply on the backend yet; send all 3 rules in a banch _firewallMgr.revokeRelatedFirewallRule(vpnFwRule.getId(), false); fwRules.add(_rulesDao.findByRelatedId(vpnFwRule.getId())); } s_logger.debug( "Marked " + fwRules.size() + " firewall rules as Revoked as a part of disable remote access vpn"); } }); // now apply vpn rules on the backend s_logger.debug( "Reapplying firewall rules for ip id=" + ipId + " as a part of disable remote access vpn"); success = _firewallMgr.applyIngressFirewallRules(ipId, caller); } if (success || forceCleanup) { try { Transaction.execute( new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { _remoteAccessVpnDao.remove(vpn.getId()); // Stop billing of VPN users when VPN is removed. VPN_User_ADD events will be // generated when VPN is created again List<VpnUserVO> vpnUsers = _vpnUsersDao.listByAccount(vpn.getAccountId()); for (VpnUserVO user : vpnUsers) { // VPN_USER_REMOVE event is already generated for users in Revoke state if (user.getState() != VpnUser.State.Revoke) { UsageEventUtils.publishUsageEvent( EventTypes.EVENT_VPN_USER_REMOVE, user.getAccountId(), 0, user.getId(), user.getUsername(), user.getClass().getName(), user.getUuid()); } } if (vpnFwRules != null) { for (FirewallRule vpnFwRule : vpnFwRules) { _rulesDao.remove(vpnFwRule.getId()); s_logger.debug( "Successfully removed firewall rule with ip id=" + vpnFwRule.getSourceIpAddressId() + " and port " + vpnFwRule.getSourcePortStart().intValue() + " as a part of vpn cleanup"); } } } }); } catch (Exception ex) { s_logger.warn("Unable to release the three vpn ports from the firewall rules", ex); } } } } return success; }
@Override @DB public void destroyRemoteAccessVpn(long ipId, Account caller) throws ResourceUnavailableException { RemoteAccessVpnVO vpn = _remoteAccessVpnDao.findById(ipId); if (vpn == null) { s_logger.debug("vpn id=" + ipId + " does not exists "); return; } _accountMgr.checkAccess(caller, null, true, vpn); Network network = _networkMgr.getNetwork(vpn.getNetworkId()); vpn.setState(RemoteAccessVpn.State.Removed); _remoteAccessVpnDao.update(vpn.getServerAddressId(), vpn); boolean success = false; try { for (RemoteAccessVPNServiceProvider element : _vpnServiceProviders) { if (element.stopVpn(network, vpn)) { success = true; break; } } } finally { if (success) { // Cleanup corresponding ports List<? extends FirewallRule> vpnFwRules = _rulesDao.listByIpAndPurpose(ipId, Purpose.Vpn); Transaction txn = Transaction.currentTxn(); boolean applyFirewall = false; List<FirewallRuleVO> fwRules = new ArrayList<FirewallRuleVO>(); // if related firewall rule is created for the first vpn port, it would be created for the 2 // other ports as well, so need to cleanup the backend if (_rulesDao.findByRelatedId(vpnFwRules.get(0).getId()) != null) { applyFirewall = true; } if (applyFirewall) { txn.start(); for (FirewallRule vpnFwRule : vpnFwRules) { // don't apply on the backend yet; send all 3 rules in a banch _firewallMgr.revokeRelatedFirewallRule(vpnFwRule.getId(), false); fwRules.add(_rulesDao.findByRelatedId(vpnFwRule.getId())); } s_logger.debug( "Marked " + fwRules.size() + " firewall rules as Revoked as a part of disable remote access vpn"); txn.commit(); // now apply vpn rules on the backend s_logger.debug( "Reapplying firewall rules for ip id=" + ipId + " as a part of disable remote access vpn"); success = _firewallMgr.applyIngressFirewallRules(ipId, caller); } if (success) { try { txn.start(); _remoteAccessVpnDao.remove(ipId); // Stop billing of VPN users when VPN is removed. VPN_User_ADD events will be generated // when VPN is created again List<VpnUserVO> vpnUsers = _vpnUsersDao.listByAccount(vpn.getAccountId()); for (VpnUserVO user : vpnUsers) { // VPN_USER_REMOVE event is already generated for users in Revoke state if (user.getState() != VpnUser.State.Revoke) { UsageEventUtils.publishUsageEvent( EventTypes.EVENT_VPN_USER_REMOVE, user.getAccountId(), 0, user.getId(), user.getUsername(), user.getClass().getName(), user.getUuid()); } } if (vpnFwRules != null) { for (FirewallRule vpnFwRule : vpnFwRules) { _rulesDao.remove(vpnFwRule.getId()); s_logger.debug( "Successfully removed firewall rule with ip id=" + vpnFwRule.getSourceIpAddressId() + " and port " + vpnFwRule.getSourcePortStart() + " as a part of vpn cleanup"); } } txn.commit(); } catch (Exception ex) { txn.rollback(); s_logger.warn("Unable to release the three vpn ports from the firewall rules", ex); } } } } }