Skip to content

assaffeuerstein/CiscoMDS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Cisco MDS SAN Automation Framework

Author: Assaf Feuerstein

A comprehensive automation framework for managing Cisco MDS SAN (Storage Area Network) switches using Ansible, Python, and Jenkins CI/CD pipelines.

🎯 Overview

This project provides enterprise-grade automation for Cisco MDS Fibre Channel switches, enabling:

  • Device Alias Management: Automated creation and removal of device aliases (human-readable names for WWPNs)
  • Zone Configuration: Automated zone and zoneset management for controlling storage access
  • Interface Management: Enable/disable FC interfaces during host provisioning and decommissioning
  • Migration Tools: Convert Brocade SAN configurations to Cisco MDS format
  • Maintenance Scripts: Automated CFS lock clearing and zone commit operations

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        CI/CD Pipeline                            β”‚
β”‚                    (Jenkins/GitHub Actions)                      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”‚
                                β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      Python Automation                           β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚   β”‚ Device Aliasβ”‚  β”‚    Zone     β”‚  β”‚    Maintenance      β”‚    β”‚
β”‚   β”‚  Scripts    β”‚  β”‚   Scripts   β”‚  β”‚      Scripts        β”‚    β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                          β”‚                                       β”‚
β”‚                          β–Ό                                       β”‚
β”‚              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                            β”‚
β”‚              β”‚   NX-API Module     β”‚                            β”‚
β”‚              β”‚ (REST API Client)   β”‚                            β”‚
β”‚              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”‚
                                β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Ansible Playbooks                             β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚
β”‚   β”‚ Device Alias Config β”‚  β”‚    Zone/Zoneset Config      β”‚     β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”‚
                                β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     Cisco MDS Fabric                             β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
β”‚   β”‚   Fabric A    β”‚                    β”‚   Fabric B    β”‚        β”‚
β”‚   β”‚  (Redundancy) β”‚                    β”‚  (Redundancy) β”‚        β”‚
β”‚   β”‚               β”‚                    β”‚               β”‚        β”‚
β”‚   β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚                    β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚        β”‚
β”‚   β”‚ β”‚Core Switchβ”‚ β”‚                    β”‚ β”‚Core Switchβ”‚ β”‚        β”‚
β”‚   β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚                    β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚        β”‚
β”‚   β”‚      β”‚        β”‚                    β”‚      β”‚        β”‚        β”‚
β”‚   β”‚ β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”   β”‚                    β”‚ β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”   β”‚        β”‚
β”‚   β”‚ β”‚Edge NPV β”‚   β”‚                    β”‚ β”‚Edge NPV β”‚   β”‚        β”‚
β”‚   β”‚ β”‚Switches β”‚   β”‚                    β”‚ β”‚Switches β”‚   β”‚        β”‚
β”‚   β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚                    β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚        β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“ Project Structure

CiscoMDS/
β”œβ”€β”€ ansible/                      # Ansible playbooks and inventory
β”‚   β”œβ”€β”€ group_vars/              # Ansible variables
β”‚   β”‚   β”œβ”€β”€ all.yml.example      # Global variables template
β”‚   β”‚   └── nxos.yml.example     # NX-OS connection settings
β”‚   β”œβ”€β”€ templates/               # Jinja2 templates
β”‚   β”œβ”€β”€ hosts.ini.example        # Inventory template
β”‚   β”œβ”€β”€ device-alias-fabric-a.yml.example
β”‚   β”œβ”€β”€ zone-fabric-a.yml.example
β”‚   └── change_interface_state.yml
β”‚
β”œβ”€β”€ python/                      # Python automation scripts
β”‚   β”œβ”€β”€ cisco/                   # NX-API client module
β”‚   β”‚   β”œβ”€β”€ __init__.py
β”‚   β”‚   └── nxapi.py            # REST API client
β”‚   β”œβ”€β”€ add_device_alias.py     # Add device aliases
β”‚   β”œβ”€β”€ add_zone.py             # Add zones
β”‚   β”œβ”€β”€ remove_device_alias.py  # Remove device aliases
β”‚   β”œβ”€β”€ remove_zone.py          # Remove zones
β”‚   β”œβ”€β”€ cisco_mds_maintenance.py # Maintenance tasks
β”‚   β”œβ”€β”€ brocade_migration.py    # Brocade to Cisco migration
β”‚   β”œβ”€β”€ find_duplicates.py      # Find duplicate PWWNs
β”‚   └── requirements.txt        # Python dependencies
β”‚
β”œβ”€β”€ pipeline/                    # Jenkins pipeline definitions
β”‚   β”œβ”€β”€ Jenkinsfile.DeviceAlias
β”‚   β”œβ”€β”€ Jenkinsfile.Zone
β”‚   └── Jenkinsfile.InterfaceState
β”‚
β”œβ”€β”€ switch_configs/              # Switch configuration templates
β”‚   β”œβ”€β”€ core_switch_initial.txt
β”‚   β”œβ”€β”€ edge_switch_npv.txt
β”‚   └── enable_nxapi.txt
β”‚
β”œβ”€β”€ scripts/                     # Shell utility scripts
β”‚   β”œβ”€β”€ fix_device_alias.sh     # Rename device aliases
β”‚   └── backup_config.sh        # Backup switch configs
β”‚
β”œβ”€β”€ configs/                     # Configuration backups (gitignored)
└── docs/                        # Additional documentation

πŸš€ Getting Started

Prerequisites

  • Python 3.8+
  • Ansible 2.10+ with cisco.nxos collection
  • Cisco MDS switches with NX-API enabled
  • (Optional) Jenkins for CI/CD pipelines

