blob: 1812002bb2118f0af39c5739e3044c8060f4d7b5 [file] [log] [blame]
hamid681877c2017-09-18 16:56:59 +05001##
2# Copyright 2017 xFlow Research Pvt. Ltd
3# This file is part of MON module
4# All Rights Reserved.
5#
6# Licensed under the Apache License, Version 2.0 (the "License"); you may
7# not use this file except in compliance with the License. You may obtain
8# a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15# License for the specific language governing permissions and limitations
16# under the License.
17#
18# For those usages not covered by the Apache License, Version 2.0 please
19# contact with: wajeeha.hamid@xflowresearch.com
20##
21
Benjamin Diaz93699892018-10-12 17:37:30 -030022"""
hamid681877c2017-09-18 16:56:59 +050023AWS-Plugin implements all the methods of MON to interact with AWS using the BOTO client
Benjamin Diaz93699892018-10-12 17:37:30 -030024"""
hamid681877c2017-09-18 16:56:59 +050025
26__author__ = "Wajeeha Hamid"
Benjamin Diaz93699892018-10-12 17:37:30 -030027__date__ = "18-Sept-2017"
hamid681877c2017-09-18 16:56:59 +050028
hamid681877c2017-09-18 16:56:59 +050029import datetime
javaid079c73d2018-01-24 10:17:55 +050030import logging
hamid681877c2017-09-18 16:56:59 +050031
32try:
33 import boto
34 import boto.ec2
35 import boto.vpc
36 import boto.ec2.cloudwatch
37 import boto.ec2.connection
38except:
39 exit("Boto not avialable. Try activating your virtualenv OR `pip install boto`")
40
javaid079c73d2018-01-24 10:17:55 +050041log = logging.getLogger(__name__)
hamid681877c2017-09-18 16:56:59 +050042
hamid681877c2017-09-18 16:56:59 +050043
Benjamin Diaz93699892018-10-12 17:37:30 -030044class Metrics:
45
46 def createMetrics(self, cloudwatch_conn, metric_info):
hamid681877c2017-09-18 16:56:59 +050047 try:
hamid681877c2017-09-18 16:56:59 +050048
Benjamin Diaz93699892018-10-12 17:37:30 -030049 """createMetrics will be returning the metric_uuid=0 and
50 status=True when the metric is supported by AWS"""
51
52 supported = self.check_metric(metric_info['metric_name'])
hamid681877c2017-09-18 16:56:59 +050053 metric_resp = dict()
hamidbfbc3dd2017-09-30 16:23:30 +050054 metric_resp['resource_uuid'] = metric_info['resource_uuid']
Benjamin Diaz93699892018-10-12 17:37:30 -030055
56 if supported['status']:
hamid681877c2017-09-18 16:56:59 +050057 metric_resp['status'] = True
58 metric_resp['metric_uuid'] = 0
Benjamin Diaz93699892018-10-12 17:37:30 -030059 log.debug("Metrics Configured Successfully : %s", metric_resp)
hamid681877c2017-09-18 16:56:59 +050060 else:
61 metric_resp['status'] = False
62 metric_resp['metric_uuid'] = None
Benjamin Diaz93699892018-10-12 17:37:30 -030063 log.error("Metric name is not supported")
64
65 return metric_resp
hamid681877c2017-09-18 16:56:59 +050066
67 except Exception as e:
68 log.error("Metric Configuration Failed: " + str(e))
Benjamin Diaz93699892018-10-12 17:37:30 -030069
70 def metricsData(self, cloudwatch_conn, data_info):
hamid681877c2017-09-18 16:56:59 +050071
Benjamin Diazb85fc8c2018-05-03 13:22:11 -030072 """Getting Metrics Stats for an Hour.The datapoints are
hamid681877c2017-09-18 16:56:59 +050073 received after every one minute.
74 Time interval can be modified using Timedelta value"""
75
76 try:
77 metric_info = dict()
78 metric_info_dict = dict()
79 timestamp_arr = {}
80 value_arr = {}
81
Benjamin Diaz93699892018-10-12 17:37:30 -030082 supported = self.check_metric(data_info['metric_name'])
hamid681877c2017-09-18 16:56:59 +050083
Benjamin Diaz93699892018-10-12 17:37:30 -030084 if supported['status']:
hamid9f6a2712017-09-27 16:53:56 +050085 if int(data_info['collection_period']) % 60 == 0:
Benjamin Diaz93699892018-10-12 17:37:30 -030086 metric_stats = cloudwatch_conn.get_metric_statistics(60,
87 datetime.datetime.utcnow() - datetime.timedelta(
88 seconds=int(
89 data_info['collection_period'])),
90 datetime.datetime.utcnow(),
91 supported['metric_name'], 'AWS/EC2', 'Maximum',
92 dimensions={
93 'InstanceId': data_info['resource_uuid']},
94 unit='Percent')
hamid9f6a2712017-09-27 16:53:56 +050095 index = 0
Benjamin Diaz93699892018-10-12 17:37:30 -030096 for itr in range(len(metric_stats)):
hamid9f6a2712017-09-27 16:53:56 +050097 timestamp_arr[index] = str(metric_stats[itr]['Timestamp'])
98 value_arr[index] = metric_stats[itr]['Maximum']
Benjamin Diaz93699892018-10-12 17:37:30 -030099 index += 1
hamid9f6a2712017-09-27 16:53:56 +0500100 metric_info_dict['time_series'] = timestamp_arr
101 metric_info_dict['metrics_series'] = value_arr
102 log.debug("Metrics Data : %s", metric_info_dict)
103 return metric_info_dict
Benjamin Diaz93699892018-10-12 17:37:30 -0300104 else:
hamid9f6a2712017-09-27 16:53:56 +0500105 log.error("Collection Period should be a multiple of 60")
106 return False
hamid681877c2017-09-18 16:56:59 +0500107
hamid9f6a2712017-09-27 16:53:56 +0500108 else:
hamidbfbc3dd2017-09-30 16:23:30 +0500109 log.error("Metric name is not supported")
hamid9f6a2712017-09-27 16:53:56 +0500110 return False
Benjamin Diaz93699892018-10-12 17:37:30 -0300111
hamid681877c2017-09-18 16:56:59 +0500112 except Exception as e:
113 log.error("Error returning Metrics Data" + str(e))
114
Benjamin Diaz93699892018-10-12 17:37:30 -0300115 def updateMetrics(self, cloudwatch_conn, metric_info):
116
117 """updateMetrics will be returning the metric_uuid=0 and
118 status=True when the metric is supported by AWS"""
hamid681877c2017-09-18 16:56:59 +0500119 try:
Benjamin Diaz93699892018-10-12 17:37:30 -0300120 supported = self.check_metric(metric_info['metric_name'])
hamid681877c2017-09-18 16:56:59 +0500121 update_resp = dict()
hamidbfbc3dd2017-09-30 16:23:30 +0500122 update_resp['resource_uuid'] = metric_info['resource_uuid']
Benjamin Diaz93699892018-10-12 17:37:30 -0300123 if supported['status']:
hamid681877c2017-09-18 16:56:59 +0500124 update_resp['status'] = True
125 update_resp['metric_uuid'] = 0
hamidbfbc3dd2017-09-30 16:23:30 +0500126 log.debug("Metric Updated : %s", update_resp)
hamid681877c2017-09-18 16:56:59 +0500127 else:
128 update_resp['status'] = False
129 update_resp['metric_uuid'] = None
hamidbfbc3dd2017-09-30 16:23:30 +0500130 log.error("Metric name is not supported")
Benjamin Diaz93699892018-10-12 17:37:30 -0300131
132 return update_resp
133
hamid681877c2017-09-18 16:56:59 +0500134 except Exception as e:
135 log.error("Error in Update Metrics" + str(e))
Benjamin Diaz93699892018-10-12 17:37:30 -0300136
137 def deleteMetrics(self, cloudwatch_conn, del_info):
138
139 """ " Not supported in AWS"
140 Returning the required parameters with status = False"""
hamid681877c2017-09-18 16:56:59 +0500141 try:
Benjamin Diaz93699892018-10-12 17:37:30 -0300142 supported = self.check_metric(del_info['metric_name'])
hamid9f6a2712017-09-27 16:53:56 +0500143 metric_resp = dict()
hamid681877c2017-09-18 16:56:59 +0500144 del_resp = dict()
Benjamin Diaz93699892018-10-12 17:37:30 -0300145 if supported['status']:
hamid9f6a2712017-09-27 16:53:56 +0500146 del_resp['schema_version'] = del_info['schema_version']
147 del_resp['schema_type'] = "delete_metric_response"
148 del_resp['metric_name'] = del_info['metric_name']
149 del_resp['metric_uuid'] = del_info['metric_uuid']
150 del_resp['resource_uuid'] = del_info['resource_uuid']
151 # TODO : yet to finalize
152 del_resp['tenant_uuid'] = del_info['tenant_uuid']
153 del_resp['correlation_id'] = del_info['correlation_uuid']
154 del_resp['status'] = False
Benjamin Diaz93699892018-10-12 17:37:30 -0300155 log.info("Metric Deletion Not supported in AWS : %s", del_resp)
hamid9f6a2712017-09-27 16:53:56 +0500156 return del_resp
157 else:
hamidbfbc3dd2017-09-30 16:23:30 +0500158 log.error("Metric name is not supported")
hamid9f6a2712017-09-27 16:53:56 +0500159 return False
hamid681877c2017-09-18 16:56:59 +0500160
161 except Exception as e:
Benjamin Diaz93699892018-10-12 17:37:30 -0300162 log.error(" Metric Deletion Not supported in AWS : " + str(e))
hamid681877c2017-09-18 16:56:59 +0500163
Benjamin Diaz93699892018-10-12 17:37:30 -0300164 def listMetrics(self, cloudwatch_conn, list_info):
165
166 """Returns the list of available AWS/EC2 metrics on which
167 alarms have been configured and the metrics are being monitored"""
hamid681877c2017-09-18 16:56:59 +0500168 try:
169 supported = self.check_metric(list_info['metric_name'])
Benjamin Diaz93699892018-10-12 17:37:30 -0300170 if supported['status']:
hamid9f6a2712017-09-27 16:53:56 +0500171 metrics_list = []
Benjamin Diaz93699892018-10-12 17:37:30 -0300172 metrics_data = dict()
hamid681877c2017-09-18 16:56:59 +0500173
Benjamin Diaz93699892018-10-12 17:37:30 -0300174 # To get the list of associated metrics with the alarms
hamid9f6a2712017-09-27 16:53:56 +0500175 alarms = cloudwatch_conn.describe_alarms()
176 itr = 0
177 if list_info['metric_name'] == "":
178 for alarm in alarms:
179 metrics_info = dict()
Benjamin Diaz93699892018-10-12 17:37:30 -0300180 instance_id = str(alarm.dimensions['InstanceId']).split("'")[1]
181 metrics_info['metric_name'] = str(alarm.metric)
182 metrics_info['metric_uuid'] = 0
183 metrics_info['metric_unit'] = str(alarm.unit)
184 metrics_info['resource_uuid'] = instance_id
185 metrics_list.insert(itr, metrics_info)
hamid681877c2017-09-18 16:56:59 +0500186 itr += 1
Benjamin Diazb85fc8c2018-05-03 13:22:11 -0300187 log.info(metrics_list)
hamid9f6a2712017-09-27 16:53:56 +0500188 return metrics_list
Benjamin Diaz93699892018-10-12 17:37:30 -0300189 else:
hamid9f6a2712017-09-27 16:53:56 +0500190 for alarm in alarms:
191 metrics_info = dict()
192 if alarm.metric == supported['metric_name']:
Benjamin Diaz93699892018-10-12 17:37:30 -0300193 instance_id = str(alarm.dimensions['InstanceId']).split("'")[1]
hamid9f6a2712017-09-27 16:53:56 +0500194 metrics_info['metric_name'] = str(alarm.metric)
Benjamin Diaz93699892018-10-12 17:37:30 -0300195 metrics_info['metric_uuid'] = 0
196 metrics_info['metric_unit'] = str(alarm.unit)
hamid9f6a2712017-09-27 16:53:56 +0500197 metrics_info['resource_uuid'] = instance_id
Benjamin Diaz93699892018-10-12 17:37:30 -0300198 metrics_list.insert(itr, metrics_info)
hamid9f6a2712017-09-27 16:53:56 +0500199 itr += 1
Benjamin Diaz93699892018-10-12 17:37:30 -0300200 return metrics_list
hamid9f6a2712017-09-27 16:53:56 +0500201 else:
hamidbfbc3dd2017-09-30 16:23:30 +0500202 log.error("Metric name is not supported")
hamid9f6a2712017-09-27 16:53:56 +0500203 return False
hamid681877c2017-09-18 16:56:59 +0500204
205 except Exception as e:
206 log.error("Error in Getting Metric List " + str(e))
207
Benjamin Diaz93699892018-10-12 17:37:30 -0300208 def check_metric(self, metric_name):
hamid681877c2017-09-18 16:56:59 +0500209
Benjamin Diaz93699892018-10-12 17:37:30 -0300210 """ Checking whether the metric is supported by AWS """
hamid681877c2017-09-18 16:56:59 +0500211 try:
212 check_resp = dict()
hamid9f6a2712017-09-27 16:53:56 +0500213 # metric_name
hamid681877c2017-09-18 16:56:59 +0500214 if metric_name == 'CPU_UTILIZATION':
215 metric_name = 'CPUUtilization'
216 metric_status = True
217 elif metric_name == 'DISK_READ_OPS':
218 metric_name = 'DiskReadOps'
219 metric_status = True
220 elif metric_name == 'DISK_WRITE_OPS':
221 metric_name = 'DiskWriteOps'
222 metric_status = True
223 elif metric_name == 'DISK_READ_BYTES':
224 metric_name = 'DiskReadBytes'
225 metric_status = True
226 elif metric_name == 'DISK_WRITE_BYTES':
227 metric_name = 'DiskWriteBytes'
228 metric_status = True
229 elif metric_name == 'PACKETS_RECEIVED':
230 metric_name = 'NetworkPacketsIn'
231 metric_status = True
232 elif metric_name == 'PACKETS_SENT':
233 metric_name = 'NetworkPacketsOut'
234 metric_status = True
hamid9f6a2712017-09-27 16:53:56 +0500235 elif metric_name == "":
236 metric_name = None
237 metric_status = True
238 log.info("Metric Not Supported by AWS plugin ")
hamid681877c2017-09-18 16:56:59 +0500239 else:
240 metric_name = None
hamid681877c2017-09-18 16:56:59 +0500241 metric_status = False
hamid9f6a2712017-09-27 16:53:56 +0500242 log.info("Metric Not Supported by AWS plugin ")
hamid681877c2017-09-18 16:56:59 +0500243 check_resp['metric_name'] = metric_name
Benjamin Diaz93699892018-10-12 17:37:30 -0300244 # status
245 if metric_status:
hamid681877c2017-09-18 16:56:59 +0500246 check_resp['status'] = True
hamid9f6a2712017-09-27 16:53:56 +0500247 else:
Benjamin Diazb85fc8c2018-05-03 13:22:11 -0300248 check_resp['status'] = False
hamid9f6a2712017-09-27 16:53:56 +0500249
250 return check_resp
251
Benjamin Diaz93699892018-10-12 17:37:30 -0300252 except Exception as e:
253 log.error("Error in Plugin Inputs %s", str(e))