Skip to content

NSX: add native route-based Site-to-Site VPN support - #13766

Open
Dogface2k wants to merge 12 commits into
apache:mainfrom
Dogface2k:feature/nsx-native-site-to-site-vpn
Open

Dogface2k wants to merge 12 commits into
apache:mainfrom
Dogface2k:feature/nsx-native-site-to-site-vpn

Conversation

@Dogface2k

@Dogface2k Dogface2k commented Aug 1, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

The built-in NSX NAT-mode VPC offering advertises Vpn/Nsx, but the existing VPN gateway path cannot provide that service. This PR implements native, route-based Site-to-Site VPN on the VPC’s NSX Tier-1 gateway. The CloudStack virtual router remains outside the IPsec data path.

main, milestone 24.0.

What changes

  • Dispatch the gateway and connection lifecycle through Site2SiteVpnServiceProvider, with defaults for existing providers.

  • Validate or allocate a dedicated public endpoint IP, record the gateway’s original provider and endpoint ownership, and create the Tier-1 IPsec service and local endpoint.

  • Create NSX IKE, tunnel and DPD profiles, a route-based IPsec session, and its virtual tunnel interface.

  • Install a Tier-1 static route and NO_SNAT exemption for each remote CIDR, preserving existing NAT policy and ordering.

  • Support stop, restart/reset, permanent connection deletion, gateway deletion and VPC teardown. Helper-router cleanup restarts preserve the native VPN datapath.

  • Poll NSX session status and update CloudStack connection state. Management-plane query failures leave the last known state unchanged and generate an alert after repeated failures.

  • Expose optional localvtiip, peervtiip and vtiprefixlength response fields, with since = 24.0, in the existing VPN connection details view.

  • Reject Remote Access VPN creation when the configured provider does not support it.

Ownership, compatibility and failure handling

The VPN endpoint is separate from the VPC source-NAT address because the NSX IPsec local endpoint must differ from the Tier-1 uplink address.

The gateway’s provider detail is persisted in the same transaction as the gateway. Connection operations validate the current VPC/account allocation and provider ownership. Gateway cleanup can retain the original provider identity after a partial release, while the IP release path locks and reloads the allocation before changing it. An unavailable recorded provider fails closed.

Auto-acquired endpoint IPs are released only while they still belong to the original VPC/account. Operator-provided IPs retain their allocation after the ownership marker is removed. Reserved endpoints are protected from conflicting IP release, reassignment, source-NAT and network-rule operations.

Older gateway rows retain the existing positive ownership lookup and virtual-router fallback. Positively identified older native gateways have provider identity recorded before cleanup can release their endpoint. Pending legacy virtual-router connections can still be deleted without starting a stopped router.

Native provisioning refuses to adopt an unowned existing deterministic NSX service. Ownership-marked retries may reconcile their service; ambiguous failures retain potentially active endpoints. Sessions remain disabled until their profiles, routes and NAT exemptions are configured. Cleanup is retryable and retains the connection identifiers needed to remove profiles after partial failure.

Tier-1 VPN mutations and teardown share the resource lock. Connection lifecycle operations and polling hold the connection lock across backend operations and state changes. Polling revalidates ownership after locking.

Unsupported algorithms, invalid lifetimes, oversized PSKs and deterministic VTI collisions are rejected. PSKs remain present in the agent wire payload and are excluded from command logging.

Deployment requirement: the Tier-0 must redistribute TIER1_IPSEC_LOCAL_ENDPOINT routes for the dedicated endpoint address to be externally reachable.

Types of changes

  • Breaking change

  • New feature

  • Bug fix

  • Enhancement

  • Cleanup

  • Build/CI

  • Test-only change

Feature/Enhancement Scale

  • Major

  • Minor

Screenshots

The UI change adds three optional fields to the existing VPN connection details renderer and localization path. It adds no new component, layout or action.

How Has This Been Tested?

Current source

Item | Value -- | -- Head | 436429c Reviewed and tested tree | c9cd1b90c877c82f33f7507826c45d2812336254 Target | main, milestone 24.0 Verified merge-base | 7086030 PR scope | 12 commits, 60 changed paths

Earlier live validation was reported on CloudStack 4.23.0.0-SNAPSHOT with NSX 4.2.4. Disposable resources exercised gateway/connection creation, repeated reset, ordered cleanup, endpoint release, active-connection VPC teardown and the unsupported Remote Access VPN guard. Separate FortiGate/NSX traffic validation succeeded in both directions while CloudStack reported the connection as Connected.

These earlier package, live and test results remain historical evidence. They do not establish live NSX validation of the current head.

