Esempio n. 1
0
    def test_create_backup(self):
        # Prioritize glance v2 over v1 for deleting/waiting for image status.
        if CONF.image_feature_enabled.api_v2:
            glance_admin_client = self.os_admin.image_client_v2
        elif CONF.image_feature_enabled.api_v1:
            glance_admin_client = self.os_admin.image_client
        else:
            raise lib_exc.InvalidConfiguration(
                'Either api_v1 or api_v2 must be True in '
                '[image-feature-enabled].')

        backup_name = data_utils.rand_name(self.__class__.__name__ + '-Backup')

        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
        resp = self.servers_client.create_backup(self.server_id,
                                                 backup_type='daily',
                                                 rotation=1,
                                                 name=backup_name).response

        # Prior to microversion 2.45, image ID must be parsed from location
        # header. With microversion 2.45+, image_id is returned.
        if api_version_utils.compare_version_header_to_response(
                "OpenStack-API-Version", "2.45", resp, "lt"):
            image_id = resp['image_id']
        else:
            image_id = data_utils.parse_image_id(resp['location'])

        # Use admin credentials to wait since waiting involves show, which is
        # a different policy.
        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
                        glance_admin_client.delete_image, image_id)
        waiters.wait_for_image_status(glance_admin_client, image_id, 'active')
Esempio n. 2
0
    def test_create_second_image_when_first_image_is_being_saved(self):
        """Test creating another server image when first image is being saved

        Creating another server image when first image is being saved is
        not allowed.
        """
        try:
            # Create first snapshot
            image = self.create_image_from_server(self.server_id)
            self.addCleanup(self._reset_server)

            # Create second snapshot
            self.assertRaises(lib_exc.Conflict, self.create_image_from_server,
                              self.server_id)

            if api_version_utils.compare_version_header_to_response(
                    "OpenStack-API-Version", "compute 2.45", image.response,
                    "lt"):
                image_id = image['image_id']
            else:
                image_id = data_utils.parse_image_id(
                    image.response['location'])
            self.client.delete_image(image_id)

        except lib_exc.TimeoutException as ex:
            # Test cannot capture the image saving state.
            # If timeout is reached, we don't need to check state,
            # since, it wouldn't be a 'SAVING' state atleast and apart from
            # it, this testcase doesn't have scope for other state transition
            # Hence, skip the test.
            raise self.skipException("This test is skipped because " + str(ex))
Esempio n. 3
0
    def test_create_image_specify_multibyte_character_image_name(self):
        # prefix character is:
        # http://unicode.org/cldr/utility/character.jsp?a=20A1

        # We use a string with 3 byte utf-8 character due to nova/glance which
        # will return 400(Bad Request) if we attempt to send a name which has
        # 4 byte utf-8 character.
        utf8_name = data_utils.rand_name(b'\xe2\x82\xa1'.decode('utf-8'))
        body = self.client.create_image(self.server_id, name=utf8_name)
        image_id = data_utils.parse_image_id(body.response['location'])
        self.addCleanup(self.client.delete_image, image_id)
Esempio n. 4
0
    def test_delete_image_that_is_not_yet_active(self):
        # Return an error while trying to delete an image what is creating

        image = self.create_image_from_server(self.server_id)
        image_id = data_utils.parse_image_id(image.response['location'])

        self.addCleanup(self._reset_server)

        # Do not wait, attempt to delete the image, ensure it's successful
        self.client.delete_image(image_id)
        self.assertRaises(lib_exc.NotFound, self.client.show_image, image_id)
Esempio n. 5
0
    def test_create_image_specify_multibyte_character_image_name(self):
        # prefix character is:
        # http://unicode.org/cldr/utility/character.jsp?a=20A1

        # We use a string with 3 byte utf-8 character due to nova/glance which
        # will return 400(Bad Request) if we attempt to send a name which has
        # 4 byte utf-8 character.
        utf8_name = data_utils.rand_name(b'\xe2\x82\xa1'.decode('utf-8'))
        body = self.client.create_image(self.server_id, name=utf8_name)
        image_id = data_utils.parse_image_id(body.response['location'])
        self.addCleanup(self.client.delete_image, image_id)
