extend_scope.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #!/usr/bin/env python3
  2. #
  3. # Copyright (c) 2017-2020 Joe Clarke <jclarke@cisco.com>
  4. # All rights reserved.
  5. #
  6. # Redistribution and use in source and binary forms, with or without
  7. # modification, are permitted provided that the following conditions
  8. # are met:
  9. # 1. Redistributions of source code must retain the above copyright
  10. # notice, this list of conditions and the following disclaimer.
  11. # 2. Redistributions in binary form must reproduce the above copyright
  12. # notice, this list of conditions and the following disclaimer in the
  13. # documentation and/or other materials provided with the distribution.
  14. #
  15. # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  16. # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  19. # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  21. # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22. # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  23. # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  24. # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  25. # SUCH DAMAGE.
  26. from builtins import str
  27. from builtins import range
  28. import json
  29. import requests
  30. from requests.packages.urllib3.exceptions import InsecureRequestWarning
  31. requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
  32. import sys
  33. import CLEUCreds
  34. from cleu.config import Config as C
  35. IDF_CNT = 99
  36. ADDITIONAL_IDFS = (252, 253, 254)
  37. IDF_OVERRIDES = {
  38. 252: {"first_ip": 160, "last_ip": "250"},
  39. 253: {"first_ip": 160, "last_ip": "250"},
  40. 254: {"first_ip": 160, "last_ip": "250"},
  41. }
  42. SCOPE_BASE = C.DHCP_BASE + "Scope"
  43. HEADERS = {"authorization": CLEUCreds.JCLARKE_BASIC, "accept": "application/json", "content-type": "application/json"}
  44. if __name__ == "__main__":
  45. if len(sys.argv) != 4:
  46. sys.stderr.write("usage: {} VLAN <IDF|CORE> START\n".format(sys.argv[0]))
  47. sys.exit(1)
  48. vlan = sys.argv[1]
  49. type = sys.argv[2].upper()
  50. start = sys.argv[3]
  51. if type != "CORE" and type != "IDF":
  52. sys.stderr.write("usage: {} VLAN <IDF|CORE> START\n".format(sys.argv[0]))
  53. sys.exit(1)
  54. idf_set = ()
  55. istart = 1
  56. prefix = "IDF-" + str(istart).zfill(3)
  57. rs = 1
  58. cnt = IDF_CNT
  59. if type == "CORE":
  60. prefix = "CORE-"
  61. rs = 0
  62. cnt = 0
  63. first_scope_name = "{}-{}".format(prefix, vlan.upper())
  64. url = "{}/{}".format(SCOPE_BASE, first_scope_name)
  65. try:
  66. response = requests.request("GET", url, headers=HEADERS, verify=False)
  67. response.raise_for_status()
  68. except Exception as e:
  69. sys.stderr.write("Failed to get first scope details for {}: {}\n".format(first_scope_name, e))
  70. sys.exit(1)
  71. first_scope = response.json()
  72. end = first_scope["rangeList"]["RangeItem"][0]["end"].split(".")[3]
  73. subnet = ".".join(first_scope["subnet"].split(".")[0:2])
  74. policy = first_scope["policy"]
  75. embedded_policy = None
  76. if "embeddedPolicy" in first_scope:
  77. embedded_policy = first_scope["embeddedPolicy"]
  78. for i in range(rs, cnt + 1):
  79. idf_set += (i,)
  80. if type != "CORE":
  81. idf_set += ADDITIONAL_IDFS
  82. for i in idf_set:
  83. rstart = "{}.{}.{}".format(subnet, i, start)
  84. eoctet = i
  85. if type == "CORE":
  86. eoctet = 255
  87. if i in IDF_OVERRIDES:
  88. end = IDF_OVERRIDES[i]["last_ip"]
  89. rend = "{}.{}.{}".format(subnet, eoctet, end)
  90. prefix = "IDF-" + str(i).zfill(3)
  91. if embedded_policy is not None:
  92. embedded_policy = {"optionList": {"OptionItem": [{"number": "3", "value": "{}.{}.{}".format(subnet, eoctet, str(254))}]}}
  93. if type == "CORE":
  94. prefix = "CORE-"
  95. scope_name = "{}-{}".format(prefix, vlan.upper())
  96. url = "{}/{}".format(SCOPE_BASE, scope_name)
  97. try:
  98. # print('Changing {} to start: {}, end: {}'.format(
  99. # scope_name, start, end))
  100. payload = {"rangeList": {"RangeItem": [{"start": rstart, "end": rend}]}, "policy": policy}
  101. if embedded_policy is not None:
  102. payload["embeddedPolicy"] = embedded_policy
  103. response = requests.request("PUT", url, json=payload, headers=HEADERS, verify=False)
  104. response.raise_for_status()
  105. except Exception as e:
  106. sys.stderr.write("Failed to update scope details for {}: {}\n".format(scope_name, e))
  107. continue