当前位置:   article > 正文

Python-Switch-Route 使用Python3通过SSH和SNMP操作交换机_python3 连接交换机

python3 连接交换机

通过Python自动操作交换机

文件一:Main_Switch.py 操作示例

文件二:DEF_SSH_eNSP_Switch_S5700.py 通过SSH交互控制交换机完成任务

文件三:DEF_SNMP_eNSP_Switch_S5700.py 通过SNMP获取交换机信息

文件四:DEV_SSH.py 操作交换机的SSH驱动部分

文件五:DEV_SNMP.py 操作交换机SNMP驱动部分,目前这个需要Linux环境

 

文件一代码:

  1. #_*_ coding:utf8 _*_
  2. from DEF_SNMP_eNSP_Switch_S5700 import *
  3. from DEF_SSH_eNSP_Switch_S5700 import *
  4. import logging # 日志模块
  5. Log = logging.getLogger('__name__') # 获取实例
  6. formatter = logging.Formatter('%(asctime)s %(levelname)-8s: %(message)s') # 指定logger输出格式
  7. file_handler = logging.FileHandler('Main_Switch.log') # 日志文件路径
  8. file_handler.setFormatter(formatter) # 可以通过setFormatter指定输出格式
  9. Log.addHandler(file_handler) # 为logger添加的日志处理器
  10. # 设置记录的日志级别
  11. #Log.setLevel(logging.DEBUG)
  12. Log.setLevel(logging.INFO)
  13. #Log.setLevel(logging.WARNING)
  14. #Log.setLevel(logging.ERROR)
  15. #Log.setLevel(logging.CRITICAL)
  16. ## 测试 SNMP 功能
  17. '''
  18. ## SNMP 功能由于 DEV_SNMP.py 是根据Linux写的,需要Linux环境
  19. SNMP_PWD = 'pwd@123'
  20. SNMP_HOST = '192.168.56.2'
  21. SNMP_Ver = '2c'
  22. ## 查询设备IP和MAC绑定信息,生成字典形式
  23. R = SNMP_生成以IP为键以MAC地址列表为值的字典(SNMP_PWD, SNMP_HOST)
  24. if R[0] == 0:
  25. D_IP_MAC = R[1]
  26. INFO = '成功,IP和MAC绑定信息字典:' + str(D_IP_MAC)
  27. Log.info(INFO)
  28. print(INFO)
  29. else:
  30. ERROR = '失败,错误信息:'+ R[1]
  31. Log.error(ERROR)
  32. print(ERROR)
  33. ## 查询设备VLAN接口的IP地址信息,生成字典形式
  34. R = SNMP_生成以VLAN为键以VLAN_IP_MASK列表为值的字典(SNMP_PWD, SNMP_HOST)
  35. if R[0] == 0:
  36. D_VLAN_NET = R[1]
  37. INFO = '成功,VLAN接口和IP信息字典:' + str(D_VLAN_NET)
  38. Log.info(INFO)
  39. print(INFO)
  40. else:
  41. ERROR = '失败,错误信息:'+ R[1]
  42. Log.error(ERROR)
  43. print(ERROR)
  44. '''
  45. ## 测试 SSH 功能
  46. # 每台SSH设备的登录信息
  47. D_DEV0 = {}
  48. D_DEV0['SSH_USER'] = 'test'
  49. D_DEV0['SSH_PASS'] = 'pwd@123'
  50. D_DEV0['SSH_IP'] = '192.168.0.1'
  51. D_DEV0['SSH_PORT'] = 2001
  52. D_DEV1 = {}
  53. D_DEV1['SSH_USER'] = 'test'
  54. D_DEV1['SSH_PASS'] = 'pwd@123'
  55. D_DEV1['SSH_IP'] = '192.168.1.1'
  56. D_DEV2 = {}
  57. D_DEV2['SSH_USER'] = 'test'
  58. D_DEV2['SSH_PASS'] = 'pwd@123'
  59. D_DEV2['SSH_IP'] = '192.168.56.2'
  60. ## 全部SSH设备组成列表(顺序无所谓)
  61. L_DEVS = [D_DEV0, D_DEV1, D_DEV2]
  62. ## 制作选提示信息
  63. 设备列表 = '''
  64. 可以登录的设备列表
  65. '''
  66. for i in range(0, len(L_DEVS)):
  67. 设备列表 += '[ '+ str(i) + ' ] 选择 ' + L_DEVS[i]['SSH_IP'] + ' 设备进行操作\n'
  68. 设备列表 += '[ q ] 退出选择设备\n请选择设备:'
  69. #print(设备列表)
  70. '''
  71. 可以登录的设备列表
  72. [ 0 ] 选择 192.168.0.1 设备进行操作
  73. [ 1 ] 选择 192.168.1.1 设备进行操作
  74. [ 2 ] 选择 192.168.56.2 设备进行操作
  75. [ q ] 退出选择设备
  76. '''
  77. ## 制作业务功能选择列表
  78. 业务列表 = '''=== 功能菜单 ===
  79. [ 0 ] 保存配置
  80. [ 1 ] 查看全部IP和MAC绑定信息
  81. [ 2 ] 绑定指定IP和指定MAC
  82. [ 3 ] 在指定网段自动选择可用IP和指定MAC绑定
  83. [ 4 ] 查找MAC地址所在网段
  84. [ 5 ] 在MAC所在网段自动选择可用IP和进行绑定
  85. [ 6 ] 解除指定IP和指定MAC的绑定
  86. [ 7 ] 解除指定IP的全部MAC绑定
  87. [ 8 ] 解除指定MAC的全部IP绑定
  88. [ e ] 改变登录设备
  89. [ q ] 退出功能程序
  90. === 功能菜单 ===
  91. 请输入功能编号:'''
  92. ## 循环交互操作
  93. while 1:
  94. if '字典_登录信息' in locals().keys():
  95. print("【提示】当前已经缓存", 字典_登录信息['SSH_IP'], "登录信息")
  96. print()
  97. else:
  98. 目标设备 = input(设备列表)
  99. INDEX = [str(i) for i in range(0, len(L_DEVS))]
  100. if 目标设备 in INDEX:
  101. 字典_登录信息 = L_DEVS[int(目标设备)]
  102. print("【提示】当前已经选择", 字典_登录信息['SSH_IP'], "登录信息")
  103. print()
  104. elif 目标设备 == 'q':
  105. print("用户退出选择")
  106. break
  107. else:
  108. print("无效输入,请重新选择")
  109. print()
  110. while 1:
  111. 目标设备 = input(设备列表)
  112. INDEX = [str(i) for i in range(0, len(L_DEVS))]
  113. if 目标设备 in INDEX:
  114. 字典_登录信息 = L_DEVS[int(目标设备)]
  115. print("【提示】当前已经选择", 字典_登录信息['SSH_IP'], "登录信息")
  116. print()
  117. elif 目标设备 == 'q':
  118. print("用户退出选择")
  119. break
  120. break
  121. 业务选择 = input(业务列表)
  122. # 0 保存配置
  123. if 业务选择 == '0':
  124. T0 = time.time()
  125. print("正在执行 保存配置 请稍后")
  126. R = 保存配置(字典_登录信息)
  127. T1 = time.time()
  128. if R[0] == 0:
  129. INFO = R[1]
  130. Log.info(INFO)
  131. print(INFO)
  132. else:
  133. ERROR = R[1]
  134. Log.error(ERROR)
  135. print(ERROR)
  136. print("耗时 %.1f 秒" % (T1-T0))
  137. print()
  138. # 1 查看全部IP和MAC绑定信息
  139. elif 业务选择 == '1':
  140. T0 = time.time()
  141. print("正在执行 查看全部IP和MAC绑定信息 请稍后")
  142. R = 获取IP和MAC绑定信息(字典_登录信息)
  143. T1 = time.time()
  144. if R[0] == 0:
  145. print("成功")
  146. D_IP_MAC = R[1]
  147. if D_IP_MAC == {}:
  148. print("当前无绑定记录")
  149. else:
  150. print("IP\t\t绑定MAC列表")
  151. for K in D_IP_MAC:
  152. print(K, "\t", D_IP_MAC[K])
  153. else:
  154. print("失败")
  155. print("失败原因", R[1])
  156. print("耗时 %.1f 秒" % (T1-T0))
  157. print()
  158. # 2 绑定指定IP和指定MAC
  159. elif 业务选择 == '2':
  160. Bind_IP = input("输入要绑定的IP地址(如192.168.0.1):")
  161. Bind_MAC = input("要绑定的MAC地址(任意mac地址写法):")
  162. T0 = time.time()
  163. print("正在执行 绑定指定IP和指定MAC 请稍后")
  164. R = 绑定指定IP和指定MAC(字典_登录信息, Bind_IP, Bind_MAC)
  165. T1 = time.time()
  166. if R[0] == 0:
  167. print("成功")
  168. print("成功信息", R[1])
  169. INFO = R[1]
  170. Log.info(INFO)
  171. print(INFO)
  172. else:
  173. print("失败")
  174. print("失败原因", R[1])
  175. ERROR = R[1]
  176. Log.error(ERROR)
  177. print("耗时 %.1f 秒" % (T1-T0))
  178. print()
  179. # 3在指定网段自动选择可用IP和指定MAC绑定
  180. elif 业务选择 == '3':
  181. Bind_NET = input("要绑定的网段(如192.168.0.1/24 或 192.168.0.1/255.255.255.0: ")
  182. Bind_MAC = input("要绑定的MAC地址(任意mac地址写法):")
  183. T0 = time.time()
  184. print("正在执行 在指定网段自动选择可用IP和指定MAC绑定 请稍后")
  185. R = 在指定网段自动选择可用IP和指定MAC绑定(字典_登录信息, Bind_NET, Bind_MAC)
  186. T1 = time.time()
  187. if R[0] == 0:
  188. print("成功")
  189. print("成功信息", R[1])
  190. INFO = R[1]
  191. Log.info(INFO)
  192. print(INFO)
  193. else:
  194. print("失败")
  195. print("失败原因", R[1])
  196. ERROR = R[1]
  197. Log.error(ERROR)
  198. print("耗时 %.1f 秒" % (T1-T0))
  199. print()
  200. # 4 查找MAC地址所在网段
  201. elif 业务选择 == '4':
  202. MAC = input("要查找的MAC地址(任意mac地址写法):")
  203. T0 = time.time()
  204. print("正在执行 查找MAC地址所在网段 请稍后")
  205. R = 查找MAC地址所在网段(字典_登录信息, MAC)
  206. T1 = time.time()
  207. if R[0] == 0:
  208. print("成功")
  209. print("成功信息", R[1])
  210. INFO = R[1]
  211. Log.info(INFO)
  212. print(INFO)
  213. else:
  214. print("失败")
  215. print("失败原因", R[1])
  216. ERROR = R[1]
  217. Log.error(ERROR)
  218. print("耗时 %.1f 秒" % (T1-T0))
  219. print()
  220. # 5 在MAC所在网段自动选择可用IP和进行绑定
  221. elif 业务选择 == '5':
  222. Bind_MAC = input("要绑定的MAC地址(任意mac地址写法):")
  223. T0 = time.time()
  224. print("正在执行 在MAC所在网段自动选择可用IP和进行绑定 请稍后")
  225. R = 在MAC所在网段自动选择可用IP和进行绑定(字典_登录信息, Bind_MAC)
  226. T1 = time.time()
  227. if R[0] == 0:
  228. print("成功")
  229. print("成功信息", R[1])
  230. INFO = R[1]
  231. Log.info(INFO)
  232. print(INFO)
  233. else:
  234. print("失败")
  235. print("失败原因", R[1])
  236. ERROR = R[1]
  237. Log.error(ERROR)
  238. print("耗时 %.1f 秒" % (T1-T0))
  239. print()
  240. # 6 解除指定IP和指定MAC的绑定
  241. elif 业务选择 == '6':
  242. Undo_Bind_IP = input("要解除绑定的IP地址(如192.168.0.1):")
  243. Undo_Bind_MAC = input("要解除绑定的MAC地址(任意mac地址写法):")
  244. T0 = time.time()
  245. print("正在执行 解除指定IP和指定MAC的绑定 请稍后")
  246. R = 解除指定IP和指定MAC的绑定(字典_登录信息, Undo_Bind_IP, Undo_Bind_MAC)
  247. T1 = time.time()
  248. if R[0] == 0:
  249. print("成功")
  250. print("成功信息", R[1])
  251. INFO = R[1]
  252. Log.info(INFO)
  253. print(INFO)
  254. else:
  255. print("失败")
  256. print("失败原因", R[1])
  257. ERROR = R[1]
  258. Log.error(ERROR)
  259. print("耗时 %.1f 秒" % (T1-T0))
  260. print()
  261. # 7 解除指定IP的全部MAC绑定
  262. elif 业务选择 == '7':
  263. Undo_Bind_IP = input("要解除绑定的IP地址(如192.168.0.1):")
  264. T0 = time.time()
  265. print("正在执行 解除指定IP的全部MAC绑定 请稍后")
  266. R = 解除指定IP的全部MAC绑定(字典_登录信息, Undo_Bind_IP)
  267. T1 = time.time()
  268. if R[0] == 0:
  269. print("成功")
  270. print("成功信息", R[1])
  271. INFO = R[1]
  272. Log.info(INFO)
  273. print(INFO)
  274. else:
  275. print("失败")
  276. print("失败原因", R[1])
  277. ERROR = R[1]
  278. Log.error(ERROR)
  279. print("耗时 %.1f 秒" % (T1-T0))
  280. print()
  281. # 8 解除指定MAC的全部IP绑定
  282. elif 业务选择 == '8':
  283. Undo_Bind_MAC = input("要解除绑定的MAC地址(任意mac地址写法):")
  284. T0 = time.time()
  285. print("正在执行 解除指定MAC的全部IP绑定 请稍后")
  286. R = 解除指定MAC的全部IP绑定(字典_登录信息, Undo_Bind_MAC)
  287. T1 = time.time()
  288. if R[0] == 0:
  289. print("成功")
  290. print("成功信息", R[1])
  291. INFO = R[1]
  292. Log.info(INFO)
  293. print(INFO)
  294. else:
  295. print("失败")
  296. print("失败原因", R[1])
  297. ERROR = R[1]
  298. Log.error(ERROR)
  299. print("耗时 %.1f 秒" % (T1-T0))
  300. print()
  301. elif 业务选择 == 'e':
  302. print()
  303. print("【提示】修改登录设备")
  304. while 1:
  305. 目标设备 = input(设备列表)
  306. INDEX = [str(i) for i in range(0, len(L_DEVS))]
  307. if 目标设备 in INDEX:
  308. 字典_登录信息 = L_DEVS[int(目标设备)]
  309. print("【提示】当前重新选择", 字典_登录信息['SSH_IP'], "登录信息")
  310. print()
  311. break
  312. elif 目标设备 == 'q':
  313. print("用户退出选择")
  314. break
  315. else:
  316. print("无效输入,请重新选择")
  317. elif 业务选择 == 'q':
  318. print("用户正常退出程序")
  319. break
  320. else:
  321. print("无效选择,重新选择")

 

 

