Quellcode durchsuchen

Add support for deleting VLANs as well.

Joe Clarke vor 4 Jahren
Ursprung
Commit
805a615f0d

+ 22 - 0
automation/cleu-ansible-n9k/delete-vlan-playbook.yml

@@ -0,0 +1,22 @@
+---
+- name: Configure network switches
+  hosts: NXOS
+  gather_facts: false
+  connection: network_cli
+  roles:
+      - nxos-vlan
+      - write-mem
+
+- name: Configure UCS Clusters
+  hosts:
+    - UCS
+    - HX
+  gather_facts: false
+  roles:
+      - ucs-vlan
+
+- name: Configure ESXi hosts through vCenter
+  hosts: vCenter
+  gather_facts: false
+  roles:
+      - vmware-vlan

+ 121 - 0
automation/cleu-ansible-n9k/delete_vlan.py

@@ -0,0 +1,121 @@
+#!/usr/bin/env python3
+
+import argparse
+import sys
+import re
+import subprocess
+import os
+import tempfile
+from yaml import load, dump
+try:
+    from yaml import CLoader as Loader, CDumper as Dumper
+except ImportError:
+    from yaml import Loader, Dumper
+
+
+def main():
+    parser = argparse.ArgumentParser(
+        prog=sys.argv[0], description='Delete a VLAN from the network')
+    parser.add_argument('--vlan-name', '-n', metavar='<VLAN_NAME>',
+                        help='Name of the VLAN to add', required=True)
+    parser.add_argument('--vm-vlan-name', metavar='<VM_VLAN_NAME>',
+                        help='Name of the VLAN port group in VMware ', required=True)
+    parser.add_argument('--vlan-id', '-i', metavar='<VLAN_ID>',
+                        help='ID of the VLAN to add', type=int, required=True)
+    parser.add_argument(
+        '--is-stretched', help='VLAN is stretched between both data centres (default: False)', action='store_true')
+    parser.add_argument('--interface', action='append', metavar='<INTF>',
+                        help='Interface to enable for VLAN (can be specified more than once)')
+    parser.add_argument(
+        '--generate-iflist', help='Automatically generate a list of allowed interfaces for VLAN (default: False)', action='store_true')
+    parser.add_argument('--vmware-cluster', action='append', metavar='<CLUSTER>',
+                        help='VMware cluster to configure for VLAN (can be specified more than once) (default: all clusters are configured)')
+    parser.add_argument('--username', '-u', metavar='<USERNAME>',
+                        help='Username to use to connect to the N9Ks', required=True)
+    parser.add_argument('--limit', '-L', metavar='<HOSTS_OR_GROUP_NAMES>',
+                        help='Comma-separated list of hosts or host group names (from inventory/hosts) on which to restrict operations')
+    parser.add_argument('--tags', metavar='<TAG_LIST>',
+                        help='Comma-separated list of task tags to execute')
+    parser.add_argument(
+        '--list-tags', help='List available task tags', action='store_true')
+    parser.add_argument(
+        '--check-only', help='Only check syntax and attempt to predict changes', action='store_true')
+    args = parser.parse_args()
+
+    if args.vlan_id < 1 or args.vlan_id > 3967:
+        print('ERROR: VLAN ID must be between 1 and 3967')
+        sys.exit(1)
+
+    is_stretched = False
+    generate_iflist = False
+
+    if args.is_stretched:
+        is_stretched = True
+
+    if args.generate_iflist and args.interface and len(args.interface) > 0:
+        print('ERROR: Cannot specify both an interface list and --generate-iflist.')
+        sys.exit(1)
+
+    if args.generate_iflist:
+        generate_iflist = True
+
+    os.environ['ANSIBLE_FORCE_COLOR'] = 'True'
+    os.environ['ANSIBLE_HOST_KEY_CHECKING'] = 'False'
+    os.environ['ANSIBLE_PERSISTENT_COMMAND_TIMEOUT'] = '300'
+
+    if 'AD_PASSWORD' not in os.environ:
+        print(
+            'ERROR: AD_PASSWORD must be set in the environment first (used for vCenter and UCS).')
+        sys.exit(1)
+
+    os.environ['VMWARE_USER'] = args.username
+    os.environ['VMWARE_PASSWORD'] = os.environ['VMWARE_PASSWORD']
+
+    cred_file = tempfile.NamedTemporaryFile(mode='w', delete=False)
+    vars = {
+        'ucs_mgr_username': args.username,
+        'ucs_mgr_password': os.environ['AD_PASSWORD']
+    }
+    dump(vars, cred_file, Dumper=Dumper)
+    cred_file.close()
+
+    command = ['ansible-playbook', '-i', 'inventory/hosts',
+               '-u', args.username, '-k', '-e',
+               'vlan_name={}'.format(
+                   args.vlan_name), '-e', 'vlan_id={}'.format(args.vlan_id), '-e', 'vm_vlan_name=\'{}\''.format(vm_vlan_name),
+               '-e', 'ansible_python_interpreter={}'.format(sys.executable),
+               '-e', '@{}'.format(cred_file.name),
+               '-e', 'delete_vlan=True',
+               '-e', 'is_stretched={}'.format(is_stretched),
+               '-e', 'generate_iflist={}'.format(generate_iflist),
+               'add-vlan-playbook.yml']
+    if args.interface and len(args.interface) > 0:
+        command += ['-e',
+                    '{{"iflist": [{}]}}'.format(','.join(args.interface))]
+    if args.generate_iflist:
+        command += ['-e', '{{"iflist": []}}']
+    if args.vmware_cluster and len(args.vmware_cluster) > 0:
+        command += ['-e',
+                    '{{"vm_clusters": [{}]}}'.format(','.join(args.vmware_cluster))]
+    if args.limit:
+        command += ['--limit', args.limit]
+    if args.tags:
+        command += ['--tags', args.tags]
+    if args.list_tags:
+        command += ['--list-tags']
+    if args.check_only:
+        command += ['-C']
+    p = subprocess.Popen(command, stdout=subprocess.PIPE,
+                         stderr=subprocess.STDOUT)
+    for c in iter(lambda: p.stdout.read(1), b''):
+        sys.stdout.write(c.decode('utf-8'))
+        sys.stdout.flush()
+
+    p.poll()
+
+    if os.path.isfile(cred_file.name):
+        os.remove(cred_file.name)
+
+
+if __name__ == '__main__':
+    main()

