feat: add new component support azure
parent
60d77b9d1d
commit
fdca6dc71b
|
@ -0,0 +1,234 @@
|
|||
from azure.identity import ClientSecretCredential
|
||||
from azure.mgmt.compute import ComputeManagementClient
|
||||
from azure.mgmt.rdbms import MySQLManagementClient
|
||||
from azure.mgmt.redis import RedisManagementClient
|
||||
from azure.core.exceptions import AzureError
|
||||
|
||||
import sys, datetime, hashlib, math, traceback
|
||||
from units import consul_kv, consul_svc
|
||||
from units.cloud import sync_ecs, sync_rds, sync_redis, notify
|
||||
from units.config_log import *
|
||||
|
||||
def exp(account,collect_days,notify_days,notify_amount):
|
||||
pass
|
||||
|
||||
def group(account):
|
||||
"""同步Azure资源组信息"""
|
||||
try:
|
||||
now = datetime.datetime.now().strftime('%m.%d/%H:%M')
|
||||
# 获取Azure认证信息
|
||||
tenant_id, client_id, client_secret = consul_kv.get_azure_credentials(account)
|
||||
|
||||
# 创建认证客户端
|
||||
credential = ClientSecretCredential(
|
||||
tenant_id=tenant_id,
|
||||
client_id=client_id,
|
||||
client_secret=client_secret
|
||||
)
|
||||
|
||||
# 获取资源组信息
|
||||
from azure.mgmt.resource import ResourceManagementClient
|
||||
resource_client = ResourceManagementClient(credential, subscription_id)
|
||||
|
||||
group_dict = {}
|
||||
for group in resource_client.resource_groups.list():
|
||||
group_dict[group.name] = {
|
||||
'name': group.name,
|
||||
'location': group.location,
|
||||
'tags': group.tags or {}
|
||||
}
|
||||
|
||||
# 保存到consul
|
||||
consul_kv.put_kv(f'ConsulManager/assets/azure/group/{account}', group_dict)
|
||||
count = len(group_dict)
|
||||
data = {
|
||||
'count': count,
|
||||
'update': now,
|
||||
'status': 20000,
|
||||
'msg': f'同步资源组成功!总数:{count}'
|
||||
}
|
||||
consul_kv.put_kv(f'ConsulManager/record/jobs/azure/{account}/group', data)
|
||||
logger.info(f'【JOB】===>azure_group {account} {data}')
|
||||
|
||||
except AzureError as e:
|
||||
handle_azure_error(e, account, 'group')
|
||||
except Exception as e:
|
||||
handle_general_error(e, account, 'group')
|
||||
|
||||
def vm(account, region, isextip=False):
|
||||
"""同步Azure虚拟机信息"""
|
||||
try:
|
||||
now = datetime.datetime.now().strftime('%m.%d/%H:%M')
|
||||
# 获取认证信息
|
||||
tenant_id, client_id, client_secret = consul_kv.get_azure_credentials(account)
|
||||
subscription_id = consul_kv.get_azure_subscription(account)
|
||||
|
||||
# 创建认证客户端
|
||||
credential = ClientSecretCredential(
|
||||
tenant_id=tenant_id,
|
||||
client_id=client_id,
|
||||
client_secret=client_secret
|
||||
)
|
||||
|
||||
# 创建计算管理客户端
|
||||
compute_client = ComputeManagementClient(credential, subscription_id)
|
||||
|
||||
ecs_dict = {}
|
||||
# 获取虚拟机列表
|
||||
for vm in compute_client.virtual_machines.list_all():
|
||||
vm_id = vm.id.split('/')[-1]
|
||||
vm_info = compute_client.virtual_machines.get(
|
||||
vm.id.split('/')[4], # 资源组名称
|
||||
vm.name,
|
||||
expand='instanceView'
|
||||
)
|
||||
|
||||
ecs_dict_temp = {vm_id: {}}
|
||||
ecs_dict_temp[vm_id].update({
|
||||
'name': vm.name,
|
||||
'group': vm.id.split('/')[4], # 资源组名称
|
||||
'ostype': 'windows' if vm.os_profile.windows_configuration else 'linux',
|
||||
'status': vm_info.instance_view.statuses[-1].display_status,
|
||||
'region': vm.location,
|
||||
'ip': get_vm_ip(vm, isextip),
|
||||
'cpu': f"{vm.hardware_profile.vm_size.split('_')[1]}核",
|
||||
'mem': get_vm_memory(vm.hardware_profile.vm_size),
|
||||
'exp': get_vm_billing_type(vm)
|
||||
})
|
||||
ecs_dict.update(ecs_dict_temp)
|
||||
|
||||
# 同步到consul
|
||||
count = len(ecs_dict)
|
||||
off, on = sync_ecs.w2consul('azure', account, region, ecs_dict)
|
||||
data = {
|
||||
'count': count,
|
||||
'update': now,
|
||||
'status': 20000,
|
||||
'on': on,
|
||||
'off': off,
|
||||
'msg': f'VM同步成功!总数:{count},开机:{on},关机:{off}'
|
||||
}
|
||||
consul_kv.put_kv(f'ConsulManager/record/jobs/azure/{account}/vm/{region}', data)
|
||||
logger.info(f'【JOB】===>azure_vm {account} {region} {data}')
|
||||
|
||||
except AzureError as e:
|
||||
handle_azure_error(e, account, 'vm', region)
|
||||
except Exception as e:
|
||||
handle_general_error(e, account, 'vm', region)
|
||||
|
||||
def redis(account, region):
|
||||
"""同步Azure Redis缓存信息"""
|
||||
try:
|
||||
now = datetime.datetime.now().strftime('%m.%d/%H:%M')
|
||||
# 获取认证信息
|
||||
tenant_id, client_id, client_secret = consul_kv.get_azure_credentials(account)
|
||||
subscription_id = consul_kv.get_azure_subscription(account)
|
||||
|
||||
# 创建Redis管理客户端
|
||||
credential = ClientSecretCredential(
|
||||
tenant_id=tenant_id,
|
||||
client_id=client_id,
|
||||
client_secret=client_secret
|
||||
)
|
||||
redis_client = RedisManagementClient(credential, subscription_id)
|
||||
|
||||
redis_dict = {}
|
||||
# 获取Redis实例列表
|
||||
for redis_cache in redis_client.redis.list():
|
||||
cache_id = redis_cache.id.split('/')[-1]
|
||||
redis_dict_temp = {cache_id: {}}
|
||||
redis_dict_temp[cache_id].update({
|
||||
'name': redis_cache.name,
|
||||
'domain': redis_cache.host_name,
|
||||
'ip': redis_cache.host_name,
|
||||
'port': redis_cache.port,
|
||||
'region': redis_cache.location,
|
||||
'group': redis_cache.id.split('/')[4], # 资源组名称
|
||||
'status': redis_cache.provisioning_state,
|
||||
'itype': 'redis',
|
||||
'ver': redis_cache.redis_version,
|
||||
'mem': f"{redis_cache.sku.capacity}GB",
|
||||
'exp': get_redis_billing_type(redis_cache)
|
||||
})
|
||||
redis_dict.update(redis_dict_temp)
|
||||
|
||||
# 同步到consul
|
||||
count = len(redis_dict)
|
||||
off, on = sync_redis.w2consul('azure', account, region, redis_dict)
|
||||
data = {
|
||||
'count': count,
|
||||
'update': now,
|
||||
'status': 20000,
|
||||
'on': on,
|
||||
'off': off,
|
||||
'msg': f'Redis同步成功!总数:{count},开机:{on},关机:{off}'
|
||||
}
|
||||
consul_kv.put_kv(f'ConsulManager/record/jobs/azure/{account}/redis/{region}', data)
|
||||
logger.info(f'【JOB】===>azure_redis {account} {region} {data}')
|
||||
|
||||
except AzureError as e:
|
||||
handle_azure_error(e, account, 'redis', region)
|
||||
except Exception as e:
|
||||
handle_general_error(e, account, 'redis', region)
|
||||
|
||||
# 辅助函数
|
||||
def handle_azure_error(e: AzureError, account: str, resource_type: str, region: str = None):
|
||||
"""处理Azure API错误"""
|
||||
emsg = str(e)
|
||||
logger.error(f"【Azure Error】\n【message:】{emsg}\n{traceback.format_exc()}")
|
||||
|
||||
# 构建错误路径
|
||||
error_path = f'ConsulManager/record/jobs/azure/{account}/{resource_type}'
|
||||
if region:
|
||||
error_path = f'{error_path}/{region}'
|
||||
|
||||
# 获取现有数据
|
||||
data = consul_kv.get_value(error_path)
|
||||
if data == {}:
|
||||
data = {'count': '无', 'update': '失败', 'status': 50000, 'msg': emsg}
|
||||
else:
|
||||
data['update'] = '失败'
|
||||
data['msg'] = emsg
|
||||
|
||||
consul_kv.put_kv(error_path, data)
|
||||
|
||||
def handle_general_error(e: Exception, account: str, resource_type: str, region: str = None):
|
||||
"""处理一般错误"""
|
||||
logger.error(f'{e}\n{traceback.format_exc()}')
|
||||
|
||||
# 构建错误路径
|
||||
error_path = f'ConsulManager/record/jobs/azure/{account}/{resource_type}'
|
||||
if region:
|
||||
error_path = f'{error_path}/{region}'
|
||||
|
||||
data = {'count': '无', 'update': '失败', 'status': 50000, 'msg': str(e)}
|
||||
consul_kv.put_kv(error_path, data)
|
||||
|
||||
def get_vm_ip(vm, isextip=False):
|
||||
"""获取虚拟机IP地址"""
|
||||
if isextip:
|
||||
# 获取公网IP
|
||||
return vm.network_profile.network_interfaces[0].ip_configurations[0].public_ip_address.ip_address
|
||||
else:
|
||||
# 获取私网IP
|
||||
return vm.network_profile.network_interfaces[0].ip_configurations[0].private_ip_address
|
||||
|
||||
def get_vm_memory(vm_size):
|
||||
"""根据VM规格获取内存大小"""
|
||||
# 这里需要实现VM规格到内存大小的映射
|
||||
size_memory_map = {
|
||||
'Standard_DS1_v2': '3.5GB',
|
||||
'Standard_DS2_v2': '7GB',
|
||||
# ... 其他规格映射
|
||||
}
|
||||
return size_memory_map.get(vm_size, '0')
|
||||
|
||||
def get_vm_billing_type(vm):
|
||||
"""获取虚拟机计费类型"""
|
||||
# 根据Azure虚拟机的计费属性判断
|
||||
return '按量' if vm.billing_profile.max_price is None else '包年包月'
|
||||
|
||||
def get_redis_billing_type(redis_cache):
|
||||
"""获取Redis实例计费类型"""
|
||||
# 根据Redis实例的计费属性判断
|
||||
return '按量' # 或根据实际情况判断
|
Loading…
Reference in New Issue