自動化運維:網站svn代碼上線更新(flask+saltstack)

階段性總結:

     跌跌撞撞的用了一週左右的時間作完了網站自動升級功能,中間遇到了不少的問題,也學到了不少,在此作一個總結。
 

一、總體架構:

後臺:nginx+uwsgi  #nginx提供web服務,uwsgi對python代碼進行解析
前臺:flask+bootstrap+html  #flask是python的一套web開發工具,bootstrap是一套現成的模板,html不用解釋。
功能:shell+saltstack+svn #saltstack 功能的核心,自動化運維工具。 shell 不解釋,svn代碼一致性工具。
 

二、用到的技巧:

python相關:

     對於文件的讀寫
     列表的相關操做
     字典的調用
     如何執行shell命令
     時間模塊
     線程的使用

flask相關:

     表單
     session
     flash
其餘的貌似想不到了,註釋代碼的時候一併回憶整理吧。
 

三、下面進行代碼的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
 

頁面展現:

頁面實現功能:html

選擇更新路徑、更新密碼驗證、自動刪除緩存、更新結果反饋、更新日誌記錄python

相關文章
相關標籤/搜索