+ 61 - 20
automation/cleu-ansible-n9k/roles/nxos-vlan/tasks/main.yml

@@ -5,6 +5,7 @@
         - vlan_id: "{{ vlan_id }}"
           enabled: True
           name: "{{ vlan_name }}"
+  when: delete_vlan is not defined or delete_vlan is False
   tags:
     - nxos
     - vlan
@@ -21,6 +22,7 @@
     - vlan
     - nxos-vlan
     - allow-vlan
+    - remove-vlan
 
 - name: Generate list of interfaces (non-stretched)
   set_fact: iflist="{{ iflist }} + [{{ item.key }}]"
@@ -31,6 +33,7 @@
     - vlan
     - nxos-vlan
     - allow-vlan
+    - remove-vlan
 
 - name: Associate interfaces to VLAN
   nxos_config:
@@ -38,7 +41,7 @@
           - switchport trunk allowed vlan add {{ vlan_id }}
       parents: interface {{ item }}
   with_items: "{{ iflist }}"
-  when: iflist is defined
+  when: iflist is defined and (delete_vlan is not defined or delete_vlan is False)
   tags:
     - nxos
     - vlan
@@ -53,7 +56,7 @@
           mode: layer3
           mtu: "{{ svi_mtu }}"
           description: "{{ svi_descr }}"
-  when: svi_mtu is defined and svi_descr is defined
+  when: svi_mtu is defined and svi_descr is defined and (delete_vlan is not defined or delete_vlan is False)
   tags:
     - nxos
     - vlan
@@ -62,7 +65,7 @@
 
 - name: Set per-DC v4 IDF ID
   set_fact: v4_idf_id={{ idf_id }}
-  when: is_stretched is False and build_v4 is True
+  when: is_stretched is False and build_v4 is True and (delete_vlan is not defined or delete_vlan is False)
   tags:
       - nxos
       - vlan
@@ -72,7 +75,7 @@
 
 - name: Set stretched v4 IDF ID
   set_fact: v4_idf_id={{ stretched_idf_id }}
-  when: is_stretched is True and build_v4 is True
+  when: is_stretched is True and build_v4 is True and (delete_vlan is not defined or delete_vlan is False)
   tags:
       - nxos
       - vlan
@@ -82,7 +85,7 @@
 
 - name: Construct SVI IPv4 address
   set_fact: svi_v4_prefix={{ base_major_net }}.{{ vlan_id }}.{{ v4_idf_id }} svi_subnet_len="24"
-  when: build_v4 is True
+  when: build_v4 is True and (delete_vlan is not defined or delete_vlan is False)
   tags:
       - nxos
       - vlan
@@ -96,7 +99,7 @@
         - name: Vlan{{ vlan_id }}
           ipv4:
             - address: "{{ svi_v4_prefix }}.{{ core_svi_v4_suffix }}/{{ svi_subnet_len }}"
-  when: svi_v4_prefix is defined
+  when: svi_v4_prefix is defined and (delete_vlan is not defined or delete_vlan is False)
   tags:
     - nxos
     - vlan
@@ -106,7 +109,7 @@
 
 - name: Set per-DC v6 IDF ID
   set_fact: v6_idf_id="{{ '%0x' % idf_id|int }}"
-  when: is_stretched is False and build_v6 is True
+  when: is_stretched is False and build_v6 is True and (delete_vlan is not defined or delete_vlan is False)
   tags:
     - nxos
     - vlan
@@ -116,7 +119,7 @@
 
 - name: Set stretched v6 IDF ID
   set_fact: v6_idf_id="{{ '%0x' % stretched_idf_id|int }}"
-  when: is_stretched is True and build_v6 is True
+  when: is_stretched is True and build_v6 is True and (delete_vlan is not defined or delete_vlan is False)
   tags:
     - nxos
     - vlan
@@ -126,7 +129,7 @@
 
 - name: Construct SVI v6 address
   set_fact: svi_v6_network="{{ base_v6_prefix }}:{{ '%0x' % vlan_id|int }}{{ v6_idf_id }}::"
-  when: build_v6 is True
+  when: build_v6 is True and (delete_vlan is not defined or delete_vlan is False)
   tags:
     - nxos
     - vlan
@@ -140,7 +143,7 @@
         - name: Vlan{{ vlan_id }}
           ipv6:
             - address: "{{ svi_v6_network }}{{ core_svi_v6_suffix }}/64"
-  when: svi_v6_network is defined
+  when: svi_v6_network is defined and (delete_vlan is not defined or delete_vlan is False)
   tags:
     - nxos
     - vlan
@@ -153,7 +156,7 @@
       lines:
           - ipv6 address use-link-local-only
       parents: interface Vlan{{ vlan_id }}
-  when: svi_v6_link_local is defined
+  when: svi_v6_link_local is defined and (delete_vlan is not defined or delete_vlan is False)
   tags:
     - nxos
     - vlan
@@ -166,7 +169,7 @@
       area: 0.0.0.0
       ospf: "{{ ospf_pid }}"
       interface: Vlan{{ vlan_id }}
-  when: svi_v4_prefix is defined
+  when: svi_v4_prefix is defined and (delete_vlan is not defined or delete_vlan is False)
   tags:
     - nxos
     - vlan
@@ -179,7 +182,7 @@
       lines:
           - ip ospf network {{ ospf_type }}
       parents: interface Vlan{{ vlan_id }}
-  when: svi_v4_prefix is defined
+  when: svi_v4_prefix is defined and (delete_vlan is not defined or delete_vlan is False)
   tags:
     - nxos
     - vlan
@@ -192,7 +195,7 @@
       lines:
           - no ip ospf passive-interface
       parents: interface Vlan{{ vlan_id }}
-  when: svi_v4_prefix is defined and not passive_interface is defined
+  when: svi_v4_prefix is defined and not passive_interface is defined and (delete_vlan is not defined or delete_vlan is False)
   tags:
     - nxos
     - vlan
@@ -206,7 +209,7 @@
           - ipv6 router ospfv3 1 area 0.0.0.0
           - ospfv3 network {{ ospf_type }}
       parents: interface Vlan{{ vlan_id }}
-  when: svi_v6_network is defined or svi_v6_link_local is defined
+  when: svi_v6_network is defined or svi_v6_link_local is defined and (delete_vlan is not defined or delete_vlan is False)
   tags:
     - nxos
     - vlan
@@ -219,7 +222,7 @@
       lines:
           - no ospfv3 passive-interface
       parents: interface Vlan{{ vlan_id }}
-  when: (svi_v6_network is defined or svi_v6_link_local is defined) and not passive_interface is defined
+  when: (svi_v6_network is defined or svi_v6_link_local is defined) and not passive_interface is defined and (delete_vlan is not defined or delete_vlan is False)
   tags:
     - nxos
     - vlan
@@ -233,7 +236,7 @@
           - no ip redirects
           - no ipv6 redirects
       parents: interface Vlan{{ vlan_id }}
-  when: svi_v4_prefix is defined or svi_v6_network is defined
+  when: svi_v4_prefix is defined or svi_v6_network is defined and (delete_vlan is not defined or delete_vlan is False)
   tags:
     - nxos
     - vlan
