美文网首页
基础自动化发布SDK,Python版

基础自动化发布SDK,Python版

作者: 天擎 | 来源:发表于2018-03-29 10:08 被阅读21次

为了让初级工程师也能快速的编写发布脚本,为此而编写了以下基础自动化发布SDK,方便工程师集成。

    # -*- coding: utf8 -*-
'''
author by 天擎
This's deploy SDK.
'''
import os,sys,time,json
import urllib,urllib2,shutil,requests
from paramiko import SSHClient,AutoAddPolicy,SSHException,ssh_exception
reload(sys)
sys.setdefaultencoding('utf-8')

class deployutils:
    def __doc__(self):
        pass

    def __init__(self,auth):
        self.auth=auth

    def timestamp(self):
        timestamp = time.strftime("%Y%m%d-%H%M%S")
        return timestamp

    def rcopy(self,fsrc,fdst):
         if os.path.exists(fsrc):
            try:
                if os.path.isfile(fsrc) and not os.path.isfile(fdst):
                    shutil.copy2(fsrc,fdst)
                elif os.path.isdir(fsrc) and not os.path.isdir(fdst):
                    shutil.copytree(fsrc,fdst,symlinks=True,ignore=None)
            except Exception,e:
                print e
                sys.exit(1)
         else:
            print 'source File or Dir not exists...'
            sys.exit(1)

    # backup('/root/anaconda-ks.cfg','/root','test.txt')
    def backup(self,srcfile,dstdir,filename,prename=""):
        prename = self.timestamp()
        filename = dstdir + "/" + filename + prename
        try:
            result=self.rcopy(srcfile,filename)
        except Exception ,e:
            print e
            result=0
        finally:
            return result

    # sshexec('192.168.1.1','ls /root',user='docker')
    def sshexec(self, remoteip=None,sshcmd=None, port=22, user='root'):
        if remoteip and sshcmd:
            client = SSHClient()
            client.set_missing_host_key_policy(AutoAddPolicy())
            try:
                print 'invoke remote host ...'
                client.connect(remoteip, port, username=user, timeout=120)
                stdin, stdout, stderr = client.exec_command(sshcmd, get_pty=True, timeout=120)
                if stdout:
                    for std in stdout.readlines():
                        print std.strip('\n')
                    exit_status = stdout.channel
                    if exit_status.recv_exit_status() == 1:
                        print 'exec command ,system exit status 1.'
                        return False
                    elif exit_status.recv_exit_status() == 0:
                        return True
                elif stderr.read():
                    print 'remote exec error !'
                    return False
                else:
                    print 'remote exec error !'
                    return False
            except ssh_exception.NoValidConnectionsError,e:
                   print e
                   print '%s lose connect.'%(remoteip)
                   return 'retry'
            except SSHException,e:
                   print e
            finally:
                client.close()
        else:
            print "exec parameter is empty ."
            return False

    # rsync file to remote ip
    def rsync(self, localpath=None, remoteip=None, remotepath=None, user='root'):

        if os.path.exists(localpath):
            synccommand="scp -r " + localpath + " " + user + '@' + remoteip + ":" + remotepath
            print  synccommand
            result = os.system(synccommand)
            if result:
                return 1
            else:
                return 0

    # build release
    def build(self, buildpath=None, buildcmd=None):
        if os.path.isdir(buildpath) and buildcmd:
            try:
                from subprocess import Popen,check_output, PIPE, STDOUT
                os.chdir(buildpath)
                out = Popen(buildcmd,shell=True,stdout=PIPE, stderr=STDOUT,close_fds=True)
                while True:
                    line = out.stdout.readline()
                    if not line and out.poll() is not None:
                        break
                    else:
                        print line.strip('\n')
                if out.returncode == 0:
                    return True
                else:
                    return False
            finally:
                pass

    # post json data to db
    def postJson(self, url=None, calldata={}, method='POST'):
        urldata = urllib.urlencode(calldata)
        ### print url + '?' + urldata
        if method == 'POST':
            request = urllib2.Request(url, data=urldata)
        elif method == 'GET':
            request = urllib2.Request(url + '?' + urldata)
        response = urllib2.urlopen(request)
        if response.code == 200:
            print response.read()
            return True
        else:
            print 'Request % code not is 200.' %(url)
            return False

    # request remote url
    def upProxy(self, url=None, pdata='', method='PUT'):
        if url:
            if method == "PUT":
                result = requests.put(url,timeout=30,data=pdata,auth=self.auth)
                if result.status_code == 200 and result.content == 'true':
                    return True
                else:
                    return False
            elif method == "DELETE":
                result = requests.delete(url,timeout=30,data=pdata,auth=self.auth)
                if result.status_code == 200 and result.content == 'true':
                    return True
                else:
                    return False
            elif method == "GET":
                result = requests.get(url,timeout=30,auth=self.auth)
                if result.status_code == 200:
                    return True
                else:
                    return False
        else:
            print 'url empty.'
            return False

    #query upstream ips
    def getServiceIps(self,url='',gdata={}):
        if url and gdata:
            getIps = requests.get(url,params=gdata,timeout=30)
            #print getIps.url
            if getIps.status_code == 200:
                adlist = []
                for ilist in getIps.json():
                    adlist.append(ilist['value'])
                if adlist:
                    return adlist
                else:
                    return False
            else:
                return False
        else:
            print "URL is None."
            return False

    #get rm release paths
    def getRmPaths(self,url='',pdata={}):
        if url and pdata:
            getpaths = requests.post(url,data=pdata,timeout=30)
            if getpaths.status_code == 200:
                outList = []
                #print getpaths.text
                for ilist in getpaths.json():
                   if 'error_code' not in ilist:
                       outList.append(ilist['project_value'])
                   else:
                       print '%s,Operating rules are not satisfied.' %ilist
                if outList:
                    return outList
                else:
                    return False
            else:
                return False
        else:
           print "url or post params is None."
           return False

    # set nginx upstream proxy rule
    def upstreamOp(self,url, pname, ip, op='down',weight='100'):
        if pname and ip:
            putData= '%s/%s' %(pname,ip)
            urlData = url + putData
            try:
                if op == 'down':
                    pdata = '{"weight":' + weight + ', "max_fails":2, "fail_timeout":10, "down":1}'
                    if self.upProxy(urlData,pdata=pdata,method='PUT'):
                        print 'op offine.'
                        return True
                    else:
                        return False
                elif op =='up':
                    pdata = '{"weight":' + weight + ', "max_fails":2, "fail_timeout":10, "down":0}'
                    if self.upProxy(urlData,pdata=pdata,method='PUT'):
                        print 'op online.'
                        return True
                    else:
                        return False
            except Exception ,e:
                print 'op server list error.'
                print e

    # set online or set offline
    def onOff(self, inop):
        if inop == 'Offine':
             return 'down'
        elif inop == 'Online':
             return 'up'

    # check url health
    def checkUrl(self,url):
        try:
            result = requests.get(url,timeout=2,auth=self.auth)
            #if result.status_code == 200:
            if result.status_code == 200 and result.json()['code'] == "200":
                return True
        except Exception:
            #print "check %s error." %(url)
            return False

    # build MySheBao Common
    def buildCommon(self,releasename):
        from config import config
        buildpath = config['Common']['buildpath']
        buildcmd = config['Common']['buildcmd']
        buildcmd = buildcmd.replace('develop',releasename)
        try:
           if buildpath and buildcmd:
               buildrlt = self.build(buildpath,buildcmd)
               if buildrlt:
                   return True
               else:
                   return False
           else:
               print 'buildpath or buildcmd is None.'
               return False
        except Exception ,e:
            print e

    def batchDeploy(self,projectname,node,config,userdata,op=None):

        releasetime = self.timestamp()
        getenv = projectname
        projectname = getenv.split(":")[0]
        remoteuser = config['remoteuser']
        posturl = config['posturl']
        geturl = config['geturl']
        upurl = config['upurl']
        downloadip = config['downloadip']
        downloadurl = config['downloadurl']
        rcodeln = config[projectname]['rcodeln']
        localdir = config[projectname]['localdir']
        buildpath = config[projectname]['buildpath']
        rcodedir = config['rcodedir']
        buildcmd = config['buildcmd']
        projectenv = config['env']

        # put release
        print "############## put release ###############"
        rd = rRedis()
        getRelease = str(rd.rget(getenv))
        print getRelease
        if getRelease:
            rcodedir =  rcodedir + projectname + getRelease
        else:
            print 'Please select the Build job, run the compiler first.'
            sys.exit(1)
        releasename = projectname + getRelease
        remoterlt = False
        if op:
            remoterlt = self.upstreamOp(upurl,projectname,node,'down')
        else:
            remoterlt = True
        ### restart remote app
        if remoterlt:
            ip = node.split (':')[0]
            command = 'rm -f ' + rcodeln + '; rm -rf ' + rcodeln.split('.war')[0]
            remoterlt = self.sshexec(ip, command,user=remoteuser)
        ### download release
        if remoterlt:
            wgetcmd = 'wget -O '+ rcodeln + ' ' + downloadurl + releasename
            #print wgetcmd
            remoterlt = self.sshexec(ip, wgetcmd,user=remoteuser)
        if remoterlt:
            time.sleep(3)
            restart = config[projectname]['restart']
            remoterlt = self.sshexec(ip, restart,user=remoteuser)
        if remoterlt:
            processid = 'ps aux|grep ' + rcodeln.split('webapps')[0] + '|grep -v grep'
            remoterlt = self.sshexec(ip,processid,user=remoteuser)
        if remoterlt:
            ### post release data
            postdata = {
                'username': userdata['username'],
                'password': userdata['password'],
                'project_name': projectname,
                'project_key': getRelease,
                'project_value': releasename + "," + rcodeln,
                'member_ip': node,
                'project_env':projectenv
            }
            print getRelease
            if self.postJson(posturl, postdata):
               remoterlt = True
            else:
               remoterlt = False
        if remoterlt:
           return True
        else:
           return False

    def rollBack(self,projectname,node,config,op=None):
        getenv = projectname
    projectname = getenv.split(":")[0]
        remoteuser = config['remoteuser']
        posturl = config['posturl']
        upurl = config['upurl']
        downloadip = config['downloadip']
        downloadurl = config['downloadurl']
        rcodeln = config[projectname]['rcodeln']
        # put release
        print "############## rollback release ###############"
        rd = rRedis()
        getRelease = str(rd.rget(getenv))
        print getRelease
        if getRelease:
            releasename = projectname + getRelease
            if op:
                remoterlt = self.upstreamOp(upurl,projectname,node,'down')
            else:
                remoterlt = True
            ### restart remote app
            if remoterlt:
                ip = node.split (':')[0]
                command = 'rm -f ' + rcodeln + '; rm -rf ' + rcodeln.split('.war')[0]
                remoterlt = self.sshexec(ip, command,user=remoteuser)
            ### download release
            if remoterlt:
                wgetcmd = 'wget -O '+ rcodeln + ' ' + downloadurl + releasename
                remoterlt = self.sshexec (ip, wgetcmd, user=remoteuser)
            if remoterlt:
                time.sleep(5)
                restart = config[projectname]['restart']
                remoterlt = self.sshexec(ip, restart,user=remoteuser)
            if remoterlt:
                processid = 'ps aux|grep ' + rcodeln.split('webapps')[0] + '|grep -v grep'
                remoterlt = self.sshexec(ip,processid,user=remoteuser)
            if remoterlt:
                return True
            else:
                return False
        else:
            print 'get release error.'
            return False


    def batchOnline(self,projectname,node,config):
        upurl = config['upurl']
        #### checkUrl ok and op online
        checkurl = 'http://' + node  + "/"+ projectname + "/checkhealth"
        if self.checkUrl(checkurl):
            print  "%s ok." %(checkurl)
            if self.upstreamOp(upurl,projectname,node,'up'):
                #print "op upstream %s ok" %(node)
                return False
        else:
            #print "%s not ready" %(node)
            return node

    def checkAppStatus(self,projectname,node,config):
        checkurl = 'http://' + node  + "/"+ projectname + "/checkhealth"
        print checkurl
        if self.checkUrl(checkurl):
            print  "%s ok." %(checkurl)
            return False
        else:
            #print "%s not ready" %(node)
            return node


### op redis
class rRedis:
    def __init__(self,host='127.0.0.1',port='6379',password=None):
        import redis
        try:
            self.rdpool = redis.ConnectionPool(host=host, port=port,password=password)
            self.rdop = redis.Redis(connection_pool=self.rdpool)
        except Exception, e:
            print 'redis connect failed.'
            print e

    def rset(self, key,value):
        if key and value:
            try:
                self.rdop.set(key,value,ex=99999999)
            except Exception ,e:
                 print 'redis set error.'
                 print e
                 return False
            return True
        else:
            print 'error,key or value is empty.'

    def rget(self, key):
        if key:
           result = self.rdop.get(key)
        if result:
           return result
        else:
           return False

    def rclose(self):
        self.rdpool.release(self.rdpool.get_connection(self.rdpool))
        print 'close redis connect.'

(ps: 本脚是较久以前编写,如需要在生产或其他环境使用,请另行改造)

相关文章

网友评论

      本文标题:基础自动化发布SDK,Python版

      本文链接:https://www.haomeiwen.com/subject/fmtmcftx.html