¡@

Home 

OpenStack Study: test_glance.py

OpenStack Index

**** CubicPower OpenStack Study ****

# Copyright 2011 OpenStack Foundation

# All Rights Reserved.

#

# Licensed under the Apache License, Version 2.0 (the "License"); you may

# not use this file except in compliance with the License. You may obtain

# a copy of the License at

#

# http://www.apache.org/licenses/LICENSE-2.0

#

# Unless required by applicable law or agreed to in writing, software

# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

# License for the specific language governing permissions and limitations

# under the License.

import datetime

import glanceclient.exc

import glanceclient.v2.client

from glanceclient.v2.client import Client as glanceclient_v2

from oslo.config import cfg

from cinder import context

from cinder import exception

from cinder.image import glance

from cinder import test

from cinder.tests.glance import stubs as glance_stubs

CONF = cfg.CONF

**** CubicPower OpenStack Study ****

class NullWriter(object):

"""Used to test ImageService.get which takes a writer object."""

**** CubicPower OpenStack Study ****

    def write(self, *arg, **kwargs):

        pass

**** CubicPower OpenStack Study ****

class TestGlanceSerializer(test.TestCase):

**** CubicPower OpenStack Study ****

    def test_serialize(self):

        metadata = {'name': 'image1',

                    'is_public': True,

                    'foo': 'bar',

                    'properties': {

                        'prop1': 'propvalue1',

                        'mappings': [

                            {'virtual': 'aaa',

                             'device': 'bbb'},

                            {'virtual': 'xxx',

                             'device': 'yyy'}],

                        'block_device_mapping': [

                            {'virtual_device': 'fake',

                             'device_name': '/dev/fake'},

                            {'virtual_device': 'ephemeral0',

                             'device_name': '/dev/fake0'}]}}

        converted_expected = {

            'name': 'image1',

            'is_public': True,

            'foo': 'bar',

            'properties': {

                'prop1': 'propvalue1',

                'mappings':

                '[{"device": "bbb", "virtual": "aaa"}, '

                '{"device": "yyy", "virtual": "xxx"}]',

                'block_device_mapping':

                '[{"virtual_device": "fake", "device_name": "/dev/fake"}, '

                '{"virtual_device": "ephemeral0", '

                '"device_name": "/dev/fake0"}]'}}

        converted = glance._convert_to_string(metadata)

        self.assertEqual(converted, converted_expected)

        self.assertEqual(glance._convert_from_string(converted), metadata)

**** CubicPower OpenStack Study ****

class TestGlanceImageService(test.TestCase):

"""Tests the Glance image service.

At a high level, the translations involved are:

1. Glance -> ImageService - This is needed so we can support

multple ImageServices (Glance, Local, etc)

2. ImageService -> API - This is needed so we can support multple

APIs (OpenStack, EC2)

"""

NOW_GLANCE_OLD_FORMAT = "2010-10-11T10:30:22"

NOW_GLANCE_FORMAT = "2010-10-11T10:30:22.000000"

class tzinfo(datetime.tzinfo):

@staticmethod

**** CubicPower OpenStack Study ****

    def setUp(self):

        super(TestGlanceImageService, self).setUp()

        #fakes.stub_out_compute_api_snapshot(self.stubs)

        client = glance_stubs.StubGlanceClient()

        self.service = self._create_image_service(client)

        self.context = context.RequestContext('fake', 'fake', auth_token=True)

        self.stubs.Set(glance.time, 'sleep', lambda s: None)

**** CubicPower OpenStack Study ****

    def _create_image_service(self, client):

        def _fake_create_glance_client(context, netloc, use_ssl, version):

            return client

        self.stubs.Set(glance,

                       '_create_glance_client',

                       _fake_create_glance_client)

        client_wrapper = glance.GlanceClientWrapper('fake', 'fake_host', 9292)

        return glance.GlanceImageService(client=client_wrapper)

    @staticmethod

**** CubicPower OpenStack Study ****

        def _fake_create_glance_client(context, netloc, use_ssl, version):

            return client

        self.stubs.Set(glance,

                       '_create_glance_client',

                       _fake_create_glance_client)

        client_wrapper = glance.GlanceClientWrapper('fake', 'fake_host', 9292)

        return glance.GlanceImageService(client=client_wrapper)

    @staticmethod

