Repository: cloud-custodian/cloud-custodian

Issue:
ec2 stop action bug - ec2 root device ebs detection missing 'xvda'
The getting started example that stops EC2 instances with a "Custodian" tag does not work. It's not clear to me how the stop action could ever work. The problem we are seeing is the code here (EC2.py:474):

       for bd in i.get('BlockDeviceMappings', []):
            if bd['DeviceName'] in ('/dev/sda1', '/dev/xvda'):

We have created an instance in which the DeviceName is "xvda", not "/dev/xvda". 

                    "BlockDeviceMappings": [
                        {
                            "Ebs": {
                                "Status": "attached",
                                "VolumeId": "vol-033f1453b3e2d2d81",
                                "DeleteOnTermination": true,
                                "AttachTime": "2017-08-29T19:09:52.000Z"
                            },
                            **"DeviceName": "xvda"**
                        }
So this code fails to detect that the instance has an EBS backed root volume. This instance was created by just using the console with all defaults except for the tagging.


Discussion:
A little more info. We are using Debian Stretch AMIs provided by the Debian group (https://wiki.debian.org/Cloud/AmazonEC2Image), and the name for the root device seems to be based on the AMI. For Debian, this ix "xvda", not "/dev/xvda". So I guess the issue is the assumptions the Custodian makes about the naming of the root device is too restrictive.
could you send a representative copy of your policy, the referenced action (`stop`) does not consider bd mappings.
It is just the sample policy from the getting started section of the
documentation:

```
policies:
  - name: my-first-policy
    resource: ec2
    filters:
      - "tag:Custodian": present
    actions:
      - stop
```

And I ran the code in a debugger and verify this was the policy that was
read, and the code path definitely led to this code:

```
@staticmethod
def is_ephemeral(i):
    for bd in i.get('BlockDeviceMappings', []):
        if bd['DeviceName'] in ('/dev/sda1', '/dev/xvda'):
            if 'Ebs' in bd:
                return False
            return True
    return True
```
I¹m guessing that you don¹t want to stop an instance if the root device is
not EBS-backed? We also noticed that if we modified the code above to accept
a DeviceName of xvda¹, the above condition passed and the instance was
indeed stopped, but then it was also terminated.



thanks for the additional information
indeed that block device examination is to avoid stopping an ephemeral instance (throws an error if an attempt is made). There doesn't seem to be any particular strong rules on the root device identification in a block device mapping, whats documented is /dev/sda1 and /dev/xvda per http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/device_naming.html which is what the code currently defines, perusing http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concepts.html#bdm-to-os and there is a reference to a device name sans /dev/ prefix though.

i'm curious regarding the identity of the image, is that a custom image, or third party.

afaics simply adding 'xvda' to the set of checked root vols should resolve. pull request incoming shortly.


Resolving patch:
diff --git a/c7n/resources/ec2.py b/c7n/resources/ec2.py
--- a/c7n/resources/ec2.py
+++ b/c7n/resources/ec2.py
@@ -471,7 +471,7 @@ def __call__(self, i):
     @staticmethod
     def is_ephemeral(i):
         for bd in i.get('BlockDeviceMappings', []):
-            if bd['DeviceName'] in ('/dev/sda1', '/dev/xvda'):
+            if bd['DeviceName'] in ('/dev/sda1', '/dev/xvda', 'xvda'):
                 if 'Ebs' in bd:
                     return False
                 return True


Test patch: