Copilot commented on code in PR #13766:
URL: https://github.com/apache/cloudstack/pull/13766#discussion_r3701578546
##########
plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxServiceImpl.java:
##########
@@ -196,6 +282,173 @@ public boolean deleteFirewallRules(Network network,
List<NsxNetworkRule> netRule
return result.getResult();
}
+ public NsxVpnGatewayResult createVpnGateway(Vpc vpc, String
localEndpointIp) {
+ CreateNsxVpnGatewayCommand createNsxVpnGatewayCommand = new
CreateNsxVpnGatewayCommand(vpc.getDomainId(),
+ vpc.getAccountId(), vpc.getZoneId(), vpc.getId(),
vpc.getName(), localEndpointIp);
+ NsxAnswer result =
nsxControllerUtils.sendNsxCommandForResult(createNsxVpnGatewayCommand,
vpc.getZoneId());
+ return new NsxVpnGatewayResult(result.getResult(),
result.isEndpointMayBeInUse());
+ }
+
+ public boolean deleteVpnGateway(Vpc vpc) {
+ DeleteNsxVpnGatewayCommand deleteNsxVpnGatewayCommand = new
DeleteNsxVpnGatewayCommand(vpc.getDomainId(),
+ vpc.getAccountId(), vpc.getZoneId(), vpc.getId(),
vpc.getName());
+ NsxAnswer result =
nsxControllerUtils.sendNsxCommand(deleteNsxVpnGatewayCommand, vpc.getZoneId());
+ return result.getResult();
+ }
+
+ public boolean createVpnConnection(Vpc vpc, String connectionUuid, String
peerAddress, String psk,
+ String ikePolicy, String espPolicy,
Long ikeLifetime, Long espLifetime,
+ boolean dpdEnabled, String ikeVersion,
boolean passive, List<String> peerCidrs,
+ String vtiLocalIp, String vtiPeerIp,
int vtiPrefixLength, String localEndpointIp) {
+ CreateNsxVpnConnectionCommand createNsxVpnConnectionCommand = new
CreateNsxVpnConnectionCommand(vpc.getDomainId(),
+ vpc.getAccountId(), vpc.getZoneId(), vpc.getId(),
vpc.getName(), connectionUuid, peerAddress, psk,
+ ikePolicy, espPolicy, ikeLifetime, espLifetime, dpdEnabled,
ikeVersion, passive, peerCidrs,
+ vtiLocalIp, vtiPeerIp, vtiPrefixLength, vpc.getCidr(),
localEndpointIp);
+ NsxAnswer result =
nsxControllerUtils.sendNsxCommand(createNsxVpnConnectionCommand,
vpc.getZoneId());
+ return result.getResult();
+ }
+
+ public boolean deleteVpnConnection(Vpc vpc, String connectionUuid) {
+ DeleteNsxVpnConnectionCommand deleteNsxVpnConnectionCommand = new
DeleteNsxVpnConnectionCommand(vpc.getDomainId(),
+ vpc.getAccountId(), vpc.getZoneId(), vpc.getId(),
vpc.getName(), connectionUuid);
+ NsxAnswer result =
nsxControllerUtils.sendNsxCommand(deleteNsxVpnConnectionCommand,
vpc.getZoneId());
+ return result.getResult();
+ }
+
+ public boolean updateVpnConnectionState(Vpc vpc, String connectionUuid,
boolean enabled) {
+ UpdateNsxVpnConnectionStateCommand command = new
UpdateNsxVpnConnectionStateCommand(vpc.getDomainId(),
+ vpc.getAccountId(), vpc.getZoneId(), vpc.getId(),
vpc.getName(), connectionUuid, enabled);
+ NsxAnswer result = nsxControllerUtils.sendNsxCommand(command,
vpc.getZoneId());
+ return result.getResult();
+ }
+
+ public String getVpnConnectionStatus(Vpc vpc, String connectionUuid) {
+ GetNsxVpnSessionStatusCommand getNsxVpnSessionStatusCommand = new
GetNsxVpnSessionStatusCommand(vpc.getDomainId(),
+ vpc.getAccountId(), vpc.getZoneId(), vpc.getId(),
vpc.getName(), connectionUuid);
+ NsxAnswer result =
nsxControllerUtils.sendNsxCommand(getNsxVpnSessionStatusCommand,
vpc.getZoneId());
+ return result.getDetails();
+ }
+
+ /**
+ * Every management server runs this poller over VPN connections whose
gateway has persisted
+ * NSX ownership; duplicate polling in a multi-server setup is tolerated,
as state transitions
+ * are serialized by the row lock in transitionVpnConnectionState
+ */
+ protected class VpnStatusPollTask extends ManagedContextRunnable {
+ @Override
+ protected void runInContext() {
+ try {
+ Set<Long> polledConnectionIds = new HashSet<>();
+ List<Site2SiteVpnConnectionVO> connections =
site2SiteVpnConnectionDao.listAll();
+ for (Site2SiteVpnConnectionVO connection : connections) {
Review Comment:
VpnStatusPollTask loads all Site2SiteVpnConnection rows
(site2SiteVpnConnectionDao.listAll()) every poll interval, then filters in
memory. On large installations this makes the poll interval proportional to
total connections (including non-NSX/terminal states). Consider adding a DAO
query that pre-filters to the polled states and (ideally) NSX-owned gateways,
so each poll touches only relevant rows.
##########
plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxServiceImpl.java:
##########
@@ -16,49 +16,135 @@
// under the License.
package org.apache.cloudstack.service;
+import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
+import javax.naming.ConfigurationException;
import org.apache.cloudstack.NsxAnswer;
import
org.apache.cloudstack.agent.api.CreateNsxDistributedFirewallRulesCommand;
import org.apache.cloudstack.agent.api.CreateNsxLoadBalancerRuleCommand;
import org.apache.cloudstack.agent.api.CreateNsxPortForwardRuleCommand;
import org.apache.cloudstack.agent.api.CreateNsxStaticNatCommand;
import org.apache.cloudstack.agent.api.CreateNsxTier1GatewayCommand;
+import org.apache.cloudstack.agent.api.CreateNsxVpnConnectionCommand;
+import org.apache.cloudstack.agent.api.CreateNsxVpnGatewayCommand;
import org.apache.cloudstack.agent.api.CreateOrUpdateNsxTier1NatRuleCommand;
import
org.apache.cloudstack.agent.api.DeleteNsxDistributedFirewallRulesCommand;
import org.apache.cloudstack.agent.api.DeleteNsxLoadBalancerRuleCommand;
import org.apache.cloudstack.agent.api.DeleteNsxNatRuleCommand;
import org.apache.cloudstack.agent.api.DeleteNsxSegmentCommand;
import org.apache.cloudstack.agent.api.DeleteNsxTier1GatewayCommand;
+import org.apache.cloudstack.agent.api.DeleteNsxVpnConnectionCommand;
+import org.apache.cloudstack.agent.api.DeleteNsxVpnGatewayCommand;
+import org.apache.cloudstack.agent.api.GetNsxVpnSessionStatusCommand;
+import org.apache.cloudstack.agent.api.UpdateNsxVpnConnectionStateCommand;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
+import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.cloudstack.resource.NsxNetworkRule;
+import org.apache.cloudstack.resourcedetail.dao.UserIpAddressDetailsDao;
import org.apache.cloudstack.utils.NsxControllerUtils;
import org.apache.cloudstack.utils.NsxHelper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import com.cloud.alert.AlertManager;
import com.cloud.network.IpAddress;
import com.cloud.network.Network;
import com.cloud.network.SDNProviderNetworkRule;
+import com.cloud.network.Site2SiteVpnConnection;
import com.cloud.network.dao.NetworkVO;
+import com.cloud.network.dao.Site2SiteVpnConnectionDao;
+import com.cloud.network.dao.Site2SiteVpnConnectionVO;
+import com.cloud.network.dao.Site2SiteVpnGatewayDao;
+import com.cloud.network.dao.Site2SiteVpnGatewayVO;
import com.cloud.network.nsx.NsxService;
+import com.cloud.network.nsx.NsxVpnGatewayResult;
import com.cloud.network.vpc.Vpc;
import com.cloud.network.vpc.VpcVO;
import com.cloud.network.vpc.dao.VpcDao;
+import com.cloud.utils.component.ManagerBase;
+import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.exception.CloudRuntimeException;
-public class NsxServiceImpl implements NsxService, Configurable {
+public class NsxServiceImpl extends ManagerBase implements NsxService,
Configurable {
+
+ public static final ConfigKey<Integer> NSX_VPN_STATUS_POLL_INTERVAL = new
ConfigKey<>("Advanced", Integer.class,
+ "nsx.vpn.status.poll.interval", "60",
+ "Interval (in seconds) between two NSX Site-to-Site VPN connection
status polls; requires a management server restart",
+ false, ConfigKey.Scope.Global);
+
+ protected static final String VPN_SESSION_STATUS_UP = "UP";
+ protected static final String VPN_SESSION_STATUS_DOWN = "DOWN";
+ protected static final String VPN_SESSION_STATUS_DEGRADED = "DEGRADED";
+ protected static final String VPN_SESSION_STATUS_NOT_FOUND = "NOT_FOUND";
+ protected static final int VPN_STATUS_POLL_FAILURE_THRESHOLD = 3;
+ protected static final int VPN_STATUS_POLL_MIN_INTERVAL = 10;
+ protected static final int VPN_STATUS_POLL_DEFAULT_INTERVAL = 60;
+
+ private static final List<Site2SiteVpnConnection.State> VPN_POLLED_STATES
= List.of(
+ Site2SiteVpnConnection.State.Pending,
Site2SiteVpnConnection.State.Connecting, Site2SiteVpnConnection.State.Connected,
+ Site2SiteVpnConnection.State.Disconnected);
+
@Inject
NsxControllerUtils nsxControllerUtils;
@Inject
VpcDao vpcDao;
+ @Inject
+ Site2SiteVpnConnectionDao site2SiteVpnConnectionDao;
+ @Inject
+ Site2SiteVpnGatewayDao site2SiteVpnGatewayDao;
+ @Inject
+ UserIpAddressDetailsDao userIpAddressDetailsDao;
+ @Inject
+ AlertManager alertManager;
protected Logger logger = LogManager.getLogger(getClass());
+ private ScheduledExecutorService vpnStatusPollExecutor;
+ private final Map<Long, Integer> vpnStatusPollFailures = new
ConcurrentHashMap<>();
+
+ @Override
+ public boolean configure(String name, Map<String, Object> params) throws
ConfigurationException {
+ super.configure(name, params);
+ vpnStatusPollExecutor = Executors.newSingleThreadScheduledExecutor(new
NamedThreadFactory("Nsx-Vpn-Status-Poll"));
+ return true;
+ }
+
+ @Override
+ public boolean start() {
+ super.start();
+ if (vpnStatusPollExecutor == null) {
+ throw new IllegalStateException("NSX VPN status poller was not
configured");
+ }
+ Integer configuredInterval = NSX_VPN_STATUS_POLL_INTERVAL.value();
+ int pollInterval = Objects.isNull(configuredInterval) ?
VPN_STATUS_POLL_DEFAULT_INTERVAL : configuredInterval;
+ if (pollInterval < VPN_STATUS_POLL_MIN_INTERVAL) {
+ logger.warn("The configured value {} of {} is below the minimum of
{} seconds, using the default of {} seconds",
+ configuredInterval, NSX_VPN_STATUS_POLL_INTERVAL.key(),
VPN_STATUS_POLL_MIN_INTERVAL, VPN_STATUS_POLL_DEFAULT_INTERVAL);
+ pollInterval = VPN_STATUS_POLL_DEFAULT_INTERVAL;
+ }
+ vpnStatusPollExecutor.scheduleWithFixedDelay(new VpnStatusPollTask(),
pollInterval, pollInterval, TimeUnit.SECONDS);
+ return true;
+ }
+
+ @Override
+ public boolean stop() {
+ if (Objects.nonNull(vpnStatusPollExecutor)) {
+ vpnStatusPollExecutor.shutdownNow();
+ }
+ return super.stop();
+ }
Review Comment:
NsxServiceImpl.stop() shuts down vpnStatusPollExecutor but start() never
recreates it. If this manager is stopped and then started again in the same JVM
(e.g., component restart), scheduleWithFixedDelay will run on a shut-down
executor (RejectedExecutionException) or fail the configured check, leaving VPN
status polling disabled.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]