Installation

  1. Clone the repository

    git clone https://github.com/assaffeuerstein/CiscoMDS.git
    cd CiscoMDS
  2. Set up Python environment

    python3 -m venv .env
    source .env/bin/activate
    pip install -r python/requirements.txt
  3. Install Ansible collections

    ansible-galaxy collection install cisco.nxos
    ansible-galaxy collection install ansible.netcommon
  4. Configure inventory

    cp ansible/hosts.ini.example ansible/hosts.ini
    # Edit hosts.ini with your switch IPs
  5. Configure credentials

    cp ansible/group_vars/nxos.yml.example ansible/group_vars/nxos.yml
    # Edit nxos.yml and use ansible-vault for encryption
    ansible-vault encrypt ansible/group_vars/nxos.yml

Enable NX-API on Switches

configure terminal
feature nxapi
no nxapi http port 8080
nxapi https port 8443
exit
copy running-config startup-config

πŸ“– Usage

Python Scripts

Maintenance Tasks

# Check and fix CFS locks and pending zone changes
python3 python/cisco_mds_maintenance.py \
    --ip 192.168.1.10 \
    --username admin \
    --password secret \
    --vsan 2

# Dry run (check only)
python3 python/cisco_mds_maintenance.py \
    --ip 192.168.1.10 \
    --username admin \
    --password secret \
    --dry-run

Device Alias Management

# Add a device alias
python3 python/add_device_alias.py \
    --device-alias esxi_prod_host_01 \
    --pwwns 10:00:00:00:00:00:00:01 \
    --sw-username admin \
    --sw-password secret

# Remove a device alias
python3 python/remove_device_alias.py \
    --fabric 1 \
    --device-alias esxi_prod_host_01

Zone Management

# Add a zone
python3 python/add_zone.py \
    --zone storage_array_01_esxi_prod_host_01 \
    --members storage_array_01,esxi_prod_host_01

# Remove a zone
python3 python/remove_zone.py \
    --fabric 1 \
    --zone storage_array_01_esxi_prod_host_01

Brocade Migration

# Convert Brocade config to Cisco Ansible playbook
python3 python/brocade_migration.py \
    --source 192.168.2.1 \
    --context 1 \
    --vsan 2 \
    --zoneset ZS_Fabric_A \
    --fabric 1 \
    --username admin \
    --password secret \
    --aliases --zones

Ansible Playbooks

# Apply device alias configuration
ansible-playbook -i ansible/hosts.ini \
    ansible/device-alias-fabric-a.yml \
    --vault-password-file vault_pass.txt

# Apply zone configuration
ansible-playbook -i ansible/hosts.ini \
    ansible/zone-fabric-a.yml \
    --vault-password-file vault_pass.txt

# Change interface state
ansible-playbook -i ansible/switches.ini \
    ansible/change_interface_state.yml \
    -e "interface_on_first_switch=fc1/5" \
    -e "interface_on_second_switch=fc1/5" \
    -e "enabled=true"

Jenkins Pipelines

The project includes three Jenkins pipelines:

  1. Device Alias Pipeline (Jenkinsfile.DeviceAlias)

    • Parameters: operation, hostname, wwn1, wwn2, dc
    • Automates adding/removing device aliases
  2. Zone Pipeline (Jenkinsfile.Zone)

    • Parameters: operation, hostname, storage_array, dc
    • Automates adding/removing zones
  3. Interface State Pipeline (Jenkinsfile.InterfaceState)

    • Parameters: action, serial, switch IPs, interfaces
    • Enables/disables FC interfaces

πŸ”§ Configuration

Ansible Vault

Store sensitive credentials using Ansible Vault:

# Create encrypted credentials file
ansible-vault create ansible/group_vars/nxos.yml

# Encrypt a single string
ansible-vault encrypt_string 'mypassword' --name 'ansible_password'

# Edit encrypted file
ansible-vault edit ansible/group_vars/nxos.yml

Environment Variables

The scripts support these environment variables:

Variable Description
CISCO_USER Default username for switch authentication
CISCO_PASSWORD Default password for switch authentication
ANSIBLE_VAULT_PASSWORD_FILE Path to vault password file

🏷️ Naming Conventions

Device Aliases

  • Use underscores, not hyphens: esxi_prod_host_01
  • Include environment: esxi_prod_, k8s_stage_
  • Storage arrays: storage_array_01_ct0_fc0

Zones

  • Format: <storage_array>_<hostname>
  • Example: storage_array_01_esxi_prod_host_01

Zonesets

  • Fabric A: ZS_Fabric_A
  • Fabric B: ZS_Fabric_B

πŸ”’ Security Considerations

  1. Credential Management

    • Use Ansible Vault for all credentials
    • Never commit passwords or vault files to Git
    • Use Jenkins credentials store for CI/CD
  2. Network Security

    • NX-API uses HTTPS by default (port 8443)
    • Disable HTTP access on switches
    • Use dedicated management network
  3. Access Control

    • Limit switch access to automation service accounts
    • Use RBAC on Jenkins for pipeline execution
    • Audit all configuration changes via Git

🀝 Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit changes (git commit -m 'Add amazing feature')
  4. Push to branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

πŸ“ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™ Acknowledgments

  • Cisco for the NX-API and Ansible modules
  • The Ansible community for the network automation tools
  • All contributors to this project

πŸ“¬ Contact

Author: Assaf Feuerstein

For questions or support, please open an issue on GitHub.


Note: This is a template project. Configure the example files with your environment-specific settings before use.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors