Dogface2k commented on code in PR #13766:
URL: https://github.com/apache/cloudstack/pull/13766#discussion_r3702074220
##########
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:
Addressed in 4cea137c21. The poller now queries
Site2SiteVpnConnectionDao.listByStates(Pending, Connecting, Connected,
Disconnected), so terminal rows are filtered by SQL instead of loading the
complete table. NSX ownership remains checked from the persisted IP detail in
NsxServiceImpl; keeping that plugin-specific marker out of the shared engine
DAO avoids coupling the schema layer to the NSX plugin. Added DAO criteria
coverage and an exact poller-query test. Full affected suites pass:
engine/schema 385/385 and NSX plugin 202/202, with checkstyle clean.
##########
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:
Addressed in 4cea137c21. Executor creation now belongs to synchronized
start(); stop() atomically clears and shuts down the current executor, and a
subsequent same-JVM start creates and schedules a fresh one. A scheduling
failure also shuts down the newly created executor before propagating. Added a
focused start -> stop -> start test that verifies the first executor is shut
down and the replacement is scheduled and later shut down. Full affected suites
pass: engine/schema 385/385 and NSX plugin 202/202, with checkstyle clean.
--
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]