文件二代码:

  1. #_*_ coding:utf8 _*_
  2. from DEV_SSH import *
  3. import struct
  4. import re
  5. import logging # 日志模块
  6. import sys
  7. Log = logging.getLogger("__name__")
  8. if not logging.FileHandler:
  9. # 指定logger输出格式
  10. formatter = logging.Formatter('%(asctime)s %(levelname)-8s : %(message)s')
  11. # 文件日志
  12. file_handler = logging.FileHandler("log")
  13. file_handler = logging.FileHandler("DEF_eNSP_Switch_S5700.log") # 日志文件路径
  14. file_handler.setFormatter(formatter) # 可以通过setFormatter指定输出格式
  15. Log.addHandler(file_handler)
  16. Log.setLevel(logging.DEBUG)
  17. ###############################################################################################################################
  18. ## 检查IP是否合法
  19. ## 参数 IP_STR 点分十进制字符串,例:'192.168.0.1'
  20. def TEST_IP_STR(IP_STR):
  21. if type(IP_STR) == str:
  22. L_IP = IP_STR.split('.') ## 以点分割,各元素组成列表
  23. if len(L_IP) == 4:
  24. try: ## 尝试把4段内容转成数字
  25. IP_0 = int(L_IP[0])
  26. IP_1 = int(L_IP[1])
  27. IP_2 = int(L_IP[2])
  28. IP_3 = int(L_IP[3])
  29. except:
  30. ERROR = '函数 TEST_IP_STR() 参数 IP_STR 以点分成4段中有不能转成数字的部分'
  31. return(1, ERROR)
  32. else: ## 4段值各自转成数字成功后判断每个数字的取值范围
  33. if 0<= IP_0 <=255 and 0<= IP_1 <=255 and 0<= IP_2 <=255 and 0<= IP_3 <=255:
  34. INFO = '函数 TEST_IP_STR() 参数 IP_STR 检测合格,变量值 = ' + IP_STR
  35. return(0, INFO)
  36. else:
  37. ERROR = '函数 TEST_IP_STR() 参数 IP_STR 以点分成4段中有超出0-255范围的值'
  38. return(1, ERROR)
  39. else:
  40. ERROR = '函数 TEST_IP_STR() 参数 IP_STR 不能以点分成4段'
  41. return(1, ERROR)
  42. else:
  43. ERROR = '函数 TEST_IP_STR() 参数 IP_STR 类型不是字符串'
  44. return(1, ERROR)
  45. ###############################################################################################################################
  46. ###############################################################################################################################
  47. ## 检查登录信息字典
  48. ## 参数 D_LOGIN_INFO 帐号、密码、地址、端口组成的字典
  49. ## 如果无端口号设置为默认22端口(会修改字典)
  50. def TEST_D_LOGIN_INFO(D_LOGIN_INFO):
  51. if type(D_LOGIN_INFO) != dict:
  52. E = '函数 TEST_D_LOGIN_INFO 参数 D_LOGIN_INFO 必须是字典类型'
  53. return(1, E)
  54. if 'SSH_USER' not in D_LOGIN_INFO:
  55. E = '函数 TEST_D_LOGIN_INFO 参数 D_LOGIN_INFO 中 KEY SSH_USER 不存在(没有登录帐号信息)'
  56. return(1, E)
  57. else:
  58. 登录帐号 = D_LOGIN_INFO['SSH_USER']
  59. if type(登录帐号) != str:
  60. E = '函数 TEST_D_LOGIN_INFO 参数 D_LOGIN_INFO 中 KEY SSH_USER 的值(登录帐号)不是字符串'
  61. return(1, E)
  62. if 'SSH_PASS' not in D_LOGIN_INFO:
  63. E = '函数 TEST_D_LOGIN_INFO 参数 D_LOGIN_INFO 中 KEY SSH_PASS 不存在(没有登录密码)'
  64. return(1, E)
  65. else:
  66. 登录密码 = D_LOGIN_INFO['SSH_PASS']
  67. if type(登录密码) != str:
  68. E = '函数 TEST_D_LOGIN_INFO 参数 D_LOGIN_INFO 中 KEY SSH_PASS 的值(登录密码)不是字符串'
  69. return(1, E)
  70. if 'SSH_IP' not in D_LOGIN_INFO:
  71. E = '函数 TEST_D_LOGIN_INFO 参数 D_LOGIN_INFO 中 KEY SSH_IP 不存在(没有登录IP地址)'
  72. return(1, E)
  73. else:
  74. IP_STR = D_LOGIN_INFO['SSH_IP']
  75. R = TEST_IP_STR(IP_STR) ## 调用 TEST_IP_STR() 检查IP是否合法
  76. if R[0] != 0:
  77. E = '函数 TEST_D_LOGIN_INFO 参数 D_LOGIN_INFO 中 KEY SSH_IP 的值(登录IP地址)IP格式错误 ' + R[1]
  78. return(1, E)
  79. if 'SSH_PORT' not in D_LOGIN_INFO:
  80. D_LOGIN_INFO['SSH_PORT'] = 22
  81. INFO = '函数 TEST_D_LOGIN_INFO 参数 D_LOGIN_INFO 中 KEY SSH_PORT 不存在(没有登录端口号)自动设置为默认22端口号'
  82. return(0, INFO) ## 修改为默认端口号后全部检查合格
  83. else:
  84. PORT = D_LOGIN_INFO['SSH_PORT']
  85. if type(PORT) != int:
  86. E = '函数 TEST_D_LOGIN_INFO 参数 D_LOGIN_INFO 中 KEY SSH_PORT 的值(登录端口号)不是数字'
  87. return(1, E)
  88. else:
  89. if 0< PORT <65535:
  90. INFO = '函数 TEST_D_LOGIN_INFO 参数 D_LOGIN_INFO 中 KEY SSH_PORT 的值(登录端口号)在(0,65535)区间内,检测合格,变量值 = ' + str(PORT)
  91. return(0, INFO) ## 全部检查合格
  92. else:
  93. E = '函数 TEST_D_LOGIN_INFO 参数 D_LOGIN_INFO 中 KEY SSH_PORT 的值(登录端口号)数值不在(0,65535)区间内'
  94. return(1, E)
  95. ###############################################################################################################################
  96. ###############################################################################################################################
  97. ## 尝试把掩码转成掩码位数
  98. ## MASK 参数类型:字符串('24' 或 '255.255.255.0' 样式)
  99. ## MASK 参数类型:数字(0到32)
  100. ## 成功返回 (0, 掩码位数(数字))
  101. ## 失败返回 (1, 错误信息)
  102. def TRY_MASK_2_MASK_INT(MASK):
  103. ## 字符串掩码格式和掩码长度对应的字典,方便快速查找
  104. D_MASK = {
  105. '0.0.0.0':0,
  106. '128.0.0.0':1,'192.0.0.0':2,'224.0.0.0':3,'240.0.0.0':4,'248.0.0.0':5,'252.0.0.0':6,'254.0.0.0':7,'255.0.0.0':8,
  107. '255.128.0.0':9,'255.192.0.0':10,'255.224.0.0':11,'255.240.0.0':12,'255.248.0.0':13,'255.252.0.0':14,'255.254.0.0':15,'255.255.0.0':16,
  108. '255.255.128.0':17,'255.255.192.0':18,'255.255.224.0':19,'255.255.240.0':20,'255.255.248.0':21,'255.255.252.0':22,'255.255.254.0':23,'255.255.255.0':24,
  109. '255.255.255.128':25,'255.255.255.192':26,'255.255.255.224':27,'255.255.255.240':28,'255.255.255.248':29,'255.255.255.252':30,'255.255.255.254':31,
  110. '255.255.255.255':32}
  111. if type(MASK) == int: ## 如果是数字类型,后续再判断数值是否在掩码范围内
  112. if 0 <= MASK <= 32: ## 如果掩码数值在0到32内
  113. return(0, MASK) ## 返回成功状态码0和掩码数值
  114. else:
  115. ERROR = 'ERROR 变量范围:掩码只能在0到32范围内'
  116. return(1, ERROR)
  117. elif type(MASK) == str: ## 如果是字符串类型,可能是数字掩码,可能是字符串类型的数字掩码
  118. try:
  119. ## 尝试把参数MASK转成数字类型
  120. MASK_INT = int(MASK) ## int() 函数可以自动删除字符串类型数字的前后空格
  121. except:
  122. ## 不能转换成数字可能是点分十格式掩码的字符串
  123. L_MASK = MASK.split('.') ## 以点分割,各元素组成列表
  124. if len(L_MASK) == 4: ## 如果能分成4段,说明是点分十格式掩码字符串
  125. if MASK in D_MASK: ## 如果这个点分十格式掩码字符串存在于掩码和掩码位数字典中
  126. MASK_INT = D_MASK[MASK] ## 获取点分十格式掩码字符串对应的掩码数值
  127. return(0, MASK_INT) ## 返回成功状态码0和掩码数值
  128. else:
  129. ERROR = 'ERROR 变量范围:掩码超出有效范围'
  130. return(1, ERROR)
  131. else: ## 如果不能分成4段,格式错误
  132. ERROR = 'ERROR 变量格式:掩码格式错误'
  133. return(1, ERROR)
  134. else: ## 可以转成数字
  135. RR = TRY_MASK_2_MASK_INT(MASK_INT) ## 调用自身函数处理新的数字类型参数
  136. return(RR) ## 返回自身处理结果给上级函数
  137. else:
  138. ERROR = 'ERROR 参数类型:只能是数字或字符串或字符串类型的数字'
  139. return(1, ERROR)
  140. ###############################################################################################################################
  141. ## IP_INT 转 IP_STR
  142. ## IP_INT(4字节无符号整数类型IP地址)
  143. ## IP_STR(点分十进制字符串类型IP地址)
  144. def IP_INT_2_IP_STR(IP_INT):
  145. IP_Byte = struct.pack('>I', IP_INT) # 打包成4字节无符号整数(大端/网络端)
  146. 元组_IP_数字 = struct.unpack('BBBB', IP_Byte)
  147. ## 每个数字转成字符串并加上'.'拼成点分十形式字符串
  148. #IP_STR = str(元组_IP_数字[0]) +'.'+ str(元组_IP_数字[1]) +'.'+ str(元组_IP_数字[2]) +'.'+ str(元组_IP_数字[3]) ## Python2用这个写法
  149. IP_STR = f'{str(元组_IP_数字[0])}.{str(元组_IP_数字[1])}.{str(元组_IP_数字[2])}.{str(元组_IP_数字[3])}' ## Python3可用的新写法
  150. return(IP_STR)
  151. ## IP_STR 转 IP_INT
  152. ## IP_STR(点分十进制字符串类型IP地址)
  153. ## IP_INT(4字节无符号整数类型IP地址)
  154. def IP_STR_2_IP_INT(IP_STR):
  155. IP分段 = IP_STR.split('.')
  156. B_IP = struct.pack('BBBB', int(IP分段[0]), int(IP分段[1]), int(IP分段[2]), int(IP分段[3])) # 4个字节数字按顺序拼成4字节字节码
  157. T_IP_INT = struct.unpack('>I', B_IP) # 把拼成的4字节字节码转成大端格式的4字节无符号整数
  158. IP_INT = T_IP_INT[0] # 打包成字节返回是元组,第一个元素是打包的结果
  159. return(IP_INT)
  160. ## 根据地址和掩码计算起始和结束地址
  161. ## 返回(NET_IP_MIN, NET_IP_MAX)
  162. ## NET_IP_MIN(网段首地址/网段号)
  163. ## NET_IP_MAX(网段末地址/广播号)
  164. def 根据地址和掩码计算起始和结束地址(IP_STR, MASK_INT):
  165. 主机位数 = 32 - MASK_INT
  166. 主机数量 = 2**主机位数
  167. IP_INT = IP_STR_2_IP_INT(IP_STR)
  168. 位移操作缓存 = IP_INT >> 主机位数
  169. IP_NET_INT = 位移操作缓存 << 主机位数
  170. NET_IP_MIN = IP_NET_INT ## 每个网段的首IP地址为网段号
  171. NET_IP_MAX = IP_NET_INT + 主机数量 -1 ## 每个网段的末IP地址为广播号(以0为第一个,最后一个要总数-1)
  172. return(NET_IP_MIN, NET_IP_MAX)
  173. ## 根据IP地址和掩码位数生成IP所在网段的全部IP_INT地址列表(列表从小到大顺序)
  174. ## IP_INT(4字节无符号整数类型IP地址)
  175. ## IP_STR(点分十进制字符串类型IP地址)
  176. ## MASK_INT(掩码长度数字,范围0-32)
  177. def IP_MASK_2_IP_INT_LIST(IP_STR, MASK_INT):
  178. 主机位数 = 32 - MASK_INT ## 32位的IPv4地址由网络位部分和主机位部分组成
  179. 主机数量 = 2**主机位数 ## 主机数量由主机位的比特个数可以组成数字的全部可能组合
  180. IP_INT = IP_STR_2_IP_INT(IP_STR) ## (点分十进制字符串类型IP地址)转成(4字节无符号整数类型IP地址)
  181. 位移操作缓存 = IP_INT >> 主机位数 ## 先往右移主机个数位,清除主机位上的值
  182. IP_NET_INT = 位移操作缓存 << 主机位数 ## 再往左移主机个数位,填充主机位上的值为0,得到IP的所在段的网络号(网段中第一个IP地址)对应的4字节数字值
  183. IP_INT_LIST = [i+IP_NET_INT for i in range(0,主机数量)] ## 生成IP所在网段的全部IP地址
  184. return(IP_INT_LIST) ## 返回网段全部IP地址
  185. ## 根据IP地址和掩码位数生成IP所在网段的全部IP_STR地址列表(列表从小到大顺序)
  186. ## IP_STR(点分十进制字符串类型IP地址)
  187. ## MASK_INT(掩码长度数字,范围0-32)
  188. def IP_MASK_2_IP_STR_LIST(IP_STR, MASK_INT):
  189. 主机位数 = 32 - MASK_INT
  190. 主机数量 = 2**主机位数
  191. IP_INT = IP_STR_2_IP_INT(IP_STR)
  192. 位移操作缓存 = IP_INT >> 主机位数
  193. IP_NET_INT = 位移操作缓存 << 主机位数
  194. IP_STR_LIST = []
  195. for i in range(0,主机数量):
  196. R = IP_INT_2_IP_STR(IP_NET_INT + i) ## IP的数字值转成IP点分十格式字符串
  197. IP_STR_LIST.append(R)
  198. return(IP_STR_LIST)
  199. ##################################################################################
  200. ## 功能函数 MAC缓存信息转成MAC对应VLAN字典()
  201. ## 把如下字符串内容
  202. ## <Huawei>display mac-address
  203. ## MAC address table of slot 0:
  204. ## -------------------------------------------------------------------------------
  205. ## MAC Address VLAN/ PEVLAN CEVLAN Port Type LSP/LSR-ID
  206. ## VSI/SI MAC-Tunnel
  207. ## -------------------------------------------------------------------------------
  208. ## 0a00-2700-0010 1 - - GE0/0/1 dynamic 0/-
  209. ## 5489-9836-1256 1 - - GE0/0/2 dynamic 0/-
  210. ## 5489-9836-1256 2 - - GE0/0/3 dynamic 0/-(缓存过期前电脑移动到别的vlan会多出这样的缓存记录)
  211. ## -------------------------------------------------------------------------------
  212. ## Total matching items on slot 0 displayed = 2
  213. ## <Huawei>
  214. ## 转换成字典 {'0a00-2700-0010': ['1'], '5489-9836-1256': ['1', '2']}
  215. ##################################################################################
  216. def MAC缓存信息转成MAC对应VLAN字典(S_DATA):
  217. D_MAC_VLAN = {}
  218. MAC表达式 = '[a-f0-9A-F]{4}\-[a-f0-9A-F]{4}\-[a-f0-9A-F]{4}'
  219. MAC缓存记录表达式 = MAC表达式 + '(.*)'
  220. RE_F = re.finditer(MAC缓存记录表达式, S_DATA)
  221. 列表_MAC缓存信息 = [i.group() for i in RE_F]
  222. #print("列表_MAC缓存信息", 列表_MAC缓存信息)
  223. if 列表_MAC缓存信息 != []:
  224. for i in 列表_MAC缓存信息:
  225. L = i.split()
  226. #print("L", L)
  227. if len(L) > 1: # 能分成2段及以上
  228. MAC = L[0] # 字符串类型MAC地址
  229. VLAN = L[1] # 字符串类型的数字(VLAN号)
  230. #print("MAC", MAC, "VLAN", VLAN)
  231. if MAC not in D_MAC_VLAN:
  232. D_MAC_VLAN[MAC] = [VLAN]
  233. else:
  234. if VLAN not in D_MAC_VLAN[MAC]:
  235. D_MAC_VLAN[MAC].append(VLAN)
  236. #else:
  237. # pass
  238. return(D_MAC_VLAN)
  239. ################################################################################
  240. ## 功能函数 VLAN和NET字典()
  241. ## 把如下字符串内容
  242. ## <Huawei>display ip interface brief
  243. ## Interface IP Address/Mask Physical Protocol
  244. ## MEth0/0/1 unassigned down down
  245. ## NULL0 unassigned up up(s)
  246. ## Vlanif10 192.168.10.1/24 down down
  247. ## Vlanif20 192.168.20.1/24 down down
  248. ## <Huawei>
  249. ## 转换成字典 {'Vlanif10': ['192.168.10.1/24'], 'Vlanif20': ['192.168.20.1/24']}
  250. ################################################################################
  251. def VLAN和NET字典(S_DATA):
  252. D_VLAN_IP_MASK = {}
  253. IP表达式 = '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+' # 数字.数字.数字.数字/数字
  254. 表达式 = '(.*)Vlanif(.*)' + IP表达式
  255. RE_F = re.finditer(表达式, S_DATA)
  256. 列表_VLAN_NET = [i.group() for i in RE_F] # 每条匹配内容做成列表形式
  257. #print("列表_VLAN_NET", 列表_VLAN_NET)
  258. if 列表_VLAN_NET != []:
  259. for i in 列表_VLAN_NET:
  260. L = i.split()
  261. #print("L", L)
  262. if len(L) > 1: # 能分成2段及以上
  263. VLAN = L[0] # 字符串类型MAC地址
  264. NET = L[1] # 字符串类型的数字(VLAN号)
  265. #print("VLAN", VLAN, "NET", NET)
  266. if VLAN not in D_VLAN_IP_MASK:
  267. D_VLAN_IP_MASK[VLAN] = [NET]
  268. else:
  269. D_VLAN_IP_MASK[VLAN].append(NET)
  270. return(D_VLAN_IP_MASK)
  271. ###############################################################################
  272. ## 功能函数 VLAN和IP字典()
  273. ## 把如下字符串内容
  274. ## <Huawei>display ip interface brief
  275. ## Interface IP Address/Mask Physical Protocol
  276. ## MEth0/0/1 unassigned down down
  277. ## NULL0 unassigned up up(s)
  278. ## Vlanif10 192.168.10.1/24 down down
  279. ## Vlanif20 192.168.20.1/24 down down
  280. ## <Huawei>
  281. ## 转换成字典 {'Vlanif10': ['192.168.10.1'], 'Vlanif20': ['192.168.20.1']}
  282. ###############################################################################
  283. def VLAN和IP字典(S_DATA):
  284. D_VLAN_IP = {}
  285. IP表达式 = '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' # 数字.数字.数字.数字
  286. 表达式 = '(.*)Vlanif(.*)' + IP表达式
  287. RE_F = re.finditer(表达式, S_DATA)
  288. 列表_VLAN_IP = [i.group() for i in RE_F] # 每条匹配内容做成列表形式
  289. #print("列表_VLAN_IP", 列表_VLAN_IP)
  290. if 列表_VLAN_IP != []:
  291. for i in 列表_VLAN_IP:
  292. L = i.split()
  293. #print("L", L)
  294. if len(L) > 1: # 能分成2段及以上
  295. VLAN = L[0] # 字符串类型MAC地址
  296. IP = L[1] # 字符串类型的数字(VLAN号)
  297. #print("VLAN", VLAN, "IP", IP)
  298. if VLAN not in D_VLAN_IP:
  299. D_VLAN_IP[VLAN] = [IP]
  300. else:
  301. D_VLAN_IP[VLAN].append(IP)
  302. return(D_VLAN_IP)
  303. ###############################################################################################################################
  304. ## 尝试把网段表示格式:'IP/MASK' 格式转成元组 (IP_STR, MASK_INT)
  305. ## 参数 NET_STR 网段表示格式(字符串)例:'192.168.0.0/255.255.255.0' 或 '192.168.0.0/24'
  306. ## 成功返回 (0, (IP_STR, MASK_INT))
  307. ## 把 192.168.0.1/24 拆成 '192.168.0.1' 和 24
  308. ## 把 192.168.0.1/255.255.255.0 拆成 '192.168.0.1' 和 24
  309. ## 失败返回 (1, 错误信息)
  310. def TRY_NET_STR_2_IP_MASK(NET_STR):
  311. if type(NET_STR) == str:
  312. L_IP_MASK = NET_STR.split('/')
  313. if len(L_IP_MASK) == 2:
  314. IP_STR = L_IP_MASK[0]
  315. MASK_STR = L_IP_MASK[1]
  316. #print("IP_STR", IP_STR, type(IP_STR))
  317. #print("MASK_STR", MASK_STR, type(MASK_STR))
  318. TEST_IP = TEST_IP_STR(IP_STR) ## 判断IP是否正确
  319. R_TRY_MASK = TRY_MASK_2_MASK_INT(MASK_STR) ## 判断并处理掩码
  320. if TEST_IP[0] == R_TRY_MASK[0] == 0: ## 当IP和MASK全部合法时计算可用IP地址
  321. MASK_INT = R_TRY_MASK[1]
  322. return(0, (IP_STR, MASK_INT))
  323. else:
  324. ERROR = 'ERROR 参数格式(字符串):'
  325. if TEST_IP[0] == 1:
  326. ERROR += 'IP格式有错误:' + TEST_IP[1]
  327. if R_TRY_MASK[0] == 1:
  328. ERROR += '掩码格式有错误:' + R_TRY_MASK[1]
  329. return(1, ERROR)
  330. else:
  331. ERROR = 'ERROR 参数格式(字符串):不能以"/"符号分成2段'
  332. return(1, ERROR)
  333. else:
  334. ERROR = 'ERROR 参数类型:必须是字符串'
  335. return(1, ERROR)
  336. ###############################################################################################################################
  337. ###############################################################################################################################
  338. ## 尝试把MAC地址转成指定格式
  339. ## 参数 MAC_STR 字符串类型的MAC地址,只要含有12个十六进制字符即可
  340. ## 参数 转换格式 把传入的MAC地址形式转成指定样式,参数默认值为网络设备常用样式:'xxxx-xxxx-xxxx'
  341. def TRY_MAC_2_MAC(MAC_STR, 转换格式='xxxx-xxxx-xxxx'):
  342. if type(MAC_STR) == str:
  343. MAC_STR = re.sub('[^a-fA-F0-9]', '', MAC_STR) # 先删除不是16进制范围的字符
  344. if len(MAC_STR) == 12: # 判断新的 mac 长度是否正常
  345. if 转换格式 == 'xxxx-xxxx-xxxx':
  346. mac = MAC_STR.lower()
  347. mac_new = mac[0:4] + '-' + mac[4:8] + '-' + mac[8:12] # 改成新格式 xxxx-xxxx-xxxx
  348. return(0, mac_new)
  349. elif 转换格式 == 'XXXX-XXXX-XXXX':
  350. MAC = MAC_STR.upper()
  351. MAC_NEW = MAC[0:4] + '-' + MAC[4:8] + '-' + MAC[8:12] # 改成新格式 XXXX-XXXX-XXXX
  352. return(0, MAC_NEW)
  353. elif 转换格式 == 'xx-xx-xx-xx-xx-xx':
  354. mac = MAC_STR.lower()
  355. mac_new = mac[0:2] + '-' + mac[2:4] + '-' + mac[4:6] + '-' + mac[6:8] + '-' + mac[8:10] + '-' + mac[10:12] # 改成新格式 xx-xx-xx-xx-xx-xx
  356. return(0, mac_new)
  357. elif 转换格式 == 'XX-XX-XX-XX-XX-XX':
  358. MAC = MAC_STR.upper()
  359. MAC_NEW = MAC[0:2] + '-' + MAC[2:4] + '-' + MAC[4:6] + '-' + MAC[6:8] + '-' + MAC[8:10] + '-' + MAC[10:12] # 改成新格式 XX-XX-XX-XX-XX-XX
  360. return(0, MAC_NEW)
  361. elif 转换格式 == 'xx:xx:xx:xx:xx:xx':
  362. mac = MAC_STR.lower()
  363. mac_new = mac[0:2] + ':' + mac[2:4] + ':' + mac[4:6] + ':' + mac[6:8] + ':' + mac[8:10] + ':' + mac[10:12] # 改成新格式 xx:xx:xx:xx:xx:xx
  364. return(0, mac_new)
  365. elif 转换格式 == 'XX:XX:XX:XX:XX:XX':
  366. MAC = MAC_STR.upper()
  367. MAC_NEW = MAC[0:2] + ':' + MAC[2:4] + ':' + MAC[4:6] + ':' + MAC[6:8] + ':' + MAC[8:10] + ':' + MAC[10:12] # 改成新格式 XX:XX:XX:XX:XX:XX
  368. return(0, MAC_NEW)
  369. else:
  370. ERROR = '函数 TRY_MAC_2_MAC() 参数 转换格式 的形式未定义'
  371. return(1, ERROR)
  372. else:
  373. ERROR = '函数 TRY_MAC_2_MAC() 参数 MAC_STR 不是有效MAC地址: ' + MAC_STR
  374. return(1, ERROR)
  375. else:
  376. ERROR = '函数 TRY_MAC_2_MAC() 参数 MAC_STR 需要是字符串类型,当前类型是:' + str(type(MAC_STR))
  377. return(1, ERROR)
  378. ###############################################################################################################################
  379. ###############################################################################################################################
  380. ## 功能函数:查看交互命令行当前所在模式,如果不是查看模式,执行quit命令直到返回查看模式
  381. ## 参数 S_DATA 执行交互命令后的回显内容
  382. ## 参数 SHELL 交互操作子SHELL对象
  383. ## 参数 最大深度 执行quit命令的最大次数
  384. def 返回查看模式(S_DATA, SHELL, 最大深度=5):
  385. if 最大深度 > 0:
  386. L_S_DATA = S_DATA.split() # 以空格分隔回显内容
  387. Log.debug('函数 返回查看模式() 的 L_S_DATA 变量值 = ' + str(L_S_DATA))
  388. 最后内容 = L_S_DATA[-1] # 取最后一段,一般为等待命令的提示符(交换机终端回显日志会有干扰,交换机设置禁止终端打印日志功能)
  389. 查看模式 = re.search('<(.*)>', 最后内容) # 尝试查找<>结构
  390. 配置模式 = re.search('\[(.*)\]', 最后内容) # 尝试查找[]结构
  391. if 配置模式:
  392. CMD = 'quit'
  393. S_DATA = SHELL_CMD(SHELL, CMD, 0.5)
  394. Log.debug('判断是配置模式,执行quit命令,回显内容:' + S_DATA)
  395. 最大深度 = 最大深度 -1
  396. R = 返回查看模式(S_DATA, SHELL, 最大深度)
  397. return(R)
  398. elif 查看模式:
  399. INFO = '已经返回到<查看模式>'
  400. return(0,INFO)
  401. else:
  402. ERROR = '最后一行找不到 <> 或 [] 符号'
  403. return(1,ERROR)
  404. else:
  405. ERROR = '已经退出最大深度还没有返回到<查看模式>放弃'
  406. return(1,ERROR)
  407. ###############################################################################################################################
  408. ###############################################################################################################################
  409. ## 功能函数:从查询静态绑定信息命令回显中提取以IP为KEY以MAC为值的字典
  410. ## 参数 S_DATA 执行交互命令后的回显内容
  411. ## 把如下字符串内容
  412. ## dis cu | include user-bind static
  413. ## user-bind static ip-address 1.1.1.1 mac-address 0000-1111-2222
  414. ## user-bind static ip-address 1.1.1.1 mac-address 0000-0000-0001
  415. ## user-bind static ip-address 1.1.1.2 mac-address 0000-0000-0002
  416. ## <Huawei>
  417. ## 转换成字典 {'1.1.1.1': ['0000-1111-2222', '0000-0000-0001'], '1.1.1.2': ['0000-0000-0002']}
  418. def IP_MAC_绑定信息转成IP为KEY字典(S_DATA):
  419. D_IP_MAC = {} # 存放IP为键MAC为值的字典 示例 {'IP1':['MAC'], 'IP2':['MAC1', 'MAC2']}
  420. ## 从命令回显中过滤出纯IP和MAC的绑定记录,并转成列表形式
  421. 表达式 = '(.*)ip-address(.*)mac-address(.*)' # 匹配绑定记录的正则表达式
  422. RE_F = re.finditer(表达式, S_DATA) # 找到所有匹配的内容(每条绑定记录)
  423. 列表_绑定信息 = [i.group() for i in RE_F] # 每条匹配内容做成列表形式
  424. #print("列表_绑定信息", 列表_绑定信息)
  425. ## 定位IP和MAC各自在绑定记录的位置
  426. if 列表_绑定信息 != []:
  427. 首条记录 = 列表_绑定信息[0] # 提取第一条绑定记录
  428. 列表_首条记录分割 = 首条记录.split() # 第一条绑定记录以空格分段变成列表
  429. IP表达式 = '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' # 匹配 x.x.x.x 类型IP地址的正则表达式
  430. MAC表达式 = '[a-f0-9A-F]{4}\-[a-f0-9A-F]{4}\-[a-f0-9A-F]{4}' # 匹配 xxxx-xxxx-xxxx 类型MAC地址的正则表达式
  431. IP_位置 = '' # 准备存放 IP 下标值
  432. MAC_位置 = '' # 准备存放 MAC 下标值
  433. for i in range(0, len(列表_首条记录分割)): # 遍历首条绑定记录每一段内容
  434. RE_IP = re.search(IP表达式, 列表_首条记录分割[i]) # 尝试在当前段中匹配IP地址
  435. RE_MAC = re.search(MAC表达式, 列表_首条记录分割[i]) # 尝试在当前段中匹配MAC地址
  436. if RE_IP: # 如果在当前段中匹配到IP地址
  437. #print(i, "is IP:", 列表_首条记录分割[i])
  438. IP_位置 = i # 设置'IP_位置'变量值为当前段下标值(数字int类型)
  439. if RE_MAC: # 如果在当前段中匹配到MAC地址
  440. #print(i, "is MAC:", 列表_首条记录分割[i])
  441. MAC_位置 = i # 设置'MAC_位置'变量值为当前段下标值(数字int类型)
  442. ## 逐行提取IP和MAC的值,做成字典形式
  443. if IP_位置 != '' and MAC_位置 != '': # 当'IP_位置'和'MAC_位置'都找到对应下标时
  444. for i in 列表_绑定信息: # 遍历每一条绑定记录
  445. #print("每行内容", i)
  446. SP = i.split() # 绑定记录以空格分段成列表
  447. #print("SP", SP)
  448. IP = SP[IP_位置] # 根据已知下标提取IP的值
  449. MAC = SP[MAC_位置] # 根据已知下标提取MAC的值
  450. if IP not in D_IP_MAC: # 如果当前IP不在D_IP_MAC字典中
  451. D_IP_MAC[IP] = [MAC] # 向D_IP_MAC字典中添加此对键值对,MAC做成列表形式
  452. else: # 如果当前IP已经存在D_IP_MAC字典中
  453. D_IP_MAC[IP].append(MAC) # 把MAC添加到对应键值对中
  454. #print("D_IP_MAC", D_IP_MAC)
  455. return(D_IP_MAC) # 返回制作好的字典,如果没有绑定记录也会返回空字典
  456. else: # 当'IP_位置'和'MAC_位置'任意一个没有找到对应下标时
  457. return(D_IP_MAC) # 直接返回空字典
  458. else:
  459. return(D_IP_MAC) # 回显结果中没有找到任何IP和MAC的绑定记录,直接返回空字典
  460. ###############################################################################################################################
  461. ###############################################################################################################################
  462. ## 功能函数:从查询静态绑定信息命令回显中提取以MAC为KEY以IP为值的字典
  463. ## 参数 S_DATA 执行交互命令后的回显内容
  464. ## 把如下字符串内容
  465. ## dis cu | include user-bind static
  466. ## user-bind static ip-address 1.1.1.1 mac-address 0000-1111-2222
  467. ## user-bind static ip-address 1.1.1.1 mac-address 0000-0000-0001
  468. ## user-bind static ip-address 1.1.1.2 mac-address 0000-0000-0002
  469. ## <Huawei>
  470. ## 转换成字典 {'0000-1111-2222': ['1.1.1.1'], '0000-0000-0001': ['1.1.1.1'], '0000-0000-0002': ['1.1.1.2']}
  471. def IP_MAC_绑定信息转成MAC为KEY字典(S_DATA):
  472. D_MAC_IP = {}
  473. 表达式 = '(.*)ip-address(.*)mac-address(.*)'
  474. RE_F = re.finditer(表达式, S_DATA)
  475. 列表_绑定信息 = [i.group() for i in RE_F]
  476. #print("列表_绑定信息", 列表_绑定信息)
  477. if 列表_绑定信息 != []:
  478. 首条记录 = 列表_绑定信息[0]
  479. 列表_首条记录分割 = 首条记录.split()
  480. IP表达式 = '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+'
  481. MAC表达式 = '[a-f0-9A-F]{4}\-[a-f0-9A-F]{4}\-[a-f0-9A-F]{4}'
  482. IP_位置 = ''
  483. MAC_位置 = ''
  484. for i in range(0, len(列表_首条记录分割)):
  485. RE_IP = re.search(IP表达式, 列表_首条记录分割[i])
  486. RE_MAC = re.search(MAC表达式, 列表_首条记录分割[i])
  487. if RE_IP:
  488. #print(i, "is IP:", 列表_首条记录分割[i])
  489. IP_位置 = i
  490. if RE_MAC:
  491. #print(i, "is MAC:", 列表_首条记录分割[i])
  492. MAC_位置 = i
  493. if IP_位置 != '' and MAC_位置 != '':
  494. for i in 列表_绑定信息:
  495. #print("每行内容", i)
  496. SP = i.split()
  497. #print("SP", SP)
  498. IP = SP[IP_位置]
  499. MAC = SP[MAC_位置]
  500. if MAC not in D_MAC_IP:
  501. D_MAC_IP[MAC] = [IP]
  502. else:
  503. D_MAC_IP[MAC].append(IP)
  504. #print("D_MAC_IP", D_MAC_IP)
  505. return(D_MAC_IP)
  506. else:
  507. return(D_MAC_IP)
  508. else:
  509. return(D_MAC_IP)
  510. ###############################################################################################################################
  511. ###############################################################################################################################
  512. ## 功能函数:在IP和MAC对应字典中是否出现IP和MAC绑定记录
  513. ## 参数 D 有IP和MAC对应关系的字典,可以是 D_IP_MAC 或 D_MAC_IP
  514. ## 参数 IP 点分十进制字符串类型IP地址
  515. ## 参数 MAC 连字符十六进制字符串类型MAC地址
  516. def 判断是否绑定成功(D, IP, MAC):
  517. if D == {}:
  518. E = '绑定失败:绑定记录是空字典'
  519. return(1,E)
  520. if IP in D: # 是以IP为key的字典格式
  521. if MAC in D[IP]:
  522. INFO = '绑定成功,当前 ' + IP + ' 的绑定MAC信息列表 ' + str(D[IP])
  523. return(0, INFO)
  524. else:
  525. ERROR = '绑定失败,当前 ' + IP + ' 的绑定MAC信息列表 ' + str(D[IP])
  526. return(1, ERROR)
  527. elif MAC in D: # 是以MAC为key的字典格式
  528. if IP in D[MAC]:
  529. INFO = '绑定成功,当前 ' + MAC + ' 的绑定IP信息列表 ' + str(D[MAC])
  530. return(0,INFO)
  531. else:
  532. ERROR = '绑定失败,当前 ' + MAC + ' 的绑定IP信息列表 ' + str(D[MAC])
  533. return(1, ERROR)
  534. else: # 没有IP或MAC的绑定记录
  535. ERROR = '绑定失败,没有 ' + IP + ' 或 ' + MAC + ' 的任何的绑定记录'
  536. return(1, ERROR)
  537. ###############################################################################################################################
  538. ###############################################################################################################################
  539. ## 功能函数 自动查找网段中可用IP_优先自增()
  540. ## 不填充中间有被删除绑定的IP地址空缺位置
  541. ## 新MAC分配的IP优先使用已经绑定的最大IP地址的后一个IP地址
  542. ## 在达到自动分配可用的最大IP后再填充中间空缺IP位置(从小开始填充)
  543. ###############################################################################################################################
  544. def 自动查找网段中可用IP_优先自增(NET_IP_STR, NET_MASK_INT, S_DATA, 网段开头保留地址数量=1, 网段末尾保留地址数量=1):
  545. ## 检查参数是否合法
  546. if 网段开头保留地址数量 < 0:
  547. ERROR = '函数参数 网段开头保留地址数量 小于0'
  548. return(1, ERROR)
  549. if 网段末尾保留地址数量 < 0:
  550. ERROR = '函数参数 网段末尾保留地址数量 小于0'
  551. return(1, ERROR)
  552. ## 计算可用IP地址范围及判断是否还有可自动分配IP地址
  553. NET_IP_MIN, NET_IP_MAX = 根据地址和掩码计算起始和结束地址(NET_IP_STR, NET_MASK_INT) ## 网段首末地址:网段号和广播号
  554. 可自动分配地址最小值 = NET_IP_MIN + 1 + 网段开头保留地址数量 ## 起始IP +1 排除网络号,再加上网段开头保留地址数量
  555. 可自动分配地址最大值 = NET_IP_MAX - 1 - 网段末尾保留地址数量 ## 结尾IP -1 避开广播号,再减去网段末尾保留地址数量
  556. #print("可自动分配地址最小值", 可自动分配地址最小值, IP_INT_2_IP_STR(可自动分配地址最小值))
  557. #print("可自动分配地址最大值", 可自动分配地址最大值, IP_INT_2_IP_STR(可自动分配地址最大值))
  558. Log.debug('可自动分配地址最小值:' + str(可自动分配地址最小值) + ' ' + IP_INT_2_IP_STR(可自动分配地址最小值))
  559. Log.debug('可自动分配地址最大值:' + str(可自动分配地址最大值) + ' ' + IP_INT_2_IP_STR(可自动分配地址最大值))
  560. if 可自动分配地址最小值 > 可自动分配地址最大值:
  561. ERROR = '没有可自动分配地址:保留地址过多 或 网段太小'
  562. return(1, ERROR)
  563. ## 开始查找可用IP地址
  564. 可用_IP_STR = ''
  565. ## 从 S_DATA 绑定信息中提取全部的IP地址
  566. D_IP_MAC = IP_MAC_绑定信息转成IP为KEY字典(S_DATA)
  567. L_BIND_IP_STR = [i for i in D_IP_MAC] ## 列表_已绑定的全部IP地址(字符形式)
  568. #print("L_BIND_IP_STR 已绑定使用地址", L_BIND_IP_STR)
  569. Log.debug('已绑定使用地址(IP_STR):' + str(L_BIND_IP_STR))
  570. L_BIND_IP_INT = [IP_STR_2_IP_INT(i) for i in L_BIND_IP_STR] ## 列表_已绑定的全部IP地址(数字形式)
  571. #print("L_BIND_IP_INT 已绑定使用地址", L_BIND_IP_INT)
  572. Log.debug('已绑定使用地址(IP_INT):' + str(L_BIND_IP_INT))
  573. ## 自动分配网段可用地址中已经被占用的地址:在已绑定的全部IP地址中有多少个是自动分配网段中可以使用的IP地址
  574. ## 如果没有,那自动分配网段中的全部地址都可以使用,直接取最小的用
  575. ## 如果有,
  576. 列表_网段已被占用地址 = [i for i in L_BIND_IP_INT if 可自动分配地址最小值<=i<=可自动分配地址最大值]
  577. #print("列表_网段已被占用地址", 列表_网段已被占用地址)
  578. Log.debug('列表_网段已被占用地址:' + str(列表_网段已被占用地址))
  579. if 列表_网段已被占用地址 == []:
  580. #print("网段", NET_IP_STR, NET_MASK_INT, "暂无绑定记录,直接使用网段中可自动分配地址的最小IP地址")
  581. Log.debug('网段' + NET_IP_STR +'/'+ str(NET_MASK_INT) + '暂无绑定记录,直接使用网段中可自动分配地址的最小IP地址')
  582. 可用_IP_INT = 可自动分配地址最小值 ## 直接使用网段中可自动分配地址的最小IP地址
  583. 可用_IP_STR = IP_INT_2_IP_STR(可用_IP_INT) ## 数字型IP地址转成字符型IP地址
  584. return(0, 可用_IP_STR)
  585. else:
  586. 网段已被占用地址_MAX = max(列表_网段已被占用地址) ## 提取网段中已经使用的最大IP值
  587. if 网段已被占用地址_MAX +1 <= 可自动分配地址最大值: ## 如果网段中已经使用的最大IP值增加1还自动分配可用地址范围内
  588. 可用_IP_INT = 网段已被占用地址_MAX +1 ## 可用IP就取网段中已经使用的最大IP的后一个IP地址
  589. 可用_IP_STR = IP_INT_2_IP_STR(可用_IP_INT)
  590. #print("使用已经绑定IP的后一个IP地址", 可用_IP_STR)
  591. Log.debug('使用已经绑定IP的后一个IP地址:' + 可用_IP_STR)
  592. return(0, 可用_IP_STR)
  593. else: ## 否则表示已经到顶,返回去看看有没有解绑掉的空缺IP地址
  594. #print("自增方式自动分配IP已经到顶,开始从头查看是否有已经解绑的空缺IP地址")
  595. 集合_网段已被占用地址 = set(列表_网段已被占用地址) ## 转成集合判断元素是否存在会快一点
  596. #print("集合_网段已被占用地址", 集合_网段已被占用地址)
  597. for i in range(可自动分配地址最小值, 可自动分配地址最大值+1): ## 从小到大遍历自动分配可用地址
  598. #print("遍历可网段中可自动分配IP地址", i, IP_INT_2_IP_STR(i))
  599. if i not in 集合_网段已被占用地址: ## 如果遍历到的这个IP地址不在已经绑定地址集合中
  600. 可用_IP_STR = IP_INT_2_IP_STR(i) ## 遍历到的这个IP地址就是可用地址,转成字符形式IP地址
  601. #print("找到空缺可用IP地址", 可用_IP_STR)
  602. Log.debug('找到空缺可用IP地址:' + 可用_IP_STR)
  603. break ## 找到了就终止循环
  604. ## 判断捡漏查找结果
  605. if 可用_IP_STR == '':
  606. ERROR = '无可用地址:网段可自动分配区间地址已经全部被使用,可以尝试扩大网段或减少保留地址数量'
  607. return(1, ERROR)
  608. else:
  609. return(0, 可用_IP_STR)
  610. ###############################################################################################################################
  611. ## 功能函数 自动查找网段中可用IP_自动填充()
  612. ## 在已用IP范围外和自动分配地址范围内找到最小可用IP
  613. ## 会填充自动分配地址范围内有被删除IP的空缺位置
  614. ###################################################
  615. def 自动查找网段中可用IP_自动填充(NET_IP_STR, NET_MASK_INT, S_DATA, 网段开头保留地址数量=1, 网段末尾保留地址数量=1):
  616. ## 检查参数是否合法
  617. if 网段开头保留地址数量 < 0:
  618. ERROR = '函数参数 网段开头保留地址数量 小于0'
  619. return(1, ERROR)
  620. if 网段末尾保留地址数量 < 0:
  621. ERROR = '函数参数 网段末尾保留地址数量 小于0'
  622. return(1, ERROR)
  623. ## 计算可用IP地址范围及判断是否还有可自动分配IP地址
  624. NET_IP_MIN, NET_IP_MAX = 根据地址和掩码计算起始和结束地址(NET_IP_STR, NET_MASK_INT) ## 网段首末地址:网段号和广播号
  625. 可自动分配地址最小值 = NET_IP_MIN + 1 + 网段开头保留地址数量 ## 起始IP +1 排除网络号,再加上网段开头保留地址数量
  626. 可自动分配地址最大值 = NET_IP_MAX - 1 - 网段末尾保留地址数量 ## 结尾IP -1 避开广播号,再减去网段末尾保留地址数量
  627. #print("可自动分配地址最小值", 可自动分配地址最小值, IP_INT_2_IP_STR(可自动分配地址最小值))
  628. #print("可自动分配地址最大值", 可自动分配地址最大值, IP_INT_2_IP_STR(可自动分配地址最大值))
  629. Log.debug('可自动分配地址最小值:' + str(可自动分配地址最小值) + ' ' + IP_INT_2_IP_STR(可自动分配地址最小值))
  630. Log.debug('可自动分配地址最大值:' + str(可自动分配地址最大值) + ' ' + IP_INT_2_IP_STR(可自动分配地址最大值))
  631. if 可自动分配地址最小值 > 可自动分配地址最大值:
  632. ERROR = '没有可自动分配地址:保留地址过多 或 网段太小'
  633. return(1, ERROR)
  634. ## 开始查找可用IP地址
  635. 可用_IP_STR = ''
  636. ## 从 S_DATA 绑定信息中提取全部的IP地址
  637. D_IP_MAC = IP_MAC_绑定信息转成IP为KEY字典(S_DATA)
  638. L_BIND_IP_STR = [i for i in D_IP_MAC] ## 列表_已绑定的全部IP地址(字符形式)
  639. #print("L_BIND_IP_STR 已绑定使用地址", L_BIND_IP_STR)
  640. Log.debug('已绑定使用地址(IP_STR):' + str(L_BIND_IP_STR))
  641. L_BIND_IP_INT = [IP_STR_2_IP_INT(i) for i in L_BIND_IP_STR] ## 列表_已绑定的全部IP地址(数字形式)
  642. #print("L_BIND_IP_INT 已绑定使用地址", L_BIND_IP_INT)
  643. Log.debug('已绑定使用地址(IP_INT):' + str(L_BIND_IP_INT))
  644. ## 从小到大遍历可以自动分配的地址范围,判断是否被使用,尝试找出没有被使用的最小IP,作为自动绑定的可用IP
  645. 列表_网段已被占用地址 = [i for i in L_BIND_IP_INT if 可自动分配地址最小值<=i<=可自动分配地址最大值]
  646. #print("列表_网段已被占用地址", 列表_网段已被占用地址)
  647. 集合_网段已被占用地址 = set(列表_网段已被占用地址) ## 转成集合判断元素是否存在会快一点
  648. #print("集合_网段已被占用地址", 集合_网段已被占用地址)
  649. for i in range(可自动分配地址最小值, 可自动分配地址最大值+1): ## 从小到大遍历自动分配可用地址
  650. #print("遍历可网段中可自动分配IP地址", i, IP_INT_2_IP_STR(i))
  651. if i not in 集合_网段已被占用地址: ## 如果遍历到的这个IP地址不在已经绑定地址集合中
  652. 可用_IP_STR = IP_INT_2_IP_STR(i) ## 遍历到的这个IP地址就是可用地址,转成字符形式IP地址
  653. #print("找到空缺可用IP地址", 可用_IP_STR)
  654. Log.debug('找到空缺可用IP地址:' + 可用_IP_STR)
  655. break ## 找到了就终止循环
  656. ## 判断捡漏查找结果
  657. if 可用_IP_STR == '':
  658. ERROR = '无可用地址:网段可自动分配区间地址已经全部被使用,可以尝试扩大网段或减少保留地址数量'
  659. return(1, ERROR)
  660. else:
  661. return(0, 可用_IP_STR)
  662. ###############################################################################################################################
  663. '''
  664. ########################
  665. ## 任务函数,完成任务 ##
  666. ########################
  667. '''
  668. ####################################################################################################
  669. ## 任务函数:保存配置()
  670. ####################################################################################################
  671. ## 任务控制部分(负责检查参数,控制SSH连接的打开和关闭,调用相应交互操作命令执行任务)
  672. def 保存配置(D_LOGIN_INFO):
  673. 测试结果,结果说明 = TEST_D_LOGIN_INFO(D_LOGIN_INFO)
  674. if 测试结果 == 0:
  675. R = SSH_LOGIN(D_LOGIN_INFO) # 尝试登录SSH设备
  676. if R[0] == 0: # 登录成功
  677. SSH = R[1] # 获取SSH连接对象
  678. SHELL = R[2] # 获取可交互操作的子SHELL对象
  679. RR = SHELL_SAVE(SSH, SHELL) # 调用相应交互操作命令执行任务
  680. SSH.close() # 任务完成后断开SSH连接
  681. return(RR) # 把任务执行结果返回给上级函数
  682. else:
  683. return(1, R[1]) # 返回失败代码和错误信息
  684. else:
  685. return(1, 结果说明)
  686. ## 任务实现部分(执行交互操作命令,根据回显结果进行处理,返回处理状态和处理结果,DEBUG日志)
  687. def SHELL_SAVE(SSH, SHELL):
  688. ## 判断当前是否是<>模式
  689. CMD = 'display clock' # 任意命令,拿到回显最后一行,判断是 <> 还是 []
  690. S_DATA = SHELL_CMD(SHELL, CMD, 0.5)
  691. Log.debug('函数 SHELL_SAVE() 的 display clock 命令回显:' + S_DATA)
  692. code,data = 返回查看模式(S_DATA, SHELL, 最大深度=5) # 调用 返回查看模式() 这个交换机需要在查看模式才能保存配置
  693. if code == 0:
  694. Log.debug(data + '开始执行 save 命令')
  695. CMD = 'save'
  696. S_DATA = SHELL_CMD(SHELL, CMD, 0.5)
  697. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 ' + CMD + ' 命令回显:' + S_DATA)
  698. 正则表达式 = '(.*)Are you sure to continue(.*)'
  699. RE_S = re.search(正则表达式, S_DATA)
  700. if RE_S:
  701. CMD = 'y'
  702. S_DATA = SHELL_CMD(SHELL, CMD, 2)
  703. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 ' + CMD + ' 命令回显:' + S_DATA)
  704. ## 如果遇到保存名字,直接回车
  705. 正则表达式 = '(.*)Please input the file name(.*)'
  706. RE_S = re.search(正则表达式, S_DATA)
  707. if RE_S:
  708. CMD = '' ## 无命令,会直接输入回车
  709. S_DATA = SHELL_CMD(SHELL, CMD, 2)
  710. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 ' + CMD + ' 命令回显:' + S_DATA)
  711. ## 查看是否出现保存成功的字样,部分机器慢,需要设置一个长一点的等待时间
  712. 保存成功字符串 = re.search('(.*)successfully(.*)', S_DATA) # 检查回显中是否有成功字样出现
  713. if 保存成功字符串:
  714. INFO = '保存成功'
  715. return(0, INFO)
  716. else:
  717. ERROR = '未发现successfully字符,可能保存时间过久,命令暂停时间不够,请开启日志DEBUG模式查看操作过程'
  718. return(1, ERROR)
  719. else:
  720. ERROR = '回显内容中没有匹配到' + 正则表达式
  721. return(1, ERROR)
  722. else:
  723. ERROR = '返回<查看模式失败>失败信息:' + data
  724. return(1, ERROR)
  725. ####################################################################################################
  726. ####################################################################################################
  727. ## 任务函数:获取IP和MAC绑定信息()
  728. ####################################################################################################
  729. ## 任务控制部分(负责检查参数,控制SSH连接的打开和关闭,调用相应交互操作命令执行任务)
  730. def 获取IP和MAC绑定信息(D_LOGIN_INFO):
  731. 测试结果,结果说明 = TEST_D_LOGIN_INFO(D_LOGIN_INFO)
  732. if 测试结果 == 0:
  733. R = SSH_LOGIN(D_LOGIN_INFO)
  734. if R[0] == 0:
  735. SSH = R[1]
  736. SHELL = R[2]
  737. RR = SHELL_D_IP_MAC(SSH, SHELL)
  738. SSH.close()
  739. return(RR)
  740. else:
  741. return(1, R[1])
  742. else:
  743. return(1, 结果说明)
  744. ## 任务实现部分(执行交互操作命令,根据回显结果进行处理,返回处理状态和处理结果,DEBUG日志)
  745. def SHELL_D_IP_MAC(SSH, SHELL):
  746. CMD = 'screen-length 0 temporary'
  747. S_DATA = SHELL_CMD(SHELL, CMD, 0.3)
  748. CMD = 'dis cu | include user-bind static' # 准备设备执行交互命令:查看IP和MAC绑定信息
  749. S_DATA = SHELL_CMD(SHELL, CMD, 2)
  750. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 ' + CMD + ' 命令回显:' + S_DATA) ## DEBUG
  751. D_IP_MAC = IP_MAC_绑定信息转成IP为KEY字典(S_DATA) # 调用功能函数处理回显内容
  752. return(0,D_IP_MAC) # 返回成功代码和处理结果
  753. ####################################################################################################
  754. ####################################################################################################
  755. ## 任务函数:绑定指定IP和指定MAC()
  756. ####################################################################################################
  757. ## 任务控制部分(负责检查参数,控制SSH连接的打开和关闭,调用相应交互操作命令执行任务)
  758. def 绑定指定IP和指定MAC(D_LOGIN_INFO, Bind_IP, Bind_MAC):
  759. ## 检查参数IP地址是否合法
  760. IP_TEST = TEST_IP_STR(Bind_IP)
  761. if IP_TEST[0] != 0:
  762. return(IP_TEST) # 不合法立即终止
  763. ## 检查参数MAC地址是否合法
  764. R_TRY = TRY_MAC_2_MAC(Bind_MAC, 转换格式='xxxx-xxxx-xxxx')
  765. if R_TRY[0] != 0:
  766. return(R_TRY) # 不合法立即终止
  767. else:
  768. Bind_MAC = R_TRY[1] # 不管用户输入什么格式,都转成'xxxx-xxxx-xxxx'格式
  769. 测试结果,结果说明 = TEST_D_LOGIN_INFO(D_LOGIN_INFO)
  770. if 测试结果 == 0:
  771. R = SSH_LOGIN(D_LOGIN_INFO)
  772. if R[0] == 0:
  773. SSH = R[1]
  774. SHELL = R[2]
  775. RR = SHELL_Bind_IP_MAC(SSH, SHELL, Bind_IP, Bind_MAC)
  776. SSH.close()
  777. return(RR)
  778. else:
  779. return(1, R[1])
  780. else:
  781. return(1, 结果说明)
  782. ## 任务实现部分(执行交互操作命令,根据回显结果进行处理,返回处理状态和处理结果,DEBUG日志)
  783. def SHELL_Bind_IP_MAC(SSH, SHELL, Bind_IP, Bind_MAC):
  784. ## 开始按顺序执行交互命令
  785. CMD = 'screen-length 0 temporary'
  786. S_DATA = SHELL_CMD(SHELL, CMD, 0.5)
  787. CMD = 'sys' # 准备设备执行交互命令:进入配置模式
  788. S_DATA = SHELL_CMD(SHELL, CMD, 0.5)
  789. CMD = 'user-bind static ip-address ' + Bind_IP + ' mac-address ' + Bind_MAC # 准备设备执行交互命令:绑定IP和MAC
  790. S_DATA = SHELL_CMD(SHELL, CMD, 0.5)
  791. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 ' + CMD + ' 命令回显:' + S_DATA) ## DEBUG
  792. ## 判断此次绑定任务是否成功
  793. CMD = 'dis cu | include user-bind static ip-address ' + Bind_IP # 准备设备执行交互命令:检查是否成功绑定
  794. S_DATA = SHELL_CMD(SHELL, CMD, 1)
  795. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 ' + CMD + ' 命令回显:' + S_DATA) ## DEBUG
  796. D_IP_MAC = IP_MAC_绑定信息转成IP为KEY字典(S_DATA)
  797. RR = 判断是否绑定成功(D_IP_MAC, Bind_IP, Bind_MAC)
  798. return(RR)
  799. ####################################################################################################
  800. ####################################################################################################
  801. ## 任务函数:在指定网段自动选择可用IP和指定MAC绑定()
  802. ####################################################################################################
  803. ## 任务控制部分(负责检查参数,控制SSH连接的打开和关闭,调用相应交互操作命令执行任务)
  804. def 在指定网段自动选择可用IP和指定MAC绑定(D_LOGIN_INFO, Bind_NET, Bind_MAC):
  805. ## 检查参数,尝试把字符串表示的网段转成网段IP_STR和掩码MASK_INT
  806. R_TRY_NET = TRY_NET_STR_2_IP_MASK(Bind_NET)
  807. if R_TRY_NET[0] != 0:
  808. return(1, R_TRY_NET[1])
  809. else:
  810. Bind_NET_IP_STR = R_TRY_NET[1][0]
  811. Bind_NET_MASK_INT = R_TRY_NET[1][1]
  812. ## 检查参数,尝试把用户输入的MAC地址转成交换机常用MAC格式
  813. R_TRY_MAC = TRY_MAC_2_MAC(Bind_MAC, 转换格式='xxxx-xxxx-xxxx')
  814. if R_TRY_MAC[0] != 0:
  815. return(1, R_TRY_MAC[1])
  816. else:
  817. Bind_MAC = R_TRY_MAC[1]
  818. 测试结果,结果说明 = TEST_D_LOGIN_INFO(D_LOGIN_INFO)
  819. if 测试结果 == 0:
  820. R = SSH_LOGIN(D_LOGIN_INFO)
  821. if R[0] == 0:
  822. SSH = R[1]
  823. SHELL = R[2]
  824. RR = SHELL_Bind_NET_MAC(SSH, SHELL, Bind_NET_IP_STR, Bind_NET_MASK_INT, Bind_MAC)
  825. SSH.close()
  826. return(RR)
  827. else:
  828. return(1, R[1])
  829. else:
  830. return(1, 结果说明)
  831. ## 任务实现部分(执行交互操作命令,根据回显结果进行处理,返回处理状态和处理结果,DEBUG日志)
  832. def SHELL_Bind_NET_MAC(SSH, SHELL, Bind_NET_IP_STR, Bind_NET_MASK_INT, Bind_MAC):
  833. ## 开始按顺序执行交互命令
  834. CMD = 'screen-length 0 temporary'
  835. S_DATA = SHELL_CMD(SHELL, CMD, 0.5)
  836. CMD = 'sys'
  837. S_DATA = SHELL_CMD(SHELL, CMD, 0.5)
  838. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 ' + CMD + ' 命令回显:' + S_DATA) ## DEBUG
  839. CMD = 'dis cu | include user-bind static'
  840. S_DATA = SHELL_CMD(SHELL, CMD, 2)
  841. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 ' + CMD + ' 命令回显:' + S_DATA) ## DEBUG
  842. 状态_搜索可用IP, 结果_搜索可用IP = 自动查找网段中可用IP_优先自增(Bind_NET_IP_STR, Bind_NET_MASK_INT, S_DATA)
  843. if 状态_搜索可用IP == 0:
  844. Bind_IP = 结果_搜索可用IP
  845. RR = SHELL_Bind_IP_MAC(SSH, SHELL, Bind_IP, Bind_MAC)
  846. return(RR)
  847. else:
  848. return(1, 结果_搜索可用IP)
  849. ####################################################################################################
  850. ####################################################################################################
  851. ## 任务函数:查找MAC地址所在网段()
  852. ####################################################################################################
  853. ## 任务控制部分(负责检查参数,控制SSH连接的打开和关闭,调用相应交互操作命令执行任务)
  854. def 查找MAC地址所在网段(D_LOGIN_INFO, MAC):
  855. R_TRY_MAC = TRY_MAC_2_MAC(MAC, 转换格式='xxxx-xxxx-xxxx')
  856. if R_TRY_MAC[0] != 0:
  857. return(1, R_TRY_MAC[1])
  858. else:
  859. MAC = R_TRY_MAC[1]
  860. 测试结果,结果说明 = TEST_D_LOGIN_INFO(D_LOGIN_INFO)
  861. if 测试结果 == 0:
  862. R = SSH_LOGIN(D_LOGIN_INFO)
  863. if R[0] == 0:
  864. SSH = R[1]
  865. SHELL = R[2]
  866. RR = SHELL_MAC_IN_VLAN(SSH, SHELL, MAC)
  867. SSH.close()
  868. return(RR)
  869. else:
  870. return(1, R[1])
  871. else:
  872. return(1, 结果说明)
  873. ## 任务实现部分(执行交互操作命令,根据回显结果进行处理,返回处理状态和处理结果,DEBUG日志)
  874. def SHELL_MAC_IN_VLAN(SSH, SHELL, MAC):
  875. CMD = 'display mac-address ' + MAC
  876. S_DATA = SHELL_CMD(SHELL, CMD, 1)
  877. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 ' + CMD + ' 命令回显:' + S_DATA) ## DEBUG
  878. D_MAC_VLAN = MAC缓存信息转成MAC对应VLAN字典(S_DATA)
  879. if MAC in D_MAC_VLAN:
  880. 列表_VLAN = D_MAC_VLAN[MAC]
  881. if len(列表_VLAN) == 1:
  882. VLAN_ID_STR = 列表_VLAN[0]
  883. return(0, VLAN_ID_STR)
  884. else:
  885. E = 'MAC地址 ' + str(MAC) + ' 在VLAN ' + str(列表_VLAN) + ' 间漂移,当前无法确定VLAN号'
  886. return(1, E)
  887. else:
  888. E = '在MAC地址缓存中没有找到 ' + str(MAC)
  889. return(1, E)
  890. ####################################################################################################
  891. ####################################################################################################
  892. ## 任务函数:在MAC所在网段自动选择可用IP和进行绑定()
  893. ####################################################################################################
  894. ## 任务控制部分(负责检查参数,控制SSH连接的打开和关闭,调用相应交互操作命令执行任务)
  895. def 在MAC所在网段自动选择可用IP和进行绑定(D_LOGIN_INFO, Bind_MAC):
  896. R_TRY_MAC = TRY_MAC_2_MAC(Bind_MAC, 转换格式='xxxx-xxxx-xxxx')
  897. if R_TRY_MAC[0] != 0:
  898. return(1, R_TRY_MAC[1])
  899. else:
  900. Bind_MAC = R_TRY_MAC[1]
  901. 测试结果,结果说明 = TEST_D_LOGIN_INFO(D_LOGIN_INFO)
  902. if 测试结果 == 0:
  903. R = SSH_LOGIN(D_LOGIN_INFO)
  904. if R[0] == 0:
  905. SSH = R[1]
  906. SHELL = R[2]
  907. RR = SHELL_AUTO_Bind_MAC(SSH, SHELL, Bind_MAC)
  908. SSH.close()
  909. return(RR)
  910. else:
  911. return(1, R[1])
  912. else:
  913. return(1, 结果说明)
  914. ## 任务实现部分(执行交互操作命令,根据回显结果进行处理,返回处理状态和处理结果,DEBUG日志)
  915. def SHELL_AUTO_Bind_MAC(SSH, SHELL, Bind_MAC):
  916. CMD = 'screen-length 0 temporary'
  917. S_DATA = SHELL_CMD(SHELL, CMD, 0.3)
  918. CMD = 'display ip interface brief' # 交换机命令:查看VLAN的接口IP
  919. S_DATA = SHELL_CMD(SHELL, CMD, 1)
  920. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 ' + CMD + ' 命令回显:' + S_DATA) ## DEBUG
  921. D_VLAN_IP_MASK = VLAN和NET字典(S_DATA)
  922. if D_VLAN_IP_MASK == {}:
  923. E = '查不到任何VLAN的接口IP'
  924. return(1,E)
  925. CMD = 'display mac-address ' + Bind_MAC # 交换机命令:查找MAC的网络信息
  926. S_DATA = SHELL_CMD(SHELL, CMD, 1)
  927. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 ' + CMD + ' 命令回显:' + S_DATA) ## DEBUG
  928. D_MAC_VLAN = MAC缓存信息转成MAC对应VLAN字典(S_DATA)
  929. if Bind_MAC in D_MAC_VLAN:
  930. #print(Bind_MAC, "VLAN缓存记录", D_MAC_VLAN[Bind_MAC])
  931. 列表_VLAN = D_MAC_VLAN[Bind_MAC]
  932. if len(列表_VLAN) == 1:
  933. #print("查VLAN网段")
  934. S_VLAN_ID = 'Vlanif' + 列表_VLAN[0]
  935. if S_VLAN_ID in D_VLAN_IP_MASK:
  936. Bind_NET = D_VLAN_IP_MASK[S_VLAN_ID][0] # 例 ['192.168.0.1/24'] 取出 '192.168.0.1/24'
  937. Bind_NET_SP = Bind_NET.split('/')
  938. Bind_NET_IP_STR = Bind_NET_SP[0]
  939. Bind_NET_MASK_INT = int(Bind_NET_SP[1])
  940. RR = SHELL_Bind_NET_MAC(SSH, SHELL, Bind_NET_IP_STR, Bind_NET_MASK_INT, Bind_MAC)
  941. return(RR)
  942. else:
  943. E = 'VLAN ' + S_VLAN_ID + ' 没有接口IP地址'
  944. return(1,E)
  945. else:
  946. E = 'MAC地址 ' + str(Bind_MAC) + ' 在VLAN' + str(列表_VLAN) + '间漂移,当前无法确定VLAN号'
  947. return(1,E)
  948. else:
  949. E = '在MAC地址缓存中没有找到 ' + str(MAC)
  950. return(1,E)
  951. ####################################################################################################
  952. ####################################################################################################
  953. ## 任务函数:解除指定IP和指定MAC的绑定()
  954. ####################################################################################################
  955. ## 任务控制部分(负责检查参数,控制SSH连接的打开和关闭,调用相应交互操作命令执行任务)
  956. def 解除指定IP和指定MAC的绑定(D_LOGIN_INFO, Undo_Bind_IP, Undo_Bind_MAC):
  957. ## 检查参数IP地址是否合法
  958. IP_TEST = TEST_IP_STR(Undo_Bind_IP)
  959. if IP_TEST[0] != 0:
  960. return(IP_TEST) # 不合法立即终止
  961. ## 检查参数MAC地址是否合法
  962. R_TRY = TRY_MAC_2_MAC(Undo_Bind_MAC, 转换格式='xxxx-xxxx-xxxx')
  963. if R_TRY[0] != 0:
  964. return(R_TRY) # 不合法立即终止
  965. else:
  966. Undo_Bind_MAC = R_TRY[1] # 不管用户输入什么格式,都转成'xxxx-xxxx-xxxx'格式
  967. 测试结果,结果说明 = TEST_D_LOGIN_INFO(D_LOGIN_INFO)
  968. if 测试结果 == 0:
  969. R = SSH_LOGIN(D_LOGIN_INFO)
  970. if R[0] == 0:
  971. SSH = R[1]
  972. SHELL = R[2]
  973. RR = SHELL_UNDO_Bind_IP_MAC(SSH, SHELL, Undo_Bind_IP, Undo_Bind_MAC)
  974. SSH.close()
  975. return(RR)
  976. else:
  977. return(1, R[1])
  978. else:
  979. return(1, 结果说明)
  980. ## 任务实现部分(执行交互操作命令,根据回显结果进行处理,返回处理状态和处理结果,DEBUG日志)
  981. def SHELL_UNDO_Bind_IP_MAC(SSH, SHELL, Undo_Bind_IP, Undo_Bind_MAC):
  982. CMD = 'sys'
  983. S_DATA = SHELL_CMD(SHELL, CMD, 0.5)
  984. CMD = 'dis cu | include user-bind static ip-address ' + Undo_Bind_IP
  985. S_DATA = SHELL_CMD(SHELL, CMD, 1)
  986. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 ' + CMD + ' 命令回显:' + S_DATA) ## DEBUG
  987. D_IP_MAC = IP_MAC_绑定信息转成IP为KEY字典(S_DATA)
  988. if Undo_Bind_IP in D_IP_MAC:
  989. if Undo_Bind_MAC in D_IP_MAC[Undo_Bind_IP]:
  990. CMD = 'undo user-bind static ip-address ' + Undo_Bind_IP + ' mac-address ' + Undo_Bind_MAC
  991. S_DATA = SHELL_CMD(SHELL, CMD, 1)
  992. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 ' + CMD + ' 命令回显:' + S_DATA) ## DEBUG
  993. CMD = 'dis cu | include user-bind static ip-address ' + Undo_Bind_IP
  994. S_DATA = SHELL_CMD(SHELL, CMD, 1)
  995. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 ' + CMD + ' 命令回显:' + S_DATA) ## DEBUG
  996. D_IP_MAC_复查 = IP_MAC_绑定信息转成IP为KEY字典(S_DATA)
  997. if Undo_Bind_IP in D_IP_MAC_复查:
  998. if Undo_Bind_MAC in D_IP_MAC_复查[Undo_Bind_IP]:
  999. ERROR = 'ERROR IP ' + Undo_Bind_IP + ' 和 ' + Undo_Bind_MAC + ' 解绑失败'
  1000. return(1,ERROR)
  1001. else:
  1002. INFO = 'INFO IP ' + Undo_Bind_IP + ' 和 ' + Undo_Bind_MAC + ' 解绑成功,剩余MAC绑定 ' + str(D_IP_MAC_复查[Undo_Bind_IP])
  1003. return(0,INFO)
  1004. else:
  1005. INFO = 'INFO IP ' + Undo_Bind_IP + ' 解绑成功,且已无MAC绑定记录'
  1006. return(0,INFO)
  1007. else:
  1008. WARNING = 'WARNING IP ' + Undo_Bind_IP + ' 原先就没有和 ' + Undo_Bind_MAC + '的绑定记录'
  1009. return(0,WARNING)
  1010. else:
  1011. WARNING = 'WARNING IP ' + Undo_Bind_IP + ' 原先就无MAC绑定记录'
  1012. return(0,WARNING)
  1013. ####################################################################################################
  1014. ####################################################################################################
  1015. ## 任务函数:解除指定IP的全部MAC绑定()
  1016. ####################################################################################################
  1017. ## 任务控制部分(负责打开和关闭SSH连接,调用相应交互操作命令)
  1018. def 解除指定IP的全部MAC绑定(D_LOGIN_INFO, Undo_Bind_IP):
  1019. ## 检查参数IP地址是否合法
  1020. IP_TEST = TEST_IP_STR(Undo_Bind_IP)
  1021. if IP_TEST[0] != 0:
  1022. return(IP_TEST) # 不合法立即终止
  1023. 测试结果,结果说明 = TEST_D_LOGIN_INFO(D_LOGIN_INFO)
  1024. if 测试结果 == 0:
  1025. R = SSH_LOGIN(D_LOGIN_INFO)
  1026. if R[0] == 0:
  1027. SSH = R[1]
  1028. SHELL = R[2]
  1029. RR = SHELL_UNDO_Bind_IP(SSH, SHELL, Undo_Bind_IP)
  1030. SSH.close()
  1031. return(RR)
  1032. else:
  1033. return(1, R[1])
  1034. else:
  1035. return(1, 结果说明)
  1036. ## 任务实现部分(执行交互操作命令,根据回显结果进行处理,返回处理状态和处理结果)
  1037. def SHELL_UNDO_Bind_IP(SSH, SHELL, Undo_Bind_IP):
  1038. CMD = 'screen-length 0 temporary'
  1039. S_DATA = SHELL_CMD(SHELL, CMD, 0.5)
  1040. CMD = 'sys'
  1041. S_DATA = SHELL_CMD(SHELL, CMD, 0.5)
  1042. CMD = 'dis cu | include user-bind static ip-address ' + Undo_Bind_IP
  1043. S_DATA = SHELL_CMD(SHELL, CMD, 1)
  1044. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 ' + CMD + ' 命令回显:' + S_DATA) ## DEBUG
  1045. D_IP_MAC = IP_MAC_绑定信息转成IP为KEY字典(S_DATA)
  1046. if Undo_Bind_IP in D_IP_MAC:
  1047. for MAC in D_IP_MAC[Undo_Bind_IP]:
  1048. CMD = 'undo user-bind static ip-address ' + Undo_Bind_IP + ' mac-address ' + MAC
  1049. S_DATA = SHELL_CMD(SHELL, CMD, 1)
  1050. ## 复查删除结果
  1051. CMD = 'dis cu | include user-bind static ip-address ' + Undo_Bind_IP
  1052. S_DATA = SHELL_CMD(SHELL, CMD, 1)
  1053. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 ' + CMD + ' 命令回显:' + S_DATA) ## DEBUG
  1054. D_IP_MAC_复查 = IP_MAC_绑定信息转成IP为KEY字典(S_DATA)
  1055. if Undo_Bind_IP in D_IP_MAC_复查:
  1056. ERROR = 'ERROR IP ' + Undo_Bind_IP + ' 解绑全部MAC失败,剩余MAC绑定 ' + str(D_IP_MAC_复查[Undo_Bind_IP])
  1057. return(1,ERROR)
  1058. else:
  1059. INFO = 'INFO IP ' + Undo_Bind_IP + ' 解绑全部MAC成功,已解除绑定的MAC列表 ' + str(D_IP_MAC[Undo_Bind_IP])
  1060. return(0,INFO)
  1061. else:
  1062. WARNING = 'WARNING IP ' + Undo_Bind_IP + ' 原先就无MAC绑定记录'
  1063. return(0,WARNING)
  1064. ####################################################################################################
  1065. ####################################################################################################
  1066. ## 任务函数:解除指定MAC的全部IP绑定()
  1067. ####################################################################################################
  1068. ## 任务控制部分(负责打开和关闭SSH连接,调用相应交互操作命令)
  1069. def 解除指定MAC的全部IP绑定(D_LOGIN_INFO, Undo_Bind_MAC):
  1070. ## 检查参数MAC地址是否合法
  1071. R_TRY = TRY_MAC_2_MAC(Undo_Bind_MAC, 转换格式='xxxx-xxxx-xxxx')
  1072. if R_TRY[0] != 0:
  1073. return(R_TRY) # 不合法立即终止
  1074. else:
  1075. Undo_Bind_MAC = R_TRY[1] # 不管用户输入什么格式,都转成'xxxx-xxxx-xxxx'格式
  1076. 测试结果,结果说明 = TEST_D_LOGIN_INFO(D_LOGIN_INFO)
  1077. if 测试结果 == 0:
  1078. R = SSH_LOGIN(D_LOGIN_INFO)
  1079. if R[0] == 0:
  1080. SSH = R[1]
  1081. SHELL = R[2]
  1082. code,data = SHELL_UNDO_Bind_MAC(SSH, SHELL, Undo_Bind_MAC)
  1083. SSH.close()
  1084. return(code,data)
  1085. else:
  1086. return(1, R[1])
  1087. else:
  1088. return(1, 结果说明)
  1089. ## 任务实现部分(执行交互操作命令,根据回显结果进行处理,返回处理状态和处理结果)
  1090. def SHELL_UNDO_Bind_MAC(SSH, SHELL, Undo_Bind_MAC):
  1091. CMD = 'screen-length 0 temporary'
  1092. S_DATA = SHELL_CMD(SHELL, CMD, 0.5)
  1093. CMD = 'sys'
  1094. S_DATA = SHELL_CMD(SHELL, CMD, 0.5)
  1095. CMD = 'dis cu | include user-bind static'
  1096. S_DATA = SHELL_CMD(SHELL, CMD, 1)
  1097. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 ' + CMD + ' 命令回显:' + S_DATA) ## DEBUG
  1098. D_MAC_IP = IP_MAC_绑定信息转成MAC为KEY字典(S_DATA)
  1099. if Undo_Bind_MAC in D_MAC_IP:
  1100. for IP in D_MAC_IP[Undo_Bind_MAC]:
  1101. CMD = 'undo user-bind static ip-address ' + IP + ' mac-address ' + Undo_Bind_MAC
  1102. S_DATA = SHELL_CMD(SHELL, CMD, 1)
  1103. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 ' + CMD + ' 命令回显:' + S_DATA) ## DEBUG
  1104. ## 复查删除结果
  1105. CMD = 'dis cu | include user-bind static'
  1106. S_DATA = SHELL_CMD(SHELL, CMD, 1)
  1107. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 ' + CMD + ' 命令回显:' + S_DATA) ## DEBUG
  1108. D_MAC_IP_复查 = IP_MAC_绑定信息转成MAC为KEY字典(S_DATA)
  1109. if Undo_Bind_MAC in D_MAC_IP_复查:
  1110. ERROR = 'ERROR MAC ' + Undo_Bind_MAC + ' 解绑全部IP失败,剩余IP绑定 ' + str(D_MAC_IP_复查[Undo_Bind_MAC])
  1111. return(1,ERROR)
  1112. else:
  1113. INFO = 'INFO MAC ' + Undo_Bind_MAC + ' 解绑全部IP成功,已解除绑定的IP列表 ' + str(D_MAC_IP[Undo_Bind_MAC])
  1114. return(0,INFO)
  1115. else:
  1116. WARNING = 'WARNING MAC ' + Undo_Bind_MAC + ' 原先就无IP绑定记录'
  1117. return(0,WARNING)
  1118. ####################################################################################################

 

 

