Authored by root

初始化负载均衡权重切换模块

#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
修改腾讯云七层负载均衡器的权重
@see doc: https://cloud.tencent.com/document/product/214/8978
"""
from qcloud.qcloud_api import QcloudApi
import time, sys, os
import json
"""
作用:切换负载均衡器的权重
"""
def modify_clb_weight(SecretId, SecretKey, lb_id, ip_weight_dict={}, hostname_weight_dict={}, default_weight=0):
"""
修改传统负载均衡器的权重
@:param lb_id 负载均衡器的ID
@:param ip_weight_dict 需要设置权重的后端IP-权重字典, 格式为 {'ip': weight }
:return: True: 修改成功
"""
# 1.获取传统型负载均衡器的后端列表
# see details at: https://cloud.tencent.com/document/api/214/1259
instance_weight = {} # instance_id --> weight
api = QcloudApi(secretId=SecretId, secretKey=SecretKey)
lb_info = api.do_query(params={'Action': 'DescribeLoadBalancerBackends', 'loadBalancerId': lb_id}, req_url=QcloudApi.URLS_lb)
for backend in lb_info['backendSet']:
if ip_weight_dict:
if backend['lanIp'] in ip_weight_dict.keys():
# setup the instance_id --> weight
instance_weight[backend['unInstanceId']] = ip_weight_dict[backend['lanIp']]
else:
instance_weight[backend['unInstanceId']] = default_weight
elif hostname_weight_dict:
if backend['instanceName'] in hostname_weight_dict.keys():
# setup the instance_id --> weight
instance_weight[backend['unInstanceId']] = hostname_weight_dict[backend['unInstanceId']]
else:
instance_weight[backend['unInstanceId']] = default_weight
else:
break
# 2.检查至少有一个weight不为0
if len(filter(lambda w: w != 0, instance_weight.values())) == 0:
sys.exit(" instance weight: %s is all zero. please check again!" % instance_weight)
# 3.修改权重: https://cloud.tencent.com/document/api/214/1264
modify_params = {'Action': 'ModifyLoadBalancerBackends', 'loadBalancerId': lb_id}
i = 1
for ins_id, ins_weight in instance_weight.iteritems():
modify_params['backends.%i.instanceId' % i] = ins_id
modify_params['backends.%i.weight' % i] = ins_weight
i = i + 1
api = QcloudApi(secretId=SecretId, secretKey=SecretKey)
rsp = api.do_query(params=modify_params, req_url=QcloudApi.URLS_lb)
return rsp['code'] == 0
def modify_alb_weight(SecretId, SecretKey, lb_id, domain, ip_weight_dict={}, hostname_weight_dict={},default_weight=0):
"""
修改应用型负载均衡器上服务器的权重
@:param lb_id: 应用型负载均衡器ID
@:param domain: 应用型负载均衡器的domain
@:param ip_weight_dict: 需要设置权重的dict, 格式为 {'ip': weight }
@return list
"""
# 查询ALB的监听器信息
# see qcloud api details at: https://cloud.tencent.com/document/product/214/8987
instance_weight = {} # instance_id --> weight
instance_port = {} # instance_id --> port
listener_ids = {} # all linsters
hostname_ip_map = {} # instance_name --> ip
api = QcloudApi(secretId=SecretId, secretKey=SecretKey)
lb_info = api.do_query(params={'Action': 'DescribeForwardLBBackends', 'loadBalancerId': lb_id}, req_url=QcloudApi.URLS_lb)
# listener : [http , https]
for listener in lb_info['data']:
for rule in listener['rules']:
if rule['domain'] == domain: # domain match
listener_ids[listener['listenerId']] = listener['protocolType']
for backend in rule['backends']:
instance_port[backend['unInstanceId']] = backend['port']
if ip_weight_dict:
if backend['lanIp'] in ip_weight_dict.keys():
# setup the instance_id --> weight
instance_weight[backend['unInstanceId']] = ip_weight_dict[backend['lanIp']]
if hostname_ip_map.has_key(backend['instanceName']):
hostname_ip_map[backend['instanceName']].append(backend['lanIp'])
else:
hostname_ip_map[backend['instanceName']] = [backend['lanIp']]
else:
instance_weight[backend['unInstanceId']] = default_weight
elif hostname_weight_dict:
if backend['instanceName'] in hostname_weight_dict.keys():
# setup the instance_id --> weight
instance_weight[backend['unInstanceId']] = hostname_weight_dict[backend['instanceName']]
else:
instance_weight[backend['unInstanceId']] = default_weight
else:
break
# 检查至少有一个weight
if len(filter(lambda w: w != 0, instance_weight.values())) == 0:
sys.exit(" instance weight: %s is all zero. please check again!" % instance_weight)
# 修改七层负载均衡器的权重
# see details at: https://cloud.tencent.com/document/product/214/8978
return_code = []
for lis_id in listener_ids.keys():
params = {'Action': 'ModifyForwardSeventhBackends', 'loadBalancerId': lb_id,
'listenerId': lis_id, 'domain': domain}
i = 1
for ins_id, ins_weight in instance_weight.iteritems():
params['backends.%i.instanceId' % i] = ins_id
params['backends.%i.weight' % i] = ins_weight
params['backends.%i.port' % i] = instance_port[ins_id]
i = i + 1
rsp = api.do_query(params, req_url=QcloudApi.URLS_lb)
print(u"response code: %s . success change domain: %s for listener : %s. wait for 10s" % (rsp['code'], domain, listener_ids[lis_id]))
return_code.append(rsp['code'])
time.sleep(10)
return return_code.count(0) == len(return_code)
def describe_lbs(SecretId, SecretKey):
api = QcloudApi(secretId=SecretId, secretKey=SecretKey)
lb_info = api.do_query(params={'Action': 'DescribeLoadBalancers', 'forward': -1, 'limit':100, 'withRs':1}, req_url=QcloudApi.URLS_lb)
return lb_info['loadBalancerSet']
... ...
No preview for this file type
#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
修改腾讯云七层负载均衡器的权重
demo: python lb_switch.py --secretid=AKID6**************dwpKK --secretkey=ACJk9**************sQaW --lb_name=ytx-switch-test --domain=search.yohoops.org --hostname=search-service-az2 --weight=10
@see doc: https://cloud.tencent.com/document/product/214/8978
"""
import time, sys, os
import argparse
from lb_action import modify_clb_weight,modify_alb_weight,describe_lbs
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('--secretid',type=str,help='腾讯云 SecretId')
parser.add_argument('--secretkey',type=str,help='腾讯云 SecretKey')
parser.add_argument('--lb_name',type=str,help='负载均衡器名称')
parser.add_argument('--domain',type=str,default='',help='应用型负载均衡器的域名')
parser.add_argument('--hostname',type=str,help='负载均衡器后端绑定的主机名称')
parser.add_argument('--weight',type=int,help='需要调整的主机权重')
parser.add_argument('--default_weight',type=int,default=0,help='同域名/负载均衡器下其他主机默认权重')
args = parser.parse_args()
lbs = describe_lbs(args.secretid,args.secretkey)
lb_id = ''
for lb in lbs:
if lb['loadBalancerName'].encode('utf-8') == args.lb_name:
lb_id = lb['loadBalancerId']
break
if not lb_id:
print '未找到负载均衡器{0}'.format(args.lb_name)
sys.exit(1)
else:
hostname_weight_dict = {
args.hostname: args.weight
}
if args.domain:
modify_alb_weight(args.secretid, args.secretkey, lb_id, args.domain, hostname_weight_dict=hostname_weight_dict, default_weight=args.default_weight)
else:
modify_clb_weight(args.secretid, args.secretkey, lb_id, hostname_weight_dict=hostname_weight_dict, default_weight=args.default_weight)
... ...
{
"lb-8gm6tsyr": {
"domain":"search.yohoops.org",
"mappings": {
"10.66.104.14": 10,
"10.66.104.4": 10,
"10.66.104.9": 10
}
}
}
... ...
No preview for this file type
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import smtplib
from email.mime.text import MIMEText
from email.header import Header
import time
class mailman(object):
def __init__(self):
self.sender = 'robot@yohoops.cn'
self.smtpObj = smtplib.SMTP('localhost')
def mail(self,receivers=[],Content='Test Mail',From ='Robot',To='YOHOOPS',Title='Test Mail'):
message = MIMEText(Content, 'plain', 'utf-8')
message['From'] = Header(From, 'utf-8')
message['To'] = Header(To, 'utf-8')
message['Subject'] = Header(Title, 'utf-8')
retry = 5
while retry>0:
try:
self.smtpObj.sendmail(self.sender, receivers, message.as_string())
print "邮件发送成功"
return True
except Exception as e:
retry-=1
print e
print "Error: 无法发送邮件"
print "重新发送邮件...还剩{0}次".format(retry)
time.sleep(10)
return False
if __name__ == '__main__':
demo = mailman()
demo.mail(['tiexin.yang@yoho.cn'])
... ...
No preview for this file type
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# author chunhua.zhang@yoho.cn
import random
import hmac
import base64
import hashlib
import time
import requests
import json
class QcloudApi:
"""腾讯云API接口"""
'pre-defined url'
'load balance'
URLS_lb = 'lb.api.qcloud.com/v2/index.php'
URLS_DNS = 'cns.api.qcloud.com/v2/index.php'
'public request params'
Region = 'ap-beijing'
Version = 'YOHO-QCLOUD-V1.0'
'see doc: https://www.qcloud.com/document/api/377/4153'
'init. must provide SecretId and SecretKey'
def __init__(self, secretId, secretKey):
self.secretId = secretId
self.secretKey = secretKey
def do_query(self, params, req_url=URLS_lb, api_version=2):
"""
Do Query Qcloud api
:param params: 查询参数,dict类型,必须包含 Action
:param req_url: 查询的地址,参考:qcloud_api.URLS_lb --> lb.api.qcloud.com/v2/index.php
:return: dict类型,腾讯云返回的消息体
"""
if 'Action' not in params:
print("must provide [Action] params !")
raise ValueError(params)
if api_version == 2:
public_params = {'RequestClient': QcloudApi.Version, 'limit': 100, 'Region': QcloudApi.Region, 'Timestamp': int(time.time()), 'Nonce': QcloudApi.generate_nonce(), 'SecretId': self.secretId}
# merge params
params = dict(params, **public_params)
# signature
sign = self.signature(params, req_url)
params['Signature'] = sign
response_dict = requests.post("https://" + req_url, data=params).json()
elif api_version == 3:
public_params = {'Region': QcloudApi.Region, 'Timestamp': int(time.time()), 'Nonce': int(QcloudApi.generate_nonce()), 'Version': '2017-03-12', 'SecretId': self.secretId, 'SignatureMethod':'HmacSHA1'}
# merge params
params = dict(params, **public_params)
# signature
req_url = req_url.rstrip('/')+'/'
sign = self.signature(params, req_url)
params['Signature'] = sign
response_dict = requests.post("https://" + req_url, data=params).json()
#print("call qcloud api success. params:\n %s \n" % (params))
#print json.dumps(response_dict, indent=4, sort_keys=True)
return response_dict
@staticmethod
def generate_nonce(length=8):
"""Generate pseudorandom number."""
return ''.join([str(random.randint(0, 9)) for i in range(length)])
def signature(self, request_params, url):
"""
对消息进行签名 see https://www.qcloud.com/document/api/377/4214
@param request_params
@param url, 请求地址,例如:lb.api.qcloud.com/v2/index.php
"""
# sort dict by key
kv_pairs = []
for key in sorted(request_params):
kv_pairs.append('%s=%s' % (key, request_params[key]))
str_req = '&'.join(kv_pairs)
str_full = 'POST%s?%s' % (url, str_req)
hmac_sign = hmac.new(bytes(self.secretKey), bytes(str_full), hashlib.sha1).digest()
return base64.b64encode(hmac_sign).decode()
... ...
No preview for this file type