**** CubicPower OpenStack Study ****

    def _make_fixture(**kwargs):

        fixture = {'name': None,

                   'properties': {},

                   'status': None,

                   'is_public': None}

        fixture.update(kwargs)

        return fixture

**** CubicPower OpenStack Study ****

    def _make_datetime_fixture(self):

        return self._make_fixture(created_at=self.NOW_GLANCE_FORMAT,

                                  updated_at=self.NOW_GLANCE_FORMAT,

                                  deleted_at=self.NOW_GLANCE_FORMAT)

**** CubicPower OpenStack Study ****

    def test_create_with_instance_id(self):

        """Ensure instance_id is persisted as an image-property."""

        fixture = {'name': 'test image',

                   'is_public': False,

                   'properties': {'instance_id': '42', 'user_id': 'fake'}}

        image_id = self.service.create(self.context, fixture)['id']

        image_meta = self.service.show(self.context, image_id)

        expected = {

            'id': image_id,

            'name': 'test image',

            'is_public': False,

            'size': None,

            'min_disk': None,

            'min_ram': None,

            'disk_format': None,

            'container_format': None,

            'checksum': None,

            'created_at': self.NOW_DATETIME,

            'updated_at': self.NOW_DATETIME,

            'deleted_at': None,

            'deleted': None,

            'status': None,

            'properties': {'instance_id': '42', 'user_id': 'fake'},

            'owner': None,

        }

        self.assertDictMatch(image_meta, expected)

        image_metas = self.service.detail(self.context)

        self.assertDictMatch(image_metas[0], expected)

**** CubicPower OpenStack Study ****

    def test_create_without_instance_id(self):

        """Test Creating images without instance_id.

        Ensure we can create an image without having to specify an

        instance_id. Public images are an example of an image not tied to an

        instance.

        """

        fixture = {'name': 'test image', 'is_public': False}

        image_id = self.service.create(self.context, fixture)['id']

        expected = {

            'id': image_id,

            'name': 'test image',

            'is_public': False,

            'size': None,

            'min_disk': None,

            'min_ram': None,

            'disk_format': None,

            'container_format': None,

            'checksum': None,

            'created_at': self.NOW_DATETIME,

            'updated_at': self.NOW_DATETIME,

            'deleted_at': None,

            'deleted': None,

            'status': None,

            'properties': {},

            'owner': None,

        }

        actual = self.service.show(self.context, image_id)

        self.assertDictMatch(actual, expected)

**** CubicPower OpenStack Study ****

    def test_create(self):

        fixture = self._make_fixture(name='test image')

        num_images = len(self.service.detail(self.context))

        image_id = self.service.create(self.context, fixture)['id']

        self.assertIsNotNone(image_id)

        self.assertEqual(num_images + 1,

                         len(self.service.detail(self.context)))

**** CubicPower OpenStack Study ****

    def test_create_and_show_non_existing_image(self):

        fixture = self._make_fixture(name='test image')

        image_id = self.service.create(self.context, fixture)['id']

        self.assertIsNotNone(image_id)

        self.assertRaises(exception.ImageNotFound,

                          self.service.show,

                          self.context,

                          'bad image id')

**** CubicPower OpenStack Study ****

    def test_detail_private_image(self):

        fixture = self._make_fixture(name='test image')

        fixture['is_public'] = False

        properties = {'owner_id': 'proj1'}

        fixture['properties'] = properties

        self.service.create(self.context, fixture)['id']

        proj = self.context.project_id

        self.context.project_id = 'proj1'

        image_metas = self.service.detail(self.context)

        self.context.project_id = proj

        self.assertEqual(1, len(image_metas))

        self.assertEqual(image_metas[0]['name'], 'test image')

        self.assertEqual(image_metas[0]['is_public'], False)