文件三代码:

  1. #_*_ coding:utf8 _*_
  2. from DEV_SNMP import * # 导入编写在另一个文件里的SNMP操作函数
  3. import sys # 本例中用于获取函数名写入日志文件
  4. import logging # 日志模块
  5. Log = logging.getLogger("__name__")
  6. ## 如果日志实例不存在,就使用本程序日志模块
  7. if not logging.FileHandler:
  8. formatter = logging.Formatter('%(asctime)s %(levelname)-8s : %(message)s') # 指定logger输出格式
  9. file_handler = logging.FileHandler("DEF_SNMP_eNSP_Switch_S5700.log") # 日志文件路径
  10. file_handler.setFormatter(formatter) # 可以通过setFormatter指定输出格式
  11. Log.addHandler(file_handler)
  12. Log.setLevel(logging.DEBUG)
  13. ## 函数调用关系
  14. '''
  15. DEF_SNMP_eNSP_Switch_S5700.py
  16. from DEV_SNMP import * # 需要导入编写DEV_SNMP.py文件里的SNMP操作函数
  17. import sys # 本文件中只用于获取函数名方便生成日志内容
  18. import logging # 日志模块
  19. SNMP_MAC_2_mac(SNMP_MAC) ## SNMP获取的MAC地址是 '00 00 00 00 00 00' 形式,需要转成 '0000-0000-0000' 形式
  20. SNMP_L_Bind_IP_STR(SNMP_PWD, SNMP_HOST) ## 获取静态绑定IP列表
  21. SNMP_L_Bind_MAC_STR(SNMP_PWD, SNMP_HOST) ## 获取静态绑定MAC列表
  22. SNMP_L_IF_IP_STR(SNMP_PWD, SNMP_HOST) ## 获取设备接口IP列表(VLAN接口、物理端口、特殊接口)
  23. SNMP_L_IF_MASK_STR(SNMP_PWD, SNMP_HOST) ## 获取设备接口IP的掩码列表(VLAN接口、物理端口、特殊接口)
  24. SNMP_L_IF_INDEX_STR(SNMP_PWD, SNMP_HOST) ## 获取设备接口编号(VLAN接口、物理端口、特殊接口)
  25. SNMP_D_IF_DESCR(SNMP_PWD, SNMP_HOST) ## 获取设备接口名称字典(VLAN接口、物理端口、特殊接口)## {'1':InLoopBack0, '2':'NULL0', '3':'Console9/0/0', '4':'MEth0/0/1', '5':'Vlanif1', '6':'GigabitEthernet0/0/1'}
  26. SNMP_生成以IP为键以MAC地址列表为值的字典(SNMP_PWD, SNMP_HOST) ## 以IP为键以MAC地址列表为值的字典 {IP_STR:[MAC_STR, MAC_STR]}
  27. SNMP_L_Bind_IP_STR(SNMP_PWD, SNMP_HOST)
  28. SNMP_L_Bind_MAC_STR(SNMP_PWD, SNMP_HOST)
  29. SNMP_MAC_2_mac(SNMP_MAC)
  30. SNMP_生成以VLAN为键以VLAN_IP_MASK列表为值的字典(SNMP_PWD, SNMP_HOST) ## D_VLAN_NET {VLAN_STR:[IP_STR/MASK_STR]}
  31. SNMP_L_IF_IP_STR(SNMP_PWD, SNMP_HOST)
  32. SNMP_L_IF_MASK_STR(SNMP_PWD, SNMP_HOST)
  33. SNMP_L_IF_INDEX_STR(SNMP_PWD, SNMP_HOST)
  34. SNMP_D_IF_DESCR(SNMP_PWD, SNMP_HOST)
  35. '''
  36. ## 全局变量 交换机 S5700 要用到的 OID
  37. OID_BIND_IP = '1.3.6.1.4.1.2011.5.25.112.1.14.1.12' # 静态绑定IP列表
  38. OID_BIND_MAC = '1.3.6.1.4.1.2011.5.25.112.1.14.1.11' # 静态绑定MAC列表
  39. OID_IF_IP_STR = '1.3.6.1.4.1.2011.5.25.41.1.2.1.1.1' # 设备接口IP列表(VLAN接口、物理端口、特殊接口)
  40. OID_IF_MASK_STR = '1.3.6.1.4.1.2011.5.25.41.1.2.1.1.3' # 设备接口IP的掩码列表(VLAN接口、物理端口、特殊接口)
  41. OID_IF_INDEX = '1.3.6.1.4.1.2011.5.25.41.1.2.1.1.2' # 设备接口编号(VLAN接口、物理端口、特殊接口)
  42. OID_IF_DESCR = 'IF-MIB::ifDescr' # 设备接口名称字典(VLAN接口、物理端口、特殊接口)
  43. ## SNMP获取的MAC地址是 '00 00 00 00 00 00' 形式,需要转成 '0000-0000-0000' 形式
  44. def SNMP_MAC_2_mac(SNMP_MAC):
  45. MAC = SNMP_MAC.replace(' ', '')
  46. mac = MAC.lower()
  47. mac_new = mac[0:4] +'-'+ mac[4:8] +'-'+ mac[8:12]
  48. return(mac_new)
  49. ## 获取静态绑定IP列表
  50. def SNMP_L_Bind_IP_STR(SNMP_PWD, SNMP_HOST):
  51. SNMP_OID = OID_BIND_IP
  52. (N, R) = SNMP_V2_R(SNMP_PWD, SNMP_HOST, SNMP_OID)
  53. if N == 0:
  54. if R.split(' = ')[-1] == 'No Such Object available on this agent at this OID':
  55. ERROR = '错误 OID ' + SNMP_OID
  56. return(1, ERROR)
  57. elif R.split(' = ')[-1] == 'No Such Instance currently exists at this OID':
  58. ## SNMP查询结果为空
  59. return(0, [])
  60. else:
  61. R_SP = R.split('\n')
  62. L_IP_STR = [i.split(': ')[-1] for i in R_SP]
  63. return(0, L_IP_STR)
  64. else:
  65. ERROR = 'SNMP命令执行失败:' + str(R)
  66. return(1, ERROR)
  67. ## 获取静态绑定MAC列表
  68. def SNMP_L_Bind_MAC_STR(SNMP_PWD, SNMP_HOST):
  69. SNMP_OID = OID_BIND_MAC
  70. (N, R) = SNMP_V2_R(SNMP_PWD, SNMP_HOST, SNMP_OID)
  71. if N == 0:
  72. if R.split(' = ')[-1] == 'No Such Object available on this agent at this OID':
  73. ERROR = '错误 OID ' + SNMP_OID
  74. return(1, ERROR)
  75. elif R.split(' = ')[-1] == 'No Such Instance currently exists at this OID':
  76. ## SNMP查询结果为空
  77. return(0, [])
  78. else:
  79. R_SP = R.split('\n')
  80. L_MAC_STR = [SNMP_MAC_2_mac(i.split(': ')[-1]) for i in R_SP]
  81. return(0, L_MAC_STR)
  82. else:
  83. ERROR = 'SNMP命令执行失败:' + str(R)
  84. return(1, ERROR)
  85. ## 获取设备接口IP列表(VLAN接口、物理端口、特殊接口)
  86. def SNMP_L_IF_IP_STR(SNMP_PWD, SNMP_HOST):
  87. SNMP_OID = OID_IF_IP_STR
  88. (N, R) = SNMP_V2_R(SNMP_PWD, SNMP_HOST, SNMP_OID)
  89. if N == 0:
  90. if R.split(' = ')[-1] == 'No Such Object available on this agent at this OID':
  91. ERROR = '错误 OID ' + SNMP_OID
  92. return(1, ERROR)
  93. elif R.split(' = ')[-1] == 'No Such Instance currently exists at this OID':
  94. ## SNMP查询结果为空
  95. return(0, [])
  96. else:
  97. R_SP = R.split('\n') ## 先用'\n'(换行符)分出每一条记录
  98. L_IP_STR = [i.split(': ')[-1] for i in R_SP] ## 再用': '(冒号加一空)分段并提取需要的值(最后一段)
  99. return(0, L_IP_STR)
  100. else:
  101. ERROR = 'SNMP命令执行失败:' + str(R)
  102. return(1, ERROR)
  103. ## 获取设备接口IP的掩码列表(VLAN接口、物理端口、特殊接口)
  104. def SNMP_L_IF_MASK_STR(SNMP_PWD, SNMP_HOST):
  105. SNMP_OID = OID_IF_MASK_STR
  106. (N, R) = SNMP_V2_R(SNMP_PWD, SNMP_HOST, SNMP_OID)
  107. if N == 0:
  108. if R.split(' = ')[-1] == 'No Such Object available on this agent at this OID':
  109. ERROR = '错误 OID ' + SNMP_OID
  110. return(1, ERROR)
  111. elif R.split(' = ')[-1] == 'No Such Instance currently exists at this OID':
  112. ## SNMP查询结果为空
  113. return(0, [])
  114. else:
  115. R_SP = R.split('\n')
  116. L_IF_MASK_STR = [i.split(': ')[-1] for i in R_SP]
  117. return(0, L_IF_MASK_STR)
  118. else:
  119. ERROR = 'SNMP命令执行失败:' + str(R)
  120. return(1, ERROR)
  121. ## 获取设备接口编号(VLAN接口、物理端口、特殊接口)
  122. def SNMP_L_IF_INDEX_STR(SNMP_PWD, SNMP_HOST):
  123. SNMP_OID = OID_IF_INDEX
  124. (N, R) = SNMP_V2_R(SNMP_PWD, SNMP_HOST, SNMP_OID)
  125. if N == 0:
  126. if R.split(' = ')[-1] == 'No Such Object available on this agent at this OID':
  127. ERROR = '错误 OID ' + SNMP_OID
  128. return(1, ERROR)
  129. elif R.split(' = ')[-1] == 'No Such Instance currently exists at this OID':
  130. ## SNMP查询结果为空
  131. return(0, [])
  132. else:
  133. R_SP = R.split('\n')
  134. L_IF_VLAN_STR = [i.split(': ')[-1] for i in R_SP]
  135. return(0, L_IF_VLAN_STR)
  136. else:
  137. ERROR = 'SNMP命令执行失败:' + str(R)
  138. return(1, ERROR)
  139. ## 获取设备接口名称字典(VLAN接口、物理端口、特殊接口)
  140. ## {'1':InLoopBack0, '2':'NULL0', '3':'Console9/0/0', '4':'MEth0/0/1', '5':'Vlanif1', '6':'GigabitEthernet0/0/1'}
  141. def SNMP_D_IF_DESCR(SNMP_PWD, SNMP_HOST):
  142. SNMP_OID = OID_IF_DESCR
  143. (N, R) = SNMP_V2_R(SNMP_PWD, SNMP_HOST, SNMP_OID)
  144. if N == 0:
  145. if R.split(' = ')[-1] == 'No Such Object available on this agent at this OID':
  146. ERROR = '错误 OID ' + SNMP_OID
  147. return(1, ERROR)
  148. elif R.split(' = ')[-1] == 'No Such Instance currently exists at this OID':
  149. ## SNMP查询结果为空
  150. return(0, {})
  151. else:
  152. D_IF_DESCR = {}
  153. R_SP = R.split('\n') ## 先用'\n'(换行符)分出每一条记录
  154. L_IF_DESCR = [i.split(': ')[-1] for i in R_SP] ## 再用': '(冒号加一空)分段并提取需要的值(最后一段)
  155. for i in range(0, len(L_IF_DESCR)):
  156. D_IF_DESCR[str(i+1)] = L_IF_DESCR[i]
  157. return(0, D_IF_DESCR)
  158. else:
  159. ERROR = 'SNMP命令执行失败:' + str(R)
  160. return(1, ERROR)
  161. ## D_IP_MAC
  162. ## 以IP为键以MAC地址列表为值的字典
  163. ## {IP_STR:[MAC_STR, MAC_STR]}
  164. ## {'x.x.x.x':['xxxx-xxxx-xxxx', 'xxxx-xxxx-xxxx']}
  165. ## {'10.0.0.1':['0000-0000-000a', '0000-0000-000b']}
  166. def SNMP_生成以IP为键以MAC地址列表为值的字典(SNMP_PWD, SNMP_HOST):
  167. (N_IP, R_IP) = SNMP_L_Bind_IP_STR(SNMP_PWD, SNMP_HOST)
  168. (N_MAC, R_MAC) = SNMP_L_Bind_MAC_STR(SNMP_PWD, SNMP_HOST)
  169. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 SNMP_L_Bind_IP_STR 调用结果:' + str(N_IP) + str(R_IP))
  170. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 SNMP_L_Bind_MAC_STR 调用结果:' + str(N_MAC) + str(R_MAC))
  171. if N_IP == 0:
  172. if N_MAC == 0:
  173. IP_List = R_IP
  174. MAC_List = R_MAC
  175. IP_List_Len = len(IP_List)
  176. MAC_List_Len = len(MAC_List)
  177. if IP_List_Len == MAC_List_Len:
  178. D_IP_MAC = {}
  179. for i in range(0, IP_List_Len):
  180. IP = IP_List[i]
  181. MAC = MAC_List[i]
  182. if IP not in D_IP_MAC:
  183. D_IP_MAC[IP] = [MAC]
  184. else:
  185. D_IP_MAC[IP].append(MAC)
  186. return(0, D_IP_MAC)
  187. else:
  188. E = '绑定记录IP和MAC不能一一对应,len(IP_List) != len(MAC_List)'
  189. return(1, E)
  190. else:
  191. E = '获取IP成功,获取MAC失败:' + R_MAC
  192. return(1, E)
  193. else:
  194. if N_MAC == 0:
  195. E = '获取MAC成功,获取IP失败:' + R_IP
  196. return(1, E)
  197. else:
  198. E = '获取IP失败:' + R_IP + ' 获取MAC失败:' + R_MAC
  199. return(1, E)
  200. ## D_VLAN_NET
  201. ## {VLAN_STR:[IP_STR/MASK_STR]}
  202. ## {'VlanifN':['x.x.x.x/x.x.x.x', 'x.x.x.x/x.x.x.x']}
  203. def SNMP_生成以VLAN为键以VLAN_IP_MASK列表为值的字典(SNMP_PWD, SNMP_HOST):
  204. D_VLAN_NET = {}
  205. (N_IP, R_IP) = SNMP_L_IF_IP_STR(SNMP_PWD, SNMP_HOST)
  206. (N_MASK, R_MASK) = SNMP_L_IF_MASK_STR(SNMP_PWD, SNMP_HOST)
  207. (N_INDEX, R_INDEX) = SNMP_L_IF_INDEX_STR(SNMP_PWD, SNMP_HOST)
  208. (N_DESCR, R_DESCR) = SNMP_D_IF_DESCR(SNMP_PWD, SNMP_HOST)
  209. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 SNMP_L_IF_IP_STR 调用结果:' + str(N_IP) + str(R_IP))
  210. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 SNMP_L_IF_MASK_STR 调用结果:' + str(N_MASK) + str(R_MASK))
  211. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 SNMP_L_IF_INDEX_STR 调用结果:' + str(N_INDEX) + str(R_INDEX))
  212. Log.debug('函数 ' + sys._getframe().f_code.co_name + ' 的 SNMP_D_IF_DESCR 调用结果:' + str(N_DESCR) + str(R_DESCR))
  213. if N_IP == N_MASK == N_INDEX == N_DESCR == 0:
  214. if len(R_IP) == len(R_MASK) == len(R_INDEX):
  215. for i in range(0, len(R_IP)):
  216. VLAN = R_INDEX[i]
  217. IP = R_IP[i]
  218. MASK = R_MASK[i]
  219. if VLAN in R_DESCR:
  220. KEY = R_DESCR[VLAN]
  221. VALUE = IP + '/' + MASK
  222. if KEY not in D_VLAN_NET:
  223. D_VLAN_NET[KEY] = [VALUE]
  224. else:
  225. D_VLAN_NET[KEY].append(VALUE)
  226. else:
  227. ERROR = 'VLAN ' + VLAN + ' 在设备中没有找到'
  228. return(1, ERROR)
  229. return(0, D_VLAN_NET)
  230. else:
  231. ERROR = 'IP MASK VLAN 数量不一致'
  232. return(1, ERROR)
  233. else:
  234. ERROR = '有错误 '
  235. if N_IP != 0:
  236. ERROR += R_IP
  237. if N_MASK != 0:
  238. ERROR += R_MASK
  239. if N_INDEX != 0:
  240. ERROR += R_INDEX
  241. if N_DESCR != 0:
  242. ERROR += R_DESCR
  243. return(1, ERROR)

 