@@ -245,7 +248,7 @@
       lines:
           - hsrp version 2
       parents: interface Vlan{{ vlan_id }}
-  when: (svi_v4_prefix is defined or svi_v6_network is defined) and use_hsrp is defined
+  when: (svi_v4_prefix is defined or svi_v6_network is defined) and use_hsrp is defined and (delete_vlan is not defined or delete_vlan is False)
   tags:
     - nxos
     - vlan
@@ -264,7 +267,7 @@
       parents:
           - interface Vlan{{ vlan_id }}
           - hsrp 1
-  when: svi_v4_prefix is defined and use_hsrp is defined
+  when: svi_v4_prefix is defined and use_hsrp is defined and (delete_vlan is not defined or delete_vlan is False)
   tags:
       - nxos
       - vlan
@@ -284,10 +287,48 @@
       parents:
           - interface Vlan{{ vlan_id }}
           - hsrp 2 ipv6
-  when: svi_v6_network is defined and use_hsrp is defined
+  when: svi_v6_network is defined and use_hsrp is defined and (delete_vlan is not defined or delete_vlan is False)
   tags:
       - nxos
       - vlan
       - nxos-vlan
       - add-hsrp
       - add-hsrp-v6
+
+- name: Remove SVI
+  nxos_interfaces:
+      config:
+        - name: Vlan{{ vlan_id }}
+      state: deleted
+  when: delete_vlan is defined or delete_vlan is True
+  tags:
+    - nxos
+    - vlan
+    - nxos-vlan
+    - delete-svi
+
+- name: Remove VLAN from interfaces
+  nxos_config:
+      lines:
+          - switchport trunk allowed vlan remove {{ vlan_id }}
+      parents: interface {{ item }}
+  with_items: "{{ iflist }}"
+  when: iflist is defined and delete_vlan is defined and delete_vlan is True
+  tags:
+    - nxos
+    - vlan
+    - nxos-vlan
+    - remove-vlan
+
+- name: Delete VLAN definition
+  nxos_vlans:
+      config:
+        - vlan_id: "{{ vlan_id }}"
+      state: deleted
+  when: delete_vlan is defined and delete_vlan is True
+  tags:
+    - nxos
+    - vlan
+    - nxos-vlan
+    - delete-vlan
+    - delete-nxos-vlan

+ 18 - 0
automation/cleu-ansible-n9k/roles/ucs-vlan/tasks/main.yml

@@ -9,9 +9,27 @@
     password: "{{ ucs_mgr_password }}"
     username: "{{ ucs_mgr_username }}"
   delegate_to: localhost
+  when: delete_vlan is not defined or delete_vlan is False
   tags:
     - ucs
     - vlan
     - ucs-vlan
     - add-vlan
     - add-ucs-vlan
+
+- name: Delete VLAN from UCS
+  ucs_vlans:
+    fabric: common
+    hostname: "{{ inventory_hostname }}"
+    name: "{{ vlan_name }}"
+    password: "{{ ucs_mgr_password }}"
+    state: absent
+    username: "{{ ucs_mgr_username }}"
+  delegate_to: localhost
+  when: delete_vlan is defined and delete_vlan is True
+  tags:
+    - ucs
+    - vlan
+    - ucs-vlan
+    - delete-vlan
+    - delete-ucs-vlan

+ 22 - 0
automation/cleu-ansible-n9k/roles/vmware-vlan/tasks/main.yml

@@ -9,6 +9,8 @@
     - vmware-vlan
     - add-vlan
     - add-vmware-vlan
+    - delete-vlan
+    - delete-vmware-vlan
 
 - name: Add VLAN to VMware cluster
   vmware_portgroup:
@@ -20,9 +22,29 @@
     validate_certs: no
   delegate_to: localhost
   with_items: "{{ vm_clusters }}"
+  when: delete_vlan is not defined or delete_vlan is False
   tags:
     - vcenter
     - vlan
     - vmware-vlan
     - add-vlan
     - add-vmware-vlan
+
+- name: Delete VLAN from VMware cluster
+  vmware_portgroup:
+    hostname: "{{ inventory_hostname }}"
+    cluster: "{{ item }}"
+    state: absent
+    switch: "{{ cluster_vswitch[item] }}"
+    portgroup: "{{ vm_vlan_name }}"
+    vlan_id: "{{ vlan_id }}"
+    validate_certs: no
+  delegate_to: localhost
+  with_items: "{{ vm_clusters }}"
+  when: delete_vlan is defined and delete_vlan is True
+  tags:
+    - vcenter
+    - vlan
+    - vmware-vlan
+    - delete-vlan
+    - delete-vmware-vlan