**** CubicPower OpenStack Study ****

    def test_detail_marker(self):

        fixtures = []

        ids = []

        for i in range(10):

            fixture = self._make_fixture(name='TestImage %d' % (i))

            fixtures.append(fixture)

            ids.append(self.service.create(self.context, fixture)['id'])

        image_metas = self.service.detail(self.context, marker=ids[1])

        self.assertEqual(len(image_metas), 8)

        i = 2

        for meta in image_metas:

            expected = {

                'id': ids[i],

                'status': None,

                'is_public': None,

                'name': 'TestImage %d' % (i),

                'properties': {},

                'size': None,

                'min_disk': None,

                'min_ram': None,

                'disk_format': None,

                'container_format': None,

                'checksum': None,

                'created_at': self.NOW_DATETIME,

                'updated_at': self.NOW_DATETIME,

                'deleted_at': None,

                'deleted': None,

                'owner': None,

            }

            self.assertDictMatch(meta, expected)

            i = i + 1

**** CubicPower OpenStack Study ****

    def test_detail_limit(self):

        fixtures = []

        ids = []

        for i in range(10):

            fixture = self._make_fixture(name='TestImage %d' % (i))

            fixtures.append(fixture)

            ids.append(self.service.create(self.context, fixture)['id'])

        image_metas = self.service.detail(self.context, limit=5)

        self.assertEqual(len(image_metas), 5)

**** CubicPower OpenStack Study ****

    def test_detail_default_limit(self):

        fixtures = []

        ids = []

        for i in range(10):

            fixture = self._make_fixture(name='TestImage %d' % (i))

            fixtures.append(fixture)

            ids.append(self.service.create(self.context, fixture)['id'])

        image_metas = self.service.detail(self.context)

        for i, meta in enumerate(image_metas):

            self.assertEqual(meta['name'], 'TestImage %d' % (i))

**** CubicPower OpenStack Study ****

    def test_detail_marker_and_limit(self):

        fixtures = []

        ids = []

        for i in range(10):

            fixture = self._make_fixture(name='TestImage %d' % (i))

            fixtures.append(fixture)

            ids.append(self.service.create(self.context, fixture)['id'])

        image_metas = self.service.detail(self.context, marker=ids[3], limit=5)

        self.assertEqual(len(image_metas), 5)

        i = 4

        for meta in image_metas:

            expected = {

                'id': ids[i],

                'status': None,

                'is_public': None,

                'name': 'TestImage %d' % (i),

                'properties': {},

                'size': None,

                'min_disk': None,

                'min_ram': None,

                'disk_format': None,

                'container_format': None,

                'checksum': None,

                'created_at': self.NOW_DATETIME,

                'updated_at': self.NOW_DATETIME,

                'deleted_at': None,

                'deleted': None,

                'owner': None,

            }

            self.assertDictMatch(meta, expected)

            i = i + 1

**** CubicPower OpenStack Study ****

    def test_detail_invalid_marker(self):

        fixtures = []

        ids = []

        for i in range(10):

            fixture = self._make_fixture(name='TestImage %d' % (i))

            fixtures.append(fixture)

            ids.append(self.service.create(self.context, fixture)['id'])

        self.assertRaises(exception.Invalid, self.service.detail,

                          self.context, marker='invalidmarker')

**** CubicPower OpenStack Study ****

    def test_update(self):

        fixture = self._make_fixture(name='test image')

        image = self.service.create(self.context, fixture)

        image_id = image['id']

        fixture['name'] = 'new image name'

        self.service.update(self.context, image_id, fixture)

        new_image_data = self.service.show(self.context, image_id)

        self.assertEqual('new image name', new_image_data['name'])

**** CubicPower OpenStack Study ****

    def test_delete(self):

        fixture1 = self._make_fixture(name='test image 1')

        fixture2 = self._make_fixture(name='test image 2')

        fixtures = [fixture1, fixture2]

        num_images = len(self.service.detail(self.context))

        self.assertEqual(0, num_images)

        ids = []

        for fixture in fixtures:

            new_id = self.service.create(self.context, fixture)['id']

            ids.append(new_id)

        num_images = len(self.service.detail(self.context))

        self.assertEqual(2, num_images)

        self.service.delete(self.context, ids[0])

        num_images = len(self.service.detail(self.context))

        self.assertEqual(1, num_images)

