diff --git a/src/check_reserved_instances/aws.py b/src/check_reserved_instances/aws.py index 41337e9..56c9d1f 100644 --- a/src/check_reserved_instances/aws.py +++ b/src/check_reserved_instances/aws.py @@ -16,27 +16,6 @@ # reserve expiration time to report with unused reservations reserve_expiry = defaultdict(list) -# normalization factor -# https://aws.amazon.com/blogs/aws/new-instance-size-flexibility-for-ec2-reserved-instances/ -NORMALIZATION_FACTOR = { - 'nano': 0.25, - 'micro': 0.5, - 'small': 1, - 'medium': 2, - 'large': 4, - 'xlarge': 8, - '2xlarge': 16, - '4xlarge': 32, - '8xlarge': 64, - '9xlarge': 72, - '10xlarge': 80, - '12xlarge': 96, - '16xlarge': 128, - '18xlarge': 144, - '24xlarge': 192, - '32xlarge': 256, -} - def create_boto_session(account): """Set up the boto3 session to connect to AWS. diff --git a/src/check_reserved_instances/calculate.py b/src/check_reserved_instances/calculate.py index ce46ac3..bd0f4e5 100644 --- a/src/check_reserved_instances/calculate.py +++ b/src/check_reserved_instances/calculate.py @@ -2,8 +2,30 @@ from __future__ import absolute_import + import datetime +RI_BASE_INSTANCE_TYPE = 'large' +# normalization factor +# https://aws.amazon.com/blogs/aws/new-instance-size-flexibility-for-ec2-reserved-instances/ +NORMALIZATION_FACTOR = { + 'nano': 0.25, + 'micro': 0.5, + 'small': 1, + 'medium': 2, + 'large': 4, + 'xlarge': 8, + '2xlarge': 16, + '4xlarge': 32, + '8xlarge': 64, + '9xlarge': 72, + '10xlarge': 80, + '12xlarge': 96, + '16xlarge': 128, + '18xlarge': 144, + '24xlarge': 192, + '32xlarge': 256, +} def calc_expiry_time(expiry): """Calculate the number of days until the reserved instance expires. @@ -18,6 +40,35 @@ def calc_expiry_time(expiry): """ return (expiry.replace(tzinfo=None) - datetime.datetime.utcnow()).days +def convert_instance(placement_key, count): + """ + Used to calculate normalisation factor. Converts an instance type to RI_BASE_INSTANCE_TYPE + placement_key is a tuple with the instance type and region: e.g ('c4.2xlarge', 'us-west-2a') + count: is an int + + """ + instance = placement_key[0] + region = placement_key[1] + family, instance_type = instance.split('.') + + # test if it is a t instance type + if instance_type.startswith('t'): + print instance_type + return placement_key, count + + # test if we know the instance type + if instance_type not in NORMALIZATION_FACTOR: + return placement_key, count + + # convert instance to normalised instance + multiplier = NORMALIZATION_FACTOR[instance_type] / NORMALIZATION_FACTOR[RI_BASE_INSTANCE_TYPE] + + normalised_placement_key = ("%s.%s" % (family, RI_BASE_INSTANCE_TYPE)) + normalised_count = multiplier * count + + #print("Normalised placement key -> %s: %s" % (normalised_placement_key, normalised_count)) + return normalised_placement_key, normalised_count + def report_diffs(running_instances, reserved_instances): """Calculate differences between reserved instances and running instances. @@ -38,10 +89,25 @@ def report_diffs(running_instances, reserved_instances): """ + normalised_running_instances = {} instance_diff = {} regional_benefit_ris = {} # loop through the reserved instances - for placement_key in reserved_instances: + + # normalise instances using normalisation factor + for placement_key, count in running_instances.items(): + print("%s: %s" % (placement_key, count)) + # convert instance type using normalisation factor + normalised_placement_key, normalised_count = convert_instance(placement_key, count) + count_ = normalised_running_instances.get(normalised_placement_key, 0) + normalised_running_instances[normalised_placement_key] = normalised_count + count_ + + print("normalised running instances") + print normalised_running_instances + + print("reserved") + for placement_key, count in reserved_instances.items(): + print("%s: %s" % (placement_key, count)) # if the AZ from an RI is 'All' (regional benefit RI) if placement_key[1] == 'All': # put into another dict for these RIs for processing later @@ -52,7 +118,8 @@ def report_diffs(running_instances, reserved_instances): placement_key] - running_instances.get(placement_key, 0) # add unreserved instances to instance_diff - for placement_key in running_instances: + for placement_key, count in running_instances.items(): + instance_type = placement_key[0] if placement_key not in reserved_instances: instance_diff[placement_key] = -running_instances[ placement_key]