Python重启深信服设备

一、背景

在生产环境中,有客户架构为阿里云线上环境及线下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天的日志,防止日志过大占用过多磁盘空间


image

微信告警信息


image

钉钉告警信息
image

查看python脚本深信服重启日志


image

五、总结

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,717评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,501评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,311评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,417评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,500评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,538评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,557评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,310评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,759评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,065评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,233评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,909评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,548评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,172评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,420评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,103评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,098评论 2 352

推荐阅读更多精彩内容