Exemple #1
0
class ListVersions(ImagesFixture):

    @data_driven_test(ImagesDatasetListGenerator.Versions())
    def ddtest_list_versions(self, url_addition):
        """
        @summary: List all versions

        @param url_addition: Parameter being passed to the list versions
        request
        @type url_addition: Dictionary

        1) Retrieve the versions data file
        2) List all versions passing in each url addition
        3) Verify that the response code is 300
        4) Verify that the number of versions received matches the number of
        versions in the versions data file
        5) For each version returned, verify that the data matches the
        versions data file
        """

        errors = []

        versions_data = self.images.behaviors.get_comparison_data(
            self.images.config.versions_data)

        resp = self.images.client.list_versions(url_addition)
        self.assertEqual(
            resp.status_code, 300,
            Messages.STATUS_CODE_MSG.format(300, resp.status_code))
        listed_versions = resp.entity

        self.assertEqual(len(listed_versions), len(versions_data))

        for version in listed_versions:
            version_data = versions_data[version.id_]

            if version.links[0].href != version_data.get('href'):
                errors.append(self.error_msg.format(
                    'href', version_data.get('href'), version.links[0].href))
            if version.links[0].rel != version_data.get('rel'):
                errors.append(self.error_msg.format(
                    'rel', version_data.get('rel'), version.links[0].rel))
            if version.status.lower() != version_data.get('status').lower():
                errors.append(self.error_msg.format(
                    'status', version_data.get('status').lower(),
                    version.status.lower()))

        # Allows the full error list to be returned if it is larger than normal
        self.assertEqual.im_class.maxDiff = None

        self.assertListEqual(
            errors, [], msg=('Unexpected errors received. Expected: No errors '
                             'Received: {0}').format(errors))
Exemple #2
0
class VersionsSmoke(ImagesFixture):
    @data_driven_test(ImagesDatasetListGenerator.Versions())
    def ddtest_list_versions(self, url_addition):
        """
        @summary: List all versions

        @param url_addition: Paremter being passed to the list versions request
        @type url_addition: Dictonary

        1) List all versions passing in each url addition
        2) Verify that the response code is 300
        """

        resp = self.images.client.list_versions(url_addition)
        self.assertEqual(
            resp.status_code, 300,
            Messages.STATUS_CODE_MSG.format(300, resp.status_code))
class ImageOperationsSmoke(ImagesFixture):
    @classmethod
    def setUpClass(cls):
        super(ImageOperationsSmoke, cls).setUpClass()

        # Count set to number of images required for this module
        created_images = cls.images.behaviors.create_images_via_task(
            image_properties={'name': rand_name('image_operations_smoke')},
            count=4)

        cls.image = created_images.pop()
        cls.alt_image = created_images.pop()
        cls.activated_image = created_images.pop()

        cls.deactivated_image = created_images.pop()
        cls.images_admin.client.deactivate_image(cls.deactivated_image.id_)

    @classmethod
    def tearDownClass(cls):
        cls.images.behaviors.resources.release()
        super(ImageOperationsSmoke, cls).tearDownClass()

    def test_register_image(self):
        """
        @summary: Register an image

        1) Register an image
        2) Verify that the response code is 201
        3) Add the image to the resource pool for deletion
        """

        resp = self.images.client.register_image(
            name=rand_name('image_operations_smoke'))
        self.assertEqual(
            resp.status_code, 201,
            Messages.STATUS_CODE_MSG.format(201, resp.status_code))
        image = resp.entity

        self.resources.add(image.id_, self.images.client.delete_image)

    @data_driven_test(ImagesDatasetListGenerator.ListImagesSmoke())
    def ddtest_list_images(self, params):
        """
        @summary: List a subset of images passing in valid query parameters

        @param params: Parameter being passed to the list images request
        @type params: Dictionary

        1) List subset of images passing in a query parameter
        2) Verify the response status code is 200
        """

        resp = self.images.client.list_images(params)
        self.assertEqual(
            resp.status_code, 200,
            Messages.STATUS_CODE_MSG.format(200, resp.status_code))

    @data_driven_test(ImagesDatasetListGenerator.ListImagesInvalidParameters())
    def ddtest_invalid_list_images(self, prop):
        """
        @summary: Attempt to list a subset of images passing in invalid query
        parameters

        @param params: Parameter being passed to the list images request
        @type params: Dictionary

        1) Attempt to list a subset of images passing in an invalid query
        parameter
        2) If the invalid query parameter is created_at or updated_at, verify
        the response status code is 400
        3) If the invalid query parameter is not created_at or updated_at,
        verify the response status code is 200
        """

        unacceptable_props = ['created_at', 'updated_at']

        # Most invalid parameters should be ignored, should return 200 response
        resp = self.images.client.list_images(prop)
        # Prop will always only have a single key
        try:
            if prop.keys()[0] in unacceptable_props:
                self.assertEqual(
                    resp.status_code, 400,
                    Messages.STATUS_CODE_MSG.format(400, resp.status_code))
            else:
                self.assertEqual(
                    resp.status_code, 200,
                    Messages.STATUS_CODE_MSG.format(200, resp.status_code))
        except IndexError, error:
            self.fail(msg='No image property passed in. '
                      'Error: {0}'.format(error))