Esempio n. 6
0
    def test_create_image_specify_multibyte_character_image_name(self):
        # prefix character is:
        # http://www.fileformat.info/info/unicode/char/1F4A9/index.htm

        # We use a string with 3 byte utf-8 character due to bug
        # #1370954 in glance which will 500 if mysql is used as the
        # backend and it attempts to store a 4 byte utf-8 character
        utf8_name = data_utils.rand_name(b'\xe2\x82\xa1'.decode('utf-8'))
        body = self.client.create_image(self.server_id, name=utf8_name)
        image_id = data_utils.parse_image_id(body.response['location'])
        self.addCleanup(self.client.delete_image, image_id)
Esempio n. 7
0
    def test_create_second_image_when_first_image_is_being_saved(self):
        # Disallow creating another image when first image is being saved

        # Create first snapshot
        image = self.create_image_from_server(self.server_id)
        self.addCleanup(self._reset_server)

        # Create second snapshot
        self.assertRaises(lib_exc.Conflict, self.create_image_from_server,
                          self.server_id)

        image_id = data_utils.parse_image_id(image.response['location'])
        self.client.delete_image(image_id)
Esempio n. 8
0
    def test_delete_image_that_is_not_yet_active(self):
        """Test deleting a non-active server image should fail"""
        image = self.create_image_from_server(self.server_id)
        if api_version_utils.compare_version_header_to_response(
                "OpenStack-API-Version", "compute 2.45", image.response, "lt"):
            image_id = image['image_id']
        else:
            image_id = data_utils.parse_image_id(image.response['location'])

        self.addCleanup(self._reset_server)

        # Do not wait, attempt to delete the image, ensure it's successful
        self.client.delete_image(image_id)
        self.assertRaises(lib_exc.NotFound, self.client.show_image, image_id)
Esempio n. 9
0
    def test_create_image_specify_multibyte_character_image_name(self):
        # prefix character is:
        # http://unicode.org/cldr/utility/character.jsp?a=20A1

        # We use a string with 3 byte utf-8 character due to nova/glance which
        # will return 400(Bad Request) if we attempt to send a name which has
        # 4 byte utf-8 character.
        utf8_name = data_utils.rand_name(b'\xe2\x82\xa1'.decode('utf-8'))
        body = self.client.create_image(self.server_id, name=utf8_name)
        if api_version_utils.compare_version_header_to_response(
            "OpenStack-API-Version", "compute 2.45", body.response, "lt"):
            image_id = body['image_id']
        else:
            image_id = data_utils.parse_image_id(body.response['location'])
        self.addCleanup(self.client.delete_image, image_id)
Esempio n. 10
0
    def test_create_image_specify_multibyte_character_image_name(self):
        # prefix character is:
        # http://unicode.org/cldr/utility/character.jsp?a=20A1

        # We use a string with 3 byte utf-8 character due to nova/glance which
        # will return 400(Bad Request) if we attempt to send a name which has
        # 4 byte utf-8 character.
        utf8_name = data_utils.rand_name(b'\xe2\x82\xa1'.decode('utf-8'))
        body = self.client.create_image(self.server_id, name=utf8_name)
        if api_version_utils.compare_version_header_to_response(
                "OpenStack-API-Version", "compute 2.45", body.response, "lt"):
            image_id = body['image_id']
        else:
            image_id = data_utils.parse_image_id(body.response['location'])
        self.addCleanup(self.client.delete_image, image_id)
    def test_delete_image_that_is_not_yet_active(self):
        # Return an error while trying to delete an image what is creating

        image = self.create_image_from_server(self.server_id)
        if api_version_utils.compare_version_header_to_response(
            "OpenStack-API-Version", "compute 2.45", image.response, "lt"):
            image_id = image['image_id']
        else:
            image_id = data_utils.parse_image_id(image.response['location'])

        self.addCleanup(self._reset_server)

        # Do not wait, attempt to delete the image, ensure it's successful
        self.client.delete_image(image_id)
        self.assertRaises(lib_exc.NotFound,
                          self.client.show_image, image_id)
