Add ImageDetail for extra information
The current Image can only receive the basics returned by a GET /images, which is just name, id, and links. A call to /images/detail gives a number of added details, some of which were already in the Image resource but not set. This change follows with how a few other basic/detail requests were done, and exposes it through the proxy with details coming by default (since they're likely expected, and most useful). Change-Id: Iadc98cd0f679777b1c6e14711ad00787142221e2
This commit is contained in:
parent
ee4c85d243
commit
f92973d7f8
@ -10,3 +10,12 @@ The ``Image`` class inherits from :class:`~openstack.resource.Resource`.
|
|||||||
|
|
||||||
.. autoclass:: openstack.compute.v2.image.Image
|
.. autoclass:: openstack.compute.v2.image.Image
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
The ImageDetail Class
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
The ``ImageDetail`` class inherits from
|
||||||
|
:class:`~openstack.compute.v2.image.Image`.
|
||||||
|
|
||||||
|
.. autoclass:: openstack.compute.v2.image.ImageDetail
|
||||||
|
:members:
|
||||||
|
@ -59,9 +59,6 @@ class Proxy(object):
|
|||||||
def update_flavor(self, **data):
|
def update_flavor(self, **data):
|
||||||
return flavor.Flavor(data).update(self.session)
|
return flavor.Flavor(data).update(self.session)
|
||||||
|
|
||||||
def create_image(self, **data):
|
|
||||||
return image.Image(data).create(self.session)
|
|
||||||
|
|
||||||
def delete_image(self, **data):
|
def delete_image(self, **data):
|
||||||
image.Image(data).delete(self.session)
|
image.Image(data).delete(self.session)
|
||||||
|
|
||||||
@ -71,11 +68,18 @@ class Proxy(object):
|
|||||||
def get_image(self, **data):
|
def get_image(self, **data):
|
||||||
return image.Image(data).get(self.session)
|
return image.Image(data).get(self.session)
|
||||||
|
|
||||||
def list_images(self):
|
def list_images(self, details=True):
|
||||||
return image.Image.list(self.session)
|
"""Return a generator of images
|
||||||
|
|
||||||
def update_image(self, **data):
|
:param bool details: When ``True``, returns
|
||||||
return image.Image(data).update(self.session)
|
:class:`~openstack.compute.v2.image.ImageDetail` objects,
|
||||||
|
otherwise :class:`~openstack.compute.v2.image.Image`.
|
||||||
|
*Default: ``True``*
|
||||||
|
|
||||||
|
:returns: A generator of image objects
|
||||||
|
"""
|
||||||
|
img = image.ImageDetail if details else image.Image
|
||||||
|
return img.list(self.session, paginate=False)
|
||||||
|
|
||||||
def create_keypair(self, **data):
|
def create_keypair(self, **data):
|
||||||
return keypair.Keypair(data).create(self.session)
|
return keypair.Keypair(data).create(self.session)
|
||||||
|
@ -21,26 +21,24 @@ class Image(resource.Resource):
|
|||||||
service = compute_service.ComputeService()
|
service = compute_service.ComputeService()
|
||||||
|
|
||||||
# capabilities
|
# capabilities
|
||||||
allow_create = True
|
|
||||||
allow_retrieve = True
|
allow_retrieve = True
|
||||||
allow_update = True
|
|
||||||
allow_delete = True
|
allow_delete = True
|
||||||
allow_list = True
|
allow_list = True
|
||||||
|
|
||||||
# Properties
|
# Properties
|
||||||
#: Timestamp when the image was created.
|
|
||||||
created = resource.prop('created')
|
|
||||||
#: Links pertaining to this image. This is a list of dictionaries,
|
#: Links pertaining to this image. This is a list of dictionaries,
|
||||||
#: each including keys ``href`` and ``rel``, and optionally ``type``.
|
#: each including keys ``href`` and ``rel``, and optionally ``type``.
|
||||||
links = resource.prop('links')
|
links = resource.prop('links')
|
||||||
|
#: The name of this image.
|
||||||
|
name = resource.prop('name')
|
||||||
|
#: Timestamp when the image was created.
|
||||||
|
created = resource.prop('created')
|
||||||
#: Metadata pertaining to this image. *Type: dict*
|
#: Metadata pertaining to this image. *Type: dict*
|
||||||
metadata = resource.prop('metadata', type=dict)
|
metadata = resource.prop('metadata', type=dict)
|
||||||
#: The mimimum disk size. *Type: int*
|
#: The mimimum disk size. *Type: int*
|
||||||
min_disk = resource.prop('minDisk', type=int)
|
min_disk = resource.prop('minDisk', type=int)
|
||||||
#: The minimum RAM size. *Type: int*
|
#: The minimum RAM size. *Type: int*
|
||||||
min_ram = resource.prop('minRam', type=int)
|
min_ram = resource.prop('minRam', type=int)
|
||||||
#: The name of this image.
|
|
||||||
name = resource.prop('name')
|
|
||||||
#: If this image is still building, its progress is represented here.
|
#: If this image is still building, its progress is represented here.
|
||||||
#: Once an image is created, progres will be 100. *Type: int*
|
#: Once an image is created, progres will be 100. *Type: int*
|
||||||
progress = resource.prop('progress', type=int)
|
progress = resource.prop('progress', type=int)
|
||||||
@ -48,3 +46,13 @@ class Image(resource.Resource):
|
|||||||
status = resource.prop('status')
|
status = resource.prop('status')
|
||||||
#: Timestamp when the image was updated.
|
#: Timestamp when the image was updated.
|
||||||
updated = resource.prop('updated')
|
updated = resource.prop('updated')
|
||||||
|
#: Size of the image in bytes. *Type: int*
|
||||||
|
size = resource.prop('OS-EXT-IMG-SIZE:size', type=int)
|
||||||
|
|
||||||
|
|
||||||
|
class ImageDetail(Image):
|
||||||
|
base_path = '/images/detail'
|
||||||
|
|
||||||
|
allow_retrieve = False
|
||||||
|
allow_delete = False
|
||||||
|
allow_list = True
|
||||||
|
@ -15,19 +15,26 @@ import testtools
|
|||||||
from openstack.compute.v2 import image
|
from openstack.compute.v2 import image
|
||||||
|
|
||||||
IDENTIFIER = 'IDENTIFIER'
|
IDENTIFIER = 'IDENTIFIER'
|
||||||
EXAMPLE = {
|
BASIC_EXAMPLE = {
|
||||||
'created': '1',
|
|
||||||
'id': IDENTIFIER,
|
'id': IDENTIFIER,
|
||||||
'links': '3',
|
'links': '2',
|
||||||
'metadata': {'key': '4'},
|
'name': '3',
|
||||||
'minDisk': 5,
|
|
||||||
'minRam': 6,
|
|
||||||
'name': '7',
|
|
||||||
'progress': 8,
|
|
||||||
'status': '9',
|
|
||||||
'updated': '10',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DETAILS = {
|
||||||
|
'created': '1',
|
||||||
|
'metadata': {'key': '2'},
|
||||||
|
'minDisk': 3,
|
||||||
|
'minRam': 4,
|
||||||
|
'progress': 5,
|
||||||
|
'status': '6',
|
||||||
|
'updated': '7',
|
||||||
|
'OS-EXT-IMG-SIZE:size': 8
|
||||||
|
}
|
||||||
|
|
||||||
|
DETAIL_EXAMPLE = BASIC_EXAMPLE.copy()
|
||||||
|
DETAIL_EXAMPLE.update(DETAILS)
|
||||||
|
|
||||||
|
|
||||||
class TestImage(testtools.TestCase):
|
class TestImage(testtools.TestCase):
|
||||||
|
|
||||||
@ -37,21 +44,40 @@ class TestImage(testtools.TestCase):
|
|||||||
self.assertEqual('images', sot.resources_key)
|
self.assertEqual('images', sot.resources_key)
|
||||||
self.assertEqual('/images', sot.base_path)
|
self.assertEqual('/images', sot.base_path)
|
||||||
self.assertEqual('compute', sot.service.service_type)
|
self.assertEqual('compute', sot.service.service_type)
|
||||||
self.assertTrue(sot.allow_create)
|
self.assertFalse(sot.allow_create)
|
||||||
self.assertTrue(sot.allow_retrieve)
|
self.assertTrue(sot.allow_retrieve)
|
||||||
self.assertTrue(sot.allow_update)
|
self.assertFalse(sot.allow_update)
|
||||||
self.assertTrue(sot.allow_delete)
|
self.assertTrue(sot.allow_delete)
|
||||||
self.assertTrue(sot.allow_list)
|
self.assertTrue(sot.allow_list)
|
||||||
|
|
||||||
def test_make_it(self):
|
def test_make_basic(self):
|
||||||
sot = image.Image(EXAMPLE)
|
sot = image.Image(BASIC_EXAMPLE)
|
||||||
self.assertEqual(EXAMPLE['created'], sot.created)
|
self.assertEqual(BASIC_EXAMPLE['id'], sot.id)
|
||||||
self.assertEqual(EXAMPLE['id'], sot.id)
|
self.assertEqual(BASIC_EXAMPLE['links'], sot.links)
|
||||||
self.assertEqual(EXAMPLE['links'], sot.links)
|
self.assertEqual(BASIC_EXAMPLE['name'], sot.name)
|
||||||
self.assertEqual(EXAMPLE['metadata'], sot.metadata)
|
|
||||||
self.assertEqual(EXAMPLE['minDisk'], sot.min_disk)
|
def test_detail(self):
|
||||||
self.assertEqual(EXAMPLE['minRam'], sot.min_ram)
|
sot = image.ImageDetail()
|
||||||
self.assertEqual(EXAMPLE['name'], sot.name)
|
self.assertEqual('image', sot.resource_key)
|
||||||
self.assertEqual(EXAMPLE['progress'], sot.progress)
|
self.assertEqual('images', sot.resources_key)
|
||||||
self.assertEqual(EXAMPLE['status'], sot.status)
|
self.assertEqual('/images/detail', sot.base_path)
|
||||||
self.assertEqual(EXAMPLE['updated'], sot.updated)
|
self.assertEqual('compute', sot.service.service_type)
|
||||||
|
self.assertFalse(sot.allow_create)
|
||||||
|
self.assertFalse(sot.allow_retrieve)
|
||||||
|
self.assertFalse(sot.allow_update)
|
||||||
|
self.assertFalse(sot.allow_delete)
|
||||||
|
self.assertTrue(sot.allow_list)
|
||||||
|
|
||||||
|
def test_make_detail(self):
|
||||||
|
sot = image.ImageDetail(DETAIL_EXAMPLE)
|
||||||
|
self.assertEqual(DETAIL_EXAMPLE['created'], sot.created)
|
||||||
|
self.assertEqual(DETAIL_EXAMPLE['id'], sot.id)
|
||||||
|
self.assertEqual(DETAIL_EXAMPLE['links'], sot.links)
|
||||||
|
self.assertEqual(DETAIL_EXAMPLE['metadata'], sot.metadata)
|
||||||
|
self.assertEqual(DETAIL_EXAMPLE['minDisk'], sot.min_disk)
|
||||||
|
self.assertEqual(DETAIL_EXAMPLE['minRam'], sot.min_ram)
|
||||||
|
self.assertEqual(DETAIL_EXAMPLE['name'], sot.name)
|
||||||
|
self.assertEqual(DETAIL_EXAMPLE['progress'], sot.progress)
|
||||||
|
self.assertEqual(DETAIL_EXAMPLE['status'], sot.status)
|
||||||
|
self.assertEqual(DETAIL_EXAMPLE['updated'], sot.updated)
|
||||||
|
self.assertEqual(DETAIL_EXAMPLE['OS-EXT-IMG-SIZE:size'], sot.size)
|
||||||
|
@ -59,10 +59,6 @@ class TestComputeProxy(test_proxy_base.TestProxyBase):
|
|||||||
self.verify_update('openstack.compute.v2.flavor.Flavor.update',
|
self.verify_update('openstack.compute.v2.flavor.Flavor.update',
|
||||||
self.proxy.update_flavor)
|
self.proxy.update_flavor)
|
||||||
|
|
||||||
def test_image_create(self):
|
|
||||||
self.verify_create('openstack.compute.v2.image.Image.create',
|
|
||||||
self.proxy.create_image)
|
|
||||||
|
|
||||||
def test_image_delete(self):
|
def test_image_delete(self):
|
||||||
self.verify_delete('openstack.compute.v2.image.Image.delete',
|
self.verify_delete('openstack.compute.v2.image.Image.delete',
|
||||||
self.proxy.delete_image)
|
self.proxy.delete_image)
|
||||||
@ -75,13 +71,17 @@ class TestComputeProxy(test_proxy_base.TestProxyBase):
|
|||||||
self.verify_get('openstack.compute.v2.image.Image.get',
|
self.verify_get('openstack.compute.v2.image.Image.get',
|
||||||
self.proxy.get_image)
|
self.proxy.get_image)
|
||||||
|
|
||||||
def test_image_list(self):
|
def test_image_list_basic(self):
|
||||||
self.verify_list('openstack.compute.v2.image.Image.list',
|
self.verify_list('openstack.compute.v2.image.Image.list',
|
||||||
self.proxy.list_images)
|
self.proxy.list_images,
|
||||||
|
method_kwargs={"details": False},
|
||||||
|
expected_kwargs={"paginate": False})
|
||||||
|
|
||||||
def test_image_update(self):
|
def test_image_list_detail(self):
|
||||||
self.verify_update('openstack.compute.v2.image.Image.update',
|
self.verify_list('openstack.compute.v2.image.ImageDetail.list',
|
||||||
self.proxy.update_image)
|
self.proxy.list_images,
|
||||||
|
method_kwargs={"details": True},
|
||||||
|
expected_kwargs={"paginate": False})
|
||||||
|
|
||||||
def test_keypair_create(self):
|
def test_keypair_create(self):
|
||||||
self.verify_create('openstack.compute.v2.keypair.Keypair.create',
|
self.verify_create('openstack.compute.v2.keypair.Keypair.create',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user