**** CubicPower OpenStack Study ****

    def test_show_passes_through_to_client(self):

        fixture = self._make_fixture(name='image1', is_public=True)

        image_id = self.service.create(self.context, fixture)['id']

        image_meta = self.service.show(self.context, image_id)

        expected = {

            'id': image_id,

            'name': 'image1',

            'is_public': True,

            'size': None,

            'min_disk': None,

            'min_ram': None,

            'disk_format': None,

            'container_format': None,

            'checksum': None,

            'created_at': self.NOW_DATETIME,

            'updated_at': self.NOW_DATETIME,

            'deleted_at': None,

            'deleted': None,

            'status': None,

            'properties': {},

            'owner': None,

        }

        self.assertEqual(image_meta, expected)

**** CubicPower OpenStack Study ****

    def test_show_raises_when_no_authtoken_in_the_context(self):

        fixture = self._make_fixture(name='image1',

                                     is_public=False,

                                     properties={'one': 'two'})

        image_id = self.service.create(self.context, fixture)['id']

        self.context.auth_token = False

        self.assertRaises(exception.ImageNotFound,

                          self.service.show,

                          self.context,

                          image_id)

**** CubicPower OpenStack Study ****

    def test_detail_passes_through_to_client(self):

        fixture = self._make_fixture(name='image10', is_public=True)

        image_id = self.service.create(self.context, fixture)['id']

        image_metas = self.service.detail(self.context)

        expected = [

            {

                'id': image_id,

                'name': 'image10',

                'is_public': True,

                'size': None,

                'min_disk': None,

                'min_ram': None,

                'disk_format': None,

                'container_format': None,

                'checksum': None,

                'created_at': self.NOW_DATETIME,

                'updated_at': self.NOW_DATETIME,

                'deleted_at': None,

                'deleted': None,

                'status': None,

                'properties': {},

                'owner': None,

            },

        ]

        self.assertEqual(image_metas, expected)

**** CubicPower OpenStack Study ****

    def test_show_makes_datetimes(self):

        fixture = self._make_datetime_fixture()

        image_id = self.service.create(self.context, fixture)['id']

        image_meta = self.service.show(self.context, image_id)

        self.assertEqual(image_meta['created_at'], self.NOW_DATETIME)

        self.assertEqual(image_meta['updated_at'], self.NOW_DATETIME)

**** CubicPower OpenStack Study ****

    def test_detail_makes_datetimes(self):

        fixture = self._make_datetime_fixture()

        self.service.create(self.context, fixture)

        image_meta = self.service.detail(self.context)[0]

        self.assertEqual(image_meta['created_at'], self.NOW_DATETIME)

        self.assertEqual(image_meta['updated_at'], self.NOW_DATETIME)

**** CubicPower OpenStack Study ****

    def test_download_with_retries(self):

        tries = [0]

        class MyGlanceStubClient(glance_stubs.StubGlanceClient):

            """A client that fails the first time, then succeeds."""

            def get(self, image_id):

                if tries[0] == 0:

                    tries[0] = 1

                    raise glanceclient.exc.ServiceUnavailable('')

                else:

                    return {}

        client = MyGlanceStubClient()

        service = self._create_image_service(client)

        image_id = 1  # doesn't matter

        writer = NullWriter()

        # When retries are disabled, we should get an exception

        self.flags(glance_num_retries=0)

        self.assertRaises(exception.GlanceConnectionFailed,

                          service.download,

                          self.context,

                          image_id,

                          writer)

        # Now lets enable retries. No exception should happen now.

        tries = [0]

        self.flags(glance_num_retries=1)

        service.download(self.context, image_id, writer)

**** CubicPower OpenStack Study ****

    def test_client_forbidden_converts_to_imagenotauthed(self):

        class MyGlanceStubClient(glance_stubs.StubGlanceClient):

            """A client that raises a Forbidden exception."""

            def get(self, image_id):

                raise glanceclient.exc.Forbidden(image_id)

        client = MyGlanceStubClient()

        service = self._create_image_service(client)

        image_id = 1  # doesn't matter

        writer = NullWriter()

        self.assertRaises(exception.ImageNotAuthorized, service.download,

                          self.context, image_id, writer)

