Merge "Complete compute aggregate functions"
This commit is contained in:
commit
e169c495de
|
@ -274,6 +274,20 @@ class Proxy(proxy.Proxy):
|
|||
"""
|
||||
return self._get(_aggregate.Aggregate, aggregate)
|
||||
|
||||
def find_aggregate(self, name_or_id, ignore_missing=True):
|
||||
"""Find a single aggregate
|
||||
|
||||
:param name_or_id: The name or ID of an aggregate.
|
||||
:param bool ignore_missing: When set to ``False``
|
||||
:class:`~openstack.exceptions.ResourceNotFound` will be raised when
|
||||
the resource does not exist. When set to ``True``, None will be
|
||||
returned when attempting to find a nonexistent resource.
|
||||
:returns: One :class:`~openstack.compute.v2.aggregate.Aggregate`
|
||||
or None
|
||||
"""
|
||||
return self._find(_aggregate.Aggregate, name_or_id,
|
||||
ignore_missing=ignore_missing)
|
||||
|
||||
def create_aggregate(self, **attrs):
|
||||
"""Create a new host aggregate from attributes
|
||||
|
||||
|
@ -358,6 +372,26 @@ class Proxy(proxy.Proxy):
|
|||
aggregate = self._get_resource(_aggregate.Aggregate, aggregate)
|
||||
return aggregate.set_metadata(self, metadata)
|
||||
|
||||
def aggregate_precache_images(self, aggregate, images):
|
||||
"""Requests image precaching on an aggregate
|
||||
|
||||
:param aggregate: Either the ID of a aggregate or a
|
||||
:class:`~openstack.compute.v2.aggregate.Aggregate` instance.
|
||||
:param images: Single image id or list of image ids.
|
||||
|
||||
:returns: ``None``
|
||||
"""
|
||||
aggregate = self._get_resource(_aggregate.Aggregate, aggregate)
|
||||
# We need to ensure we pass list of image IDs
|
||||
if isinstance(images, str):
|
||||
images = [images]
|
||||
image_data = []
|
||||
for img in images:
|
||||
image_data.append({'id': img})
|
||||
return aggregate.precache_images(self, image_data)
|
||||
|
||||
# ========== Images ==========
|
||||
|
||||
def delete_image(self, image, ignore_missing=True):
|
||||
"""Delete an image
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
from openstack import exceptions
|
||||
from openstack import resource
|
||||
from openstack import utils
|
||||
|
||||
|
@ -30,25 +30,31 @@ class Aggregate(resource.Resource):
|
|||
# Properties
|
||||
#: Availability zone of aggregate
|
||||
availability_zone = resource.Body('availability_zone')
|
||||
#: The date and time when the resource was created.
|
||||
created_at = resource.Body('created_at')
|
||||
#: The date and time when the resource was deleted.
|
||||
deleted_at = resource.Body('deleted_at')
|
||||
#: Deleted?
|
||||
deleted = resource.Body('deleted')
|
||||
is_deleted = resource.Body('deleted', type=bool)
|
||||
#: Name of aggregate
|
||||
name = resource.Body('name')
|
||||
#: Hosts
|
||||
hosts = resource.Body('hosts')
|
||||
hosts = resource.Body('hosts', type=list)
|
||||
#: Metadata
|
||||
metadata = resource.Body('metadata')
|
||||
metadata = resource.Body('metadata', type=dict)
|
||||
#: The date and time when the resource was updated
|
||||
updated_at = resource.Body('updated_at')
|
||||
#: UUID
|
||||
uuid = resource.Body('uuid')
|
||||
# uuid introduced in 2.41
|
||||
_max_microversion = '2.41'
|
||||
# Image pre-caching introduced in 2.81
|
||||
_max_microversion = '2.81'
|
||||
|
||||
def _action(self, session, body, microversion=None):
|
||||
"""Preform aggregate actions given the message body."""
|
||||
url = utils.urljoin(self.base_path, self.id, 'action')
|
||||
headers = {'Accept': ''}
|
||||
response = session.post(
|
||||
url, json=body, headers=headers, microversion=microversion)
|
||||
url, json=body, microversion=microversion)
|
||||
exceptions.raise_from_response(response)
|
||||
aggregate = Aggregate()
|
||||
aggregate._translate_response(response=response)
|
||||
return aggregate
|
||||
|
@ -67,3 +73,12 @@ class Aggregate(resource.Resource):
|
|||
"""Creates or replaces metadata for an aggregate."""
|
||||
body = {'set_metadata': {'metadata': metadata}}
|
||||
return self._action(session, body)
|
||||
|
||||
def precache_images(self, session, images):
|
||||
"""Requests image pre-caching"""
|
||||
body = {'cache': images}
|
||||
url = utils.urljoin(self.base_path, self.id, 'images')
|
||||
response = session.post(
|
||||
url, json=body, microversion=self._max_microversion)
|
||||
exceptions.raise_from_response(response)
|
||||
# This API has no result
|
||||
|
|
|
@ -1895,7 +1895,9 @@ class Resource(dict):
|
|||
connection=session._get_connection(),
|
||||
**params)
|
||||
return match.fetch(session, **params)
|
||||
except exceptions.NotFoundException:
|
||||
except (exceptions.NotFoundException, exceptions.BadRequestException):
|
||||
# NOTE(gtema): There are few places around openstack that return
|
||||
# 400 if we try to GET resource and it doesn't exist.
|
||||
pass
|
||||
|
||||
if ('name' in cls._query_mapping._mapping.keys()
|
||||
|
|
|
@ -60,7 +60,10 @@ class TestAggregate(base.TestCase):
|
|||
sot = aggregate.Aggregate(**EXAMPLE)
|
||||
self.assertEqual(EXAMPLE['name'], sot.name)
|
||||
self.assertEqual(EXAMPLE['availability_zone'], sot.availability_zone)
|
||||
self.assertEqual(EXAMPLE['deleted'], sot.deleted)
|
||||
self.assertEqual(EXAMPLE['deleted'], sot.is_deleted)
|
||||
self.assertEqual(EXAMPLE['deleted_at'], sot.deleted_at)
|
||||
self.assertEqual(EXAMPLE['created_at'], sot.created_at)
|
||||
self.assertEqual(EXAMPLE['updated_at'], sot.updated_at)
|
||||
self.assertEqual(EXAMPLE['hosts'], sot.hosts)
|
||||
self.assertEqual(EXAMPLE['id'], sot.id)
|
||||
self.assertEqual(EXAMPLE['uuid'], sot.uuid)
|
||||
|
@ -73,9 +76,8 @@ class TestAggregate(base.TestCase):
|
|||
|
||||
url = 'os-aggregates/4/action'
|
||||
body = {"add_host": {"host": "host1"}}
|
||||
headers = {'Accept': ''}
|
||||
self.sess.post.assert_called_with(
|
||||
url, json=body, headers=headers, microversion=None)
|
||||
url, json=body, microversion=None)
|
||||
|
||||
def test_remove_host(self):
|
||||
sot = aggregate.Aggregate(**EXAMPLE)
|
||||
|
@ -84,9 +86,8 @@ class TestAggregate(base.TestCase):
|
|||
|
||||
url = 'os-aggregates/4/action'
|
||||
body = {"remove_host": {"host": "host1"}}
|
||||
headers = {'Accept': ''}
|
||||
self.sess.post.assert_called_with(
|
||||
url, json=body, headers=headers, microversion=None)
|
||||
url, json=body, microversion=None)
|
||||
|
||||
def test_set_metadata(self):
|
||||
sot = aggregate.Aggregate(**EXAMPLE)
|
||||
|
@ -95,6 +96,15 @@ class TestAggregate(base.TestCase):
|
|||
|
||||
url = 'os-aggregates/4/action'
|
||||
body = {"set_metadata": {"metadata": {"key: value"}}}
|
||||
headers = {'Accept': ''}
|
||||
self.sess.post.assert_called_with(
|
||||
url, json=body, headers=headers, microversion=None)
|
||||
url, json=body, microversion=None)
|
||||
|
||||
def test_precache_image(self):
|
||||
sot = aggregate.Aggregate(**EXAMPLE)
|
||||
|
||||
sot.precache_images(self.sess, ['1'])
|
||||
|
||||
url = 'os-aggregates/4/images'
|
||||
body = {"cache": ['1']}
|
||||
self.sess.post.assert_called_with(
|
||||
url, json=body, microversion=sot._max_microversion)
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
from unittest import mock
|
||||
|
||||
from openstack.compute.v2 import _proxy
|
||||
from openstack.compute.v2 import aggregate
|
||||
from openstack.compute.v2 import availability_zone as az
|
||||
from openstack.compute.v2 import extension
|
||||
from openstack.compute.v2 import flavor
|
||||
|
@ -248,6 +249,63 @@ class TestKeyPair(TestComputeProxy):
|
|||
)
|
||||
|
||||
|
||||
class TestAggregate(TestComputeProxy):
|
||||
def test_aggregate_create(self):
|
||||
self.verify_create(self.proxy.create_aggregate, aggregate.Aggregate)
|
||||
|
||||
def test_aggregate_delete(self):
|
||||
self.verify_delete(
|
||||
self.proxy.delete_aggregate, aggregate.Aggregate, False)
|
||||
|
||||
def test_aggregate_delete_ignore(self):
|
||||
self.verify_delete(
|
||||
self.proxy.delete_aggregate, aggregate.Aggregate, True)
|
||||
|
||||
def test_aggregate_find(self):
|
||||
self.verify_find(self.proxy.find_aggregate, aggregate.Aggregate)
|
||||
|
||||
def test_aggregates(self):
|
||||
self.verify_list_no_kwargs(self.proxy.aggregates, aggregate.Aggregate)
|
||||
|
||||
def test_aggregate_get(self):
|
||||
self.verify_get(self.proxy.get_aggregate, aggregate.Aggregate)
|
||||
|
||||
def test_aggregate_update(self):
|
||||
self.verify_update(self.proxy.update_aggregate, aggregate.Aggregate)
|
||||
|
||||
def test_aggregate_add_host(self):
|
||||
self._verify("openstack.compute.v2.aggregate.Aggregate.add_host",
|
||||
self.proxy.add_host_to_aggregate,
|
||||
method_args=["value", "host"],
|
||||
expected_args=["host"])
|
||||
|
||||
def test_aggregate_remove_host(self):
|
||||
self._verify("openstack.compute.v2.aggregate.Aggregate.remove_host",
|
||||
self.proxy.remove_host_from_aggregate,
|
||||
method_args=["value", "host"],
|
||||
expected_args=["host"])
|
||||
|
||||
def test_aggregate_set_metadata(self):
|
||||
self._verify("openstack.compute.v2.aggregate.Aggregate.set_metadata",
|
||||
self.proxy.set_aggregate_metadata,
|
||||
method_args=["value", {'a': 'b'}],
|
||||
expected_args=[{'a': 'b'}])
|
||||
|
||||
def test_aggregate_precache_image(self):
|
||||
self._verify(
|
||||
"openstack.compute.v2.aggregate.Aggregate.precache_images",
|
||||
self.proxy.aggregate_precache_images,
|
||||
method_args=["value", '1'],
|
||||
expected_args=[[{'id': '1'}]])
|
||||
|
||||
def test_aggregate_precache_images(self):
|
||||
self._verify(
|
||||
"openstack.compute.v2.aggregate.Aggregate.precache_images",
|
||||
self.proxy.aggregate_precache_images,
|
||||
method_args=["value", ['1', '2']],
|
||||
expected_args=[[{'id': '1'}, {'id': '2'}]])
|
||||
|
||||
|
||||
class TestCompute(TestComputeProxy):
|
||||
def test_extension_find(self):
|
||||
self.verify_find(self.proxy.find_extension, extension.Extension)
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
features:
|
||||
- Complete compute.aggregate functions to the latest state
|
||||
fixes:
|
||||
- aggregate.deleted property is renamed to 'is_deleted' to comply with the
|
||||
naming convention
|
Loading…
Reference in New Issue