0

Please help me get around this issue: When I try to run the following script, it always returns this error: KeyError: 'AvailabilityZone'

client.describe_instances(Filters=[ {'Name': 'instance-state-name', 'Values': [ 'running', ] } , ], )

Also, I observed that there is no AvailabilityZone string in the response.

Example snippet:

import boto3
import collections
ec2 = boto3.resource('ec2')
instances = ec2.instances.filter(
    Filters=[{'Name': 'instance-state-name', 'Values': ['running']}])


running_instances = {}
for instance in instances:
    az = instance.placement['AvailabilityZone']
    os = instance.platform
    instance_type = instance.instance_type
    if os is None:
        os = 'Linux/UNIX'
    else:
        os = 'Windows'
    if az not in running_instances:
        running_instances[az] = {}
    if os not in running_instances[az]:
        running_instances[az][os] = {}
    if instance_type not in running_instances[az][os]:
        running_instances[az][os][instance_type] = 0
    running_instances[az][os][instance_type] += 1

client = boto3.client('ec2')
response = client.describe_reserved_instances(
    Filters=[
        {
            'Name': 'state',
            'Values': [
                'active',
            ]
        }
    ],
)
cnt = collections.Counter()

reserved_instances = {}
for instance in response['ReservedInstances']:
    az = instance['AvailabilityZone']
    os = instance['ProductDescription']
    instance_type = instance['InstanceType']
    instance_count = instance['InstanceCount']
    if az not in reserved_instances:
        reserved_instances[az] = {}
    if os not in reserved_instances[az]:
        reserved_instances[az][os] = {}
    if instance_type not in reserved_instances[az][os]:
        reserved_instances[az][os][instance_type] = 0
    reserved_instances[az][os][instance_type] += instance_count

print("****** Running Instances breakdown *****")
print(running_instances)
print("****** Reserved Instance breakdown *****")
print(reserved_instances)

2 Answers2

1

First of all, I would recommend pasting your code sample directly into the question rather than linking to it as above. If the linked data ever goes away it will make the question much harder to understand.

I think the problem you are seeing is that as your are looping through the instances returned by describe_instances you are assuming that the placement attribute will always contain a key called AvailabilityZone however if the instance in question is in a stopped state or is terminated that will not be true.

So, you should check to make sure placement has that attribute before accessing it (e.g. if 'AvailabilityZone' in instance.placement).