**** CubicPower OpenStack Study ****

    def test_client_httpforbidden_converts_to_imagenotauthed(self):

        class MyGlanceStubClient(glance_stubs.StubGlanceClient):

            """A client that raises a HTTPForbidden exception."""

            def get(self, image_id):

                raise glanceclient.exc.HTTPForbidden(image_id)

        client = MyGlanceStubClient()

        service = self._create_image_service(client)

        image_id = 1  # doesn't matter

        writer = NullWriter()

        self.assertRaises(exception.ImageNotAuthorized, service.download,

                          self.context, image_id, writer)

**** CubicPower OpenStack Study ****

    def test_client_notfound_converts_to_imagenotfound(self):

        class MyGlanceStubClient(glance_stubs.StubGlanceClient):

            """A client that raises a NotFound exception."""

            def get(self, image_id):

                raise glanceclient.exc.NotFound(image_id)

        client = MyGlanceStubClient()

        service = self._create_image_service(client)

        image_id = 1  # doesn't matter

        writer = NullWriter()

        self.assertRaises(exception.ImageNotFound, service.download,

                          self.context, image_id, writer)

**** CubicPower OpenStack Study ****

    def test_client_httpnotfound_converts_to_imagenotfound(self):

        class MyGlanceStubClient(glance_stubs.StubGlanceClient):

            """A client that raises a HTTPNotFound exception."""

            def get(self, image_id):

                raise glanceclient.exc.HTTPNotFound(image_id)

        client = MyGlanceStubClient()

        service = self._create_image_service(client)

        image_id = 1  # doesn't matter

        writer = NullWriter()

        self.assertRaises(exception.ImageNotFound, service.download,

                          self.context, image_id, writer)

**** CubicPower OpenStack Study ****

    def test_glance_client_image_id(self):

        fixture = self._make_fixture(name='test image')

        image_id = self.service.create(self.context, fixture)['id']

        (service, same_id) = glance.get_remote_image_service(self.context,

                                                             image_id)

        self.assertEqual(same_id, image_id)

**** CubicPower OpenStack Study ****

    def test_glance_client_image_ref(self):

        fixture = self._make_fixture(name='test image')

        image_id = self.service.create(self.context, fixture)['id']

        image_url = 'http://something-less-likely/%s' % image_id

        (service, same_id) = glance.get_remote_image_service(self.context,

                                                             image_url)

        self.assertEqual(same_id, image_id)

        self.assertEqual(service._client.netloc, 'something-less-likely')

        for ipv6_url in ('[::1]', '::1', '[::1]:444'):

            image_url = 'http://%s/%s' % (ipv6_url, image_id)

            (service, same_id) = glance.get_remote_image_service(self.context,

                                                                 image_url)

            self.assertEqual(same_id, image_id)

            self.assertEqual(service._client.netloc, ipv6_url)

**** CubicPower OpenStack Study ****

class TestGlanceClientVersion(test.TestCase):

"""Tests the version of the glance client generated."""

**** CubicPower OpenStack Study ****

    def setUp(self):

        super(TestGlanceClientVersion, self).setUp()

        def fake_get_model(self):

            return

        self.stubs.Set(glanceclient_v2, '_get_image_model',

                       fake_get_model)

        try:

            self.stubs.Set(glanceclient_v2, '_get_member_model',

                           fake_get_model)

        except AttributeError:

            # method requires stubbing only with newer glanceclients.

            pass

**** CubicPower OpenStack Study ****

        def fake_get_model(self):

            return

        self.stubs.Set(glanceclient_v2, '_get_image_model',

                       fake_get_model)

        try:

            self.stubs.Set(glanceclient_v2, '_get_member_model',

                           fake_get_model)

        except AttributeError:

            # method requires stubbing only with newer glanceclients.

            pass

**** CubicPower OpenStack Study ****

    def test_glance_version_by_flag(self):

        """Test glance version set by flag is honoured."""

        client_wrapper_v1 = glance.GlanceClientWrapper('fake', 'fake_host',

                                                       9292)

        self.assertEqual(client_wrapper_v1.client.__module__,

                         'glanceclient.v1.client')

        self.flags(glance_api_version=2)

        client_wrapper_v2 = glance.GlanceClientWrapper('fake', 'fake_host',

                                                       9292)

        self.assertEqual(client_wrapper_v2.client.__module__,

                         'glanceclient.v2.client')

        CONF.reset()

