#!usr/bin/env python
# _*_ coding:utf-8 _*_
"""
@note: 自动注册服务
@author: jiashunx
@file: auto_register.py
@time: 2019/10/11
"""


import urllib2
import base64
from threading import Timer


class AutoRegister:
    def __init__(self, req_model):
        self.req_model = req_model

    @staticmethod
    def _get_request_models(apps):
        req_models = []
        for app in apps:
            instance = app["instance"]
            json_body = AutoRegister._get_request_json_body(instance=instance)
            registers = app["registers"]
            for register in registers:
                username = None
                password = None
                if "username" in register:
                    username = register["username"]
                if "password" in register:
                    password = register["password"]
                req_models.append(RequestModel(
                    register_url=AutoRegister._format_register_url(register["url"]),
                    username=username,
                    password=password,
                    json_body=json_body,
                    instance=instance
                ))
        return req_models

    @staticmethod
    def _format_register_url(url):
        if url is not None and len(url) > 0:
            if not url.endswith("/"):
                url += "/"
            if not url.endswith("eureka/"):
                url += "eureka/"
        return url

    @staticmethod
    def _get_request_json_body(instance):
        ipAddr = instance["ipAddr"]
        schema = "http://"
        port = instance["port"]
        if instance["securePortEnable"]:
            schema = "https://"
            port = instance["securePort"]
        homePageUrl = schema + ipAddr + ":" + str(port) + "/"
        statusPageUrl = homePageUrl + "Status"
        healthCheckUrl = homePageUrl + "healthcheck"
        return "<instance>" \
               + "<instanceId>" + instance["instanceId"] + "</instanceId>"\
               + "<hostName>" + instance["ipAddr"] + "</hostName>"\
               + "<app>" + instance["appId"] + "</app>"\
               + "<ipAddr>" + instance["ipAddr"] + "</ipAddr>"\
               + "<status>UP</status>"\
               + "<overriddenstatus>UNKNOWN</overriddenstatus>"\
               + "<port enable=\"" + str(instance["portEnable"]).lower() + "\">" + str(instance["port"]) + "</port>"\
               + "<securePort enabled=\"" + str(instance["securePortEnable"]).lower() + "\">" + str(instance["securePort"]) + "</securePort>"\
               + "<vipAddress>" + instance["vipAddress"] + "</vipAddress>"\
               + "<secureVipAddress>" + instance["secureVipAddress"] + "</secureVipAddress>"\
               + "<dataCenterInfo class=\"com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo\">"\
               + "<name>MyOwn</name>"\
               + "</dataCenterInfo>"\
               + "<metadata></metadata>"\
               + "<homePageUrl>" + homePageUrl + "</homePageUrl>"\
               + "<statusPageUrl>" + statusPageUrl + "</statusPageUrl>"\
               + "<healthCheckUrl>" + healthCheckUrl + "</healthCheckUrl>"\
               + "</instance>"

    @staticmethod
    def start(apps):
        req_models = AutoRegister._get_request_models(apps)
        for req_model in req_models:
            AutoRegister(req_model=req_model)._auto_register()

    def _auto_register(self):
        self._register()
        self._heartbeat()

    def _get_authorization_value(self):
        return "Basic " + base64.b64encode(str(self.req_model.username) + ":" + str(self.req_model.password))

    def _register(self):
        success = False
        try:
            request_url = self.req_model.register_url + "apps/" + self.req_model.appId
            request = urllib2.Request(url=request_url, data=self.req_model.json_body, headers={
                "Content-Type": "application/xml",
                "Authorization": self._get_authorization_value()
            })
            request.get_method = lambda: "POST"
            response = urllib2.urlopen(request)
            if response.code == 204:
                success = True
                print("service:%s register success, target register-center: %s" % (str(self.req_model), self.req_model.register_url))
        except Exception, e:
            print("service:%s register failed, target register-center: %s, error reason: %s" % (str(self.req_model), self.req_model.register_url, str(e)))
        finally:
            return success

    def _heartbeat(self):
        success = False
        try:
            request_url = self.req_model.register_url + "apps/" + self.req_model.appId + "/" + self.req_model.instanceId
            request = urllib2.Request(url=request_url, headers={
                "Authorization": self._get_authorization_value()
            })
            request.get_method = lambda: "PUT"
            response = urllib2.urlopen(request)
            if response.code == 200:
                success = True
                print("service:%s heartbeat success, target register-center: %s" % (str(self.req_model), self.req_model.register_url))
        except Exception, e:
            print("service:%s heartbeat failed, target register-center: %s, error reason: %s" % (str(self.req_model), self.req_model.register_url, str(e)))
        if not success:
            print("service: %s heartbeat to register-center: %s failed, retry to register" % (str(self.req_model), self.req_model.register_url))
            self._register()
        # 心跳间隔-30s
        Timer(30, self._heartbeat).start()


class RequestModel:
    def __init__(self, register_url, username, password, json_body, instance):
        self.register_url = register_url
        self.username = username;
        self.password = password;
        self.json_body = json_body
        self.instance = instance
        self.appId = instance["appId"]
        self.instanceId = instance["instanceId"]

    def __str__(self):
        return "{appId=%s, vipAddrss=%s, instanceId=%s}" % (self.instance["appId"], self.instance["vipAddress"], self.instance["instanceId"])


if __name__ == "__main__":
    AutoRegister.start([
        {
            "instance": {
                "appId": "appId",
                "instanceId": "instanceId",
                "vipAddress": "vipAddress",
                "secureVipAddress": "vipAddress",
                "ipAddr": "127.0.0.1",
                "portEnable": True,
                "port": 8080,
                "securePortEnable": False,
                "securePort": 443
            },
            "registers": [
                {"url": "http://127.0.0.1:9081/"},
                {"url": "http://127.0.0.1:9082/"}
            ]
        },
        {
            "instance": {
                "appId": "appId",
                "instanceId": "instanceId",
                "vipAddress": "vipAddress",
                "secureVipAddress": "vipAddress",
                "ipAddr": "127.0.0.1",
                "portEnable": True,
                "port": 8081,
                "securePortEnable": False,
                "securePort": 443
            },
            "registers": [
                # 开启安全认证的注册中心,指定用户名及密码
                # 注册中心可添加参数关闭安全认证: -Dspring.security.enabled=false
                {"url": "http://127.0.0.1:9083/", "username": "admin", "password": "admin123"}
            ]
        }
    ])

jiashunx
1 声望0 粉丝