<NME> test_volumes_get.py
<BEF> # Copyright 2012 OpenStack Foundation
# 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. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

import testtools
from testtools import matchers

from tempest.api.volume import base
from tempest.common import utils
from tempest.common import waiters
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators

CONF = config.CONF


class VolumesGetTest(base.BaseVolumeTest):
    """Test getting volume info"""

    def _volume_create_get_update_delete(self, **kwargs):
        # Create a volume, Get it's details and Delete the volume
        self.assertEqual(202, resp.status)
        self.client.wait_for_resource_deletion(volume_id)

    def _volume_create_get_update_delete(self, **kwargs):
        # Create a volume, Get it's details and Delete the volume
        volume = {}
            volume['id'])['volume']
        self.assertEqual(v_name,
                         fetched_volume['name'],
                         'The fetched Volume name is different '
                         'from the created Volume')
        self.assertEqual(volume['id'],
                         fetched_volume['id'],
                         'The fetched Volume id is different '
                         'from the created Volume')
        self.assertThat(fetched_volume['metadata'].items(),
                        matchers.ContainsAll(metadata.items()),
                        'The fetched Volume metadata misses data '
                        'from the created Volume')

        if 'imageRef' in kwargs:
            self.assertEqual('true', fetched_volume['bootable'])
        else:
            self.assertEqual('false', fetched_volume['bootable'])

        # Update Volume
        # Test volume update when display_name is same with original value
        params = {'name': v_name}
        self.volumes_client.update_volume(volume['id'], **params)
        # Test volume update when display_name is new
        new_v_name = data_utils.rand_name(
            self.__class__.__name__ + '-new-Volume')
        new_desc = 'This is the new description of volume'
        params = {'name': new_v_name,
                  'description': new_desc}
                         fetched_volume['metadata'],
                         'The fetched Volume is different '
                         'from the created Volume')
        if 'imageRef' in kwargs:
            self.assertEqual(fetched_volume['bootable'], True)
        if 'imageRef' not in kwargs:
            self.assertEqual(fetched_volume['bootable'], False)

        # Update Volume
        new_v_name = rand_name('new-Volume')
                        'from the created Volume')

        # Test volume create when display_name is none and display_description
        # contains specific characters,
        # then test volume update if display_name is duplicated
        new_v_desc = data_utils.rand_name('@#$%^* description')
        params = {'description': new_v_desc,
                  'availability_zone': volume['availability_zone'],
                  'size': CONF.volume.volume_size}
        new_volume = self.volumes_client.create_volume(**params)['volume']
        self.addCleanup(self.delete_volume, self.volumes_client,
                        new_volume['id'])
        waiters.wait_for_volume_resource_status(self.volumes_client,
        self.assertEqual(new_v_name, updated_volume['display_name'])
        self.assertEqual(new_desc, updated_volume['display_description'])
        self.assertEqual(metadata, updated_volume['metadata'])
        if 'imageRef' in kwargs:
            self.assertEqual(updated_volume['bootable'], True)
        if 'imageRef' not in kwargs:
            self.assertEqual(updated_volume['bootable'], False)

    @attr(type='gate')
    def test_volume_get_metadata_none(self):
        """Test Create/Get/Update/Delete of a blank volume"""
        self._volume_create_get_update_delete(size=CONF.volume.volume_size)

    @decorators.attr(type='smoke')
    @decorators.idempotent_id('54a01030-c7fc-447c-86ee-c1182beae638')
    @utils.services('image')
    def test_volume_create_get_update_delete_from_image(self):
        """Test Create/Get/Update/Delete of a volume created from image"""
        image = self.images_client.show_image(CONF.compute.image_ref)
        min_disk = image['min_disk']
        disk_size = max(min_disk, CONF.volume.volume_size)
        self._volume_create_get_update_delete(
            imageRef=CONF.compute.image_ref, size=disk_size)

    @decorators.idempotent_id('3f591b4a-7dc6-444c-bd51-77469506b3a1')
    @testtools.skipUnless(CONF.volume_feature_enabled.clone,
                          'Cinder volume clones are disabled')
    def test_volume_create_get_update_delete_as_clone(self):
        """Test Create/Get/Update/Delete of a cloned volume"""
        origin = self.create_volume()
        self._volume_create_get_update_delete(source_volid=origin['id'],
                                              size=CONF.volume.volume_size)


class VolumesSummaryTest(base.BaseVolumeTest):
    """Test volume summary"""

    volume_min_microversion = '3.12'
    volume_max_microversion = 'latest'

    @decorators.idempotent_id('c4f2431e-4920-4736-9e00-4040386b6feb')
    def test_show_volume_summary(self):
        """Test showing volume summary"""
        # check response schema
        self.volumes_client.show_volume_summary()

<MSG> Fix json version of bootable check

This is a follow up to change id:
  I8a4b1f4ce3a6a420e8152ea8c66a9b3fc127fe96

The initial change only addressed the xml aspect of the bug
and ignored the json tests.

This change updates the check to catch the same errors when
performing the json version of the checks.

Both of these patches are temporary and after the Cinder update
lands should be replaced with a proper/strictly enforced check of
'true' and 'false' values in the volume['bootable'] field.

Change-Id: Iffe5d380410f5c698018a5c3106c99af05f0b80d

<DFF> @@ -34,6 +34,15 @@ class VolumesGetTest(base.BaseVolumeTest):
         self.assertEqual(202, resp.status)
         self.client.wait_for_resource_deletion(volume_id)
 
+    def _is_true(self, val):
+        # NOTE(jdg): Temporary conversion method to get cinder patch
+        # merged.  Then we'll make this strict again and
+        #specifically check "true" or "false"
+        if val in ['true', 'True', True]:
+            return True
+        else:
+            return False
+
     def _volume_create_get_update_delete(self, **kwargs):
         # Create a volume, Get it's details and Delete the volume
         volume = {}
@@ -69,10 +78,14 @@ class VolumesGetTest(base.BaseVolumeTest):
                          fetched_volume['metadata'],
                          'The fetched Volume is different '
                          'from the created Volume')
