#!/bin/env python
#coding=utf-8
#edite  panwang
import docker
import sys
import  requests
import json
import queue
import threading
from aliyunsdkcore import client
from aliyunsdkecs.request.v20140526.DescribeNetworkInterfacesRequest import DescribeNetworkInterfacesRequest
from aliyunsdkcore.request import CommonRequest
from aliyunsdkslb.request.v20140515.DescribeLoadBalancerAttributeRequest import DescribeLoadBalancerAttributeRequest
import time


AccessKey = 'LTAIuPbTPL3LDDKN'
AccessSecret = 'ORcNedKwWuwVtcq4IRFtUDZgS0b1le'
RegionId = 'cn-hangzhou'
version = sys.argv[1]
slbIDs = ['lb-bp1jtzhp9krunyv3mim2q','lb-bp1mfk1gmd47twfh6bgwv']
#slbIDs = ['lb-bp136gme0r0n02aew4vjc','lb-bp1mfk1gmd47twfh6bgwv']
apps = 'piaoquan-gateway'
repository = 'registry-vpc.cn-hangzhou.aliyuncs.com/stuuudy/{}'.format(apps)
registry = 'registry-vpc.cn-hangzhou.aliyuncs.com/stuuudy/{}:{}'.format(apps, version)



clt = client.AcsClient (AccessKey, AccessSecret, RegionId)

class MyThread (threading.Thread):
    def __init__(self, func):
        threading.Thread.__init__ (self)

        self.func = func

    def run(self):
        self.func ()

def  checkHealth(ipadd):
    while  True:
        health_url = 'http://%s:9000/healthcheck' %(ipadd)
        header = {"Content-Type":"application/json"}
        try:
            health_code = requests.get(health_url).status_code
        except  Exception  as  e:
           continue
        if  health_code == 200:
            print("httpcode 200,开始挂载流量")
            return  False
#服务更新完之后逐步修改服务器的权重值,直接加载100会出现502。权重值每次增加10,每2s修改一次
def setInstanceWeightProcess(slb_id, instance_id):
    for  i in range(1,6):
        weight = i*20
        setWeight(slb_id,instance_id,weight)
        print("当前权重: ", weight)
        time.sleep(5)

#设置权重 instance_id :服务器id,weight:权重值
def setWeight(slb_id,instance_id ,weight):

    BackendServers = [{"ServerId": instance_id, "Weight": weight}]

    request = CommonRequest ()
    request.set_accept_format ('json')
    request.set_domain ('slb.aliyuncs.com')
    request.set_version ('2014-05-15')
    request.set_method ('POST')
    request.set_action_name ('SetBackendServers')
    request.add_query_param ('BackendServers', BackendServers)
    request.add_query_param ('LoadBalancerId', slb_id)
    try:
        response = clt.do_action (request)
    except Exception as e:
        print (e)


def  getInstanceId(slb_id):
    request = DescribeLoadBalancerAttributeRequest()
    request.set_accept_format('json')
    request.set_LoadBalancerId(slb_id)
    response = clt.do_action_with_exception(request)
    return json.loads (response)


#获取实例IP地址
def  getIpadd(instance_id):
    request = DescribeNetworkInterfacesRequest()
    request.set_accept_format('json')
    request.set_InstanceId(instance_id)
    response = clt.do_action_with_exception(request)
    request_content = json.loads(response)
    IpAddr  = request_content['NetworkInterfaceSets']['NetworkInterfaceSet'][0]['PrivateIpAddress']
    return  IpAddr


#更新服务
def  update(instance_id):
    time.sleep(10)
    global success_count

    ipadd = getIpadd(instance_id)
    print("服务器信息:" + "%s/%s" %(instance_id, ipadd))
    client = docker.DockerClient(base_url='tcp://%s:2375'  %(ipadd),timeout=60 )
    try:
    #更新前移除旧的容器
        id = client.containers.get(apps)
        id.remove(force = True)

    except Exception as e:
        print("容器不存在或者无法删除当前容器")

    try:
        #登录镜像仓库
        client.login(username='stuuudys' ,password='Qingqu@2019', registry='registry-vpc.cn-hangzhou.aliyuncs.com')
        #启动一个容器
        client.containers.run(registry, detach = True, cap_add = 'SYS_PTRACE', network_mode = 'host', name = apps,volumes={'/datalog/': {'bind': '/datalog/', 'mode': 'rw'}})
        print("开始健康检查")
        checkHealth(ipadd)
        print("%s :权重修改中......" %(ipadd))

        for slbID in slbIDs:
            setInstanceWeightProcess(slbID, instance_id)
        success_count = success_count + 1
        print("更新进度" + "%s/%s"  %(success_count, total))
    except Exception as e:
        print(e)
        sys.exit()
        #容器启动失败立即退出更新


def  pull_image():
    instanceId = q1.get()
    ipaddr = getIpadd(instanceId)
    cd_url = "tcp://{}:2375".format(ipaddr)
    client = docker.DockerClient(base_url=cd_url, timeout=30)

    try:
        client.images.pull(repository, tag=version)
        print(ipaddr, "pull  images success ")

        return  True
    except Exception as e:
        print(e, "images pull  fail")
        return  False


if __name__ == '__main__':


    #更新完成计数
    success_count = 0
    threads = []
    res = getInstanceId (slbIDs[0])
    #slb下服务器总数
    total = len(res["BackendServers"]["BackendServer"])
    InstanceIDs = []
    q1 = queue.Queue()
    if res["BackendServers"]["BackendServer"]:
        for i in range ((len (res["BackendServers"]["BackendServer"]))):
            InstanceID = res["BackendServers"]["BackendServer"][i]["ServerId"]
            InstanceIDs.append(InstanceID)
            q1.put(InstanceID)
    print(InstanceIDs)
    #多线程预先pull images
    for i in range (len(InstanceIDs)):
        thread = MyThread (pull_image)
        thread.start ()
        threads.append(thread)
    for thread in threads:
            thread.join ()

    #单线程更新
    for instanceID in InstanceIDs:
        for slbID in slbIDs:
            setWeight(slbID,instanceID,0)
        update(instanceID)