Exemple #4
0
class ListImages(ImagesIntegrationFixture):
    @classmethod
    def setUpClass(cls):
        super(ListImages, cls).setUpClass()

        cls.alt_one_member = cls.images_alt_one.auth.tenant_id

        # Count set to number of images required for this module
        created_images = cls.images.behaviors.create_images_via_task(
            image_properties={'name': rand_name('list_images')}, count=4)

        cls.created_image = created_images.pop()
        cls.images.client.create_image_member(cls.created_image.id_,
                                              cls.alt_one_member)
        resp = cls.images.client.get_image_member(cls.created_image.id_,
                                                  cls.alt_one_member)
        cls.created_image_member = resp.entity

        cls.shared_image = created_images.pop()
        cls.images.client.create_image_member(cls.shared_image.id_,
                                              cls.alt_one_member)

        image = created_images.pop()
        cls.images_admin.client.deactivate_image(image.id_)
        cls.deactivated_imported_image = (cls.images.client.get_image_details(
            image.id_)).entity

        alt_image = created_images.pop()
        cls.images_admin.client.deactivate_image(alt_image.id_)
        cls.images_admin.client.reactivate_image(alt_image.id_)
        cls.reactivated_imported_image = (cls.images.client.get_image_details(
            alt_image.id_)).entity

        created_server = cls.compute.servers.behaviors.create_active_server(
            image_ref=cls.images.config.primary_image).entity
        cls.resources.add(created_server.id,
                          cls.compute.servers.client.delete_server)

        snapshot_image = cls.compute.images.behaviors.create_active_image(
            created_server.id).entity
        cls.resources.add(snapshot_image.id, cls.images.client.delete_image)
        cls.images_admin.client.deactivate_image(snapshot_image.id)
        cls.deactivated_snapshot_image = (cls.images.client.get_image_details(
            snapshot_image.id).entity)

        alt_snapshot_image = cls.compute.images.behaviors.create_active_image(
            created_server.id).entity
        cls.resources.add(alt_snapshot_image.id,
                          cls.images.client.delete_image)
        cls.images_admin.client.deactivate_image(alt_snapshot_image.id)
        cls.images_admin.client.reactivate_image(alt_snapshot_image.id)
        cls.reactivated_snapshot_image = (cls.images.client.get_image_details(
            alt_snapshot_image.id).entity)

    @classmethod
    def tearDownClass(cls):
        cls.images.behaviors.resources.release()
        super(ListImages, cls).tearDownClass()

    def test_compare_list_images_between_glance_and_nova(self):
        """
        @summary: Compare the list of images returned from the glance api and
        the nova api

        1) List images with a limit set to 100 and image_type set to base
        through the glance api
        2) Verify that the response is ok
        3) Verify that the images returned is not none
        4) List images with a limit set to 100 and image_type set to base
        through the nova api
        5) Verify that the response is ok
        6) Verify that the images returned is not none
        7) Verify that the length of the list of images is the same through the
        glance api and the nova api
        8) Verify that each image name in the list of images is the same
        through the glance api and the nova api
        """

        resp = self.images.client.list_images(params={
            'limit': 100,
            'image_type': ImageType.BASE
        })
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))

        glance_image_names = [image.name for image in resp.entity]
        self.assertIsNotNone(glance_image_names,
                             msg=('Unexpected images received.'
                                  'Expected: At least one image received '
                                  'Received: No images received'))

        resp = self.compute.images.client.list_images_with_detail(
            limit=100, image_type='base')
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))

        nova_image_names = [image.name for image in resp.entity]
        self.assertIsNotNone(nova_image_names,
                             msg=('Unexpected images received.'
                                  'Expected: At least one image received '
                                  'Received: No images received'))

        self.assertEqual(
            len(nova_image_names),
            len(glance_image_names),
            msg=('Unexpected images received. Expected: Number of Nova images '
                 '({0}) to match number of Glance images ({1}) Received: '
                 'Number of images do not '
                 'match'.format(len(nova_image_names),
                                len(glance_image_names))))

        images_diff = list(set(glance_image_names) - set(nova_image_names))
        self.assertEqual(images_diff, [],
                         msg=('Unexpected images listed in Glance that are '
                              'not listed in Nova: {0}').format(images_diff))

    def test_image_visibility_of_shared_images(self):
        """
        @summary: Image visibility of shared images

        1) Using alt_one_member, list all images
        2) Verify that shared_image is not present
        3) Using alt_one_member, list all images passing visibility as shared
        and member status as all
        4) Verify that shared_image is now present
        5) Using alt_one_member, update image member status to rejected
        6) Verify that the response is ok
        7) Using alt_one_member, list all images passing visibility as shared
        and member status as all
        8) Verify that shared_image is still present
        """

        listed_images = self.images_alt_one.behaviors.list_all_images()
        self.assertNotIn(
            self.shared_image,
            listed_images,
            msg=('Unexpected image received. Expected: {0} to not be in list '
                 'of images Received: {1}').format(self.shared_image,
                                                   listed_images))

        listed_images = self.images_alt_one.behaviors.list_all_images(
            visibility=ImageVisibility.SHARED,
            member_status=ImageMemberStatus.ALL)
        self.assertIn(
            self.shared_image,
            listed_images,
            msg=('Expected image not received. Expected: {0} to be in list of '
                 'images Received: {1}').format(self.shared_image,
                                                listed_images))

        resp = self.images_alt_one.client.update_image_member(
            self.shared_image.id_, self.alt_one_member,
            ImageMemberStatus.REJECTED)
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))

        listed_images = self.images_alt_one.behaviors.list_all_images(
            visibility=ImageVisibility.SHARED,
            member_status=ImageMemberStatus.ALL)
        self.assertIn(
            self.shared_image,
            listed_images,
            msg=('Expected image not received. Expected: {0} to be in list of '
                 'images Received: {1}').format(self.shared_image,
                                                listed_images))

    @data_driven_test(ImagesDatasetListGenerator.ListImagesFilters())
    def ddtest_filter_images_list(self, params):
        """
        @summary: List all images that match a filter, passing in a specific
        query parameter

        @param param: Parameter being passed to the list images request
        @type param: Dictionary

        1) List all images passing in a query parameter
        2) Verify that the list of images returned is not empty
        3) Verify that each image returned contains a value for the given
        filter that is acceptable
        """

        api_args = {}

        for param in params:
            if param == 'id_':
                api_args.update({'id': getattr(self.created_image, param)})
            elif param == 'created_at' or param == 'updated_at':
                # Params will always only have a single value
                api_args.update({param: 'lte:{0}'.format(params[param])})
            else:
                api_args.update({param: getattr(self.created_image, param)})

        listed_images = self.images.behaviors.list_all_images(**api_args)
        self.assertNotEqual(
            len(listed_images),
            0,
            msg=('Unexpected number of images received. Expected: Not 0 '
                 'Received: {0}').format(len(listed_images)))

        for image in listed_images:
            for param in params:
                received = getattr(image, param)
                expected = getattr(self.created_image, param)
                if param == 'created_at' or param == 'updated_at':
                    # Params will always only have a single value
                    received = datetime.datetime.strptime(
                        str(received), '%Y-%m-%d %H:%M:%S+00:00')
                    expected = datetime.datetime.strptime(
                        params[param], '%Y-%m-%dT%H:%M:%SZ')
                    self.assertLessEqual(
                        received,
                        expected,
                        msg=('Unexpected property value for image {0} '
                             'received. Expected: {1} '
                             'Received: {2}').format(image.id_, expected,
                                                     received))
                else:
                    self.assertEqual(
                        received,
                        expected,
                        msg=('Unexpected property value for image {0} '
                             'received. Expected: {1} '
                             'Received: {2}').format(image.id_, expected,
                                                     received))

    def test_filter_images_list_passing_additional_property(self):
        """
        @summary: List all images that match a filter, passing in an additional
        property as the query parameter

        1) List all images passing in an additional property as the query
        parameter
        2) Verify that the list of images returned is not empty
        3) Verify that each image returned contains a value for the additional
        property that matches the additional property that is being used as the
        filter
        """

        prop = self.images.config.additional_property

        api_args = ({prop: self.created_image.additional_properties.get(prop)})

        listed_images = self.images.behaviors.list_all_images(**api_args)
        self.assertNotEqual(
            len(listed_images),
            0,
            msg=('Unexpected number of images received. Expected: Not 0 '
                 'Received: {0}').format(len(listed_images)))

        for image in listed_images:
            received = image.additional_properties.get(prop)
            expected = (self.created_image.additional_properties.get(prop))
            self.assertEqual(received,
                             expected,
                             msg=('Unexpected property for image {0} received.'
                                  'Expected: {1} '
                                  'Received: {2}').format(
                                      image.id_, expected, received))

    def test_filter_images_list_passing_member_status_pending(self):
        """
        @summary: List all images that match in member_status of pending and
        visibility of shared as the query parameters

        1) List all images passing in member_status of pending and visibility
        of shared as the query parameters
        2) Verify that the list of images returned is not empty
        3) Verify that each image returned list image members
        4) Verify that each image returned contains a value for member_status
        that matches the member_status that is being used as the filter
        """

        api_args = ({
            'member_status':
            getattr(self.created_image_member, 'status'),
            'visibility':
            ImageVisibility.SHARED
        })

        listed_images = self.images_alt_one.behaviors.list_all_images(
            **api_args)
        self.assertNotEqual(
            len(listed_images),
            0,
            msg=('Unexpected number of images received. Expected: Not {0} '
                 'Received: {1}').format(0, len(listed_images)))

        for image in listed_images:
            image_member_statuses = []
            resp = self.images.client.list_image_members(image.id_)
            self.assertTrue(resp.ok,
                            Messages.OK_RESP_MSG.format(resp.status_code))
            list_image_members = resp.entity
            for member in list_image_members:
                image_member_statuses.append(member.status)
                received_image_member_status = (getattr(
                    self.created_image_member, 'status'))
                self.assertIn(getattr(self.created_image_member, 'status'),
                              image_member_statuses,
                              msg=('Unexpected image member status for image'
                                   '{0} received. Expected: {1} in list of'
                                   'image member statuses Received: '
                                   '{2}').format(image.id_,
                                                 received_image_member_status,
                                                 image_member_statuses))

    def test_filter_images_list_passing_size_max(self):
        """
        @summary: List all images that match a filter, passing in size_max as
        the query parameter

        1) List all images passing in size_max as the query parameter
        2) Verify that the list of images returned is not empty
        3) Verify that each image returned contains a value for size that is
        less than or equal to the size_max that is being used as the filter
        """

        api_args = {'size_max': self.images.config.size_max}

        listed_images = self.images.behaviors.list_all_images(**api_args)
        self.assertNotEqual(
            len(listed_images),
            0,
            msg=('Unexpected number of images received. Expected: Not {0} '
                 'Received: {1}').format(0, len(listed_images)))

        for image in listed_images:
            received = getattr(image, 'size')
            expected = self.images.config.size_max
            self.assertLessEqual(
                received,
                expected,
                msg=('Unexpected size_max for image {0} received.'
                     'Expected: <= {1} '
                     'Received: {2}').format(image.id_, expected, received))

    def test_filter_images_list_passing_size_max_and_size_min(self):
        """
        @summary: List all images that match a filter, passing in both size_max
        and size_min as the query parameters

        1) List all images passing in size_max and size_min as the query
        parameters
        2) Verify that the list of images returned is not empty
        3) Verify that each image returned contains a value for size that is
        less than or equal to the size_max that is being used as the filter and
        greater than or equal to the size_min that is being used as the filter
        """

        api_args = {
            'size_max': self.images.config.size_max,
            'size_min': self.images.config.size_min
        }

        listed_images = self.images.behaviors.list_all_images(**api_args)
        self.assertNotEqual(
            len(listed_images),
            0,
            msg=('Unexpected number of images received. Expected: Not {0} '
                 'Received: {1}').format(0, len(listed_images)))

        for image in listed_images:
            received = getattr(image, 'size')
            expected = self.images.config.size_max
            self.assertLessEqual(
                received,
                expected,
                msg=('Unexpected size_max for image {0} received.'
                     'Expected: <= {1} '
                     'Received: {2}').format(image.id_, expected, received))
            expected = getattr(self.images.config, 'size_min')
            self.assertGreaterEqual(
                received,
                expected,
                msg=('Unexpected size_min for image {0} received.'
                     'Expected: >= {1} '
                     'Received: {2}').format(image.id_, expected, received))

    def test_filter_images_list_passing_size_min(self):
        """
        @summary: List all images that match a filter, passing in size_min as
        the query parameter

        1) List all images passing in size_min as the query parameter
        2) Verify that the list of images returned is not empty
        3) Verify that each image returned contains a value for size that is
        greater than or equal to the size_min that is being used as the filter
        """

        api_args = {'size_min': self.images.config.size_min}

        listed_images = self.images.behaviors.list_all_images(**api_args)
        self.assertNotEqual(
            len(listed_images),
            0,
            msg=('Unexpected number of images received. Expected: Not {0} '
                 'Received: {1}').format(0, len(listed_images)))

        for image in listed_images:
            received = getattr(image, 'size')
            expected = self.images.config.size_min
            self.assertGreaterEqual(
                received,
                expected,
                msg=('Unexpected size_min for image {0} received.'
                     'Expected: >= {1} '
                     'Received: {2}').format(image.id_, expected, received))

    def test_filter_images_list_passing_tag(self):
        """
        @summary: List all images that match a filter, passing in tag as
        the query parameter

        1) List all images passing in tag as the query parameter
        2) Verify that the list of images returned is not empty
        3) Verify that each image returned contains a value for tags that
        matches the tag that is being used as the filter
        """

        api_args = {'tag': getattr(self.created_image, 'tags')}

        listed_images = self.images.behaviors.list_all_images(**api_args)
        self.assertNotEqual(
            len(listed_images),
            0,
            msg=('Unexpected number of images received. Expected: Not {0} '
                 'Received: {1}').format(0, len(listed_images)))

        for image in listed_images:
            received = getattr(image, 'tags')
            expected = getattr(self.created_image, 'tags')
            self.assertEqual(
                received,
                expected,
                msg=('Unexpected tags for image {0} received. Expected: {1} '
                     'Received: {2}').format(image.id_, expected, received))

    def test_list_images_using_limit(self):
        """
        @summary: List images using limit

        1) List images passing in 1 as the limit
        2) Verify that the response code is ok
        4) Verify that the number of images returned is 1
        """

        resp = self.images.client.list_images(params={'limit': 1})
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))

        listed_images = resp.entity
        self.assertEqual(
            len(listed_images),
            1,
            msg=('Unexpected number of images received. Expected: {0} '
                 'Received: {1}').format(1, len(listed_images)))

    def test_list_images_using_limit_zero(self):
        """
        @summary: List images using limit of zero

        1) List images passing in 0 as the limit
        2) Verify that the response code is ok
        3) Verify that the number of images returned is 0
        """

        resp = self.images.client.list_images(params={'limit': 0})
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))

        listed_images = resp.entity
        self.assertEqual(
            len(listed_images),
            0,
            msg=('Unexpected number of images received. Expected: {0} '
                 'Received: {1}').format(0, len(listed_images)))

    def test_list_images_using_marker_pagination(self):
        """
        @summary: List images using marker pagination

        1) List images passing in 1 as the limit, the created image's name as
        the name, and the user as the owner
        2) Verify that the response code is ok
        3) Verify that the returned list only contains 1 image
        4) List images again passing in the listed image id as the marker as
        well as 1 as the limit, the created image's name as the name, and the
        user as the owner
        5) Verify that the response code is ok
        6) Verify that the returned list only contains 1 image
        7) Verify that the newly returned image is not the same as the
        previously returned image
        """

        resp = self.images.client.list_images(
            params={
                'limit': 1,
                'name': self.created_image.name,
                'owner': self.images.auth.tenant_id
            })
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))

        listed_image = resp.entity
        self.assertEqual(
            len(listed_image),
            1,
            msg=('Unexpected number of images received. Expected: {0} '
                 'Received: {1}').format(1, len(listed_image)))

        marker = listed_image[0].id_

        resp = self.images.client.list_images(
            params={
                'limit': 1,
                'marker': marker,
                'name': self.created_image.name,
                'owner': self.images.auth.tenant_id
            })
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))

        next_listed_image = resp.entity
        self.assertEqual(
            len(next_listed_image),
            1,
            msg=('Unexpected number of images received. Expected: {0} '
                 'Received: {1}').format(1, len(next_listed_image)))

        self.assertNotEqual(
            listed_image[0],
            next_listed_image[0],
            msg=('Unexpected images received. Expected: Images to not match '
                 'Received: Images match'))

    @data_driven_test(ImagesDatasetListGenerator.ListImagesSort())
    def ddtest_sort_images_list(self, params):
        """
        @summary: List all base images, sorting the list by passing in a query
        parameter as the sort_key and a direction as the sort_dir

        @param params: Parameter being passed to the list images request
        @type params: Dictionary

        1) List all base images passing in a query parameter as the sort_key
        and a direction as the sort_dir
        2) Verify that the list of images returned is not empty
        3) Verify that each image returned is in order based on the sort_key
        and sort_dir
        """

        sort_dir = None
        sort_key = None
        not_str_list = [
            'created_at', 'min_disk', 'min_ram', 'owner', 'size', 'updated_at',
            'user_id'
        ]

        # Only two key-value pairs are passed in, sort_dir and sort_key
        for key in params.keys():
            if key == 'sort_dir':
                sort_dir = params[key]
            elif key == 'sort_key':
                sort_key = params[key]

        params.update({'image_type': ImageType.BASE})

        listed_images = self.images.behaviors.list_all_images(**params)
        self.assertNotEqual(
            len(listed_images),
            0,
            msg=('Unexpected number of images received. Expected: Not {0} '
                 'Received: {1}').format(0, len(listed_images)))

        if sort_key == 'id':
            sort_key = 'id_'

        for current, next_ in zip(listed_images[0::2], listed_images[1::2]):
            current_item = getattr(current, sort_key)
            next_item = getattr(next_, sort_key)
            if sort_key not in not_str_list:
                if current_item is not None:
                    current_item = current_item.lower()
                if next_item is not None:
                    next_item = next_item.lower()
            if sort_dir.lower() == 'asc':
                self.assertLessEqual(
                    current_item,
                    next_item,
                    msg=('Unexpected items for images {0} and {1} received.'
                         'Expected: Less than or equal to {2} '
                         'Received: {3}').format(next_.id_, current.id_,
                                                 next_item, current_item))
            else:
                self.assertGreaterEqual(
                    current_item,
                    next_item,
                    msg=('Unexpected items for images {0} and {1} received.'
                         'Expected: Greater than or equal to {2} '
                         'Received: {3}').format(next_.id_, current.id_,
                                                 next_item, current_item))

    def test_sort_images_list_using_multiple_sort_keys_only(self):
        """
        @summary: List all images, sorting the list by passing in multiple
        query parameters as the sort_keys only

        1) List all images passing in multiple query parameters as the
        sort_keys only via wrapper test method
        2) Verify that each image returned is in order based on the first
        sort_key (descending by default)
        3) If the two images being compared have the same value for the first
        sort_key, verify that each image returned in then in order based on the
        second sort_key (descending by default)
        """

        listed_images = self._list_images_with_sort_keys_dirs(
            ['created_at', 'size'])

        for current, next_ in zip(listed_images[0::2], listed_images[1::2]):
            self.assertGreaterEqual(
                current.created_at,
                next_.created_at,
                msg=('Unexpected order of images {0} and {1} received. '
                     'Expected: Greater than or equal to {2} Received: '
                     '{3}').format(next_.id_, current.id_, next_.created_at,
                                   current.created_at))

            # If created_at dates are equal, verify sizes are in expected order
            if current.created_at == next_.created_at:
                self.assertGreaterEqual(
                    current.size,
                    next_.size,
                    msg=('Unexpected order of images {0} and {1} received.'
                         'Expected: Greater than or equal to {2} Received: '
                         '{3}').format(next_.id_, current.id_, next_.size,
                                       current.size))

    def test_sort_images_list_using_multiple_sort_keys_and_sort_dirs(self):
        """
        @summary: List all images, sorting the list by passing in multiple
        query parameters as the sort_keys and multiple directions as the
        sort_dirs

        1) List all images passing in multiple query parameters as the
        sort_keys and multiple directions as the sort_dirs via wrapper test
        method
        2) Verify that each image returned is in order based on the first
        sort_key and sort_dir
        3) Verify that each image returned in then in order based on the second
        sort_key and sort_dir
        """

        listed_images = self._list_images_with_sort_keys_dirs(
            ['name', 'size'],
            [SortDirection.ASCENDING, SortDirection.DESCENDING])

        for current, next_ in zip(listed_images[0::2], listed_images[1::2]):
            current_name = current.name
            next_name = next_.name
            if current_name is not None:
                current_name = current_name.lower()
            if next_name is not None:
                next_name = next_name.lower()

            self.assertLessEqual(
                next_name,
                next_name,
                msg=('Unexpected order of images {0} and {1} received.'
                     'Expected: Less than or equal to {2} Received: '
                     '{3}').format(next_.id_, current.id_, next_name,
                                   current_name))

            if current_name == next_name:
                self.assertGreaterEqual(
                    current.size,
                    next_.size,
                    msg=('Unexpected order of images {0} and {1} received.'
                         'Expected: Greater than or equal to {2} Received: '
                         '{3}').format(next_.id_, current.id_, next_.size,
                                       current.size))

    def test_sort_images_list_using_multi_sort_keys_and_single_sort_dir(self):
        """
        @summary: List all images, sorting the list by passing in multiple
        query parameters as the sort_keys and a single direction as the
        sort_dir

        1) List all images passing in multiple query parameters as the
        sort_keys and a single direction as the sort_dir via wrapper test
        method
        2) Verify that each image returned is in order based on the first
        sort_key and sort_dir
        3) Verify that each image returned in then in order based on the second
        sort_key and the same sort_dir
        """

        listed_images = self._list_images_with_sort_keys_dirs(
            ['created_at', 'size'], [SortDirection.ASCENDING])

        for current, next_ in zip(listed_images[0::2], listed_images[1::2]):
            self.assertLessEqual(
                current.created_at,
                next_.created_at,
                msg=('Unexpected order of images {0} and {1} received.'
                     'Expected: Less than or equal to {2} Received: '
                     '{3}').format(next_.id_, current.id_, next_.created_at,
                                   current.created_at))

            if current.created_at == next_.created_at:
                self.assertLessEqual(
                    current.size,
                    next_.size,
                    msg=('Unexpected order of images {0} and {1} received.'
                         'Expected: Less than or equal to {2} Received: '
                         '{3}').format(next_.id_, current.id_, next_.size,
                                       current.size))

    def test_sort_images_list_using_multiple_sort_dirs_only(self):
        """
        @summary: List all images, sorting the list by passing in multiple
        query parameters as the sort_dirs only

        1) List all images passing in multiple query parameters as the
        sort_dirs only
        2) Verify that the response code is 400
        """

        sort_dirs = [SortDirection.ASCENDING, SortDirection.DESCENDING]

        sort_pairs = ['sort_dir={0}'.format(key) for key in sort_dirs]

        url_addition = '&'.join(sort_pairs)

        resp = self.images.client.list_images(url_addition=url_addition)
        self.assertEqual(
            resp.status_code, 400,
            Messages.STATUS_CODE_MSG.format(400, resp.status_code))

    def test_sort_images_list_using_single_sort_key_and_multi_sort_dirs(self):
        """
        @summary: List all images, sorting the list by passing in a single
        query parameter as the sort_key and multiple query parameters as the
        sort_dirs

        1) List all images passing in a single query parameter as the sort_key
        and multiple query parameters as the sort_dirs
        2) Verify that the response code is 400
        """

        sort_key = 'name'
        sort_dirs = [SortDirection.ASCENDING, SortDirection.DESCENDING]

        sort_pairs = ['sort_dir={0}'.format(key) for key in sort_dirs]
        sort_pairs.append('sort_key={0}'.format(sort_key))

        url_addition = '&'.join(sort_pairs)

        resp = self.images.client.list_images(url_addition=url_addition)
        self.assertEqual(
            resp.status_code, 400,
            Messages.STATUS_CODE_MSG.format(400, resp.status_code))

    def test_list_deactivated_images(self):
        """
        @summary: List all images with no additional query parameters,
        paginating through the results as needed, and verify that the
        deactivated images are listed

        1) List all images via wrapper test method
        2) Verify that there are no errors
        """

        errors = self._verify_listed_images(
            [self.deactivated_imported_image, self.deactivated_snapshot_image])

        self.assertEqual(
            errors, [],
            msg=('Unexpected errors received. Expected: No errors '
                 'Received: {0}').format(errors))

    def test_list_reactivated_images(self):
        """
        @summary: List all images with no additional query parameters,
        paginating through the results as needed, and verify that the
        reactivated images are listed

        1) List all images via wrapper test method
        2) Verify that there are no errors
        """

        errors = self._verify_listed_images(
            [self.reactivated_imported_image, self.reactivated_snapshot_image])

        self.assertEqual(
            errors, [],
            msg=('Unexpected errors received. Expected: No errors '
                 'Received: {0}').format(errors))

    def _verify_listed_images(self, expected_images):
        """
        @summary: List all images with no additional query parameters,
        paginating through the results as needed, and verify that the
        expected images are listed

        @param expected_images: Images to expect
        @type expected_images: List

        @return: Errors
        @rtype: List

        1) List all images not passing in any additional query parameter,
        paginating through the results as needed
        2) Verify that the list is not empty
        3) Verify that the expected images are in the returned list of
        images
        4) Return errors
        """

        listed_images = self.images.behaviors.list_all_images()

        self.assertNotEqual(
            len(listed_images),
            0,
            msg=('Unexpected number of images received. Expected: Not {0} '
                 'Received: {1}').format(0, len(listed_images)))

        return [('Expected image not received. Expected: {0} in list of '
                 'images Received: {1}').format(image.id_, listed_images)
                for image in expected_images if image not in listed_images]

    def _list_images_with_sort_keys_dirs(self, sort_keys, sort_dirs=None):
        """
        @summary: List all images, sorting the list by passing in query
        parameters for the sort_keys and sort_dirs and return the list of
        images

        @param sort_keys: Keys to sort an image list by
        @type sort_keys: List
        @param sort_dirs: Directions to sort an image list by
        @type sort_dirs: Object

        @return: Listed images
        @rtype: List

        1) List all images passing in query parameters for the sort_keys and
        sort_dirs
        2) Verify that the list of images returned is not empty
        3) Return the list of images
        """

        sort_pairs = [
            'sort_key={0}'.format(sort_key) for sort_key in sort_keys
        ]
        if sort_dirs is not None:
            [
                sort_pairs.append('sort_dir={0}'.format(sort_dir))
                for sort_dir in sort_dirs
            ]

        url_addition = '&'.join(sort_pairs)

        listed_images = self.images.behaviors.list_all_images(url_addition)
        self.assertNotEqual(
            len(listed_images),
            0,
            msg=('Unexpected number of images received. Expected: Not {0} '
                 'Received: {1}').format(0, len(listed_images)))

        return listed_images
