场景:通过Python3自动下发交换机配置
import dns.resolver
from netmiko import ConnectHandler, SSHDetect, Netmiko
from netmiko.exceptions import NetMikoTimeoutException, NetMikoAuthenticationException
import logging
import os
class RunningLogger:
def __init__(self, path,clevel = logging.DEBUG,Flevel = logging.DEBUG):
self.logger = logging.getLogger(path)
self.logger.setLevel(logging.DEBUG)
fmt = logging.Formatter('[%(asctime)s] [%(levelname)s] %(message)s', '%Y-%m-%d %H:%M:%S')
#设置CMD日志
sh = logging.StreamHandler()
sh.setFormatter(fmt)
sh.setLevel(clevel)
#设置文件日志
fh = logging.FileHandler(path)
fh.setFormatter(fmt)
fh.setLevel(Flevel)
self.logger.addHandler(sh)
self.logger.addHandler(fh)
def debug(self,message):
self.logger.debug(message)
def info(self,message):
self.logger.info(message)
def war(self,message):
self.logger.warn(message)
def error(self,message):
self.logger.error(message)
def cri(self,message):
self.logger.critical(message)
running_logger = RunningLogger('Bot_Running.log', logging.ERROR,logging.DEBUG, )
app_redis_db = redis.StrictRedis(host='127.0.0.1',port=6379,db=0,decode_responses=True)
def Is_Valid_IPv4(ipv4):
try:
ipaddress.IPv4Address(ipv4)
return True
except ipaddress.AddressValueError:
return False
def Get_DNS_Record_List(public_dns_ip,domain,query_type='A'):
resolver = dns.resolver.Resolver(configure=False)
resolver.nameservers = [public_dns_ip]
resolver.timeout = 2
resolver.lifetime = 2
try:
answer = resolver.resolve(qname=domain, rdtype=query_type)
dns_record_list = []
for i in answer.response.answer:
for j in i.items:
if Is_Valid_IPv4(j.to_text()):
dns_record_list.append(j.to_text())
return dns_record_list
except Exception as e:
# running_logger.info(f'【INFO】DNS解析失败,{public_dns_ip} {e}!')
return [False,str(e)]
pass
def Execute_CDN_Switch_CMD(name="", mode="", cmd="",cmd_list=[]):
if name == "cdn-1":
ip = "103.1.1.1"
elif name == "cdn-2":
ip = "103.1.1.2"
elif name == "cdn-3":
ip = "103.1.1.3"
try:
device = {
'device_type': 'hp_comware',
'ip': ip,
'username': 'blueduck',
'password': 'blueduck',
'port': 22,
# 'verbose': True,
'session_log': 'session.log',
'timeout' : 180,
'secret': ''
}
i = 0
cmd_result = ''
loop_delay = 1
timeout = 100
loops = timeout / loop_delay
end_pattern1 = '>'
end_pattern2 = ']'
with ConnectHandler(**device) as conn:
conn.enable()
# config_cmds = ['ip route-static 114.1.1.1 32 100.65.0.2','ip route-static 114.2.2.2 32 100.65.0.2']
config_cmds = cmd_list
conn.send_config_set(config_commands=config_cmds)
# conn.write_channel('{}{}'.format(f'{cmd}',conn.RETURN))
if mode == "read":
while i <= loops:
output = conn.read_channel()
if output:
cmd_result = cmd_result + output
# print("output____:", output)
time.sleep(loop_delay)
i = i + 1
if i > 1 and (end_pattern1 in output or end_pattern2 in output):
break
if mode == "read":
print('执行结果为:{}'.format(cmd_result))
IPv4_Pattern = r'\b(?:\d{1,3}\.){3}\d{1,3}\b'
IPv4_Addr_List = re.findall(IPv4_Pattern, cmd_result)
IPv4_Addr_List = list(set(IPv4_Addr_List))
if IPv4_Addr_List:
print(IPv4_Addr_List)
conn.disconnect()
except (EOFError, NetMikoTimeoutException):
running_logger.error("NetMiko: Can not connect to H3C Switch")
except (EOFError, NetMikoAuthenticationException):
running_logger.error("NetMiko: Wrong username or password")
except Exception as e:
running_logger.error("NetMiko: Wrong enable password")
# Execute_CDN_Switch_CMD(name="cdn-1", mode="read", cmd="dis ip routing-table | in 100.65.0.2")
def Deplopy_Oversea_Task():
if file_name == "SecOpsBot":
OverseaLine_IP_Domains = "OverseaLine_IP_Domains"
OverseaLine_VM_Destionation_IP_Relationship = "OverseaLine_VM_Destionation_IP_Relationship"
else:
OverseaLine_IP_Domains = "OverseaLine_IP_Domains_Test"
OverseaLine_VM_Destionation_IP_Relationship = "OverseaLine_VM_Destionation_IP_Relationship_Test"
oversea_ip_domains_in_redis = app_redis_db.get(OverseaLine_IP_Domains)
oversea_vm_destionation_ip_in_redis = app_redis_db.get(OverseaLine_VM_Destionation_IP_Relationship)
if oversea_vm_destionation_ip_in_redis:
oversea_vm_destionation_ip_dict = json.loads(oversea_vm_destionation_ip_in_redis)
else:
oversea_vm_destionation_ip_dict = {}
# 如果有新增业务IP和域名数据就开始往下执行
if oversea_ip_domains_in_redis:
oversea_ip_domains_dict = json.loads(oversea_ip_domains_in_redis)
switch_config_cmd = []
for vm_ip in oversea_ip_domains_dict.keys():
# 判断vm ip有没有存在的关联数据,有关联数据,需要检查是否有更新的目的IP地址需要添加
if oversea_vm_destionation_ip_dict.get(vm_ip):
dns_record_list = []
new_DstIP_list = []
for domain in oversea_ip_domains_dict.get(vm_ip):
dns_record_list += Get_DNS_Record_List(public_dns_ip="172.16.16.16",domain=domain,query_type='A')
dns_record_list = list(set(dns_record_list))
for DstIP in dns_record_list:
if DstIP not in oversea_vm_destionation_ip_dict.get(vm_ip):
# 如果解析出来的IP不在已有数据里,需要更新
new_DstIP_list.append(DstIP)
new_DstIP_list = list(set(new_DstIP_list))
for item in new_DstIP_list:
switch_config_cmd.append(f'ip route-static {item} 32 {vm_ip}')
running_logger.info(f"有关联数据,新增目的IP, ip route-static {item} 32 {vm_ip}")
# 将增量数据生成交换机命令,然后统一执行
all_dns_record = list(set(new_DstIP_list + oversea_vm_destionation_ip_dict[vm_ip]))
oversea_vm_destionation_ip_dict[vm_ip] = all_dns_record
# 保存至redis中
app_redis_db.set(OverseaLine_VM_Destionation_IP_Relationship, json.dumps(oversea_vm_destionation_ip_dict))
else:
# redis里没有vm和转发目的IP的关联数据,需要初始化数据,然后下发静态路由至交换机
#动态解析域名获取目的IP,并保存起来,保存格式为
# {
# '100.65.0.1': [1.1.1.1,2.2.2.2]
#}
dns_record_list = []
for domain in oversea_ip_domains_dict.get(vm_ip):
dns_record_list += Get_DNS_Record_List(public_dns_ip="172.16.16.16",domain=domain,query_type='A')
dns_record_list = list(set(dns_record_list))
oversea_vm_destionation_ip_dict[vm_ip] = dns_record_list
# 将增量数据生成交换机命令,然后统一执行
for DstIP in dns_record_list:
switch_config_cmd.append(f'ip route-static {DstIP} 32 {vm_ip}')
running_logger.info(f"初始化,新增目的IP,ip route-static {DstIP} 32 {vm_ip} ")
# 保存至redis中
app_redis_db.set(OverseaLine_VM_Destionation_IP_Relationship, json.dumps(oversea_vm_destionation_ip_dict))
switch_config_cmd = list(set(switch_config_cmd))
if switch_config_cmd:
Execute_CDN_Switch_CMD(name="cdn-1", cmd_list=switch_config_cmd)
# Deplopy_Oversea_Task()



