delete_vlan.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. #!/usr/bin/env python3
  2. import argparse
  3. import sys
  4. import re
  5. import subprocess
  6. import os
  7. import tempfile
  8. from yaml import load, dump
  9. try:
  10. from yaml import CLoader as Loader, CDumper as Dumper
  11. except ImportError:
  12. from yaml import Loader, Dumper
  13. def main():
  14. parser = argparse.ArgumentParser(
  15. prog=sys.argv[0], description="Delete a VLAN from the network"
  16. )
  17. parser.add_argument(
  18. "--vlan-name",
  19. "-n",
  20. metavar="<VLAN_NAME>",
  21. help="Name of the VLAN to add",
  22. required=True,
  23. )
  24. parser.add_argument(
  25. "--vm-vlan-name",
  26. metavar="<VM_VLAN_NAME>",
  27. help="Name of the VLAN port group in VMware (required when removing VLAN from vCenter)",
  28. )
  29. parser.add_argument(
  30. "--vlan-id",
  31. "-i",
  32. metavar="<VLAN_ID>",
  33. help="ID of the VLAN to delete",
  34. type=int,
  35. required=True,
  36. )
  37. parser.add_argument(
  38. "--is-stretched",
  39. help="VLAN is stretched between both data centres (default: False)",
  40. action="store_true",
  41. )
  42. parser.add_argument(
  43. "--interface",
  44. action="append",
  45. metavar="<INTF>",
  46. help="Interface to enable for VLAN (can be specified more than once)",
  47. )
  48. parser.add_argument(
  49. "--generate-iflist",
  50. help="Automatically generate a list of allowed interfaces for VLAN (default: False)",
  51. action="store_true",
  52. )
  53. parser.add_argument(
  54. "--vmware-cluster",
  55. action="append",
  56. metavar="<CLUSTER>",
  57. help="VMware cluster to configure for VLAN (can be specified more than once) (default: all clusters are configured)",
  58. )
  59. parser.add_argument(
  60. "--username",
  61. "-u",
  62. metavar="<USERNAME>",
  63. help="Username to use to connect to the N9Ks",
  64. required=True,
  65. )
  66. parser.add_argument(
  67. "--limit",
  68. "-L",
  69. metavar="<HOSTS_OR_GROUP_NAMES>",
  70. help="Comma-separated list of hosts or host group names (from inventory/hosts) on which to restrict operations",
  71. )
  72. parser.add_argument(
  73. "--tags",
  74. metavar="<TAG_LIST>",
  75. help="Comma-separated list of task tags to execute",
  76. )
  77. parser.add_argument(
  78. "--list-tags", help="List available task tags", action="store_true"
  79. )
  80. parser.add_argument(
  81. "--test-only",
  82. help="Only check syntax and attempt to predict changes (NO CHANGES WILL BE MADE)",
  83. action="store_true",
  84. )
  85. args = parser.parse_args()
  86. if args.vlan_id < 1 or args.vlan_id > 3967:
  87. print("ERROR: VLAN ID must be between 1 and 3967")
  88. sys.exit(1)
  89. is_stretched = False
  90. generate_iflist = False
  91. if args.is_stretched:
  92. is_stretched = True
  93. if args.generate_iflist and args.interface and len(args.interface) > 0:
  94. print("ERROR: Cannot specify both an interface list and --generate-iflist.")
  95. sys.exit(1)
  96. if args.generate_iflist:
  97. generate_iflist = True
  98. os.environ["ANSIBLE_FORCE_COLOR"] = "True"
  99. os.environ["ANSIBLE_HOST_KEY_CHECKING"] = "False"
  100. os.environ["ANSIBLE_PERSISTENT_COMMAND_TIMEOUT"] = "300"
  101. os.environ["ANSIBLE_DEPRECATION_WARNINGS"] = "False"
  102. if "AD_PASSWORD" not in os.environ:
  103. print(
  104. "ERROR: AD_PASSWORD must be set in the environment first (used for vCenter and UCS)."
  105. )
  106. sys.exit(1)
  107. os.environ["VMWARE_USER"] = args.username
  108. os.environ["VMWARE_PASSWORD"] = os.environ["AD_PASSWORD"]
  109. cred_file = tempfile.NamedTemporaryFile(mode="w", delete=False)
  110. vars = {
  111. "ucs_mgr_username": args.username,
  112. "ucs_mgr_password": os.environ["AD_PASSWORD"],
  113. }
  114. dump(vars, cred_file, Dumper=Dumper)
  115. cred_file.close()
  116. command = [
  117. "ansible-playbook",
  118. "-i",
  119. "inventory/hosts",
  120. "-u",
  121. args.username,
  122. "-k",
  123. "-e",
  124. "vlan_name={}".format(args.vlan_name),
  125. "-e",
  126. "vlan_id={}".format(args.vlan_id),
  127. "-e",
  128. "ansible_python_interpreter={}".format(sys.executable),
  129. "-e",
  130. "@{}".format(cred_file.name),
  131. "-e",
  132. "delete_vlan=True",
  133. "-e",
  134. "is_stretched={}".format(is_stretched),
  135. "-e",
  136. "generate_iflist={}".format(generate_iflist),
  137. "delete-vlan-playbook.yml",
  138. ]
  139. if args.vm_vlan_name:
  140. command += ["-e", "vm_vlan_name='{}'".format(args.vm_vlan_name)]
  141. if args.interface and len(args.interface) > 0:
  142. command += ["-e", '{{"iflist": [{}]}}'.format(",".join(args.interface))]
  143. if args.vmware_cluster and len(args.vmware_cluster) > 0:
  144. command += [
  145. "-e",
  146. '{{"vm_clusters": [{}]}}'.format(",".join(args.vmware_cluster)),
  147. ]
  148. if args.limit:
  149. command += ["--limit", args.limit]
  150. if args.tags:
  151. command += ["--tags", args.tags]
  152. if args.list_tags:
  153. command += ["--list-tags"]
  154. if args.test_only:
  155. command += ["-C"]
  156. p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  157. for c in iter(lambda: p.stdout.read(1), b""):
  158. sys.stdout.write(c.decode("utf-8"))
  159. sys.stdout.flush()
  160. p.poll()
  161. if os.path.isfile(cred_file.name):
  162. os.remove(cred_file.name)
  163. if __name__ == "__main__":
  164. main()