text: ###################################################################################################################### 
  #  Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.                                           # 
  #                                                                                                                    # 
  #  Licensed under the Apache License Version 2.0 (the "License"). You may not use this file except in compliance     # 
  #  with the License. A copy of the License is located at                                                             # 
  #                                                                                                                    # 
  #      http://www.apache.org/licenses/                                                                               # 
  #                                                                                                                    # 
  #  or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES # 
  #  OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions    # 
  #  and limitations under the License.                                                                                # 
  ######################################################################################################################
  import time
  from datetime import datetime, timedelta
  
  import boto3
  import boto3.exceptions
  
  from helpers.timer import Timer
  
  ONE_DAY = 24 * 3600
  MEGA_BYTE = 1024 * 1024
  
  
  class CloudwatchMetrics(object):
  
      def __init__(self, region=None, session=None):
          self.region = region if region is not None else boto3.Session().region_name
          self.session = session if session is not None else boto3.Session(region_name=self.region)
          self.metrics_client = self.session.client("cloudwatch", region_name=self.region)
  
      def get_daily_volume_iops(self, volume_id, days):
          query_data = [
              {
                  "Id": "rw",
                  "Expression": "r+w",
              },
              {
  
                  "Id": "r",
                  "MetricStat": {
                      "Metric": {
                          "Namespace": "AWS/EBS",
                          "MetricName": "VolumeReadOps",
                          "Dimensions": [
                              {
                                  "Name": "VolumeId",
                                  "Value": volume_id
                              }
                          ]
                      },
                      "Period": 24 * 3600,
                      "Stat": "Sum"
                  },
                  "ReturnData": False
              },
              {
  
                  "Id": "w",
                  "MetricStat": {
                      "Metric": {
                          "Namespace": "AWS/EBS",
                          "MetricName": "VolumeWriteOps",
                          "Dimensions": [
                              {
                                  "Name": "VolumeId",
                                  "Value": volume_id
                              }
                          ]
                      },
                      "Period": 24 * 3600,
                      "Stat": "Sum"
                  },
                  "ReturnData": False
              }
  
          ]
          metrics_data = self.metrics_client.get_metric_data(
              MetricDataQueries=query_data,
              StartTime=datetime.now() - timedelta(days=days),
              EndTime=datetime.now()).get("MetricDataResults", [])
  
          return metrics_data[0]["Values"]
  
      def get_daily_cpu_utilization(self, instance_id, days):
          query_data = [
  
              {
                  "Id": "cpu",
                  "MetricStat": {
                      "Metric": {
                          "Namespace": "AWS/EC2",
                          "MetricName": "CPUUtilization",
                          "Dimensions": [
                              {
                                  "Name": "InstanceId",
                                  "Value": instance_id
                              }
                          ]
                      },
                      "Period": ONE_DAY,
                      "Stat": "Average"
                  },
                  "ReturnData": True
              }
  
          ]
          metrics_data = self.metrics_client.get_metric_data(
              MetricDataQueries=query_data,
              StartTime=datetime.now() - timedelta(days=days),
              EndTime=datetime.now()).get("MetricDataResults", [])
  
          return metrics_data[0]["Values"]
  
      def get_daily_network_io(self, instance_id, days):
          query_data = [
              {
                  "Id": "io",
                  "Expression": "in+out"
              },
              {
  
                  "Id": "in",
                  "MetricStat": {
                      "Metric": {
                          "Namespace": "AWS/EC2",
                          "MetricName": "NetworkIn",
                          "Dimensions": [
                              {
                                  "Name": "InstanceId",
                                  "Value": instance_id
                              }
                          ]
                      },
                      "Period": ONE_DAY,
                      "Stat": "Sum"
                  },
                  "ReturnData": False
              },
              {
  
                  "Id": "out",
                  "MetricStat": {
                      "Metric": {
                          "Namespace": "AWS/EC2",
                          "MetricName": "NetworkOut",
                          "Dimensions": [
                              {
                                  "Name": "InstanceId",
                                  "Value": instance_id
                              }
                          ]
                      },
                      "Period": ONE_DAY,
                      "Stat": "Sum"
                  },
                  "ReturnData": False
              }
          ]
  
          metrics_data = self.metrics_client.get_metric_data(
              MetricDataQueries=query_data,
              StartTime=datetime.now() - timedelta(days=days),
              EndTime=datetime.now()).get("MetricDataResults", [])
  
          return metrics_data[0]["Values"]
  
      def wait_for_volume_iops(self, volume_id, timeout, min_iops):
          with Timer(timeout, start=True) as t:
              while not t.timeout:
                  iops = self.get_daily_volume_iops(volume_id, 1)
                  if len(iops) > 0 and iops[0] >= min_iops:
                      return True
                  time.sleep(15)
  
          return False
  
      def wait_for_cpu_load(self, instance_id, timeout, load):
          with Timer(timeout, start=True) as t:
              while not t.timeout:
                  cpu = self.get_daily_cpu_utilization(instance_id, 1)
                  if len(cpu) > 0 and cpu[0] >= load:
                      return True
                  time.sleep(15)
  
          return False
  
      def wait_for_network_io(self, instance_id, timeout, io_mb):
          with Timer(timeout, start=True) as t:
              while not t.timeout:
                  io = self.get_daily_network_io(instance_id, 1)
                  if len(io) > 0 and io[0] >= io_mb * MEGA_BYTE:
                      return True
                  time.sleep(15)
  
          return False
  
      def get_daily_database_connections(self, db_instance_id, days):
          query_data = [
  
              {
                  "Id": db_instance_id.replace("-", ""),
                  "MetricStat": {
                      "Metric": {
                          "Namespace": "AWS/RDS",
                          "MetricName": "DatabaseConnections",
                          "Dimensions": [
                              {
                                  "Name": "DBInstanceIdentifier",
                                  "Value": db_instance_id
                              }
                          ]
                      },
                      "Period": 24 * 3600,
                      "Stat": "Sum",
                      "Unit": "Count"
                  },
                  "ReturnData": True
              }
          ]
  
          args = {
              "MetricDataQueries": query_data,
              "StartTime": datetime.now() - timedelta(days=days),
              "EndTime": datetime.now()
          }
  
          return self.metrics_client.get_metric_data(**args).get("MetricDataResults", [{}])[0].get("Values", [])
  
      def wait_for_db_connections(self, db_instance_id, timeout):
          with Timer(timeout_seconds=timeout, start=True) as t:
              while not t.timeout:
                  c = self.get_daily_database_connections(db_instance_id, 1)
                  if len(c) > 0 and c[0] > 0:
                      return True
                  time.sleep(15)
              return False
  