Migrated aggregates_client.py from tempest

This migrates the above files from tempest. This includes tempest commits:

 * aggregates_client.py     : Iac7e2e59b0a5b498fb5be5c7696ebe7bb15be8fe
 * test_aggregates_client.py: I3ad6761651cec5e66012d08e6b63322f53286a5c
 * aggregates.py            : Ica929c402a3d042ae751302384e68853eb28b405

to see the commit history for these files refer to the above sha1s in the tempest repository

Partially implements blueprint migrate-service-clients-to-tempest-lib

Change-Id: Ia20fd3914aa6e5ac829bfd3fb88bb4f654958b53
This commit is contained in:
Ken'ichi Ohmichi 2015-09-17 05:48:36 +09:00
parent 0214849e8c
commit 3bc9fe3678
3 changed files with 322 additions and 0 deletions

View File

@ -0,0 +1,92 @@
# Copyright 2014 NEC Corporation. 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 copy
# create-aggregate api doesn't have 'hosts' and 'metadata' attributes.
aggregate_for_create = {
'type': 'object',
'properties': {
'availability_zone': {'type': ['string', 'null']},
'created_at': {'type': 'string'},
'deleted': {'type': 'boolean'},
'deleted_at': {'type': ['string', 'null']},
'id': {'type': 'integer'},
'name': {'type': 'string'},
'updated_at': {'type': ['string', 'null']}
},
'additionalProperties': False,
'required': ['availability_zone', 'created_at', 'deleted',
'deleted_at', 'id', 'name', 'updated_at'],
}
common_aggregate_info = copy.deepcopy(aggregate_for_create)
common_aggregate_info['properties'].update({
'hosts': {'type': 'array'},
'metadata': {'type': 'object'}
})
common_aggregate_info['required'].extend(['hosts', 'metadata'])
list_aggregates = {
'status_code': [200],
'response_body': {
'type': 'object',
'properties': {
'aggregates': {
'type': 'array',
'items': common_aggregate_info
}
},
'additionalProperties': False,
'required': ['aggregates'],
}
}
get_aggregate = {
'status_code': [200],
'response_body': {
'type': 'object',
'properties': {
'aggregate': common_aggregate_info
},
'additionalProperties': False,
'required': ['aggregate'],
}
}
aggregate_set_metadata = get_aggregate
# The 'updated_at' attribute of 'update_aggregate' can't be null.
update_aggregate = copy.deepcopy(get_aggregate)
update_aggregate['response_body']['properties']['aggregate']['properties'][
'updated_at'] = {
'type': 'string'
}
delete_aggregate = {
'status_code': [200]
}
create_aggregate = {
'status_code': [200],
'response_body': {
'type': 'object',
'properties': {
'aggregate': aggregate_for_create
},
'additionalProperties': False,
'required': ['aggregate'],
}
}
aggregate_add_remove_host = get_aggregate

View File

@ -0,0 +1,100 @@
# Copyright 2013 NEC Corporation.
# 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.
from oslo_serialization import jsonutils as json
from tempest_lib.api_schema.response.compute.v2_1 import aggregates as schema
from tempest_lib.common import rest_client
from tempest_lib import exceptions as lib_exc
class AggregatesClient(rest_client.RestClient):
def list_aggregates(self):
"""Get aggregate list."""
resp, body = self.get("os-aggregates")
body = json.loads(body)
self.validate_response(schema.list_aggregates, resp, body)
return rest_client.ResponseBody(resp, body)
def show_aggregate(self, aggregate_id):
"""Get details of the given aggregate."""
resp, body = self.get("os-aggregates/%s" % aggregate_id)
body = json.loads(body)
self.validate_response(schema.get_aggregate, resp, body)
return rest_client.ResponseBody(resp, body)
def create_aggregate(self, **kwargs):
"""Creates a new aggregate."""
post_body = json.dumps({'aggregate': kwargs})
resp, body = self.post('os-aggregates', post_body)
body = json.loads(body)
self.validate_response(schema.create_aggregate, resp, body)
return rest_client.ResponseBody(resp, body)
def update_aggregate(self, aggregate_id, **kwargs):
"""Update a aggregate."""
put_body = json.dumps({'aggregate': kwargs})
resp, body = self.put('os-aggregates/%s' % aggregate_id, put_body)
body = json.loads(body)
self.validate_response(schema.update_aggregate, resp, body)
return rest_client.ResponseBody(resp, body)
def delete_aggregate(self, aggregate_id):
"""Deletes the given aggregate."""
resp, body = self.delete("os-aggregates/%s" % aggregate_id)
self.validate_response(schema.delete_aggregate, resp, body)
return rest_client.ResponseBody(resp, body)
def is_resource_deleted(self, id):
try:
self.show_aggregate(id)
except lib_exc.NotFound:
return True
return False
@property
def resource_type(self):
"""Returns the primary type of resource this client works with."""
return 'aggregate'
def add_host(self, aggregate_id, **kwargs):
"""Adds a host to the given aggregate."""
post_body = json.dumps({'add_host': kwargs})
resp, body = self.post('os-aggregates/%s/action' % aggregate_id,
post_body)
body = json.loads(body)
self.validate_response(schema.aggregate_add_remove_host, resp, body)
return rest_client.ResponseBody(resp, body)
def remove_host(self, aggregate_id, **kwargs):
"""Removes a host from the given aggregate."""
post_body = json.dumps({'remove_host': kwargs})
resp, body = self.post('os-aggregates/%s/action' % aggregate_id,
post_body)
body = json.loads(body)
self.validate_response(schema.aggregate_add_remove_host, resp, body)
return rest_client.ResponseBody(resp, body)
def set_metadata(self, aggregate_id, **kwargs):
"""Replaces the aggregate's existing metadata with new metadata."""
post_body = json.dumps({'set_metadata': kwargs})
resp, body = self.post('os-aggregates/%s/action' % aggregate_id,
post_body)
body = json.loads(body)
self.validate_response(schema.aggregate_set_metadata, resp, body)
return rest_client.ResponseBody(resp, body)