class RegisterImage(ImagesFixture):
    @classmethod
    def tearDownClass(cls):
        cls.resources.release()
        super(RegisterImage, cls).tearDownClass()

    def test_register_image_without_passing_properties(self):
        """
        @summary: Register image without passing any properties

        1) Register image without passing any properties
        2) Verify that the response code is 201
        3) Add the image to the resource pool for deletion
        4) Verify that the response contains the properties and values as
        expected
        """

        errors = []
        id_regex = re.compile(ImageProperties.ID_REGEX)

        resp = self.images.client.register_image()
        image_created_at_time_in_sec = calendar.timegm(time.gmtime())
        self.assertEqual(
            resp.status_code, 201,
            Messages.STATUS_CODE_MSG.format(201, resp.status_code))
        reg_image = resp.entity

        self.resources.add(reg_image.id_, self.images.client.delete_image)

        created_at_delta = self.images.behaviors.get_time_delta(
            image_created_at_time_in_sec, reg_image.created_at)
        updated_at_delta = self.images.behaviors.get_time_delta(
            image_created_at_time_in_sec, reg_image.updated_at)

        if reg_image.auto_disk_config is not None:
            errors.append(
                Messages.PROPERTY_MSG.format('auto_disk_config', 'None',
                                             reg_image.auto_disk_config))
        if reg_image.checksum is not None:
            errors.append(
                Messages.PROPERTY_MSG.format('checksum', 'None',
                                             reg_image.checksum))
        if reg_image.container_format is not None:
            errors.append(
                Messages.PROPERTY_MSG.format('container_format', 'None',
                                             reg_image.container_format))
        if created_at_delta > self.images.config.max_created_at_delta:
            errors.append(
                Messages.PROPERTY_MSG.format(
                    'created_at delta',
                    self.images.config.max_created_at_delta, created_at_delta))
        if reg_image.disk_format is not None:
            errors.append(
                Messages.PROPERTY_MSG.format('disk_format', 'None',
                                             reg_image.disk_format))
        if reg_image.file_ != '/v2/images/{0}/file'.format(reg_image.id_):
            errors.append(
                Messages.PROPERTY_MSG.format(
                    'file_', '/v2/images/{0}/file'.format(reg_image.id_),
                    reg_image.file_))
        if id_regex.match(reg_image.id_) is None:
            errors.append(
                Messages.PROPERTY_MSG.format('id_', 'not None', id_regex))
        if reg_image.image_type is not None:
            errors.append(
                Messages.PROPERTY_MSG.format('image_type', 'None',
                                             reg_image.image_type))
        if reg_image.min_disk != 0:
            errors.append(
                Messages.PROPERTY_MSG.format('min_disk', 0,
                                             reg_image.min_disk))
        if reg_image.min_ram != 0:
            errors.append(
                Messages.PROPERTY_MSG.format('min_ram', 0, reg_image.min_ram))
        if reg_image.name is not None:
            errors.append(
                Messages.PROPERTY_MSG.format('name', 'None', reg_image.name))
        if reg_image.os_type is not None:
            errors.append(
                Messages.PROPERTY_MSG.format('os_type', 'None',
                                             reg_image.os_type))
        if reg_image.owner != self.images.auth.tenant_id:
            errors.append(
                Messages.PROPERTY_MSG.format('owner',
                                             self.images.auth.tenant_id,
                                             reg_image.owner))
        if reg_image.protected is not False:
            errors.append(
                Messages.PROPERTY_MSG.format('protected', False,
                                             reg_image.protected))
        if reg_image.schema != Schemas.IMAGE_SCHEMA:
            errors.append(
                Messages.PROPERTY_MSG.format('schema', Schemas.IMAGE_SCHEMA,
                                             reg_image.schema))
        if reg_image.self_ != '/v2/images/{0}'.format(reg_image.id_):
            errors.append(
                Messages.PROPERTY_MSG.format(
                    'self', '/v2/images/{0}'.format(reg_image.id_),
                    reg_image.self_))
        if reg_image.size is not None:
            errors.append(
                Messages.PROPERTY_MSG.format('size', 'None', reg_image.size))
        if reg_image.status != ImageStatus.QUEUED:
            errors.append(
                Messages.PROPERTY_MSG.format('status', ImageStatus.QUEUED,
                                             reg_image.status))
        if reg_image.tags != []:
            errors.append(
                Messages.PROPERTY_MSG.format('tags', [], reg_image.tags))
        if updated_at_delta > self.images.config.max_updated_at_delta:
            errors.append(
                Messages.PROPERTY_MSG.format(
                    'updated_at delta',
                    self.images.config.max_updated_at_delta, updated_at_delta))
        if reg_image.user_id is not None:
            errors.append(
                Messages.PROPERTY_MSG.format('user_id', 'None',
                                             reg_image.user_id))
        if reg_image.visibility != ImageVisibility.PRIVATE:
            errors.append(
                Messages.PROPERTY_MSG.format('visibility',
                                             ImageVisibility.PRIVATE,
                                             reg_image.visibility))
        if reg_image.additional_properties != {}:
            errors.append(
                Messages.PROPERTY_MSG.format('additional_properties', {},
                                             reg_image.additional_properties))

        self.assertEqual(errors, [],
                         msg=('Unexpected error received. Expected: No errors '
                              'Received: {0}').format(errors))

    @unittest.skip('Redmine bug #11436')
    def test_register_image_passing_all_allowed_properties(self):
        """
        @summary: Register image passing all allowed properties

        1) Register image passing all allowed properties
        2) Verify that the response code is 201
        3) Add the image to the resource pool for deletion
        4) Verify that the response contains values for all allowed properties
        as expected
        """

        errors = []
        id_regex = re.compile(ImageProperties.ID_REGEX)
        auto_disk_config = 'False'
        container_format = ImageContainerFormat.AKI
        disk_format = ImageDiskFormat.ISO
        id_ = '00000000-0000-0000-0000-000000000000'
        image_type = ImageType.IMPORT
        min_disk = images.config.min_disk
        min_ram = images.config.min_ram
        name = rand_name('register_image')
        os_type = ImageOSType.LINUX
        protected = False
        tags = [rand_name('tag1')]
        user_id = random_string()
        additional_properties = {
            self.images.config.additional_property:
            self.images.config.additional_property_value
        }

        resp = self.images.client.register_image(
            auto_disk_config=auto_disk_config,
            container_format=container_format,
            disk_format=disk_format,
            id_=id_,
            image_type=image_type,
            min_disk=min_disk,
            min_ram=min_ram,
            name=name,
            os_type=os_type,
            protected=protected,
            tags=tags,
            user_id=user_id,
            additional_properties=additional_properties)
        self.assertEqual(
            resp.status_code, 201,
            Messages.STATUS_CODE_MSG.format(201, resp.status_code))
        reg_image = resp.entity

        self.resources.add(reg_image.id_, self.images.client.delete_image)

        if reg_image.auto_disk_config != auto_disk_config:
            errors.append(
                Messages.PROPERTY_MSG.format('auto_disk_config',
                                             auto_disk_config,
                                             reg_image.auto_disk_config))
        if reg_image.container_format != container_format:
            errors.append(
                Messages.PROPERTY_MSG.format('container_format',
                                             container_format,
                                             reg_image.container_format))
        if reg_image.disk_format != disk_format:
            errors.append(
                Messages.PROPERTY_MSG.format('disk_format', disk_format,
                                             reg_image.disk_format))
        if id_regex.match(reg_image.id_) is None:
            errors.append(
                Messages.PROPERTY_MSG.format('id_', 'not None', id_regex))
        if reg_image.image_type is not None:
            errors.append(
                Messages.PROPERTY_MSG.format('image_type', 'None',
                                             reg_image.image_type))
        if reg_image.min_disk != min_disk:
            errors.append(
                Messages.PROPERTY_MSG.format('min_disk', min_disk,
                                             reg_image.min_disk))
        if reg_image.min_ram != min_ram:
            errors.append(
                Messages.PROPERTY_MSG.format('min_ram', min_ram,
                                             reg_image.min_ram))
        if reg_image.name != name:
            errors.append(
                Messages.PROPERTY_MSG.format('name', name, reg_image.name))
        if reg_image.os_type is not None:
            errors.append(
                Messages.PROPERTY_MSG.format('os_type', 'None',
                                             reg_image.os_type))
        if reg_image.protected != protected:
            errors.append(
                Messages.PROPERTY_MSG.format('protected', protected,
                                             reg_image.protected))
        if reg_image.tags != tags:
            errors.append(
                Messages.PROPERTY_MSG.format('tags', tags, reg_image.tags))
        if reg_image.user_id is not None:
            errors.append(
                Messages.PROPERTY_MSG.format('user_id', 'None',
                                             reg_image.user_id))
        if reg_image.additional_properties != additional_properties:
            errors.append(
                Messages.PROPERTY_MSG.format('additional_properties',
                                             additional_properties,
                                             reg_image.additional_properties))

        self.assertEqual(errors, [],
                         msg=('Unexpected error received. Expected: No errors '
                              'Received: {0}').format(errors))

    @data_driven_test(
        ImagesDatasetListGenerator.UpdateRegisterImageRestricted())
    def ddtest_register_image_passing_restricted_property(self, prop):
        """
        @summary: Register image passing restricted property

        @param prop: Key-value pair containing the image property to validate
        @type prop: Dictionary

        1) Register image passing restricted property
        2) Verify that the response code is 403
        """

        # Each prop passed in only has one key-value pair
        prop_key, prop_val = prop.popitem()

        # This is a temporary workaround for skips in ddtests
        failure_prop_list = [
            'checksum', 'created_at', 'id', 'image_type', 'location',
            'os_type', 'owner', 'schema', 'size', 'status', 'updated_at',
            'user_id', 'visibility'
        ]
        if prop_key in failure_prop_list:
            sys.stderr.write('skipped \'Redmine bug #11436\' ... ')
            return

        if prop_key == 'file' or prop_key == 'self':
            prop = {'{0}_'.format(prop_key): prop_val}

        resp = self.images.client.register_image(
            name=rand_name('register_image'), **prop)
        self.assertEqual(
            resp.status_code, 403,
            Messages.STATUS_CODE_MSG.format(403, resp.status_code))

    def test_register_two_images_passing_same_name(self):
        """
        @summary: Register two images passing the same name for both

        1) Register image passing only name
        2) Verify that the response code is 201
        3) Add the image to the resource pool for deletion
        4) Register another image passing only the same name
        5) Verify that the response code is 201
        6) Add the image to the resource pool for deletion
        7) Verify that the image ids are not the equal
        """

        name = rand_name('register_image')

        resp = self.images.client.register_image(name=name)
        self.assertEqual(
            resp.status_code, 201,
            Messages.STATUS_CODE_MSG.format(201, resp.status_code))
        reg_image = resp.entity

        self.resources.add(reg_image.id_, self.images.client.delete_image)

        resp = self.images.client.register_image(name=name)
        self.assertEqual(
            resp.status_code, 201,
            Messages.STATUS_CODE_MSG.format(201, resp.status_code))
        alt_reg_image = resp.entity

        self.resources.add(alt_reg_image.id_, self.images.client.delete_image)

        self.assertNotEqual(
            reg_image.id_,
            alt_reg_image.id_,
            msg=('Unexpected image ids received. Expected: Image {0} to be '
                 'different from image {1} '
                 'Received: The same image ids'.format(reg_image.id_,
                                                       alt_reg_image.id_)))

    @data_driven_test(ImagesDatasetListGenerator.RegisterImageInvalidValues())
    def ddtest_register_image_passing_invalid_values(self, prop):
        """
        @summary: Register image passing invalid value for image property

        @param prop: Key-value pair containing the image property to validate
        @type prop: Dictionary

        1) Register image passing invalid value for image property
        2) Verify that the response code is 400
        """

        # This is a temporary workaround for skips in ddtests
        if 'auto_disk_config' in prop:
            sys.stderr.write('skipped \'Redmine bug #11438\' ... ')
            return

        if 'name' in prop:
            resp = self.images.client.register_image(**prop)
        else:
            resp = self.images.client.register_image(
                name=rand_name('register_image'), **prop)
        self.assertEqual(
            resp.status_code, 400,
            Messages.STATUS_CODE_MSG.format(400, resp.status_code))

    def test_register_public_image(self):
        """
        @summary: Register a public image by setting the visibility property to
        public

        1) Register image setting the visibility property to public
        2) If the allow_public_images_crud property is true, verify
        that the response code is 201, else verify that the response code is
        403
        3) If the allow_public_images_crud property is true, add the image for
        deletion. List all images accounting for pagination and verify that
        the image is present.
        """

        name = rand_name('register_image')
        resp = self.images.client.register_image(
            name=name, visibility=ImageVisibility.PUBLIC)

        if self.images.config.allow_public_images_crud:
            self.assertEqual(
                resp.status_code, 201,
                Messages.STATUS_CODE_MSG.format(201, resp.status_code))
            reg_image = resp.entity

            self.resources.add(reg_image.id_, self.images.client.delete_image)

            list_images = self.images.behaviors.list_all_images()

            image_names = [image.name for image in list_images]
            self.assertIn(
                name,
                image_names,
                msg=('Unexpected image name received. Expected: {0} in {1} '
                     'Received: Was not present').format(name, image_names))

        else:
            self.assertEqual(
                resp.status_code, 403,
                Messages.STATUS_CODE_MSG.format(403, resp.status_code))
