Python重启深信服设备

发布时间:2019-09-21 10:51:44编辑:auto阅读(1274)

    一、背景

    在生产环境中,有客户架构为阿里云线上环境及线下IDC需要内网互通,互联采用阿里云使用第三方深信服云产品与线下IDC侧Cisco防火墙ipsec打通实现,主要用于定时阿里云文件及数据备份至IDC,在生产应用中无故隧道会不定时中断,联系深信服及思科售后排查均没有结果,但是进行手动的重启阿里云上深信服设备隧道立即恢复,在两边网络工程师排查无果后,想到去编写监控脚本,如果隧道终端去利用python重启深信服设备,从而恢复隧道,数据传输延迟timeout及使用断点续传,当网络层面异常无法解决时,换另一种思路来解决问题。

    二、技术要点

    2.1 编写隧道监控脚本

    由于线上阿里云侧为公有云,且为配置EIP及NAT网关,ecs均采用前端公网SLB负责业务请求接入,其内部无法出公网,隧道监控脚本想告警出来发送至微信及后续的去操作深信服需要公网连通,因此在线下IDC侧放置检查及重启脚本。

    2.2 深信服重启

    • 利用Python编写去操作深信服,web页面模拟登录,主要利用到了selenium模块,logging来记录日志。
    • 利用阿里云ECS API来操作重启深信服设备。

    三、源码

    3.1 隧道检测脚本

    3.1.1 检查脚本功能

    检测隧道连通性,如果隧道终端告警至微信及钉钉,其次触发深信服重启脚本。

    #!/bin/bash
    #检测内网地址
    IP=10.10.10.2
    dir="/sangfor/Shscripts/pdc/"
    if [ ! -d ${dir} ];then
        mkdir -p ${dir}
    fi
    echo 1 > ${dir}pdcping.lock
    while true
    do
        #日志分割归档
        Time=`date +%F`
        TIME="${Time} 23:59"
        if [ "${data}" == "${TIME}" ];then
            mkdir ${dir}${Time} && mv ${dir}pdcping.log ${dir}${Time}-pingpdc.log
            mv ${dir}${Time}-pingpdc.log ${dir}${Time}
        fi
        find ${dir} -mtime +7 -type d -exec rm -rf {} \;
    
        find ${dir} -mtime +7 -name "*-pingpdc.log" -exec rm -rf {} \;
        data=`date +%F' '%H:%M`
        data1=`date +%F' '%H:%M:%S`
        echo "------------${data1}---------------">>${dir}pingpdc.log
        ping -c 10 ${IP} >>${dir}pingpdc.log
        if [ $? -eq 1 ];then
            STAT=`cat ${dir}pdcping.lock`
            if [ ${STAT} -eq 1 ];then
                            /usr/local/python34/bin/python3 /sangfor/Pysangfor/sangfor_public.py
                echo 0 > ${dir}pdcping.lock
            else
                continue
            fi
        else
            STAT=`cat ${dir}pdcping.lock`
            if [ ${STAT} -eq 0 ];then
                echo 1 > ${dir}pdcping.lock
            else
                continue
            fi
        fi
    done

    3.1.2 检查脚本功能

    为防止隧道检测脚本异常,另外编写监控监测脚本的脚本配合定时任务来定时监控,如果异常,重新拉起。

    #!/bin/bash
    num=$(ps -ef |grep pdc.sh|wc -l)
    cmd="/usr/bin/nohup /bin/bash /sangfor/Shscripts/pdc/pdc.sh &"
    if [ ${num} -lt 2 ];then
    ${cmd}
    fi

    配合定时任务

    * * * * * /bin/bash /sangfor/Shscripts/pdc/checkpdc.sh

    3.2 深信服操作脚本

    3.2.1 基础环境部署

    • A 依赖软件及python3.4版本安装
      yum -y install zlib-devel zlib readline-devel  openssl-devel wget gcc-c++ Xvfb lrzsz firefox
      cd /tmp
      wget -c https://www.python.org/ftp/python/3.4.5/Python-3.4.5.tgz
      tar -zxvf Python-3.4.5.tgz
      cd Python-3.4.5
      ./configure --prefix=/usr/local/python34
      make && make install
      echo "export PATH=$PATH:/usr/local/python34/bin" >/etc/profile.d/python34.sh
      source /etc/profile.d/python34.sh
    • B pip安装
      cd /tmp
      wget https://bootstrap.pypa.io/get-pip.py
      python3 get-pip.py
    • C 安装python模块
      pip3 install selenium
      pip3 install pyvirtualdisplay
      pip3 install xvfbwrapper
    • D 下载安装geckodriver
      cd /tmp
      wget -c https://github.com/mozilla/geckodriver/releases/download/v0.16.1/geckodriver-v0.16.1-linux64.tar.gz
      tar zxvf geckodriver-v0.16.1-linux64.tar.gz
      cp geckodriver /usr/bin/

    3.2.2 python代码

    github地址
    模拟web登录操作深信服

    cat > /sangfor/Pysangfor/sangfor_public.py<<EOF
    #!/bin/env python3
    # -*- coding:UTF-8 -*-
    # _author:kaliarch
    #导入模块
    from pyvirtualdisplay import Display
    from selenium import webdriver
    import time
    import os
    import logging
    
    #定义深信服重启类
    class Glp_SangFor:
        def __init__(self,logger):
            self.logger = logger
            self.logger.info("--------------start log----------------")
            self.display = Display(visible=0, size=(800, 600))
            self.display.start()
            self.browser = webdriver.Firefox()
            self.logger.info("start browser successfuly")
    
            self.sangfor_url = "深信服公网url"
            self.username = '深信服登录用户名'
            self.password = '深信服登录密码'
    
        def login(self):
            self.browser.get(self.sangfor_url)
            self.browser.implicitly_wait(5)
            self.browser.find_element_by_name('user').send_keys(self.username)
            self.browser.find_element_by_name('password').send_keys(self.password)
            self.browser.find_element_by_class_name('buttons').click()
            self.browser.implicitly_wait(5)
            self.logger.info("loggin sangfor successfuly")
    
        def client_reboot(self):
            self.browser.find_element_by_id("ext-gen111").click()
            print(self.browser.find_element_by_id("ext-gen111").text)
            self.browser.implicitly_wait(15)
            time.sleep(60)
            self.logger.info("switch mainiframe start")
            try:
                print(self.browser.find_element_by_link_text("重启/重启服务/关机").text)
                self.browser.find_element_by_link_text("重启/重启服务/关机").click()
                self.browser.implicitly_wait(3)
                self.browser.switch_to_frame("mainiframe")
                self.browser.implicitly_wait(8)
                time.sleep(10)
                self.browser.find_element_by_xpath("//button[@id='ext-gen19']").click()
                print(self.browser.find_element_by_xpath("//button[@id='ext-gen19']").text)
                self.browser.implicitly_wait(10)
                #self.browser.find_element_by_xpath("//button[@id='ext-gen42']").click()
                print(self.browser.find_element_by_xpath("//button[@id='ext-gen42']").text)
            except Exception as e:
                self.logger.exception("reboot successful")
                return 1
            self.browser.close()
            self.logger.info("browser close successful")
            self.logger.info("--------------end log----------------")
            return 0
    
    #定义日志记录
    class Glp_Log:
        def __init__(self,filename):
            self.filename = filename
        def createDir(self):
            _LOGDIR = os.path.join(os.path.dirname(__file__), 'publiclog')
            print(_LOGDIR)
            _TIME = time.strftime('%Y-%m-%d', time.gmtime()) + '-'
            _LOGNAME = _TIME + self.filename
            print(_LOGNAME)
            LOGFILENAME = os.path.join(_LOGDIR, _LOGNAME)
            print(LOGFILENAME)
            if not os.path.exists(_LOGDIR):
                os.mkdir(_LOGDIR)
            return LOGFILENAME
            print(LOGFILENAME)
    
        def createlogger(self,logfilename):
            logger= logging.getLogger()
            logger.setLevel(logging.INFO)
            handler = logging.FileHandler(logfilename)
            handler.setLevel(logging.INFO)
            formater = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
            handler.setFormatter(formater)
            logger.addHandler(handler)
            return logger
    
    #主函数调用
    if __name__ == '__main__':
        os.system("pkill firefox")
        os.system("pkill Xvfb")
        glploger = Glp_Log('public-***.log')
        logfilename = glploger.createDir()
        logger = glploger.createlogger(logfilename)
    
        sangfor_oper = Glp_SangFor(logger)
        sangfor_oper.login()
        sangfor_oper.client_reboot()
    EOF

    通过阿里云ECS API操作深信服设备

    #!/bin/env python3
    # -*- coding:UTF-8 -*-
    # _author:kaliarch
    from aliyunsdkcore import client
    from aliyunsdkecs.request.v20140526 import RebootInstanceRequest,StartInstanceRequest,StopInstanceRequest
    import time
    import os
    import logging
    class ecsOper():
        def __init__(self,logger):
            self.clentoper = client.AcsClient('<accessKeyId>', '<accessSecret>', 'cn-hangzhou')
            self.logger = logger
            self.logger.info("------------------------start reboot *** ecs of API log-------------")
        def reboot_instance(self):
            # 设置参数
            request = RebootInstanceRequest.RebootInstanceRequest()
            request.set_accept_format('json')
            request.add_query_param('InstanceId', 'i-bpxxzx1rlsgvclq79au')
            # 发起请求
            response = self.clentoper.do_action_with_exception(request)
            self.logger.info("public ecs *** reboot successful!")
            self.logger.info(response)
            print(response)
    
        def start_instance(self):
            request = StartInstanceRequest.StartInstanceRequest()
            request.set_accept_format('json')
            request.add_query_param('InstanceId', 'i-bpxxzx1rlsgvclq79au')
            # 发起请求
            response = self.clentoper.do_action_with_exception(request)
            self.logger.info("public ecs *** start successful!")
            self.logger.info(response)
            print(response)
    
        def stop_instance(self):
            request = StopInstanceRequest.StopInstanceRequest()
            request.set_accept_format('json')
            request.add_query_param('InstanceId', 'i-bp1djzd1rlsgvclq79au')
            request.add_query_param('ForceStop', 'false')
            # 发起请求
            response = self.clentoper.do_action_with_exception(request)
            request.add_query_param('InstanceId', 'i-bpxxzxd1rlsgvclq79au')
            self.logger.info(response)
            print(response)
    
        def testlog(self):
            self.logger.info("public test log")
    
    class Glp_Log:
        def __init__(self,filename):
            self.filename = filename
        def createDir(self):
            _LOGDIR = os.path.join(os.path.dirname(__file__), 'publiclog')
            print(_LOGDIR)
            _TIME = time.strftime('%Y-%m-%d', time.gmtime()) + '-'
            _LOGNAME = _TIME + self.filename
            print(_LOGNAME)
            LOGFILENAME = os.path.join(_LOGDIR, _LOGNAME)
            print(LOGFILENAME)
            if not os.path.exists(_LOGDIR):
                os.mkdir(_LOGDIR)
            return LOGFILENAME
            print(LOGFILENAME)
    
        def createlogger(self,logfilename):
            logger= logging.getLogger()
            logger.setLevel(logging.INFO)
            handler = logging.FileHandler(logfilename)
            handler.setLevel(logging.INFO)
            formater = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
            handler.setFormatter(formater)
            logger.addHandler(handler)
            return logger
    
    if __name__ == "__main__":
        glploger = Glp_Log('public-***.log')
        logfilename = glploger.createDir()
        logger = glploger.createlogger(logfilename)
    
        app = ecsOper(logger)
        app.reboot_instance()
    

    四、效果展示

    查看检查脚本日志已经进行了切割,且保留7天的日志,防止日志过大占用过多磁盘空间
    Python重启深信服设备
    微信告警信息
    Python重启深信服设备
    钉钉告警信息
    Python重启深信服设备
    查看python脚本深信服重启日志
    Python重启深信服设备

    五、总结

    其简单的实现了故障自愈,利用其思路客户配合很多业务,例如简单的应用重启等。

关键字