文件四代码:

  1. #_*_ coding:utf8 _*_
  2. import paramiko # SSH 操作模块
  3. import time # 计时
  4. ## SSH_LOGIN
  5. ## 登录SSH设备成功不关闭会话,返回ssh连接对象和交互子shell对象,后续可以在登录状态继续操作
  6. def SSH_LOGIN(D_LOGIN_INFO):
  7. SSH_IP = D_LOGIN_INFO['SSH_IP']
  8. SSH_PORT = D_LOGIN_INFO['SSH_PORT']
  9. SSH_USER = D_LOGIN_INFO['SSH_USER']
  10. SSH_PASS = D_LOGIN_INFO['SSH_PASS']
  11. SSH = paramiko.SSHClient()
  12. SSH.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  13. try:
  14. SSH.connect(SSH_IP, SSH_PORT, SSH_USER, SSH_PASS) # 尝试登录SSH设备
  15. except Exception as e: # 登录失败
  16. E = '函数 SSH_LOGIN() 登录SSH设备失败 '+ str(e)
  17. return(1, E) # 返回错误代码1和失败原因
  18. else: # 登录成功
  19. SHELL = SSH.invoke_shell() # 使用伪终端(子shell)(交互操作界面需要用到)
  20. return(0, SSH, SHELL) # 返回成功代码0,ssh连接对象,交互子shell对象
  21. ## 函数 SHELL_CMD() 执行交互命令返回命令回显字符串
  22. def SHELL_CMD(SHELL, CMD, TIME=2, BUFF=10240): # 在交互子SHELL里执行操作命令并预设默认参数
  23. SHELL.sendall(str(CMD) + '\n') # 把命令转成字符串,防止类型不同不能相加
  24. time.sleep(TIME) # 命令执行后等待足够的时间(默认2秒)以接收回显内容
  25. B_DATA = SHELL.recv(BUFF) # 保存接收到的回显内容(字节码类型)(接收最大值默认为10240字节)
  26. S_DATA = B_DATA.decode('utf-8') # 回显内容转成字符串类型(使用UTF8编码)
  27. return(S_DATA)
  28. ## 函数 SHELL_CTRL() 执行控制命令返回命令回显字符串
  29. def SHELL_CTRL(SHELL, CTRL, TIME=2, BUFF=10240):
  30. SHELL.sendall(CTRL)
  31. time.sleep(TIME)
  32. B_DATA = SHELL.recv(BUFF)
  33. S_DATA = B_DATA.decode('utf-8')
  34. return(S_DATA)

 