Exemple #6
0
class UpdateRegisteredImage(ImagesFixture):
    @classmethod
    def setUpClass(cls):
        super(UpdateRegisteredImage, cls).setUpClass()

        cls.reg_image = cls.images.behaviors.register_new_image(
            name=rand_name('update_registered_image'))

    @classmethod
    def tearDownClass(cls):
        cls.images.behaviors.resources.release()
        super(UpdateRegisteredImage, cls).tearDownClass()

    @data_driven_test(
        ImagesDatasetListGenerator.UpdateImageAllowed(
            image_status=ImageStatus.QUEUED))
    def ddtest_update_reg_image_replace_allowed_property(self, prop):
        """
        @summary: Update image replacing allowed image property

        @param prop: Key-value pair containing the image property to validate
        @type prop: Dictionary

        1) Update image replacing allowed image property's value
        2) Verify that the response code is 200
        3) Verify that the update image response shows that the property's
        value has been updated as expected
        4) Get image details for the image
        5) Verify that the response is ok
        6) Verify that the get image details response shows that the property's
        value has been updated as expected
        7) Verify that the image's updated_at time has increased
        """

        # Each prop passed in only has one key-value pair
        prop_key, prop_val = prop.popitem()

        resp = self.images.client.update_image(self.reg_image.id_,
                                               replace={prop_key: prop_val})
        self.assertEqual(
            resp.status_code, 200,
            Messages.STATUS_CODE_MSG.format(200, resp.status_code))
        updated_image = resp.entity

        self.assertEqual(
            getattr(updated_image, prop_key),
            prop_val,
            msg=('Unexpected updated image value received. Expected: {0} '
                 'Received: {1}').format(prop_val,
                                         getattr(updated_image, prop_key)))

        resp = self.images.client.get_image_details(self.reg_image.id_)
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))
        get_image = resp.entity

        self.assertEqual(
            getattr(get_image, prop_key),
            prop_val,
            msg=('Unexpected get image details value received. Expected: {0} '
                 'Received: {1}').format(prop_val,
                                         getattr(get_image, prop_key)))

        self.assertGreaterEqual(updated_image.updated_at,
                                self.reg_image.updated_at,
                                msg=('Unexpected updated_at value received. '
                                     'Expected: Greater than {0} '
                                     'Received: {1}').format(
                                         self.reg_image.updated_at,
                                         updated_image.updated_at))
class ImageOperationsSmoke(ImagesFixture):

    @classmethod
    def setUpClass(cls):
        super(ImageOperationsSmoke, cls).setUpClass()

        # Count set to number of images required for this module
        created_images = cls.images.behaviors.create_images_via_task(
            image_properties={'name': rand_name('image_operations_smoke')},
            count=2)

        cls.image = created_images.pop()
        cls.alt_image = created_images.pop()

    @classmethod
    def tearDownClass(cls):
        cls.images.behaviors.resources.release()
        super(ImageOperationsSmoke, cls).tearDownClass()

    @data_driven_test(ImagesDatasetListGenerator.ListImagesSmoke())
    def ddtest_list_images(self, params):
        """
        @summary: List a subset of images passing in valid query parameters

        @param params: Parameter being passed to the list images request
        @type params: Dictionary

        1) List subset of images passing in a query parameter
        2) Verify the response status code is 200
        """

        resp = self.images.client.list_images(params)
        self.assertEqual(
            resp.status_code, 200,
            Messages.STATUS_CODE_MSG.format(200, resp.status_code))

    @data_driven_test(
        ImagesDatasetListGenerator.ListImagesInvalidParameters())
    def ddtest_invalid_list_images(self, params):
        """
        @summary: Attempt to list a subset of images passing in invalid query
        parameters

        @param params: Parameter being passed to the list images request
        @type params: Dictionary

        1) Attempt to list a subset of images passing in an invalid query
        parameter
        2) Verify the response status code is 200
        """

        # Invalid parameters should be ignored, the response code should be 200
        resp = self.images.client.list_images(params)
        self.assertEqual(
            resp.status_code, 200,
            Messages.STATUS_CODE_MSG.format(200, resp.status_code))

    def test_get_image_details(self):
        """
        @summary: Get the details of an image

        1) Get the details of an image passing in an image id
        2) Verify the response status code is 200
        """

        resp = self.images.client.get_image_details(self.image.id_)
        self.assertEqual(
            resp.status_code, 200,
            Messages.STATUS_CODE_MSG.format(200, resp.status_code))

    def test_update_image(self):
        """
        @summary: Update an image

        1) Update an image replacing a single property
        2) Verify that the response code is 200
        """

        updated_name = rand_name('image_operations_smoke_updated')

        resp = self.images.client.update_image(
            self.image.id_, replace={'name': updated_name})
        self.assertEqual(
            resp.status_code, 200,
            Messages.STATUS_CODE_MSG.format(200, resp.status_code))

    def test_delete_image(self):
        """
        @summary: Delete an image

        1) Delete an image
        2) Verify that the response code is 204
        """

        resp = self.images.client.delete_image(self.alt_image.id_)
        self.assertEqual(
            resp.status_code, 204,
            Messages.STATUS_CODE_MSG.format(204, resp.status_code))