+
+        # NOTE(jdg): Revert back to strict true/false checking
+        # after fix for bug #1227837 merges
+        boot_flag = self._is_true(fetched_volume['bootable'])
         if 'imageRef' in kwargs:
-            self.assertEqual(fetched_volume['bootable'], True)
+            self.assertEqual(boot_flag, True)
         if 'imageRef' not in kwargs:
-            self.assertEqual(fetched_volume['bootable'], False)
+            self.assertEqual(boot_flag, False)
 
         # Update Volume
         new_v_name = rand_name('new-Volume')
@@ -92,10 +105,14 @@ class VolumesGetTest(base.BaseVolumeTest):
         self.assertEqual(new_v_name, updated_volume['display_name'])
         self.assertEqual(new_desc, updated_volume['display_description'])
         self.assertEqual(metadata, updated_volume['metadata'])
+
+        # NOTE(jdg): Revert back to strict true/false checking
+        # after fix for bug #1227837 merges
+        boot_flag = self._is_true(updated_volume['bootable'])
         if 'imageRef' in kwargs:
-            self.assertEqual(updated_volume['bootable'], True)
+            self.assertEqual(boot_flag, True)
         if 'imageRef' not in kwargs:
-            self.assertEqual(updated_volume['bootable'], False)
+            self.assertEqual(boot_flag, False)
 
     @attr(type='gate')
     def test_volume_get_metadata_none(self):