garnaat
  • 44,310
  • 7
  • 123
  • 103
  • Apologies! Pasted the code into the question. The code used to work fine before but now it is giving errors. Could it be because something changed from AWS side / Boto3 module itself? – Irfan Junaid Aug 27 '17 at 13:06
  • Actually, how about just including the full stack trace. That would help a lot. – garnaat Aug 27 '17 at 17:19
  • The error is occurring in your second loop, as you are iterating over the response to ``describe_reserved_instances``. At least one of the items in that list does not have an ``AvailabilityZone`` key. Try printing the value of ``instance`` each time through the loop and look at the structures that are being returned. – garnaat Aug 30 '17 at 12:16
  • I tried to check the response of client.describe_reserved_instances here [link](https://codeshare.io/5geXlR) As per the documentation [here](http://boto3.readthedocs.io/en/latest/reference/services/ec2.html#EC2.Client.describe_reserved_instances) **describe_reserved_instances** should have _AvailabilityZone_ string in its output... This is what I am concerned of... – Irfan Junaid Aug 30 '17 at 13:27
  • The docs don't say that field will always be there. They say it could be there. Apparently, for at least one of the items in the response it is not. Have you printed that response out to see what it is? – garnaat Aug 30 '17 at 13:36
  • Perhaps that particular reserved instance is part of an offer that is valid across the entire region rather than being limited to a particular AZ? This is an option when purchasing reserved instances. What's the value of the ``Scope`` field? – garnaat Aug 30 '17 at 13:58
  • Thank you for all your help, issue turned out to be due to [this](https://aws.amazon.com/blogs/aws/ec2-reserved-instance-update-convertible-ris-and-regional-benefit/) – Irfan Junaid Aug 30 '17 at 14:01
0

This is the complete ec2.describe_instances response results. The whole json dict structure ls shown clearly as

# ec2.client.describe_instances() responnse structure
{ 'Reservations':[
   {"Group": [{....}]},  
   {"Instances:[{.....}]} 
   ],
  'NextToken': 'string'
}

ec2.client.describe_reserved_instances is about reserved instances you purchase. Reserved instances discounts are dynamically matched with instances that you start, in hourly basis. So you will never get info like OS, instance count,etc.

# describe_reserved_instances is about reserved instances you purchase
{
    'ReservedInstances': [
        {
            'AvailabilityZone': 'string',
            'Duration': 123,
            'End': datetime(2015, 1, 1),
            'FixedPrice': ...,
            'InstanceCount': 123,
            'InstanceType':  
             ............
        },
    ]
} 

What you need to do is follow the correct python dictionary reference. Python will NOT convert the dictionary to dot notation unless you load module like jsontree(only in python2) to convert them. There is also named tuple conversion but I ddint' use them. It is much easier just use the simple dict reference.

So the correct notation reference should looks like this

result = ec2.instances.filter(
    Filters=[{'Name': 'instance-state-name', 'Values': ['running']}])

for reservation in result['Reservations']:
    for instance in reservation['Instances']:
        az = instance['Placement']['AvailabilityZone']

(update) A new AWS admin/user will raise the question, why describe_instances and describe_reserved_intances show different results set?

The short answer is : they are not the same things. describe_instances will show actual AWS VM that you created in the system. On the other hand, reserved instances is NOT a VM, but actually a discounted billing mechanism. So you will NOT see any VM attribute associated with it, but monetary info. AWS will apply the discount logic whenever it see fits, so you will not see a solid itemised billing from describe_reserved_instances.

mootmoot
  • 12,845
  • 5
  • 47
  • 44
  • Hi, thanks for your help... I tried your suggestion, I get an error for this: for reservation in result['Reservations']: Undefined variable:result When I changed it to: for reservation in response['Reservations']: I get: KeyError: 'Reservations' – Irfan Junaid Aug 29 '17 at 02:13
  • @IrfanJunaid Did you notice I change your the code and assign the value to `result` , i.e. `result = ec2.instances.filter....` instead of your code `instances = ec2.instances.filter...` . By the way, your describe_reserved_instances syntax is correct. – mootmoot Aug 29 '17 at 07:27
  • I still don't get it. Tried your edits but still same error. This is the simplified code: [code](https://codeshare.io/2Werq3) – Irfan Junaid Aug 30 '17 at 09:50
  • @IrfanJunaid **Read the response results of boto3 documentation** for both `describe_reserved_instances` and `describe_instances` carefully, they are not the same. You must apply the correct reference for both dictionary. – mootmoot Aug 30 '17 at 11:00
  • @IrfanJunaid if you are still confused, split your code and put into 2 program and diagnose them. – mootmoot Aug 30 '17 at 11:10
  • Please have a look at the code [here](https://codeshare.io/5geXlR). It is not returning the _AvailabilityZone_ string from the response... – Irfan Junaid Aug 30 '17 at 13:29
  • @IrfanJunaid There is NO availabilityzone in `describe_reserved_instances` . Because reserved instances is NOT a real instances, it is a DISCOUNTED BILLING mechanism. Please read the AWS documentation on billing , there are 8 languages that explain this issue. http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/concepts-reserved-instances-application.html – mootmoot Aug 30 '17 at 13:37
  • This is really it! References: [link](https://aws.amazon.com/blogs/aws/ec2-reserved-instance-update-convertible-ris-and-regional-benefit/) and [link](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/concepts-reserved-instances-application.html) Thank You! @mootmoot – Irfan Junaid Aug 30 '17 at 13:59