Exemple #8
0
class ImageSharingOperationsSmoke(ImagesFixture):
    @classmethod
    def setUpClass(cls):
        super(ImageSharingOperationsSmoke, cls).setUpClass()

        cls.member_id = cls.images_alt_one.auth.tenant_id

        # Count set to number of images required for this module
        created_images = cls.images.behaviors.create_images_via_task(
            image_properties={
                'name': rand_name('image_sharing_operations_smoke')
            },
            count=4)

        cls.created_image = created_images.pop()

        cls.alt_created_image = created_images.pop()
        cls.images.client.create_image_member(cls.alt_created_image.id_,
                                              cls.member_id)

        cls.delete_member_image = created_images.pop()
        cls.images.client.create_image_member(cls.delete_member_image.id_,
                                              cls.member_id)

        cls.update_member_image = created_images.pop()
        cls.images.client.create_image_member(cls.update_member_image.id_,
                                              cls.member_id)

    @classmethod
    def tearDownClass(cls):
        cls.images.behaviors.resources.release()
        super(ImageSharingOperationsSmoke, cls).tearDownClass()

    @data_driven_test(ImagesDatasetListGenerator.ListImageMembersStatuses())
    def ddtest_list_image_members(self, params):
        """
        @summary: List all image members

        @param params: Parameter being passed to the list image members request
        @type params: Dictionary

        1) List all image members passing in a query parameter
        2) Verify the response status code is 200
        """

        resp = self.images.client.list_image_members(self.created_image.id_,
                                                     params)
        self.assertEqual(
            resp.status_code, 200,
            Messages.STATUS_CODE_MSG.format(200, resp.status_code))

    def test_get_image_member(self):
        """
        @summary: Get an image member of an image

        1) Get an image member of an image passing in the image id
        and member id
        4) Verify the response status code is 200
        """

        resp = self.images.client.get_image_member(self.alt_created_image.id_,
                                                   self.member_id)
        self.assertEqual(
            resp.status_code, 200,
            Messages.STATUS_CODE_MSG.format(200, resp.status_code))

    def test_create_image_member(self):
        """
        @summary: Create an image member

        1) As user A, create an image member for an image passing the image id
        and user B's tenant id as member id
        2) Verify the response status code is 200
        """

        resp = self.images.client.create_image_member(self.created_image.id_,
                                                      self.member_id)
        self.assertEqual(
            resp.status_code, 200,
            Messages.STATUS_CODE_MSG.format(200, resp.status_code))

    def test_delete_image_member(self):
        """
        @summary: Delete an image member

        1) As user A, delete an image member for an image passing the image id
        and user B's tenant id as member id
        2) Verify the response status code is 204
        """

        resp = self.images.client.delete_image_member(
            self.delete_member_image.id_, self.member_id)
        self.assertEqual(
            resp.status_code, 204,
            Messages.STATUS_CODE_MSG.format(204, resp.status_code))

    def test_update_image_member(self):
        """
        @summary: Update an image member

        1) As user B, update an image member of an image passing in the
        image id, member id, and 'accepted' as the status
        2) Verify the response status code is 200
        """

        resp = self.images_alt_one.client.update_image_member(
            self.update_member_image.id_, self.member_id,
            ImageMemberStatus.ACCEPTED)
        self.assertEqual(
            resp.status_code, 200,
            Messages.STATUS_CODE_MSG.format(200, resp.status_code))
Exemple #9
0
class UpdateImage(ImagesFixture):
    @classmethod
    def setUpClass(cls):
        super(UpdateImage, cls).setUpClass()

        # Count set to number of images required for this module
        created_images = cls.images.behaviors.create_images_via_task(
            image_properties={'name': rand_name('update_image')}, count=3)

        cls.created_image = created_images.pop()
        cls.alt_created_image = created_images.pop()
        cls.quota_image = created_images.pop()

    @classmethod
    def tearDownClass(cls):
        cls.images.client.update_image(cls.created_image.id_,
                                       replace={'protected': False})
        cls.images.behaviors.resources.release()
        super(UpdateImage, cls).tearDownClass()

    @data_driven_test(ImagesDatasetListGenerator.UpdateImageAllowed())
    def ddtest_update_image_replace_allowed_property(self, prop):
        """
        @summary: Update image replacing allowed image property

        @param prop: Key-value pair containing the image property to validate
        @type prop: Dictionary

        1) Update image replacing allowed image property's value
        2) Verify that the response code is 200
        3) Verify that the update image response shows that the property's
        value has been updated as expected
        4) Get image details for the image
        5) Verify that the response is ok
        6) Verify that the get image details response shows that the property's
        value has been updated as expected
        7) Verify that the image's updated_at time has increased
        """

        # Each prop passed in only has one key-value pair
        prop_key, prop_val = prop.popitem()

        resp = self.images.client.update_image(self.created_image.id_,
                                               replace={prop_key: prop_val})
        self.assertEqual(
            resp.status_code, 200,
            Messages.STATUS_CODE_MSG.format(200, resp.status_code))
        updated_image = resp.entity

        self.assertEqual(
            getattr(updated_image, prop_key),
            prop_val,
            msg=('Unexpected updated image value received. Expected: {0} '
                 'Received: {1}').format(prop_val,
                                         getattr(updated_image, prop_key)))

        resp = self.images.client.get_image_details(self.created_image.id_)
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))
        get_image = resp.entity

        self.assertEqual(
            getattr(get_image, prop_key),
            prop_val,
            msg=('Unexpected get image details value received. Expected: {0} '
                 'Received: {1}').format(prop_val,
                                         getattr(get_image, prop_key)))

        self.assertGreaterEqual(updated_image.updated_at,
                                self.created_image.updated_at,
                                msg=('Unexpected updated_at value received. '
                                     'Expected: Greater than {0} '
                                     'Received: {1}').format(
                                         self.created_image.updated_at,
                                         updated_image.updated_at))

    @data_driven_test(ImagesDatasetListGenerator.UpdateImageInaccessible())
    def ddtest_update_image_replace_inaccessible_property(self, prop):
        """
        @summary: Update image replacing inaccessible image property

        @param prop: Key-value pair containing the image property to validate
        @type prop: Dictionary

        1) Update image replacing inaccessible image property's value
        2) Verify that the response code is 403
        """

        # Each prop passed in only has one key-value pair
        prop_key, prop_val = prop.popitem()

        resp = self.images.client.update_image(self.alt_created_image.id_,
                                               replace={prop_key: prop_val})
        self.assertEqual(
            resp.status_code, 403,
            Messages.STATUS_CODE_MSG.format(403, resp.status_code))

    @data_driven_test(
        ImagesDatasetListGenerator.UpdateRegisterImageRestricted())
    def ddtest_update_image_replace_restricted_property(self, prop):
        """
        @summary: Update image replacing restricted image property

        @param prop: Key-value pair containing the image property to validate
        @type prop: Dictionary

        1) Update image replacing restricted image property's value
        2) Verify that the response code is 403
        3) Get image details for the image
        4) Verify that the response is ok
        5) Verify that the get image details response shows that the property's
        value has not been updated
        """

        # Each prop passed in only has one key-value pair
        prop_key, prop_val = prop.popitem()

        # This is a temporary workaround for skips in ddtests
        if prop_key == 'id':
            sys.stderr.write('skipped \'Redmine bug #11398\' ... ')
            return

        resp = self.images.client.update_image(self.alt_created_image.id_,
                                               replace={prop_key: prop_val})
        self.assertEqual(
            resp.status_code, 403,
            Messages.STATUS_CODE_MSG.format(403, resp.status_code))

        resp = self.images.client.get_image_details(self.alt_created_image.id_)
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))
        get_image = resp.entity

        prop_key = self._check_prop_key(prop_key)

        self.assertEqual(
            getattr(get_image, prop_key),
            getattr(self.alt_created_image, prop_key),
            msg=('Unexpected get image details value received. Expected: {0} '
                 'Received: {1}').format(
                     getattr(self.alt_created_image, prop_key),
                     getattr(get_image, prop_key)))

    @data_driven_test(
        ImagesDatasetListGenerator.UpdateRegisterImageRestricted())
    def ddtest_update_image_add_restricted_property(self, prop):
        """
        @summary: Update image adding restricted image property

        @param prop: Key-value pair containing the image property to validate
        @type prop: Dictionary

        1) Update image adding restricted image property
        2) Verify that the response code is 403
        3) Get image details for the image
        4) Verify that the response is ok
        5) Verify that the get image details response shows that the property
        has been not been added
        """

        # Each prop passed in only has one key-value pair
        prop_key, prop_val = prop.popitem()

        # This is a temporary workaround for skips in ddtests
        if prop_key == 'id':
            sys.stderr.write('skipped \'Redmine bug #11398\' ... ')
            return

        resp = self.images.client.update_image(self.alt_created_image.id_,
                                               add={prop_key: prop_val})
        self.assertEqual(
            resp.status_code, 403,
            Messages.STATUS_CODE_MSG.format(403, resp.status_code))

        resp = self.images.client.get_image_details(self.alt_created_image.id_)
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))
        get_image = resp.entity

        prop_key = self._check_prop_key(prop_key)

        self.assertEqual(
            getattr(get_image, prop_key),
            getattr(self.alt_created_image, prop_key),
            msg=('Unexpected get image details value received. Expected: {0} '
                 'Received: {1}').format(
                     getattr(self.alt_created_image, prop_key),
                     getattr(get_image, prop_key)))

    @data_driven_test(
        ImagesDatasetListGenerator.UpdateRegisterImageRestricted())
    def ddtest_update_image_remove_restricted_property(self, prop):
        """
        @summary: Update image removing restricted image property

        @param prop: Key-value pair containing the image property to validate
        @type prop: Dictionary

        1) Update image removing restricted image property
        2) Verify that the response code is 403
        3) Get image details for the image
        4) Verify that the response is ok
        5) Verify that the get image details response shows that the property
        has been not been removed
        """

        # Each prop passed in only has one key-value pair
        prop_key, prop_val = prop.popitem()

        # This is a temporary workaround for skips in ddtests
        failure_prop_list = ['id', 'file', 'schema', 'self']
        if prop_key in failure_prop_list:
            sys.stderr.write('skipped \'Launchpad bug #1438826\' ... ')
            return

        resp = self.images.client.update_image(self.alt_created_image.id_,
                                               remove={prop_key: prop_val})
        self.assertEqual(
            resp.status_code, 403,
            Messages.STATUS_CODE_MSG.format(403, resp.status_code))

        resp = self.images.client.get_image_details(self.alt_created_image.id_)
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))
        get_image = resp.entity

        prop_key = self._check_prop_key(prop_key)

        self.assertEqual(
            getattr(get_image, prop_key),
            getattr(self.alt_created_image, prop_key),
            msg=('Unexpected get image details value received. Expected: {0} '
                 'Received: {1}').format(
                     getattr(self.alt_created_image, prop_key),
                     getattr(get_image, prop_key)))

    def test_update_image_add_new_property(self):
        """
        @summary: Update image by adding a new image property

        1) Update image adding a new image property
        2) Verify that the response code is 200
        3) Verify that the update image response shows that the new property
        has been added as expected
        4) Get image details for the image
        5) Verify that the response is ok
        6) Verify that the get image details response shows that the new
        property has been added as expected
        """

        new_prop = 'new_property'
        new_prop_value = rand_name('new_property_value')

        resp = self.images.client.update_image(self.created_image.id_,
                                               add={new_prop: new_prop_value})
        self.assertEqual(
            resp.status_code, 200,
            Messages.STATUS_CODE_MSG.format(200, resp.status_code))
        updated_image = resp.entity

        added_prop_value = (updated_image.additional_properties.get(
            new_prop, None))

        self.assertEqual(
            added_prop_value,
            new_prop_value,
            msg=('Unexpected new image property value received. Expected: {0} '
                 'Received: {1}').format(new_prop_value, added_prop_value))

        resp = self.images.client.get_image_details(self.created_image.id_)
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))
        get_image = resp.entity

        get_added_prop_value = (get_image.additional_properties.get(
            new_prop, None))

        self.assertEqual(
            get_added_prop_value,
            new_prop_value,
            msg=('Unexpected new image property value received. Expected: {0} '
                 'Received: {1}').format(new_prop_value, get_added_prop_value))

    def test_update_image_remove_property(self):
        """
        @summary: Update image by removing an image property

        1) Update image adding a new image property
        2) Verify that the response code is 200
        3) Update the image removing the new image property
        4) Verify that the response code is 200
        5) Verify that the update image response shows that the new
        property has been removed as expected
        6) Get image details for the image
        7) Verify that the response code is ok
        8) Verify that the get image response shows that the new
        property has been removed as expected
        """

        new_prop = 'alt_new_property'
        new_prop_value = rand_name('alt_new_property_value')

        resp = self.images.client.update_image(self.created_image.id_,
                                               add={new_prop: new_prop_value})
        self.assertEqual(
            resp.status_code, 200,
            Messages.STATUS_CODE_MSG.format(200, resp.status_code))

        response = self.images.client.update_image(
            self.created_image.id_, remove={new_prop: new_prop_value})
        self.assertEqual(
            resp.status_code, 200,
            Messages.STATUS_CODE_MSG.format(200, resp.status_code))
        updated_image = response.entity

        self.assertNotIn(
            new_prop,
            updated_image.additional_properties,
            msg=('Unexpected removed image property received. Expected: {0} '
                 'to not be present '
                 'Received: {1}').format(new_prop,
                                         updated_image.additional_properties))

        resp = self.images.client.get_image_details(self.created_image.id_)
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))
        get_image = resp.entity

        self.assertNotIn(
            new_prop,
            get_image.additional_properties,
            msg=('Unexpected removed image property received. Expected: {0} '
                 'to not be present '
                 'Received: {1}').format(new_prop,
                                         get_image.additional_properties))

    def test_update_image_replace_additional_property(self):
        """
        @summary: Update image by replacing an additional image property

        1) Update image adding a new image property
        2) Verify that the response code is 200
        3) Update the image replacing the new image property's value
        4) Verify that the response code is 200
        5) Verify that the update image response shows that the new property's
        value has been updated as expected
        6) Get image details for the image
        7) Verify that the response code is ok
        8) Verify that the get image response shows that the new
        property's value has been updated as expected
        """

        new_prop = 'alt_two_new_property'
        new_prop_value = rand_name('alt_two_new_property_value')
        updated_prop_value = rand_name('updated_new_property_value')

        resp = self.images.client.update_image(self.created_image.id_,
                                               add={new_prop: new_prop_value})
        self.assertEqual(
            resp.status_code, 200,
            Messages.STATUS_CODE_MSG.format(200, resp.status_code))

        resp = self.images.client.update_image(
            self.created_image.id_, replace={new_prop: updated_prop_value})
        self.assertEqual(
            resp.status_code, 200,
            Messages.STATUS_CODE_MSG.format(200, resp.status_code))
        updated_image = resp.entity

        replaced_prop_value = (updated_image.additional_properties.get(
            new_prop, None))

        self.assertEqual(
            replaced_prop_value,
            updated_prop_value,
            msg=('Unexpected updated image property value received. '
                 'Expected: {0} '
                 'Received: {1}').format(updated_prop_value,
                                         replaced_prop_value))

        resp = self.images.client.get_image_details(self.created_image.id_)
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))
        get_image = resp.entity

        get_replaced_prop_value = (get_image.additional_properties.get(
            new_prop, None))

        self.assertEqual(
            get_replaced_prop_value,
            updated_prop_value,
            msg=('Unexpected updated image property value received.'
                 'Expected: {0} '
                 'Received: {1}').format(new_prop_value,
                                         get_replaced_prop_value))

    def test_update_image_property_quota_limit(self):
        """
        @summary: Validate image properties quota limit

        1) While the number of image properties is not equal to the image
        properties quota, update image adding a new image property
        2) Verify that the response code is 200
        3) When the number of image properties is equal to the image properties
        quota, update image adding another new image property
        4) Verify that the response code is 413
        5) Get image details
        6) Verify that the response is ok
        7) Verify that the number of image properties matches the image
        properties quota
        """

        number_of_image_properties = 0
        additional_props = [
            'auto_disk_config', 'image_type', 'os_type', 'user_id'
        ]
        quota_limit = self.images.config.image_properties_limit

        # Decrease quota limit for every property that image already contains
        for prop in additional_props:
            if hasattr(self.quota_image, prop):
                quota_limit -= 1

        while number_of_image_properties != quota_limit:
            new_prop = rand_name('prop')
            new_prop_value = rand_name('prop_value')

            resp = self.images.client.update_image(
                self.quota_image.id_, add={new_prop: new_prop_value})
            self.assertEqual(
                resp.status_code, 200,
                Messages.STATUS_CODE_MSG.format(200, resp.status_code))

            resp = self.images.client.get_image_details(self.quota_image.id_)
            self.assertTrue(resp.ok,
                            Messages.OK_RESP_MSG.format(resp.status_code))
            get_image = resp.entity

            number_of_image_properties = len(
                getattr(get_image, 'additional_properties'))

        new_prop = rand_name('prop')
        new_prop_value = rand_name('prop_value')

        resp = self.images.client.update_image(self.quota_image.id_,
                                               add={new_prop: new_prop_value})
        self.assertEqual(
            resp.status_code, 413,
            Messages.STATUS_CODE_MSG.format(413, resp.status_code))

        resp = self.images.client.get_image_details(self.quota_image.id_)
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))
        get_image = resp.entity

        self.assertEqual(len(getattr(get_image, 'additional_properties')),
                         quota_limit,
                         msg='Unexpected number of image properties returned.'
                         'Expected: {0} '
                         'Received: {1}'.format(
                             quota_limit,
                             len(getattr(get_image, 'additional_properties'))))

    def test_update_image_using_blank_image_id(self):
        """
        @summary: Update image using a blank image id

        1) Update image using blank image id
        2) Verify that the response code is 404
        """

        resp = self.images.client.update_image(
            image_id='', add={'new_prop': rand_name('new_prop_value')})
        self.assertEqual(
            resp.status_code, 404,
            Messages.STATUS_CODE_MSG.format(404, resp.status_code))

    def test_update_image_using_invalid_image_id(self):
        """
        @summary: Update image using an invalid image id

        1) Update image using invalid image id
        2) Verify that the response code is 404
        """

        resp = self.images.client.update_image(
            image_id='invalid', add={'new_prop': rand_name('new_prop_value')})
        self.assertEqual(
            resp.status_code, 404,
            Messages.STATUS_CODE_MSG.format(404, resp.status_code))

    def _check_prop_key(self, prop_key):
        """
        @summary: Check if prop_key needs an underscore added

        @param prop_key: Image property to check
        @type prop_key: String

        @return: Prop_key
        @rtype: String
        """

        keys_need_underscore = ['file', 'id', 'self']

        if prop_key in keys_need_underscore:
            prop_key = '{0}_'.format(prop_key)

        if prop_key == 'location':
            prop_key = 'file_'

        return prop_key
