Showing
11 changed files
with
323 additions
and
0 deletions
scripts/lb_manager/lb_action.py
0 → 100644
1 | +#!/usr/bin/python | ||
2 | +# -*- coding: UTF-8 -*- | ||
3 | + | ||
4 | +""" | ||
5 | +修改腾讯云七层负载均衡器的权重 | ||
6 | + | ||
7 | +@see doc: https://cloud.tencent.com/document/product/214/8978 | ||
8 | + | ||
9 | +""" | ||
10 | + | ||
11 | +from qcloud.qcloud_api import QcloudApi | ||
12 | +import time, sys, os | ||
13 | +import json | ||
14 | + | ||
15 | + | ||
16 | + | ||
17 | +""" | ||
18 | + 作用:切换负载均衡器的权重 | ||
19 | +""" | ||
20 | + | ||
21 | +def modify_clb_weight(SecretId, SecretKey, lb_id, ip_weight_dict={}, hostname_weight_dict={}, default_weight=0): | ||
22 | + """ | ||
23 | + 修改传统负载均衡器的权重 | ||
24 | + @:param lb_id 负载均衡器的ID | ||
25 | + @:param ip_weight_dict 需要设置权重的后端IP-权重字典, 格式为 {'ip': weight } | ||
26 | + :return: True: 修改成功 | ||
27 | + """ | ||
28 | + # 1.获取传统型负载均衡器的后端列表 | ||
29 | + # see details at: https://cloud.tencent.com/document/api/214/1259 | ||
30 | + instance_weight = {} # instance_id --> weight | ||
31 | + | ||
32 | + api = QcloudApi(secretId=SecretId, secretKey=SecretKey) | ||
33 | + lb_info = api.do_query(params={'Action': 'DescribeLoadBalancerBackends', 'loadBalancerId': lb_id}, req_url=QcloudApi.URLS_lb) | ||
34 | + for backend in lb_info['backendSet']: | ||
35 | + if ip_weight_dict: | ||
36 | + if backend['lanIp'] in ip_weight_dict.keys(): | ||
37 | + # setup the instance_id --> weight | ||
38 | + instance_weight[backend['unInstanceId']] = ip_weight_dict[backend['lanIp']] | ||
39 | + else: | ||
40 | + instance_weight[backend['unInstanceId']] = default_weight | ||
41 | + elif hostname_weight_dict: | ||
42 | + if backend['instanceName'] in hostname_weight_dict.keys(): | ||
43 | + # setup the instance_id --> weight | ||
44 | + instance_weight[backend['unInstanceId']] = hostname_weight_dict[backend['unInstanceId']] | ||
45 | + else: | ||
46 | + instance_weight[backend['unInstanceId']] = default_weight | ||
47 | + else: | ||
48 | + break | ||
49 | + | ||
50 | + # 2.检查至少有一个weight不为0 | ||
51 | + if len(filter(lambda w: w != 0, instance_weight.values())) == 0: | ||
52 | + sys.exit(" instance weight: %s is all zero. please check again!" % instance_weight) | ||
53 | + | ||
54 | + # 3.修改权重: https://cloud.tencent.com/document/api/214/1264 | ||
55 | + modify_params = {'Action': 'ModifyLoadBalancerBackends', 'loadBalancerId': lb_id} | ||
56 | + i = 1 | ||
57 | + for ins_id, ins_weight in instance_weight.iteritems(): | ||
58 | + modify_params['backends.%i.instanceId' % i] = ins_id | ||
59 | + modify_params['backends.%i.weight' % i] = ins_weight | ||
60 | + i = i + 1 | ||
61 | + api = QcloudApi(secretId=SecretId, secretKey=SecretKey) | ||
62 | + rsp = api.do_query(params=modify_params, req_url=QcloudApi.URLS_lb) | ||
63 | + return rsp['code'] == 0 | ||
64 | + | ||
65 | + | ||
66 | +def modify_alb_weight(SecretId, SecretKey, lb_id, domain, ip_weight_dict={}, hostname_weight_dict={},default_weight=0): | ||
67 | + """ | ||
68 | + 修改应用型负载均衡器上服务器的权重 | ||
69 | + @:param lb_id: 应用型负载均衡器ID | ||
70 | + @:param domain: 应用型负载均衡器的domain | ||
71 | + @:param ip_weight_dict: 需要设置权重的dict, 格式为 {'ip': weight } | ||
72 | + @return list | ||
73 | + """ | ||
74 | + | ||
75 | + # 查询ALB的监听器信息 | ||
76 | + # see qcloud api details at: https://cloud.tencent.com/document/product/214/8987 | ||
77 | + instance_weight = {} # instance_id --> weight | ||
78 | + instance_port = {} # instance_id --> port | ||
79 | + listener_ids = {} # all linsters | ||
80 | + hostname_ip_map = {} # instance_name --> ip | ||
81 | + | ||
82 | + | ||
83 | + api = QcloudApi(secretId=SecretId, secretKey=SecretKey) | ||
84 | + lb_info = api.do_query(params={'Action': 'DescribeForwardLBBackends', 'loadBalancerId': lb_id}, req_url=QcloudApi.URLS_lb) | ||
85 | + | ||
86 | + # listener : [http , https] | ||
87 | + for listener in lb_info['data']: | ||
88 | + for rule in listener['rules']: | ||
89 | + if rule['domain'] == domain: # domain match | ||
90 | + listener_ids[listener['listenerId']] = listener['protocolType'] | ||
91 | + for backend in rule['backends']: | ||
92 | + instance_port[backend['unInstanceId']] = backend['port'] | ||
93 | + if ip_weight_dict: | ||
94 | + if backend['lanIp'] in ip_weight_dict.keys(): | ||
95 | + # setup the instance_id --> weight | ||
96 | + instance_weight[backend['unInstanceId']] = ip_weight_dict[backend['lanIp']] | ||
97 | + if hostname_ip_map.has_key(backend['instanceName']): | ||
98 | + hostname_ip_map[backend['instanceName']].append(backend['lanIp']) | ||
99 | + else: | ||
100 | + hostname_ip_map[backend['instanceName']] = [backend['lanIp']] | ||
101 | + else: | ||
102 | + instance_weight[backend['unInstanceId']] = default_weight | ||
103 | + elif hostname_weight_dict: | ||
104 | + if backend['instanceName'] in hostname_weight_dict.keys(): | ||
105 | + # setup the instance_id --> weight | ||
106 | + instance_weight[backend['unInstanceId']] = hostname_weight_dict[backend['instanceName']] | ||
107 | + else: | ||
108 | + instance_weight[backend['unInstanceId']] = default_weight | ||
109 | + else: | ||
110 | + break | ||
111 | + | ||
112 | + # 检查至少有一个weight | ||
113 | + if len(filter(lambda w: w != 0, instance_weight.values())) == 0: | ||
114 | + sys.exit(" instance weight: %s is all zero. please check again!" % instance_weight) | ||
115 | + | ||
116 | + # 修改七层负载均衡器的权重 | ||
117 | + # see details at: https://cloud.tencent.com/document/product/214/8978 | ||
118 | + return_code = [] | ||
119 | + for lis_id in listener_ids.keys(): | ||
120 | + params = {'Action': 'ModifyForwardSeventhBackends', 'loadBalancerId': lb_id, | ||
121 | + 'listenerId': lis_id, 'domain': domain} | ||
122 | + i = 1 | ||
123 | + for ins_id, ins_weight in instance_weight.iteritems(): | ||
124 | + params['backends.%i.instanceId' % i] = ins_id | ||
125 | + params['backends.%i.weight' % i] = ins_weight | ||
126 | + params['backends.%i.port' % i] = instance_port[ins_id] | ||
127 | + i = i + 1 | ||
128 | + | ||
129 | + rsp = api.do_query(params, req_url=QcloudApi.URLS_lb) | ||
130 | + print(u"response code: %s . success change domain: %s for listener : %s. wait for 10s" % (rsp['code'], domain, listener_ids[lis_id])) | ||
131 | + return_code.append(rsp['code']) | ||
132 | + time.sleep(10) | ||
133 | + return return_code.count(0) == len(return_code) | ||
134 | + | ||
135 | + | ||
136 | +def describe_lbs(SecretId, SecretKey): | ||
137 | + api = QcloudApi(secretId=SecretId, secretKey=SecretKey) | ||
138 | + lb_info = api.do_query(params={'Action': 'DescribeLoadBalancers', 'forward': -1, 'limit':100, 'withRs':1}, req_url=QcloudApi.URLS_lb) | ||
139 | + return lb_info['loadBalancerSet'] |
scripts/lb_manager/lb_action.pyc
0 → 100644
No preview for this file type
scripts/lb_manager/lb_switch.py
0 → 100644
1 | +#!/usr/bin/python | ||
2 | +# -*- coding: UTF-8 -*- | ||
3 | + | ||
4 | +""" | ||
5 | +修改腾讯云七层负载均衡器的权重 | ||
6 | + | ||
7 | +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 | ||
8 | + | ||
9 | +@see doc: https://cloud.tencent.com/document/product/214/8978 | ||
10 | + | ||
11 | +""" | ||
12 | + | ||
13 | +import time, sys, os | ||
14 | +import argparse | ||
15 | +from lb_action import modify_clb_weight,modify_alb_weight,describe_lbs | ||
16 | + | ||
17 | + | ||
18 | +if __name__ == "__main__": | ||
19 | + parser = argparse.ArgumentParser() | ||
20 | + parser.add_argument('--secretid',type=str,help='腾讯云 SecretId') | ||
21 | + parser.add_argument('--secretkey',type=str,help='腾讯云 SecretKey') | ||
22 | + parser.add_argument('--lb_name',type=str,help='负载均衡器名称') | ||
23 | + parser.add_argument('--domain',type=str,default='',help='应用型负载均衡器的域名') | ||
24 | + parser.add_argument('--hostname',type=str,help='负载均衡器后端绑定的主机名称') | ||
25 | + parser.add_argument('--weight',type=int,help='需要调整的主机权重') | ||
26 | + parser.add_argument('--default_weight',type=int,default=0,help='同域名/负载均衡器下其他主机默认权重') | ||
27 | + args = parser.parse_args() | ||
28 | + lbs = describe_lbs(args.secretid,args.secretkey) | ||
29 | + lb_id = '' | ||
30 | + for lb in lbs: | ||
31 | + if lb['loadBalancerName'].encode('utf-8') == args.lb_name: | ||
32 | + lb_id = lb['loadBalancerId'] | ||
33 | + break | ||
34 | + | ||
35 | + if not lb_id: | ||
36 | + print '未找到负载均衡器{0}'.format(args.lb_name) | ||
37 | + sys.exit(1) | ||
38 | + else: | ||
39 | + | ||
40 | + hostname_weight_dict = { | ||
41 | + args.hostname: args.weight | ||
42 | + } | ||
43 | + | ||
44 | + if args.domain: | ||
45 | + modify_alb_weight(args.secretid, args.secretkey, lb_id, args.domain, hostname_weight_dict=hostname_weight_dict, default_weight=args.default_weight) | ||
46 | + else: | ||
47 | + modify_clb_weight(args.secretid, args.secretkey, lb_id, hostname_weight_dict=hostname_weight_dict, default_weight=args.default_weight) |
No preview for this file type
scripts/lb_manager/qcloud/__init__.py
0 → 100644
scripts/lb_manager/qcloud/__init__.pyc
0 → 100644
No preview for this file type
scripts/lb_manager/qcloud/mailer.py
0 → 100644
1 | +#!/usr/bin/python | ||
2 | +# -*- coding: UTF-8 -*- | ||
3 | + | ||
4 | +import smtplib | ||
5 | +from email.mime.text import MIMEText | ||
6 | +from email.header import Header | ||
7 | +import time | ||
8 | + | ||
9 | + | ||
10 | +class mailman(object): | ||
11 | + def __init__(self): | ||
12 | + self.sender = 'robot@yohoops.cn' | ||
13 | + self.smtpObj = smtplib.SMTP('localhost') | ||
14 | + | ||
15 | + def mail(self,receivers=[],Content='Test Mail',From ='Robot',To='YOHOOPS',Title='Test Mail'): | ||
16 | + message = MIMEText(Content, 'plain', 'utf-8') | ||
17 | + message['From'] = Header(From, 'utf-8') | ||
18 | + message['To'] = Header(To, 'utf-8') | ||
19 | + message['Subject'] = Header(Title, 'utf-8') | ||
20 | + | ||
21 | + retry = 5 | ||
22 | + while retry>0: | ||
23 | + try: | ||
24 | + self.smtpObj.sendmail(self.sender, receivers, message.as_string()) | ||
25 | + print "邮件发送成功" | ||
26 | + return True | ||
27 | + except Exception as e: | ||
28 | + retry-=1 | ||
29 | + print e | ||
30 | + print "Error: 无法发送邮件" | ||
31 | + print "重新发送邮件...还剩{0}次".format(retry) | ||
32 | + time.sleep(10) | ||
33 | + return False | ||
34 | + | ||
35 | +if __name__ == '__main__': | ||
36 | + demo = mailman() | ||
37 | + demo.mail(['tiexin.yang@yoho.cn']) |
scripts/lb_manager/qcloud/mailer.pyc
0 → 100644
No preview for this file type
scripts/lb_manager/qcloud/qcloud_api.py
0 → 100644
1 | +#!/usr/bin/python | ||
2 | +# -*- coding: UTF-8 -*- | ||
3 | +# author chunhua.zhang@yoho.cn | ||
4 | +import random | ||
5 | +import hmac | ||
6 | +import base64 | ||
7 | +import hashlib | ||
8 | +import time | ||
9 | +import requests | ||
10 | +import json | ||
11 | + | ||
12 | + | ||
13 | +class QcloudApi: | ||
14 | + """腾讯云API接口""" | ||
15 | + | ||
16 | + 'pre-defined url' | ||
17 | + 'load balance' | ||
18 | + URLS_lb = 'lb.api.qcloud.com/v2/index.php' | ||
19 | + URLS_DNS = 'cns.api.qcloud.com/v2/index.php' | ||
20 | + | ||
21 | + 'public request params' | ||
22 | + Region = 'ap-beijing' | ||
23 | + Version = 'YOHO-QCLOUD-V1.0' | ||
24 | + | ||
25 | + 'see doc: https://www.qcloud.com/document/api/377/4153' | ||
26 | + 'init. must provide SecretId and SecretKey' | ||
27 | + def __init__(self, secretId, secretKey): | ||
28 | + self.secretId = secretId | ||
29 | + self.secretKey = secretKey | ||
30 | + | ||
31 | + def do_query(self, params, req_url=URLS_lb, api_version=2): | ||
32 | + """ | ||
33 | + Do Query Qcloud api | ||
34 | + :param params: 查询参数,dict类型,必须包含 Action | ||
35 | + :param req_url: 查询的地址,参考:qcloud_api.URLS_lb --> lb.api.qcloud.com/v2/index.php | ||
36 | + :return: dict类型,腾讯云返回的消息体 | ||
37 | + """ | ||
38 | + if 'Action' not in params: | ||
39 | + print("must provide [Action] params !") | ||
40 | + raise ValueError(params) | ||
41 | + | ||
42 | + if api_version == 2: | ||
43 | + public_params = {'RequestClient': QcloudApi.Version, 'limit': 100, 'Region': QcloudApi.Region, 'Timestamp': int(time.time()), 'Nonce': QcloudApi.generate_nonce(), 'SecretId': self.secretId} | ||
44 | + # merge params | ||
45 | + params = dict(params, **public_params) | ||
46 | + # signature | ||
47 | + sign = self.signature(params, req_url) | ||
48 | + params['Signature'] = sign | ||
49 | + response_dict = requests.post("https://" + req_url, data=params).json() | ||
50 | + elif api_version == 3: | ||
51 | + public_params = {'Region': QcloudApi.Region, 'Timestamp': int(time.time()), 'Nonce': int(QcloudApi.generate_nonce()), 'Version': '2017-03-12', 'SecretId': self.secretId, 'SignatureMethod':'HmacSHA1'} | ||
52 | + # merge params | ||
53 | + params = dict(params, **public_params) | ||
54 | + # signature | ||
55 | + req_url = req_url.rstrip('/')+'/' | ||
56 | + sign = self.signature(params, req_url) | ||
57 | + params['Signature'] = sign | ||
58 | + response_dict = requests.post("https://" + req_url, data=params).json() | ||
59 | + | ||
60 | + #print("call qcloud api success. params:\n %s \n" % (params)) | ||
61 | + #print json.dumps(response_dict, indent=4, sort_keys=True) | ||
62 | + return response_dict | ||
63 | + | ||
64 | + @staticmethod | ||
65 | + def generate_nonce(length=8): | ||
66 | + """Generate pseudorandom number.""" | ||
67 | + return ''.join([str(random.randint(0, 9)) for i in range(length)]) | ||
68 | + | ||
69 | + def signature(self, request_params, url): | ||
70 | + """ | ||
71 | + 对消息进行签名 see https://www.qcloud.com/document/api/377/4214 | ||
72 | + @param request_params | ||
73 | + @param url, 请求地址,例如:lb.api.qcloud.com/v2/index.php | ||
74 | + """ | ||
75 | + # sort dict by key | ||
76 | + kv_pairs = [] | ||
77 | + for key in sorted(request_params): | ||
78 | + kv_pairs.append('%s=%s' % (key, request_params[key])) | ||
79 | + str_req = '&'.join(kv_pairs) | ||
80 | + str_full = 'POST%s?%s' % (url, str_req) | ||
81 | + hmac_sign = hmac.new(bytes(self.secretKey), bytes(str_full), hashlib.sha1).digest() | ||
82 | + return base64.b64encode(hmac_sign).decode() | ||
83 | + | ||
84 | + | ||
85 | + | ||
86 | + | ||
87 | + | ||
88 | + | ||
89 | + | ||
90 | + |
scripts/lb_manager/qcloud/qcloud_api.pyc
0 → 100644
No preview for this file type
-
Please register or login to post a comment