文件五代码:

  1. #_*_ coding:utf8 _*_
  2. import subprocess # 调用操作系统命令
  3. import logging # 日志模块
  4. ## 如果日志实例不存在,就使用本程序日志模块
  5. Log = logging.getLogger("__name__")
  6. if not logging.FileHandler:
  7. formatter = logging.Formatter('%(asctime)s %(levelname)-8s : %(message)s') # 指定logger输出格式
  8. file_handler = logging.FileHandler("DEV_SNMP.log") # 日志文件路径
  9. file_handler.setFormatter(formatter) # 可以通过setFormatter指定输出格式
  10. Log.addHandler(file_handler)
  11. Log.setLevel(logging.DEBUG)
  12. '''
  13. 说明:以下函数是通过 Python3 subprocess 模块调用系统命令实现操作SNMP的功能
  14. 前提条件1:系统需要先安装好SNMP工具,有查询和修改SNMP的命令
  15. 安装SNMP命令:以 CentOS7 系统为例
  16. yum install net-snmp-utils # 安装SNMP工具
  17. 安装后就会有如下命令
  18. snmpbulkwalk # 用于SNMP查询值
  19. snmpset # 用于SNMP修改值
  20. 前提条件2:被管理设备上要开启SNMP功能,以华为模拟器S5700交换机为例:
  21. system-view # 进入配置模式
  22. snmp-agent # 配置SNMP
  23. snmp-agent sys-info version v2c # 设置SNMP版本
  24. snmp-agent community read pwd@123 # 设置只读SNMP密码
  25. snmp-agent community write pwd@456 # 设置修改SNMP密码
  26. snmp-agent udp-port 161 # 设置SNMP端口,默认就是 UDP 161
  27. '''
  28. ## SNMP v2c 版本查询功能
  29. def SNMP_V2_R(SNMP_PWD, SNMP_HOST, SNMP_OID):
  30. SNMP_CMD = 'snmpbulkwalk -v 2c -c ' + SNMP_PWD + ' ' + SNMP_HOST + ' ' + SNMP_OID
  31. RR = subprocess.getstatusoutput(SNMP_CMD)
  32. Log.debug('函数 SNMP_V2_R 执行了系统命令 ' + SNMP_CMD) ## DEBUG
  33. Log.debug('命令执行结果 ' + str(RR)) ## DEBUG
  34. return(RR)
  35. ## SNMP v2c 版本设置功能
  36. def SNMP_V2_W(SNMP_PWD, SNMP_HOST, SNMP_OID, SNMP_TYPE, SNMP_VALUE):
  37. SNMP_CMD = 'snmpset -v 2c -c '+ SNMP_PWD +' '+ SNMP_HOST +' '+ SNMP_OID +' '+ SNMP_TYPE +' '+ SNMP_VALUE
  38. RR = subprocess.getstatusoutput(SNMP_CMD)
  39. Log.debug('函数 SNMP_V2_W 执行了系统命令 ' + SNMP_CMD) ## DEBUG
  40. Log.debug('命令执行结果 ' + str(RR)) ## DEBUG
  41. return(RR)