**** CubicPower OpenStack Study ****

    def test_glance_version_by_arg(self):

        """Test glance version set by arg to GlanceClientWrapper"""

        client_wrapper_v1 = glance.GlanceClientWrapper('fake', 'fake_host',

                                                       9292, version=1)

        self.assertEqual(client_wrapper_v1.client.__module__,

                         'glanceclient.v1.client')

        client_wrapper_v2 = glance.GlanceClientWrapper('fake', 'fake_host',

                                                       9292, version=2)

        self.assertEqual(client_wrapper_v2.client.__module__,

                         'glanceclient.v2.client')

def _create_failing_glance_client(info):

    class MyGlanceStubClient(glance_stubs.StubGlanceClient):

        """A client that fails the first time, then succeeds."""

        def get(self, image_id):

            info['num_calls'] += 1

            if info['num_calls'] == 1:

                raise glanceclient.exc.ServiceUnavailable('')

            return {}

    return MyGlanceStubClient()

**** CubicPower OpenStack Study ****

        def get(self, image_id):

            info['num_calls'] += 1

            if info['num_calls'] == 1:

                raise glanceclient.exc.ServiceUnavailable('')

            return {}

    return MyGlanceStubClient()

**** CubicPower OpenStack Study ****

class TestGlanceImageServiceClient(test.TestCase):

**** CubicPower OpenStack Study ****

    def setUp(self):

        super(TestGlanceImageServiceClient, self).setUp()

        self.context = context.RequestContext('fake', 'fake', auth_token=True)

        self.stubs.Set(glance.time, 'sleep', lambda s: None)

**** CubicPower OpenStack Study ****

    def test_create_glance_client(self):

        self.flags(auth_strategy='keystone')

        self.flags(glance_request_timeout=60)

        class MyGlanceStubClient(object):

            def __init__(inst, version, *args, **kwargs):

                self.assertEqual('1', version)

                self.assertEqual("http://fake_host:9292", args[0])

                self.assertEqual(True, kwargs['token'])

                self.assertEqual(60, kwargs['timeout'])

        self.stubs.Set(glance.glanceclient, 'Client', MyGlanceStubClient)

        client = glance._create_glance_client(self.context, 'fake_host:9292',

                                              False)

        self.assertIsInstance(client, MyGlanceStubClient)

**** CubicPower OpenStack Study ****

    def test_create_glance_client_auth_strategy_is_not_keystone(self):

        self.flags(auth_strategy='noauth')

        self.flags(glance_request_timeout=60)

        class MyGlanceStubClient(object):

            def __init__(inst, version, *args, **kwargs):

                self.assertEqual('1', version)

                self.assertEqual('http://fake_host:9292', args[0])

                self.assertNotIn('token', kwargs)

                self.assertEqual(60, kwargs['timeout'])

        self.stubs.Set(glance.glanceclient, 'Client', MyGlanceStubClient)

        client = glance._create_glance_client(self.context, 'fake_host:9292',

                                              False)

        self.assertIsInstance(client, MyGlanceStubClient)

**** CubicPower OpenStack Study ****

    def test_create_glance_client_glance_request_default_timeout(self):

        self.flags(auth_strategy='keystone')

        self.flags(glance_request_timeout=None)

        class MyGlanceStubClient(object):

            def __init__(inst, version, *args, **kwargs):

                self.assertEqual("1", version)

                self.assertEqual("http://fake_host:9292", args[0])

                self.assertEqual(True, kwargs['token'])

                self.assertNotIn('timeout', kwargs)

        self.stubs.Set(glance.glanceclient, 'Client', MyGlanceStubClient)

        client = glance._create_glance_client(self.context, 'fake_host:9292',

                                              False)

        self.assertIsInstance(client, MyGlanceStubClient)

**** CubicPower OpenStack Study ****

    def tearDown(self):

        self.stubs.UnsetAll()

        super(TestGlanceImageServiceClient, self).tearDown()