View File

@ -0,0 +1,130 @@
# Copyright 2015 NEC Corporation. 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.
from tempest_lib.services.compute import aggregates_client
from tempest_lib.tests import fake_auth_provider
from tempest_lib.tests.services.compute import base
class TestAggregatesClient(base.BaseComputeServiceTest):
FAKE_SHOW_AGGREGATE = {
"aggregate":
{
"name": "hoge",
"availability_zone": None,
"deleted": False,
"created_at":
"2015-07-16T03:07:32.000000",
"updated_at": None,
"hosts": [],
"deleted_at": None,
"id": 1,
"metadata": {}
}
}
FAKE_CREATE_AGGREGATE = {
"aggregate":
{
"name": u'\xf4',
"availability_zone": None,
"deleted": False,
"created_at": "2015-07-21T04:11:18.000000",
"updated_at": None,
"deleted_at": None,
"id": 1
}
}
FAKE_UPDATE_AGGREGATE = {
"aggregate":
{
"name": u'\xe9',
"availability_zone": None,
"deleted": False,
"created_at": "2015-07-16T03:07:32.000000",
"updated_at": "2015-07-23T05:16:29.000000",
"hosts": [],
"deleted_at": None,
"id": 1,
"metadata": {}
}
}
def setUp(self):
super(TestAggregatesClient, self).setUp()
fake_auth = fake_auth_provider.FakeAuthProvider()
self.client = aggregates_client.AggregatesClient(
fake_auth, 'compute', 'regionOne')
def _test_list_aggregates(self, bytes_body=False):
self.check_service_client_function(
self.client.list_aggregates,
'tempest_lib.common.rest_client.RestClient.get',
{"aggregates": []},
bytes_body)
def test_list_aggregates_with_str_body(self):
self._test_list_aggregates()
def test_list_aggregates_with_bytes_body(self):
self._test_list_aggregates(bytes_body=True)
def _test_show_aggregate(self, bytes_body=False):
self.check_service_client_function(
self.client.show_aggregate,
'tempest_lib.common.rest_client.RestClient.get',
self.FAKE_SHOW_AGGREGATE,
bytes_body,
aggregate_id=1)
def test_show_aggregate_with_str_body(self):
self._test_show_aggregate()
def test_show_aggregate_with_bytes_body(self):
self._test_show_aggregate(bytes_body=True)
def _test_create_aggregate(self, bytes_body=False):
self.check_service_client_function(
self.client.create_aggregate,
'tempest_lib.common.rest_client.RestClient.post',
self.FAKE_CREATE_AGGREGATE,
bytes_body,
name='hoge')
def test_create_aggregate_with_str_body(self):
self._test_create_aggregate()
def test_create_aggregate_with_bytes_body(self):
self._test_create_aggregate(bytes_body=True)
def test_delete_aggregate(self):
self.check_service_client_function(
self.client.delete_aggregate,
'tempest_lib.common.rest_client.RestClient.delete',
{}, aggregate_id="1")
def _test_update_aggregate(self, bytes_body=False):
self.check_service_client_function(
self.client.update_aggregate,
'tempest_lib.common.rest_client.RestClient.put',
self.FAKE_UPDATE_AGGREGATE,
bytes_body,
aggregate_id=1)
def test_update_aggregate_with_str_body(self):
self._test_update_aggregate()
def test_update_aggregate_with_bytes_body(self):
self._test_update_aggregate(bytes_body=True)