结构示意图:

 

 

说明文件:

########################################################################################
## (业务层)
## 管理任务实现业务(根据任务结果处理业务逻辑)
## 如WEB端、命令行端、交互控制端等根据实际业务需要调用任务函数完成业务功能
## 调用 DEF_SSH_eNSP_Switch_S5700.py 里的任务函数执行SSH交互操作,获取任务执行状态和结果
## 调用 DEF_SNMP_eNSP_Switch_S5700.py 里的任务函数执行SNMP操作,获取任务执行状态和结果
## 调用 数据库任务,完成数据记录更新
########################################################################################

## 只操作交换机
Main_Switch
    交互操作测试

#############################################################
## (任务层)
## 管理执行实现任务(根据执行结果处理任务逻辑)
## 向上级返回任务完成结果
## 示例:交换机应用功能的实现函数(华为eNSP模拟器S5700交换机)
#############################################################

## 通过SSH交互操作交换机
DEF_SSH_eNSP_Switch_S5700.py
    from DEV_SSH import *   # 需要导入DEV_SSH.py文件里的SNMP操作函数
    import struct           # 用于解析、打包字节码
    import re               # 用于匹配
    import logging          # 日志模块
    import sys              # 本文件中只用于获取函数名方便生成日志内容
    TEST_D_LOGIN_INFO(D_LOGIN_INFO)         # 检查登录信息字典是否合法
    TEST_IP_STR(IP_STR)                     # 检查IP是否合法
    TRY_MASK_2_MASK_INT(MASK)               # 尝试把掩码转成掩码位数
    IP_INT_2_IP_STR(IP_INT)                 # IP_INT 转 IP_STR
    IP_STR_2_IP_INT(IP_STR)                 # IP_STR 转 IP_INT
    根据地址和掩码计算起始和结束地址(IP_STR, MASK_INT)  # 根据地址和掩码计算起始和结束地址
    IP_MASK_2_IP_INT_LIST(IP_STR, MASK_INT)             # 根据IP地址和掩码位数生成IP所在网段的全部IP_INT地址列表(列表从小到大顺序)
    IP_MASK_2_IP_STR_LIST(IP_STR, MASK_INT)             # 根据IP地址和掩码位数生成IP所在网段的全部IP_STR地址列表(列表从小到大顺序)
    MAC缓存信息转成MAC对应VLAN字典(S_DATA)
    VLAN和NET字典(S_DATA)                               # {'Vlanif10': ['192.168.10.1/24'], 'Vlanif20': ['192.168.20.1/24']}
    VLAN和IP字典(S_DATA)                                # {'Vlanif10': ['192.168.10.1'], 'Vlanif20': ['192.168.20.1']}
    TRY_NET_STR_2_IP_MASK(NET_STR)                      # 尝试把网段表示格式:'IP/MASK' 格式转成元组 (IP_STR, MASK_INT)
    TRY_MAC_2_MAC(MAC_STR, 转换格式='xxxx-xxxx-xxxx')   # 尝试把MAC地址转成指定格式
    返回查看模式(S_DATA, SHELL, 最大深度=5)
    IP_MAC_绑定信息转成IP为KEY字典(S_DATA)              # 从查询静态绑定信息命令回显中提取以IP为KEY以MAC为值的字典
    IP_MAC_绑定信息转成MAC为KEY字典(S_DATA)             # 从查询静态绑定信息命令回显中提取以MAC为KEY以IP为值的字典
    判断是否绑定成功(D, IP, MAC)                        # 在IP和MAC对应字典中是否出现IP和MAC绑定记录
    自动查找网段中可用IP_优先自增(NET_IP_STR, NET_MASK_INT, S_DATA, 网段开头保留地址数量=1, 网段末尾保留地址数量=1)
    自动查找网段中可用IP_自动填充(NET_IP_STR, NET_MASK_INT, S_DATA, 网段开头保留地址数量=1, 网段末尾保留地址数量=1)
    ## 任务函数,传入要登录的设备信息和任务必须的参数
    ## 任务函数分2部分
    ## 第1部分 任务控制函数(用于检查参数,控制SSH连接的打开和关闭,调用任务实现函数)
    ## 第2部分 任务实现函数(用于执行交互操作命令,根据回显结果进行处理,返回任务处理状态和处理结果,方便相同功能复用代码)
    保存配置(D_LOGIN_INFO)
        SHELL_SAVE(SSH, SHELL)
    获取IP和MAC绑定信息(D_LOGIN_INFO)
        SHELL_D_IP_MAC(SSH, SHELL)
    绑定指定IP和指定MAC(D_LOGIN_INFO, Bind_IP, Bind_MAC)
        SHELL_Bind_IP_MAC(SSH, SHELL, Bind_IP, Bind_MAC)
    在指定网段自动选择可用IP和指定MAC绑定(D_LOGIN_INFO, Bind_NET, Bind_MAC)
        SHELL_Bind_NET_MAC(SSH, SHELL, Bind_NET_IP_STR, Bind_NET_MASK_INT, Bind_MAC)
    查找MAC地址所在网段(D_LOGIN_INFO, MAC)
        SHELL_MAC_IN_VLAN(SSH, SHELL, MAC)
    在MAC所在网段自动选择可用IP和进行绑定(D_LOGIN_INFO, Bind_MAC)
        SHELL_AUTO_Bind_MAC(SSH, SHELL, Bind_MAC)
    解除指定IP和指定MAC的绑定(D_LOGIN_INFO, Undo_Bind_IP, Undo_Bind_MAC)
        SHELL_UNDO_Bind_IP_MAC(SSH, SHELL, Undo_Bind_IP, Undo_Bind_MAC)
    解除指定IP的全部MAC绑定(D_LOGIN_INFO, Undo_Bind_IP)
        SHELL_UNDO_Bind_IP(SSH, SHELL, Undo_Bind_IP)
    解除指定MAC的全部IP绑定(D_LOGIN_INFO, Undo_Bind_MAC)
        SHELL_UNDO_Bind_MAC(SSH, SHELL, Undo_Bind_MAC)
    