</details>

### Summary

The built-in NSX NAT-mode VPC offering advertises Vpn/Nsx, but the existing VPN gateway path cannot provide that service. This PR implements native, route-based Site-to-Site VPN on the VPC’s NSX Tier-1 gateway. The CloudStack virtual router remains outside the IPsec data path.

This makes the existing service mapping functional and supersedes the capability-removal approach in the closed #13765. Seeded offerings and the database schema are unchanged.

Related issue: #13764. Target: main, milestone 24.0.

What changes

  • Dispatch the gateway and connection lifecycle through Site2SiteVpnServiceProvider, with defaults for existing providers.
  • Validate or allocate a dedicated public endpoint IP, record the gateway’s original provider and endpoint ownership, and create the Tier-1 IPsec service and local endpoint.
  • Create NSX IKE, tunnel and DPD profiles, a route-based IPsec session, and its virtual tunnel interface.
  • Install a Tier-1 static route and NO_SNAT exemption for each remote CIDR, preserving existing NAT policy and ordering.
  • Support stop, restart/reset, permanent connection deletion, gateway deletion and VPC teardown. Helper-router cleanup restarts preserve the native VPN datapath.
  • Poll NSX session status and update CloudStack connection state. Management-plane query failures leave the last known state unchanged and generate an alert after repeated failures.
  • Expose optional localvtiip, peervtiip and vtiprefixlength response fields, with since = 24.0, in the existing VPN connection details view.
  • Reject Remote Access VPN creation when the configured provider does not support it.

Ownership, compatibility and failure handling

The VPN endpoint is separate from the VPC source-NAT address because the NSX IPsec local endpoint must differ from the Tier-1 uplink address.

The gateway’s provider detail is persisted in the same transaction as the gateway. Connection operations validate the current VPC/account allocation and provider ownership. Gateway cleanup can retain the original provider identity after a partial release, while the IP release path locks and reloads the allocation before changing it. An unavailable recorded provider fails closed.

Auto-acquired endpoint IPs are released only while they still belong to the original VPC/account. Operator-provided IPs retain their allocation after the ownership marker is removed. Reserved endpoints are protected from conflicting IP release, reassignment, source-NAT and network-rule operations.

Older gateway rows retain the existing positive ownership lookup and virtual-router fallback. Positively identified older native gateways have provider identity recorded before cleanup can release their endpoint. Pending legacy virtual-router connections can still be deleted without starting a stopped router.

Native provisioning refuses to adopt an unowned existing deterministic NSX service. Ownership-marked retries may reconcile their service; ambiguous failures retain potentially active endpoints. Sessions remain disabled until their profiles, routes and NAT exemptions are configured. Cleanup is retryable and retains the connection identifiers needed to remove profiles after partial failure.

Tier-1 VPN mutations and teardown share the resource lock. Connection lifecycle operations and polling hold the connection lock across backend operations and state changes. Polling revalidates ownership after locking.

Unsupported algorithms, invalid lifetimes, oversized PSKs and deterministic VTI collisions are rejected. PSKs remain present in the agent wire payload and are excluded from command logging.

Deployment requirement: the Tier-0 must redistribute TIER1_IPSEC_LOCAL_ENDPOINT routes for the dedicated endpoint address to be externally reachable.

Types of changes

  • Breaking change
  • New feature
  • Bug fix
  • Enhancement
  • Cleanup
  • Build/CI
  • Test-only change

Feature/Enhancement Scale

  • Major
  • Minor

Screenshots

The UI change adds three optional fields to the existing VPN connection details renderer and localization path. It adds no new component, layout or action.

How Has This Been Tested?

Current source

Item Value
Head 436429c468e8937d99c2f2910cc0411c27773d18
Reviewed and tested tree c9cd1b90c877c82f33f7507826c45d2812336254
Target main, milestone 24.0
Verified merge-base 70860301eb14cb0dc6af1c8546de9997e515d166
PR scope 12 commits, 60 changed paths