Exemple #10
0
class ListImages(ImagesIntergrationFixture):

    @classmethod
    def setUpClass(cls):
        super(ListImages, cls).setUpClass()

        cls.alt_one_member = cls.images_alt_one.auth.tenant_id

        # Count set to number of images required for this module
        created_images = cls.images.behaviors.create_images_via_task(
            image_properties={'name': rand_name('list_images')}, count=2)

        cls.created_image = created_images.pop()
        cls.images.client.create_image_member(
            cls.created_image.id_, cls.alt_one_member)
        resp = cls.images.client.get_image_member(
            cls.created_image.id_, cls.alt_one_member)
        cls.created_image_member = resp.entity

        cls.shared_image = created_images.pop()
        cls.images.client.create_image_member(
            cls.shared_image.id_, cls.alt_one_member)

    @classmethod
    def tearDownClass(cls):
        cls.images.behaviors.resources.release()
        super(ListImages, cls).tearDownClass()

    def test_compare_list_images_between_glance_and_nova(self):
        """
        @summary: Compare the list of images returned from the glance api and
        the nova api

        1) List images with a limit set to 100 and visiblity set to public
        through the glance api
        2) Verify that the response is ok
        3) Verify that the images returned is not none
        4) List images with a limit set to 100 and image_type set to base
        through the nova api
        5) Verify that the response is ok
        6) Verify that the images returned is not none
        7) Verify that the length of the list of images is the same through the
        glance api and the nova api
        8) Verify that each image name in the list of images is the same
        through the glance api and the nova api
        """

        resp = self.images.client.list_images(
            params={'limit': 100, 'visibility': ImageVisibility.PUBLIC})
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))

        glance_image_names = [image.name for image in resp.entity]
        self.assertIsNotNone(
            glance_image_names, msg=('Unexpected images received.'
                                     'Expected: At least one image received '
                                     'Received: No images received'))

        resp = self.compute.images.client.list_images_with_detail(
            limit=100, image_type='base')
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))

        nova_image_names = [image.name for image in resp.entity]
        self.assertIsNotNone(
            nova_image_names, msg=('Unexpected images received.'
                                   'Expected: At least one image received '
                                   'Received: No images received'))

        self.assertEqual(
            len(glance_image_names), len(nova_image_names),
            msg=('Unexpected images received. Expected: Number of images to '
                 'match Received: Number of images do not match'))

        for image_name in glance_image_names:
            self.assertIn(
                image_name, nova_image_names,
                msg=('Unexpected images received. Expected: {0} in list of '
                     'images '
                     'Received: {1}').format(image_name, nova_image_names))

    def test_list_all_images(self):
        """
        @summary: List all images with no additional query parameters,
        paginating through the results as needed, and verify that the created
        image is listed

        1) List all images not passing in any additional query parameter,
        paginating through the results as needed
        2) Verify that the list is not empty
        3) Verify that the created image is in the returned list of images
        4) Verify that each image returned has a status of active
        """

        listed_images = self.images.behaviors.list_all_images()
        self.assertNotEqual(
            len(listed_images), 0,
            msg=('Unexpected number of images received. Expected: Not {0} '
                 'Received: {1}').format(0, len(listed_images)))

        self.assertIn(
            self.created_image, listed_images,
            msg=('Unexpected images received. Expected: {0} in list of '
                 'images '
                 'Received: {1}').format(self.created_image, listed_images))

        # TODO: Add additional assertions to verify all images are as expected
        for image in listed_images:
            self.assertEqual(
                image.status, ImageStatus.ACTIVE,
                msg=('Unexpected status for image {0} received. Expected: {1} '
                     'Received: {2}').format(image.id_,
                                             ImageStatus.ACTIVE, image.status))

    def test_image_visibility_of_shared_images(self):
        """
        @summary: Image visibility of shared images

        1) Using alt_one_member, list all images
        2) Verify that shared_image is not present
        3) Using alt_one_member, list all images passing visibility as shared
        and member status as all
        4) Verify that shared_image is now present
        5) Using alt_one_member, update image member status to rejected
        6) Verify that the response is ok
        7) Using alt_one_member, list all images passing visibility as shared
        and member status as all
        8) Verify that shared_image is still present
        """

        listed_images = self.images_alt_one.behaviors.list_all_images()
        self.assertNotIn(
            self.shared_image, listed_images,
            msg=('Unexpected image received. Expected: {0} to not be in list '
                 'of images Received: {1}').format(self.shared_image,
                                                   listed_images))

        listed_images = self.images_alt_one.behaviors.list_all_images(
            visibility=ImageVisibility.SHARED,
            member_status=ImageMemberStatus.ALL)
        self.assertIn(
            self.shared_image, listed_images,
            msg=('Expected image not received. Expected: {0} to be in list of '
                 'images Received: {1}').format(self.shared_image,
                                                listed_images))

        resp = self.images_alt_one.client.update_image_member(
            self.shared_image.id_, self.alt_one_member,
            ImageMemberStatus.REJECTED)
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))

        listed_images = self.images_alt_one.behaviors.list_all_images(
            visibility=ImageVisibility.SHARED,
            member_status=ImageMemberStatus.ALL)
        self.assertIn(
            self.shared_image, listed_images,
            msg=('Expected image not received. Expected: {0} to be in list of '
                 'images Received: {1}').format(self.shared_image,
                                                listed_images))

    @data_driven_test(
        ImagesDatasetListGenerator.ListImagesFilters())
    def ddtest_filter_images_list(self, params):
        """
        @summary: List all images that match a filter, passing in a specific
        query parameter

        @param param: Parameter being passed to the list images request
        @type param: Dictionary

        1) List all images passing in a query parameter
        2) Verify that the list of images returned is not empty
        3) Verify that each image returned contains a value for the given
        filter that is acceptable
        """

        # This is a temporary workaround for skips in ddtests
        if 'id_' in params or 'created_at' in params:
            sys.stderr.write('skipped \'Redmine bug #11168\' ... ')
            return

        api_args = {}

        for param in params:
            api_args.update({param: getattr(self.created_image, param)})

        listed_images = self.images.behaviors.list_all_images(**api_args)
        self.assertNotEqual(
            len(listed_images), 0,
            msg=('Unexpected number of images received. Expected: Not 0 '
                 'Received: {0}').format(len(listed_images)))

        for image in listed_images:
            for param in params:
                received = getattr(image, param)
                expected = getattr(self.created_image, param)
                self.assertEqual(
                    received, expected,
                    msg=('Unexpected property value for image {0} received.'
                         'Expected: {1} '
                         'Received: {2}').format(image.id_, expected,
                                                 received))

    def test_filter_images_list_passing_additional_property(self):
        """
        @summary: List all images that match a filter, passing in an additional
        property as the query parameter

        1) List all images passing in an additional property as the query
        parameter
        2) Verify that the list of images returned is not empty
        3) Verify that each image returned contains a value for the additional
        property that matches the additional property that is being used as the
        filter
        """

        prop = self.images.config.additional_property

        api_args = ({prop: self.created_image.additional_properties.get(prop)})

        listed_images = self.images.behaviors.list_all_images(**api_args)
        self.assertNotEqual(
            len(listed_images), 0,
            msg=('Unexpected number of images received. Expected: Not 0 '
                 'Received: {0}').format(len(listed_images)))

        for image in listed_images:
            received = image.additional_properties.get(prop)
            expected = (self.created_image.additional_properties.get(prop))
            self.assertEqual(
                received, expected,
                msg=('Unexpected property for image {0} received.'
                     'Expected: {1} '
                     'Received: {2}').format(image.id_, expected, received))

    @unittest.skip('Redmine bug #11270')
    def test_filter_images_list_passing_member_status(self):
        """
        @summary: List all images that match a filter, passing in member_status
        as the query parameter

        1) List all images passing in member_status as the query parameter
        2) Verify that the list of images returned is not empty
        3) Verify that each image returned list image members
        4) Verify that each image returned contains a value for member_status
        that matches the member_status that is being used as the filter
        """

        api_args = ({'member_status':
                     getattr(self.created_image_member, 'status'),
                     'visibility': getattr(self.created_image, 'visibility')})

        listed_images = self.images.behaviors.list_all_images(**api_args)
        self.assertNotEqual(
            len(listed_images), 0,
            msg=('Unexpected number of images received. Expected: Not {0} '
                 'Received: {1}').format(0, len(listed_images)))

        for image in listed_images:
            image_member_statuses = []
            resp = self.images.client.list_image_members(image.id_)
            self.assertTrue(resp.ok,
                            Messages.OK_RESP_MSG.format(resp.status_code))
            list_image_members = resp.entity
            for member in list_image_members:
                image_member_statuses.append(member.status)
                received_image_member_status = (
                    getattr(self.created_image_member, 'status'))
                self.assertIn(getattr(self.created_image_member, 'status'),
                              image_member_statuses,
                              msg=('Unexpected image member status for image'
                                   '{0} received. Expected: {1} in list of'
                                   'image member statuses Received: '
                                   '{2}').format(image.id_,
                                                 received_image_member_status,
                                                 image_member_statuses))

    def test_filter_images_list_passing_size_max(self):
        """
        @summary: List all images that match a filter, passing in size_max as
        the query parameter

        1) List all images passing in size_max as the query parameter
        2) Verify that the list of images returned is not empty
        3) Verify that each image returned contains a value for size that is
        less than or equal to the size_max that is being used as the filter
        """

        api_args = {'size_max': self.images.config.size_max}

        listed_images = self.images.behaviors.list_all_images(**api_args)
        self.assertNotEqual(
            len(listed_images), 0,
            msg=('Unexpected number of images received. Expected: Not {0} '
                 'Received: {1}').format(0, len(listed_images)))

        for image in listed_images:
            received = getattr(image, 'size')
            expected = self.images.config.size_max
            self.assertLessEqual(
                received, expected,
                msg=('Unexpected size_max for image {0} received.'
                     'Expected: <= {1} '
                     'Received: {2}').format(image.id_, expected, received))

    def test_filter_images_list_passing_size_max_and_size_min(self):
        """
        @summary: List all images that match a filter, passing in both size_max
        and size_min as the query parameters

        1) List all images passing in size_max and size_min as the query
        parameters
        2) Verify that the list of images returned is not empty
        3) Verify that each image returned contains a value for size that is
        less than or equal to the size_max that is being used as the filter and
        greater than or equal to the size_min that is being used as the filter
        """

        api_args = {'size_max': self.images.config.size_max,
                    'size_min': self.images.config.size_min}

        listed_images = self.images.behaviors.list_all_images(**api_args)
        self.assertNotEqual(
            len(listed_images), 0,
            msg=('Unexpected number of images received. Expected: Not {0} '
                 'Received: {1}').format(0, len(listed_images)))

        for image in listed_images:
            received = getattr(image, 'size')
            expected = self.images.config.size_max
            self.assertLessEqual(
                received, expected,
                msg=('Unexpected size_max for image {0} received.'
                     'Expected: <= {1} '
                     'Received: {2}').format(image.id_, expected, received))
            expected = getattr(self.images.config, 'size_min')
            self.assertGreaterEqual(
                received, expected,
                msg=('Unexpected size_min for image {0} received.'
                     'Expected: >= {1} '
                     'Received: {2}').format(image.id_, expected, received))

    def test_filter_images_list_passing_size_min(self):
        """
        @summary: List all images that match a filter, passing in size_min as
        the query parameter

        1) List all images passing in size_min as the query parameter
        2) Verify that the list of images returned is not empty
        3) Verify that each image returned contains a value for size that is
        greater than or equal to the size_min that is being used as the filter
        """

        api_args = {'size_min': self.images.config.size_min}

        listed_images = self.images.behaviors.list_all_images(**api_args)
        self.assertNotEqual(
            len(listed_images), 0,
            msg=('Unexpected number of images received. Expected: Not {0} '
                 'Received: {1}').format(0, len(listed_images)))

        for image in listed_images:
            received = getattr(image, 'size')
            expected = self.images.config.size_min
            self.assertGreaterEqual(
                received, expected,
                msg=('Unexpected size_min for image {0} received.'
                     'Expected: >= {1} '
                     'Received: {2}').format(image.id_, expected, received))

    def test_filter_images_list_passing_tag(self):
        """
        @summary: List all images that match a filter, passing in tag as
        the query parameter

        1) List all images passing in tag as the query parameter
        2) Verify that the list of images returned is not empty
        3) Verify that each image returned contains a value for tags that
        matches the tag that is being used as the filter
        """

        api_args = {'tag': getattr(self.created_image, 'tags')}

        listed_images = self.images.behaviors.list_all_images(**api_args)
        self.assertNotEqual(
            len(listed_images), 0,
            msg=('Unexpected number of images received. Expected: Not {0} '
                 'Received: {1}').format(0, len(listed_images)))

        for image in listed_images:
            received = getattr(image, 'tags')
            expected = getattr(self.created_image, 'tags')
            self.assertEqual(
                received, expected,
                msg=('Unexpected tags for image {0} received. Expected: {1} '
                     'Received: {2}').format(image.id_, expected, received))

    def test_list_images_using_limit(self):
        """
        @summary: List images using limit

        1) List images passing in 1 as the limit
        2) Verify that the response code is ok
        4) Verify that the number of images returned is 1
        """

        resp = self.images.client.list_images(params={'limit': 1})
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))

        listed_images = resp.entity
        self.assertEqual(
            len(listed_images), 1,
            msg=('Unexpected number of images received. Expected: {0} '
                 'Received: {1}').format(1, len(listed_images)))

    def test_list_images_using_limit_zero(self):
        """
        @summary: List images using limit of zero

        1) List images passing in 0 as the limit
        2) Verify that the response code is ok
        3) Verify that the number of images returned is 0
        """

        resp = self.images.client.list_images(params={'limit': 0})
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))

        listed_images = resp.entity
        self.assertEqual(
            len(listed_images), 0,
            msg=('Unexpected number of images received. Expected: {0} '
                 'Received: {1}').format(0, len(listed_images)))

    def test_list_images_using_marker_pagination(self):
        """
        @summary: List images using marker pagination

        1) List images passing in 1 as the limit, the created image's name as
        the name, and the user as the owner
        2) Verify that the response code is ok
        3) Verify that the returned list only contains 1 image
        4) List images again passing in the listed image id as the marker as
        well as 1 as the limit, the created image's name as the name, and the
        user as the owner
        5) Verify that the response code is ok
        6) Verify that the returned list only contains 1 image
        7) Verify that the newly returned image is not the same as the
        previously returned image
        """

        resp = self.images.client.list_images(
            params={'limit': 1, 'name': self.created_image.name,
                    'owner': self.images.auth.tenant_id})
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))

        listed_image = resp.entity
        self.assertEqual(
            len(listed_image), 1,
            msg=('Unexpected number of images received. Expected: {0} '
                 'Received: {1}').format(1, len(listed_image)))

        marker = listed_image[0].id_

        resp = self.images.client.list_images(
            params={'limit': 1, 'marker': marker,
                    'name': self.created_image.name,
                    'owner': self.images.auth.tenant_id})
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))

        next_listed_image = resp.entity
        self.assertEqual(
            len(next_listed_image), 1,
            msg=('Unexpected number of images received. Expected: {0} '
                 'Received: {1}').format(1, len(next_listed_image)))

        self.assertNotEqual(
            listed_image[0], next_listed_image[0],
            msg=('Unexpected images received. Expected: Images to not match '
                 'Received: Images match'))

    @data_driven_test(
        ImagesDatasetListGenerator.ListImagesSort())
    def ddtest_sort_images_list(self, params):
        """
        @summary: List all images, sorting the list by passing in a query
        parameter as the sort_key and a direction as the sort_dir

        @param params: Parameter being passed to the list images request
        @type params: Dictionary

        1) List all images passing in a query parameter as the sort_key and a
        direction as the sort_dir
        2) Verify that the list of images returned is not empty
        3) Verify that each image returned is in order based on the sort_key
        and sort_dir
        """

        sort_dir = None
        sort_key = None
        not_str_list = ['created_at', 'min_disk', 'min_ram', 'owner', 'size',
                        'updated_at', 'user_id']

        # Only two key-value pairs are passed in, sort_dir and sort_key
        for key in params.keys():
            if key == 'sort_dir':
                sort_dir = params[key]
            elif key == 'sort_key':
                sort_key = params[key]

        # This is a temporary workaround for skips in ddtests
        additional_property = self.images.config.additional_property
        expected_failure_properties = [
            additional_property, 'auto_disk_config', 'id', 'image_type',
            'os_type', 'protected', 'tags', 'user_id', 'visibility']
        if sort_key in expected_failure_properties:
            sys.stderr.write('skipped \'Redmine bugs #11260 and #11262\' ... ')
            return

        listed_images = self.images.behaviors.list_all_images(**params)
        self.assertNotEqual(
            len(listed_images), 0,
            msg=('Unexpected number of images received. Expected: Not {0} '
                 'Received: {1}').format(0, len(listed_images)))

        for current, next_ in zip(listed_images[0::2], listed_images[1::2]):
            current_item = getattr(current, sort_key)
            next_item = getattr(next_, sort_key)
            if sort_key not in not_str_list:
                if current_item is not None:
                    current_item = current_item.lower()
                if next_item is not None:
                    next_item = next_item.lower()
            if sort_dir.lower() == 'asc':
                self.assertLessEqual(
                    current_item, next_item,
                    msg=('Unexpected items for images {0} and {1} received.'
                         'Expected: Less than or equal to {2} '
                         'Received: {3}').format(next_.id_, current.id_,
                                                 next_item, current_item))
            else:
                self.assertGreaterEqual(
                    current_item, next_item,
                    msg=('Unexpected items for images {0} and {1} received.'
                         'Expected: Greater than or equal to {0} '
                         'Received: {1}').format(next_.id_, current.id_,
                                                 next_item, current_item))

    @unittest.skip('Redmine bug #11261')
    def test_sort_images_list_passing_id_asc(self):
        """
        @summary: List all images, sorting the list by passing in id as the
        sort_key and asc as the sort_dir

        1) List all images passing in id as the sort_key and asc as the
        sort_dir
        2) Verify that the list of images returned is not empty
        3) Verify that each image returned contains a value for id that is less
        than or equal to the value for id of the next image
        """

        sort_key_var = 'id_'

        api_args = {'sort_key': 'id', 'sort_dir': SortDirection.ASCENDING}

        listed_images = self.images.behaviors.list_all_images(**api_args)
        self.assertNotEqual(
            len(listed_images), 0,
            msg=('Unexpected number of images received. Expected: Not {0} '
                 'Received: {1}').format(0, len(listed_images)))

        for current, next_ in zip(listed_images[0::2], listed_images[1::2]):
            current_item = getattr(current, sort_key_var).replace('-', '')
            next_item = getattr(next_, sort_key_var).replace('-', '')

            self.assertLessEqual(
                current_item, next_item,
                msg=('Unexpected item received. Expected: Less than or equal '
                     'to {0} Received: {1}').format(next_item, current_item))

    @unittest.skip('Redmine bug #11261')
    def test_sort_images_list_passing_id_desc(self):
        """
        @summary: List all images, sorting the list by passing in id as the
        sort_key and desc as the sort_dir

        1) List all images passing in id as the sort_key and desc as the
        sort_dir
        2) Verify that the list of images returned is not empty
        3) Verify that each image returned contains a value for id that is
        greater than or equal to the value for id of the next image
        """

        sort_key_var = 'id_'

        api_args = {'sort_key': 'id', 'sort_dir': SortDirection.DESCENDING}

        listed_images = self.images.behaviors.list_all_images(**api_args)
        self.assertNotEqual(
            len(listed_images), 0,
            msg=('Unexpected number of images received. Expected: Not {0} '
                 'Received: {1}').format(0, len(listed_images)))

        for current, next_ in zip(listed_images[0::2], listed_images[1::2]):
            current_item = getattr(current, sort_key_var).replace('-', '')
            next_item = getattr(next_, sort_key_var).replace('-', '')

            self.assertGreaterEqual(
                current_item, next_item,
                msg=('Unexpected item received. Expected: Greater than or '
                     'equal to {0} Received: {1}').format(next_item,
                                                          current_item))