## 通过SNMP操作交换机
DEF_SNMP_eNSP_Switch_S5700.py
    from DEV_SNMP import *      # 需要导入DEV_SNMP.py文件里的SNMP操作函数
    import sys                  # 本文件中只用于获取函数名方便生成日志内容
    import logging              # 日志模块
    SNMP_MAC_2_mac(SNMP_MAC)                                               ## SNMP获取的MAC地址是 '00 00 00 00 00 00' 形式,需要转成 '0000-0000-0000' 形式
    SNMP_L_Bind_IP_STR(SNMP_PWD, SNMP_HOST)                                ## 获取静态绑定IP列表
    SNMP_L_Bind_MAC_STR(SNMP_PWD, SNMP_HOST)                               ## 获取静态绑定MAC列表
    SNMP_L_IF_IP_STR(SNMP_PWD, SNMP_HOST)                                  ## 获取设备接口IP列表(VLAN接口、物理端口、特殊接口)
    SNMP_L_IF_MASK_STR(SNMP_PWD, SNMP_HOST)                                ## 获取设备接口IP的掩码列表(VLAN接口、物理端口、特殊接口)
    SNMP_L_IF_INDEX_STR(SNMP_PWD, SNMP_HOST)                               ## 获取设备接口编号(VLAN接口、物理端口、特殊接口)
    SNMP_D_IF_DESCR(SNMP_PWD, SNMP_HOST)                                   ## 获取设备接口名称字典(VLAN接口、物理端口、特殊接口)## {'1':InLoopBack0, '2':'NULL0', '3':'Console9/0/0', '4':'MEth0/0/1', '5':'Vlanif1', '6':'GigabitEthernet0/0/1'}
    SNMP_生成以IP为键以MAC地址列表为值的字典(SNMP_PWD, SNMP_HOST)          ## 以IP为键以MAC地址列表为值的字典 {IP_STR:[MAC_STR, MAC_STR]}
    SNMP_生成以VLAN为键以VLAN_IP_MASK列表为值的字典(SNMP_PWD, SNMP_HOST)   ## D_VLAN_NET {VLAN_STR:[IP_STR/MASK_STR]}

