Для взаимодействия с облачной инфраструктурой AWS компания Amazon поддерживает открытый проект на GitHub, который реализует Python SDK. С помощью библиотек из этого проекта можно реализовать взаимодействие с облачной инфраструктурой посредством скриптов или даже написать собственный облегченный веб-сервис для AWS. Полная документация к библиотекам опубликована в библиотеке Amazon.
print('--- importing module_aws.py ---')
# импортирование модулей, установленных в системе
from boto3 import client as aws_client
from botocore.config import Config
from datetime import datetime, timedelta
from os import path as os_path
from os import getcwd as os_getcwd
from os import environ as os_environ
from sys import path as sys_path
# импортирование модулей из проекта
try:
print(' trying to import modules with relative paths')
from .module_core import instances_json_read
from django.conf import settings
print(' relative import is OK')
except ImportError:
print(' relative import failed')
print(' trying to import modules with absolute paths')
try:
# получение текущей дирректории, откуда запущен скрипт - должен быть корень проекта
current_directory = os_getcwd()
# добавление пути к папке проекта в переменные среды
sys_path.append(current_directory)
# подключение настроек проекта
os_environ.setdefault('DJANGO_SETTINGS_MODULE', 'webconsole.settings')
# импортирование переменных Django в текущую среду
from django.conf import settings
from module_core import instances_json_read
print(' absolute import is OK')
except ModuleNotFoundError:
print(' absolute import failed')
exit()
print()
aws_access_key_id = settings.AWS_ACCESS_KEY
aws_secret_access_key = settings.AWS_SECRET_KEY
region_name = settings.AWS_REGION
proxies = settings.PROXY_SETTINGS['proxies']
aws_ec2_types = settings.AWS_EC2_TYPES
def aws_ec2_client(aws_access_key_id, aws_secret_access_key, region_name, proxies):
client = aws_client(
'ec2',
aws_access_key_id=aws_access_key_id,
aws_secret_access_key=aws_secret_access_key,
region_name=region_name,
config=Config(proxies=proxies),
)
return client
def aws_cloudwatch_client(aws_access_key_id, aws_secret_access_key, region_name, proxies):
client = aws_client(
'cloudwatch',
aws_access_key_id=aws_access_key_id,
aws_secret_access_key=aws_secret_access_key,
region_name=region_name,
config=Config(proxies=proxies),
)
return client
def aws_instance_properties_local(id):
# путь к json-файлу
instances_filepath = os_path.join(settings.BASE_DIR, settings.PROJECT_INSTANCES_JSON_FILEPATH)
# запрос данных из json-файла
try:
instances_table = instances_json_read(instances_filepath)['aws_vm_table']
instance_line = instances_table.loc[id.lower()].to_dict()
except:
instance_line = ''
return instance_line
def aws_instance_properties_mixed(id):
# получение локальных данных из файла
vm_properties = aws_instance_properties_local(id)
# получение облачных данных
ec2_client = aws_ec2_client(aws_access_key_id, aws_secret_access_key, region_name, proxies)
response = ec2_client.describe_instances(Filters=[{
'Name': 'instance-id',
'Values': [id,]
},])
instance_attr = response['Reservations'][0]['Instances'][0]
tags = {}
for item in instance_attr['Tags']:
tags.update({item['Key']: item['Value']})
i_id = instance_attr['InstanceId']
# описание сервера
i_description = ''
if 'Description' in tags:
i_description = tags['Description']
# назначение сервера
i_purpose = ''
if 'Description' in tags:
i_purpose = tags['Purpose']
# расписание резервного копирования сервера
i_backup = ''
if 'cpm backup' in tags:
i_backup = tags['cpm backup']
# расписание работы сервера
i_schedule = ''
if 'StartStopSchedule' in tags:
i_schedule = tags['StartStopSchedule']
# список доступа к управлению питанием
i_start_stop_access = ''
if 'StartStopAccess' in tags:
i_start_stop_access = tags['StartStopAccess'].lower()
# состояние сервера
i_state = instance_attr['State']['Name']
# построение словаря атрибутов
curValues = {
'id': i_id,
'name': vm_properties['name'],
'type': vm_properties['type'],
'zone': vm_properties['vpc_description'],
'ip_address': vm_properties['ip_address'],
'responsible': vm_properties['responsible'],
'project': vm_properties['project'],
'description': i_description,
'purpose': i_purpose,
'state': i_state,
'backup': i_backup,
'schedule': i_schedule,
'schedule_description': '',
'start_stop_access': i_start_stop_access,
}
return curValues
def aws_instance_start(vm_id):
ec2_client = aws_ec2_client(aws_access_key_id, aws_secret_access_key, region_name, proxies)
result = ec2_client.start_instances(InstanceIds=[vm_id,])
return result
def aws_instance_stop(vm_id):
ec2_client = aws_ec2_client(aws_access_key_id, aws_secret_access_key, region_name, proxies)
result = ec2_client.stop_instances(InstanceIds=[vm_id,])
return result
def aws_instance_save(vm_id, description, purpose, backup_name, schedule_name, start_stop_access):
# построение коллекции тэгов
update_tags = []
delete_tags = []
# заполнение тэгов
update_tags.append({'Key': 'Description', 'Value': description},)
update_tags.append({'Key': 'Purpose', 'Value': purpose},)
if not (backup_name == ''):
update_tags.append({'Key': 'cpm backup', 'Value': backup_name},)
else:
delete_tags.append({'Key': 'cpm backup',})
if not (schedule_name == ''):
update_tags.append({'Key': 'StartStopSchedule', 'Value': schedule_name},)
else:
delete_tags.append({'Key': 'StartStopSchedule',})
if not (start_stop_access == ''):
# заменить "," и пробелы на ";", преобразовать в строчные
start_stop_access = start_stop_access.replace(' ',';').replace(',',';').lower()
# преобразовать строку в список
start_stop_access_list = start_stop_access.split(";")
# удалить пустые элементы
start_stop_access_list = list(filter(None, start_stop_access_list))
# удалить дубликаты из списка (преобразовать список в множество и обратно в список)
start_stop_access_list = list(set(start_stop_access_list))
# сортировка списка
start_stop_access_list.sort()
# преобразовать список в строку
start_stop_access = ';'.join(start_stop_access_list)
update_tags.append({'Key': 'StartStopAccess', 'Value': start_stop_access},)
else:
delete_tags.append({'Key': 'StartStopAccess',})
# создание клиента подключения к AWS EC2
ec2_client = aws_ec2_client(aws_access_key_id, aws_secret_access_key, region_name, proxies)
# выполнение запроса на удаление тэгов в AWS EC2
if len(delete_tags) > 0 :
result = ec2_client.delete_tags(
Resources=[vm_id,],
Tags=delete_tags,
)
# выполнение запроса на обновление тэгов в AWS EC2
if len(update_tags) > 0 :
result = ec2_client.create_tags(
Resources=[vm_id,],
Tags=update_tags,
)
return
def aws_instance_metrics(vm_id):
import pandas as pd
cw_client = aws_cloudwatch_client(aws_access_key_id, aws_secret_access_key, region_name, proxies)
time_start = datetime.utcnow() - timedelta(hours=8)
time_stop = datetime.utcnow()
vm_properties = aws_instance_properties_local(vm_id)
response = cw_client.get_metric_statistics(
Namespace='AWS/EC2',
MetricName='CPUUtilization',
StartTime=time_start,
EndTime=time_stop,
Statistics=['Maximum'],
Period=300,
Dimensions=[
{
'Name': 'InstanceId',
'Value': vm_id
},
],
)
json_data = response['Datapoints']
if len(json_data) > 0:
res_table = pd.json_normalize(json_data)
res_table.sort_values(['Timestamp'], ascending=[True], inplace=True)
res_table['Time'] = res_table['Timestamp'].apply(lambda x: (x+timedelta(hours=1)).strftime('%H:%M'))
res_table.set_index('Timestamp', inplace=True)
# переименование колонок в таблице
res_table.rename(inplace=True, columns={'Maximum': 'CPU'})
if ('ws' in vm_properties['name']):
response = cw_client.get_metric_statistics(
Namespace='AGC/Windows',
MetricName='Memory Physical Available',
StartTime=time_start,
EndTime=time_stop,
Statistics=['Maximum'],
Period=300,
Dimensions=[
{
'Name': 'InstanceId',
'Value': vm_id
},
{
'Name': 'instance',
'Value': '_Total',
},
{
'Name': 'objectname',
'Value': 'Memory',
},
],
)
json_data = response['Datapoints']
if len(json_data) > 0:
ram_table = pd.json_normalize(json_data)
ram_table.rename(inplace=True, columns={'Maximum': 'RAM'})
ram_table.set_index('Timestamp', inplace=True)
res_table = res_table.join(ram_table,rsuffix='_r')
# конвертирование доступной памяти из байт в мегабайт
res_table['RAM'] = res_table['RAM'] / 1048576
if (vm_properties['type'] in aws_ec2_types):
# получение размера памяти и конвертирование из гигабайтов в магабайты
vm_ram = aws_ec2_types[vm_properties['type']]['ram'] * 1024
else:
vm_ram = 0
# вычислеине используемой памяти в процентах
res_table['RAM'] = round((vm_ram - res_table['RAM']) / vm_ram * 100)
else:
res_table['RAM'] = 0
else:
response = cw_client.get_metric_statistics(
Namespace='AGC/Linux',
MetricName='Memory Utilization Percent',
StartTime=time_start,
EndTime=time_stop,
Statistics=['Maximum'],
Period=300,
Dimensions=[
{
'Name': 'InstanceId',
'Value': vm_id
},
],
)
json_data = response['Datapoints']
if len(json_data) > 0:
ram_table = pd.json_normalize(json_data)
ram_table.rename(inplace=True, columns={'Maximum': 'RAM'})
ram_table.set_index('Timestamp', inplace=True)
res_table = res_table.join(ram_table,rsuffix='_r')
else:
res_table['RAM'] = 0
res_table = res_table.fillna(0)
result = res_table[['Time', 'CPU', 'RAM']].values.tolist()
else:
result = ''
return result
if __name__ == '__main__':
print(datetime.today())
result = aws_instance_metrics('i-1234567890abcdef')
print(result)