Exemple #11
0
class DeactivateImage(ImagesIntegrationFixture):
    @classmethod
    def setUpClass(cls):
        super(DeactivateImage, cls).setUpClass()

        # Count set to number of images required for this module
        created_images = cls.images.behaviors.create_images_via_task(
            image_properties={'name': rand_name('deactivate_image')}, count=3)

        cls.deleted_image = created_images.pop()
        cls.images.client.delete_image(cls.deleted_image.id_)

        cls.protected_image = created_images.pop()
        cls.images.client.update_image(cls.protected_image.id_,
                                       replace={'protected': True})

        cls.created_image = created_images.pop()

        created_server = cls.compute.servers.behaviors.create_active_server(
            image_ref=cls.images.config.primary_image).entity
        cls.resources.add(created_server.id,
                          cls.compute.servers.client.delete_server)
        cls.created_snapshot = (
            cls.compute.images.behaviors.create_active_image(
                created_server.id).entity)
        cls.resources.add(cls.created_snapshot.id,
                          cls.images.client.delete_image)

    @classmethod
    def tearDownClass(cls):
        cls.images.client.update_image(cls.protected_image.id_,
                                       replace={'protected': False})
        cls.images.behaviors.resources.release()
        super(DeactivateImage, cls).tearDownClass()

    @data_driven_test(ImagesDatasetListGenerator.DeactivateImageTypes())
    def ddtest_deactivate_image(self, image):
        """
        @summary: Deactivate an image

        1) Deactivate an image via wrapper test method
        2) Verify that the image's status is deactivated
        """

        get_image = self._deactivate_image(image.id_)

        self.assertEqual(get_image.status,
                         ImageStatus.DEACTIVATED,
                         msg=('Unexpected status for image {0}. '
                              'Expected: {1} Received: '
                              '{2}').format(image.id_, ImageStatus.DEACTIVATED,
                                            get_image.status))

    def test_deactivate_protected_image(self):
        """
        @summary: Deactivate a protected image

        1) Deactivate a protected image via wrapper test method
        2) Verify that the image's status is deactivated
        """

        get_image = self._deactivate_image(self.protected_image.id_)

        self.assertEqual(get_image.status,
                         ImageStatus.DEACTIVATED,
                         msg=('Unexpected status for image {0}. '
                              'Expected: {1} Received: '
                              '{2}').format(self.protected_image.id_,
                                            ImageStatus.DEACTIVATED,
                                            get_image.status))

    def test_deactivate_snapshot_image(self):
        """
        @summary: Deactivate a snapshot image

        1) Deactivate a snapshot image via wrapper test method
        2) Verify that the image's status is deactivated
        """

        get_image = self._deactivate_image(self.created_snapshot.id)

        self.assertEqual(get_image.status,
                         ImageStatus.DEACTIVATED,
                         msg=('Unexpected status for image {0}. '
                              'Expected: {1} Received: '
                              '{2}').format(self.created_snapshot.id,
                                            ImageStatus.DEACTIVATED,
                                            get_image.status))

    def test_deactivate_deleted_image(self):
        """
        @summary: Deactivate a deleted image

        1) Deactivate a deleted image
        2) Verify that the response code is 404
        """

        resp = self.images_admin.client.deactivate_image(
            self.deleted_image.id_)
        self.assertEqual(
            resp.status_code, 404,
            Messages.STATUS_CODE_MSG.format(404, resp.status_code))

    def test_deactivate_image_using_non_admin_forbidden(self):
        """
        @summary: Deactivate an image as non-admin

        1) Deactivate an image as non-admin via wrapper test method
        2) Verify that the image's status is still active
        """

        get_image = self._deactivate_image(self.created_image.id_,
                                           self.images.client, 403)

        self.assertEqual(get_image.status,
                         ImageStatus.ACTIVE,
                         msg=('Unexpected status for image {0}. '
                              'Expected: {1} Received: '
                              '{2}').format(self.created_image.id_,
                                            ImageStatus.ACTIVE,
                                            get_image.status))

    def test_deactivate_image_using_invalid_image_id(self):
        """
        @summary: Deactivate an image using an invalid image id

        1) Deactivate an image using an invalid image id
        2) Verify that the response code is 404
        """

        resp = self.images_admin.client.deactivate_image(image_id='invalid')
        self.assertEqual(
            resp.status_code, 404,
            Messages.STATUS_CODE_MSG.format(404, resp.status_code))

    def _deactivate_image(self,
                          image_id,
                          images_client=None,
                          response_code=None):
        """
        @summary: Deactivate image and return the get image details response

        @param image_id: Image id to deactivate
        @type image_id: Uuid
        @param images_client: Images client to user
        @type images_client: Object
        @param response_code: Response status code
        @type response_code: Integer

        @return: Get image details response
        @rtype: Object

        1) Deactivate an image as specified user
        2) Verify that the response code is as expected
        3) Get image details passing in the image id
        4) Verify that the response is ok
        5) Return the get image details response
        """

        if images_client is None:
            images_client = self.images_admin.client
        if response_code is None:
            response_code = 204

        resp = images_client.deactivate_image(image_id)
        self.assertEqual(
            resp.status_code, response_code,
            Messages.STATUS_CODE_MSG.format(response_code, resp.status_code))

        resp = self.images.client.get_image_details(image_id)
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))

        return resp.entity