###################################################
## (执行层)
## 根据任务需要操作具体设备,并返操作状态和操作结果
###################################################

## 操作SSH交互设备
DEV_SSH.py                                      # SSH登录设备执行命令并返回命令结果的函数文件
    import paramiko                             # SSH 操作模块(第三方模块 pip install paramiko 安装)
    import time                                 # 时间模块
    SSH_LOGIN(D_LOGIN_INFO)                     # 尝试登录设备,登录成功返回SSH连接对象和交互子SHELL对象
    SHELL_CMD(SHELL, CMD, TIME=2, BUFF=10240)   # 执行交互命令返回命令回显字符串
    SHELL_CTRL(SHELL, CTRL, TIME=2, BUFF=10240) # 在交互界面发送控制符(未完成)

## 操作SNMP设备
DEV_SNMP.py(目前只完成Linux环境下应用)
    import subprocess                                                   # 调用操作系统命令
    import logging                                                      # 日志模块
    SNMP_V2_R(SNMP_PWD, SNMP_HOST, SNMP_OID)                            # 读取SNMP设备信息
    SNMP_V2_W(SNMP_PWD, SNMP_HOST, SNMP_OID, SNMP_TYPE, SNMP_VALUE)     # 修改SNMP设备配置

##################
## 变量含义说明 ##
##################

## 变量前缀后缀
B       字节
S       字符串
L       列表
T       元组
D       字典
P       集合
INT     数字
STR     字符串
R       接收函数全部返回内容为一个变量 R = 函数()


D_LOGIN_INFO = {SSH_IP:'192.168.0.1', SSH_PORT:22, SSH_USER:'abc', SSH_PASS:'pwd@123'}   # 字典类型登录信息
SSH_IP          # D_LOGIN_INFO 的 KEY 其值为 登录地址(字符串)
SSH_PORT        # D_LOGIN_INFO 的 KEY 其值为 设备端口(数字)
SSH_USER        # D_LOGIN_INFO 的 KEY 其值为 登录用户(字符串)
SSH_PASS        # D_LOGIN_INFO 的 KEY 其值为 登录密码(字符串)

B_DATA          # 执行交互命令后回显的内容(字节)
S_DATA          # 执行交互命令后回显的内容(字符串)

网段开头保留地址数量  # 一般第一个IP做网关,或者前面保留一些IP地址
网段末尾保留地址数量  # 一般最后一个做网关,或者后面保留一些IP地址

D               # 字典,D_IP_MAC 或 D_MAC_IP 字典

IP              # 临时变量名 或 任意格式IP地址(IP_STR 或 IP_INT)
IP_STR          # 点分十进制字符串类型IP地址(字符串)
IP_INT          # 4字节无符号整数类型IP地址(数字)

MASK            # 临时变量名 或 任意格式掩码(MASK_STR 或 MASK_INT)
MASK_STR        # 点分十进制字符串类型掩码(字符串)'255.255.255.0'
MASK_INT        # 掩码长度(掩码位数)(数字)

MAC             # 临时变量名 或 任意格式MAC地址(字符串)3段6段大写小写
mac_H_SP3       # 连字符分3段16进制小写(字符串)'xxxx-xxxx-xxxx'(hyphen)
MAC_H_SP3       # 连字符分3段16进制大写(字符串)'XXXX-XXXX-XXXX'(hyphen)
mac_H_SP6       # 连字符分6段16进制小写(字符串)'xx-xx-xx-xx-xx-xx'(hyphen)
mac_H_SP6       # 连字符分6段16进制大写(字符串)'XX-XX-XX-XX-XX-XX'(hyphen)
mac_C_SP6       # 冒号符分6段16进制小写(字符串)'xx:xx:xx:xx:xx:xx'(colon)
MAC_C_SP6       # 冒号符分6段16进制大写(字符串)'XX:XX:XX:XX:XX:XX'(colon)

D_IP_MAC        # 以 IP_STR 为键以 MAC_STR_SP3 为值的字典
D_MAC_IP        # 以 MAC_STR_SP3 为键以 IP_STR 为值的字典

IP_MASK         # 网段表示格式(字符串)例:'192.168.0.0/255.255.255.0' 或 '192.168.0.0/24'
NET_STR         # 网段表示格式(字符串)例:'192.168.0.0/255.255.255.0' 或 '192.168.0.0/24'
T_NET           (IP_STR, MASK_INT)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/156736
推荐阅读
相关标签
  

闽ICP备14008679号