- Added main script (main.py) for syncing IPs between NSX managers. - Implemented logging setup and YAML configuration loading. - Created NSXClient for interacting with NSX Policy API. - Developed SyncEngine for comparing and syncing IPs. - Added interactive group selection feature. - Implemented data export functionality for JSON and CSV formats. - Created requirements.txt for dependencies. - Added __init__.py for package versioning. - Included error handling and validation for configuration.
5.6 KiB
NSX Security Group IP Sync
Syncs effective IP members from Security Groups on a source NSX manager to static IP entries on matching groups on a target NSX manager. The source is the source of truth for each pair.
Supports NSX 3.x, 4.x, and 9.x via the Policy REST API.
How it works
Source NSX Target NSX
────────────────────────── ──────────────────────────
Security-Group-A Security-Group-A
[VM Criteria: Name contains [VM Criteria: Name contains
win-svr-web] win-svr-web]
Effective IPs (computed): Static IP entries:
10.0.1.10 10.0.1.10 ← already synced
10.0.1.11 ← missing on target (nothing)
(10.0.1.99 removed from source) 10.0.1.99 ← will be removed
The script:
- Fetches effective (computed) IPs from each group on the source.
- Fetches static IP entries from matching groups on the target.
- Diffs: source IPs are the desired state.
- Patches the target group: adds missing IPs, removes extra IPs.
Only the IPAddressExpression entries are touched. Existing VM/Tag/Condition criteria on the target group are left unchanged.
Requirements
- Python 3.10+
pip install -r requirements.txt
Quick start
# 1. Install dependencies
pip install -r requirements.txt
# 2. Copy and edit the config
cp config.example.yaml config.yaml
$EDITOR config.yaml
# 3. Dry-run (WhatIf – no changes written)
python main.py --config config.yaml --whatif
# 4. Live sync
python main.py --config config.yaml
Usage
python main.py [--config FILE] [options]
Connection flags (override config)
| Flag | Description |
|---|---|
--source-host HOST |
Source NSX manager hostname or IP |
--source-user USER |
Source username |
--source-pass PASS |
Source password (prefer env var) |
--source-domain DOMAIN |
Policy domain (default: default) |
--target-host HOST |
Target NSX manager hostname or IP |
--target-user USER |
Target username |
--target-pass PASS |
Target password (prefer env var) |
--target-domain DOMAIN |
Policy domain (default: default) |
--no-verify-ssl |
Skip SSL certificate verification |
Sync flags
| Flag | Description |
|---|---|
--groups NAME [NAME ...] |
Security group names to sync |
--whatif |
Show what would change, write nothing |
--interactive |
Terminal UI for group selection |
--workers N |
Concurrent API threads (default: 4) |
Output / export flags
| Flag | Description |
|---|---|
--export json|csv|both |
Export source/target snapshots + diff |
--export-dir DIR |
Output directory (default: exports/) |
--silent |
Suppress console output (automation) |
--log-file FILE |
Write logs to a file |
--debug |
Verbose API logging |
Credentials via environment variables
Store passwords in environment variables instead of the config file:
export NSX_SOURCE_PASSWORD="your-source-password"
export NSX_TARGET_PASSWORD="your-target-password"
python main.py --config config.yaml
The config file also supports ${ENV_VAR} interpolation:
password: "${NSX_SOURCE_PASSWORD}"
WhatIf / Test mode
python main.py --config config.yaml --whatif
Prints exactly what would be added or removed per group without writing any changes to the target. Use this to validate before a live run.
Export for auditing
# Export JSON and CSV before syncing
python main.py --config config.yaml --export both --whatif
Creates timestamped files in exports/:
| File | Contents |
|---|---|
source_<ts>.json/csv |
Effective IPs per group on source |
target_<ts>.json/csv |
Current static IPs per group on target |
diff_<ts>.json/csv |
Per-IP action: add, remove, or in_sync |
Automation (silent mode)
python main.py --config config.yaml --silent --log-file logs/sync.log
echo "Exit code: $?"
Exit codes:
| Code | Meaning |
|---|---|
0 |
Success – all groups synced (or already in sync) |
1 |
Configuration error – check args/config |
2 |
Runtime error – one or more groups failed; check logs |
Interactive mode
python main.py --config config.yaml --interactive
Pulls the full group list from the source manager and presents a paginated terminal selector. Use row numbers to toggle selection, then press d to confirm.
Project structure
nsx_fed_sync_script/
├── main.py Entry point / CLI
├── config.example.yaml Configuration template
├── requirements.txt
├── .gitignore
├── nsx_sync/
│ ├── nsx_client.py NSX Policy API client (auth, pagination, retries)
│ ├── sync_engine.py Diff + apply logic (concurrent fetch & patch)
│ ├── exporter.py JSON / CSV export helpers
│ └── interactive.py Terminal group-selection UI
├── exports/ Runtime export files (git-ignored)
└── logs/ Runtime log files (git-ignored)
Notes on NSX version compatibility
The script exclusively uses the NSX Policy API (/policy/api/v1/...), which is available and recommended on NSX 3.x, 4.x, and later. The deprecated Manager API (/api/v1/ns-groups/...) is not used.
For NSX 3.x environments where the Policy API may not yet be the primary interface, ensure that Security Groups are managed through the Policy plane (not the legacy Manager plane) for the effective-IP endpoint to return accurate results.