自动化运维:网站svn代码上线更新(flask+saltstack)

时间:2022-03-27 19:10:14

阶段性总结:

     跌跌撞撞的用了一周左右的时间做完了网站自动升级功能,中间遇到了很多的问题,也学到了很多,在此做一个总结。

1、整体架构:

后台:nginx+uwsgi  #nginx提供web服务,uwsgi对python代码进行解析
前台:flask+bootstrap+html  #flask是python的一套web开发工具,bootstrap是一*成的模板,html不用解释。
功能:shell+saltstack+svn #saltstack 功能的核心,自动化运维工具。 shell 不解释,svn代码一致性工具。

2、用到的技巧:

python相关:

     对于文件的读写
     列表的相关操作
     字典的调用
     如何执行shell命令
     时间模块
     线程的使用

flask相关:

     表单
     session
     flash
其他的貌似想不到了,注释代码的时候一并回忆整理吧。

3、下面进行代码的review和注释

########################################################################################
########################################################################################
#调用flask相关的模块
from flask import Flask, render_template, session, redirect, url_for, flash
from flask.ext.script import Manager
from flask.ext.bootstrap import Bootstrap
from flask.ext.moment import Moment
from flask.ext.wtf import Form
#调用需要用到的表单类型以及属性
from wtforms import TextAreaField,StringField,SubmitField,SelectField,PasswordField
from wtforms.validators import Required,DataRequired
#调用基础模块
import os,commands,subprocess,time,threading
#调用字典文件并加载
from webpath import webpath
from userdata import userdata
app = Flask(__name__)
app.config['SECRET_KEY'] = 'who is your boss'
manager = Manager(app)
bootstrap = Bootstrap(app)
moment = Moment(app)
#函数:获取指定格式的当前时间
def gettime():
        ISOTIMEFORMAT='%Y-%m-%d %X'     #指定时间格式
        ttime = time.strftime( ISOTIMEFORMAT,time.localtime(time.time()))     #获取当前时间
        return ttime
#函数:将输出转换为列表
def make_list(listin,symbol):
        tem = listin.replace(symbol,'')     #将指定内容替换为空
        tem1 = tem.splitlines()     #按照行将输入转换为列表
        return tem1
#函数:输出日志
def inputF(con):
        f = open('seos.log','a')     #以追加的模式打开文件,如果没有,创建
        updatetime = gettime()
        uptime = str(updatetime) + '\n'
        f.write(uptime)
        conx = con + '\n'
        f.write(conx)
        f.close()     #关闭文件,释放资源
#函数:获取当前存活的web服务器名称,转换为列表
def getweb():
     #执行shell命令,获取saltstack中存活的web服务器
    p = subprocess.Popen('salt-run manage.up | grep web',shell=True,stdout=subprocess.PIPE)
    tem0 = p.stdout.read()     #获取脚本执行结果
    tem2 = make_list(tem0,'- ')
    return tem2
#函数:删除指定web的相关模块缓存
def rmcache_Newseos(webname):
        wbapp = 'Wap Weibo'
        tem2 = getweb()
        basicpath = webpath.get(webname)
     #执行脚本,调用saltstack的客户端服务器上的脚本,实现删除缓存功能
        res = subprocess.Popen('salt \'%s\' cmd.run \'sh %scleancache.sh %s\'' % (webname, basicpath, wbapp),shell=True,stdout=subprocess.PIPE)
#函数:删除所有web的相关模块缓存
#这个函数是使用线程之前的函数,作用如上,效率比较低
def rmomscache():
        p = subprocess.Popen('salt-run manage.up | grep web',shell=True,stdout=subprocess.PIPE)
        path = 'oms/Runtime/*'
        tem0 = p.stdout.read()
        tem2 = make_list(tem0,'- ')
        for webname in tem2:
                basicpath = webpath.get(webname)
                tpath = '%s%s' % (basicpath, path)
                res = subprocess.Popen('salt \'%s\' cmd.run \'rm -rf %s\'' % (webname, tpath),shell=True,stdout=subprocess.PIPE)
                res_in = res.stdout.read()
                print res_in
                print tpath
        return 'Delete oms cache!'
#函数:删除指定web的指定模块缓存
def rmomscache_new(webname):
    path = 'oms/Runtime/*'
    basicpath = webpath.get(webname)
    tpath = '%s%s' % (basicpath, path)
    res = subprocess.Popen('salt \'%s\' cmd.run \'rm -rf %s\'' % (webname, tpath),shell=True,stdout=subprocess.PIPE)