{'commit': 'diff --git a/tempest/api/volume/test_volumes_get.py b/tempest/api/volume/test_volumes_get.py\nindex 119e3e02f..f2915f7ff 100644\n--- a/tempest/api/volume/test_volumes_get.py\n+++ b/tempest/api/volume/test_volumes_get.py\n@@ -34,6 +34,15 @@ class VolumesGetTest(base.BaseVolumeTest):\n         self.assertEqual(202, resp.status)\n         self.client.wait_for_resource_deletion(volume_id)\n \n+    def _is_true(self, val):\n+        # NOTE(jdg): Temporary conversion method to get cinder patch\n+        # merged.  Then we\'ll make this strict again and\n+        #specifically check "true" or "false"\n+        if val in [\'true\', \'True\', True]:\n+            return True\n+        else:\n+            return False\n+\n     def _volume_create_get_update_delete(self, **kwargs):\n         # Create a volume, Get it\'s details and Delete the volume\n         volume = {}\n@@ -69,10 +78,14 @@ class VolumesGetTest(base.BaseVolumeTest):\n                          fetched_volume[\'metadata\'],\n                          \'The fetched Volume is different \'\n                          \'from the created Volume\')\n+\n+        # NOTE(jdg): Revert back to strict true/false checking\n+        # after fix for bug #1227837 merges\n+        boot_flag = self._is_true(fetched_volume[\'bootable\'])\n         if \'imageRef\' in kwargs:\n-            self.assertEqual(fetched_volume[\'bootable\'], True)\n+            self.assertEqual(boot_flag, True)\n         if \'imageRef\' not in kwargs:\n-            self.assertEqual(fetched_volume[\'bootable\'], False)\n+            self.assertEqual(boot_flag, False)\n \n         # Update Volume\n         new_v_name = rand_name(\'new-Volume\')\n@@ -92,10 +105,14 @@ class VolumesGetTest(base.BaseVolumeTest):\n         self.assertEqual(new_v_name, updated_volume[\'display_name\'])\n         self.assertEqual(new_desc, updated_volume[\'display_description\'])\n         self.assertEqual(metadata, updated_volume[\'metadata\'])\n+\n+        # NOTE(jdg): Revert back to strict true/false checking\n+        # after fix for bug #1227837 merges\n+        boot_flag = self._is_true(updated_volume[\'bootable\'])\n         if \'imageRef\' in kwargs:\n-            self.assertEqual(updated_volume[\'bootable\'], True)\n+            self.assertEqual(boot_flag, True)\n         if \'imageRef\' not in kwargs:\n-            self.assertEqual(updated_volume[\'bootable\'], False)\n+            self.assertEqual(boot_flag, False)\n \n     @attr(type=\'gate\')\n     def test_volume_get_metadata_none(self):\n', 'commit_subject': 'Fix json version of bootable check', 'repo_name': 'openstack/tempest', 'committer': {'name': 'John Griffith', 'email': '09b4803c8a41cc8175d06916a7ee91aa990410f4@solidfire.com', 'time_sec': '1379975417', 'tz_offset': '0', 'date': {'seconds': '1379975417'}}, 'commit_tree': 'a3df75cd1238e4dcab70200d65b9be33d30c4766', 'commit_message': "Fix json version of bootable check\n\nThis is a follow up to change id:\n  I8a4b1f4ce3a6a420e8152ea8c66a9b3fc127fe96\n\nThe initial change only addressed the xml aspect of the bug\nand ignored the json tests.\n\nThis change updates the check to catch the same errors when\nperforming the json version of the checks.\n\nBoth of these patches are temporary and after the Cinder update\nlands should be replaced with a proper/strictly enforced check of\n'true' and 'false' values in the volume['bootable'] field.\n\nChange-Id: Iffe5d380410f5c698018a5c3106c99af05f0b80d\n", 'language_name': 'Shell', 'license': 'apache-2.0', 'hunks': '@@ -34,6 +34,15 @@ class VolumesGetTest(base.BaseVolumeTest):\n         self.assertEqual(202, resp.status)\n         self.client.wait_for_resource_deletion(volume_id)\n \n+    def _is_true(self, val):\n+        # NOTE(jdg): Temporary conversion method to get cinder patch\n+        # merged.  Then we\'ll make this strict again and\n+        #specifically check "true" or "false"\n+        if val in [\'true\', \'True\', True]:\n+            return True\n+        else:\n+            return False\n+\n     def _volume_create_get_update_delete(self, **kwargs):\n         # Create a volume, Get it\'s details and Delete the volume\n         volume = {}\n@@ -69,10 +78,14 @@ class VolumesGetTest(base.BaseVolumeTest):\n                          fetched_volume[\'metadata\'],\n                          \'The fetched Volume is different \'\n                          \'from the created Volume\')\n+\n+        # NOTE(jdg): Revert back to strict true/false checking\n+        # after fix for bug #1227837 merges\n+        boot_flag = self._is_true(fetched_volume[\'bootable\'])\n         if \'imageRef\' in kwargs:\n-            self.assertEqual(fetched_volume[\'bootable\'], True)\n+            self.assertEqual(boot_flag, True)\n         if \'imageRef\' not in kwargs:\n-            self.assertEqual(fetched_volume[\'bootable\'], False)\n+            self.assertEqual(boot_flag, False)\n \n         # Update Volume\n         new_v_name = rand_name(\'new-Volume\')\n@@ -92,10 +105,14 @@ class VolumesGetTest(base.BaseVolumeTest):\n         self.assertEqual(new_v_name, updated_volume[\'display_name\'])\n         self.assertEqual(new_desc, updated_volume[\'display_description\'])\n         self.assertEqual(metadata, updated_volume[\'metadata\'])\n+\n+        # NOTE(jdg): Revert back to strict true/false checking\n+        # after fix for bug #1227837 merges\n+        boot_flag = self._is_true(updated_volume[\'bootable\'])\n         if \'imageRef\' in kwargs:\n-            self.assertEqual(updated_volume[\'bootable\'], True)\n+            self.assertEqual(boot_flag, True)\n         if \'imageRef\' not in kwargs:\n-            self.assertEqual(updated_volume[\'bootable\'], False)\n+            self.assertEqual(boot_flag, False)\n \n     @attr(type=\'gate\')\n     def test_volume_get_metadata_none(self):\n', 'addition_count': 21, 'deletion_count': 4, 'src_file': 'a/tempest/api/volume/test_volumes_get.py', 'tgt_file': 'b/tempest/api/volume/test_volumes_get.py', 'file_extension': '.py', 'before_file': '# Copyright 2012 OpenStack Foundation\n# All Rights Reserved.\n#\n#    Licensed under the Apache License, Version 2.0 (the "License"); you may\n#    not use this file except in compliance with the License. You may obtain\n#    a copy of the License at\n#\n#         http://www.apache.org/licenses/LICENSE-2.0\n#\n#    Unless required by applicable law or agreed to in writing, software\n#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\n#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n#    License for the specific language governing permissions and limitations\n#    under the License.\n\nimport testtools\nfrom testtools import matchers\n\nfrom tempest.api.volume import base\nfrom tempest.common import utils\nfrom tempest.common import waiters\nfrom tempest import config\nfrom tempest.lib.common.utils import data_utils\nfrom tempest.lib import decorators\n\nCONF = config.CONF\n\n\nclass VolumesGetTest(base.BaseVolumeTest):\n    """Test getting volume info"""\n\n    def _volume_create_get_update_delete(self, **kwargs):\n        # Create a volume, Get it\'s details and Delete the volume\n        self.assertEqual(202, resp.status)\n        self.client.wait_for_resource_deletion(volume_id)\n\n    def _volume_create_get_update_delete(self, **kwargs):\n        # Create a volume, Get it\'s details and Delete the volume\n        volume = {}\n            volume[\'id\'])[\'volume\']\n        self.assertEqual(v_name,\n                         fetched_volume[\'name\'],\n                         \'The fetched Volume name is different \'\n                         \'from the created Volume\')\n        self.assertEqual(volume[\'id\'],\n                         fetched_volume[\'id\'],\n                         \'The fetched Volume id is different \'\n                         \'from the created Volume\')\n        self.assertThat(fetched_volume[\'metadata\'].items(),\n                        matchers.ContainsAll(metadata.items()),\n                        \'The fetched Volume metadata misses data \'\n                        \'from the created Volume\')\n\n        if \'imageRef\' in kwargs:\n            self.assertEqual(\'true\', fetched_volume[\'bootable\'])\n        else:\n            self.assertEqual(\'false\', fetched_volume[\'bootable\'])\n\n        # Update Volume\n        # Test volume update when display_name is same with original value\n        params = {\'name\': v_name}\n        self.volumes_client.update_volume(volume[\'id\'], **params)\n        # Test volume update when display_name is new\n        new_v_name = data_utils.rand_name(\n            self.__class__.__name__ + \'-new-Volume\')\n        new_desc = \'This is the new description of volume\'\n        params = {\'name\': new_v_name,\n                  \'description\': new_desc}\n                         fetched_volume[\'metadata\'],\n                         \'The fetched Volume is different \'\n                         \'from the created Volume\')\n        if \'imageRef\' in kwargs:\n            self.assertEqual(fetched_volume[\'bootable\'], True)\n        if \'imageRef\' not in kwargs:\n            self.assertEqual(fetched_volume[\'bootable\'], False)\n\n        # Update Volume\n        new_v_name = rand_name(\'new-Volume\')\n                        \'from the created Volume\')\n\n        # Test volume create when display_name is none and display_description\n        # contains specific characters,\n        # then test volume update if display_name is duplicated\n        new_v_desc = data_utils.rand_name(\'@#$%^* description\')\n        params = {\'description\': new_v_desc,\n                  \'availability_zone\': volume[\'availability_zone\'],\n                  \'size\': CONF.volume.volume_size}\n        new_volume = self.volumes_client.create_volume(**params)[\'volume\']\n        self.addCleanup(self.delete_volume, self.volumes_client,\n                        new_volume[\'id\'])\n        waiters.wait_for_volume_resource_status(self.volumes_client,\n        self.assertEqual(new_v_name, updated_volume[\'display_name\'])\n        self.assertEqual(new_desc, updated_volume[\'display_description\'])\n        self.assertEqual(metadata, updated_volume[\'metadata\'])\n        if \'imageRef\' in kwargs:\n            self.assertEqual(updated_volume[\'bootable\'], True)\n        if \'imageRef\' not in kwargs:\n            self.assertEqual(updated_volume[\'bootable\'], False)\n\n    @attr(type=\'gate\')\n    def test_volume_get_metadata_none(self):\n        """Test Create/Get/Update/Delete of a blank volume"""\n        self._volume_create_get_update_delete(size=CONF.volume.volume_size)\n\n    @decorators.attr(type=\'smoke\')\n    @decorators.idempotent_id(\'54a01030-c7fc-447c-86ee-c1182beae638\')\n    @utils.services(\'image\')\n    def test_volume_create_get_update_delete_from_image(self):\n        """Test Create/Get/Update/Delete of a volume created from image"""\n        image = self.images_client.show_image(CONF.compute.image_ref)\n        min_disk = image[\'min_disk\']\n        disk_size = max(min_disk, CONF.volume.volume_size)\n        self._volume_create_get_update_delete(\n            imageRef=CONF.compute.image_ref, size=disk_size)\n\n    @decorators.idempotent_id(\'3f591b4a-7dc6-444c-bd51-77469506b3a1\')\n    @testtools.skipUnless(CONF.volume_feature_enabled.clone,\n                          \'Cinder volume clones are disabled\')\n    def test_volume_create_get_update_delete_as_clone(self):\n        """Test Create/Get/Update/Delete of a cloned volume"""\n        origin = self.create_volume()\n        self._volume_create_get_update_delete(source_volid=origin[\'id\'],\n                                              size=CONF.volume.volume_size)\n\n\nclass VolumesSummaryTest(base.BaseVolumeTest):\n    """Test volume summary"""\n\n    volume_min_microversion = \'3.12\'\n    volume_max_microversion = \'latest\'\n\n    @decorators.idempotent_id(\'c4f2431e-4920-4736-9e00-4040386b6feb\')\n    def test_show_volume_summary(self):\n        """Test showing volume summary"""\n        # check response schema\n        self.volumes_client.show_volume_summary()\n', 'message': "Fix json version of bootable check\n\nThis is a follow up to change id:\n  I8a4b1f4ce3a6a420e8152ea8c66a9b3fc127fe96\n\nThe initial change only addressed the xml aspect of the bug\nand ignored the json tests.\n\nThis change updates the check to catch the same errors when\nperforming the json version of the checks.\n\nBoth of these patches are temporary and after the Cinder update\nlands should be replaced with a proper/strictly enforced check of\n'true' and 'false' values in the volume['bootable'] field.\n\nChange-Id: Iffe5d380410f5c698018a5c3106c99af05f0b80d\n", 'author_name': 'John Griffith', 'lang': 'py'}