Esempio n. 12
0
    def create_image_from_server(cls, server_id, **kwargs):
        """Wrapper utility that returns an image created from the server."""
        name = kwargs.pop('name',
                          data_utils.rand_name(cls.__name__ + "-image"))
        wait_until = kwargs.pop('wait_until', None)
        wait_for_server = kwargs.pop('wait_for_server', True)

        image = cls.compute_images_client.create_image(server_id,
                                                       name=name,
                                                       **kwargs)
        if api_version_utils.compare_version_header_to_response(
                "OpenStack-API-Version", "compute 2.45", image.response, "lt"):
            image_id = image['image_id']
        else:
            image_id = data_utils.parse_image_id(image.response['location'])
        cls.addClassResourceCleanup(test_utils.call_and_ignore_notfound_exc,
                                    cls.compute_images_client.delete_image,
                                    image_id)

        if wait_until is not None:
            try:
                waiters.wait_for_image_status(cls.compute_images_client,
                                              image_id, wait_until)
            except lib_exc.NotFound:
                if wait_until.upper() == 'ACTIVE':
                    # If the image is not found after create_image returned
                    # that means the snapshot failed in nova-compute and nova
                    # deleted the image. There should be a compute fault
                    # recorded with the server in that case, so get the server
                    # and dump some details.
                    server = (
                        cls.servers_client.show_server(server_id)['server'])
                    if 'fault' in server:
                        raise exceptions.SnapshotNotFoundException(
                            server['fault'], image_id=image_id)
                    else:
                        raise exceptions.SnapshotNotFoundException(
                            image_id=image_id)
                else:
                    raise
            image = cls.compute_images_client.show_image(image_id)['image']

            if wait_until.upper() == 'ACTIVE':
                if wait_for_server:
                    waiters.wait_for_server_status(cls.servers_client,
                                                   server_id, 'ACTIVE')
        return image
    def test_create_second_image_when_first_image_is_being_saved(self):
        # Disallow creating another image when first image is being saved

        # Create first snapshot
        image = self.create_image_from_server(self.server_id)
        self.addCleanup(self._reset_server)

        # Create second snapshot
        self.assertRaises(lib_exc.Conflict, self.create_image_from_server,
                          self.server_id)

        if api_version_utils.compare_version_header_to_response(
            "OpenStack-API-Version", "compute 2.45", image.response, "lt"):
            image_id = image['image_id']
        else:
            image_id = data_utils.parse_image_id(image.response['location'])
        self.client.delete_image(image_id)
Esempio n. 14
0
    def test_create_second_image_when_first_image_is_being_saved(self):
        # Disallow creating another image when first image is being saved

        # Create first snapshot
        image = self.create_image_from_server(self.server_id)
        self.addCleanup(self._reset_server)

        # Create second snapshot
        self.assertRaises(lib_exc.Conflict, self.create_image_from_server,
                          self.server_id)

        if api_version_utils.compare_version_header_to_response(
            "OpenStack-API-Version", "compute 2.45", image.response, "lt"):
            image_id = image['image_id']
        else:
            image_id = data_utils.parse_image_id(image.response['location'])
        self.client.delete_image(image_id)
Esempio n. 15
0
    def create_image_from_server(cls, server_id, **kwargs):
        """Wrapper utility that returns an image created from the server."""
        name = kwargs.pop('name',
                          data_utils.rand_name(cls.__name__ + "-image"))
        wait_until = kwargs.pop('wait_until', None)
        wait_for_server = kwargs.pop('wait_for_server', True)

        image = cls.compute_images_client.create_image(server_id, name=name,
                                                       **kwargs)
        image_id = data_utils.parse_image_id(image.response['location'])
        cls.images.append(image_id)

        if wait_until is not None:
            try:
                waiters.wait_for_image_status(cls.compute_images_client,
                                              image_id, wait_until)
            except lib_exc.NotFound:
                if wait_until.upper() == 'ACTIVE':
                    # If the image is not found after create_image returned
                    # that means the snapshot failed in nova-compute and nova
                    # deleted the image. There should be a compute fault
                    # recorded with the server in that case, so get the server
                    # and dump some details.
                    server = (
                        cls.servers_client.show_server(server_id)['server'])
                    if 'fault' in server:
                        raise exceptions.SnapshotNotFoundException(
                            server['fault'], image_id=image_id)
                    else:
                        raise exceptions.SnapshotNotFoundException(
                            image_id=image_id)
                else:
                    raise
            image = cls.compute_images_client.show_image(image_id)['image']

            if wait_until.upper() == 'ACTIVE':
                if wait_for_server:
                    waiters.wait_for_server_status(cls.servers_client,
                                                   server_id, 'ACTIVE')
        return image
