Table of Contents
场景需求
前面老季写了一个 PHP如何登录连接TELNET并执行交换机命令类 图文教程 ,最近项目中遇到了要换python3来登录交换机并拉取配置。这里我们直接贴出相关代码使用telnetlib类来登录交换机并拉取配置。
我们在代码中可以处理交换机拉取配置时,内容过长,出现 --- More ---
需要按空格的场景。并且将所有交换机命令的返回值都进行了返回给调用方法。
代码实例
class TelnetClient(): def __init__(self,): self.tn = telnetlib.Telnet() time.sleep(0.2) # 此函数实现telnet登录主机 def login(self,host_ip,username,password,port=23): try: # self.tn = telnetlib.Telnet(host_ip,port=23) self.tn.open(host_ip,port) except: logging.critical('网络连接失败'+repr(host_ip)) return False # 等待login出现后输入用户名,最多等待10秒 self.tn.read_until(b'Username: ',timeout=1) self.tn.write(username.encode('ascii') + b'n') self.tn.read_until(b'Password: ',timeout=1) self.tn.write(password.encode('ascii') + b'n') # 延时两秒再收取返回结果,给服务端足够响应时间 time.sleep(0.2) # 获取登录结果 # read_very_eager()获取到的是的是上次获取之后本次获取之前的所有输出 command_result = self.tn.read_very_eager().decode('ascii') if 'Login incorrect' not in command_result: return True else: return False # 此函数实现执行传过来的命令,并输出其执行结果 def execute_some_command(self,command): logging.info('开始执行交换机命令:'+command) # 执行命令 self.tn.write(command.encode('ascii')+b'n') time.sleep(0.2) # 获取命令结果 a = [] a.append(('--- More ---').encode('ascii')) command_result = self.tn.read_very_eager().decode('ascii') while True: b,c,d = self.tn.expect(a,timeout=1) command_result += d.decode('ascii') if 0 == b: time.sleep(0.2) self.tn.write(b' n') #不用rn来继续 else: break logging.info('命令执行结果:'+repr(command_result)) if 'Error:' in command_result : logging.critical('执行结果中可能包含错误`Error:`,脚本强制退出') sendWxMsg('流量调度系统交换机命令执行出现错误,请及时处理!') sys.exit() return command_result # 退出telnet def logout(self): self.tn.write(b"exitn") self.tn.close()
多个交换机命令时封装调用(可自行封装)
# 执行多条交换机命令 def execSwitchCmd( host , username , password , commands , extra = '1' ) : ''' :param host:主机地址 :param username:用户名 :param password:密码 :param commands:列表命令集 :param extra: 是否需要执行 system-view , commit 命令 ''' logging.info('开始执行交换机命令【'+repr(commands)+'】') # return True telnet_client = TelnetClient() msg = '' # 如果登录结果返加True,则执行命令,然后退出 if telnet_client.login(host,username,password) : if extra == 1: msg += telnet_client.execute_some_command( 'system-view' ) for command in commands : msg += telnet_client.execute_some_command( command ) if extra == 1: msg += telnet_client.execute_some_command( 'commit' ) telnet_client.logout() return msg
调用方法
cmd = [] cmd.append('dis traffic-policy applied-record TO_TrafficCenter') res = func.execSwitchCmd(room['host'],room['username'],room['password'],cmd , '0') if 'xxxxx' in res : # 某些配置在交换机中,做什么处理 ......
交换机命令过多时,建议使用rn拼接命令并分组
def centerSchedulingOut95( destination_id , pieces ) : # ..... #....... cmd = [] i = 1 divided = 12 tmpCmd = '' for policy in policys : from_room = getRoomById( policy['destination_id'] ) if i % divided == 0 : cmd.append( tmpCmd ) tmpCmd = '' else : tmpCmd += 'rn' + policy['name'] + 'rn' + 'UNDO traffic-policy TO_'+from_room['abbr']+' inbound' + 'rn' + 'traffic-policy TO_'+to_room['abbr']+' inbound' + 'rn' i += 1 config.cursor.execute("UPDATE center_policy SET status = 2 ,destination_id = %s , update_time=%s WHERE id = %s" , [ destination_id , getNow() , policy['id'] ] ) logging.info('|----已更改 %s 状态为:使用中,去向机房ID:%s',policy['name'] , to_room['id']) if tmpCmd != '' : cmd.append( tmpCmd ) logging.info('|----开始登录调度中心交换机,批量执行调出POLICY命令') config.cursor.execute("SELECT * FROM center") centerObj = config.cursor.fetchone() if len(cmd) > 0 : logging.info('|----本次实际调度POLICY规则条数:%s',repr( len(policys) ) ) execSwitchCmd( host = centerObj['host'] , username = centerObj['username'] , password = centerObj['password'] , commands = cmd )
我们这里将命令拼接成 rn的格式拼接,每12个命令一组,传入到交换机里执行。