美文网首页
基础自动化发布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