Esempio n. 16
0
    def create_image_from_server(cls, server_id, **kwargs):
        """Wrapper utility that returns an image created from the server.

        If compute microversion >= 2.36, the returned image response will
        be from the image service API rather than the compute image proxy API.
        """
        name = kwargs.pop('name',
                          data_utils.rand_name(cls.__name__ + "-image"))
        wait_until = kwargs.pop('wait_until', None)
        wait_for_server = kwargs.pop('wait_for_server', True)

        image = cls.compute_images_client.create_image(server_id,
                                                       name=name,
                                                       **kwargs)
        if api_version_utils.compare_version_header_to_response(
                "OpenStack-API-Version", "compute 2.45", image.response, "lt"):
            image_id = image['image_id']
        else:
            image_id = data_utils.parse_image_id(image.response['location'])

        # The compute image proxy APIs were deprecated in 2.35 so
        # use the images client directly if the API microversion being
        # used is >=2.36.
        if not cls.is_requested_microversion_compatible('2.35'):
            client = cls.images_client
        else:
            client = cls.compute_images_client
        cls.addClassResourceCleanup(test_utils.call_and_ignore_notfound_exc,
                                    client.delete_image, image_id)

        if wait_until is not None:
            try:
                wait_until = wait_until.upper()
                if not cls.is_requested_microversion_compatible('2.35'):
                    wait_until = wait_until.lower()
                waiters.wait_for_image_status(client, image_id, wait_until)
            except lib_exc.NotFound:
                if wait_until.upper() == 'ACTIVE':
                    # If the image is not found after create_image returned
                    # that means the snapshot failed in nova-compute and nova
                    # deleted the image. There should be a compute fault
                    # recorded with the server in that case, so get the server
                    # and dump some details.
                    server = (
                        cls.servers_client.show_server(server_id)['server'])
                    if 'fault' in server:
                        raise exceptions.SnapshotNotFoundException(
                            server['fault'], image_id=image_id)
                    else:
                        raise exceptions.SnapshotNotFoundException(
                            image_id=image_id)
                else:
                    raise
            image = client.show_image(image_id)
            # Compute image client returns response wrapped in 'image' element
            # which is not the case with Glance image client.
            if 'image' in image:
                image = image['image']

            if wait_until.upper() == 'ACTIVE':
                if wait_for_server:
                    waiters.wait_for_server_status(cls.servers_client,
                                                   server_id, 'ACTIVE')
        return image
Esempio n. 17
0
    def create_image_from_server(cls, server_id, **kwargs):
        """Wrapper utility that returns an image created from the server.

        If compute microversion >= 2.36, the returned image response will
        be from the image service API rather than the compute image proxy API.
        """
        name = kwargs.pop('name',
                          data_utils.rand_name(cls.__name__ + "-image"))
        wait_until = kwargs.pop('wait_until', None)
        wait_for_server = kwargs.pop('wait_for_server', True)

        image = cls.compute_images_client.create_image(server_id, name=name,
                                                       **kwargs)
        if api_version_utils.compare_version_header_to_response(
            "OpenStack-API-Version", "compute 2.45", image.response, "lt"):
            image_id = image['image_id']
        else:
            image_id = data_utils.parse_image_id(image.response['location'])

        # The compute image proxy APIs were deprecated in 2.35 so
        # use the images client directly if the API microversion being
        # used is >=2.36.
        if not cls.is_requested_microversion_compatible('2.35'):
            client = cls.images_client
        else:
            client = cls.compute_images_client
        cls.addClassResourceCleanup(test_utils.call_and_ignore_notfound_exc,
                                    client.delete_image, image_id)

        if wait_until is not None:
            try:
                wait_until = wait_until.upper()
                if not cls.is_requested_microversion_compatible('2.35'):
                    wait_until = wait_until.lower()
                waiters.wait_for_image_status(client, image_id, wait_until)
            except lib_exc.NotFound:
                if wait_until.upper() == 'ACTIVE':
                    # If the image is not found after create_image returned
                    # that means the snapshot failed in nova-compute and nova
                    # deleted the image. There should be a compute fault
                    # recorded with the server in that case, so get the server
                    # and dump some details.
                    server = (
                        cls.servers_client.show_server(server_id)['server'])
                    if 'fault' in server:
                        raise exceptions.SnapshotNotFoundException(
                            server['fault'], image_id=image_id)
                    else:
                        raise exceptions.SnapshotNotFoundException(
                            image_id=image_id)
                else:
                    raise
            image = client.show_image(image_id)
            # Compute image client returns response wrapped in 'image' element
            # which is not the case with Glance image client.
            if 'image' in image:
                image = image['image']

            if wait_until.upper() == 'ACTIVE':
                if wait_for_server:
                    waiters.wait_for_server_status(cls.servers_client,
                                                   server_id, 'ACTIVE')
        return image