The current head merges upstream 70860301 into the previous PR head, [6eee8284](https://github.com/apache/cloudstack/commit/6eee8284e4e3e22a5ba2e5077c43c4b42eb6ef7d). The ownership, reservation and validation fixes in that commit remain included.

The only manual conflict resolution was the import block in NetworkServiceImplTest.java. Both branches’ required imports and added test methods are retained. The entire NSX plugin subtree is byte-identical to 6eee8284. The complete merge was checked for preservation of both parents’ changes, and git diff --check is clean.

As of 12 November 2026, 12:03 UTC, upstream main is 6982fac34a6ebcf7219455de9ae01fa0f4bd5d27, three commits beyond the incorporated base. Those account/LDAP changes were reviewed for interaction with this PR. A local merge computation completes without conflicts; the only overlapping changed file is the English locale file, with separate translation keys. That combined tree was not separately built.

Local validation on the current tree

The completed run finished on 12 November 2026 at 00:50:59 UTC, using Linux, Temurin 17.0.21+9 and Maven 3.9.16.

Validation Result
Selected affected Maven reactor 34 modules — BUILD SUCCESS
Surefire totals 28 suites; 862 reported cases: 860 passed, 0 failures, 0 errors, 2 skips
NSX tests, included above 272 passed across 11 suites
Site2SiteVpnManagerImplTest 96 passed
NetworkServiceImplTest 140 passed
VPN lifecycle API command tests 8 passed
Upstream integration cases, included above 22 network-command tests and 27 VLAN-trunk migration tests passed
Checkstyle 27 reports, zero violations
Source identity Before/after checks match the published tree, with no tracked source changes

The two existing skips are FirewallManagerTest.testApplyRules and testApplyFWRules, both requiring a configured database.

This was an incremental selected reactor using cached dependencies/classes from the same source and fresh test/style reports. The runner preloaded ByteBuddy agent 1.15.11 because dynamic attachment was unavailable, used temporary proxy settings, and disabled the optional Develocity extension. Project source, POMs and workflow configuration were unchanged, and no extra test skips were introduced.

Selected reactor command
mvn -B -ntp \
  -Ddevelocity.enabled=false \
  -Ddevelocity.scan.disabled=true \
  -Ddevelocity.cache.remote.enabled=false \
  -Dnoredist -pl plugins/network-elements/nsx -am \
  '-Dtest=ApiResponseHelperTest,ConfigurationManagerTest,NetworkServiceImplTest,NetworkModelImplTest,NetworkModelTest,IpAddressManagerTest,RemoteAccessVpnManagerImplTest,Site2SiteVpnManagerImplTest,VpcManagerImplTest,VpcVirtualRouterElementTest,VpnConnectionLifecycleCmdTest,Nsx*Test,PagedFetcherTest,FirewallManagerTest,FirewallManagerImplTest,VlanTrunkMigrationHelperTest,AssociateNetworkToNicCmdTest,ChangeNicPrimaryNetworkCmdTest,DisassociateNetworkFromNicCmdTest' \
  -Dsurefire.failIfNoSpecifiedTests=false test

Automatic CI on the current head

At 12 November 2026, 12:03 UTC, all 27 checks associated with 436429c have completed successfully. These include the Maven build and coverage jobs, simulator tests, UI build, RAT, pre-commit, CodeQL and both Codecov checks.

The UI job log confirms a successful production build, no lint errors, and 200 tests passed across 13 suites. Its checked-out merge commit has the same tree as the PR head.

The coverage build succeeded. The separate SonarQube upload step was skipped by the existing fork condition; no completed SonarQube analysis gate is claimed.

[Codecov](#13766 (comment)) reports 73.34% patch coverage, with 598 changed lines uncovered, and 21.00% project coverage, an increase of 0.28 percentage points against 70860301. Both configured coverage checks pass. The earlier incomplete-upload failure has cleared.

Failure and compatibility coverage

The reviewed tests exercise:

  • Endpoint validation and reservation, retained allocations, operator-provided addresses and later IP reuse.
  • Persisted provider identity, offering changes, unavailable providers and partial cleanup.
  • Validation before persistence, including customer-gateway updates through the public API.
  • Route and NO_SNAT payload values, existing NAT/Tier-1 field preservation and rule ordering.
  • Session enable/disable, rollback, stale route cleanup and profile-deletion retries.
  • Ownership changes while waiting for locks, migration/gateway exclusion and polling under the connection lock.
  • Legacy virtual-router selection and Pending deletion, helper-router restart and VPC teardown.
  • Actual agent wire/log serialization, including PSK delivery and log exclusion.
  • Status-query failure handling and bounded deletion retries with interruption handling.

The follow-up source audit covered the complete 60-path PR diff and affected callers. It found no proven blocking correctness defect.

Validation limits

Current-head live NSX realization/traffic, physical database rollback/crash injection and cross-management-server fault injection have not been rerun. Unit and mocked backend/DAO tests establish the exercised decisions, payloads and ordering; historical live results below are not presented as execution on this head.

Review feedback

All eight inline review threads were resolved when checked on 12 November.

Review point Current disposition
[Ownership-marker cleanup](#13766 (comment)) IP unassignment already clears details. The redundant second removal is gone; locked allocation checks protect later allocations, and saved provider identity supports cleanup retries.
[Shared ownership key](#13766 (comment)) The NSX IP-marker key remains one definition within the NSX package. The separate provider-neutral gateway detail is defined on the shared provider SPI.
[Controller exception context](#13766 (comment)) Existing ERROR logs retain operation context. Raw backend details are not forwarded to the public API without a sanitization contract.
[Missing annotations](#13766 (comment)) All seven VPN methods declared by NsxService have @Override in NsxServiceImpl.
Historical validation — results remain attributed to their original commits

Previous head: 6eee828 — 10 November 2026

The [November 10 update](#13766 (comment)) records the consolidated ownership/reservation fix and its validation on tree f080cb8ec6eaf54b0520a09cdd14dba20b3eac57:

  • Windows; Temurin 17.0.20.1; Maven 3.9.16.
  • Selected 34-module reactor: BUILD SUCCESS; 24 suites; 749 reported cases, with 747 passed, 0 failures/errors and 2 existing database-dependent skips.
  • 272 NSX tests passed within that total.
  • 27 Checkstyle reports with zero violations.
  • 16 deliberate fault controls recorded as detecting the intended faults.
  • Earlier UI validation of 193 tests across 10 suites was reused for that head.

Those runtime, mutation-test, source-identity and UI-reuse statements belong to 6eee8284. The merge retains the fixes and tests, but the historical fault-control runs are not claimed to have been repeated on 436429c.

The two simulator failures previously reported on 8e982497 remain historical; their root cause was not established. They are not current-head failures. The current head’s checks are reported separately above.

Earlier head: a70061fe

Earlier validation on a70061fe, with OpenJDK 17.0.19 and Maven 3.9.12, recorded:

Validation Historical result
Affected clean reactor 34 modules; 8,486 reported tests; 0 failures/errors; 11 skips
Full developer/systemvm/simulator/noredist reactor 165 modules; BUILD SUCCESS; 13,909 reported tests; 0 failures/errors; 13 skips
Quality/JaCoCo reactor BUILD SUCCESS; 13,909 tests in each normal/instrumented report set; 0 failures/errors; 13 skips; 24.73% aggregate line coverage
UI Production build and lint passed; 175 tests across 4 suites passed
Apache RAT 11,111 resources; zero unapproved/unknown licenses
Pre-commit Standard all-files and manual-stage hooks passed
Packaging el8, el9, el10, Debian and SUSE 15 passed, recorded as Blue Orangutan SL-JID 18806

Earlier live validation was conducted on CloudStack 4.23.0.0-SNAPSHOT with NSX 4.2.4. Disposable resources exercised gateway/connection creation, repeated reset, ordered cleanup, endpoint release, active-connection VPC teardown and the unsupported Remote Access VPN guard. Separate FortiGate/NSX traffic validation succeeded in both directions while CloudStack reported the connection as Connected.

@Dogface2k

Copy link
Copy Markdown
Collaborator Author

Follow-up validation and lifecycle hardening

Commit 98cd4ed6f4 adds the lifecycle hardening identified by live NSX validation.

  • The existing marked-for-deletion retry is now shared by route-based session creation and the complete static-route/NO_SNAT programming operation. It remains bounded at 24 attempts with a 15-second interval.
  • NsxApiClientTest.testAddVpnConnectionRoutesRetriesMarkedForDeletion forces the NSX marked-for-deletion response during route creation and verifies the deterministic route is retried before NO_SNAT programming continues.
  • State changes use a read-modify-write of the existing route-based session, preserving the mandatory tunnel_interfaces field implicated by the pre-deploy failure.
  • VPN connection, gateway, customer-gateway, and VPC lifecycle operations use VPC-scoped synchronization and deterministic cleanup.

Live validation on 4.22.1.0 with NSX 4.2.4 used an intentionally unreachable RFC 5737 test peer. The connection reached Disconnected; the first reset reproduced the marked-for-deletion 431, the same reset succeeded after the purge window, and connection/customer-gateway/VPN-gateway/VPC deletion completed with the dedicated test IP released. No production connection was modified, and no tunnel-traffic success is claimed from this test peer.

The supplied pre-deploy tunnel_interfaces error is a distinct historical failure; the current read-modify-write path passed the stop half of the live reset test. The local checkout has no JDK/Maven executable, so the new focused test must be run by repository CI; git diff --check is clean.

@Dogface2k
Dogface2k marked this pull request as ready for review August 2, 2026 05:20
@Dogface2k

Dogface2k commented Aug 2, 2026 •

Copy link
Copy Markdown
Collaborator Author

Additional live data-plane evidence

Operator-side testing between 192.168.46.5 and 10.35.0.1 succeeded in both directions over the documented FortiGate/NSX path. The original direction returned 2/2 ICMP replies with 0% loss and 17.45 ms average latency; traceroute showed 6x.xxx.xxx.xxx (FortiGate) followed by 10.35.0.1.

CloudStack connection 8 remained Connected before and after. This is positive bidirectional endpoint-reachability evidence through the VPN path.

@codecov

codecov Bot commented Aug 3, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 73.33928% with 598 lines in your changes missing coverage. Please review.
✅ Project coverage is 21.00%. Comparing base (7086030) to head (436429c).

Files with missing lines Patch % Lines
...va/org/apache/cloudstack/service/NsxApiClient.java 72.58% 184 Missing and 40 partials ⚠️
...java/org/apache/cloudstack/service/NsxElement.java 74.85% 52 Missing and 33 partials ⚠️
...com/cloud/network/vpn/Site2SiteVpnManagerImpl.java 75.07% 46 Missing and 32 partials ⚠️
.../org/apache/cloudstack/service/NsxServiceImpl.java 64.40% 48 Missing and 15 partials ⚠️
...va/org/apache/cloudstack/resource/NsxResource.java 84.26% 26 Missing and 2 partials ⚠️
.../cloud/configuration/ConfigurationManagerImpl.java 40.00% 15 Missing and 6 partials ⚠️
...d/network/element/Site2SiteVpnServiceProvider.java 6.25% 14 Missing and 1 partial ⚠️
.../cloud/network/vpn/RemoteAccessVpnManagerImpl.java 62.85% 7 Missing and 6 partials ⚠️
...org/apache/cloudstack/utils/NsxVpnCryptoUtils.java 86.20% 5 Missing and 7 partials ⚠️
...k/api/response/Site2SiteVpnConnectionResponse.java 50.00% 9 Missing ⚠️
... and 14 more
Additional details and impacted files
@@             Coverage Diff              @@
##               main   #13766      +/-   ##
============================================
+ Coverage     20.72%   21.00%   +0.28%     
- Complexity    20768    21163     +395     
============================================
  Files          6049     6059      +10     
  Lines        547749   549833    +2084     
  Branches      73171    73450     +279     
============================================
+ Hits         113500   115472    +1972     
+ Misses       420943   420811     -132     
- Partials      13306    13550     +244     
Flag Coverage Δ
uitests 3.86% <ø> (ø)
unittests 22.45% <73.33%> (+0.29%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds native, route-based Site-to-Site VPN support for NSX NAT-mode VPCs by terminating IPsec on the NSX Tier-1 gateway (keeping the CloudStack virtual router out of the data path) and by making the existing Vpn/Nsx service mapping functional via provider-dispatched lifecycle handling.

Changes:

  • Extends the Site-to-Site VPN provider SPI to support provider-owned gateway IP acquisition/release and persisted ownership-based provider selection.
  • Implements NSX VPN gateway/connection lifecycle (gateway creation, route/NAT exemptions, session state updates, and teardown) plus a scheduled management-server poller mapping NSX session status back to CloudStack state.
  • Adds extensive unit tests across api, server, and NSX plugin modules to cover lifecycle hardening, rollback/ambiguity handling, and sensitive-data logging behavior.

Reviewed changes

Copilot reviewed 32 out of 32 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
server/src/test/java/com/cloud/network/vpn/Site2SiteVpnManagerImplTest.java Expands S2S manager tests for provider selection/ownership, locking, and lifecycle error handling.
server/src/test/java/com/cloud/network/vpn/RemoteAccessVpnManagerImplTest.java Adds tests ensuring Remote Access VPN provider mapping is validated before persistence/start.
server/src/main/java/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java Routes S2S lifecycle through the owning provider, supports provider-owned gateway IPs, and hardens connection locking/state transitions.
server/src/main/java/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java Selects a single mapped Remote Access VPN provider and fails fast when none is available.
plugins/network-elements/nsx/src/test/java/org/apache/cloudstack/utils/NsxVpnCryptoUtilsTest.java Adds unit tests for CloudStack-to-NSX VPN crypto policy mapping/validation.
plugins/network-elements/nsx/src/test/java/org/apache/cloudstack/utils/NsxHelperTest.java Adds tests for deterministic VTI /30 address derivation.
plugins/network-elements/nsx/src/test/java/org/apache/cloudstack/utils/NsxControllerUtilsTest.java Tests failed-answer behavior for “throwing” vs “returning” NSX command helpers.
plugins/network-elements/nsx/src/test/java/org/apache/cloudstack/service/NsxServiceImplTest.java Adds tests for status polling behavior and VPN gateway failure result propagation.
plugins/network-elements/nsx/src/test/java/org/apache/cloudstack/service/NsxElementTest.java Adds tests for NSX gateway IP acquisition/release semantics and S2S VPN lifecycle dispatch.
plugins/network-elements/nsx/src/test/java/org/apache/cloudstack/service/NsxApiClientTest.java Adds extensive tests for NSX Policy object ordering, rollback, retries, and cleanup behavior.
plugins/network-elements/nsx/src/test/java/org/apache/cloudstack/resource/NsxResourceTest.java Adds tests validating agent-side command dispatch, rollback semantics, and PSK log redaction on the wire/loggers.
plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/utils/NsxVpnCryptoUtils.java Implements crypto parameter mapping/validation for NSX constraints.
plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/utils/NsxHelper.java Adds deterministic VTI address allocation helper for NSX route-based VPN sessions.
plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/utils/NsxControllerUtils.java Adds VPN naming helpers and splits “throw on failure” vs “return failed answer” command sending.
plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxServiceImpl.java Adds NSX VPN lifecycle command dispatch and a scheduled poller to sync NSX session state to CloudStack.
plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java Implements Site2SiteVpnServiceProvider for NSX, including gateway IP ownership markers and NSX-side lifecycle operations.
plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxResource.java Adds agent handling for NSX VPN commands and introduces per-Tier1 locking for VPN mutations/teardown ordering.
plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/NsxAnswer.java Extends NSX answer payload with structured “endpoint may be in use” failure signaling.
plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/UpdateNsxVpnConnectionStateCommand.java New agent command for enabling/disabling an NSX VPN session.
plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/GetNsxVpnSessionStatusCommand.java New agent command for fetching NSX session status.
plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/DeleteNsxVpnGatewayCommand.java New agent command for deleting an NSX VPN service on Tier-1.
plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/DeleteNsxVpnConnectionCommand.java New agent command for deleting an NSX VPN session.
plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/CreateNsxVpnGatewayCommand.java New agent command for creating an NSX VPN service/local endpoint on Tier-1.
plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/CreateNsxVpnConnectionCommand.java New agent command for creating a route-based VPN session, VTI, routes, and NAT exemptions (with PSK log redaction).
api/src/test/java/org/apache/cloudstack/api/command/user/vpn/VpnConnectionLifecycleCmdTest.java Adds tests ensuring VPN reset/delete commands synchronize on VPC.
api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ResetVpnConnectionCmd.java Synchronizes reset jobs on VPC to serialize Tier-1/VPN mutations.
api/src/main/java/org/apache/cloudstack/api/command/user/vpn/DeleteVpnGatewayCmd.java Synchronizes gateway deletion jobs on VPC.
api/src/main/java/org/apache/cloudstack/api/command/user/vpn/DeleteVpnConnectionCmd.java Synchronizes connection deletion jobs on VPC.
api/src/main/java/com/cloud/network/nsx/NsxVpnGatewayResult.java New API DTO for structured NSX gateway creation outcomes.
api/src/main/java/com/cloud/network/nsx/NsxService.java Extends NSX service interface with VPN gateway/connection lifecycle operations.
api/src/main/java/com/cloud/network/element/Site2SiteVpnServiceProvider.java Extends provider SPI with gateway IP acquisition/release, ownership, and customer-gateway validation hooks.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@DaanHoogland

Copy link
Copy Markdown
Contributor

@Dogface2k , want to address the co-pilot comments ?

@Dogface2k

Copy link
Copy Markdown
Collaborator Author

@DaanHoogland Addressed both Copilot findings in 4cea137: the poller now uses a state-filtered DAO query, and its executor is restart-safe across start/stop/start. Added focused DAO, lifecycle, and status-mapping tests; the complete affected suites pass (engine/schema 385/385 and NSX plugin 202/202), with checkstyle clean. Both review threads are now resolved.

@DaanHoogland
DaanHoogland requested a review from Copilot August 3, 2026 07:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 35 out of 35 changed files in this pull request and generated 1 comment.

Suppressed comments (5)

server/src/main/java/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java:1

  • Connection deletion/reset now depends on getVpnGatewayForConnection(), which throws when the gateway row is missing. That makes delete/cleanup non-idempotent: a partially-deleted environment (missing gateway/VPC) will prevent connection teardown and can strand the DB row/lock-based workflows. Consider making the delete path tolerant to a missing gateway (e.g., in stopVpnConnectionLocked when deleting==true, skip provider-side stop/delete if the gateway is absent, proceed with DB removal; or make getVpnGatewayForConnection optionally return null and handle it in delete/stop flows).
    server/src/main/java/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java:1
  • Connection deletion/reset now depends on getVpnGatewayForConnection(), which throws when the gateway row is missing. That makes delete/cleanup non-idempotent: a partially-deleted environment (missing gateway/VPC) will prevent connection teardown and can strand the DB row/lock-based workflows. Consider making the delete path tolerant to a missing gateway (e.g., in stopVpnConnectionLocked when deleting==true, skip provider-side stop/delete if the gateway is absent, proceed with DB removal; or make getVpnGatewayForConnection optionally return null and handle it in delete/stop flows).
    server/src/main/java/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java:1
  • These validation methods were widened from private to package-visible to support testing. This increases the callable surface area of internal validation logic and makes it easier for other production classes in the package to start depending on them. If possible, keep them private and test via the public entrypoints; alternatively, clearly document they are package-visible only for tests (and keep tests in the same package) to reduce the risk of accidental reuse.
    server/src/main/java/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java:1
  • These validation methods were widened from private to package-visible to support testing. This increases the callable surface area of internal validation logic and makes it easier for other production classes in the package to start depending on them. If possible, keep them private and test via the public entrypoints; alternatively, clearly document they are package-visible only for tests (and keep tests in the same package) to reduce the risk of accidental reuse.
    plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/utils/NsxControllerUtils.java:58
  • When NSX returns a failed (but non-null) NsxAnswer, the log and exception discard useful troubleshooting context (command type, zone, and the answer details/error). Include cmd.getClass()/cmd.toString(), zoneId, and answer.getDetails() (and any structured flags like endpointMayBeInUse/objectExists) in the log message and/or exception text so operators can diagnose failures without enabling deeper debug logging.
        NsxAnswer answer = sendNsxCommandForResult(cmd, zoneId);
        if (!answer.getResult()) {
            logger.error("NSX API Command failed");
            throw new InvalidParameterValueException("Failed API call to NSX controller");
        }

@Dogface2k

Dogface2k commented Aug 4, 2026 •

Copy link
Copy Markdown
Collaborator Author

Live end-to-end validation completed against the deployed 4.23.0.0-SNAPSHOT build with NSX 4.2.4, using disposable account-scoped resources.\n\n- Created an NSX NAT-mode VPC, tier, dedicated VPN gateway endpoint and route-based connection.\n- Reset the connection immediately after creation twice. Both reset jobs completed successfully in about 16 seconds, directly exercising the marked-for-deletion retry and route-based session update paths.\n- Deleted the connection, customer gateway and VPN gateway; the dedicated endpoint address was released.\n- Repeated teardown with an active VPN connection and deleted the VPC. The Tier-1 VPN service, session, gateway record, connection record and endpoint address were all absent afterward.\n- Confirmed the NSX Remote Access VPN capability guard rejects the unsupported provider before persisting a remote-access VPN record.\n- Existing bidirectional routed-tunnel traffic evidence remains unchanged; no production VPN connection was modified during this disposable lifecycle run.\n\nThis completes the live control-plane lifecycle validation for the scope of this PR. Connection/tunnel already has E2E

@DaanHoogland

Copy link
Copy Markdown
Contributor

@blueorangutan package

@blueorangutan

Copy link
Copy Markdown

@DaanHoogland a [SL] Jenkins job has been kicked to build packages. It will be bundled with no SystemVM templates. I'll keep you posted as I make progress.

@blueorangutan

Copy link
Copy Markdown

Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 18766

@blueorangutan

Copy link
Copy Markdown

Packaging result [SF]: ✖️ el8 ✖️ el9 ✖️ debian ✖️ suse15. SL-JID 18773

@DaanHoogland

Copy link
Copy Markdown
Contributor

@Dogface2k fyi

09:45:43 [INFO] -------------------------------------------------------------
09:45:52 [ERROR] COMPILATION ERROR : 
09:45:52 [INFO] -------------------------------------------------------------
09:45:52 [ERROR] /jenkins/workspace/acs-deb-pkg-builder/server/src/test/java/com/cloud/network/vpn/Site2SiteVpnManagerImplTest.java:[362,8] error: cannot find symbol
09:45:52   symbol:   class ArgumentCaptor
09:45:52   location: class Site2SiteVpnManagerImplTest
09:45:52 [ERROR] /jenkins/workspace/acs-deb-pkg-builder/server/src/test/java/com/cloud/network/vpn/Site2SiteVpnManagerImplTest.java:[362,62] error: cannot find symbol
09:45:52   symbol:   variable ArgumentCaptor
09:45:52   location: class Site2SiteVpnManagerImplTest
09:45:52 [INFO] 2 errors 

(the github action output can be inconvenient)

The added system-VM source-NAT test asserted behavior that the production legacy fallback does not implement, and the test also failed compilation due to a missing ArgumentCaptor import. Restore the previously validated test tree without changing production code.
@Dogface2k

Copy link
Copy Markdown
Collaborator Author

Reviewing one final time.

@Dogface2k
Dogface2k marked this pull request as draft August 6, 2026 15:40
@Dogface2k
Dogface2k marked this pull request as ready for review August 14, 2026 19:05
@DaanHoogland DaanHoogland added this to the 4.24.0 milestone Aug 17, 2026
@DaanHoogland

Copy link
Copy Markdown
Contributor

@blueorangutan package

@blueorangutan

Copy link
Copy Markdown

@DaanHoogland a [SL] Jenkins job has been kicked to build packages. It will be bundled with no SystemVM templates. I'll keep you posted as I make progress.

@blueorangutan

Copy link
Copy Markdown

Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 18888

@DaanHoogland

Copy link
Copy Markdown
Contributor

@blueorangutan test

@blueorangutan

Copy link
Copy Markdown

@DaanHoogland a [SL] Trillian-Jenkins test job (ol8 mgmt + kvm-ol8) has been kicked to run smoke tests

@vishesh92

Copy link
Copy Markdown
Member

@blueorangutan test

@blueorangutan

Copy link
Copy Markdown

@vishesh92 a [SL] Trillian-Jenkins test job (ol8 mgmt + kvm-ol8) has been kicked to run smoke tests

@blueorangutan

Copy link
Copy Markdown

[SF] Trillian test result (tid-16918)
Environment: kvm-ol8 (x2), zone: Advanced Networking with Mgmt server ol8
Total time taken: 59242 seconds
Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr13766-t16918-kvm-ol8.zip
Smoke tests completed. 156 look OK, 0 have errors, 0 did not run
Only failed and skipped tests results shown below:

Test Result Time (s) Test File

@github-actions

Copy link
Copy Markdown

This pull request has merge conflicts. Dear author, please fix the conflicts and sync your branch with the base branch.

Preserve Pending through provider deletion so the legacy default does not require a running router, while NSX still receives permanent cleanup. Add real stopped-router regression and failure/dispatch controls, align VTI API metadata with 24.0, and retain remote-access VPN tests from both merge parents.
@DaanHoogland

Copy link
Copy Markdown
Contributor

@Pearl1594 @nvazquez , can you have a look please?

I am not sure if we can test this reliably , given the infra requirements for this.

@nvazquez nvazquez left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code LGTM - thanks @Dogface2k. Unfortunately, I do not have the infra anymore to test it, however changes look good to me

@nvazquez
nvazquez requested a balanced review from Copilot November 9, 2026 17:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Copilot review overview

4 open issues
1 resolved since last review

Review effort: Lite

Keep gateway provider identity through partial cleanup and recheck the IP allocation before release, connection operations and polling. Preserve the prior lifecycle and reserved-endpoint fixes.

Strengthen validation, provider-selection and route/NAT payload tests; exercise customer-gateway updates through the public API and control retry waits in tests.
@Dogface2k
Dogface2k force-pushed the feature/nsx-native-site-to-site-vpn branch from 8e98249 to 6eee828 Compare November 10, 2026 22:21
@Dogface2k

Copy link
Copy Markdown
Collaborator Author

Consolidated the latest two commits into 6eee828, retaining the lifecycle, endpoint-reservation and firewall fixes.

The gateway now retains its original provider through partial cleanup; release and polling recheck the current IP allocation. The misleading validation fixtures and missing route/NAT payload assertions are corrected.

Two fresh independent reviews passed the complete final tree and accounted for every removal. On that exact source: 747 tests passed, 0 failures/errors, 2 existing DB skips; all 16 deliberate fault controls failed as intended.

The four review points were independently rechecked. New-head CI is running; the earlier two simulator failures remain unexplained. Live NSX testing was not rerun.

@github-actions

Copy link
Copy Markdown

This pull request has merge conflicts. Dear author, please fix the conflicts and sync your branch with the base branch.

Retain both the VPN reservation test imports and upstream multi-VLAN test imports in NetworkServiceImplTest.

Preserve the existing native VPN changes while syncing with main.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Ready

Development

Successfully merging this pull request may close these issues.

6 participants