執(zhí)行過程持續(xù)返回
簡要
1. 挑用插件:
django-celery jenkins
2. 基于Python版本:
Python2.7
3. 基于django版本:
django1.8.18
主要問題:
需要把jenkins代碼發(fā)布的執(zhí)行過程持續(xù)輸出佩厚,后臺(tái)執(zhí)行完成后消息數(shù)據(jù)返回到前臺(tái)秉剑。
解決方案:
使用django-celery的異步執(zhí)行操作饵筑,把異步執(zhí)行的數(shù)據(jù)返回到rabbitmq温圆,從rabbitmq讀取數(shù)據(jù)寫入數(shù)據(jù)庫萄焦,頁面中返回?cái)?shù)據(jù)庫的信息馁龟,頁面使用定時(shí)器腿时,當(dāng)返回結(jié)果不為失敗或者成功時(shí)雷滋,5秒刷新頁面,讀取最新的操作內(nèi)容臼勉。
具體代碼如下:
1. django setting.py配置:
djcelery.setup_loader()
BROKER_URL = 'amqp://guest:guest@localhost:5672//'
BROKER_POOL_LIMIT = 0
#CELERY_TASK_SERIALIZER = 'json' (由于設(shè)置Json以后輸入也必須要使用Json格式邻吭,暫時(shí)未啟用)
#CELERY_RESULT_SERIALIZER = 'json'
CELERY_ENABLE_UTC = True
CELERY_RESULT_BACKEND= 'amqp'
INSTALLED_APPS = (
'djcelery',
'app',
)
2. django celery.py配置:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from __future__ import absolute_import
import os
from celery import Celery
from django.conf import settings
from app.backend.tasks import *
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'CMDB.settings')
app = Celery('CMDB')
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
3. app view配置:
def job_release(request):
if request.method == 'GET':
try:
global job_enable (執(zhí)行開關(guān),防止多次執(zhí)行)
id = request.GET.get('id') (獲取指定的ID)
name = request.GET.get('name') (執(zhí)行會(huì)帶name,返回到執(zhí)行頁面不會(huì)帶name,防止返回被執(zhí)行)
all_result = jenkins_return.objects.filter(id=id) (獲取當(dāng)前執(zhí)行的項(xiàng)目信息)
job_name = all_result[0] (執(zhí)行的項(xiàng)目名稱)
full_name = all_result.values()[0]['full_name'] (執(zhí)行的項(xiàng)目全稱宴霸,jenkins需要指定到子目錄才能build)
except:
all_result = job_release_return.objects.filter(id=id) (返回囱晴,或者刷新,還是獲取到當(dāng)前的內(nèi)容)
return render_to_response("job_release.html",locals())
else:
if job_enable == 1: (執(zhí)行開關(guān)瓢谢,為1的時(shí)候開啟執(zhí)行功能)
res = goto_html.delay(full_name,job_name) (異步執(zhí)行第一步畸写,準(zhǔn)備執(zhí)行)
import_goto_html.delay(res.get()) (導(dǎo)入到數(shù)據(jù)庫)
ret_in = get_job_runinng_in.delay(full_name,res.get()) (異步執(zhí)行第二步,獲取執(zhí)行中狀態(tài)內(nèi)容)
ret_end =get_job_runinng_end.delay(full_name,res.get()) (異步執(zhí)行第三部氓扛,取得執(zhí)行結(jié)果)
job_enable = 0 (執(zhí)行完成后功能取消枯芬,當(dāng)返回到執(zhí)行頁面時(shí)復(fù)位)
time.sleep(0.5) (返回內(nèi)容)
all_result = job_release_return.objects.all()
return render_to_response("job_release.html",locals())
4. js配置(很簡單,不是執(zhí)行成功或者執(zhí)行失敗時(shí)刷新頁面):
<script language="JavaScript">
function myrefresh(){
window.location.reload();
}
function show(){
var mytable = document.getElementById("dataTables-example").rows[1].cells[7].innerHTML;
if(mytable == "執(zhí)行成功" || mytable == "執(zhí)行失敗"){
return true;}
else{
myrefresh();}
}
setTimeout('show()',5000);
</script>
5. app task.py配置:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from __future__ import absolute_import
from celery import task
from app.backend.fb_jenkins import *
import urllib
import jenkins
import time
from datetime import datetime
import sys
jenkins_server_url="" (jenkins地址)
host="" (主機(jī)IP)
user_id = "" (jenkins用戶)
api_token = "" (jenkins token)
#server=jenkins.Jenkins(jenkins_server_url, username=user_id, password=api_token) (這里兩種方式采郎,一直使用oken,另一種使用passwd)
server=jenkins.Jenkins(jenkins_server_url, username=user_id, password="*****")
joblist=[]
#(jenkins的方法千所,獲取項(xiàng)目構(gòu)建過程)
@task
def get_job_output(jobName):
last = server.get_job_info(jobName)['lastBuild']['number']
return server.get_build_console_output(jobName,last)
# (進(jìn)入執(zhí)行頁面,并執(zhí)行job任務(wù))
@task
def goto_html(full_name,jobName):
result = get_job_output(full_name)
start_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
result_log = " {0} {1} 程序開始構(gòu)建".format(start_time, full_name)
parameters = {}
parameters['project0001'] = 'test001'
server.build_job(full_name,parameters)
results = []
workspace = result.split('Building in workspace')[1].strip().split('\n')[0]
next_build_number = server.get_job_info(full_name)['nextBuildNumber']
results.extend([jobName,host,workspace,start_time,"end_time",next_build_number,next_build_number,"執(zhí)行開始","result",result_log])
return results
# (寫入數(shù)據(jù)庫)
@task
def import_goto_html(ret):
import_release_sql(ret)
return True
# (執(zhí)行中狀態(tài))
@task
def get_job_runinng_in(full_name,ret):
result = get_job_output(full_name)
results = []
jobName = ret[0]
start_time = ret[3]
workspace = ret[2]
next_build_number = ret[5]
time_now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
for i in range(20):
builds = server.get_running_builds()
if len(builds)!=0:break
time.sleep(0.2)
result_log = ret[9] + "\n {0} {1} 程序構(gòu)建中".format(time_now, full_name)
results.extend(
[jobName, host, workspace, start_time, "end_time", next_build_number, next_build_number, "執(zhí)行中", "result",
result_log])
import_goto_html(results)
return results
# (執(zhí)行完成狀態(tài))
@task
def get_job_runinng_end(full_name,ret):
results = []
jobName = ret[0]
start_time = ret[3]
workspace = ret[2]
next_build_number = ret[5]
time_now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
time.sleep(3)
while True:
try:
build_info = server.get_build_info(full_name, next_build_number)
except:
continue
else:
if build_info[u'building'] == False:
break
time.sleep(1)
end_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
result = get_job_output(full_name)
result_log = ret[9] + "\n {0} {1} 程序構(gòu)建中".format(time_now, full_name) + "\n {0} {1} 程序構(gòu)建完成".format(end_time,full_name)
results.extend(
[jobName, host, workspace, start_time, end_time, next_build_number, next_build_number, "執(zhí)行成功", result,
result_log])
import_goto_html(results)
return results