Esempio n. 18
0
 def test_parse_image_id(self):
     actual = data_utils.parse_image_id("/foo/bar/deadbeaf")
     self.assertEqual("deadbeaf", actual)
Esempio n. 19
0
 def test_parse_image_id(self):
     actual = data_utils.parse_image_id("/foo/bar/deadbeaf")
     self.assertEqual("deadbeaf", actual)
Esempio n. 20
0
    def test_create_backup(self):
        # Positive test:create backup successfully and rotate backups correctly
        # create the first and the second backup

        # Check if glance v1 is available to determine which client to use. We
        # prefer glance v1 for the compute API tests since the compute image
        # API proxy was written for glance v1.
        if CONF.image_feature_enabled.api_v1:
            glance_client = self.os_primary.image_client
        elif CONF.image_feature_enabled.api_v2:
            glance_client = self.os_primary.image_client_v2
        else:
            raise lib_exc.InvalidConfiguration(
                'Either api_v1 or api_v2 must be True in '
                '[image-feature-enabled].')

        backup1 = data_utils.rand_name('backup-1')
        resp = self.client.create_backup(self.server_id,
                                         backup_type='daily',
                                         rotation=2,
                                         name=backup1).response
        oldest_backup_exist = True

        # the oldest one should be deleted automatically in this test
        def _clean_oldest_backup(oldest_backup):
            if oldest_backup_exist:
                try:
                    glance_client.delete_image(oldest_backup)
                except lib_exc.NotFound:
                    pass
                else:
                    LOG.warning(
                        "Deletion of oldest backup %s should not have "
                        "been successful as it should have been "
                        "deleted during rotation.", oldest_backup)

        image1_id = data_utils.parse_image_id(resp['location'])
        self.addCleanup(_clean_oldest_backup, image1_id)
        waiters.wait_for_image_status(glance_client, image1_id, 'active')

        backup2 = data_utils.rand_name('backup-2')
        waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
        resp = self.client.create_backup(self.server_id,
                                         backup_type='daily',
                                         rotation=2,
                                         name=backup2).response
        image2_id = data_utils.parse_image_id(resp['location'])
        self.addCleanup(glance_client.delete_image, image2_id)
        waiters.wait_for_image_status(glance_client, image2_id, 'active')

        # verify they have been created
        properties = {
            'image_type': 'backup',
            'backup_type': "daily",
            'instance_uuid': self.server_id,
        }
        params = {
            'status': 'active',
            'sort_key': 'created_at',
            'sort_dir': 'asc'
        }
        if CONF.image_feature_enabled.api_v1:
            for key, value in properties.items():
                params['property-%s' % key] = value
            image_list = glance_client.list_images(detail=True,
                                                   **params)['images']
        else:
            # Additional properties are flattened in glance v2.
            params.update(properties)
            image_list = glance_client.list_images(params)['images']

        self.assertEqual(2, len(image_list))
        self.assertEqual((backup1, backup2),
                         (image_list[0]['name'], image_list[1]['name']))

        # create the third one, due to the rotation is 2,
        # the first one will be deleted
        backup3 = data_utils.rand_name('backup-3')
        waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
        resp = self.client.create_backup(self.server_id,
                                         backup_type='daily',
                                         rotation=2,
                                         name=backup3).response
        image3_id = data_utils.parse_image_id(resp['location'])
        self.addCleanup(glance_client.delete_image, image3_id)
        # the first back up should be deleted
        waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
        glance_client.wait_for_resource_deletion(image1_id)
        oldest_backup_exist = False
        if CONF.image_feature_enabled.api_v1:
            image_list = glance_client.list_images(detail=True,
                                                   **params)['images']
        else:
            image_list = glance_client.list_images(params)['images']
        self.assertEqual(
            2, len(image_list), 'Unexpected number of images for '
            'v2:test_create_backup; was the oldest backup not '
            'yet deleted? Image list: %s' %
            [image['name'] for image in image_list])
        self.assertEqual((backup2, backup3),
                         (image_list[0]['name'], image_list[1]['name']))
Esempio n. 21
0
    def test_create_backup(self):
        # Positive test:create backup successfully and rotate backups correctly
        # create the first and the second backup

        # Check if glance v1 is available to determine which client to use. We
        # prefer glance v1 for the compute API tests since the compute image
        # API proxy was written for glance v1.
        if CONF.image_feature_enabled.api_v1:
            glance_client = self.os_primary.image_client
        elif CONF.image_feature_enabled.api_v2:
            glance_client = self.os_primary.image_client_v2
        else:
            raise lib_exc.InvalidConfiguration(
                'Either api_v1 or api_v2 must be True in '
                '[image-feature-enabled].')

        backup1 = data_utils.rand_name('backup-1')
        resp = self.client.create_backup(self.server_id,
                                         backup_type='daily',
                                         rotation=2,
                                         name=backup1)
        oldest_backup_exist = True

        # the oldest one should be deleted automatically in this test
        def _clean_oldest_backup(oldest_backup):
            if oldest_backup_exist:
                try:
                    glance_client.delete_image(oldest_backup)
                except lib_exc.NotFound:
                    pass
                else:
                    LOG.warning("Deletion of oldest backup %s should not have "
                                "been successful as it should have been "
                                "deleted during rotation.", oldest_backup)

        if api_version_utils.compare_version_header_to_response(
                "OpenStack-API-Version", "compute 2.45", resp.response, "lt"):
            image1_id = resp['image_id']
        else:
            image1_id = data_utils.parse_image_id(resp.response['location'])
        self.addCleanup(_clean_oldest_backup, image1_id)
        waiters.wait_for_image_status(glance_client,
                                      image1_id, 'active')

        backup2 = data_utils.rand_name('backup-2')
        waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
        resp = self.client.create_backup(self.server_id,
                                         backup_type='daily',
                                         rotation=2,
                                         name=backup2)
        if api_version_utils.compare_version_header_to_response(
                "OpenStack-API-Version", "compute 2.45", resp.response, "lt"):
            image2_id = resp['image_id']
        else:
            image2_id = data_utils.parse_image_id(resp.response['location'])
        self.addCleanup(glance_client.delete_image, image2_id)
        waiters.wait_for_image_status(glance_client,
                                      image2_id, 'active')

        # verify they have been created
        properties = {
            'image_type': 'backup',
            'backup_type': "daily",
            'instance_uuid': self.server_id,
        }
        params = {
            'status': 'active',
            'sort_key': 'created_at',
            'sort_dir': 'asc'
        }
        if CONF.image_feature_enabled.api_v1:
            for key, value in properties.items():
                params['property-%s' % key] = value
            image_list = glance_client.list_images(
                detail=True,
                **params)['images']
        else:
            # Additional properties are flattened in glance v2.
            params.update(properties)
            image_list = glance_client.list_images(params)['images']

        self.assertEqual(2, len(image_list))
        self.assertEqual((backup1, backup2),
                         (image_list[0]['name'], image_list[1]['name']))

        # create the third one, due to the rotation is 2,
        # the first one will be deleted
        backup3 = data_utils.rand_name('backup-3')
        waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
        resp = self.client.create_backup(self.server_id,
                                         backup_type='daily',
                                         rotation=2,
                                         name=backup3)
        if api_version_utils.compare_version_header_to_response(
                "OpenStack-API-Version", "compute 2.45", resp.response, "lt"):
            image3_id = resp['image_id']
        else:
            image3_id = data_utils.parse_image_id(resp.response['location'])
        self.addCleanup(glance_client.delete_image, image3_id)
        # the first back up should be deleted
        waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
        glance_client.wait_for_resource_deletion(image1_id)
        oldest_backup_exist = False
        if CONF.image_feature_enabled.api_v1:
            image_list = glance_client.list_images(
                detail=True, **params)['images']
        else:
            image_list = glance_client.list_images(params)['images']
        self.assertEqual(2, len(image_list),
                         'Unexpected number of images for '
                         'v2:test_create_backup; was the oldest backup not '
                         'yet deleted? Image list: %s' %
                         [image['name'] for image in image_list])
        self.assertEqual((backup2, backup3),
                         (image_list[0]['name'], image_list[1]['name']))