From 033d2bb80e82fcaa7534405bd85dc1d8506fadde Mon Sep 17 00:00:00 2001 From: "StarsL.cn" Date: Sat, 22 Oct 2022 01:46:30 +0800 Subject: [PATCH] add rds monit --- flask-consul/requirements.txt | 1 + flask-consul/units/cloud/huaweicloud.py | 58 +- flask-consul/units/cloud/sync_rds.py | 78 +++ flask-consul/views/jobs.py | 34 +- vue-consul/src/api/.node-exporter.js.swp | Bin 0 -> 12288 bytes vue-consul/src/router/index.js | 110 +++- vue-consul/src/views/node-exporter/index.vue | 3 + vue-consul/src/views/node-exporter/jobs.vue | 26 +- vue-consul/src/views/rds/.lists.vue.swp | Bin 0 -> 16384 bytes vue-consul/src/views/rds/grafana.vue | 19 + vue-consul/src/views/rds/index.vue | 3 + vue-consul/src/views/rds/lists.vue | 146 +++++ vue-consul/src/views/rds/pconfig.vue | 75 +++ vue-consul/src/views/rds/rules.vue | 51 ++ vue-consul/src/views/rds/self.vue | 596 +++++++++++++++++++ 15 files changed, 1144 insertions(+), 56 deletions(-) create mode 100644 flask-consul/units/cloud/sync_rds.py create mode 100644 vue-consul/src/api/.node-exporter.js.swp create mode 100644 vue-consul/src/views/node-exporter/index.vue create mode 100644 vue-consul/src/views/rds/.lists.vue.swp create mode 100644 vue-consul/src/views/rds/grafana.vue create mode 100644 vue-consul/src/views/rds/index.vue create mode 100644 vue-consul/src/views/rds/lists.vue create mode 100644 vue-consul/src/views/rds/pconfig.vue create mode 100644 vue-consul/src/views/rds/rules.vue create mode 100644 vue-consul/src/views/rds/self.vue diff --git a/flask-consul/requirements.txt b/flask-consul/requirements.txt index 0053822..8d00921 100644 --- a/flask-consul/requirements.txt +++ b/flask-consul/requirements.txt @@ -14,6 +14,7 @@ huaweicloudsdkcore==3.0.95 huaweicloudsdkecs==3.0.95 huaweicloudsdkeps==3.0.95 huaweicloudsdkbss==3.0.95 +huaweicloudsdkrds==3.1.5 alibabacloud_resourcemanager20200331==2.1.0 alibabacloud_ecs20140526==2.1.0 alibabacloud_bssopenapi20171214==2.0.5 diff --git a/flask-consul/units/cloud/huaweicloud.py b/flask-consul/units/cloud/huaweicloud.py index 03a85c5..ddcb318 100644 --- a/flask-consul/units/cloud/huaweicloud.py +++ b/flask-consul/units/cloud/huaweicloud.py @@ -3,12 +3,15 @@ from huaweicloudsdkeps.v1.region.eps_region import EpsRegion from huaweicloudsdkcore.exceptions import exceptions from huaweicloudsdkbss.v2.region.bss_region import BssRegion from huaweicloudsdkeps.v1 import * -from huaweicloudsdkecs.v2.region.ecs_region import EcsRegion -from huaweicloudsdkecs.v2 import * from huaweicloudsdkbss.v2 import * +from huaweicloudsdkecs.v2 import * +from huaweicloudsdkecs.v2.region.ecs_region import EcsRegion +from huaweicloudsdkrds.v3 import * +from huaweicloudsdkrds.v3.region.rds_region import RdsRegion import sys,datetime,hashlib from units import consul_kv from units.cloud import sync_ecs +from units.cloud import sync_rds from units.cloud import notify def exp(account,collect_days,notify_days,notify_amount): @@ -166,3 +169,54 @@ def ecs(account,region): except Exception as e: data = {'count':'无','update':f'失败','status':50000,'msg':str(e)} consul_kv.put_kv(f'ConsulManager/record/jobs/huaweicloud/{account}/ecs/{region}', data) + + +def rds(account,region): + ak,sk = consul_kv.get_aksk('huaweicloud',account) + now = datetime.datetime.now().strftime('%m%d/%H:%M') + group_dict = consul_kv.get_value(f'ConsulManager/assets/huaweicloud/group/{account}') + credentials = BasicCredentials(ak, sk) + try: + client = RdsClient.new_builder() \ + .with_credentials(credentials) \ + .with_region(RdsRegion.value_of(region)) \ + .build() + request = ListInstancesRequest() + request.datastore_type = "MySQL" + request.limit = 100 + info = client.list_instances(request).to_dict()['instances'] + + rds_dict = {i['id']:{'name':i['name'], + 'domain':i['private_dns_names'][0], + 'ip':i['private_ips'][0], + 'port':i['port'], + 'region':region, + 'group':group_dict[i['enterprise_project_id']], + 'status':i['status'], + 'itype':i['type'], + 'ver':i['datastore']['version'], + 'cpu':f"{i['cpu']}核", + 'mem':f"{i['mem']}GB", + 'disk':f"{i['volume']['size']}GB", + 'exp': i['expiration_time'] + } for i in info} + count = len(rds_dict) + off,on = sync_rds.w2consul('huaweicloud',account,region,rds_dict) + data = {'count':count,'update':now,'status':20000,'on':on,'off':off,'msg':f'RDS同步成功!总数:{count},开机:{on},关机:{off}'} + consul_kv.put_kv(f'ConsulManager/record/jobs/huaweicloud/{account}/rds/{region}', data) + print('【JOB】===>', 'huaweicloud_rds', account,region, data, flush=True) + except exceptions.ClientRequestException as e: + print(e.status_code, flush=True) + print(e.request_id, flush=True) + print(e.error_code, flush=True) + print(e.error_msg, flush=True) + data = consul_kv.get_value(f'ConsulManager/record/jobs/huaweicloud/{account}/rds/{region}') + if data == {}: + data = {'count':'无','update':f'失败{e.status_code}','status':50000,'on':0,'off':0,'msg':e.error_msg} + else: + data['update'] = f'失败{e.status_code}' + data['msg'] = e.error_msg + consul_kv.put_kv(f'ConsulManager/record/jobs/huaweicloud/{account}/rds/{region}', data) + except Exception as e: + data = {'count':'无','update':f'失败','status':50000,'msg':str(e)} + consul_kv.put_kv(f'ConsulManager/record/jobs/huaweicloud/{account}/rds/{region}', data) diff --git a/flask-consul/units/cloud/sync_rds.py b/flask-consul/units/cloud/sync_rds.py new file mode 100644 index 0000000..3850d6e --- /dev/null +++ b/flask-consul/units/cloud/sync_rds.py @@ -0,0 +1,78 @@ +#!/usr/bin/python3 +import requests,json +from units import consul_kv +from config import consul_token,consul_url,vendors,regions +headers = {'X-Consul-Token': consul_token} +geturl = f'{consul_url}/agent/services' +delurl = f'{consul_url}/agent/service/deregister' +puturl = f'{consul_url}/agent/service/register' +def w2consul(vendor,account,region,rds_dict): + service_name = f'{vendor}_{account}_rds' + params = {'filter': f'Service == "{service_name}" and "{region}" in Tags and Meta.account == "{account}"'} + try: + consul_rds_iid_list = requests.get(geturl, headers=headers, params=params).json().keys() + except: + consul_rds_iid_list = [] + + #在consul中删除云厂商不存在的rds + for del_rds in [x for x in consul_rds_iid_list if x not in rds_dict.keys()]: + dereg = requests.put(f'{delurl}/{del_rds}', headers=headers) + if dereg.status_code == 200: + print({"code": 20000,"data": f"{account}-删除成功!"}, flush=True) + else: + print({"code": 50000,"data": f'{dereg.status_code}:{dereg.text}'}, flush=True) + off,on = 0,0 + for k,v in rds_dict.items(): + iid = k + #对consul中关机的rds做标记。 + if v['status'] in ['SHUTDOWN']: + off = off + 1 + tags = ['shutoff',v['itype'],v['ver'], region] + stat = 'off' + else: + on = on + 1 + tags = [v['itype'],v['ver'],region] + stat = 'on' + custom_rds = consul_kv.get_value(f'ConsulManager/assets/sync_rds_custom/{iid}') + port = custom_rds.get('port') + ip = custom_rds.get('ip') + if port == None: + port = v['port'] + if ip == None: + ip = v['ip'] + instance = f'{ip}:{port}' + data = { + 'id': iid, + 'name': service_name, + 'Address': ip, + 'port': port, + 'tags': tags, + 'Meta': { + 'iid': iid, + 'name': v['name'], + 'region': regions[vendor].get(region,'未找到'), + 'group': v['group'], + 'instance': instance, + 'account': account, + 'vendor': vendors.get(vendor,'未找到'), + 'disk': v['disk'], + 'cpu': v['cpu'], + 'mem': v['mem'], + 'ver': v['ver'], + 'domain':v['domain'], + 'exp': v['exp'], + 'stat': stat + }, + "check": { + "tcp": f"{ip}:{port}", + "interval": "60s" + } + } + reg = requests.put(puturl, headers=headers, data=json.dumps(data)) + if reg.status_code == 200: + pass + #print({f"{account}:code": 20000,"data": "增加成功!"}, flush=True) + else: + print({f"{account}:code": 50000,"data": f'{reg.status_code}:{reg.text}'}, flush=True) + #return {"code": 50000,"data": f'{reg.status_code}:{reg.text}'} + return off,on diff --git a/flask-consul/views/jobs.py b/flask-consul/views/jobs.py index 30295aa..3c212b0 100644 --- a/flask-consul/views/jobs.py +++ b/flask-consul/views/jobs.py @@ -75,37 +75,39 @@ class Jobs(Resource): ak = job_dict['ak'] sk = job_dict['sk'] consul_kv.put_aksk(job_dict['vendor'],job_dict['account'],ak,sk) - + restype = job_dict['restype'] + restype.remove('group') proj_job_id = f"{job_dict['vendor']}/{job_dict['account']}/group" proj_job_func = f"__main__:{job_dict['vendor']}.group" proj_job_args = [job_dict['account']] proj_job_interval = int(job_dict['proj_interval']) - - ecs_job_id = f"{job_dict['vendor']}/{job_dict['account']}/ecs/{job_dict['region']}" - ecs_job_func = f"__main__:{job_dict['vendor']}.ecs" - ecs_job_args = [job_dict['account'],job_dict['region']] - ecs_job_interval = int(job_dict['ecs_interval']) - - Scheduler.add_job(id=proj_job_id, func=proj_job_func, args=proj_job_args, trigger='interval', + Scheduler.add_job(id=proj_job_id, func=proj_job_func, args=proj_job_args, trigger='interval', minutes=proj_job_interval, replace_existing=True) - Scheduler.add_job(id=ecs_job_id, func=ecs_job_func, args=ecs_job_args, trigger='interval', - minutes=ecs_job_interval, replace_existing=True) - proj_job_dict = {'id':proj_job_id,'func':proj_job_func,'args':proj_job_args,'minutes':proj_job_interval, "trigger": "interval","replace_existing": True} Scheduler.run_job(proj_job_id) - ecs_job_dict = {'id':ecs_job_id,'func':ecs_job_func,'args':ecs_job_args,'minutes':ecs_job_interval, - "trigger": "interval","replace_existing": True} + record_dict = consul_kv.get_value(f"ConsulManager/record/jobs/{proj_job_id}") if record_dict['status'] == 20000: consul_kv.put_kv(f'ConsulManager/jobs/{proj_job_id}',proj_job_dict) - consul_kv.put_kv(f'ConsulManager/jobs/{ecs_job_id}',ecs_job_dict) + for res in restype: + + res_job_id = f"{job_dict['vendor']}/{job_dict['account']}/{res}/{job_dict['region']}" + res_job_func = f"__main__:{job_dict['vendor']}.{res}" + res_job_args = [job_dict['account'],job_dict['region']] + res_job_interval = int(job_dict[f'{res}_interval']) + Scheduler.add_job(id=res_job_id, func=res_job_func, args=res_job_args, trigger='interval', + minutes=res_job_interval, replace_existing=True) + res_job_dict = {'id':res_job_id,'func':res_job_func,'args':res_job_args,'minutes':res_job_interval, + "trigger": "interval","replace_existing": True} + + consul_kv.put_kv(f'ConsulManager/jobs/{res_job_id}',res_job_dict) else: Scheduler.remove_job(proj_job_id) - Scheduler.remove_job(ecs_job_id) + exp = consul_kv.get_value(f'ConsulManager/exp/config') switch = exp.get('switch',False) - if switch: + if switch and record_dict['status'] == 20000: vendor = job_dict['vendor'] account = job_dict['account'] exp_job_id = f'{vendor}/{account}/exp' diff --git a/vue-consul/src/api/.node-exporter.js.swp b/vue-consul/src/api/.node-exporter.js.swp new file mode 100644 index 0000000000000000000000000000000000000000..45b6d44880e90cc309f3e4775138dbeda149b647 GIT binary patch literal 12288 zcmeI2&r1|x7{_0`l%*945fSlL(5~gWYXyN26e^OaX`%!jWSo6>9h;eVoOfm^#3a0Q z?dUPc=wP=F{tHD#1=b<)5G39cK1@-{*Nh?+;k^oz6_& z80J^HE;C$58MC$q&6CYZwk;X+r401ze_eUQag3BL^C_V+-Sta9&<&=0rK>`F*l>-! z@Y97*q|E3|TKQ($@T{~evmzz#dD0Jr-!-f1H%Q-*0W#2lfmU|uVs}PYID6(aZ*QAu zpe_|917v^??KTPU+rMbuT^AjSP?hGC&5%02v?y zWPl8i0Wv@a$N(AGg9eN&W2X)<_N*DnPg{4@`hjFam}_2RH^8 z_;DC@zB$x#=;3_x|TENyJlm(x`I#>fM;1MW*IUs=xdO-%Xf$f8c z1vbG3_yS&nCtwlS;5HZsV_+1V0QV}pfagGaUjcNH0Wv@a$N(8217x7mzyjlZ zp#vYBdxmc~s)x_>Svf6CHRT$P=;Y>%Fz<>i*Cjc3L@*<>Jv@;YL83Ey75X-w{~WMX zX;THLZdk|wN!AM9!RHyPnW|+q zo*7Ps=Azu=XNIGtIV+z;wCYr{Mqp@X==7A9mbJ{F+Lb3uDmbqrD_%OfouaAa&T!Q! zRg6*XA@W08sCYp!I=6J`qz!Y^2+*hSAHr?HbL4M9b?s+3}MTn|yXiP)jX zOI?iSXX7!8Gdgy(K{<`J5b56OyJC4xH8kzf>DbW`y1Wb#q&upE7QzPy?9oG%@oxRwqB%U0>q7N3%yO0eJYGh<`` literal 0 HcmV?d00001 diff --git a/vue-consul/src/router/index.js b/vue-consul/src/router/index.js index 3ce1774..96e2efe 100644 --- a/vue-consul/src/router/index.js +++ b/vue-consul/src/router/index.js @@ -95,12 +95,6 @@ export const constantRoutes = [ component: () => import('@/views/node-exporter/jobs'), meta: { title: '接入数据源', icon: 'el-icon-school' } }, - { - path: 'jms', - name: 'JumpServer', - component: () => import('@/views/jms/index'), - meta: { title: 'JumpServer 同步', icon: 'el-icon-copy-document' } - }, { path: 'exp', name: '余额与到期通知', @@ -108,34 +102,86 @@ export const constantRoutes = [ meta: { title: '余额与到期通知', icon: 'el-icon-alarm-clock' } }, { - path: 'lists', - name: '云主机列表', - component: () => import('@/views/node-exporter/lists'), - meta: { title: '云主机列表', icon: 'el-icon-cloudy' } + path: 'ecs', + name: 'ECS', + component: () => import('@/views/node-exporter/index'), + meta: { title: 'ECS管理', icon: 'el-icon-cpu' }, + children: [ + { + path: 'jms', + name: 'JumpServer', + component: () => import('@/views/jms/index'), + meta: { title: 'JumpServer 同步', icon: 'el-icon-copy-document' } + }, + { + path: 'lists', + name: '云主机列表', + component: () => import('@/views/node-exporter/lists'), + meta: { title: '云主机列表', icon: 'el-icon-cloudy' } + }, + { + path: 'self', + name: '自建主机管理', + component: () => import('@/views/node-exporter/self'), + meta: { title: '自建主机管理', icon: 'el-icon-s-platform' } + }, + { + path: 'pconfig', + name: 'node-pconfig', + component: () => import('@/views/node-exporter/pconfig'), + meta: { title: 'Prometheus 配置', icon: 'el-icon-set-up' } + }, + { + path: 'rules', + name: 'node-rules', + component: () => import('@/views/node-exporter/rules'), + meta: { title: '告警规则', icon: 'el-icon-bell' } + }, + { + path: 'grafana', + name: 'node-grafana', + component: () => import('@/views/node-exporter/grafana'), + meta: { title: 'Grafana 看板', icon: 'el-icon-data-line' } + } + ] }, { - path: 'self', - name: '自建主机管理', - component: () => import('@/views/node-exporter/self'), - meta: { title: '自建主机管理', icon: 'el-icon-s-platform' } - }, - { - path: 'pconfig', - name: 'node-pconfig', - component: () => import('@/views/node-exporter/pconfig'), - meta: { title: 'Prometheus 配置', icon: 'el-icon-set-up' } - }, - { - path: 'rules', - name: 'node-rules', - component: () => import('@/views/node-exporter/rules'), - meta: { title: '告警规则', icon: 'el-icon-bell' } - }, - { - path: 'grafana', - name: 'node-grafana', - component: () => import('@/views/node-exporter/grafana'), - meta: { title: 'Grafana 看板', icon: 'el-icon-data-line' } + path: 'rds', + name: 'RDS', + component: () => import('@/views/rds/index'), + meta: { title: 'MySQL管理', icon: 'el-icon-cpu' }, + children: [ + { + path: 'lists', + name: '云MySQL列表', + component: () => import('@/views/rds/lists'), + meta: { title: '云MySQL列表', icon: 'el-icon-cloudy' } + }, + { + path: 'self', + name: '自建MySQL管理', + component: () => import('@/views/rds/self'), + meta: { title: '自建MySQL管理', icon: 'el-icon-s-platform' } + }, + { + path: 'pconfig', + name: 'rds-pconfig', + component: () => import('@/views/rds/pconfig'), + meta: { title: 'Prometheus 配置', icon: 'el-icon-set-up' } + }, + { + path: 'rules', + name: 'rds-rules', + component: () => import('@/views/rds/rules'), + meta: { title: '告警规则', icon: 'el-icon-bell' } + }, + { + path: 'grafana', + name: 'rds-grafana', + component: () => import('@/views/rds/grafana'), + meta: { title: 'Grafana 看板', icon: 'el-icon-data-line' } + } + ] } ] }, diff --git a/vue-consul/src/views/node-exporter/index.vue b/vue-consul/src/views/node-exporter/index.vue new file mode 100644 index 0000000..98240ae --- /dev/null +++ b/vue-consul/src/views/node-exporter/index.vue @@ -0,0 +1,3 @@ + diff --git a/vue-consul/src/views/node-exporter/jobs.vue b/vue-consul/src/views/node-exporter/jobs.vue index 99e544f..c396b10 100644 --- a/vue-consul/src/views/node-exporter/jobs.vue +++ b/vue-consul/src/views/node-exporter/jobs.vue @@ -58,7 +58,7 @@