#函数:创建线程集合
def getthreads(targets):
        allweb = getweb()
        threads = []
        for webname in allweb:
                t = threading.Thread(target=targets, args=(webname,))
                threads.append(t)
        return threads
#函数:升级网站
def update_web(path):
        f = open('resault.txt','a')
        tem2 = getweb()
        for webname in tem2:
                basicpath = webpath.get(webname)
                tpath = '%s%s' % (basicpath, path)
                res = subprocess.Popen('salt \'%s\' cmd.run \'svn update %s\'' % (webname, tpath),shell=True,stdout=subprocess.PIPE)
                res_in = res.stdout.read()
                f.write(str(res_in))
                res_list = make_list(res_in,'    ')
        f.close()
        resault = open('resault.txt').read()
        f.close()
        os.remove('resault.txt')
        return resault
#定义表单
class NameForm(Form):
    uppath = SelectField('Path', choices=[('do','do'),('oms','oms')])
    username = SelectField('User', choices=[('admin','admin'),('liujian','liujian')])
    upkey = PasswordField('Password', validators=[DataRequired()])
    submit = SubmitField('Update')
@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404
@app.errorhandler(500)
def internal_server_error(e):
    return render_template('500.html'), 500
#主程序
@app.route('/', methods=['GET', 'POST'])
def index():
    name = None
    uppath = None
    username = None
    upkey = None
    passwd = None
    rmcache = 'Does it need to delete the cache'
    form = NameForm()
    if form.validate_on_submit():
        uppath = form.uppath.data
        upkey = form.upkey.data
        username = form.username.data
        passwd = userdata.get(username)
        if upkey is None or upkey != passwd:
                flash('Your key is wrong!')
                session['name'] = 'Please input right key.'
                session['rmcache'] = 'Does it need to delete the cache'
                return redirect(url_for('index'))
        else:
                utime = gettime()
                print '%s Start update WEB' % utime
                resaul = update_web(uppath)
                resault = resaul.replace('\n','<br>')
                session['name'] = resault
                if uppath.startswith('Newseos'):
                        Newseostime = gettime()
                        print '%s Newseos is updated,start remove cache.' % Newseostime
                        threads = getthreads(rmcache_Newseos)
                        for t in threads:
                                t.setDaemon(True)
                                t.start()
                        t.join()
                        endtime = gettime()
                        print '%s Newseos upgrade over!' % endtime
                        session['rmcache'] = 'Delete Newseos Cache.'
                        uplog = 'Operator:' + username + '\n' + 'Update Path:' + uppath + '\n' + resaul
                        inputF(uplog)
                        return redirect(url_for('index'))
                elif uppath.startswith('oms'):
                        omstime = gettime()
                        print '%s oms id updated,start remove cache.' % omstime
                        threads = getthreads(rmomscache_new)
                        for t in threads:
                                t.setDaemon(True)
                                t.start()
                        t.join()
                        endtime = gettime()
                        print '%s oms upgrade over!' % endtime
                        session['rmcache'] = 'Delete oms Cache.'
                        uplog = 'Operator:' + username + '\n' + 'Update Path:' + uppath + '\n' + resaul
                        inputF(uplog)
                        return redirect(url_for('index'))
                else:
                        session['rmcache'] = 'No need delete cache.'
                        uplog = 'Operator:' + username + '\n' + 'Update Path:' + uppath + '\n' + resaul
                        inputF(uplog)
                        return redirect(url_for('index'))
    return render_template('index.html', form=form, name=session.get('name'), uppath=uppath, upkey=upkey, username = username, rmcache=session.get('rmcache'))
if __name__ == '__main__':
    manager.run()
结语:模板相关的代码以及整体程序结构没有展示,感觉必要性也不是很大。下边给出我参考和学习的一些资料和链接吧:

书籍:

《Flask Web开发-基于Python的Web应用开发实战》   ---核心书籍
《Python 核心编程》第二版
链接:
linux部署flask+uwsgi+nginx详解
http://www.tuicool.com/articles/zUvqMr
flask学习的博客
http://my.oschina.net/ykbj/blog

页面展示:

页面实现功能:

选择更新路径、更新密码验证、自动删除缓存、更新结果反馈、更新日志记录

自动化运维:网站svn代码上线更新(flask+saltstack)