Repository: GoogleCloudPlatform/PerfKitBenchmarker

Issue:
GPU benchmark - image does not exist: ami-a9d276c9
The AWS image `ami-a9d276c9` does not exist anymore, and it is hard-coded in the `gpu_pcie_bandwidth` benchmark. I believe that this was the latest Ubuntu16.04 image. The benchmark should be modified so that it does not depend on a specific AMI; `describe-images` could be used instead to get the latest 16.04 image.


Discussion:
This AMI does in fact exist and can be found using `describe-images` on the CLI by passing in `--region us-west-2`. Perhaps the AWS provider needs to be modified so that a region can be specified along with an AMI. 
I think PKB's `--zone` flag maps to the AWS' region.

See: https://github.com/GoogleCloudPlatform/PerfKitBenchmarker/blob/master/perfkitbenchmarker/providers/aws/aws_virtual_machine.py#L170

Resolving patch:
diff --git a/perfkitbenchmarker/providers/aws/aws_virtual_machine.py b/perfkitbenchmarker/providers/aws/aws_virtual_machine.py
--- a/perfkitbenchmarker/providers/aws/aws_virtual_machine.py
+++ b/perfkitbenchmarker/providers/aws/aws_virtual_machine.py
@@ -71,11 +71,12 @@
 KNOWN_HOST_STATES = HOST_EXISTS_STATES | HOST_RELEASED_STATES
 
 
-def GetRootBlockDeviceSpecForImage(image_id):
+def GetRootBlockDeviceSpecForImage(image_id, region):
   """ Queries the CLI and returns the root block device specification as a dict.
 
   Args:
     image_id: The EC2 image id to query
+    region: The EC2 region in which the image resides
 
   Returns:
     The root block device specification as returned by the AWS cli,
@@ -85,6 +86,7 @@ def GetRootBlockDeviceSpecForImage(image_id):
   command = util.AWS_PREFIX + [
       'ec2',
       'describe-images',
+      '--region=%s' % region,
       '--image-ids=%s' % image_id,
       '--query', 'Images[]']
   stdout, _ = util.IssueRetryableCommand(command)
@@ -100,7 +102,8 @@ def GetRootBlockDeviceSpecForImage(image_id):
   return root_block_device_dict
 
 
-def GetBlockDeviceMap(machine_type, root_volume_size_gb=None, image_id=None):
+def GetBlockDeviceMap(machine_type, root_volume_size_gb=None,
+                      image_id=None, region=None):
   """Returns the block device map to expose all devices for a given machine.
 
   Args:
@@ -110,6 +113,8 @@ def GetBlockDeviceMap(machine_type, root_volume_size_gb=None, image_id=None):
     image: The image id (AMI) to use in order to lookup the default
       root device specs. This is only required if root_volume_size
       is specified.
+    region: The region which contains the specified image. This is only
+      required if image_id is specified.
 
   Returns:
     The json representation of the block device map for a machine compatible
@@ -122,7 +127,10 @@ def GetBlockDeviceMap(machine_type, root_volume_size_gb=None, image_id=None):
     if image_id is None:
       raise ValueError(
           "image_id must be provided if root_volume_size_gb is specified")
-    root_block_device = GetRootBlockDeviceSpecForImage(image_id)
+    if region is None:
+      raise ValueError(
+          "region must be provided if image_id is specified")
+    root_block_device = GetRootBlockDeviceSpecForImage(image_id, region)
     root_block_device['Ebs']['VolumeSize'] = root_volume_size_gb
     # The 'Encrypted' key must be removed or the CLI will complain
     root_block_device['Ebs'].pop('Encrypted')
@@ -424,7 +432,8 @@ def _Create(self):
     placement = ','.join(placement)
     block_device_map = GetBlockDeviceMap(self.machine_type,
                                          self.boot_disk_size,
-                                         self.image)
+                                         self.image,
+                                         self.region)
     create_cmd = util.AWS_PREFIX + [
         'ec2',
         'run-instances',


Test patch:
diff --git a/tests/aws_test.py b/tests/aws_test.py
--- a/tests/aws_test.py
+++ b/tests/aws_test.py
@@ -181,6 +181,7 @@ def testValidMachineTypeWithSpecifiedRootVolumeSize(self):
     desired_root_volume_size_gb = 35
     machine_type = 'c1.medium'
     image_id = 'ami-a9d276c9'
+    region = 'us-west-2'
     expected = [{'DeviceName': '/dev/sda1',
                  'Ebs': {'SnapshotId': 'snap-826344d5',
                          'DeleteOnTermination': True,
@@ -189,7 +190,7 @@ def testValidMachineTypeWithSpecifiedRootVolumeSize(self):
                 {'DeviceName': '/dev/xvdb',
                  'VirtualName': 'ephemeral0'}]
     actual = json.loads(aws_virtual_machine.GetBlockDeviceMap(
-        machine_type, desired_root_volume_size_gb, image_id))
+        machine_type, desired_root_volume_size_gb, image_id, region))
     self.assertEqual(actual, expected)
 
 
@@ -208,6 +209,7 @@ def setUp(self):
   def testOk(self):
     util.IssueRetryableCommand.side_effect = [(self.describeImageOutput, None)]
     image_id = 'ami-a9d276c9'
+    region = 'us-west-2'
     expected = {
         'DeviceName': '/dev/sda1',
         'Ebs': {
@@ -218,5 +220,6 @@ def testOk(self):
             'Encrypted': False
         }
     }
-    actual = aws_virtual_machine.GetRootBlockDeviceSpecForImage(image_id)
+    actual = aws_virtual_machine.GetRootBlockDeviceSpecForImage(image_id,
+                                                                region)
     self.assertEqual(actual, expected)