Exemple #12
0
class ReactivateImage(ImagesIntegrationFixture):

    @classmethod
    def setUpClass(cls):
        super(ReactivateImage, cls).setUpClass()

        # Count set to number of images required for this module
        created_images = cls.images.behaviors.create_images_via_task(
            image_properties={'name': rand_name('deactivate_image')}, count=3)

        cls.deleted_image = created_images.pop()
        cls.images.client.delete_image(cls.deleted_image.id_)

        cls.protected_image = created_images.pop()
        cls.images_admin.client.deactivate_image(cls.protected_image.id_)
        cls.images.client.update_image(
            cls.protected_image.id_, replace={'protected': True})

        cls.deactivated_image = created_images.pop()
        cls.images_admin.client.deactivate_image(cls.deactivated_image.id_)

        created_server = cls.compute.servers.behaviors.create_active_server(
            image_ref=cls.images.config.primary_image).entity
        cls.resources.add(
            created_server.id, cls.compute.servers.client.delete_server)
        cls.created_snapshot = (
            cls.compute.images.behaviors.create_active_image(
                created_server.id).entity)
        cls.resources.add(
            cls.created_snapshot.id, cls.images.client.delete_image)
        cls.images_admin.client.deactivate_image(cls.created_snapshot.id)

    @classmethod
    def tearDownClass(cls):
        cls.images.client.update_image(
            cls.protected_image.id_, replace={'protected': False})
        cls.images.behaviors.resources.release()
        super(ReactivateImage, cls).tearDownClass()

    @data_driven_test(
        ImagesDatasetListGenerator.ReactivateImageTypes())
    def ddtest_reactivate_image(self, image):
        """
        @summary: Reactivate an image

        1) Reactivate an image
        2) Verify that the response code is 204
        3) Get image details passing in the image id
        4) Verify that the response is ok
        5) Verify that the returned image's status is active
        """

        resp = self.images_admin.client.reactivate_image(image.id_)
        self.assertEqual(
            resp.status_code, 204,
            Messages.STATUS_CODE_MSG.format(204, resp.status_code))

        resp = self.images.client.get_image_details(image.id_)
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))
        get_image = resp.entity

        self.assertEqual(
            get_image.status, ImageStatus.ACTIVE,
            msg=('Unexpected status for image {0}. '
                 'Expected: {1} Received: '
                 '{2}').format(image.id_, ImageStatus.ACTIVE,
                               get_image.status))

    def test_reactivate_protected_image(self):
        """
        @summary: Reactivate a protected image

        1) Reactivate a protected image
        2) Verify that the response code is 204
        3) Get image details passing in the image id
        4) Verify that the response is ok
        5) Verify that the returned image's status is active
        """

        resp = self.images_admin.client.reactivate_image(
            self.protected_image.id_)
        self.assertEqual(
            resp.status_code, 204,
            Messages.STATUS_CODE_MSG.format(204, resp.status_code))

        resp = self.images.client.get_image_details(self.protected_image.id_)
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))
        get_image = resp.entity

        self.assertEqual(
            get_image.status, ImageStatus.ACTIVE,
            msg=('Unexpected status for image {0}. '
                 'Expected: {1} Received: '
                 '{2}').format(self.protected_image.id_,
                               ImageStatus.ACTIVE, get_image.status))

    def test_reactivate_snapshot_image(self):
        """
        @summary: Reactivate a snapshot image

        1) Reactivate a snapshot image
        2) Verify that the response code is 204
        3) Get image details passing in the image id
        4) Verify that the response is ok
        5) Verify that the returned image's status is active
        """

        resp = self.images_admin.client.reactivate_image(
            self.created_snapshot.id)
        self.assertEqual(
            resp.status_code, 204,
            Messages.STATUS_CODE_MSG.format(204, resp.status_code))

        resp = self.images.client.get_image_details(self.created_snapshot.id)
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))
        get_image = resp.entity

        self.assertEqual(
            get_image.status, ImageStatus.ACTIVE,
            msg=('Unexpected status for image {0}. '
                 'Expected: {1} Received: '
                 '{2}').format(self.created_snapshot.id,
                               ImageStatus.ACTIVE, get_image.status))

    def test_reactivate_deleted_image(self):
        """
        @summary: Reactivate a deleted image

        1) Reactivate a deleted image
        2) Verify that the response code is 404
        """

        resp = self.images_admin.client.reactivate_image(
            self.deleted_image.id_)
        self.assertEqual(
            resp.status_code, 404,
            Messages.STATUS_CODE_MSG.format(404, resp.status_code))

    def test_reactivate_image_using_non_admin_forbidden(self):
        """
        @summary: Reactivate an image as non-admin

        1) Reactivate an image as non-admin
        2) Verify that the response code is 403
        3) Get image details passing in the image id
        4) Verify that the response is ok
        5) Verify that the returned image's status is still deactivated
        """

        resp = self.images.client.reactivate_image(
            self.deactivated_image.id_)
        self.assertEqual(
            resp.status_code, 403,
            Messages.STATUS_CODE_MSG.format(403, resp.status_code))

        resp = self.images.client.get_image_details(
            self.deactivated_image.id_)
        self.assertTrue(resp.ok, Messages.OK_RESP_MSG.format(resp.status_code))
        get_image = resp.entity

        self.assertEqual(
            get_image.status, ImageStatus.DEACTIVATED,
            msg=('Unexpected status for image {0}. '
                 'Expected: {1} Received: '
                 '{2}').format(self.deactivated_image.id_,
                               ImageStatus.DEACTIVATED, get_image.status))

    def test_reactivate_image_using_invalid_image_id(self):
        """
        @summary: Reactivate an image using an invalid image id

        1) Reactivate an image using an invalid image id
        2) Verify that the response code is 404
        """

        resp = self.images_admin.client.deactivate_image(image_id='invalid')
        self.assertEqual(
            resp.status_code, 404,
            Messages.STATUS_CODE_MSG.format(404, resp.status_code))