Remove Nova v3 API tests
Nova v3 API has disappeared, and Tempest isn't testing the API on the gate now. In addition, Nova team is creating a new REST API "Nova v2.1 API + microversions" and the interfaces are different from v3 API. So it is not necessary to keep Nova v3 API tests in Tempest. This patch removes them. Change-Id: I5de01deaa699e03b0e838952239011da54702daf
This commit is contained in:
parent
ab6106ddaa
commit
9f5adf8053
@ -17,15 +17,15 @@ from tempest.api.compute import base
|
|||||||
from tempest import test
|
from tempest import test
|
||||||
|
|
||||||
|
|
||||||
class AZAdminV3Test(base.BaseComputeAdminTest):
|
class AZAdminV2TestJSON(base.BaseComputeAdminTest):
|
||||||
"""
|
"""
|
||||||
Tests Availability Zone API List
|
Tests Availability Zone API List
|
||||||
"""
|
"""
|
||||||
_api_version = 3
|
_api_version = 2
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def resource_setup(cls):
|
def resource_setup(cls):
|
||||||
super(AZAdminV3Test, cls).resource_setup()
|
super(AZAdminV2TestJSON, cls).resource_setup()
|
||||||
cls.client = cls.availability_zone_admin_client
|
cls.client = cls.availability_zone_admin_client
|
||||||
|
|
||||||
@test.attr(type='gate')
|
@test.attr(type='gate')
|
||||||
@ -42,7 +42,3 @@ class AZAdminV3Test(base.BaseComputeAdminTest):
|
|||||||
self.client.get_availability_zone_list_detail()
|
self.client.get_availability_zone_list_detail()
|
||||||
self.assertEqual(200, resp.status)
|
self.assertEqual(200, resp.status)
|
||||||
self.assertTrue(len(availability_zone) > 0)
|
self.assertTrue(len(availability_zone) > 0)
|
||||||
|
|
||||||
|
|
||||||
class AZAdminV2TestJSON(AZAdminV3Test):
|
|
||||||
_api_version = 2
|
|
||||||
|
@ -31,7 +31,7 @@ LOG = logging.getLogger(__name__)
|
|||||||
class BaseComputeTest(tempest.test.BaseTestCase):
|
class BaseComputeTest(tempest.test.BaseTestCase):
|
||||||
"""Base test case class for all Compute API tests."""
|
"""Base test case class for all Compute API tests."""
|
||||||
|
|
||||||
_api_version = 3
|
_api_version = 2
|
||||||
force_tenant_isolation = False
|
force_tenant_isolation = False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -87,29 +87,6 @@ class BaseComputeTest(tempest.test.BaseTestCase):
|
|||||||
cls.migrations_client = cls.os.migrations_client
|
cls.migrations_client = cls.os.migrations_client
|
||||||
cls.security_group_default_rules_client = (
|
cls.security_group_default_rules_client = (
|
||||||
cls.os.security_group_default_rules_client)
|
cls.os.security_group_default_rules_client)
|
||||||
|
|
||||||
elif cls._api_version == 3:
|
|
||||||
if not CONF.compute_feature_enabled.api_v3:
|
|
||||||
skip_msg = ("%s skipped as nova v3 api is not available" %
|
|
||||||
cls.__name__)
|
|
||||||
raise cls.skipException(skip_msg)
|
|
||||||
cls.servers_client = cls.os.servers_v3_client
|
|
||||||
cls.images_client = cls.os.image_client
|
|
||||||
cls.flavors_client = cls.os.flavors_v3_client
|
|
||||||
cls.services_client = cls.os.services_v3_client
|
|
||||||
cls.extensions_client = cls.os.extensions_v3_client
|
|
||||||
cls.availability_zone_client = cls.os.availability_zone_v3_client
|
|
||||||
cls.interfaces_client = cls.os.interfaces_v3_client
|
|
||||||
cls.hypervisor_client = cls.os.hypervisor_v3_client
|
|
||||||
cls.keypairs_client = cls.os.keypairs_v3_client
|
|
||||||
cls.volumes_client = cls.os.volumes_client
|
|
||||||
cls.certificates_client = cls.os.certificates_v3_client
|
|
||||||
cls.keypairs_client = cls.os.keypairs_v3_client
|
|
||||||
cls.aggregates_client = cls.os.aggregates_v3_client
|
|
||||||
cls.hosts_client = cls.os.hosts_v3_client
|
|
||||||
cls.quotas_client = cls.os.quotas_v3_client
|
|
||||||
cls.version_client = cls.os.version_v3_client
|
|
||||||
cls.migrations_client = cls.os.migrations_v3_client
|
|
||||||
else:
|
else:
|
||||||
msg = ("Unexpected API version is specified (%s)" %
|
msg = ("Unexpected API version is specified (%s)" %
|
||||||
cls._api_version)
|
cls._api_version)
|
||||||
@ -316,20 +293,14 @@ class BaseComputeTest(tempest.test.BaseTestCase):
|
|||||||
if 'name' in kwargs:
|
if 'name' in kwargs:
|
||||||
name = kwargs.pop('name')
|
name = kwargs.pop('name')
|
||||||
|
|
||||||
if cls._api_version == 2:
|
resp, image = cls.images_client.create_image(server_id, name)
|
||||||
resp, image = cls.images_client.create_image(server_id, name)
|
|
||||||
elif cls._api_version == 3:
|
|
||||||
resp, image = cls.servers_client.create_image(server_id, name)
|
|
||||||
image_id = data_utils.parse_image_id(resp['location'])
|
image_id = data_utils.parse_image_id(resp['location'])
|
||||||
cls.images.append(image_id)
|
cls.images.append(image_id)
|
||||||
|
|
||||||
if 'wait_until' in kwargs:
|
if 'wait_until' in kwargs:
|
||||||
cls.images_client.wait_for_image_status(image_id,
|
cls.images_client.wait_for_image_status(image_id,
|
||||||
kwargs['wait_until'])
|
kwargs['wait_until'])
|
||||||
if cls._api_version == 2:
|
resp, image = cls.images_client.get_image(image_id)
|
||||||
resp, image = cls.images_client.get_image(image_id)
|
|
||||||
elif cls._api_version == 3:
|
|
||||||
resp, image = cls.images_client.get_image_meta(image_id)
|
|
||||||
|
|
||||||
if kwargs['wait_until'] == 'ACTIVE':
|
if kwargs['wait_until'] == 'ACTIVE':
|
||||||
if kwargs.get('wait_for_server', True):
|
if kwargs.get('wait_for_server', True):
|
||||||
@ -347,19 +318,13 @@ class BaseComputeTest(tempest.test.BaseTestCase):
|
|||||||
except Exception:
|
except Exception:
|
||||||
LOG.exception('Failed to delete server %s' % server_id)
|
LOG.exception('Failed to delete server %s' % server_id)
|
||||||
resp, server = cls.create_test_server(wait_until='ACTIVE', **kwargs)
|
resp, server = cls.create_test_server(wait_until='ACTIVE', **kwargs)
|
||||||
if cls._api_version == 2:
|
cls.password = server['adminPass']
|
||||||
cls.password = server['adminPass']
|
|
||||||
elif cls._api_version == 3:
|
|
||||||
cls.password = server['admin_password']
|
|
||||||
return server['id']
|
return server['id']
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def delete_volume(cls, volume_id):
|
def delete_volume(cls, volume_id):
|
||||||
"""Deletes the given volume and waits for it to be gone."""
|
"""Deletes the given volume and waits for it to be gone."""
|
||||||
if cls._api_version == 2:
|
cls._delete_volume(cls.volumes_extensions_client, volume_id)
|
||||||
cls._delete_volume(cls.volumes_extensions_client, volume_id)
|
|
||||||
elif cls._api_version == 3:
|
|
||||||
cls._delete_volume(cls.volumes_client, volume_id)
|
|
||||||
|
|
||||||
|
|
||||||
class BaseV2ComputeTest(BaseComputeTest):
|
class BaseV2ComputeTest(BaseComputeTest):
|
||||||
@ -367,11 +332,6 @@ class BaseV2ComputeTest(BaseComputeTest):
|
|||||||
_interface = "json"
|
_interface = "json"
|
||||||
|
|
||||||
|
|
||||||
class BaseV3ComputeTest(BaseComputeTest):
|
|
||||||
_api_version = 3
|
|
||||||
_interface = "json"
|
|
||||||
|
|
||||||
|
|
||||||
class BaseComputeAdminTest(BaseComputeTest):
|
class BaseComputeAdminTest(BaseComputeTest):
|
||||||
"""Base test case class for Compute Admin API tests."""
|
"""Base test case class for Compute Admin API tests."""
|
||||||
_interface = "json"
|
_interface = "json"
|
||||||
@ -387,29 +347,10 @@ class BaseComputeAdminTest(BaseComputeTest):
|
|||||||
msg = ("Missing Compute Admin API credentials in configuration.")
|
msg = ("Missing Compute Admin API credentials in configuration.")
|
||||||
raise cls.skipException(msg)
|
raise cls.skipException(msg)
|
||||||
|
|
||||||
if cls._api_version == 2:
|
cls.availability_zone_admin_client = (
|
||||||
cls.availability_zone_admin_client = (
|
cls.os_adm.availability_zone_client)
|
||||||
cls.os_adm.availability_zone_client)
|
|
||||||
|
|
||||||
else:
|
|
||||||
cls.servers_admin_client = cls.os_adm.servers_v3_client
|
|
||||||
cls.services_admin_client = cls.os_adm.services_v3_client
|
|
||||||
cls.availability_zone_admin_client = \
|
|
||||||
cls.os_adm.availability_zone_v3_client
|
|
||||||
cls.hypervisor_admin_client = cls.os_adm.hypervisor_v3_client
|
|
||||||
cls.flavors_admin_client = cls.os_adm.flavors_v3_client
|
|
||||||
cls.aggregates_admin_client = cls.os_adm.aggregates_v3_client
|
|
||||||
cls.hosts_admin_client = cls.os_adm.hosts_v3_client
|
|
||||||
cls.quotas_admin_client = cls.os_adm.quotas_v3_client
|
|
||||||
cls.agents_admin_client = cls.os_adm.agents_v3_client
|
|
||||||
cls.migrations_admin_client = cls.os_adm.migrations_v3_client
|
|
||||||
|
|
||||||
|
|
||||||
class BaseV2ComputeAdminTest(BaseComputeAdminTest):
|
class BaseV2ComputeAdminTest(BaseComputeAdminTest):
|
||||||
"""Base test case class for Compute Admin V2 API tests."""
|
"""Base test case class for Compute Admin V2 API tests."""
|
||||||
_api_version = 2
|
_api_version = 2
|
||||||
|
|
||||||
|
|
||||||
class BaseV3ComputeAdminTest(BaseComputeAdminTest):
|
|
||||||
"""Base test case class for Compute Admin V3 API tests."""
|
|
||||||
_api_version = 3
|
|
||||||
|
@ -17,9 +17,9 @@ from tempest.api.compute import base
|
|||||||
from tempest import test
|
from tempest import test
|
||||||
|
|
||||||
|
|
||||||
class CertificatesV3Test(base.BaseComputeTest):
|
class CertificatesV2TestJSON(base.BaseComputeTest):
|
||||||
|
|
||||||
_api_version = 3
|
_api_version = 2
|
||||||
|
|
||||||
@test.attr(type='gate')
|
@test.attr(type='gate')
|
||||||
def test_create_root_certificate(self):
|
def test_create_root_certificate(self):
|
||||||
@ -35,7 +35,3 @@ class CertificatesV3Test(base.BaseComputeTest):
|
|||||||
self.assertEqual(200, resp.status)
|
self.assertEqual(200, resp.status)
|
||||||
self.assertIn('data', body)
|
self.assertIn('data', body)
|
||||||
self.assertIn('private_key', body)
|
self.assertIn('private_key', body)
|
||||||
|
|
||||||
|
|
||||||
class CertificatesV2TestJSON(CertificatesV3Test):
|
|
||||||
_api_version = 2
|
|
||||||
|
@ -17,15 +17,15 @@ from tempest.api.compute import base
|
|||||||
from tempest import test
|
from tempest import test
|
||||||
|
|
||||||
|
|
||||||
class FlavorsV3Test(base.BaseComputeTest):
|
class FlavorsV2TestJSON(base.BaseComputeTest):
|
||||||
|
|
||||||
_api_version = 3
|
_api_version = 2
|
||||||
_min_disk = 'min_disk'
|
_min_disk = 'minDisk'
|
||||||
_min_ram = 'min_ram'
|
_min_ram = 'minRam'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def resource_setup(cls):
|
def resource_setup(cls):
|
||||||
super(FlavorsV3Test, cls).resource_setup()
|
super(FlavorsV2TestJSON, cls).resource_setup()
|
||||||
cls.client = cls.flavors_client
|
cls.client = cls.flavors_client
|
||||||
|
|
||||||
@test.attr(type='smoke')
|
@test.attr(type='smoke')
|
||||||
@ -125,10 +125,3 @@ class FlavorsV3Test(base.BaseComputeTest):
|
|||||||
params = {self._min_ram: flavor['ram'] + 1}
|
params = {self._min_ram: flavor['ram'] + 1}
|
||||||
resp, flavors = self.client.list_flavors(params)
|
resp, flavors = self.client.list_flavors(params)
|
||||||
self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]))
|
self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]))
|
||||||
|
|
||||||
|
|
||||||
class FlavorsV2TestJSON(FlavorsV3Test):
|
|
||||||
|
|
||||||
_api_version = 2
|
|
||||||
_min_disk = 'minDisk'
|
|
||||||
_min_ram = 'minRam'
|
|
||||||
|
@ -18,13 +18,13 @@ from tempest.common.utils import data_utils
|
|||||||
from tempest import test
|
from tempest import test
|
||||||
|
|
||||||
|
|
||||||
class KeyPairsV3Test(base.BaseComputeTest):
|
class KeyPairsV2TestJSON(base.BaseComputeTest):
|
||||||
|
|
||||||
_api_version = 3
|
_api_version = 2
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def resource_setup(cls):
|
def resource_setup(cls):
|
||||||
super(KeyPairsV3Test, cls).resource_setup()
|
super(KeyPairsV2TestJSON, cls).resource_setup()
|
||||||
cls.client = cls.keypairs_client
|
cls.client = cls.keypairs_client
|
||||||
|
|
||||||
def _delete_keypair(self, keypair_name):
|
def _delete_keypair(self, keypair_name):
|
||||||
@ -113,7 +113,3 @@ class KeyPairsV3Test(base.BaseComputeTest):
|
|||||||
self.assertEqual(key_name, k_name,
|
self.assertEqual(key_name, k_name,
|
||||||
"The created keypair name is not equal "
|
"The created keypair name is not equal "
|
||||||
"to the requested name!")
|
"to the requested name!")
|
||||||
|
|
||||||
|
|
||||||
class KeyPairsV2TestJSON(KeyPairsV3Test):
|
|
||||||
_api_version = 2
|
|
||||||
|
@ -17,15 +17,15 @@ from tempest.api.compute import base
|
|||||||
from tempest import test
|
from tempest import test
|
||||||
|
|
||||||
|
|
||||||
class AZV3Test(base.BaseComputeTest):
|
class AZV2TestJSON(base.BaseComputeTest):
|
||||||
"""
|
"""
|
||||||
Tests Availability Zone API List
|
Tests Availability Zone API List
|
||||||
"""
|
"""
|
||||||
_api_version = 3
|
_api_version = 2
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def resource_setup(cls):
|
def resource_setup(cls):
|
||||||
super(AZV3Test, cls).resource_setup()
|
super(AZV2TestJSON, cls).resource_setup()
|
||||||
cls.client = cls.availability_zone_client
|
cls.client = cls.availability_zone_client
|
||||||
|
|
||||||
@test.attr(type='gate')
|
@test.attr(type='gate')
|
||||||
@ -34,7 +34,3 @@ class AZV3Test(base.BaseComputeTest):
|
|||||||
resp, availability_zone = self.client.get_availability_zone_list()
|
resp, availability_zone = self.client.get_availability_zone_list()
|
||||||
self.assertEqual(200, resp.status)
|
self.assertEqual(200, resp.status)
|
||||||
self.assertTrue(len(availability_zone) > 0)
|
self.assertTrue(len(availability_zone) > 0)
|
||||||
|
|
||||||
|
|
||||||
class AZV2TestJSON(AZV3Test):
|
|
||||||
_api_version = 2
|
|
||||||
|
@ -1,91 +0,0 @@
|
|||||||
# 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.
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class AgentsAdminV3Test(base.BaseV3ComputeAdminTest):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Tests Agents API that require admin privileges
|
|
||||||
"""
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(AgentsAdminV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.agents_admin_client
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_create_update_list_delete_agents(self):
|
|
||||||
|
|
||||||
"""
|
|
||||||
1. Create 2 agents.
|
|
||||||
2. Update one of the agents.
|
|
||||||
3. List all agent builds.
|
|
||||||
4. List the agent builds by the filter.
|
|
||||||
5. Delete agents.
|
|
||||||
"""
|
|
||||||
params_kvm = expected_kvm = {'hypervisor': 'kvm',
|
|
||||||
'os': 'win',
|
|
||||||
'architecture': 'x86',
|
|
||||||
'version': '7.0',
|
|
||||||
'url': 'xxx://xxxx/xxx/xxx',
|
|
||||||
'md5hash': ("""add6bb58e139be103324d04d"""
|
|
||||||
"""82d8f545""")}
|
|
||||||
|
|
||||||
resp, agent_kvm = self.client.create_agent(**params_kvm)
|
|
||||||
self.assertEqual(201, resp.status)
|
|
||||||
for expected_item, value in expected_kvm.items():
|
|
||||||
self.assertEqual(value, agent_kvm[expected_item])
|
|
||||||
|
|
||||||
params_xen = expected_xen = {'hypervisor': 'xen',
|
|
||||||
'os': 'linux',
|
|
||||||
'architecture': 'x86',
|
|
||||||
'version': '7.0',
|
|
||||||
'url': 'xxx://xxxx/xxx/xxx1',
|
|
||||||
'md5hash': """add6bb58e139be103324d04d8"""
|
|
||||||
"""2d8f546"""}
|
|
||||||
|
|
||||||
resp, agent_xen = self.client.create_agent(**params_xen)
|
|
||||||
self.assertEqual(201, resp.status)
|
|
||||||
|
|
||||||
for expected_item, value in expected_xen.items():
|
|
||||||
self.assertEqual(value, agent_xen[expected_item])
|
|
||||||
|
|
||||||
params_kvm_new = expected_kvm_new = {'version': '8.0',
|
|
||||||
'url': 'xxx://xxxx/xxx/xxx2',
|
|
||||||
'md5hash': """add6bb58e139be103"""
|
|
||||||
"""324d04d82d8f547"""}
|
|
||||||
|
|
||||||
resp, resp_agent_kvm = self.client.update_agent(agent_kvm['agent_id'],
|
|
||||||
**params_kvm_new)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
for expected_item, value in expected_kvm_new.items():
|
|
||||||
self.assertEqual(value, resp_agent_kvm[expected_item])
|
|
||||||
|
|
||||||
resp, agents = self.client.list_agents()
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertTrue(len(agents) > 1)
|
|
||||||
|
|
||||||
params_filter = {'hypervisor': 'kvm'}
|
|
||||||
resp, agent = self.client.list_agents(params_filter)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertTrue(len(agent) > 0)
|
|
||||||
self.assertEqual('kvm', agent[0]['hypervisor'])
|
|
||||||
|
|
||||||
resp, _ = self.client.delete_agent(agent_kvm['agent_id'])
|
|
||||||
self.assertEqual(204, resp.status)
|
|
||||||
resp, _ = self.client.delete_agent(agent_xen['agent_id'])
|
|
||||||
self.assertEqual(204, resp.status)
|
|
@ -1,213 +0,0 @@
|
|||||||
# 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 tempest.api.compute import base
|
|
||||||
from tempest.common import tempest_fixtures as fixtures
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class AggregatesAdminV3Test(base.BaseV3ComputeAdminTest):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Tests Aggregates API that require admin privileges
|
|
||||||
"""
|
|
||||||
|
|
||||||
_host_key = 'os-extended-server-attributes:host'
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(AggregatesAdminV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.aggregates_admin_client
|
|
||||||
cls.aggregate_name_prefix = 'test_aggregate_'
|
|
||||||
cls.az_name_prefix = 'test_az_'
|
|
||||||
|
|
||||||
resp, hosts_all = cls.hosts_admin_client.list_hosts()
|
|
||||||
hosts = map(lambda x: x['host_name'],
|
|
||||||
filter(lambda y: y['service'] == 'compute', hosts_all))
|
|
||||||
cls.host = hosts[0]
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_aggregate_create_delete(self):
|
|
||||||
# Create and delete an aggregate.
|
|
||||||
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
|
|
||||||
resp, aggregate = self.client.create_aggregate(name=aggregate_name)
|
|
||||||
self.assertEqual(201, resp.status)
|
|
||||||
self.assertEqual(aggregate_name, aggregate['name'])
|
|
||||||
self.assertIsNone(aggregate['availability_zone'])
|
|
||||||
|
|
||||||
resp, _ = self.client.delete_aggregate(aggregate['id'])
|
|
||||||
self.assertEqual(204, resp.status)
|
|
||||||
self.client.wait_for_resource_deletion(aggregate['id'])
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_aggregate_create_delete_with_az(self):
|
|
||||||
# Create and delete an aggregate.
|
|
||||||
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
|
|
||||||
az_name = data_utils.rand_name(self.az_name_prefix)
|
|
||||||
resp, aggregate = self.client.create_aggregate(
|
|
||||||
name=aggregate_name, availability_zone=az_name)
|
|
||||||
self.assertEqual(201, resp.status)
|
|
||||||
self.assertEqual(aggregate_name, aggregate['name'])
|
|
||||||
self.assertEqual(az_name, aggregate['availability_zone'])
|
|
||||||
|
|
||||||
resp, _ = self.client.delete_aggregate(aggregate['id'])
|
|
||||||
self.assertEqual(204, resp.status)
|
|
||||||
self.client.wait_for_resource_deletion(aggregate['id'])
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_aggregate_create_verify_entry_in_list(self):
|
|
||||||
# Create an aggregate and ensure it is listed.
|
|
||||||
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
|
|
||||||
resp, aggregate = self.client.create_aggregate(name=aggregate_name)
|
|
||||||
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
|
|
||||||
|
|
||||||
resp, aggregates = self.client.list_aggregates()
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertIn((aggregate['id'], aggregate['availability_zone']),
|
|
||||||
map(lambda x: (x['id'], x['availability_zone']),
|
|
||||||
aggregates))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_aggregate_create_update_metadata_get_details(self):
|
|
||||||
# Create an aggregate and ensure its details are returned.
|
|
||||||
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
|
|
||||||
resp, aggregate = self.client.create_aggregate(name=aggregate_name)
|
|
||||||
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
|
|
||||||
|
|
||||||
resp, body = self.client.get_aggregate(aggregate['id'])
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(aggregate['name'], body['name'])
|
|
||||||
self.assertEqual(aggregate['availability_zone'],
|
|
||||||
body['availability_zone'])
|
|
||||||
self.assertEqual({}, body["metadata"])
|
|
||||||
|
|
||||||
# set the metadata of the aggregate
|
|
||||||
meta = {"key": "value"}
|
|
||||||
resp, body = self.client.set_metadata(aggregate['id'], meta)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(meta, body["metadata"])
|
|
||||||
|
|
||||||
# verify the metadata has been set
|
|
||||||
resp, body = self.client.get_aggregate(aggregate['id'])
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(meta, body["metadata"])
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_aggregate_create_update_with_az(self):
|
|
||||||
# Update an aggregate and ensure properties are updated correctly
|
|
||||||
self.useFixture(fixtures.LockFixture('availability_zone'))
|
|
||||||
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
|
|
||||||
az_name = data_utils.rand_name(self.az_name_prefix)
|
|
||||||
resp, aggregate = self.client.create_aggregate(
|
|
||||||
name=aggregate_name, availability_zone=az_name)
|
|
||||||
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
|
|
||||||
|
|
||||||
self.assertEqual(201, resp.status)
|
|
||||||
self.assertEqual(aggregate_name, aggregate['name'])
|
|
||||||
self.assertEqual(az_name, aggregate['availability_zone'])
|
|
||||||
self.assertIsNotNone(aggregate['id'])
|
|
||||||
|
|
||||||
aggregate_id = aggregate['id']
|
|
||||||
new_aggregate_name = aggregate_name + '_new'
|
|
||||||
new_az_name = az_name + '_new'
|
|
||||||
|
|
||||||
resp, resp_aggregate = self.client.update_aggregate(aggregate_id,
|
|
||||||
new_aggregate_name,
|
|
||||||
new_az_name)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(new_aggregate_name, resp_aggregate['name'])
|
|
||||||
self.assertEqual(new_az_name, resp_aggregate['availability_zone'])
|
|
||||||
|
|
||||||
resp, aggregates = self.client.list_aggregates()
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertIn((aggregate_id, new_aggregate_name, new_az_name),
|
|
||||||
map(lambda x:
|
|
||||||
(x['id'], x['name'], x['availability_zone']),
|
|
||||||
aggregates))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_aggregate_add_remove_host(self):
|
|
||||||
# Add an host to the given aggregate and remove.
|
|
||||||
self.useFixture(fixtures.LockFixture('availability_zone'))
|
|
||||||
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
|
|
||||||
resp, aggregate = self.client.create_aggregate(name=aggregate_name)
|
|
||||||
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
|
|
||||||
|
|
||||||
resp, body = self.client.add_host(aggregate['id'], self.host)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.assertEqual(aggregate_name, body['name'])
|
|
||||||
self.assertEqual(aggregate['availability_zone'],
|
|
||||||
body['availability_zone'])
|
|
||||||
self.assertIn(self.host, body['hosts'])
|
|
||||||
|
|
||||||
resp, body = self.client.remove_host(aggregate['id'], self.host)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.assertEqual(aggregate_name, body['name'])
|
|
||||||
self.assertEqual(aggregate['availability_zone'],
|
|
||||||
body['availability_zone'])
|
|
||||||
self.assertNotIn(self.host, body['hosts'])
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_aggregate_add_host_list(self):
|
|
||||||
# Add an host to the given aggregate and list.
|
|
||||||
self.useFixture(fixtures.LockFixture('availability_zone'))
|
|
||||||
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
|
|
||||||
resp, aggregate = self.client.create_aggregate(name=aggregate_name)
|
|
||||||
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
|
|
||||||
self.client.add_host(aggregate['id'], self.host)
|
|
||||||
self.addCleanup(self.client.remove_host, aggregate['id'], self.host)
|
|
||||||
|
|
||||||
resp, aggregates = self.client.list_aggregates()
|
|
||||||
aggs = filter(lambda x: x['id'] == aggregate['id'], aggregates)
|
|
||||||
self.assertEqual(1, len(aggs))
|
|
||||||
agg = aggs[0]
|
|
||||||
self.assertEqual(aggregate_name, agg['name'])
|
|
||||||
self.assertIsNone(agg['availability_zone'])
|
|
||||||
self.assertIn(self.host, agg['hosts'])
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_aggregate_add_host_get_details(self):
|
|
||||||
# Add an host to the given aggregate and get details.
|
|
||||||
self.useFixture(fixtures.LockFixture('availability_zone'))
|
|
||||||
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
|
|
||||||
resp, aggregate = self.client.create_aggregate(name=aggregate_name)
|
|
||||||
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
|
|
||||||
self.client.add_host(aggregate['id'], self.host)
|
|
||||||
self.addCleanup(self.client.remove_host, aggregate['id'], self.host)
|
|
||||||
|
|
||||||
resp, body = self.client.get_aggregate(aggregate['id'])
|
|
||||||
self.assertEqual(aggregate_name, body['name'])
|
|
||||||
self.assertIsNone(body['availability_zone'])
|
|
||||||
self.assertIn(self.host, body['hosts'])
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_aggregate_add_host_create_server_with_az(self):
|
|
||||||
# Add an host to the given aggregate and create a server.
|
|
||||||
self.useFixture(fixtures.LockFixture('availability_zone'))
|
|
||||||
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
|
|
||||||
az_name = data_utils.rand_name(self.az_name_prefix)
|
|
||||||
resp, aggregate = self.client.create_aggregate(
|
|
||||||
name=aggregate_name, availability_zone=az_name)
|
|
||||||
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
|
|
||||||
self.client.add_host(aggregate['id'], self.host)
|
|
||||||
self.addCleanup(self.client.remove_host, aggregate['id'], self.host)
|
|
||||||
server_name = data_utils.rand_name('test_server_')
|
|
||||||
admin_servers_client = self.servers_admin_client
|
|
||||||
resp, server = self.create_test_server(name=server_name,
|
|
||||||
availability_zone=az_name,
|
|
||||||
wait_until='ACTIVE')
|
|
||||||
resp, body = admin_servers_client.get_server(server['id'])
|
|
||||||
self.assertEqual(self.host, body[self._host_key])
|
|
@ -1,188 +0,0 @@
|
|||||||
# Copyright 2013 Huawei Technologies Co.,LTD.
|
|
||||||
# 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.api.compute import base
|
|
||||||
from tempest.common import tempest_fixtures as fixtures
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class AggregatesAdminNegativeV3Test(base.BaseV3ComputeAdminTest):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Tests Aggregates API that require admin privileges
|
|
||||||
"""
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(AggregatesAdminNegativeV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.aggregates_admin_client
|
|
||||||
cls.user_client = cls.aggregates_client
|
|
||||||
cls.aggregate_name_prefix = 'test_aggregate_'
|
|
||||||
cls.az_name_prefix = 'test_az_'
|
|
||||||
|
|
||||||
resp, hosts_all = cls.hosts_admin_client.list_hosts()
|
|
||||||
hosts = map(lambda x: x['host_name'],
|
|
||||||
filter(lambda y: y['service'] == 'compute', hosts_all))
|
|
||||||
cls.host = hosts[0]
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_aggregate_create_as_user(self):
|
|
||||||
# Regular user is not allowed to create an aggregate.
|
|
||||||
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
|
|
||||||
self.assertRaises(exceptions.Unauthorized,
|
|
||||||
self.user_client.create_aggregate,
|
|
||||||
name=aggregate_name)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_aggregate_create_aggregate_name_length_less_than_1(self):
|
|
||||||
# the length of aggregate name should >= 1 and <=255
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.create_aggregate,
|
|
||||||
name='')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_aggregate_create_aggregate_name_length_exceeds_255(self):
|
|
||||||
# the length of aggregate name should >= 1 and <=255
|
|
||||||
aggregate_name = 'a' * 256
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.create_aggregate,
|
|
||||||
name=aggregate_name)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_aggregate_create_with_existent_aggregate_name(self):
|
|
||||||
# creating an aggregate with existent aggregate name is forbidden
|
|
||||||
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
|
|
||||||
resp, aggregate = self.client.create_aggregate(name=aggregate_name)
|
|
||||||
self.assertEqual(201, resp.status)
|
|
||||||
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.Conflict,
|
|
||||||
self.client.create_aggregate,
|
|
||||||
name=aggregate_name)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_aggregate_delete_as_user(self):
|
|
||||||
# Regular user is not allowed to delete an aggregate.
|
|
||||||
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
|
|
||||||
resp, aggregate = self.client.create_aggregate(name=aggregate_name)
|
|
||||||
self.assertEqual(201, resp.status)
|
|
||||||
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.Unauthorized,
|
|
||||||
self.user_client.delete_aggregate,
|
|
||||||
aggregate['id'])
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_aggregate_list_as_user(self):
|
|
||||||
# Regular user is not allowed to list aggregates.
|
|
||||||
self.assertRaises(exceptions.Unauthorized,
|
|
||||||
self.user_client.list_aggregates)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_aggregate_get_details_as_user(self):
|
|
||||||
# Regular user is not allowed to get aggregate details.
|
|
||||||
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
|
|
||||||
resp, aggregate = self.client.create_aggregate(name=aggregate_name)
|
|
||||||
self.assertEqual(201, resp.status)
|
|
||||||
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.Unauthorized,
|
|
||||||
self.user_client.get_aggregate,
|
|
||||||
aggregate['id'])
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_aggregate_delete_with_invalid_id(self):
|
|
||||||
# Delete an aggregate with invalid id should raise exceptions.
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.delete_aggregate, -1)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_aggregate_get_details_with_invalid_id(self):
|
|
||||||
# Get aggregate details with invalid id should raise exceptions.
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.get_aggregate, -1)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_aggregate_add_non_exist_host(self):
|
|
||||||
# Adding a non-exist host to an aggregate should raise exceptions.
|
|
||||||
resp, hosts_all = self.hosts_admin_client.list_hosts()
|
|
||||||
hosts = map(lambda x: x['host_name'], hosts_all)
|
|
||||||
while True:
|
|
||||||
non_exist_host = data_utils.rand_name('nonexist_host_')
|
|
||||||
if non_exist_host not in hosts:
|
|
||||||
break
|
|
||||||
|
|
||||||
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
|
|
||||||
resp, aggregate = self.client.create_aggregate(name=aggregate_name)
|
|
||||||
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.NotFound, self.client.add_host,
|
|
||||||
aggregate['id'], non_exist_host)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_aggregate_add_host_as_user(self):
|
|
||||||
# Regular user is not allowed to add a host to an aggregate.
|
|
||||||
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
|
|
||||||
resp, aggregate = self.client.create_aggregate(name=aggregate_name)
|
|
||||||
self.assertEqual(201, resp.status)
|
|
||||||
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.Unauthorized,
|
|
||||||
self.user_client.add_host,
|
|
||||||
aggregate['id'], self.host)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_aggregate_add_existent_host(self):
|
|
||||||
self.useFixture(fixtures.LockFixture('availability_zone'))
|
|
||||||
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
|
|
||||||
resp, aggregate = self.client.create_aggregate(name=aggregate_name)
|
|
||||||
self.assertEqual(201, resp.status)
|
|
||||||
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
|
|
||||||
|
|
||||||
resp, body = self.client.add_host(aggregate['id'], self.host)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.addCleanup(self.client.remove_host, aggregate['id'], self.host)
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.Conflict, self.client.add_host,
|
|
||||||
aggregate['id'], self.host)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_aggregate_remove_host_as_user(self):
|
|
||||||
# Regular user is not allowed to remove a host from an aggregate.
|
|
||||||
self.useFixture(fixtures.LockFixture('availability_zone'))
|
|
||||||
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
|
|
||||||
resp, aggregate = self.client.create_aggregate(name=aggregate_name)
|
|
||||||
self.assertEqual(201, resp.status)
|
|
||||||
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
|
|
||||||
resp, body = self.client.add_host(aggregate['id'], self.host)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.addCleanup(self.client.remove_host, aggregate['id'], self.host)
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.Unauthorized,
|
|
||||||
self.user_client.remove_host,
|
|
||||||
aggregate['id'], self.host)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_aggregate_remove_nonexistent_host(self):
|
|
||||||
non_exist_host = data_utils.rand_name('nonexist_host_')
|
|
||||||
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
|
|
||||||
resp, aggregate = self.client.create_aggregate(name=aggregate_name)
|
|
||||||
self.assertEqual(201, resp.status)
|
|
||||||
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.NotFound, self.client.remove_host,
|
|
||||||
aggregate['id'], non_exist_host)
|
|
@ -1,39 +0,0 @@
|
|||||||
# 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 tempest.api.compute import base
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class AZAdminNegativeV3Test(base.BaseV3ComputeAdminTest):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Tests Availability Zone API List
|
|
||||||
"""
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(AZAdminNegativeV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.availability_zone_admin_client
|
|
||||||
cls.non_adm_client = cls.availability_zone_client
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_get_availability_zone_list_detail_with_non_admin_user(self):
|
|
||||||
# List of availability zones and available services with
|
|
||||||
# non-administrator user
|
|
||||||
self.assertRaises(
|
|
||||||
exceptions.Unauthorized,
|
|
||||||
self.non_adm_client.get_availability_zone_list_detail)
|
|
@ -1,308 +0,0 @@
|
|||||||
# Copyright 2012 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 uuid
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class FlavorsAdminV3Test(base.BaseV3ComputeAdminTest):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Tests Flavors API Create and Delete that require admin privileges
|
|
||||||
"""
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(FlavorsAdminV3Test, cls).resource_setup()
|
|
||||||
|
|
||||||
cls.client = cls.flavors_admin_client
|
|
||||||
cls.user_client = cls.flavors_client
|
|
||||||
cls.flavor_name_prefix = 'test_flavor_'
|
|
||||||
cls.ram = 512
|
|
||||||
cls.vcpus = 1
|
|
||||||
cls.disk = 10
|
|
||||||
cls.ephemeral = 10
|
|
||||||
cls.swap = 1024
|
|
||||||
cls.rxtx = 2
|
|
||||||
|
|
||||||
def flavor_clean_up(self, flavor_id):
|
|
||||||
resp, body = self.client.delete_flavor(flavor_id)
|
|
||||||
self.assertEqual(resp.status, 204)
|
|
||||||
self.client.wait_for_resource_deletion(flavor_id)
|
|
||||||
|
|
||||||
def _create_flavor(self, flavor_id):
|
|
||||||
# Create a flavor and ensure it is listed
|
|
||||||
# This operation requires the user to have 'admin' role
|
|
||||||
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
|
|
||||||
# Create the flavor
|
|
||||||
resp, flavor = self.client.create_flavor(flavor_name,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
flavor_id,
|
|
||||||
ephemeral=self.ephemeral,
|
|
||||||
swap=self.swap,
|
|
||||||
rxtx=self.rxtx)
|
|
||||||
self.addCleanup(self.flavor_clean_up, flavor['id'])
|
|
||||||
self.assertEqual(201, resp.status)
|
|
||||||
self.assertEqual(flavor['name'], flavor_name)
|
|
||||||
self.assertEqual(flavor['vcpus'], self.vcpus)
|
|
||||||
self.assertEqual(flavor['disk'], self.disk)
|
|
||||||
self.assertEqual(flavor['ram'], self.ram)
|
|
||||||
self.assertEqual(flavor['swap'], self.swap)
|
|
||||||
if test.is_extension_enabled("os-flavor-rxtx", "compute_v3"):
|
|
||||||
self.assertEqual(flavor['os-flavor-rxtx:rxtx_factor'], self.rxtx)
|
|
||||||
self.assertEqual(flavor['ephemeral'],
|
|
||||||
self.ephemeral)
|
|
||||||
self.assertEqual(flavor['flavor-access:is_public'], True)
|
|
||||||
|
|
||||||
# Verify flavor is retrieved
|
|
||||||
resp, flavor = self.client.get_flavor_details(flavor['id'])
|
|
||||||
self.assertEqual(resp.status, 200)
|
|
||||||
self.assertEqual(flavor['name'], flavor_name)
|
|
||||||
|
|
||||||
return flavor['id']
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_create_flavor_with_int_id(self):
|
|
||||||
flavor_id = data_utils.rand_int_id(start=1000)
|
|
||||||
new_flavor_id = self._create_flavor(flavor_id)
|
|
||||||
self.assertEqual(new_flavor_id, str(flavor_id))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_create_flavor_with_uuid_id(self):
|
|
||||||
flavor_id = str(uuid.uuid4())
|
|
||||||
new_flavor_id = self._create_flavor(flavor_id)
|
|
||||||
self.assertEqual(new_flavor_id, flavor_id)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_create_flavor_with_none_id(self):
|
|
||||||
# If nova receives a request with None as flavor_id,
|
|
||||||
# nova generates flavor_id of uuid.
|
|
||||||
flavor_id = None
|
|
||||||
new_flavor_id = self._create_flavor(flavor_id)
|
|
||||||
self.assertEqual(new_flavor_id, str(uuid.UUID(new_flavor_id)))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_create_flavor_verify_entry_in_list_details(self):
|
|
||||||
# Create a flavor and ensure it's details are listed
|
|
||||||
# This operation requires the user to have 'admin' role
|
|
||||||
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
new_flavor_id = data_utils.rand_int_id(start=1000)
|
|
||||||
|
|
||||||
# Create the flavor
|
|
||||||
resp, flavor = self.client.create_flavor(flavor_name,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
new_flavor_id,
|
|
||||||
ephemeral=self.ephemeral,
|
|
||||||
swap=self.swap,
|
|
||||||
rxtx=self.rxtx)
|
|
||||||
self.addCleanup(self.flavor_clean_up, flavor['id'])
|
|
||||||
flag = False
|
|
||||||
# Verify flavor is retrieved
|
|
||||||
resp, flavors = self.client.list_flavors_with_detail()
|
|
||||||
self.assertEqual(resp.status, 200)
|
|
||||||
for flavor in flavors:
|
|
||||||
if flavor['name'] == flavor_name:
|
|
||||||
flag = True
|
|
||||||
self.assertTrue(flag)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_create_list_flavor_without_extra_data(self):
|
|
||||||
# Create a flavor and ensure it is listed
|
|
||||||
# This operation requires the user to have 'admin' role
|
|
||||||
|
|
||||||
def verify_flavor_response_extension(flavor):
|
|
||||||
# check some extensions for the flavor create/show/detail response
|
|
||||||
self.assertEqual(flavor['swap'], 0)
|
|
||||||
if test.is_extension_enabled("os-flavor-rxtx", "compute_v3"):
|
|
||||||
self.assertEqual(int(flavor['os-flavor-rxtx:rxtx_factor']), 1)
|
|
||||||
self.assertEqual(int(flavor['ephemeral']), 0)
|
|
||||||
self.assertEqual(flavor['flavor-access:is_public'], True)
|
|
||||||
|
|
||||||
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
new_flavor_id = data_utils.rand_int_id(start=1000)
|
|
||||||
|
|
||||||
# Create the flavor
|
|
||||||
resp, flavor = self.client.create_flavor(flavor_name,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
new_flavor_id)
|
|
||||||
self.addCleanup(self.flavor_clean_up, flavor['id'])
|
|
||||||
self.assertEqual(201, resp.status)
|
|
||||||
self.assertEqual(flavor['name'], flavor_name)
|
|
||||||
self.assertEqual(flavor['ram'], self.ram)
|
|
||||||
self.assertEqual(flavor['vcpus'], self.vcpus)
|
|
||||||
self.assertEqual(flavor['disk'], self.disk)
|
|
||||||
self.assertEqual(int(flavor['id']), new_flavor_id)
|
|
||||||
verify_flavor_response_extension(flavor)
|
|
||||||
|
|
||||||
# Verify flavor is retrieved
|
|
||||||
resp, flavor = self.client.get_flavor_details(new_flavor_id)
|
|
||||||
self.assertEqual(resp.status, 200)
|
|
||||||
self.assertEqual(flavor['name'], flavor_name)
|
|
||||||
verify_flavor_response_extension(flavor)
|
|
||||||
|
|
||||||
# Check if flavor is present in list
|
|
||||||
resp, flavors = self.user_client.list_flavors_with_detail()
|
|
||||||
self.assertEqual(resp.status, 200)
|
|
||||||
for flavor in flavors:
|
|
||||||
if flavor['name'] == flavor_name:
|
|
||||||
verify_flavor_response_extension(flavor)
|
|
||||||
flag = True
|
|
||||||
self.assertTrue(flag)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_non_public_flavor(self):
|
|
||||||
# Create a flavor with os-flavor-access:is_public false should
|
|
||||||
# be present in list_details.
|
|
||||||
# This operation requires the user to have 'admin' role
|
|
||||||
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
new_flavor_id = data_utils.rand_int_id(start=1000)
|
|
||||||
|
|
||||||
# Create the flavor
|
|
||||||
resp, flavor = self.client.create_flavor(flavor_name,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
new_flavor_id,
|
|
||||||
is_public="False")
|
|
||||||
self.addCleanup(self.flavor_clean_up, flavor['id'])
|
|
||||||
# Verify flavor is retrieved
|
|
||||||
flag = False
|
|
||||||
resp, flavors = self.client.list_flavors_with_detail()
|
|
||||||
self.assertEqual(resp.status, 200)
|
|
||||||
for flavor in flavors:
|
|
||||||
if flavor['name'] == flavor_name:
|
|
||||||
flag = True
|
|
||||||
self.assertTrue(flag)
|
|
||||||
|
|
||||||
# Verify flavor is not retrieved with other user
|
|
||||||
flag = False
|
|
||||||
resp, flavors = self.user_client.list_flavors_with_detail()
|
|
||||||
self.assertEqual(resp.status, 200)
|
|
||||||
for flavor in flavors:
|
|
||||||
if flavor['name'] == flavor_name:
|
|
||||||
flag = True
|
|
||||||
self.assertFalse(flag)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_create_server_with_non_public_flavor(self):
|
|
||||||
# Create a flavor with os-flavor-access:is_public false
|
|
||||||
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
new_flavor_id = data_utils.rand_int_id(start=1000)
|
|
||||||
|
|
||||||
# Create the flavor
|
|
||||||
resp, flavor = self.client.create_flavor(flavor_name,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
new_flavor_id,
|
|
||||||
is_public="False")
|
|
||||||
self.addCleanup(self.flavor_clean_up, flavor['id'])
|
|
||||||
self.assertEqual(201, resp.status)
|
|
||||||
|
|
||||||
# Verify flavor is not used by other user
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.servers_client.create_server,
|
|
||||||
'test', self.image_ref, flavor['id'])
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_public_flavor_with_other_user(self):
|
|
||||||
# Create a Flavor with public access.
|
|
||||||
# Try to List/Get flavor with another user
|
|
||||||
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
new_flavor_id = data_utils.rand_int_id(start=1000)
|
|
||||||
|
|
||||||
# Create the flavor
|
|
||||||
resp, flavor = self.client.create_flavor(flavor_name,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
new_flavor_id,
|
|
||||||
is_public="True")
|
|
||||||
self.addCleanup(self.flavor_clean_up, flavor['id'])
|
|
||||||
flag = False
|
|
||||||
self.new_client = self.flavors_client
|
|
||||||
# Verify flavor is retrieved with new user
|
|
||||||
resp, flavors = self.new_client.list_flavors_with_detail()
|
|
||||||
self.assertEqual(resp.status, 200)
|
|
||||||
for flavor in flavors:
|
|
||||||
if flavor['name'] == flavor_name:
|
|
||||||
flag = True
|
|
||||||
self.assertTrue(flag)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_is_public_string_variations(self):
|
|
||||||
flavor_id_not_public = data_utils.rand_int_id(start=1000)
|
|
||||||
flavor_name_not_public = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
flavor_id_public = data_utils.rand_int_id(start=1000)
|
|
||||||
flavor_name_public = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
|
|
||||||
# Create a non public flavor
|
|
||||||
resp, flavor = self.client.create_flavor(flavor_name_not_public,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
flavor_id_not_public,
|
|
||||||
is_public="False")
|
|
||||||
self.addCleanup(self.flavor_clean_up, flavor['id'])
|
|
||||||
|
|
||||||
# Create a public flavor
|
|
||||||
resp, flavor = self.client.create_flavor(flavor_name_public,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
flavor_id_public,
|
|
||||||
is_public="True")
|
|
||||||
self.addCleanup(self.flavor_clean_up, flavor['id'])
|
|
||||||
|
|
||||||
def _flavor_lookup(flavors, flavor_name):
|
|
||||||
for flavor in flavors:
|
|
||||||
if flavor['name'] == flavor_name:
|
|
||||||
return flavor
|
|
||||||
return None
|
|
||||||
|
|
||||||
def _test_string_variations(variations, flavor_name):
|
|
||||||
for string in variations:
|
|
||||||
params = {'is_public': string}
|
|
||||||
r, flavors = self.client.list_flavors_with_detail(params)
|
|
||||||
self.assertEqual(r.status, 200)
|
|
||||||
flavor = _flavor_lookup(flavors, flavor_name)
|
|
||||||
self.assertIsNotNone(flavor)
|
|
||||||
|
|
||||||
_test_string_variations(['f', 'false', 'no', '0'],
|
|
||||||
flavor_name_not_public)
|
|
||||||
|
|
||||||
_test_string_variations(['t', 'true', 'yes', '1'],
|
|
||||||
flavor_name_public)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_create_flavor_using_string_ram(self):
|
|
||||||
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
new_flavor_id = data_utils.rand_int_id(start=1000)
|
|
||||||
|
|
||||||
ram = "1024"
|
|
||||||
resp, flavor = self.client.create_flavor(flavor_name,
|
|
||||||
ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
new_flavor_id)
|
|
||||||
self.addCleanup(self.flavor_clean_up, flavor['id'])
|
|
||||||
self.assertEqual(201, resp.status)
|
|
||||||
self.assertEqual(flavor['name'], flavor_name)
|
|
||||||
self.assertEqual(flavor['vcpus'], self.vcpus)
|
|
||||||
self.assertEqual(flavor['disk'], self.disk)
|
|
||||||
self.assertEqual(flavor['ram'], int(ram))
|
|
||||||
self.assertEqual(int(flavor['id']), new_flavor_id)
|
|
@ -1,95 +0,0 @@
|
|||||||
# 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 tempest.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class FlavorsAccessV3Test(base.BaseV3ComputeAdminTest):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Tests Flavor Access API extension.
|
|
||||||
Add and remove Flavor Access require admin privileges.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(FlavorsAccessV3Test, cls).resource_setup()
|
|
||||||
|
|
||||||
cls.client = cls.flavors_admin_client
|
|
||||||
admin_client = cls._get_identity_admin_client()
|
|
||||||
cls.tenant_id = cls.client.tenant_id
|
|
||||||
cls.adm_tenant_id = admin_client.tenant_id
|
|
||||||
cls.flavor_name_prefix = 'test_flavor_access_'
|
|
||||||
cls.ram = 512
|
|
||||||
cls.vcpus = 1
|
|
||||||
cls.disk = 10
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_flavor_access_list_with_private_flavor(self):
|
|
||||||
# Test to list flavor access successfully by querying private flavor
|
|
||||||
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
new_flavor_id = data_utils.rand_int_id(start=1000)
|
|
||||||
resp, new_flavor = self.client.create_flavor(flavor_name,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
new_flavor_id,
|
|
||||||
is_public='False')
|
|
||||||
self.addCleanup(self.client.delete_flavor, new_flavor['id'])
|
|
||||||
self.assertEqual(resp.status, 201)
|
|
||||||
resp, flavor_access = self.client.list_flavor_access(new_flavor_id)
|
|
||||||
self.assertEqual(resp.status, 200)
|
|
||||||
self.assertEqual(len(flavor_access), 1, str(flavor_access))
|
|
||||||
first_flavor = flavor_access[0]
|
|
||||||
self.assertEqual(str(new_flavor_id), str(first_flavor['flavor_id']))
|
|
||||||
self.assertEqual(self.adm_tenant_id, first_flavor['tenant_id'])
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_flavor_access_add_remove(self):
|
|
||||||
# Test to add and remove flavor access to a given tenant.
|
|
||||||
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
new_flavor_id = data_utils.rand_int_id(start=1000)
|
|
||||||
resp, new_flavor = self.client.create_flavor(flavor_name,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
new_flavor_id,
|
|
||||||
is_public='False')
|
|
||||||
self.addCleanup(self.client.delete_flavor, new_flavor['id'])
|
|
||||||
# Add flavor access to a tenant.
|
|
||||||
resp_body = {
|
|
||||||
"tenant_id": str(self.tenant_id),
|
|
||||||
"flavor_id": str(new_flavor['id']),
|
|
||||||
}
|
|
||||||
add_resp, add_body = \
|
|
||||||
self.client.add_flavor_access(new_flavor['id'], self.tenant_id)
|
|
||||||
self.assertEqual(add_resp.status, 200)
|
|
||||||
self.assertIn(resp_body, add_body)
|
|
||||||
|
|
||||||
# The flavor is present in list.
|
|
||||||
resp, flavors = self.flavors_client.list_flavors_with_detail()
|
|
||||||
self.assertEqual(resp.status, 200)
|
|
||||||
self.assertIn(new_flavor['id'], map(lambda x: x['id'], flavors))
|
|
||||||
|
|
||||||
# Remove flavor access from a tenant.
|
|
||||||
remove_resp, remove_body = \
|
|
||||||
self.client.remove_flavor_access(new_flavor['id'], self.tenant_id)
|
|
||||||
self.assertEqual(remove_resp.status, 200)
|
|
||||||
self.assertNotIn(resp_body, remove_body)
|
|
||||||
|
|
||||||
# The flavor is not present in list.
|
|
||||||
resp, flavors = self.flavors_client.list_flavors_with_detail()
|
|
||||||
self.assertEqual(resp.status, 200)
|
|
||||||
self.assertNotIn(new_flavor['id'], map(lambda x: x['id'], flavors))
|
|
@ -1,134 +0,0 @@
|
|||||||
# Copyright 2013 IBM 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 uuid
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class FlavorsAccessNegativeV3Test(base.BaseV3ComputeAdminTest):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Tests Flavor Access API extension.
|
|
||||||
Add and remove Flavor Access require admin privileges.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(FlavorsAccessNegativeV3Test, cls).resource_setup()
|
|
||||||
|
|
||||||
cls.client = cls.flavors_admin_client
|
|
||||||
cls.tenant_id = cls.client.tenant_id
|
|
||||||
cls.flavor_name_prefix = 'test_flavor_access_'
|
|
||||||
cls.ram = 512
|
|
||||||
cls.vcpus = 1
|
|
||||||
cls.disk = 10
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_flavor_access_list_with_public_flavor(self):
|
|
||||||
# Test to list flavor access with exceptions by querying public flavor
|
|
||||||
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
new_flavor_id = data_utils.rand_int_id(start=1000)
|
|
||||||
resp, new_flavor = self.client.create_flavor(flavor_name,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
new_flavor_id,
|
|
||||||
is_public='True')
|
|
||||||
self.addCleanup(self.client.delete_flavor, new_flavor['id'])
|
|
||||||
self.assertEqual(resp.status, 201)
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.list_flavor_access,
|
|
||||||
new_flavor_id)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_flavor_non_admin_add(self):
|
|
||||||
# Test to add flavor access as a user without admin privileges.
|
|
||||||
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
new_flavor_id = data_utils.rand_int_id(start=1000)
|
|
||||||
resp, new_flavor = self.client.create_flavor(flavor_name,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
new_flavor_id,
|
|
||||||
is_public='False')
|
|
||||||
self.addCleanup(self.client.delete_flavor, new_flavor['id'])
|
|
||||||
self.assertRaises(exceptions.Unauthorized,
|
|
||||||
self.flavors_client.add_flavor_access,
|
|
||||||
new_flavor['id'],
|
|
||||||
self.tenant_id)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_flavor_non_admin_remove(self):
|
|
||||||
# Test to remove flavor access as a user without admin privileges.
|
|
||||||
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
new_flavor_id = data_utils.rand_int_id(start=1000)
|
|
||||||
resp, new_flavor = self.client.create_flavor(flavor_name,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
new_flavor_id,
|
|
||||||
is_public='False')
|
|
||||||
self.addCleanup(self.client.delete_flavor, new_flavor['id'])
|
|
||||||
# Add flavor access to a tenant.
|
|
||||||
self.client.add_flavor_access(new_flavor['id'], self.tenant_id)
|
|
||||||
self.addCleanup(self.client.remove_flavor_access,
|
|
||||||
new_flavor['id'], self.tenant_id)
|
|
||||||
self.assertRaises(exceptions.Unauthorized,
|
|
||||||
self.flavors_client.remove_flavor_access,
|
|
||||||
new_flavor['id'],
|
|
||||||
self.tenant_id)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_add_flavor_access_duplicate(self):
|
|
||||||
# Create a new flavor.
|
|
||||||
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
new_flavor_id = data_utils.rand_int_id(start=1000)
|
|
||||||
resp, new_flavor = self.client.create_flavor(flavor_name,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
new_flavor_id,
|
|
||||||
is_public='False')
|
|
||||||
self.addCleanup(self.client.delete_flavor, new_flavor['id'])
|
|
||||||
|
|
||||||
# Add flavor access to a tenant.
|
|
||||||
self.client.add_flavor_access(new_flavor['id'], self.tenant_id)
|
|
||||||
self.addCleanup(self.client.remove_flavor_access,
|
|
||||||
new_flavor['id'], self.tenant_id)
|
|
||||||
|
|
||||||
# An exception should be raised when adding flavor access to the same
|
|
||||||
# tenant
|
|
||||||
self.assertRaises(exceptions.Conflict,
|
|
||||||
self.client.add_flavor_access,
|
|
||||||
new_flavor['id'],
|
|
||||||
self.tenant_id)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_remove_flavor_access_not_found(self):
|
|
||||||
# Create a new flavor.
|
|
||||||
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
new_flavor_id = data_utils.rand_int_id(start=1000)
|
|
||||||
resp, new_flavor = self.client.create_flavor(flavor_name,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
new_flavor_id,
|
|
||||||
is_public='False')
|
|
||||||
self.addCleanup(self.client.delete_flavor, new_flavor['id'])
|
|
||||||
|
|
||||||
# An exception should be raised when flavor access is not found
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.remove_flavor_access,
|
|
||||||
new_flavor['id'],
|
|
||||||
str(uuid.uuid4()))
|
|
@ -1,120 +0,0 @@
|
|||||||
# Copyright 2012 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.
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class FlavorsExtraSpecsV3Test(base.BaseV3ComputeAdminTest):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Tests Flavor Extra Spec API extension.
|
|
||||||
SET, UNSET, UPDATE Flavor Extra specs require admin privileges.
|
|
||||||
GET Flavor Extra specs can be performed even by without admin privileges.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(FlavorsExtraSpecsV3Test, cls).resource_setup()
|
|
||||||
|
|
||||||
cls.client = cls.flavors_admin_client
|
|
||||||
flavor_name = data_utils.rand_name('test_flavor')
|
|
||||||
ram = 512
|
|
||||||
vcpus = 1
|
|
||||||
disk = 10
|
|
||||||
ephemeral = 10
|
|
||||||
cls.new_flavor_id = data_utils.rand_int_id(start=1000)
|
|
||||||
swap = 1024
|
|
||||||
rxtx = 1
|
|
||||||
# Create a flavor so as to set/get/unset extra specs
|
|
||||||
resp, cls.flavor = cls.client.create_flavor(flavor_name,
|
|
||||||
ram, vcpus,
|
|
||||||
disk,
|
|
||||||
cls.new_flavor_id,
|
|
||||||
ephemeral=ephemeral,
|
|
||||||
swap=swap, rxtx=rxtx)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_cleanup(cls):
|
|
||||||
resp, body = cls.client.delete_flavor(cls.flavor['id'])
|
|
||||||
cls.client.wait_for_resource_deletion(cls.flavor['id'])
|
|
||||||
super(FlavorsExtraSpecsV3Test, cls).resource_cleanup()
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_flavor_set_get_update_show_unset_keys(self):
|
|
||||||
# Test to SET, GET, UPDATE, SHOW, UNSET flavor extra
|
|
||||||
# spec as a user with admin privileges.
|
|
||||||
# Assigning extra specs values that are to be set
|
|
||||||
specs = {"key1": "value1", "key2": "value2"}
|
|
||||||
# SET extra specs to the flavor created in setUp
|
|
||||||
set_resp, set_body = \
|
|
||||||
self.client.set_flavor_extra_spec(self.flavor['id'], specs)
|
|
||||||
self.assertEqual(set_resp.status, 201)
|
|
||||||
self.assertEqual(set_body, specs)
|
|
||||||
# GET extra specs and verify
|
|
||||||
get_resp, get_body = \
|
|
||||||
self.client.get_flavor_extra_spec(self.flavor['id'])
|
|
||||||
self.assertEqual(get_resp.status, 200)
|
|
||||||
self.assertEqual(get_body, specs)
|
|
||||||
|
|
||||||
# UPDATE the value of the extra specs key1
|
|
||||||
update_resp, update_body = \
|
|
||||||
self.client.update_flavor_extra_spec(self.flavor['id'],
|
|
||||||
"key1",
|
|
||||||
key1="value")
|
|
||||||
self.assertEqual(update_resp.status, 200)
|
|
||||||
self.assertEqual({"key1": "value"}, update_body)
|
|
||||||
|
|
||||||
# GET extra specs and verify the value of the key2
|
|
||||||
# is the same as before
|
|
||||||
get_resp, get_body = \
|
|
||||||
self.client.get_flavor_extra_spec(self.flavor['id'])
|
|
||||||
self.assertEqual(get_resp.status, 200)
|
|
||||||
self.assertEqual(get_body, {"key1": "value", "key2": "value2"})
|
|
||||||
|
|
||||||
# UNSET extra specs that were set in this test
|
|
||||||
unset_resp, _ = \
|
|
||||||
self.client.unset_flavor_extra_spec(self.flavor['id'], "key1")
|
|
||||||
self.assertEqual(unset_resp.status, 204)
|
|
||||||
unset_resp, _ = \
|
|
||||||
self.client.unset_flavor_extra_spec(self.flavor['id'], "key2")
|
|
||||||
self.assertEqual(unset_resp.status, 204)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_flavor_non_admin_get_all_keys(self):
|
|
||||||
specs = {"key1": "value1", "key2": "value2"}
|
|
||||||
set_resp, set_body = self.client.set_flavor_extra_spec(
|
|
||||||
self.flavor['id'], specs)
|
|
||||||
resp, body = self.flavors_client.get_flavor_extra_spec(
|
|
||||||
self.flavor['id'])
|
|
||||||
self.assertEqual(resp.status, 200)
|
|
||||||
|
|
||||||
for key in specs:
|
|
||||||
self.assertEqual(body[key], specs[key])
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_flavor_non_admin_get_specific_key(self):
|
|
||||||
specs = {"key1": "value1", "key2": "value2"}
|
|
||||||
resp, body = self.client.set_flavor_extra_spec(
|
|
||||||
self.flavor['id'], specs)
|
|
||||||
self.assertEqual(resp.status, 201)
|
|
||||||
self.assertEqual(body['key1'], 'value1')
|
|
||||||
self.assertIn('key2', body)
|
|
||||||
resp, body = self.flavors_client.get_flavor_extra_spec_with_key(
|
|
||||||
self.flavor['id'], 'key1')
|
|
||||||
self.assertEqual(resp.status, 200)
|
|
||||||
self.assertEqual(body['key1'], 'value1')
|
|
||||||
self.assertNotIn('key2', body)
|
|
@ -1,124 +0,0 @@
|
|||||||
# Copyright 2012 OpenStack Foundation
|
|
||||||
# All Rights Reserved.
|
|
||||||
# Copyright 2013 IBM Corp.
|
|
||||||
#
|
|
||||||
# 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.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class FlavorsExtraSpecsNegativeV3Test(base.BaseV3ComputeAdminTest):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Negative Tests Flavor Extra Spec API extension.
|
|
||||||
SET, UNSET, UPDATE Flavor Extra specs require admin privileges.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(FlavorsExtraSpecsNegativeV3Test, cls).resource_setup()
|
|
||||||
|
|
||||||
cls.client = cls.flavors_admin_client
|
|
||||||
flavor_name = data_utils.rand_name('test_flavor')
|
|
||||||
ram = 512
|
|
||||||
vcpus = 1
|
|
||||||
disk = 10
|
|
||||||
ephemeral = 10
|
|
||||||
cls.new_flavor_id = data_utils.rand_int_id(start=1000)
|
|
||||||
swap = 1024
|
|
||||||
rxtx = 1
|
|
||||||
# Create a flavor
|
|
||||||
resp, cls.flavor = cls.client.create_flavor(flavor_name,
|
|
||||||
ram, vcpus,
|
|
||||||
disk,
|
|
||||||
cls.new_flavor_id,
|
|
||||||
ephemeral=ephemeral,
|
|
||||||
swap=swap, rxtx=rxtx)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_cleanup(cls):
|
|
||||||
resp, body = cls.client.delete_flavor(cls.flavor['id'])
|
|
||||||
cls.client.wait_for_resource_deletion(cls.flavor['id'])
|
|
||||||
super(FlavorsExtraSpecsNegativeV3Test, cls).resource_cleanup()
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_flavor_non_admin_set_keys(self):
|
|
||||||
# Test to SET flavor extra spec as a user without admin privileges.
|
|
||||||
specs = {"key1": "value1", "key2": "value2"}
|
|
||||||
self.assertRaises(exceptions.Unauthorized,
|
|
||||||
self.flavors_client.set_flavor_extra_spec,
|
|
||||||
self.flavor['id'],
|
|
||||||
specs)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_flavor_non_admin_update_specific_key(self):
|
|
||||||
# non admin user is not allowed to update flavor extra spec
|
|
||||||
specs = {"key1": "value1", "key2": "value2"}
|
|
||||||
resp, body = self.client.set_flavor_extra_spec(
|
|
||||||
self.flavor['id'], specs)
|
|
||||||
self.assertEqual(resp.status, 201)
|
|
||||||
self.assertEqual(body['key1'], 'value1')
|
|
||||||
self.assertRaises(exceptions.Unauthorized,
|
|
||||||
self.flavors_client.
|
|
||||||
update_flavor_extra_spec,
|
|
||||||
self.flavor['id'],
|
|
||||||
'key1',
|
|
||||||
key1='value1_new')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_flavor_non_admin_unset_keys(self):
|
|
||||||
specs = {"key1": "value1", "key2": "value2"}
|
|
||||||
set_resp, set_body = self.client.set_flavor_extra_spec(
|
|
||||||
self.flavor['id'], specs)
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.Unauthorized,
|
|
||||||
self.flavors_client.unset_flavor_extra_spec,
|
|
||||||
self.flavor['id'],
|
|
||||||
'key1')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_flavor_unset_nonexistent_key(self):
|
|
||||||
nonexistent_key = data_utils.rand_name('flavor_key')
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.unset_flavor_extra_spec,
|
|
||||||
self.flavor['id'],
|
|
||||||
nonexistent_key)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_flavor_get_nonexistent_key(self):
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.flavors_client.get_flavor_extra_spec_with_key,
|
|
||||||
self.flavor['id'],
|
|
||||||
"nonexistent_key")
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_flavor_update_mismatch_key(self):
|
|
||||||
# the key will be updated should be match the key in the body
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.update_flavor_extra_spec,
|
|
||||||
self.flavor['id'],
|
|
||||||
"key2",
|
|
||||||
key1="value")
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_flavor_update_more_key(self):
|
|
||||||
# there should be just one item in the request body
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.update_flavor_extra_spec,
|
|
||||||
self.flavor['id'],
|
|
||||||
"key1",
|
|
||||||
key1="value",
|
|
||||||
key2="value")
|
|
@ -1,333 +0,0 @@
|
|||||||
# Copyright 2012 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 uuid
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class FlavorsAdminNegativeV3Test(base.BaseV3ComputeAdminTest):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Tests Flavors API Create and Delete that require admin privileges
|
|
||||||
"""
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(FlavorsAdminNegativeV3Test, cls).resource_setup()
|
|
||||||
|
|
||||||
cls.client = cls.flavors_admin_client
|
|
||||||
cls.user_client = cls.flavors_client
|
|
||||||
cls.flavor_name_prefix = 'test_flavor_'
|
|
||||||
cls.ram = 512
|
|
||||||
cls.vcpus = 1
|
|
||||||
cls.disk = 10
|
|
||||||
cls.ephemeral = 10
|
|
||||||
cls.swap = 1024
|
|
||||||
cls.rxtx = 2
|
|
||||||
|
|
||||||
def flavor_clean_up(self, flavor_id):
|
|
||||||
resp, body = self.client.delete_flavor(flavor_id)
|
|
||||||
self.assertEqual(resp.status, 204)
|
|
||||||
self.client.wait_for_resource_deletion(flavor_id)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_get_flavor_details_for_deleted_flavor(self):
|
|
||||||
# Delete a flavor and ensure it is not listed
|
|
||||||
# Create a test flavor
|
|
||||||
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
|
|
||||||
# no need to specify flavor_id, we can get the flavor_id from a
|
|
||||||
# response of create_flavor() call.
|
|
||||||
resp, flavor = self.client.create_flavor(flavor_name,
|
|
||||||
self.ram,
|
|
||||||
self.vcpus, self.disk,
|
|
||||||
None,
|
|
||||||
ephemeral=self.ephemeral,
|
|
||||||
swap=self.swap,
|
|
||||||
rxtx=self.rxtx)
|
|
||||||
# Delete the flavor
|
|
||||||
new_flavor_id = flavor['id']
|
|
||||||
resp_delete, body = self.client.delete_flavor(new_flavor_id)
|
|
||||||
self.assertEqual(201, resp.status)
|
|
||||||
self.assertEqual(204, resp_delete.status)
|
|
||||||
|
|
||||||
# Deleted flavors can be seen via detailed GET
|
|
||||||
resp, flavor = self.client.get_flavor_details(new_flavor_id)
|
|
||||||
self.assertEqual(resp.status, 200)
|
|
||||||
self.assertEqual(flavor['name'], flavor_name)
|
|
||||||
|
|
||||||
# Deleted flavors should not show up in a list however
|
|
||||||
resp, flavors = self.client.list_flavors_with_detail()
|
|
||||||
self.assertEqual(resp.status, 200)
|
|
||||||
flag = True
|
|
||||||
for flavor in flavors:
|
|
||||||
if flavor['name'] == flavor_name:
|
|
||||||
flag = False
|
|
||||||
self.assertTrue(flag)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_invalid_is_public_string(self):
|
|
||||||
# the 'is_public' parameter can be 'none/true/false' if it exists
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.list_flavors_with_detail,
|
|
||||||
{'is_public': 'invalid'})
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_flavor_as_user(self):
|
|
||||||
# only admin user can create a flavor
|
|
||||||
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
new_flavor_id = str(uuid.uuid4())
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.Unauthorized,
|
|
||||||
self.user_client.create_flavor,
|
|
||||||
flavor_name, self.ram, self.vcpus, self.disk,
|
|
||||||
new_flavor_id, ephemeral=self.ephemeral,
|
|
||||||
swap=self.swap, rxtx=self.rxtx)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_delete_flavor_as_user(self):
|
|
||||||
# only admin user can delete a flavor
|
|
||||||
self.assertRaises(exceptions.Unauthorized,
|
|
||||||
self.user_client.delete_flavor,
|
|
||||||
self.flavor_ref_alt)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_flavor_using_invalid_ram(self):
|
|
||||||
# the 'ram' attribute must be positive integer
|
|
||||||
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
new_flavor_id = str(uuid.uuid4())
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.create_flavor,
|
|
||||||
flavor_name, -1, self.vcpus,
|
|
||||||
self.disk, new_flavor_id)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_flavor_using_invalid_vcpus(self):
|
|
||||||
# the 'vcpu' attribute must be positive integer
|
|
||||||
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
new_flavor_id = str(uuid.uuid4())
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.create_flavor,
|
|
||||||
flavor_name, self.ram, -1,
|
|
||||||
self.disk, new_flavor_id)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_flavor_with_name_length_less_than_1(self):
|
|
||||||
# ensure name length >= 1
|
|
||||||
new_flavor_id = str(uuid.uuid4())
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.create_flavor,
|
|
||||||
'',
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
new_flavor_id,
|
|
||||||
ephemeral=self.ephemeral,
|
|
||||||
swap=self.swap,
|
|
||||||
rxtx=self.rxtx,
|
|
||||||
is_public='False')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_flavor_with_name_length_exceeds_255(self):
|
|
||||||
# ensure name do not exceed 255 characters
|
|
||||||
new_flavor_name = 'a' * 256
|
|
||||||
new_flavor_id = str(uuid.uuid4())
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.create_flavor,
|
|
||||||
new_flavor_name,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
new_flavor_id,
|
|
||||||
ephemeral=self.ephemeral,
|
|
||||||
swap=self.swap,
|
|
||||||
rxtx=self.rxtx,
|
|
||||||
is_public='False')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_flavor_with_invalid_name(self):
|
|
||||||
# the regex of flavor_name is '^[\w\.\- ]*$'
|
|
||||||
invalid_flavor_name = data_utils.rand_name('invalid-!@#$%-')
|
|
||||||
new_flavor_id = str(uuid.uuid4())
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.create_flavor,
|
|
||||||
invalid_flavor_name,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
new_flavor_id,
|
|
||||||
ephemeral=self.ephemeral,
|
|
||||||
swap=self.swap,
|
|
||||||
rxtx=self.rxtx,
|
|
||||||
is_public='False')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_flavor_with_invalid_flavor_id(self):
|
|
||||||
# the regex of flavor_id is '^[\w\.\- ]*$', and it cannot contain
|
|
||||||
# leading and/or trailing whitespace
|
|
||||||
new_flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
invalid_flavor_id = '!@#$%'
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.create_flavor,
|
|
||||||
new_flavor_name,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
invalid_flavor_id,
|
|
||||||
ephemeral=self.ephemeral,
|
|
||||||
swap=self.swap,
|
|
||||||
rxtx=self.rxtx,
|
|
||||||
is_public='False')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_flavor_with_id_length_exceeds_255(self):
|
|
||||||
# the length of flavor_id should not exceed 255 characters
|
|
||||||
new_flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
invalid_flavor_id = 'a' * 256
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.create_flavor,
|
|
||||||
new_flavor_name,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
invalid_flavor_id,
|
|
||||||
ephemeral=self.ephemeral,
|
|
||||||
swap=self.swap,
|
|
||||||
rxtx=self.rxtx,
|
|
||||||
is_public='False')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_flavor_with_invalid_root_gb(self):
|
|
||||||
# root_gb attribute should be non-negative ( >= 0) integer
|
|
||||||
new_flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
new_flavor_id = str(uuid.uuid4())
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.create_flavor,
|
|
||||||
new_flavor_name,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
-1,
|
|
||||||
new_flavor_id,
|
|
||||||
ephemeral=self.ephemeral,
|
|
||||||
swap=self.swap,
|
|
||||||
rxtx=self.rxtx,
|
|
||||||
is_public='False')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_flavor_with_invalid_ephemeral_gb(self):
|
|
||||||
# ephemeral_gb attribute should be non-negative ( >= 0) integer
|
|
||||||
new_flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
new_flavor_id = str(uuid.uuid4())
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.create_flavor,
|
|
||||||
new_flavor_name,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
new_flavor_id,
|
|
||||||
ephemeral=-1,
|
|
||||||
swap=self.swap,
|
|
||||||
rxtx=self.rxtx,
|
|
||||||
is_public='False')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_flavor_with_invalid_swap(self):
|
|
||||||
# swap attribute should be non-negative ( >= 0) integer
|
|
||||||
new_flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
new_flavor_id = str(uuid.uuid4())
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.create_flavor,
|
|
||||||
new_flavor_name,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
new_flavor_id,
|
|
||||||
ephemeral=self.ephemeral,
|
|
||||||
swap=-1,
|
|
||||||
rxtx=self.rxtx,
|
|
||||||
is_public='False')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_flavor_with_invalid_rxtx_factor(self):
|
|
||||||
# rxtx_factor attribute should be a positive float
|
|
||||||
new_flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
new_flavor_id = str(uuid.uuid4())
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.create_flavor,
|
|
||||||
new_flavor_name,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
new_flavor_id,
|
|
||||||
ephemeral=self.ephemeral,
|
|
||||||
swap=self.swap,
|
|
||||||
rxtx=-1.5,
|
|
||||||
is_public='False')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_flavor_with_invalid_is_public(self):
|
|
||||||
# is_public attribute should be boolean
|
|
||||||
new_flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
new_flavor_id = str(uuid.uuid4())
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.create_flavor,
|
|
||||||
new_flavor_name,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
new_flavor_id,
|
|
||||||
ephemeral=self.ephemeral,
|
|
||||||
swap=self.swap,
|
|
||||||
rxtx=self.rxtx,
|
|
||||||
is_public='Invalid')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_flavor_already_exists(self):
|
|
||||||
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
|
|
||||||
new_flavor_id = str(uuid.uuid4())
|
|
||||||
|
|
||||||
resp, flavor = self.client.create_flavor(flavor_name,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
new_flavor_id,
|
|
||||||
ephemeral=self.ephemeral,
|
|
||||||
swap=self.swap,
|
|
||||||
rxtx=self.rxtx)
|
|
||||||
self.assertEqual(201, resp.status)
|
|
||||||
self.addCleanup(self.flavor_clean_up, flavor['id'])
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.Conflict,
|
|
||||||
self.client.create_flavor,
|
|
||||||
flavor_name,
|
|
||||||
self.ram, self.vcpus,
|
|
||||||
self.disk,
|
|
||||||
new_flavor_id,
|
|
||||||
ephemeral=self.ephemeral,
|
|
||||||
swap=self.swap,
|
|
||||||
rxtx=self.rxtx)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_delete_nonexistent_flavor(self):
|
|
||||||
nonexistent_flavor_id = str(uuid.uuid4())
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.delete_flavor,
|
|
||||||
nonexistent_flavor_id)
|
|
@ -1,86 +0,0 @@
|
|||||||
# Copyright 2013 IBM Corp.
|
|
||||||
#
|
|
||||||
# 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.api.compute import base
|
|
||||||
from tempest.common import tempest_fixtures as fixtures
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class HostsAdminV3Test(base.BaseV3ComputeAdminTest):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Tests hosts API using admin privileges.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(HostsAdminV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.hosts_admin_client
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_hosts(self):
|
|
||||||
resp, hosts = self.client.list_hosts()
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertTrue(len(hosts) >= 2, str(hosts))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_hosts_with_zone(self):
|
|
||||||
self.useFixture(fixtures.LockFixture('availability_zone'))
|
|
||||||
resp, hosts = self.client.list_hosts()
|
|
||||||
host = hosts[0]
|
|
||||||
zone_name = host['zone']
|
|
||||||
params = {'zone': zone_name}
|
|
||||||
resp, hosts = self.client.list_hosts(params)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertTrue(len(hosts) >= 1)
|
|
||||||
self.assertIn(host, hosts)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_hosts_with_a_blank_zone(self):
|
|
||||||
# If send the request with a blank zone, the request will be successful
|
|
||||||
# and it will return all the hosts list
|
|
||||||
params = {'zone': ''}
|
|
||||||
resp, hosts = self.client.list_hosts(params)
|
|
||||||
self.assertNotEqual(0, len(hosts))
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_hosts_with_nonexistent_zone(self):
|
|
||||||
# If send the request with a nonexistent zone, the request will be
|
|
||||||
# successful and no hosts will be retured
|
|
||||||
params = {'zone': 'xxx'}
|
|
||||||
resp, hosts = self.client.list_hosts(params)
|
|
||||||
self.assertEqual(0, len(hosts))
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_show_host_detail(self):
|
|
||||||
resp, hosts = self.client.list_hosts()
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
|
|
||||||
hosts = [host for host in hosts if host['service'] == 'compute']
|
|
||||||
self.assertTrue(len(hosts) >= 1)
|
|
||||||
|
|
||||||
for host in hosts:
|
|
||||||
hostname = host['host_name']
|
|
||||||
resp, resources = self.client.show_host_detail(hostname)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertTrue(len(resources) >= 1)
|
|
||||||
host_resource = resources[0]['resource']
|
|
||||||
self.assertIsNotNone(host_resource)
|
|
||||||
self.assertIsNotNone(host_resource['cpu'])
|
|
||||||
self.assertIsNotNone(host_resource['disk_gb'])
|
|
||||||
self.assertIsNotNone(host_resource['memory_mb'])
|
|
||||||
self.assertIsNotNone(host_resource['project'])
|
|
||||||
self.assertEqual(hostname, host_resource['host'])
|
|
@ -1,168 +0,0 @@
|
|||||||
# Copyright 2013 Huawei Technologies Co.,LTD.
|
|
||||||
#
|
|
||||||
# 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.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class HostsAdminNegativeV3Test(base.BaseV3ComputeAdminTest):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Tests hosts API using admin privileges.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(HostsAdminNegativeV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.hosts_admin_client
|
|
||||||
cls.non_admin_client = cls.hosts_client
|
|
||||||
|
|
||||||
def _get_host_name(self):
|
|
||||||
resp, hosts = self.client.list_hosts()
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertTrue(len(hosts) >= 1)
|
|
||||||
hostname = hosts[0]['host_name']
|
|
||||||
return hostname
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_list_hosts_with_non_admin_user(self):
|
|
||||||
self.assertRaises(exceptions.Unauthorized,
|
|
||||||
self.non_admin_client.list_hosts)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_show_host_detail_with_nonexistent_hostname(self):
|
|
||||||
nonexitent_hostname = data_utils.rand_name('rand_hostname')
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.show_host_detail, nonexitent_hostname)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_show_host_detail_with_non_admin_user(self):
|
|
||||||
hostname = self._get_host_name()
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.Unauthorized,
|
|
||||||
self.non_admin_client.show_host_detail,
|
|
||||||
hostname)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_update_host_with_non_admin_user(self):
|
|
||||||
hostname = self._get_host_name()
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.Unauthorized,
|
|
||||||
self.non_admin_client.update_host,
|
|
||||||
hostname,
|
|
||||||
status='enable',
|
|
||||||
maintenance_mode='enable')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_update_host_with_extra_param(self):
|
|
||||||
# only 'status' and 'maintenance_mode' are the valid params.
|
|
||||||
hostname = self._get_host_name()
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.update_host,
|
|
||||||
hostname,
|
|
||||||
status='enable',
|
|
||||||
maintenance_mode='enable',
|
|
||||||
param='XXX')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_update_host_with_invalid_status(self):
|
|
||||||
# 'status' can only be 'enable' or 'disable'
|
|
||||||
hostname = self._get_host_name()
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.update_host,
|
|
||||||
hostname,
|
|
||||||
status='invalid',
|
|
||||||
maintenance_mode='enable')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_update_host_with_invalid_maintenance_mode(self):
|
|
||||||
# 'maintenance_mode' can only be 'enable' or 'disable'
|
|
||||||
hostname = self._get_host_name()
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.update_host,
|
|
||||||
hostname,
|
|
||||||
status='enable',
|
|
||||||
maintenance_mode='invalid')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_update_host_without_param(self):
|
|
||||||
# 'status' or 'maintenance_mode' needed for host update
|
|
||||||
hostname = self._get_host_name()
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.update_host,
|
|
||||||
hostname)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_update_nonexistent_host(self):
|
|
||||||
nonexitent_hostname = data_utils.rand_name('rand_hostname')
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.update_host,
|
|
||||||
nonexitent_hostname,
|
|
||||||
status='enable',
|
|
||||||
maintenance_mode='enable')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_startup_nonexistent_host(self):
|
|
||||||
nonexitent_hostname = data_utils.rand_name('rand_hostname')
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.startup_host,
|
|
||||||
nonexitent_hostname)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_startup_host_with_non_admin_user(self):
|
|
||||||
hostname = self._get_host_name()
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.Unauthorized,
|
|
||||||
self.non_admin_client.startup_host,
|
|
||||||
hostname)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_shutdown_nonexistent_host(self):
|
|
||||||
nonexitent_hostname = data_utils.rand_name('rand_hostname')
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.shutdown_host,
|
|
||||||
nonexitent_hostname)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_shutdown_host_with_non_admin_user(self):
|
|
||||||
hostname = self._get_host_name()
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.Unauthorized,
|
|
||||||
self.non_admin_client.shutdown_host,
|
|
||||||
hostname)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_reboot_nonexistent_host(self):
|
|
||||||
nonexitent_hostname = data_utils.rand_name('rand_hostname')
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.reboot_host,
|
|
||||||
nonexitent_hostname)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_reboot_host_with_non_admin_user(self):
|
|
||||||
hostname = self._get_host_name()
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.Unauthorized,
|
|
||||||
self.non_admin_client.reboot_host,
|
|
||||||
hostname)
|
|
@ -1,117 +0,0 @@
|
|||||||
# Copyright 2013 IBM 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.api.compute import base
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class HypervisorAdminV3Test(base.BaseV3ComputeAdminTest):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Tests Hypervisors API that require admin privileges
|
|
||||||
"""
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(HypervisorAdminV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.hypervisor_admin_client
|
|
||||||
|
|
||||||
def _list_hypervisors(self):
|
|
||||||
# List of hypervisors
|
|
||||||
resp, hypers = self.client.get_hypervisor_list()
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
return hypers
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_get_hypervisor_list(self):
|
|
||||||
# List of hypervisor and available hypervisors hostname
|
|
||||||
hypers = self._list_hypervisors()
|
|
||||||
self.assertTrue(len(hypers) > 0)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_get_hypervisor_list_details(self):
|
|
||||||
# Display the details of the all hypervisor
|
|
||||||
resp, hypers = self.client.get_hypervisor_list_details()
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertTrue(len(hypers) > 0)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_get_hypervisor_show_details(self):
|
|
||||||
# Display the details of the specified hypervisor
|
|
||||||
hypers = self._list_hypervisors()
|
|
||||||
self.assertTrue(len(hypers) > 0)
|
|
||||||
|
|
||||||
resp, details = (self.client.
|
|
||||||
get_hypervisor_show_details(hypers[0]['id']))
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertTrue(len(details) > 0)
|
|
||||||
self.assertEqual(details['hypervisor_hostname'],
|
|
||||||
hypers[0]['hypervisor_hostname'])
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_get_hypervisor_show_servers(self):
|
|
||||||
# Show instances about the specific hypervisors
|
|
||||||
hypers = self._list_hypervisors()
|
|
||||||
self.assertTrue(len(hypers) > 0)
|
|
||||||
|
|
||||||
hypervisor_id = hypers[0]['id']
|
|
||||||
resp, hypervisors = self.client.get_hypervisor_servers(hypervisor_id)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertTrue(len(hypervisors) > 0)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_get_hypervisor_stats(self):
|
|
||||||
# Verify the stats of the all hypervisor
|
|
||||||
resp, stats = self.client.get_hypervisor_stats()
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertTrue(len(stats) > 0)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_get_hypervisor_uptime(self):
|
|
||||||
# Verify that GET shows the specified hypervisor uptime
|
|
||||||
hypers = self._list_hypervisors()
|
|
||||||
|
|
||||||
# Ironic will register each baremetal node as a 'hypervisor',
|
|
||||||
# so the hypervisor list can contain many hypervisors of type
|
|
||||||
# 'ironic'. If they are ALL ironic, skip this test since ironic
|
|
||||||
# doesn't support hypervisor uptime. Otherwise, remove them
|
|
||||||
# from the list of hypervisors to test.
|
|
||||||
ironic_only = True
|
|
||||||
hypers_without_ironic = []
|
|
||||||
for hyper in hypers:
|
|
||||||
resp, details = (self.client.
|
|
||||||
get_hypervisor_show_details(hypers[0]['id']))
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
if details['hypervisor_type'] != 'ironic':
|
|
||||||
hypers_without_ironic.append(hyper)
|
|
||||||
ironic_only = False
|
|
||||||
|
|
||||||
if ironic_only:
|
|
||||||
raise self.skipException(
|
|
||||||
"Ironic does not support hypervisor uptime")
|
|
||||||
|
|
||||||
resp, uptime = self.client.get_hypervisor_uptime(
|
|
||||||
hypers_without_ironic[0]['id'])
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertTrue(len(uptime) > 0)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_search_hypervisor(self):
|
|
||||||
hypers = self._list_hypervisors()
|
|
||||||
self.assertTrue(len(hypers) > 0)
|
|
||||||
resp, hypers = self.client.search_hypervisor(
|
|
||||||
hypers[0]['hypervisor_hostname'])
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertTrue(len(hypers) > 0)
|
|
@ -1,136 +0,0 @@
|
|||||||
# Copyright 2013 Huawei Technologies Co.,LTD.
|
|
||||||
# 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 uuid
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class HypervisorAdminNegativeV3Test(base.BaseV3ComputeAdminTest):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Tests Hypervisors API that require admin privileges
|
|
||||||
"""
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(HypervisorAdminNegativeV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.hypervisor_admin_client
|
|
||||||
cls.non_adm_client = cls.hypervisor_client
|
|
||||||
|
|
||||||
def _list_hypervisors(self):
|
|
||||||
# List of hypervisors
|
|
||||||
resp, hypers = self.client.get_hypervisor_list()
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
return hypers
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_show_nonexistent_hypervisor(self):
|
|
||||||
nonexistent_hypervisor_id = str(uuid.uuid4())
|
|
||||||
|
|
||||||
self.assertRaises(
|
|
||||||
exceptions.NotFound,
|
|
||||||
self.client.get_hypervisor_show_details,
|
|
||||||
nonexistent_hypervisor_id)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_show_hypervisor_with_non_admin_user(self):
|
|
||||||
hypers = self._list_hypervisors()
|
|
||||||
self.assertTrue(len(hypers) > 0)
|
|
||||||
|
|
||||||
self.assertRaises(
|
|
||||||
exceptions.Unauthorized,
|
|
||||||
self.non_adm_client.get_hypervisor_show_details,
|
|
||||||
hypers[0]['id'])
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_show_servers_with_non_admin_user(self):
|
|
||||||
hypers = self._list_hypervisors()
|
|
||||||
self.assertTrue(len(hypers) > 0)
|
|
||||||
|
|
||||||
self.assertRaises(
|
|
||||||
exceptions.Unauthorized,
|
|
||||||
self.non_adm_client.get_hypervisor_servers,
|
|
||||||
hypers[0]['id'])
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_show_servers_with_nonexistent_hypervisor(self):
|
|
||||||
nonexistent_hypervisor_id = str(uuid.uuid4())
|
|
||||||
|
|
||||||
self.assertRaises(
|
|
||||||
exceptions.NotFound,
|
|
||||||
self.client.get_hypervisor_servers,
|
|
||||||
nonexistent_hypervisor_id)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_get_hypervisor_stats_with_non_admin_user(self):
|
|
||||||
self.assertRaises(
|
|
||||||
exceptions.Unauthorized,
|
|
||||||
self.non_adm_client.get_hypervisor_stats)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_get_nonexistent_hypervisor_uptime(self):
|
|
||||||
nonexistent_hypervisor_id = str(uuid.uuid4())
|
|
||||||
|
|
||||||
self.assertRaises(
|
|
||||||
exceptions.NotFound,
|
|
||||||
self.client.get_hypervisor_uptime,
|
|
||||||
nonexistent_hypervisor_id)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_get_hypervisor_uptime_with_non_admin_user(self):
|
|
||||||
hypers = self._list_hypervisors()
|
|
||||||
self.assertTrue(len(hypers) > 0)
|
|
||||||
|
|
||||||
self.assertRaises(
|
|
||||||
exceptions.Unauthorized,
|
|
||||||
self.non_adm_client.get_hypervisor_uptime,
|
|
||||||
hypers[0]['id'])
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_get_hypervisor_list_with_non_admin_user(self):
|
|
||||||
# List of hypervisor and available services with non admin user
|
|
||||||
self.assertRaises(
|
|
||||||
exceptions.Unauthorized,
|
|
||||||
self.non_adm_client.get_hypervisor_list)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_get_hypervisor_list_details_with_non_admin_user(self):
|
|
||||||
# List of hypervisor details and available services with non admin user
|
|
||||||
self.assertRaises(
|
|
||||||
exceptions.Unauthorized,
|
|
||||||
self.non_adm_client.get_hypervisor_list_details)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_search_nonexistent_hypervisor(self):
|
|
||||||
nonexistent_hypervisor_name = data_utils.rand_name('test_hypervisor')
|
|
||||||
|
|
||||||
resp, hypers = self.client.search_hypervisor(
|
|
||||||
nonexistent_hypervisor_name)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(0, len(hypers))
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_search_hypervisor_with_non_admin_user(self):
|
|
||||||
hypers = self._list_hypervisors()
|
|
||||||
self.assertTrue(len(hypers) > 0)
|
|
||||||
|
|
||||||
self.assertRaises(
|
|
||||||
exceptions.Unauthorized,
|
|
||||||
self.non_adm_client.search_hypervisor,
|
|
||||||
hypers[0]['hypervisor_hostname'])
|
|
@ -1,50 +0,0 @@
|
|||||||
# 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 testtools
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest import config
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
CONF = config.CONF
|
|
||||||
|
|
||||||
|
|
||||||
class MigrationsAdminV3Test(base.BaseV3ComputeAdminTest):
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_migrations(self):
|
|
||||||
# Admin can get the migrations list
|
|
||||||
resp, _ = self.migrations_admin_client.list_migrations()
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
|
|
||||||
'Resize not available.')
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_migrations_in_flavor_resize_situation(self):
|
|
||||||
# Admin can get the migrations list which contains the resized server
|
|
||||||
resp, server = self.create_test_server(wait_until="ACTIVE")
|
|
||||||
server_id = server['id']
|
|
||||||
|
|
||||||
resp, _ = self.servers_client.resize(server_id, self.flavor_ref_alt)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.servers_client.wait_for_server_status(server_id, 'VERIFY_RESIZE')
|
|
||||||
self.servers_client.confirm_resize(server_id)
|
|
||||||
self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
|
|
||||||
|
|
||||||
resp, body = self.migrations_admin_client.list_migrations()
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
|
|
||||||
instance_uuids = [x['instance_uuid'] for x in body]
|
|
||||||
self.assertIn(server_id, instance_uuids)
|
|
@ -1,150 +0,0 @@
|
|||||||
# Copyright 2013 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.
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import config
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
CONF = config.CONF
|
|
||||||
|
|
||||||
|
|
||||||
class QuotasAdminV3Test(base.BaseV3ComputeAdminTest):
|
|
||||||
force_tenant_isolation = True
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(QuotasAdminV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.quotas_client
|
|
||||||
cls.adm_client = cls.quotas_admin_client
|
|
||||||
|
|
||||||
# NOTE(afazekas): these test cases should always create and use a new
|
|
||||||
# tenant most of them should be skipped if we can't do that
|
|
||||||
cls.demo_tenant_id = cls.client.tenant_id
|
|
||||||
|
|
||||||
cls.default_quota_set = set(('metadata_items',
|
|
||||||
'ram', 'floating_ips',
|
|
||||||
'fixed_ips', 'key_pairs',
|
|
||||||
'instances', 'security_group_rules',
|
|
||||||
'cores', 'security_groups'))
|
|
||||||
|
|
||||||
@test.attr(type='smoke')
|
|
||||||
def test_get_default_quotas(self):
|
|
||||||
# Admin can get the default resource quota set for a tenant
|
|
||||||
expected_quota_set = self.default_quota_set | set(['id'])
|
|
||||||
resp, quota_set = self.adm_client.get_default_quota_set(
|
|
||||||
self.demo_tenant_id)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(sorted(expected_quota_set),
|
|
||||||
sorted(quota_set.keys()))
|
|
||||||
self.assertEqual(quota_set['id'], self.demo_tenant_id)
|
|
||||||
|
|
||||||
@test.attr(type='smoke')
|
|
||||||
def test_get_quota_set_detail(self):
|
|
||||||
# Admin can get the detail of resource quota set for a tenant
|
|
||||||
expected_quota_set = self.default_quota_set | set(['id'])
|
|
||||||
expected_detail = ['reserved', 'limit', 'in_use']
|
|
||||||
resp, quota_set = self.adm_client.get_quota_set_detail(
|
|
||||||
self.demo_tenant_id)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(sorted(expected_quota_set), sorted(quota_set.keys()))
|
|
||||||
self.assertEqual(quota_set['id'], self.demo_tenant_id)
|
|
||||||
for quota in quota_set:
|
|
||||||
if quota == 'id':
|
|
||||||
continue
|
|
||||||
self.assertEqual(sorted(expected_detail),
|
|
||||||
sorted(quota_set[quota].keys()))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_update_all_quota_resources_for_tenant(self):
|
|
||||||
# Admin can update all the resource quota limits for a tenant
|
|
||||||
resp, default_quota_set = self.adm_client.get_default_quota_set(
|
|
||||||
self.demo_tenant_id)
|
|
||||||
new_quota_set = {'metadata_items': 256,
|
|
||||||
'ram': 10240, 'floating_ips': 20, 'fixed_ips': 10,
|
|
||||||
'key_pairs': 200,
|
|
||||||
'instances': 20, 'security_group_rules': 20,
|
|
||||||
'cores': 2, 'security_groups': 20}
|
|
||||||
# Update limits for all quota resources
|
|
||||||
resp, quota_set = self.adm_client.update_quota_set(
|
|
||||||
self.demo_tenant_id,
|
|
||||||
force=True,
|
|
||||||
**new_quota_set)
|
|
||||||
|
|
||||||
default_quota_set.pop('id')
|
|
||||||
self.addCleanup(self.adm_client.update_quota_set,
|
|
||||||
self.demo_tenant_id, **default_quota_set)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
quota_set.pop('id')
|
|
||||||
self.assertEqual(new_quota_set, quota_set)
|
|
||||||
|
|
||||||
# TODO(afazekas): merge these test cases
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_get_updated_quotas(self):
|
|
||||||
# Verify that GET shows the updated quota set of tenant
|
|
||||||
tenant_name = data_utils.rand_name('cpu_quota_tenant_')
|
|
||||||
tenant_desc = tenant_name + '-desc'
|
|
||||||
identity_client = self.os_adm.identity_client
|
|
||||||
_, tenant = identity_client.create_tenant(name=tenant_name,
|
|
||||||
description=tenant_desc)
|
|
||||||
tenant_id = tenant['id']
|
|
||||||
self.addCleanup(identity_client.delete_tenant, tenant_id)
|
|
||||||
|
|
||||||
self.adm_client.update_quota_set(tenant_id, ram='5120')
|
|
||||||
resp, quota_set = self.adm_client.get_quota_set(tenant_id)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(5120, quota_set['ram'])
|
|
||||||
|
|
||||||
# Verify that GET shows the updated quota set of user
|
|
||||||
user_name = data_utils.rand_name('cpu_quota_user_')
|
|
||||||
password = data_utils.rand_name('password-')
|
|
||||||
email = user_name + '@testmail.tm'
|
|
||||||
_, user = identity_client.create_user(name=user_name,
|
|
||||||
password=password,
|
|
||||||
tenant_id=tenant_id,
|
|
||||||
email=email)
|
|
||||||
user_id = user['id']
|
|
||||||
self.addCleanup(identity_client.delete_user, user_id)
|
|
||||||
|
|
||||||
self.adm_client.update_quota_set(tenant_id,
|
|
||||||
user_id=user_id,
|
|
||||||
ram='2048')
|
|
||||||
resp, quota_set = self.adm_client.get_quota_set(tenant_id,
|
|
||||||
user_id=user_id)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(2048, quota_set['ram'])
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_delete_quota(self):
|
|
||||||
# Admin can delete the resource quota set for a tenant
|
|
||||||
tenant_name = data_utils.rand_name('cpu_quota_tenant_')
|
|
||||||
tenant_desc = tenant_name + '-desc'
|
|
||||||
identity_client = self.os_adm.identity_client
|
|
||||||
_, tenant = identity_client.create_tenant(name=tenant_name,
|
|
||||||
description=tenant_desc)
|
|
||||||
tenant_id = tenant['id']
|
|
||||||
self.addCleanup(identity_client.delete_tenant, tenant_id)
|
|
||||||
resp, quota_set_default = self.adm_client.get_quota_set(tenant_id)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
ram_default = quota_set_default['ram']
|
|
||||||
|
|
||||||
self.adm_client.update_quota_set(tenant_id, ram='5120')
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
resp, _ = self.adm_client.delete_quota_set(tenant_id)
|
|
||||||
self.assertEqual(204, resp.status)
|
|
||||||
|
|
||||||
resp, quota_set_new = self.adm_client.get_quota_set(tenant_id)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(ram_default, quota_set_new['ram'])
|
|
@ -1,89 +0,0 @@
|
|||||||
# Copyright 2013 OpenStack Foundation
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class QuotasAdminNegativeV3Test(base.BaseV3ComputeAdminTest):
|
|
||||||
force_tenant_isolation = True
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(QuotasAdminNegativeV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.quotas_client
|
|
||||||
cls.adm_client = cls.quotas_admin_client
|
|
||||||
|
|
||||||
# NOTE(afazekas): these test cases should always create and use a new
|
|
||||||
# tenant most of them should be skipped if we can't do that
|
|
||||||
cls.demo_tenant_id = cls.isolated_creds.get_primary_creds().tenant_id
|
|
||||||
|
|
||||||
# TODO(afazekas): Add dedicated tenant to the skiped quota tests
|
|
||||||
# it can be moved into the setUpClass as well
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_server_when_cpu_quota_is_full(self):
|
|
||||||
# Disallow server creation when tenant's vcpu quota is full
|
|
||||||
resp, quota_set = self.adm_client.get_quota_set(self.demo_tenant_id)
|
|
||||||
default_vcpu_quota = quota_set['cores']
|
|
||||||
vcpu_quota = 0 # Set the quota to zero to conserve resources
|
|
||||||
|
|
||||||
resp, quota_set = self.adm_client.update_quota_set(self.demo_tenant_id,
|
|
||||||
force=True,
|
|
||||||
cores=vcpu_quota)
|
|
||||||
|
|
||||||
self.addCleanup(self.adm_client.update_quota_set, self.demo_tenant_id,
|
|
||||||
cores=default_vcpu_quota)
|
|
||||||
self.assertRaises((exceptions.Unauthorized, exceptions.OverLimit),
|
|
||||||
self.create_test_server)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_server_when_memory_quota_is_full(self):
|
|
||||||
# Disallow server creation when tenant's memory quota is full
|
|
||||||
resp, quota_set = self.adm_client.get_quota_set(self.demo_tenant_id)
|
|
||||||
default_mem_quota = quota_set['ram']
|
|
||||||
mem_quota = 0 # Set the quota to zero to conserve resources
|
|
||||||
|
|
||||||
self.adm_client.update_quota_set(self.demo_tenant_id,
|
|
||||||
force=True,
|
|
||||||
ram=mem_quota)
|
|
||||||
|
|
||||||
self.addCleanup(self.adm_client.update_quota_set, self.demo_tenant_id,
|
|
||||||
ram=default_mem_quota)
|
|
||||||
self.assertRaises((exceptions.Unauthorized, exceptions.OverLimit),
|
|
||||||
self.create_test_server)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_update_quota_normal_user(self):
|
|
||||||
self.assertRaises(exceptions.Unauthorized,
|
|
||||||
self.client.update_quota_set,
|
|
||||||
self.demo_tenant_id,
|
|
||||||
ram=0)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_server_when_instances_quota_is_full(self):
|
|
||||||
# Once instances quota limit is reached, disallow server creation
|
|
||||||
resp, quota_set = self.adm_client.get_quota_set(self.demo_tenant_id)
|
|
||||||
default_instances_quota = quota_set['instances']
|
|
||||||
instances_quota = 0 # Set quota to zero to disallow server creation
|
|
||||||
|
|
||||||
self.adm_client.update_quota_set(self.demo_tenant_id,
|
|
||||||
force=True,
|
|
||||||
instances=instances_quota)
|
|
||||||
self.addCleanup(self.adm_client.update_quota_set, self.demo_tenant_id,
|
|
||||||
instances=default_instances_quota)
|
|
||||||
self.assertRaises((exceptions.Unauthorized, exceptions.OverLimit),
|
|
||||||
self.create_test_server)
|
|
@ -1,174 +0,0 @@
|
|||||||
# Copyright 2013 IBM Corp.
|
|
||||||
#
|
|
||||||
# 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.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class ServersAdminV3Test(base.BaseV3ComputeAdminTest):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Tests Servers API using admin privileges
|
|
||||||
"""
|
|
||||||
|
|
||||||
_host_key = 'os-extended-server-attributes:host'
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(ServersAdminV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.servers_admin_client
|
|
||||||
cls.non_admin_client = cls.servers_client
|
|
||||||
cls.flavors_client = cls.flavors_admin_client
|
|
||||||
|
|
||||||
cls.s1_name = data_utils.rand_name('server')
|
|
||||||
resp, server = cls.create_test_server(name=cls.s1_name,
|
|
||||||
wait_until='ACTIVE')
|
|
||||||
cls.s1_id = server['id']
|
|
||||||
|
|
||||||
cls.s2_name = data_utils.rand_name('server')
|
|
||||||
resp, server = cls.create_test_server(name=cls.s2_name,
|
|
||||||
wait_until='ACTIVE')
|
|
||||||
cls.s2_id = server['id']
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_servers_by_admin(self):
|
|
||||||
# Listing servers by admin user returns empty list by default
|
|
||||||
resp, body = self.client.list_servers_with_detail()
|
|
||||||
servers = body['servers']
|
|
||||||
self.assertEqual('200', resp['status'])
|
|
||||||
self.assertEqual([], servers)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_servers_by_admin_with_all_tenants(self):
|
|
||||||
# Listing servers by admin user with all tenants parameter
|
|
||||||
# Here should be listed all servers
|
|
||||||
params = {'all_tenants': ''}
|
|
||||||
resp, body = self.client.list_servers_with_detail(params)
|
|
||||||
servers = body['servers']
|
|
||||||
servers_name = map(lambda x: x['name'], servers)
|
|
||||||
|
|
||||||
self.assertIn(self.s1_name, servers_name)
|
|
||||||
self.assertIn(self.s2_name, servers_name)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_servers_filter_by_existent_host(self):
|
|
||||||
# Filter the list of servers by existent host
|
|
||||||
name = data_utils.rand_name('server')
|
|
||||||
flavor = self.flavor_ref
|
|
||||||
image_id = self.image_ref
|
|
||||||
resp, test_server = self.client.create_server(
|
|
||||||
name, image_id, flavor)
|
|
||||||
self.assertEqual('202', resp['status'])
|
|
||||||
self.addCleanup(self.client.delete_server, test_server['id'])
|
|
||||||
self.client.wait_for_server_status(test_server['id'], 'ACTIVE')
|
|
||||||
resp, server = self.client.get_server(test_server['id'])
|
|
||||||
self.assertEqual(server['status'], 'ACTIVE')
|
|
||||||
hostname = server[self._host_key]
|
|
||||||
params = {'host': hostname}
|
|
||||||
resp, body = self.client.list_servers(params)
|
|
||||||
self.assertEqual('200', resp['status'])
|
|
||||||
servers = body['servers']
|
|
||||||
nonexistent_params = {'host': 'nonexistent_host'}
|
|
||||||
resp, nonexistent_body = self.client.list_servers(
|
|
||||||
nonexistent_params)
|
|
||||||
self.assertEqual('200', resp['status'])
|
|
||||||
nonexistent_servers = nonexistent_body['servers']
|
|
||||||
self.assertIn(test_server['id'], map(lambda x: x['id'], servers))
|
|
||||||
self.assertNotIn(test_server['id'],
|
|
||||||
map(lambda x: x['id'], nonexistent_servers))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_reset_state_server(self):
|
|
||||||
# Reset server's state to 'error'
|
|
||||||
resp, server = self.client.reset_state(self.s1_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
|
|
||||||
# Verify server's state
|
|
||||||
resp, server = self.client.get_server(self.s1_id)
|
|
||||||
self.assertEqual(server['status'], 'ERROR')
|
|
||||||
|
|
||||||
# Reset server's state to 'active'
|
|
||||||
resp, server = self.client.reset_state(self.s1_id, state='active')
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
|
|
||||||
# Verify server's state
|
|
||||||
resp, server = self.client.get_server(self.s1_id)
|
|
||||||
self.assertEqual(server['status'], 'ACTIVE')
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
@test.skip_because(bug="1240043")
|
|
||||||
def test_get_server_diagnostics_by_admin(self):
|
|
||||||
# Retrieve server diagnostics by admin user
|
|
||||||
resp, diagnostic = self.client.get_server_diagnostics(self.s1_id)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
basic_attrs = ['rx_packets', 'rx_errors', 'rx_drop',
|
|
||||||
'tx_packets', 'tx_errors', 'tx_drop',
|
|
||||||
'read_req', 'write_req', 'cpu', 'memory']
|
|
||||||
for key in basic_attrs:
|
|
||||||
self.assertIn(key, str(diagnostic.keys()))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_servers_filter_by_error_status(self):
|
|
||||||
# Filter the list of servers by server error status
|
|
||||||
params = {'status': 'error'}
|
|
||||||
resp, server = self.client.reset_state(self.s1_id, state='error')
|
|
||||||
resp, body = self.non_admin_client.list_servers(params)
|
|
||||||
# Reset server's state to 'active'
|
|
||||||
resp, server = self.client.reset_state(self.s1_id, state='active')
|
|
||||||
# Verify server's state
|
|
||||||
resp, server = self.client.get_server(self.s1_id)
|
|
||||||
self.assertEqual(server['status'], 'ACTIVE')
|
|
||||||
servers = body['servers']
|
|
||||||
# Verify error server in list result
|
|
||||||
self.assertIn(self.s1_id, map(lambda x: x['id'], servers))
|
|
||||||
self.assertNotIn(self.s2_id, map(lambda x: x['id'], servers))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_rebuild_server_in_error_state(self):
|
|
||||||
# The server in error state should be rebuilt using the provided
|
|
||||||
# image and changed to ACTIVE state
|
|
||||||
|
|
||||||
# resetting vm state require admin privilege
|
|
||||||
resp, server = self.client.reset_state(self.s1_id, state='error')
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
resp, rebuilt_server = self.non_admin_client.rebuild(
|
|
||||||
self.s1_id, self.image_ref_alt)
|
|
||||||
self.addCleanup(self.non_admin_client.wait_for_server_status,
|
|
||||||
self.s1_id, 'ACTIVE')
|
|
||||||
self.addCleanup(self.non_admin_client.rebuild, self.s1_id,
|
|
||||||
self.image_ref)
|
|
||||||
|
|
||||||
# Verify the properties in the initial response are correct
|
|
||||||
self.assertEqual(self.s1_id, rebuilt_server['id'])
|
|
||||||
rebuilt_image_id = rebuilt_server['image']['id']
|
|
||||||
self.assertEqual(self.image_ref_alt, rebuilt_image_id)
|
|
||||||
self.assertEqual(self.flavor_ref, rebuilt_server['flavor']['id'])
|
|
||||||
self.non_admin_client.wait_for_server_status(rebuilt_server['id'],
|
|
||||||
'ACTIVE',
|
|
||||||
raise_on_error=False)
|
|
||||||
# Verify the server properties after rebuilding
|
|
||||||
resp, server = self.non_admin_client.get_server(rebuilt_server['id'])
|
|
||||||
rebuilt_image_id = server['image']['id']
|
|
||||||
self.assertEqual(self.image_ref_alt, rebuilt_image_id)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_reset_network_inject_network_info(self):
|
|
||||||
resp, server = self.create_test_server(wait_until='ACTIVE')
|
|
||||||
# Reset Network of a Server
|
|
||||||
resp, server_body = self.client.reset_network(server['id'])
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
# Inject the Network Info into Server
|
|
||||||
resp, server = self.client.inject_network_info(server['id'])
|
|
||||||
self.assertEqual(202, resp.status)
|
|
@ -1,144 +0,0 @@
|
|||||||
# Copyright 2013 Huawei Technologies Co.,LTD.
|
|
||||||
#
|
|
||||||
# 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 uuid
|
|
||||||
|
|
||||||
import testtools
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest.common import tempest_fixtures as fixtures
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import config
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
CONF = config.CONF
|
|
||||||
|
|
||||||
|
|
||||||
class ServersAdminNegativeV3Test(base.BaseV3ComputeAdminTest):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Tests Servers API using admin privileges
|
|
||||||
"""
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(ServersAdminNegativeV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.servers_admin_client
|
|
||||||
cls.non_adm_client = cls.servers_client
|
|
||||||
cls.flavors_client = cls.flavors_admin_client
|
|
||||||
cls.tenant_id = cls.client.tenant_id
|
|
||||||
|
|
||||||
cls.s1_name = data_utils.rand_name('server')
|
|
||||||
resp, server = cls.create_test_server(name=cls.s1_name,
|
|
||||||
wait_until='ACTIVE')
|
|
||||||
cls.s1_id = server['id']
|
|
||||||
|
|
||||||
def _get_unused_flavor_id(self):
|
|
||||||
flavor_id = data_utils.rand_int_id(start=1000)
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
resp, body = self.flavors_client.get_flavor_details(flavor_id)
|
|
||||||
except exceptions.NotFound:
|
|
||||||
break
|
|
||||||
flavor_id = data_utils.rand_int_id(start=1000)
|
|
||||||
return flavor_id
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_resize_server_using_overlimit_ram(self):
|
|
||||||
# NOTE(mriedem): Avoid conflicts with os-quota-class-sets tests.
|
|
||||||
self.useFixture(fixtures.LockFixture('compute_quotas'))
|
|
||||||
flavor_name = data_utils.rand_name("flavor-")
|
|
||||||
flavor_id = self._get_unused_flavor_id()
|
|
||||||
resp, quota_set = self.quotas_client.get_default_quota_set(
|
|
||||||
self.tenant_id)
|
|
||||||
ram = int(quota_set['ram']) + 1
|
|
||||||
vcpus = 8
|
|
||||||
disk = 10
|
|
||||||
resp, flavor_ref = self.flavors_client.create_flavor(flavor_name,
|
|
||||||
ram, vcpus, disk,
|
|
||||||
flavor_id)
|
|
||||||
self.addCleanup(self.flavors_client.delete_flavor, flavor_id)
|
|
||||||
self.assertRaises((exceptions.Unauthorized, exceptions.OverLimit),
|
|
||||||
self.client.resize,
|
|
||||||
self.servers[0]['id'],
|
|
||||||
flavor_ref['id'])
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_resize_server_using_overlimit_vcpus(self):
|
|
||||||
# NOTE(mriedem): Avoid conflicts with os-quota-class-sets tests.
|
|
||||||
self.useFixture(fixtures.LockFixture('compute_quotas'))
|
|
||||||
flavor_name = data_utils.rand_name("flavor-")
|
|
||||||
flavor_id = self._get_unused_flavor_id()
|
|
||||||
ram = 512
|
|
||||||
resp, quota_set = self.quotas_client.get_default_quota_set(
|
|
||||||
self.tenant_id)
|
|
||||||
vcpus = int(quota_set['cores']) + 1
|
|
||||||
disk = 10
|
|
||||||
resp, flavor_ref = self.flavors_client.create_flavor(flavor_name,
|
|
||||||
ram, vcpus, disk,
|
|
||||||
flavor_id)
|
|
||||||
self.addCleanup(self.flavors_client.delete_flavor, flavor_id)
|
|
||||||
self.assertRaises((exceptions.Unauthorized, exceptions.OverLimit),
|
|
||||||
self.client.resize,
|
|
||||||
self.servers[0]['id'],
|
|
||||||
flavor_ref['id'])
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_reset_state_server_invalid_state(self):
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.reset_state, self.s1_id,
|
|
||||||
state='invalid')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_reset_state_server_invalid_type(self):
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.reset_state, self.s1_id,
|
|
||||||
state=1)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_reset_state_server_nonexistent_server(self):
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.reset_state, '999')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_get_server_diagnostics_by_non_admin(self):
|
|
||||||
# Non-admin user can not view server diagnostics according to policy
|
|
||||||
self.assertRaises(exceptions.Unauthorized,
|
|
||||||
self.non_adm_client.get_server_diagnostics,
|
|
||||||
self.s1_id)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_migrate_non_existent_server(self):
|
|
||||||
# migrate a non existent server
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.migrate_server,
|
|
||||||
str(uuid.uuid4()))
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.suspend,
|
|
||||||
'Suspend is not available.')
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_migrate_server_invalid_state(self):
|
|
||||||
# create server.
|
|
||||||
resp, server = self.create_test_server(wait_until='ACTIVE')
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
server_id = server['id']
|
|
||||||
# suspend the server.
|
|
||||||
resp, _ = self.client.suspend_server(server_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.client.wait_for_server_status(server_id, 'SUSPENDED')
|
|
||||||
# migrate an suspended server should fail
|
|
||||||
self.assertRaises(exceptions.Conflict,
|
|
||||||
self.client.migrate_server,
|
|
||||||
server_id)
|
|
@ -1,79 +0,0 @@
|
|||||||
# Copyright 2013 NEC Corporation
|
|
||||||
# Copyright 2013 IBM Corp.
|
|
||||||
# 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.api.compute import base
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class ServicesAdminV3Test(base.BaseV3ComputeAdminTest):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Tests Services API. List and Enable/Disable require admin privileges.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(ServicesAdminV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.services_admin_client
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_services(self):
|
|
||||||
resp, services = self.client.list_services()
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertNotEqual(0, len(services))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_get_service_by_service_binary_name(self):
|
|
||||||
binary_name = 'nova-compute'
|
|
||||||
params = {'binary': binary_name}
|
|
||||||
resp, services = self.client.list_services(params)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertNotEqual(0, len(services))
|
|
||||||
for service in services:
|
|
||||||
self.assertEqual(binary_name, service['binary'])
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_get_service_by_host_name(self):
|
|
||||||
resp, services = self.client.list_services()
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
host_name = services[0]['host']
|
|
||||||
services_on_host = [service for service in services if
|
|
||||||
service['host'] == host_name]
|
|
||||||
params = {'host': host_name}
|
|
||||||
|
|
||||||
resp, services = self.client.list_services(params)
|
|
||||||
|
|
||||||
# we could have a periodic job checkin between the 2 service
|
|
||||||
# lookups, so only compare binary lists.
|
|
||||||
s1 = map(lambda x: x['binary'], services)
|
|
||||||
s2 = map(lambda x: x['binary'], services_on_host)
|
|
||||||
|
|
||||||
# sort the lists before comparing, to take out dependency
|
|
||||||
# on order.
|
|
||||||
self.assertEqual(sorted(s1), sorted(s2))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_get_service_by_service_and_host_name(self):
|
|
||||||
resp, services = self.client.list_services()
|
|
||||||
host_name = services[0]['host']
|
|
||||||
binary_name = services[0]['binary']
|
|
||||||
params = {'host': host_name, 'binary': binary_name}
|
|
||||||
|
|
||||||
resp, services = self.client.list_services(params)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(1, len(services))
|
|
||||||
self.assertEqual(host_name, services[0]['host'])
|
|
||||||
self.assertEqual(binary_name, services[0]['binary'])
|
|
@ -1,64 +0,0 @@
|
|||||||
# Copyright 2013 NEC Corporation
|
|
||||||
# Copyright 2013 IBM Corp.
|
|
||||||
# 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.api.compute import base
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class ServicesAdminNegativeV3Test(base.BaseV3ComputeAdminTest):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Tests Services API. List and Enable/Disable require admin privileges.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(ServicesAdminNegativeV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.services_admin_client
|
|
||||||
cls.non_admin_client = cls.services_client
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_list_services_with_non_admin_user(self):
|
|
||||||
self.assertRaises(exceptions.Unauthorized,
|
|
||||||
self.non_admin_client.list_services)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_get_service_by_invalid_params(self):
|
|
||||||
# return all services if send the request with invalid parameter
|
|
||||||
resp, services = self.client.list_services()
|
|
||||||
params = {'xxx': 'nova-compute'}
|
|
||||||
resp, services_xxx = self.client.list_services(params)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(len(services), len(services_xxx))
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_get_service_by_invalid_service_and_valid_host(self):
|
|
||||||
resp, services = self.client.list_services()
|
|
||||||
host_name = services[0]['host']
|
|
||||||
params = {'host': host_name, 'binary': 'xxx'}
|
|
||||||
resp, services = self.client.list_services(params)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(0, len(services))
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_get_service_with_valid_service_and_invalid_host(self):
|
|
||||||
resp, services = self.client.list_services()
|
|
||||||
binary_name = services[0]['binary']
|
|
||||||
params = {'host': 'xxx', 'binary': binary_name}
|
|
||||||
resp, services = self.client.list_services(params)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(0, len(services))
|
|
@ -1,40 +0,0 @@
|
|||||||
# Copyright 2013 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.
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest.api_schema.request.compute.v3 import flavors
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
load_tests = test.NegativeAutoTest.load_tests
|
|
||||||
|
|
||||||
|
|
||||||
@test.SimpleNegativeAutoTest
|
|
||||||
class FlavorsListNegativeV3Test(base.BaseV3ComputeTest,
|
|
||||||
test.NegativeAutoTest):
|
|
||||||
_service = 'computev3'
|
|
||||||
_schema = flavors.flavor_list
|
|
||||||
|
|
||||||
|
|
||||||
@test.SimpleNegativeAutoTest
|
|
||||||
class FlavorDetailsNegativeV3Test(base.BaseV3ComputeTest,
|
|
||||||
test.NegativeAutoTest):
|
|
||||||
_service = 'computev3'
|
|
||||||
_schema = flavors.flavors_details
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(FlavorDetailsNegativeV3Test, cls).resource_setup()
|
|
||||||
cls.set_resource("flavor", cls.flavor_ref)
|
|
@ -1,56 +0,0 @@
|
|||||||
# Copyright 2012 OpenStack Foundation
|
|
||||||
#
|
|
||||||
# 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.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import config
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
CONF = config.CONF
|
|
||||||
|
|
||||||
|
|
||||||
class ImagesV3Test(base.BaseV3ComputeTest):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(ImagesV3Test, cls).resource_setup()
|
|
||||||
if not CONF.service_available.glance:
|
|
||||||
skip_msg = ("%s skipped as glance is not available" % cls.__name__)
|
|
||||||
raise cls.skipException(skip_msg)
|
|
||||||
cls.client = cls.images_client
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_create_image_from_stopped_server(self):
|
|
||||||
resp, server = self.create_test_server(wait_until='ACTIVE')
|
|
||||||
self.servers_client.stop(server['id'])
|
|
||||||
self.servers_client.wait_for_server_status(server['id'],
|
|
||||||
'SHUTOFF')
|
|
||||||
self.addCleanup(self.servers_client.delete_server, server['id'])
|
|
||||||
snapshot_name = data_utils.rand_name('test-snap-')
|
|
||||||
resp, image = self.create_image_from_server(server['id'],
|
|
||||||
name=snapshot_name,
|
|
||||||
wait_until='active')
|
|
||||||
self.addCleanup(self.client.delete_image, image['id'])
|
|
||||||
self.assertEqual(snapshot_name, image['name'])
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_delete_queued_image(self):
|
|
||||||
snapshot_name = data_utils.rand_name('test-snap-')
|
|
||||||
resp, server = self.create_test_server(wait_until='ACTIVE')
|
|
||||||
self.addCleanup(self.servers_client.delete_server, server['id'])
|
|
||||||
resp, image = self.create_image_from_server(server['id'],
|
|
||||||
name=snapshot_name,
|
|
||||||
wait_until='queued')
|
|
||||||
resp, body = self.client.delete_image(image['id'])
|
|
||||||
self.assertEqual('200', resp['status'])
|
|
@ -1,82 +0,0 @@
|
|||||||
# 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.
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import config
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
CONF = config.CONF
|
|
||||||
|
|
||||||
|
|
||||||
class ImagesNegativeV3Test(base.BaseV3ComputeTest):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(ImagesNegativeV3Test, cls).resource_setup()
|
|
||||||
if not CONF.service_available.glance:
|
|
||||||
skip_msg = ("%s skipped as glance is not available" % cls.__name__)
|
|
||||||
raise cls.skipException(skip_msg)
|
|
||||||
cls.client = cls.images_client
|
|
||||||
|
|
||||||
def __create_image__(self, server_id, name, meta=None):
|
|
||||||
resp, body = self.servers_client.create_image(server_id, name, meta)
|
|
||||||
image_id = data_utils.parse_image_id(resp['location'])
|
|
||||||
self.addCleanup(self.client.delete_image, image_id)
|
|
||||||
self.client.wait_for_image_status(image_id, 'active')
|
|
||||||
return resp, body
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_image_from_deleted_server(self):
|
|
||||||
# An image should not be created if the server instance is removed
|
|
||||||
resp, server = self.create_test_server(wait_until='ACTIVE')
|
|
||||||
|
|
||||||
# Delete server before trying to create server
|
|
||||||
self.servers_client.delete_server(server['id'])
|
|
||||||
self.servers_client.wait_for_server_termination(server['id'])
|
|
||||||
# Create a new image after server is deleted
|
|
||||||
name = data_utils.rand_name('image')
|
|
||||||
meta = {'image_type': 'test'}
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.__create_image__,
|
|
||||||
server['id'], name, meta)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_image_from_nonexistent_server(self):
|
|
||||||
# An image should not be created with invalid server id
|
|
||||||
# Create a new image with invalid server id
|
|
||||||
nonexistent_server_id = data_utils.rand_uuid()
|
|
||||||
name = data_utils.rand_name('image')
|
|
||||||
meta = {'image_type': 'test'}
|
|
||||||
self.assertRaises(exceptions.NotFound, self.__create_image__,
|
|
||||||
nonexistent_server_id, name, meta)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_image_specify_uuid_35_characters_or_less(self):
|
|
||||||
# Return an error if Image ID passed is 35 characters or less
|
|
||||||
snapshot_name = data_utils.rand_name('test-snap-')
|
|
||||||
test_uuid = ('a' * 35)
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.servers_client.create_image,
|
|
||||||
test_uuid, snapshot_name)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_image_specify_uuid_37_characters_or_more(self):
|
|
||||||
# Return an error if Image ID passed is 37 characters or more
|
|
||||||
snapshot_name = data_utils.rand_name('test-snap-')
|
|
||||||
test_uuid = ('a' * 37)
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.servers_client.create_image,
|
|
||||||
test_uuid, snapshot_name)
|
|
@ -1,105 +0,0 @@
|
|||||||
# Copyright 2012 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.
|
|
||||||
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import config
|
|
||||||
from tempest.openstack.common import log as logging
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
CONF = config.CONF
|
|
||||||
LOG = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class ImagesOneServerV3Test(base.BaseV3ComputeTest):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
# NOTE(afazekas): Normally we use the same server with all test cases,
|
|
||||||
# but if it has an issue, we build a new one
|
|
||||||
super(ImagesOneServerV3Test, self).setUp()
|
|
||||||
# Check if the server is in a clean state after test
|
|
||||||
try:
|
|
||||||
self.servers_client.wait_for_server_status(self.server_id,
|
|
||||||
'ACTIVE')
|
|
||||||
except Exception:
|
|
||||||
LOG.exception('server %s timed out to become ACTIVE. rebuilding'
|
|
||||||
% self.server_id)
|
|
||||||
# Rebuild server if cannot reach the ACTIVE state
|
|
||||||
# Usually it means the server had a serious accident
|
|
||||||
self.__class__.server_id = self.rebuild_server(self.server_id)
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
"""Terminate test instances created after a test is executed."""
|
|
||||||
self.server_check_teardown()
|
|
||||||
super(ImagesOneServerV3Test, self).tearDown()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(ImagesOneServerV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.images_client
|
|
||||||
if not CONF.service_available.glance:
|
|
||||||
skip_msg = ("%s skipped as glance is not available" % cls.__name__)
|
|
||||||
raise cls.skipException(skip_msg)
|
|
||||||
|
|
||||||
resp, server = cls.create_test_server(wait_until='ACTIVE')
|
|
||||||
cls.server_id = server['id']
|
|
||||||
|
|
||||||
def _get_default_flavor_disk_size(self, flavor_id):
|
|
||||||
resp, flavor = self.flavors_client.get_flavor_details(flavor_id)
|
|
||||||
return flavor['disk']
|
|
||||||
|
|
||||||
@test.attr(type='smoke')
|
|
||||||
def test_create_delete_image(self):
|
|
||||||
|
|
||||||
# Create a new image
|
|
||||||
name = data_utils.rand_name('image')
|
|
||||||
meta = {'image_type': 'test'}
|
|
||||||
resp, body = self.servers_client.create_image(self.server_id,
|
|
||||||
name, meta)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
image_id = data_utils.parse_image_id(resp['location'])
|
|
||||||
self.client.wait_for_image_status(image_id, 'active')
|
|
||||||
|
|
||||||
# Verify the image was created correctly
|
|
||||||
resp, image = self.client.get_image_meta(image_id)
|
|
||||||
self.assertEqual(name, image['name'])
|
|
||||||
self.assertEqual('test', image['properties']['image_type'])
|
|
||||||
|
|
||||||
resp, original_image = self.client.get_image_meta(self.image_ref)
|
|
||||||
|
|
||||||
# Verify minRAM is the same as the original image
|
|
||||||
self.assertEqual(image['min_ram'], original_image['min_ram'])
|
|
||||||
|
|
||||||
# Verify minDisk is the same as the original image or the flavor size
|
|
||||||
flavor_disk_size = self._get_default_flavor_disk_size(self.flavor_ref)
|
|
||||||
self.assertIn(str(image['min_disk']),
|
|
||||||
(str(original_image['min_disk']), str(flavor_disk_size)))
|
|
||||||
|
|
||||||
# Verify the image was deleted correctly
|
|
||||||
resp, body = self.client.delete_image(image_id)
|
|
||||||
self.assertEqual('200', resp['status'])
|
|
||||||
self.client.wait_for_resource_deletion(image_id)
|
|
||||||
|
|
||||||
@test.attr(type=['gate'])
|
|
||||||
def test_create_image_specify_multibyte_character_image_name(self):
|
|
||||||
# prefix character is:
|
|
||||||
# http://www.fileformat.info/info/unicode/char/1F4A9/index.htm
|
|
||||||
utf8_name = data_utils.rand_name(u'\xF0\x9F\x92\xA9')
|
|
||||||
resp, body = self.servers_client.create_image(self.server_id,
|
|
||||||
utf8_name)
|
|
||||||
image_id = data_utils.parse_image_id(resp['location'])
|
|
||||||
self.addCleanup(self.client.delete_image, image_id)
|
|
||||||
self.assertEqual('202', resp['status'])
|
|
@ -1,145 +0,0 @@
|
|||||||
# Copyright 2012 OpenStack Foundation
|
|
||||||
# Copyright 2013 IBM Corp.
|
|
||||||
# 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.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import config
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest.openstack.common import log as logging
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
CONF = config.CONF
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class ImagesOneServerNegativeV3Test(base.BaseV3ComputeTest):
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
"""Terminate test instances created after a test is executed."""
|
|
||||||
for image_id in self.image_ids:
|
|
||||||
self.client.delete_image(image_id)
|
|
||||||
self.image_ids.remove(image_id)
|
|
||||||
self.server_check_teardown()
|
|
||||||
super(ImagesOneServerNegativeV3Test, self).tearDown()
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
# NOTE(afazekas): Normally we use the same server with all test cases,
|
|
||||||
# but if it has an issue, we build a new one
|
|
||||||
super(ImagesOneServerNegativeV3Test, self).setUp()
|
|
||||||
# Check if the server is in a clean state after test
|
|
||||||
try:
|
|
||||||
self.servers_client.wait_for_server_status(self.server_id,
|
|
||||||
'ACTIVE')
|
|
||||||
except Exception:
|
|
||||||
LOG.exception('server %s timed out to become ACTIVE. rebuilding'
|
|
||||||
% self.server_id)
|
|
||||||
# Rebuild server if cannot reach the ACTIVE state
|
|
||||||
# Usually it means the server had a serious accident
|
|
||||||
self._reset_server()
|
|
||||||
|
|
||||||
def _reset_server(self):
|
|
||||||
self.__class__.server_id = self.rebuild_server(self.server_id)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(ImagesOneServerNegativeV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.images_client
|
|
||||||
if not CONF.service_available.glance:
|
|
||||||
skip_msg = ("%s skipped as glance is not available" % cls.__name__)
|
|
||||||
raise cls.skipException(skip_msg)
|
|
||||||
|
|
||||||
resp, server = cls.create_test_server(wait_until='ACTIVE')
|
|
||||||
cls.server_id = server['id']
|
|
||||||
|
|
||||||
cls.image_ids = []
|
|
||||||
|
|
||||||
@test.skip_because(bug="1006725")
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_image_specify_multibyte_character_image_name(self):
|
|
||||||
# invalid multibyte sequence from:
|
|
||||||
# http://stackoverflow.com/questions/1301402/
|
|
||||||
# example-invalid-utf8-string
|
|
||||||
invalid_name = data_utils.rand_name(u'\xc3\x28')
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.servers_client.create_image,
|
|
||||||
self.server_id,
|
|
||||||
invalid_name)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_image_specify_invalid_metadata(self):
|
|
||||||
# Return an error when creating image with invalid metadata
|
|
||||||
snapshot_name = data_utils.rand_name('test-snap-')
|
|
||||||
meta = {'': ''}
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.servers_client.create_image,
|
|
||||||
self.server_id, snapshot_name, meta)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_image_specify_metadata_over_limits(self):
|
|
||||||
# Return an error when creating image with meta data over 256 chars
|
|
||||||
snapshot_name = data_utils.rand_name('test-snap-')
|
|
||||||
meta = {'a' * 260: 'b' * 260}
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.servers_client.create_image,
|
|
||||||
self.server_id, snapshot_name, meta)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_second_image_when_first_image_is_being_saved(self):
|
|
||||||
# Disallow creating another image when first image is being saved
|
|
||||||
|
|
||||||
# Create first snapshot
|
|
||||||
snapshot_name = data_utils.rand_name('test-snap-')
|
|
||||||
resp, body = self.servers_client.create_image(self.server_id,
|
|
||||||
snapshot_name)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
image_id = data_utils.parse_image_id(resp['location'])
|
|
||||||
self.image_ids.append(image_id)
|
|
||||||
self.addCleanup(self._reset_server)
|
|
||||||
|
|
||||||
# Create second snapshot
|
|
||||||
alt_snapshot_name = data_utils.rand_name('test-snap-')
|
|
||||||
self.assertRaises(exceptions.Conflict,
|
|
||||||
self.servers_client.create_image,
|
|
||||||
self.server_id, alt_snapshot_name)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_image_specify_name_over_256_chars(self):
|
|
||||||
# Return an error if snapshot name over 256 characters is passed
|
|
||||||
|
|
||||||
snapshot_name = data_utils.rand_name('a' * 260)
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.servers_client.create_image,
|
|
||||||
self.server_id, snapshot_name)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_delete_image_that_is_not_yet_active(self):
|
|
||||||
# Return an error while trying to delete an image what is creating
|
|
||||||
|
|
||||||
snapshot_name = data_utils.rand_name('test-snap-')
|
|
||||||
resp, body = self.servers_client.create_image(self.server_id,
|
|
||||||
snapshot_name)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
image_id = data_utils.parse_image_id(resp['location'])
|
|
||||||
self.image_ids.append(image_id)
|
|
||||||
self.addCleanup(self._reset_server)
|
|
||||||
|
|
||||||
# Do not wait, attempt to delete the image, ensure it's successful
|
|
||||||
resp, body = self.client.delete_image(image_id)
|
|
||||||
self.assertEqual('200', resp['status'])
|
|
||||||
self.image_ids.remove(image_id)
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.NotFound, self.client.get_image, image_id)
|
|
@ -1,94 +0,0 @@
|
|||||||
# Copyright 2012 OpenStack Foundation
|
|
||||||
# Copyright 2013 IBM Corp
|
|
||||||
# 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.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class KeyPairsNegativeV3Test(base.BaseV3ComputeTest):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(KeyPairsNegativeV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.keypairs_client
|
|
||||||
|
|
||||||
def _create_keypair(self, keypair_name, pub_key=None):
|
|
||||||
self.client.create_keypair(keypair_name, pub_key)
|
|
||||||
self.addCleanup(self.client.delete_keypair, keypair_name)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_keypair_create_with_invalid_pub_key(self):
|
|
||||||
# Keypair should not be created with a non RSA public key
|
|
||||||
k_name = data_utils.rand_name('keypair-')
|
|
||||||
pub_key = "ssh-rsa JUNK nova@ubuntu"
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self._create_keypair, k_name, pub_key)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_keypair_delete_nonexistent_key(self):
|
|
||||||
# Non-existent key deletion should throw a proper error
|
|
||||||
k_name = data_utils.rand_name("keypair-non-existent-")
|
|
||||||
self.assertRaises(exceptions.NotFound, self.client.delete_keypair,
|
|
||||||
k_name)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_keypair_with_empty_public_key(self):
|
|
||||||
# Keypair should not be created with an empty public key
|
|
||||||
k_name = data_utils.rand_name("keypair-")
|
|
||||||
pub_key = ' '
|
|
||||||
self.assertRaises(exceptions.BadRequest, self._create_keypair,
|
|
||||||
k_name, pub_key)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_keypair_when_public_key_bits_exceeds_maximum(self):
|
|
||||||
# Keypair should not be created when public key bits are too long
|
|
||||||
k_name = data_utils.rand_name("keypair-")
|
|
||||||
pub_key = 'ssh-rsa ' + 'A' * 2048 + ' openstack@ubuntu'
|
|
||||||
self.assertRaises(exceptions.BadRequest, self._create_keypair,
|
|
||||||
k_name, pub_key)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_keypair_with_duplicate_name(self):
|
|
||||||
# Keypairs with duplicate names should not be created
|
|
||||||
k_name = data_utils.rand_name('keypair-')
|
|
||||||
resp, _ = self.client.create_keypair(k_name)
|
|
||||||
self.addCleanup(self.client.delete_keypair, k_name)
|
|
||||||
self.assertEqual(201, resp.status)
|
|
||||||
# Now try the same keyname to create another key
|
|
||||||
self.assertRaises(exceptions.Conflict, self._create_keypair,
|
|
||||||
k_name)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_keypair_with_empty_name_string(self):
|
|
||||||
# Keypairs with name being an empty string should not be created
|
|
||||||
self.assertRaises(exceptions.BadRequest, self._create_keypair,
|
|
||||||
'')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_keypair_with_long_keynames(self):
|
|
||||||
# Keypairs with name longer than 255 chars should not be created
|
|
||||||
k_name = 'keypair-'.ljust(260, '0')
|
|
||||||
self.assertRaises(exceptions.BadRequest, self._create_keypair,
|
|
||||||
k_name)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_keypair_invalid_name(self):
|
|
||||||
# Keypairs with name being an invalid name should not be created
|
|
||||||
k_name = 'key_/.\@:'
|
|
||||||
self.assertRaises(exceptions.BadRequest, self._create_keypair,
|
|
||||||
k_name)
|
|
@ -1,157 +0,0 @@
|
|||||||
# Copyright 2013 IBM Corp.
|
|
||||||
# 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.api.compute import base
|
|
||||||
from tempest import config
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
import time
|
|
||||||
|
|
||||||
CONF = config.CONF
|
|
||||||
|
|
||||||
|
|
||||||
class AttachInterfacesV3Test(base.BaseV3ComputeTest):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
if not CONF.service_available.neutron:
|
|
||||||
raise cls.skipException("Neutron is required")
|
|
||||||
if not CONF.compute_feature_enabled.interface_attach:
|
|
||||||
raise cls.skipException("Interface attachment is not available.")
|
|
||||||
# This test class requires network and subnet
|
|
||||||
cls.set_network_resources(network=True, subnet=True)
|
|
||||||
super(AttachInterfacesV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.interfaces_client
|
|
||||||
|
|
||||||
def _check_interface(self, iface, port_id=None, network_id=None,
|
|
||||||
fixed_ip=None):
|
|
||||||
self.assertIn('port_state', iface)
|
|
||||||
if port_id:
|
|
||||||
self.assertEqual(iface['port_id'], port_id)
|
|
||||||
if network_id:
|
|
||||||
self.assertEqual(iface['net_id'], network_id)
|
|
||||||
if fixed_ip:
|
|
||||||
self.assertEqual(iface['fixed_ips'][0]['ip_address'], fixed_ip)
|
|
||||||
|
|
||||||
def _create_server_get_interfaces(self):
|
|
||||||
resp, server = self.create_test_server(wait_until='ACTIVE')
|
|
||||||
resp, ifs = self.client.list_interfaces(server['id'])
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
resp, body = self.client.wait_for_interface_status(
|
|
||||||
server['id'], ifs[0]['port_id'], 'ACTIVE')
|
|
||||||
ifs[0]['port_state'] = body['port_state']
|
|
||||||
return server, ifs
|
|
||||||
|
|
||||||
def _test_create_interface(self, server):
|
|
||||||
resp, iface = self.client.create_interface(server['id'])
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
resp, iface = self.client.wait_for_interface_status(
|
|
||||||
server['id'], iface['port_id'], 'ACTIVE')
|
|
||||||
self._check_interface(iface)
|
|
||||||
return iface
|
|
||||||
|
|
||||||
def _test_create_interface_by_network_id(self, server, ifs):
|
|
||||||
network_id = ifs[0]['net_id']
|
|
||||||
resp, iface = self.client.create_interface(server['id'],
|
|
||||||
network_id=network_id)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
resp, iface = self.client.wait_for_interface_status(
|
|
||||||
server['id'], iface['port_id'], 'ACTIVE')
|
|
||||||
self._check_interface(iface, network_id=network_id)
|
|
||||||
return iface
|
|
||||||
|
|
||||||
def _test_show_interface(self, server, ifs):
|
|
||||||
iface = ifs[0]
|
|
||||||
resp, _iface = self.client.show_interface(server['id'],
|
|
||||||
iface['port_id'])
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(iface, _iface)
|
|
||||||
|
|
||||||
def _test_delete_interface(self, server, ifs):
|
|
||||||
# NOTE(danms): delete not the first or last, but one in the middle
|
|
||||||
iface = ifs[1]
|
|
||||||
resp, _ = self.client.delete_interface(server['id'], iface['port_id'])
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
_ifs = self.client.list_interfaces(server['id'])[1]
|
|
||||||
start = int(time.time())
|
|
||||||
|
|
||||||
while len(ifs) == len(_ifs):
|
|
||||||
time.sleep(self.build_interval)
|
|
||||||
_ifs = self.client.list_interfaces(server['id'])[1]
|
|
||||||
timed_out = int(time.time()) - start >= self.build_timeout
|
|
||||||
if len(ifs) == len(_ifs) and timed_out:
|
|
||||||
message = ('Failed to delete interface within '
|
|
||||||
'the required time: %s sec.' % self.build_timeout)
|
|
||||||
raise exceptions.TimeoutException(message)
|
|
||||||
|
|
||||||
self.assertNotIn(iface['port_id'], [i['port_id'] for i in _ifs])
|
|
||||||
return _ifs
|
|
||||||
|
|
||||||
def _compare_iface_list(self, list1, list2):
|
|
||||||
# NOTE(danms): port_state will likely have changed, so just
|
|
||||||
# confirm the port_ids are the same at least
|
|
||||||
list1 = [x['port_id'] for x in list1]
|
|
||||||
list2 = [x['port_id'] for x in list2]
|
|
||||||
|
|
||||||
self.assertEqual(sorted(list1), sorted(list2))
|
|
||||||
|
|
||||||
@test.attr(type='smoke')
|
|
||||||
def test_create_list_show_delete_interfaces(self):
|
|
||||||
server, ifs = self._create_server_get_interfaces()
|
|
||||||
interface_count = len(ifs)
|
|
||||||
self.assertTrue(interface_count > 0)
|
|
||||||
self._check_interface(ifs[0])
|
|
||||||
|
|
||||||
iface = self._test_create_interface(server)
|
|
||||||
ifs.append(iface)
|
|
||||||
|
|
||||||
iface = self._test_create_interface_by_network_id(server, ifs)
|
|
||||||
ifs.append(iface)
|
|
||||||
|
|
||||||
resp, _ifs = self.client.list_interfaces(server['id'])
|
|
||||||
self._compare_iface_list(ifs, _ifs)
|
|
||||||
|
|
||||||
self._test_show_interface(server, ifs)
|
|
||||||
|
|
||||||
_ifs = self._test_delete_interface(server, ifs)
|
|
||||||
self.assertEqual(len(ifs) - 1, len(_ifs))
|
|
||||||
|
|
||||||
@test.attr(type='smoke')
|
|
||||||
def test_add_remove_fixed_ip(self):
|
|
||||||
# Add and Remove the fixed IP to server.
|
|
||||||
server, ifs = self._create_server_get_interfaces()
|
|
||||||
interface_count = len(ifs)
|
|
||||||
self.assertGreater(interface_count, 0)
|
|
||||||
self._check_interface(ifs[0])
|
|
||||||
network_id = ifs[0]['net_id']
|
|
||||||
resp, body = self.client.add_fixed_ip(server['id'],
|
|
||||||
network_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
server_resp, server_detail = self.servers_client.get_server(
|
|
||||||
server['id'])
|
|
||||||
# Get the Fixed IP from server.
|
|
||||||
fixed_ip = None
|
|
||||||
for ip_set in server_detail['addresses']:
|
|
||||||
for ip in server_detail['addresses'][ip_set]:
|
|
||||||
if ip['type'] == 'fixed':
|
|
||||||
fixed_ip = ip['addr']
|
|
||||||
break
|
|
||||||
if fixed_ip is not None:
|
|
||||||
break
|
|
||||||
# Remove the fixed IP from server.
|
|
||||||
resp, body = self.client.remove_fixed_ip(server['id'],
|
|
||||||
fixed_ip)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
@ -1,111 +0,0 @@
|
|||||||
# Copyright 2013 IBM Corp.
|
|
||||||
# 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 testtools
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest.common.utils.linux import remote_client
|
|
||||||
from tempest import config
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
CONF = config.CONF
|
|
||||||
|
|
||||||
|
|
||||||
class AttachVolumeV3Test(base.BaseV3ComputeTest):
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super(AttachVolumeV3Test, self).__init__(*args, **kwargs)
|
|
||||||
self.server = None
|
|
||||||
self.volume = None
|
|
||||||
self.attached = False
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
cls.prepare_instance_network()
|
|
||||||
super(AttachVolumeV3Test, cls).resource_setup()
|
|
||||||
cls.device = CONF.compute.volume_device_name
|
|
||||||
if not CONF.service_available.cinder:
|
|
||||||
skip_msg = ("%s skipped as Cinder is not available" % cls.__name__)
|
|
||||||
raise cls.skipException(skip_msg)
|
|
||||||
|
|
||||||
def _detach(self, server_id, volume_id):
|
|
||||||
if self.attached:
|
|
||||||
self.servers_client.detach_volume(server_id, volume_id)
|
|
||||||
self.volumes_client.wait_for_volume_status(volume_id, 'available')
|
|
||||||
|
|
||||||
def _delete_volume(self):
|
|
||||||
if self.volume:
|
|
||||||
self.volumes_client.delete_volume(self.volume['id'])
|
|
||||||
self.volume = None
|
|
||||||
|
|
||||||
def _create_and_attach(self):
|
|
||||||
# Start a server and wait for it to become ready
|
|
||||||
admin_pass = self.image_ssh_password
|
|
||||||
resp, server = self.create_test_server(wait_until='ACTIVE',
|
|
||||||
admin_password=admin_pass)
|
|
||||||
self.server = server
|
|
||||||
|
|
||||||
# Record addresses so that we can ssh later
|
|
||||||
resp, server['addresses'] = \
|
|
||||||
self.servers_client.list_addresses(server['id'])
|
|
||||||
|
|
||||||
# Create a volume and wait for it to become ready
|
|
||||||
resp, volume = self.volumes_client.create_volume(1,
|
|
||||||
display_name='test')
|
|
||||||
self.volume = volume
|
|
||||||
self.addCleanup(self._delete_volume)
|
|
||||||
self.volumes_client.wait_for_volume_status(volume['id'], 'available')
|
|
||||||
|
|
||||||
# Attach the volume to the server
|
|
||||||
self.servers_client.attach_volume(server['id'], volume['id'],
|
|
||||||
device='/dev/%s' % self.device)
|
|
||||||
self.volumes_client.wait_for_volume_status(volume['id'], 'in-use')
|
|
||||||
|
|
||||||
self.attached = True
|
|
||||||
self.addCleanup(self._detach, server['id'], volume['id'])
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute.run_ssh, 'SSH required for this test')
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_attach_detach_volume(self):
|
|
||||||
# Stop and Start a server with an attached volume, ensuring that
|
|
||||||
# the volume remains attached.
|
|
||||||
self._create_and_attach()
|
|
||||||
server = self.server
|
|
||||||
volume = self.volume
|
|
||||||
|
|
||||||
self.servers_client.stop(server['id'])
|
|
||||||
self.servers_client.wait_for_server_status(server['id'], 'SHUTOFF')
|
|
||||||
|
|
||||||
self.servers_client.start(server['id'])
|
|
||||||
self.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
|
|
||||||
|
|
||||||
linux_client = remote_client.RemoteClient(server, self.image_ssh_user,
|
|
||||||
server['admin_password'])
|
|
||||||
partitions = linux_client.get_partitions()
|
|
||||||
self.assertIn(self.device, partitions)
|
|
||||||
|
|
||||||
self._detach(server['id'], volume['id'])
|
|
||||||
self.attached = False
|
|
||||||
|
|
||||||
self.servers_client.stop(server['id'])
|
|
||||||
self.servers_client.wait_for_server_status(server['id'], 'SHUTOFF')
|
|
||||||
|
|
||||||
self.servers_client.start(server['id'])
|
|
||||||
self.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
|
|
||||||
|
|
||||||
linux_client = remote_client.RemoteClient(server, self.image_ssh_user,
|
|
||||||
server['admin_password'])
|
|
||||||
partitions = linux_client.get_partitions()
|
|
||||||
self.assertNotIn(self.device, partitions)
|
|
@ -1,199 +0,0 @@
|
|||||||
# Copyright 2012 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 base64
|
|
||||||
|
|
||||||
import netaddr
|
|
||||||
import testtools
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest.common.utils.linux import remote_client
|
|
||||||
from tempest import config
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
CONF = config.CONF
|
|
||||||
|
|
||||||
|
|
||||||
class ServersV3Test(base.BaseV3ComputeTest):
|
|
||||||
disk_config = 'AUTO'
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
cls.prepare_instance_network()
|
|
||||||
super(ServersV3Test, cls).resource_setup()
|
|
||||||
cls.meta = {'hello': 'world'}
|
|
||||||
cls.accessIPv4 = '1.1.1.1'
|
|
||||||
cls.accessIPv6 = '0000:0000:0000:0000:0000:babe:220.12.22.2'
|
|
||||||
cls.name = data_utils.rand_name('server')
|
|
||||||
file_contents = 'This is a test file.'
|
|
||||||
personality = [{'path': '/test.txt',
|
|
||||||
'contents': base64.b64encode(file_contents)}]
|
|
||||||
cls.client = cls.servers_client
|
|
||||||
cli_resp = cls.create_test_server(name=cls.name,
|
|
||||||
meta=cls.meta,
|
|
||||||
access_ip_v4=cls.accessIPv4,
|
|
||||||
access_ip_v6=cls.accessIPv6,
|
|
||||||
personality=personality,
|
|
||||||
disk_config=cls.disk_config)
|
|
||||||
cls.resp, cls.server_initial = cli_resp
|
|
||||||
cls.password = cls.server_initial['admin_password']
|
|
||||||
cls.client.wait_for_server_status(cls.server_initial['id'], 'ACTIVE')
|
|
||||||
resp, cls.server = cls.client.get_server(cls.server_initial['id'])
|
|
||||||
|
|
||||||
@test.attr(type='smoke')
|
|
||||||
def test_verify_server_details(self):
|
|
||||||
# Verify the specified server attributes are set correctly
|
|
||||||
self.assertEqual(self.accessIPv4,
|
|
||||||
self.server['os-access-ips:access_ip_v4'])
|
|
||||||
# NOTE(maurosr): See http://tools.ietf.org/html/rfc5952 (section 4)
|
|
||||||
# Here we compare directly with the canonicalized format.
|
|
||||||
self.assertEqual(self.server['os-access-ips:access_ip_v6'],
|
|
||||||
str(netaddr.IPAddress(self.accessIPv6)))
|
|
||||||
self.assertEqual(self.name, self.server['name'])
|
|
||||||
self.assertEqual(self.image_ref, self.server['image']['id'])
|
|
||||||
self.assertEqual(self.flavor_ref, self.server['flavor']['id'])
|
|
||||||
self.assertEqual(self.meta, self.server['metadata'])
|
|
||||||
|
|
||||||
@test.attr(type='smoke')
|
|
||||||
def test_list_servers(self):
|
|
||||||
# The created server should be in the list of all servers
|
|
||||||
resp, body = self.client.list_servers()
|
|
||||||
servers = body['servers']
|
|
||||||
found = any([i for i in servers if i['id'] == self.server['id']])
|
|
||||||
self.assertTrue(found)
|
|
||||||
|
|
||||||
@test.attr(type='smoke')
|
|
||||||
def test_list_servers_with_detail(self):
|
|
||||||
# The created server should be in the detailed list of all servers
|
|
||||||
resp, body = self.client.list_servers_with_detail()
|
|
||||||
servers = body['servers']
|
|
||||||
found = any([i for i in servers if i['id'] == self.server['id']])
|
|
||||||
self.assertTrue(found)
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute.run_ssh,
|
|
||||||
'Instance validation tests are disabled.')
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_verify_created_server_vcpus(self):
|
|
||||||
# Verify that the number of vcpus reported by the instance matches
|
|
||||||
# the amount stated by the flavor
|
|
||||||
resp, flavor = self.flavors_client.get_flavor_details(self.flavor_ref)
|
|
||||||
linux_client = remote_client.RemoteClient(self.server,
|
|
||||||
self.ssh_user, self.password)
|
|
||||||
self.assertEqual(flavor['vcpus'], linux_client.get_number_of_vcpus())
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute.run_ssh,
|
|
||||||
'Instance validation tests are disabled.')
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_host_name_is_same_as_server_name(self):
|
|
||||||
# Verify the instance host name is the same as the server name
|
|
||||||
linux_client = remote_client.RemoteClient(self.server,
|
|
||||||
self.ssh_user, self.password)
|
|
||||||
self.assertTrue(linux_client.hostname_equals_servername(self.name))
|
|
||||||
|
|
||||||
|
|
||||||
class ServersWithSpecificFlavorV3Test(base.BaseV3ComputeAdminTest):
|
|
||||||
disk_config = 'AUTO'
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
cls.prepare_instance_network()
|
|
||||||
super(ServersWithSpecificFlavorV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.servers_client
|
|
||||||
cls.flavor_client = cls.flavors_admin_client
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute.run_ssh,
|
|
||||||
'Instance validation tests are disabled.')
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_verify_created_server_ephemeral_disk(self):
|
|
||||||
# Verify that the ephemeral disk is created when creating server
|
|
||||||
|
|
||||||
def create_flavor_with_extra_specs():
|
|
||||||
flavor_with_eph_disk_name = data_utils.rand_name('eph_flavor')
|
|
||||||
flavor_with_eph_disk_id = data_utils.rand_int_id(start=1000)
|
|
||||||
ram = 512
|
|
||||||
vcpus = 1
|
|
||||||
disk = 10
|
|
||||||
|
|
||||||
# Create a flavor with extra specs
|
|
||||||
resp, flavor = (self.flavor_client.
|
|
||||||
create_flavor(flavor_with_eph_disk_name,
|
|
||||||
ram, vcpus, disk,
|
|
||||||
flavor_with_eph_disk_id,
|
|
||||||
ephemeral=1, rxtx=1))
|
|
||||||
self.addCleanup(flavor_clean_up, flavor['id'])
|
|
||||||
self.assertEqual(201, resp.status)
|
|
||||||
|
|
||||||
return flavor['id']
|
|
||||||
|
|
||||||
def create_flavor_without_extra_specs():
|
|
||||||
flavor_no_eph_disk_name = data_utils.rand_name('no_eph_flavor')
|
|
||||||
flavor_no_eph_disk_id = data_utils.rand_int_id(start=1000)
|
|
||||||
|
|
||||||
ram = 512
|
|
||||||
vcpus = 1
|
|
||||||
disk = 10
|
|
||||||
|
|
||||||
# Create a flavor without extra specs
|
|
||||||
resp, flavor = (self.flavor_client.
|
|
||||||
create_flavor(flavor_no_eph_disk_name,
|
|
||||||
ram, vcpus, disk,
|
|
||||||
flavor_no_eph_disk_id))
|
|
||||||
self.addCleanup(flavor_clean_up, flavor['id'])
|
|
||||||
self.assertEqual(201, resp.status)
|
|
||||||
|
|
||||||
return flavor['id']
|
|
||||||
|
|
||||||
def flavor_clean_up(flavor_id):
|
|
||||||
resp, body = self.flavor_client.delete_flavor(flavor_id)
|
|
||||||
self.assertEqual(resp.status, 204)
|
|
||||||
self.flavor_client.wait_for_resource_deletion(flavor_id)
|
|
||||||
|
|
||||||
flavor_with_eph_disk_id = create_flavor_with_extra_specs()
|
|
||||||
flavor_no_eph_disk_id = create_flavor_without_extra_specs()
|
|
||||||
|
|
||||||
admin_pass = self.image_ssh_password
|
|
||||||
|
|
||||||
resp, server_no_eph_disk = (self.create_test_server(
|
|
||||||
wait_until='ACTIVE',
|
|
||||||
adminPass=admin_pass,
|
|
||||||
flavor=flavor_no_eph_disk_id))
|
|
||||||
resp, server_with_eph_disk = (self.create_test_server(
|
|
||||||
wait_until='ACTIVE',
|
|
||||||
adminPass=admin_pass,
|
|
||||||
flavor=flavor_with_eph_disk_id))
|
|
||||||
# Get partition number of server without extra specs.
|
|
||||||
_, server_no_eph_disk = self.client.get_server(
|
|
||||||
server_no_eph_disk['id'])
|
|
||||||
linux_client = remote_client.RemoteClient(server_no_eph_disk,
|
|
||||||
self.ssh_user, admin_pass)
|
|
||||||
partition_num = len(linux_client.get_partitions().split('\n'))
|
|
||||||
_, server_with_eph_disk = self.client.get_server(
|
|
||||||
server_with_eph_disk['id'])
|
|
||||||
linux_client = remote_client.RemoteClient(server_with_eph_disk,
|
|
||||||
self.ssh_user, admin_pass)
|
|
||||||
partition_num_emph = len(linux_client.get_partitions().split('\n'))
|
|
||||||
self.assertEqual(partition_num + 1, partition_num_emph)
|
|
||||||
|
|
||||||
|
|
||||||
class ServersV3TestManualDisk(ServersV3Test):
|
|
||||||
disk_config = 'MANUAL'
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
if not CONF.compute_feature_enabled.disk_config:
|
|
||||||
msg = "DiskConfig extension not enabled."
|
|
||||||
raise cls.skipException(msg)
|
|
||||||
super(ServersV3TestManualDisk, cls).resource_setup()
|
|
@ -1,156 +0,0 @@
|
|||||||
# Copyright 2012 OpenStack Foundation
|
|
||||||
#
|
|
||||||
# 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 testtools
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest import config
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
CONF = config.CONF
|
|
||||||
|
|
||||||
|
|
||||||
class DeleteServersV3Test(base.BaseV3ComputeTest):
|
|
||||||
# NOTE: Server creations of each test class should be under 10
|
|
||||||
# for preventing "Quota exceeded for instances".
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(DeleteServersV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.servers_client
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_delete_server_while_in_building_state(self):
|
|
||||||
# Delete a server while it's VM state is Building
|
|
||||||
resp, server = self.create_test_server(wait_until='BUILD')
|
|
||||||
resp, _ = self.client.delete_server(server['id'])
|
|
||||||
self.assertEqual('204', resp['status'])
|
|
||||||
self.client.wait_for_server_termination(server['id'])
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_delete_active_server(self):
|
|
||||||
# Delete a server while it's VM state is Active
|
|
||||||
resp, server = self.create_test_server(wait_until='ACTIVE')
|
|
||||||
resp, _ = self.client.delete_server(server['id'])
|
|
||||||
self.assertEqual('204', resp['status'])
|
|
||||||
self.client.wait_for_server_termination(server['id'])
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_delete_server_while_in_shutoff_state(self):
|
|
||||||
# Delete a server while it's VM state is Shutoff
|
|
||||||
resp, server = self.create_test_server(wait_until='ACTIVE')
|
|
||||||
resp, body = self.client.stop(server['id'])
|
|
||||||
self.client.wait_for_server_status(server['id'], 'SHUTOFF')
|
|
||||||
resp, _ = self.client.delete_server(server['id'])
|
|
||||||
self.assertEqual('204', resp['status'])
|
|
||||||
self.client.wait_for_server_termination(server['id'])
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.pause,
|
|
||||||
'Pause is not available.')
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_delete_server_while_in_pause_state(self):
|
|
||||||
# Delete a server while it's VM state is Pause
|
|
||||||
resp, server = self.create_test_server(wait_until='ACTIVE')
|
|
||||||
resp, body = self.client.pause_server(server['id'])
|
|
||||||
self.client.wait_for_server_status(server['id'], 'PAUSED')
|
|
||||||
resp, _ = self.client.delete_server(server['id'])
|
|
||||||
self.assertEqual('204', resp['status'])
|
|
||||||
self.client.wait_for_server_termination(server['id'])
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.shelve,
|
|
||||||
'Shelve is not available.')
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_delete_server_while_in_shelved_state(self):
|
|
||||||
# Delete a server while it's VM state is Shelved
|
|
||||||
resp, server = self.create_test_server(wait_until='ACTIVE')
|
|
||||||
resp, body = self.client.shelve_server(server['id'])
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
|
|
||||||
offload_time = CONF.compute.shelved_offload_time
|
|
||||||
if offload_time >= 0:
|
|
||||||
self.client.wait_for_server_status(server['id'],
|
|
||||||
'SHELVED_OFFLOADED',
|
|
||||||
extra_timeout=offload_time)
|
|
||||||
else:
|
|
||||||
self.client.wait_for_server_status(server['id'],
|
|
||||||
'SHELVED')
|
|
||||||
|
|
||||||
resp, _ = self.client.delete_server(server['id'])
|
|
||||||
self.assertEqual('204', resp['status'])
|
|
||||||
self.client.wait_for_server_termination(server['id'])
|
|
||||||
|
|
||||||
@testtools.skipIf(not CONF.compute_feature_enabled.resize,
|
|
||||||
'Resize not available.')
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_delete_server_while_in_verify_resize_state(self):
|
|
||||||
# Delete a server while it's VM state is VERIFY_RESIZE
|
|
||||||
resp, server = self.create_test_server(wait_until='ACTIVE')
|
|
||||||
resp, body = self.client.resize(server['id'], self.flavor_ref_alt)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.client.wait_for_server_status(server['id'], 'VERIFY_RESIZE')
|
|
||||||
resp, _ = self.client.delete_server(server['id'])
|
|
||||||
self.assertEqual('204', resp['status'])
|
|
||||||
self.client.wait_for_server_termination(server['id'])
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_delete_server_while_in_attached_volume(self):
|
|
||||||
# Delete a server while a volume is attached to it
|
|
||||||
device = '/dev/%s' % CONF.compute.volume_device_name
|
|
||||||
resp, server = self.create_test_server(wait_until='ACTIVE')
|
|
||||||
|
|
||||||
resp, volume = self.volumes_client.create_volume(1)
|
|
||||||
self.addCleanup(self.volumes_client.delete_volume, volume['id'])
|
|
||||||
self.volumes_client.wait_for_volume_status(volume['id'], 'available')
|
|
||||||
resp, body = self.client.attach_volume(server['id'],
|
|
||||||
volume['id'],
|
|
||||||
device=device)
|
|
||||||
self.volumes_client.wait_for_volume_status(volume['id'], 'in-use')
|
|
||||||
|
|
||||||
resp, _ = self.client.delete_server(server['id'])
|
|
||||||
self.assertEqual('204', resp['status'])
|
|
||||||
self.client.wait_for_server_termination(server['id'])
|
|
||||||
self.volumes_client.wait_for_volume_status(volume['id'], 'available')
|
|
||||||
|
|
||||||
|
|
||||||
class DeleteServersAdminV3Test(base.BaseV3ComputeAdminTest):
|
|
||||||
# NOTE: Server creations of each test class should be under 10
|
|
||||||
# for preventing "Quota exceeded for instances".
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(DeleteServersAdminV3Test, cls).resource_setup()
|
|
||||||
cls.non_admin_client = cls.servers_client
|
|
||||||
cls.admin_client = cls.servers_admin_client
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_delete_server_while_in_error_state(self):
|
|
||||||
# Delete a server while it's VM state is error
|
|
||||||
resp, server = self.create_test_server(wait_until='ACTIVE')
|
|
||||||
resp, body = self.admin_client.reset_state(server['id'], state='error')
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
# Verify server's state
|
|
||||||
resp, server = self.non_admin_client.get_server(server['id'])
|
|
||||||
self.assertEqual(server['status'], 'ERROR')
|
|
||||||
resp, _ = self.non_admin_client.delete_server(server['id'])
|
|
||||||
self.assertEqual('204', resp['status'])
|
|
||||||
self.servers_client.wait_for_server_termination(server['id'],
|
|
||||||
ignore_error=True)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_admin_delete_servers_of_others(self):
|
|
||||||
# Administrator can delete servers of others
|
|
||||||
resp, server = self.create_test_server(wait_until='ACTIVE')
|
|
||||||
resp, _ = self.admin_client.delete_server(server['id'])
|
|
||||||
self.assertEqual('204', resp['status'])
|
|
||||||
self.servers_client.wait_for_server_termination(server['id'])
|
|
@ -1,50 +0,0 @@
|
|||||||
# 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 tempest.api.compute import base
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class InstanceActionsV3Test(base.BaseV3ComputeTest):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(InstanceActionsV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.servers_client
|
|
||||||
resp, server = cls.create_test_server(wait_until='ACTIVE')
|
|
||||||
cls.resp = resp
|
|
||||||
cls.server_id = server['id']
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_server_actions(self):
|
|
||||||
# List actions of the provided server
|
|
||||||
resp, body = self.client.reboot(self.server_id, 'HARD')
|
|
||||||
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
||||||
|
|
||||||
resp, body = self.client.list_server_actions(self.server_id)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertTrue(len(body) == 2, str(body))
|
|
||||||
self.assertTrue(any([i for i in body if i['action'] == 'create']))
|
|
||||||
self.assertTrue(any([i for i in body if i['action'] == 'reboot']))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_get_server_action(self):
|
|
||||||
# Get the action details of the provided server
|
|
||||||
request_id = self.resp['x-openstack-request-id']
|
|
||||||
resp, body = self.client.get_server_action(self.server_id,
|
|
||||||
request_id)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(self.server_id, body['server_uuid'])
|
|
||||||
self.assertEqual('create', body['action'])
|
|
@ -1,43 +0,0 @@
|
|||||||
# 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.
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class InstanceActionsNegativeV3Test(base.BaseV3ComputeTest):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(InstanceActionsNegativeV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.servers_client
|
|
||||||
resp, server = cls.create_test_server(wait_until='ACTIVE')
|
|
||||||
cls.server_id = server['id']
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_list_server_actions_invalid_server(self):
|
|
||||||
# List actions of the invalid server id
|
|
||||||
invalid_server_id = data_utils.rand_uuid()
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.list_server_actions, invalid_server_id)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_get_server_action_invalid_request(self):
|
|
||||||
# Get the action details of the provided server with invalid request
|
|
||||||
invalid_request_id = 'req-' + data_utils.rand_uuid()
|
|
||||||
self.assertRaises(exceptions.NotFound, self.client.get_server_action,
|
|
||||||
self.server_id, invalid_request_id)
|
|
@ -1,269 +0,0 @@
|
|||||||
# Copyright 2012 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.
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest.api import utils
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import config
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
CONF = config.CONF
|
|
||||||
|
|
||||||
|
|
||||||
class ListServerFiltersV3Test(base.BaseV3ComputeTest):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
cls.set_network_resources(network=True, subnet=True, dhcp=True)
|
|
||||||
super(ListServerFiltersV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.servers_client
|
|
||||||
|
|
||||||
# Check to see if the alternate image ref actually exists...
|
|
||||||
images_client = cls.images_client
|
|
||||||
resp, images = images_client.image_list()
|
|
||||||
|
|
||||||
if cls.image_ref != cls.image_ref_alt and \
|
|
||||||
any([image for image in images
|
|
||||||
if image['id'] == cls.image_ref_alt]):
|
|
||||||
cls.multiple_images = True
|
|
||||||
else:
|
|
||||||
cls.image_ref_alt = cls.image_ref
|
|
||||||
|
|
||||||
# Do some sanity checks here. If one of the images does
|
|
||||||
# not exist, fail early since the tests won't work...
|
|
||||||
try:
|
|
||||||
cls.images_client.get_image_meta(cls.image_ref)
|
|
||||||
except exceptions.NotFound:
|
|
||||||
raise RuntimeError("Image %s (image_ref) was not found!" %
|
|
||||||
cls.image_ref)
|
|
||||||
|
|
||||||
try:
|
|
||||||
cls.images_client.get_image_meta(cls.image_ref_alt)
|
|
||||||
except exceptions.NotFound:
|
|
||||||
raise RuntimeError("Image %s (image_ref_alt) was not found!" %
|
|
||||||
cls.image_ref_alt)
|
|
||||||
|
|
||||||
cls.s1_name = data_utils.rand_name(cls.__name__ + '-instance')
|
|
||||||
resp, cls.s1 = cls.create_test_server(name=cls.s1_name,
|
|
||||||
wait_until='ACTIVE')
|
|
||||||
|
|
||||||
cls.s2_name = data_utils.rand_name(cls.__name__ + '-instance')
|
|
||||||
resp, cls.s2 = cls.create_test_server(name=cls.s2_name,
|
|
||||||
image_id=cls.image_ref_alt,
|
|
||||||
wait_until='ACTIVE')
|
|
||||||
|
|
||||||
cls.s3_name = data_utils.rand_name(cls.__name__ + '-instance')
|
|
||||||
resp, cls.s3 = cls.create_test_server(name=cls.s3_name,
|
|
||||||
flavor=cls.flavor_ref_alt,
|
|
||||||
wait_until='ACTIVE')
|
|
||||||
|
|
||||||
cls.fixed_network_name = CONF.compute.fixed_network_name
|
|
||||||
if CONF.service_available.neutron:
|
|
||||||
if hasattr(cls.isolated_creds, 'get_primary_network'):
|
|
||||||
network = cls.isolated_creds.get_primary_network()
|
|
||||||
cls.fixed_network_name = network['name']
|
|
||||||
|
|
||||||
@utils.skip_unless_attr('multiple_images', 'Only one image found')
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_servers_filter_by_image(self):
|
|
||||||
# Filter the list of servers by image
|
|
||||||
params = {'image': self.image_ref}
|
|
||||||
resp, body = self.client.list_servers(params)
|
|
||||||
servers = body['servers']
|
|
||||||
|
|
||||||
self.assertIn(self.s1['id'], map(lambda x: x['id'], servers))
|
|
||||||
self.assertNotIn(self.s2['id'], map(lambda x: x['id'], servers))
|
|
||||||
self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_servers_filter_by_flavor(self):
|
|
||||||
# Filter the list of servers by flavor
|
|
||||||
params = {'flavor': self.flavor_ref_alt}
|
|
||||||
resp, body = self.client.list_servers(params)
|
|
||||||
servers = body['servers']
|
|
||||||
|
|
||||||
self.assertNotIn(self.s1['id'], map(lambda x: x['id'], servers))
|
|
||||||
self.assertNotIn(self.s2['id'], map(lambda x: x['id'], servers))
|
|
||||||
self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_servers_filter_by_server_name(self):
|
|
||||||
# Filter the list of servers by server name
|
|
||||||
params = {'name': self.s1_name}
|
|
||||||
resp, body = self.client.list_servers(params)
|
|
||||||
servers = body['servers']
|
|
||||||
|
|
||||||
self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
|
|
||||||
self.assertNotIn(self.s2_name, map(lambda x: x['name'], servers))
|
|
||||||
self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_servers_filter_by_server_status(self):
|
|
||||||
# Filter the list of servers by server status
|
|
||||||
params = {'status': 'active'}
|
|
||||||
resp, body = self.client.list_servers(params)
|
|
||||||
servers = body['servers']
|
|
||||||
|
|
||||||
self.assertIn(self.s1['id'], map(lambda x: x['id'], servers))
|
|
||||||
self.assertIn(self.s2['id'], map(lambda x: x['id'], servers))
|
|
||||||
self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_servers_filter_by_limit(self):
|
|
||||||
# Verify only the expected number of servers are returned
|
|
||||||
params = {'limit': 1}
|
|
||||||
resp, servers = self.client.list_servers(params)
|
|
||||||
self.assertEqual(1, len([x for x in servers['servers'] if 'id' in x]))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_servers_filter_by_zero_limit(self):
|
|
||||||
# Verify only the expected number of servers are returned
|
|
||||||
params = {'limit': 0}
|
|
||||||
resp, servers = self.client.list_servers(params)
|
|
||||||
self.assertEqual(0, len(servers['servers']))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_servers_filter_by_exceed_limit(self):
|
|
||||||
# Verify only the expected number of servers are returned
|
|
||||||
params = {'limit': 100000}
|
|
||||||
resp, servers = self.client.list_servers(params)
|
|
||||||
resp, all_servers = self.client.list_servers()
|
|
||||||
self.assertEqual(len([x for x in all_servers['servers'] if 'id' in x]),
|
|
||||||
len([x for x in servers['servers'] if 'id' in x]))
|
|
||||||
|
|
||||||
@utils.skip_unless_attr('multiple_images', 'Only one image found')
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_servers_detailed_filter_by_image(self):
|
|
||||||
# Filter the detailed list of servers by image
|
|
||||||
params = {'image': self.image_ref}
|
|
||||||
resp, body = self.client.list_servers_with_detail(params)
|
|
||||||
servers = body['servers']
|
|
||||||
|
|
||||||
self.assertIn(self.s1['id'], map(lambda x: x['id'], servers))
|
|
||||||
self.assertNotIn(self.s2['id'], map(lambda x: x['id'], servers))
|
|
||||||
self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_servers_detailed_filter_by_flavor(self):
|
|
||||||
# Filter the detailed list of servers by flavor
|
|
||||||
params = {'flavor': self.flavor_ref_alt}
|
|
||||||
resp, body = self.client.list_servers_with_detail(params)
|
|
||||||
servers = body['servers']
|
|
||||||
|
|
||||||
self.assertNotIn(self.s1['id'], map(lambda x: x['id'], servers))
|
|
||||||
self.assertNotIn(self.s2['id'], map(lambda x: x['id'], servers))
|
|
||||||
self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_servers_detailed_filter_by_server_name(self):
|
|
||||||
# Filter the detailed list of servers by server name
|
|
||||||
params = {'name': self.s1_name}
|
|
||||||
resp, body = self.client.list_servers_with_detail(params)
|
|
||||||
servers = body['servers']
|
|
||||||
|
|
||||||
self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
|
|
||||||
self.assertNotIn(self.s2_name, map(lambda x: x['name'], servers))
|
|
||||||
self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_servers_detailed_filter_by_server_status(self):
|
|
||||||
# Filter the detailed list of servers by server status
|
|
||||||
params = {'status': 'active'}
|
|
||||||
resp, body = self.client.list_servers_with_detail(params)
|
|
||||||
expected_servers = (self.s1['id'], self.s2['id'], self.s3['id'])
|
|
||||||
servers = [x for x in body['servers'] if x['id'] in expected_servers]
|
|
||||||
|
|
||||||
self.assertIn(self.s1['id'], map(lambda x: x['id'], servers))
|
|
||||||
self.assertIn(self.s2['id'], map(lambda x: x['id'], servers))
|
|
||||||
self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
|
|
||||||
self.assertEqual(['ACTIVE'] * 3, [x['status'] for x in servers])
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_servers_filter_by_shutoff_status(self):
|
|
||||||
# Filter the list of servers by server shutoff status
|
|
||||||
params = {'status': 'shutoff'}
|
|
||||||
self.client.stop(self.s1['id'])
|
|
||||||
self.client.wait_for_server_status(self.s1['id'],
|
|
||||||
'SHUTOFF')
|
|
||||||
resp, body = self.client.list_servers(params)
|
|
||||||
self.client.start(self.s1['id'])
|
|
||||||
self.client.wait_for_server_status(self.s1['id'],
|
|
||||||
'ACTIVE')
|
|
||||||
servers = body['servers']
|
|
||||||
|
|
||||||
self.assertIn(self.s1['id'], map(lambda x: x['id'], servers))
|
|
||||||
self.assertNotIn(self.s2['id'], map(lambda x: x['id'], servers))
|
|
||||||
self.assertNotIn(self.s3['id'], map(lambda x: x['id'], servers))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_servers_filtered_by_name_wildcard(self):
|
|
||||||
# List all servers that contains '-instance' in name
|
|
||||||
params = {'name': '-instance'}
|
|
||||||
resp, body = self.client.list_servers(params)
|
|
||||||
servers = body['servers']
|
|
||||||
|
|
||||||
self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
|
|
||||||
self.assertIn(self.s2_name, map(lambda x: x['name'], servers))
|
|
||||||
self.assertIn(self.s3_name, map(lambda x: x['name'], servers))
|
|
||||||
|
|
||||||
# Let's take random part of name and try to search it
|
|
||||||
part_name = self.s1_name[6:-1]
|
|
||||||
|
|
||||||
params = {'name': part_name}
|
|
||||||
resp, body = self.client.list_servers(params)
|
|
||||||
servers = body['servers']
|
|
||||||
|
|
||||||
self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
|
|
||||||
self.assertNotIn(self.s2_name, map(lambda x: x['name'], servers))
|
|
||||||
self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_servers_filtered_by_ip(self):
|
|
||||||
# Filter servers by ip
|
|
||||||
# Here should be listed 1 server
|
|
||||||
resp, self.s1 = self.client.get_server(self.s1['id'])
|
|
||||||
ip = self.s1['addresses'][self.fixed_network_name][0]['addr']
|
|
||||||
params = {'ip': ip}
|
|
||||||
resp, body = self.client.list_servers(params)
|
|
||||||
servers = body['servers']
|
|
||||||
|
|
||||||
self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
|
|
||||||
self.assertNotIn(self.s2_name, map(lambda x: x['name'], servers))
|
|
||||||
self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
|
|
||||||
|
|
||||||
@test.skip_because(bug="1182883",
|
|
||||||
condition=CONF.service_available.neutron)
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_servers_filtered_by_ip_regex(self):
|
|
||||||
# Filter servers by regex ip
|
|
||||||
# List all servers filtered by part of ip address.
|
|
||||||
# Here should be listed all servers
|
|
||||||
resp, self.s1 = self.client.get_server(self.s1['id'])
|
|
||||||
ip = self.s1['addresses'][self.fixed_network_name][0]['addr'][0:-3]
|
|
||||||
params = {'ip': ip}
|
|
||||||
resp, body = self.client.list_servers(params)
|
|
||||||
servers = body['servers']
|
|
||||||
|
|
||||||
self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
|
|
||||||
self.assertIn(self.s2_name, map(lambda x: x['name'], servers))
|
|
||||||
self.assertIn(self.s3_name, map(lambda x: x['name'], servers))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_servers_detailed_limit_results(self):
|
|
||||||
# Verify only the expected number of detailed results are returned
|
|
||||||
params = {'limit': 1}
|
|
||||||
resp, servers = self.client.list_servers_with_detail(params)
|
|
||||||
self.assertEqual(1, len(servers['servers']))
|
|
@ -1,164 +0,0 @@
|
|||||||
# Copyright 2012 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
|
|
||||||
|
|
||||||
from six import moves
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class ListServersNegativeV3Test(base.BaseV3ComputeTest):
|
|
||||||
force_tenant_isolation = True
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(ListServersNegativeV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.servers_client
|
|
||||||
|
|
||||||
# The following servers are created for use
|
|
||||||
# by the test methods in this class. These
|
|
||||||
# servers are cleaned up automatically in the
|
|
||||||
# tearDownClass method of the super-class.
|
|
||||||
cls.existing_fixtures = []
|
|
||||||
cls.deleted_fixtures = []
|
|
||||||
cls.start_time = datetime.datetime.utcnow()
|
|
||||||
for x in moves.xrange(2):
|
|
||||||
resp, srv = cls.create_test_server(wait_until='ACTIVE')
|
|
||||||
cls.existing_fixtures.append(srv)
|
|
||||||
|
|
||||||
resp, srv = cls.create_test_server()
|
|
||||||
cls.client.delete_server(srv['id'])
|
|
||||||
# We ignore errors on termination because the server may
|
|
||||||
# be put into ERROR status on a quick spawn, then delete,
|
|
||||||
# as the compute node expects the instance local status
|
|
||||||
# to be spawning, not deleted. See LP Bug#1061167
|
|
||||||
cls.client.wait_for_server_termination(srv['id'],
|
|
||||||
ignore_error=True)
|
|
||||||
cls.deleted_fixtures.append(srv)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_list_servers_with_a_deleted_server(self):
|
|
||||||
# Verify deleted servers do not show by default in list servers
|
|
||||||
# List servers and verify server not returned
|
|
||||||
resp, body = self.client.list_servers()
|
|
||||||
servers = body['servers']
|
|
||||||
deleted_ids = [s['id'] for s in self.deleted_fixtures]
|
|
||||||
actual = [srv for srv in servers
|
|
||||||
if srv['id'] in deleted_ids]
|
|
||||||
self.assertEqual('200', resp['status'])
|
|
||||||
self.assertEqual([], actual)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_list_servers_by_non_existing_image(self):
|
|
||||||
# Listing servers for a non existing image returns empty list
|
|
||||||
non_existing_image = '1234abcd-zzz0-aaa9-ppp3-0987654abcde'
|
|
||||||
resp, body = self.client.list_servers(dict(image=non_existing_image))
|
|
||||||
servers = body['servers']
|
|
||||||
self.assertEqual('200', resp['status'])
|
|
||||||
self.assertEqual([], servers)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_list_servers_by_non_existing_flavor(self):
|
|
||||||
# Listing servers by non existing flavor returns empty list
|
|
||||||
non_existing_flavor = 1234
|
|
||||||
resp, body = self.client.list_servers(dict(flavor=non_existing_flavor))
|
|
||||||
servers = body['servers']
|
|
||||||
self.assertEqual('200', resp['status'])
|
|
||||||
self.assertEqual([], servers)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_list_servers_by_non_existing_server_name(self):
|
|
||||||
# Listing servers for a non existent server name returns empty list
|
|
||||||
non_existing_name = 'junk_server_1234'
|
|
||||||
resp, body = self.client.list_servers(dict(name=non_existing_name))
|
|
||||||
servers = body['servers']
|
|
||||||
self.assertEqual('200', resp['status'])
|
|
||||||
self.assertEqual([], servers)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_list_servers_status_non_existing(self):
|
|
||||||
# Return an empty list when invalid status is specified
|
|
||||||
non_existing_status = 'BALONEY'
|
|
||||||
resp, body = self.client.list_servers(dict(status=non_existing_status))
|
|
||||||
servers = body['servers']
|
|
||||||
self.assertEqual('200', resp['status'])
|
|
||||||
self.assertEqual([], servers)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_servers_by_limits(self):
|
|
||||||
# List servers by specifying limits
|
|
||||||
resp, body = self.client.list_servers({'limit': 1})
|
|
||||||
self.assertEqual('200', resp['status'])
|
|
||||||
self.assertEqual(1, len([x for x in body['servers'] if 'id' in x]))
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_list_servers_by_limits_greater_than_actual_count(self):
|
|
||||||
# List servers by specifying a greater value for limit
|
|
||||||
resp, body = self.client.list_servers({'limit': 100})
|
|
||||||
self.assertEqual('200', resp['status'])
|
|
||||||
self.assertEqual(len(self.existing_fixtures), len(body['servers']))
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_list_servers_by_limits_pass_string(self):
|
|
||||||
# Return an error if a string value is passed for limit
|
|
||||||
self.assertRaises(exceptions.BadRequest, self.client.list_servers,
|
|
||||||
{'limit': 'testing'})
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_list_servers_by_limits_pass_negative_value(self):
|
|
||||||
# Return an error if a negative value for limit is passed
|
|
||||||
self.assertRaises(exceptions.BadRequest, self.client.list_servers,
|
|
||||||
{'limit': -1})
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_servers_by_changes_since(self):
|
|
||||||
# Servers are listed by specifying changes-since date
|
|
||||||
changes_since = {'changes_since': self.start_time.isoformat()}
|
|
||||||
resp, body = self.client.list_servers(changes_since)
|
|
||||||
self.assertEqual('200', resp['status'])
|
|
||||||
# changes-since returns all instances, including deleted.
|
|
||||||
num_expected = (len(self.existing_fixtures) +
|
|
||||||
len(self.deleted_fixtures))
|
|
||||||
self.assertEqual(num_expected, len(body['servers']),
|
|
||||||
"Number of servers %d is wrong in %s" %
|
|
||||||
(num_expected, body['servers']))
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_list_servers_by_changes_since_invalid_date(self):
|
|
||||||
# Return an error when invalid date format is passed
|
|
||||||
self.assertRaises(exceptions.BadRequest, self.client.list_servers,
|
|
||||||
{'changes_since': '2011/01/01'})
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_list_servers_by_changes_since_future_date(self):
|
|
||||||
# Return an empty list when a date in the future is passed
|
|
||||||
changes_since = {'changes_since': '2051-01-01T12:34:00Z'}
|
|
||||||
resp, body = self.client.list_servers(changes_since)
|
|
||||||
self.assertEqual('200', resp['status'])
|
|
||||||
self.assertEqual(0, len(body['servers']))
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_list_servers_detail_server_is_deleted(self):
|
|
||||||
# Server details are not listed for a deleted server
|
|
||||||
deleted_ids = [s['id'] for s in self.deleted_fixtures]
|
|
||||||
resp, body = self.client.list_servers_with_detail()
|
|
||||||
servers = body['servers']
|
|
||||||
actual = [srv for srv in servers
|
|
||||||
if srv['id'] in deleted_ids]
|
|
||||||
self.assertEqual('200', resp['status'])
|
|
||||||
self.assertEqual([], actual)
|
|
@ -1,55 +0,0 @@
|
|||||||
# Copyright 2013 IBM Corp
|
|
||||||
# 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.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class MultipleCreateV3Test(base.BaseV3ComputeTest):
|
|
||||||
_name = 'multiple-create-test'
|
|
||||||
|
|
||||||
def _generate_name(self):
|
|
||||||
return data_utils.rand_name(self._name)
|
|
||||||
|
|
||||||
def _create_multiple_servers(self, name=None, wait_until=None, **kwargs):
|
|
||||||
"""
|
|
||||||
This is the right way to create_multiple servers and manage to get the
|
|
||||||
created servers into the servers list to be cleaned up after all.
|
|
||||||
"""
|
|
||||||
kwargs['name'] = kwargs.get('name', self._generate_name())
|
|
||||||
resp, body = self.create_test_server(**kwargs)
|
|
||||||
|
|
||||||
return resp, body
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_multiple_create(self):
|
|
||||||
resp, body = self._create_multiple_servers(wait_until='ACTIVE',
|
|
||||||
min_count=1,
|
|
||||||
max_count=2)
|
|
||||||
# NOTE(maurosr): do status response check and also make sure that
|
|
||||||
# reservation_id is not in the response body when the request send
|
|
||||||
# contains return_reservation_id=False
|
|
||||||
self.assertEqual('202', resp['status'])
|
|
||||||
self.assertNotIn('reservation_id', body)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_multiple_create_with_reservation_return(self):
|
|
||||||
resp, body = self._create_multiple_servers(wait_until='ACTIVE',
|
|
||||||
min_count=1,
|
|
||||||
max_count=2,
|
|
||||||
return_reservation_id=True)
|
|
||||||
self.assertEqual(resp['status'], '202')
|
|
||||||
self.assertIn('reservation_id', body)
|
|
@ -1,68 +0,0 @@
|
|||||||
# Copyright 2013 IBM Corp
|
|
||||||
# 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.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class MultipleCreateV3NegativeTest(base.BaseV3ComputeTest):
|
|
||||||
_name = 'multiple-create-negative-test'
|
|
||||||
|
|
||||||
def _generate_name(self):
|
|
||||||
return data_utils.rand_name(self._name)
|
|
||||||
|
|
||||||
def _create_multiple_servers(self, name=None, wait_until=None, **kwargs):
|
|
||||||
"""
|
|
||||||
This is the right way to create_multiple servers and manage to get the
|
|
||||||
created servers into the servers list to be cleaned up after all.
|
|
||||||
"""
|
|
||||||
kwargs['name'] = kwargs.get('name', self._generate_name())
|
|
||||||
resp, body = self.create_test_server(**kwargs)
|
|
||||||
|
|
||||||
return resp, body
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_min_count_less_than_one(self):
|
|
||||||
invalid_min_count = 0
|
|
||||||
self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
|
|
||||||
min_count=invalid_min_count)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_min_count_non_integer(self):
|
|
||||||
invalid_min_count = 2.5
|
|
||||||
self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
|
|
||||||
min_count=invalid_min_count)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_max_count_less_than_one(self):
|
|
||||||
invalid_max_count = 0
|
|
||||||
self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
|
|
||||||
max_count=invalid_max_count)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_max_count_non_integer(self):
|
|
||||||
invalid_max_count = 2.5
|
|
||||||
self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
|
|
||||||
max_count=invalid_max_count)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_max_count_less_than_min_count(self):
|
|
||||||
min_count = 3
|
|
||||||
max_count = 2
|
|
||||||
self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
|
|
||||||
min_count=min_count,
|
|
||||||
max_count=max_count)
|
|
@ -1,509 +0,0 @@
|
|||||||
# Copyright 2012 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 logging
|
|
||||||
import urlparse
|
|
||||||
|
|
||||||
import testtools
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest.common.utils.linux import remote_client
|
|
||||||
from tempest import config
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
CONF = config.CONF
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class ServerActionsV3Test(base.BaseV3ComputeTest):
|
|
||||||
run_ssh = CONF.compute.run_ssh
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
# NOTE(afazekas): Normally we use the same server with all test cases,
|
|
||||||
# but if it has an issue, we build a new one
|
|
||||||
super(ServerActionsV3Test, self).setUp()
|
|
||||||
# Check if the server is in a clean state after test
|
|
||||||
try:
|
|
||||||
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
||||||
except Exception:
|
|
||||||
# Rebuild server if something happened to it during a test
|
|
||||||
self.__class__.server_id = self.rebuild_server(self.server_id)
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
_, server = self.client.get_server(self.server_id)
|
|
||||||
self.assertEqual(self.image_ref, server['image']['id'])
|
|
||||||
self.server_check_teardown()
|
|
||||||
super(ServerActionsV3Test, self).tearDown()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
cls.prepare_instance_network()
|
|
||||||
super(ServerActionsV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.servers_client
|
|
||||||
cls.server_id = cls.rebuild_server(None)
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.change_password,
|
|
||||||
'Change password not available.')
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_change_server_password(self):
|
|
||||||
# The server's password should be set to the provided password
|
|
||||||
new_password = 'Newpass1234'
|
|
||||||
resp, body = self.client.change_password(self.server_id, new_password)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
||||||
|
|
||||||
if self.run_ssh:
|
|
||||||
# Verify that the user can authenticate with the new password
|
|
||||||
resp, server = self.client.get_server(self.server_id)
|
|
||||||
linux_client = remote_client.RemoteClient(server, self.ssh_user,
|
|
||||||
new_password)
|
|
||||||
linux_client.validate_authentication()
|
|
||||||
|
|
||||||
@test.attr(type='smoke')
|
|
||||||
def test_reboot_server_hard(self):
|
|
||||||
# The server should be power cycled
|
|
||||||
if self.run_ssh:
|
|
||||||
# Get the time the server was last rebooted,
|
|
||||||
resp, server = self.client.get_server(self.server_id)
|
|
||||||
linux_client = remote_client.RemoteClient(server, self.ssh_user,
|
|
||||||
self.password)
|
|
||||||
boot_time = linux_client.get_boot_time()
|
|
||||||
|
|
||||||
resp, body = self.client.reboot(self.server_id, 'HARD')
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
||||||
|
|
||||||
if self.run_ssh:
|
|
||||||
# Log in and verify the boot time has changed
|
|
||||||
linux_client = remote_client.RemoteClient(server, self.ssh_user,
|
|
||||||
self.password)
|
|
||||||
new_boot_time = linux_client.get_boot_time()
|
|
||||||
self.assertGreater(new_boot_time, boot_time)
|
|
||||||
|
|
||||||
@test.skip_because(bug="1014647")
|
|
||||||
@test.attr(type='smoke')
|
|
||||||
def test_reboot_server_soft(self):
|
|
||||||
# The server should be signaled to reboot gracefully
|
|
||||||
if self.run_ssh:
|
|
||||||
# Get the time the server was last rebooted,
|
|
||||||
resp, server = self.client.get_server(self.server_id)
|
|
||||||
linux_client = remote_client.RemoteClient(server, self.ssh_user,
|
|
||||||
self.password)
|
|
||||||
boot_time = linux_client.get_boot_time()
|
|
||||||
|
|
||||||
resp, body = self.client.reboot(self.server_id, 'SOFT')
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
||||||
|
|
||||||
if self.run_ssh:
|
|
||||||
# Log in and verify the boot time has changed
|
|
||||||
linux_client = remote_client.RemoteClient(server, self.ssh_user,
|
|
||||||
self.password)
|
|
||||||
new_boot_time = linux_client.get_boot_time()
|
|
||||||
self.assertGreater(new_boot_time, boot_time)
|
|
||||||
|
|
||||||
@test.attr(type='smoke')
|
|
||||||
def test_rebuild_server(self):
|
|
||||||
# The server should be rebuilt using the provided image and data
|
|
||||||
meta = {'rebuild': 'server'}
|
|
||||||
new_name = data_utils.rand_name('server')
|
|
||||||
password = 'rebuildPassw0rd'
|
|
||||||
resp, rebuilt_server = self.client.rebuild(self.server_id,
|
|
||||||
self.image_ref_alt,
|
|
||||||
name=new_name,
|
|
||||||
metadata=meta,
|
|
||||||
admin_password=password)
|
|
||||||
|
|
||||||
# Verify the properties in the initial response are correct
|
|
||||||
self.assertEqual(self.server_id, rebuilt_server['id'])
|
|
||||||
rebuilt_image_id = rebuilt_server['image']['id']
|
|
||||||
self.assertTrue(self.image_ref_alt.endswith(rebuilt_image_id))
|
|
||||||
self.assertEqual(self.flavor_ref, rebuilt_server['flavor']['id'])
|
|
||||||
|
|
||||||
# Verify the server properties after the rebuild completes
|
|
||||||
self.client.wait_for_server_status(rebuilt_server['id'], 'ACTIVE')
|
|
||||||
resp, server = self.client.get_server(rebuilt_server['id'])
|
|
||||||
rebuilt_image_id = server['image']['id']
|
|
||||||
self.assertTrue(self.image_ref_alt.endswith(rebuilt_image_id))
|
|
||||||
self.assertEqual(new_name, server['name'])
|
|
||||||
|
|
||||||
if self.run_ssh:
|
|
||||||
# Verify that the user can authenticate with the provided password
|
|
||||||
linux_client = remote_client.RemoteClient(server, self.ssh_user,
|
|
||||||
password)
|
|
||||||
linux_client.validate_authentication()
|
|
||||||
|
|
||||||
if self.image_ref_alt != self.image_ref:
|
|
||||||
self.client.rebuild(self.server_id, self.image_ref)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_rebuild_server_in_stop_state(self):
|
|
||||||
# The server in stop state should be rebuilt using the provided
|
|
||||||
# image and remain in SHUTOFF state
|
|
||||||
resp, server = self.client.get_server(self.server_id)
|
|
||||||
old_image = server['image']['id']
|
|
||||||
new_image = self.image_ref_alt \
|
|
||||||
if old_image == self.image_ref else self.image_ref
|
|
||||||
resp, server = self.client.stop(self.server_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.client.wait_for_server_status(self.server_id, 'SHUTOFF')
|
|
||||||
resp, rebuilt_server = self.client.rebuild(self.server_id, new_image)
|
|
||||||
|
|
||||||
# Verify the properties in the initial response are correct
|
|
||||||
self.assertEqual(self.server_id, rebuilt_server['id'])
|
|
||||||
rebuilt_image_id = rebuilt_server['image']['id']
|
|
||||||
self.assertEqual(new_image, rebuilt_image_id)
|
|
||||||
self.assertEqual(self.flavor_ref, rebuilt_server['flavor']['id'])
|
|
||||||
|
|
||||||
# Verify the server properties after the rebuild completes
|
|
||||||
self.client.wait_for_server_status(rebuilt_server['id'], 'SHUTOFF')
|
|
||||||
resp, server = self.client.get_server(rebuilt_server['id'])
|
|
||||||
rebuilt_image_id = server['image']['id']
|
|
||||||
self.assertEqual(new_image, rebuilt_image_id)
|
|
||||||
|
|
||||||
# Restore to the original image (The tearDown will test it again)
|
|
||||||
if self.image_ref_alt != self.image_ref:
|
|
||||||
self.client.rebuild(self.server_id, old_image)
|
|
||||||
self.client.wait_for_server_status(self.server_id, 'SHUTOFF')
|
|
||||||
self.client.start(self.server_id)
|
|
||||||
|
|
||||||
def _detect_server_image_flavor(self, server_id):
|
|
||||||
# Detects the current server image flavor ref.
|
|
||||||
resp, server = self.client.get_server(server_id)
|
|
||||||
current_flavor = server['flavor']['id']
|
|
||||||
new_flavor_ref = self.flavor_ref_alt \
|
|
||||||
if current_flavor == self.flavor_ref else self.flavor_ref
|
|
||||||
return current_flavor, new_flavor_ref
|
|
||||||
|
|
||||||
def _test_resize_server_confirm(self, stop=False):
|
|
||||||
# The server's RAM and disk space should be modified to that of
|
|
||||||
# the provided flavor
|
|
||||||
|
|
||||||
previous_flavor_ref, new_flavor_ref = \
|
|
||||||
self._detect_server_image_flavor(self.server_id)
|
|
||||||
|
|
||||||
if stop:
|
|
||||||
resp = self.servers_client.stop(self.server_id)[0]
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.servers_client.wait_for_server_status(self.server_id,
|
|
||||||
'SHUTOFF')
|
|
||||||
|
|
||||||
resp, server = self.client.resize(self.server_id, new_flavor_ref)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.client.wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
|
|
||||||
|
|
||||||
self.client.confirm_resize(self.server_id)
|
|
||||||
expected_status = 'SHUTOFF' if stop else 'ACTIVE'
|
|
||||||
self.client.wait_for_server_status(self.server_id, expected_status)
|
|
||||||
|
|
||||||
resp, server = self.client.get_server(self.server_id)
|
|
||||||
self.assertEqual(new_flavor_ref, server['flavor']['id'])
|
|
||||||
|
|
||||||
if stop:
|
|
||||||
# NOTE(mriedem): tearDown requires the server to be started.
|
|
||||||
self.client.start(self.server_id)
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
|
|
||||||
'Resize not available.')
|
|
||||||
@test.attr(type='smoke')
|
|
||||||
def test_resize_server_confirm(self):
|
|
||||||
self._test_resize_server_confirm(stop=False)
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
|
|
||||||
'Resize not available.')
|
|
||||||
@test.attr(type='smoke')
|
|
||||||
def test_resize_server_confirm_from_stopped(self):
|
|
||||||
self._test_resize_server_confirm(stop=True)
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
|
|
||||||
'Resize not available.')
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_resize_server_revert(self):
|
|
||||||
# The server's RAM and disk space should return to its original
|
|
||||||
# values after a resize is reverted
|
|
||||||
|
|
||||||
previous_flavor_ref, new_flavor_ref = \
|
|
||||||
self._detect_server_image_flavor(self.server_id)
|
|
||||||
|
|
||||||
resp, server = self.client.resize(self.server_id, new_flavor_ref)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.client.wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
|
|
||||||
|
|
||||||
self.client.revert_resize(self.server_id)
|
|
||||||
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
||||||
|
|
||||||
resp, server = self.client.get_server(self.server_id)
|
|
||||||
self.assertEqual(previous_flavor_ref, server['flavor']['id'])
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
|
|
||||||
'Snapshotting not available, backup not possible.')
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_create_backup(self):
|
|
||||||
# Positive test:create backup successfully and rotate backups correctly
|
|
||||||
# create the first and the second backup
|
|
||||||
backup1 = data_utils.rand_name('backup-1')
|
|
||||||
resp, _ = self.servers_client.create_backup(self.server_id,
|
|
||||||
'daily',
|
|
||||||
2,
|
|
||||||
backup1)
|
|
||||||
oldest_backup_exist = True
|
|
||||||
|
|
||||||
# the oldest one should be deleted automatically in this test
|
|
||||||
def _clean_oldest_backup(oldest_backup):
|
|
||||||
if oldest_backup_exist:
|
|
||||||
try:
|
|
||||||
self.images_client.delete_image(oldest_backup)
|
|
||||||
except exceptions.NotFound:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
LOG.warning("Deletion of oldest backup %s should not have "
|
|
||||||
"been successful as it should have been "
|
|
||||||
"deleted during rotation." % oldest_backup)
|
|
||||||
|
|
||||||
image1_id = data_utils.parse_image_id(resp['location'])
|
|
||||||
self.addCleanup(_clean_oldest_backup, image1_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.images_client.wait_for_image_status(image1_id, 'active')
|
|
||||||
|
|
||||||
backup2 = data_utils.rand_name('backup-2')
|
|
||||||
self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
||||||
resp, _ = self.servers_client.create_backup(self.server_id,
|
|
||||||
'daily',
|
|
||||||
2,
|
|
||||||
backup2)
|
|
||||||
image2_id = data_utils.parse_image_id(resp['location'])
|
|
||||||
self.addCleanup(self.images_client.delete_image, image2_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.images_client.wait_for_image_status(image2_id, 'active')
|
|
||||||
|
|
||||||
# verify they have been created
|
|
||||||
properties = {
|
|
||||||
'image_type': 'backup',
|
|
||||||
'backup_type': "daily",
|
|
||||||
'instance_uuid': self.server_id,
|
|
||||||
}
|
|
||||||
resp, image_list = self.images_client.image_list_detail(
|
|
||||||
properties,
|
|
||||||
sort_key='created_at',
|
|
||||||
sort_dir='asc')
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(2, len(image_list))
|
|
||||||
self.assertEqual((backup1, backup2),
|
|
||||||
(image_list[0]['name'], image_list[1]['name']))
|
|
||||||
|
|
||||||
# create the third one, due to the rotation is 2,
|
|
||||||
# the first one will be deleted
|
|
||||||
backup3 = data_utils.rand_name('backup-3')
|
|
||||||
self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
||||||
resp, _ = self.servers_client.create_backup(self.server_id,
|
|
||||||
'daily',
|
|
||||||
2,
|
|
||||||
backup3)
|
|
||||||
image3_id = data_utils.parse_image_id(resp['location'])
|
|
||||||
self.addCleanup(self.images_client.delete_image, image3_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
# the first back up should be deleted
|
|
||||||
self.images_client.wait_for_resource_deletion(image1_id)
|
|
||||||
oldest_backup_exist = False
|
|
||||||
resp, image_list = self.images_client.image_list_detail(
|
|
||||||
properties,
|
|
||||||
sort_key='created_at',
|
|
||||||
sort_dir='asc')
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(2, len(image_list),
|
|
||||||
'Unexpected number of images for '
|
|
||||||
'v3:test_create_backup; was the oldest backup not '
|
|
||||||
'yet deleted? Image list: %s' %
|
|
||||||
[image['name'] for image in image_list])
|
|
||||||
self.assertEqual((backup2, backup3),
|
|
||||||
(image_list[0]['name'], image_list[1]['name']))
|
|
||||||
|
|
||||||
def _get_output(self):
|
|
||||||
resp, output = self.servers_client.get_console_output(
|
|
||||||
self.server_id, 10)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertTrue(output, "Console output was empty.")
|
|
||||||
lines = len(output.split('\n'))
|
|
||||||
self.assertEqual(lines, 10)
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.console_output,
|
|
||||||
'Console output not supported.')
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_get_console_output(self):
|
|
||||||
# Positive test:Should be able to GET the console output
|
|
||||||
# for a given server_id and number of lines
|
|
||||||
|
|
||||||
# This reboot is necessary for outputting some console log after
|
|
||||||
# creating a instance backup. If a instance backup, the console
|
|
||||||
# log file is truncated and we cannot get any console log through
|
|
||||||
# "console-log" API.
|
|
||||||
# The detail is https://bugs.launchpad.net/nova/+bug/1251920
|
|
||||||
resp, body = self.servers_client.reboot(self.server_id, 'HARD')
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
||||||
|
|
||||||
self.wait_for(self._get_output)
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.console_output,
|
|
||||||
'Console output not supported.')
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_get_console_output_server_id_in_shutoff_status(self):
|
|
||||||
# Positive test:Should be able to GET the console output
|
|
||||||
# for a given server_id in SHUTOFF status
|
|
||||||
|
|
||||||
# NOTE: SHUTOFF is irregular status. To avoid test instability,
|
|
||||||
# one server is created only for this test without using
|
|
||||||
# the server that was created in setupClass.
|
|
||||||
resp, server = self.create_test_server(wait_until='ACTIVE')
|
|
||||||
temp_server_id = server['id']
|
|
||||||
|
|
||||||
resp, server = self.servers_client.stop(temp_server_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.servers_client.wait_for_server_status(temp_server_id, 'SHUTOFF')
|
|
||||||
|
|
||||||
self.wait_for(self._get_output)
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.pause,
|
|
||||||
'Pause is not available.')
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_pause_unpause_server(self):
|
|
||||||
resp, server = self.client.pause_server(self.server_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.client.wait_for_server_status(self.server_id, 'PAUSED')
|
|
||||||
resp, server = self.client.unpause_server(self.server_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.suspend,
|
|
||||||
'Suspend is not available.')
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_suspend_resume_server(self):
|
|
||||||
resp, server = self.client.suspend_server(self.server_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.client.wait_for_server_status(self.server_id, 'SUSPENDED')
|
|
||||||
resp, server = self.client.resume_server(self.server_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.shelve,
|
|
||||||
'Shelve is not available.')
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_shelve_unshelve_server(self):
|
|
||||||
resp, server = self.client.shelve_server(self.server_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
|
|
||||||
offload_time = CONF.compute.shelved_offload_time
|
|
||||||
if offload_time >= 0:
|
|
||||||
self.client.wait_for_server_status(self.server_id,
|
|
||||||
'SHELVED_OFFLOADED',
|
|
||||||
extra_timeout=offload_time)
|
|
||||||
else:
|
|
||||||
self.client.wait_for_server_status(self.server_id,
|
|
||||||
'SHELVED')
|
|
||||||
|
|
||||||
resp, server = self.client.shelve_offload_server(self.server_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.client.wait_for_server_status(self.server_id,
|
|
||||||
'SHELVED_OFFLOADED')
|
|
||||||
|
|
||||||
resp, server = self.client.get_server(self.server_id)
|
|
||||||
image_name = server['name'] + '-shelved'
|
|
||||||
resp, images = self.images_client.image_list(name=image_name)
|
|
||||||
self.assertEqual(1, len(images))
|
|
||||||
self.assertEqual(image_name, images[0]['name'])
|
|
||||||
|
|
||||||
resp, server = self.client.unshelve_server(self.server_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_stop_start_server(self):
|
|
||||||
resp, server = self.servers_client.stop(self.server_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.servers_client.wait_for_server_status(self.server_id, 'SHUTOFF')
|
|
||||||
resp, server = self.servers_client.start(self.server_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_lock_unlock_server(self):
|
|
||||||
# Lock the server,try server stop(exceptions throw),unlock it and retry
|
|
||||||
resp, server = self.servers_client.lock_server(self.server_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
resp, server = self.servers_client.get_server(self.server_id)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(server['status'], 'ACTIVE')
|
|
||||||
# Locked server is not allowed to be stopped by non-admin user
|
|
||||||
self.assertRaises(exceptions.Conflict,
|
|
||||||
self.servers_client.stop, self.server_id)
|
|
||||||
resp, server = self.servers_client.unlock_server(self.server_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
resp, server = self.servers_client.stop(self.server_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.servers_client.wait_for_server_status(self.server_id, 'SHUTOFF')
|
|
||||||
resp, server = self.servers_client.start(self.server_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
||||||
|
|
||||||
def _validate_url(self, url):
|
|
||||||
valid_scheme = ['http', 'https']
|
|
||||||
parsed_url = urlparse.urlparse(url)
|
|
||||||
self.assertNotEqual('None', parsed_url.hostname)
|
|
||||||
self.assertIn(parsed_url.scheme, valid_scheme)
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.vnc_console,
|
|
||||||
'VNC Console feature is disabled')
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_get_vnc_console(self):
|
|
||||||
# Get the VNC console
|
|
||||||
console_types = ['novnc', 'xvpvnc']
|
|
||||||
for console_type in console_types:
|
|
||||||
resp, body = self.servers_client.get_vnc_console(self.server_id,
|
|
||||||
console_type)
|
|
||||||
self.assertEqual(
|
|
||||||
200, resp.status,
|
|
||||||
"Failed to get Console Type: %s" % (console_type))
|
|
||||||
self.assertEqual(console_type, body['type'])
|
|
||||||
self.assertNotEqual('', body['url'])
|
|
||||||
self._validate_url(body['url'])
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.spice_console,
|
|
||||||
'Spice Console feature is disabled.')
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_get_spice_console(self):
|
|
||||||
# Get the Spice console of type "spice-html5"
|
|
||||||
console_type = 'spice-html5'
|
|
||||||
resp, body = self.servers_client.get_spice_console(self.server_id,
|
|
||||||
console_type)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(console_type, body['type'])
|
|
||||||
self.assertNotEqual('', body['url'])
|
|
||||||
self._validate_url(body['url'])
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.rdp_console,
|
|
||||||
'RDP Console feature is disabled.')
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_get_rdp_console(self):
|
|
||||||
# Get the RDP console of type "rdp-html5"
|
|
||||||
console_type = 'rdp-html5'
|
|
||||||
resp, body = self.servers_client.get_rdp_console(self.server_id,
|
|
||||||
console_type)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(console_type, body['type'])
|
|
||||||
self.assertNotEqual('', body['url'])
|
|
||||||
self._validate_url(body['url'])
|
|
@ -1,65 +0,0 @@
|
|||||||
# Copyright 2012 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.
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class ServerAddressesV3Test(base.BaseV3ComputeTest):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
# This test module might use a network and a subnet
|
|
||||||
cls.set_network_resources(network=True, subnet=True)
|
|
||||||
super(ServerAddressesV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.servers_client
|
|
||||||
|
|
||||||
resp, cls.server = cls.create_test_server(wait_until='ACTIVE')
|
|
||||||
|
|
||||||
@test.attr(type='smoke')
|
|
||||||
def test_list_server_addresses(self):
|
|
||||||
# All public and private addresses for
|
|
||||||
# a server should be returned
|
|
||||||
|
|
||||||
resp, addresses = self.client.list_addresses(self.server['id'])
|
|
||||||
self.assertEqual('200', resp['status'])
|
|
||||||
|
|
||||||
# We do not know the exact network configuration, but an instance
|
|
||||||
# should at least have a single public or private address
|
|
||||||
self.assertTrue(len(addresses) >= 1)
|
|
||||||
for network_name, network_addresses in addresses.iteritems():
|
|
||||||
self.assertTrue(len(network_addresses) >= 1)
|
|
||||||
for address in network_addresses:
|
|
||||||
self.assertTrue(address['addr'])
|
|
||||||
self.assertTrue(address['version'])
|
|
||||||
|
|
||||||
@test.attr(type='smoke')
|
|
||||||
def test_list_server_addresses_by_network(self):
|
|
||||||
# Providing a network type should filter
|
|
||||||
# the addresses return by that type
|
|
||||||
|
|
||||||
resp, addresses = self.client.list_addresses(self.server['id'])
|
|
||||||
|
|
||||||
# Once again we don't know the environment's exact network config,
|
|
||||||
# but the response for each individual network should be the same
|
|
||||||
# as the partial result of the full address list
|
|
||||||
id = self.server['id']
|
|
||||||
for addr_type in addresses:
|
|
||||||
resp, addr = self.client.list_addresses_by_network(id, addr_type)
|
|
||||||
self.assertEqual('200', resp['status'])
|
|
||||||
|
|
||||||
addr = addr[addr_type]
|
|
||||||
for address in addresses[addr_type]:
|
|
||||||
self.assertTrue(any([a for a in addr if a == address]))
|
|
@ -1,46 +0,0 @@
|
|||||||
# Copyright 2012 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.
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class ServerAddressesV3NegativeTest(base.BaseV3ComputeTest):
|
|
||||||
_interface = 'json'
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
# This test module might use a network and a subnet
|
|
||||||
cls.set_network_resources(network=True, subnet=True)
|
|
||||||
super(ServerAddressesV3NegativeTest, cls).resource_setup()
|
|
||||||
cls.client = cls.servers_client
|
|
||||||
|
|
||||||
resp, cls.server = cls.create_test_server(wait_until='ACTIVE')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_list_server_addresses_nonexistent_server_id(self):
|
|
||||||
# List addresses request should fail if server id not in system
|
|
||||||
non_existent_server_id = data_utils.rand_uuid()
|
|
||||||
self.assertRaises(exceptions.NotFound, self.client.list_addresses,
|
|
||||||
non_existent_server_id)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_list_server_addresses_by_network_neg(self):
|
|
||||||
# List addresses by network should fail if network name not valid
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.list_addresses_by_network,
|
|
||||||
self.server['id'], 'invalid')
|
|
@ -1,115 +0,0 @@
|
|||||||
# Copyright 2012 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.
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class ServerMetadataV3Test(base.BaseV3ComputeTest):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(ServerMetadataV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.servers_client
|
|
||||||
cls.quotas = cls.quotas_client
|
|
||||||
resp, server = cls.create_test_server(meta={}, wait_until='ACTIVE')
|
|
||||||
cls.server_id = server['id']
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(ServerMetadataV3Test, self).setUp()
|
|
||||||
meta = {'key1': 'value1', 'key2': 'value2'}
|
|
||||||
resp, _ = self.client.set_server_metadata(self.server_id, meta)
|
|
||||||
self.assertEqual(resp.status, 200)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_server_metadata(self):
|
|
||||||
# All metadata key/value pairs for a server should be returned
|
|
||||||
resp, resp_metadata = self.client.list_server_metadata(self.server_id)
|
|
||||||
|
|
||||||
# Verify the expected metadata items are in the list
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
expected = {'key1': 'value1', 'key2': 'value2'}
|
|
||||||
self.assertEqual(expected, resp_metadata)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_set_server_metadata(self):
|
|
||||||
# The server's metadata should be replaced with the provided values
|
|
||||||
# Create a new set of metadata for the server
|
|
||||||
req_metadata = {'meta2': 'data2', 'meta3': 'data3'}
|
|
||||||
resp, metadata = self.client.set_server_metadata(self.server_id,
|
|
||||||
req_metadata)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
|
|
||||||
# Verify the expected values are correct, and that the
|
|
||||||
# previous values have been removed
|
|
||||||
resp, resp_metadata = self.client.list_server_metadata(self.server_id)
|
|
||||||
self.assertEqual(resp_metadata, req_metadata)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_update_server_metadata(self):
|
|
||||||
# The server's metadata values should be updated to the
|
|
||||||
# provided values
|
|
||||||
meta = {'key1': 'alt1', 'key3': 'value3'}
|
|
||||||
resp, metadata = self.client.update_server_metadata(self.server_id,
|
|
||||||
meta)
|
|
||||||
self.assertEqual(201, resp.status)
|
|
||||||
|
|
||||||
# Verify the values have been updated to the proper values
|
|
||||||
resp, resp_metadata = self.client.list_server_metadata(self.server_id)
|
|
||||||
expected = {'key1': 'alt1', 'key2': 'value2', 'key3': 'value3'}
|
|
||||||
self.assertEqual(expected, resp_metadata)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_update_metadata_empty_body(self):
|
|
||||||
# The original metadata should not be lost if empty metadata body is
|
|
||||||
# passed
|
|
||||||
meta = {}
|
|
||||||
_, metadata = self.client.update_server_metadata(self.server_id, meta)
|
|
||||||
resp, resp_metadata = self.client.list_server_metadata(self.server_id)
|
|
||||||
expected = {'key1': 'value1', 'key2': 'value2'}
|
|
||||||
self.assertEqual(expected, resp_metadata)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_get_server_metadata_item(self):
|
|
||||||
# The value for a specific metadata key should be returned
|
|
||||||
resp, meta = self.client.get_server_metadata_item(self.server_id,
|
|
||||||
'key2')
|
|
||||||
self.assertEqual('value2', meta['key2'])
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_set_server_metadata_item(self):
|
|
||||||
# The item's value should be updated to the provided value
|
|
||||||
# Update the metadata value
|
|
||||||
meta = {'nova': 'alt'}
|
|
||||||
resp, body = self.client.set_server_metadata_item(self.server_id,
|
|
||||||
'nova', meta)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
|
|
||||||
# Verify the meta item's value has been updated
|
|
||||||
resp, resp_metadata = self.client.list_server_metadata(self.server_id)
|
|
||||||
expected = {'key1': 'value1', 'key2': 'value2', 'nova': 'alt'}
|
|
||||||
self.assertEqual(expected, resp_metadata)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_delete_server_metadata_item(self):
|
|
||||||
# The metadata value/key pair should be deleted from the server
|
|
||||||
resp, meta = self.client.delete_server_metadata_item(self.server_id,
|
|
||||||
'key1')
|
|
||||||
self.assertEqual(204, resp.status)
|
|
||||||
|
|
||||||
# Verify the metadata item has been removed
|
|
||||||
resp, resp_metadata = self.client.list_server_metadata(self.server_id)
|
|
||||||
expected = {'key2': 'value2'}
|
|
||||||
self.assertEqual(expected, resp_metadata)
|
|
@ -1,155 +0,0 @@
|
|||||||
# 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.
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class ServerMetadataV3NegativeTest(base.BaseV3ComputeTest):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(ServerMetadataV3NegativeTest, cls).resource_setup()
|
|
||||||
cls.client = cls.servers_client
|
|
||||||
cls.quotas = cls.quotas_client
|
|
||||||
cls.tenant_id = cls.client.tenant_id
|
|
||||||
resp, server = cls.create_test_server(meta={}, wait_until='ACTIVE')
|
|
||||||
|
|
||||||
cls.server_id = server['id']
|
|
||||||
|
|
||||||
@test.skip_because(bug="1273948")
|
|
||||||
@test.attr(type=['gate', 'negative'])
|
|
||||||
def test_server_create_metadata_key_too_long(self):
|
|
||||||
# Attempt to start a server with a meta-data key that is > 255
|
|
||||||
# characters
|
|
||||||
|
|
||||||
# Tryset_server_metadata_item a few values
|
|
||||||
for sz in [256, 257, 511, 1023]:
|
|
||||||
key = "k" * sz
|
|
||||||
meta = {key: 'data1'}
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.create_test_server,
|
|
||||||
meta=meta)
|
|
||||||
|
|
||||||
# no teardown - all creates should fail
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_server_metadata_blank_key(self):
|
|
||||||
# Blank key should trigger an error.
|
|
||||||
meta = {'': 'data1'}
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.create_test_server,
|
|
||||||
meta=meta)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_server_metadata_non_existent_server(self):
|
|
||||||
# GET on a non-existent server should not succeed
|
|
||||||
non_existent_server_id = data_utils.rand_uuid()
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.get_server_metadata_item,
|
|
||||||
non_existent_server_id,
|
|
||||||
'test2')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_list_server_metadata_non_existent_server(self):
|
|
||||||
# List metadata on a non-existent server should not succeed
|
|
||||||
non_existent_server_id = data_utils.rand_uuid()
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.list_server_metadata,
|
|
||||||
non_existent_server_id)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_wrong_key_passed_in_body(self):
|
|
||||||
# Raise BadRequest if key in uri does not match
|
|
||||||
# the key passed in body.
|
|
||||||
meta = {'testkey': 'testvalue'}
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.set_server_metadata_item,
|
|
||||||
self.server_id, 'key', meta)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_set_metadata_non_existent_server(self):
|
|
||||||
# Set metadata on a non-existent server should not succeed
|
|
||||||
non_existent_server_id = data_utils.rand_uuid()
|
|
||||||
meta = {'meta1': 'data1'}
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.set_server_metadata,
|
|
||||||
non_existent_server_id,
|
|
||||||
meta)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_update_metadata_non_existent_server(self):
|
|
||||||
# An update should not happen for a non-existent server
|
|
||||||
non_existent_server_id = data_utils.rand_uuid()
|
|
||||||
meta = {'key1': 'value1', 'key2': 'value2'}
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.update_server_metadata,
|
|
||||||
non_existent_server_id,
|
|
||||||
meta)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_update_metadata_with_blank_key(self):
|
|
||||||
# Blank key should trigger an error
|
|
||||||
meta = {'': 'data1'}
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.update_server_metadata,
|
|
||||||
self.server_id, meta=meta)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_delete_metadata_non_existent_server(self):
|
|
||||||
# Should not be able to delete metadata item from a non-existent server
|
|
||||||
non_existent_server_id = data_utils.rand_uuid()
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.delete_server_metadata_item,
|
|
||||||
non_existent_server_id,
|
|
||||||
'd')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_metadata_items_limit(self):
|
|
||||||
# Raise a 413 OverLimit exception while exceeding metadata items limit
|
|
||||||
# for tenant.
|
|
||||||
_, quota_set = self.quotas.get_quota_set(self.tenant_id)
|
|
||||||
quota_metadata = quota_set['metadata_items']
|
|
||||||
req_metadata = {}
|
|
||||||
for num in range(1, quota_metadata + 2):
|
|
||||||
req_metadata['key' + str(num)] = 'val' + str(num)
|
|
||||||
self.assertRaises(exceptions.OverLimit,
|
|
||||||
self.client.set_server_metadata,
|
|
||||||
self.server_id, req_metadata)
|
|
||||||
|
|
||||||
# Raise a 413 OverLimit exception while exceeding metadata items limit
|
|
||||||
# for tenant (update).
|
|
||||||
self.assertRaises(exceptions.OverLimit,
|
|
||||||
self.client.update_server_metadata,
|
|
||||||
self.server_id, req_metadata)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_set_server_metadata_blank_key(self):
|
|
||||||
# Raise a bad request error for blank key.
|
|
||||||
# set_server_metadata will replace all metadata with new value
|
|
||||||
meta = {'': 'data1'}
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.set_server_metadata,
|
|
||||||
self.server_id, meta=meta)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_set_server_metadata_missing_metadata(self):
|
|
||||||
# Raise a bad request error for a missing metadata field
|
|
||||||
# set_server_metadata will replace all metadata with new value
|
|
||||||
meta = {'meta1': 'data1'}
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.set_server_metadata,
|
|
||||||
self.server_id, meta=meta, no_metadata_field=True)
|
|
@ -1,37 +0,0 @@
|
|||||||
# Copyright 2013 IBM 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.api.compute import base
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class ServerPasswordV3Test(base.BaseV3ComputeTest):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(ServerPasswordV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.servers_client
|
|
||||||
resp, cls.server = cls.create_test_server(wait_until="ACTIVE")
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_get_server_password(self):
|
|
||||||
resp, body = self.client.get_password(self.server['id'])
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_delete_server_password(self):
|
|
||||||
resp, body = self.client.delete_password(self.server['id'])
|
|
||||||
self.assertEqual(204, resp.status)
|
|
@ -1,46 +0,0 @@
|
|||||||
# Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
# 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.api.compute import base
|
|
||||||
from tempest import config
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
CONF = config.CONF
|
|
||||||
|
|
||||||
|
|
||||||
class ServerRescueV3Test(base.BaseV3ComputeTest):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
if not CONF.compute_feature_enabled.rescue:
|
|
||||||
msg = "Server rescue not available."
|
|
||||||
raise cls.skipException(msg)
|
|
||||||
super(ServerRescueV3Test, cls).resource_setup()
|
|
||||||
|
|
||||||
# Server for positive tests
|
|
||||||
resp, server = cls.create_test_server(wait_until='BUILD')
|
|
||||||
cls.server_id = server['id']
|
|
||||||
cls.password = server['admin_password']
|
|
||||||
cls.servers_client.wait_for_server_status(cls.server_id, 'ACTIVE')
|
|
||||||
|
|
||||||
@test.attr(type='smoke')
|
|
||||||
def test_rescue_unrescue_instance(self):
|
|
||||||
resp, body = self.servers_client.rescue_server(
|
|
||||||
self.server_id, admin_password=self.password)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.servers_client.wait_for_server_status(self.server_id, 'RESCUE')
|
|
||||||
resp, body = self.servers_client.unrescue_server(self.server_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
@ -1,145 +0,0 @@
|
|||||||
# Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
||||||
# 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 testtools
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import config
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
CONF = config.CONF
|
|
||||||
|
|
||||||
|
|
||||||
class ServerRescueNegativeV3Test(base.BaseV3ComputeTest):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
if not CONF.compute_feature_enabled.rescue:
|
|
||||||
msg = "Server rescue not available."
|
|
||||||
raise cls.skipException(msg)
|
|
||||||
|
|
||||||
super(ServerRescueNegativeV3Test, cls).resource_setup()
|
|
||||||
cls.device = CONF.compute.volume_device_name
|
|
||||||
|
|
||||||
# Create a volume and wait for it to become ready for attach
|
|
||||||
resp, cls.volume = cls.volumes_client.create_volume(
|
|
||||||
1, display_name=data_utils.rand_name(cls.__name__ + '_volume'))
|
|
||||||
cls.volumes_client.wait_for_volume_status(
|
|
||||||
cls.volume['id'], 'available')
|
|
||||||
|
|
||||||
# Server for negative tests
|
|
||||||
resp, server = cls.create_test_server(wait_until='BUILD')
|
|
||||||
resp, resc_server = cls.create_test_server(wait_until='ACTIVE')
|
|
||||||
cls.server_id = server['id']
|
|
||||||
cls.password = server['admin_password']
|
|
||||||
cls.rescue_id = resc_server['id']
|
|
||||||
cls.rescue_password = resc_server['admin_password']
|
|
||||||
|
|
||||||
cls.servers_client.rescue_server(
|
|
||||||
cls.rescue_id, admin_password=cls.rescue_password)
|
|
||||||
cls.servers_client.wait_for_server_status(cls.rescue_id, 'RESCUE')
|
|
||||||
cls.servers_client.wait_for_server_status(cls.server_id, 'ACTIVE')
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_cleanup(cls):
|
|
||||||
if hasattr(cls, 'volume'):
|
|
||||||
cls.delete_volume(cls.volume['id'])
|
|
||||||
super(ServerRescueNegativeV3Test, cls).resource_cleanup()
|
|
||||||
|
|
||||||
def _detach(self, server_id, volume_id):
|
|
||||||
self.servers_client.detach_volume(server_id, volume_id)
|
|
||||||
self.volumes_client.wait_for_volume_status(volume_id,
|
|
||||||
'available')
|
|
||||||
|
|
||||||
def _unrescue(self, server_id):
|
|
||||||
resp, body = self.servers_client.unrescue_server(server_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
|
|
||||||
|
|
||||||
def _unpause(self, server_id):
|
|
||||||
resp, body = self.servers_client.unpause_server(server_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.pause,
|
|
||||||
'Pause is not available.')
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_rescue_paused_instance(self):
|
|
||||||
# Rescue a paused server
|
|
||||||
resp, body = self.servers_client.pause_server(
|
|
||||||
self.server_id)
|
|
||||||
self.addCleanup(self._unpause, self.server_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.servers_client.wait_for_server_status(self.server_id, 'PAUSED')
|
|
||||||
self.assertRaises(exceptions.Conflict,
|
|
||||||
self.servers_client.rescue_server,
|
|
||||||
self.server_id)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_rescued_vm_reboot(self):
|
|
||||||
self.assertRaises(exceptions.Conflict, self.servers_client.reboot,
|
|
||||||
self.rescue_id, 'HARD')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_rescue_non_existent_server(self):
|
|
||||||
# Rescue a non-existing server
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.servers_client.rescue_server,
|
|
||||||
data_utils.rand_uuid())
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_rescued_vm_rebuild(self):
|
|
||||||
self.assertRaises(exceptions.Conflict,
|
|
||||||
self.servers_client.rebuild,
|
|
||||||
self.rescue_id,
|
|
||||||
self.image_ref_alt)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_rescued_vm_attach_volume(self):
|
|
||||||
# Rescue the server
|
|
||||||
self.servers_client.rescue_server(self.server_id,
|
|
||||||
admin_password=self.password)
|
|
||||||
self.servers_client.wait_for_server_status(self.server_id, 'RESCUE')
|
|
||||||
self.addCleanup(self._unrescue, self.server_id)
|
|
||||||
|
|
||||||
# Attach the volume to the server
|
|
||||||
self.assertRaises(exceptions.Conflict,
|
|
||||||
self.servers_client.attach_volume,
|
|
||||||
self.server_id,
|
|
||||||
self.volume['id'],
|
|
||||||
device='/dev/%s' % self.device)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_rescued_vm_detach_volume(self):
|
|
||||||
# Attach the volume to the server
|
|
||||||
self.servers_client.attach_volume(self.server_id,
|
|
||||||
self.volume['id'],
|
|
||||||
device='/dev/%s' % self.device)
|
|
||||||
self.volumes_client.wait_for_volume_status(self.volume['id'], 'in-use')
|
|
||||||
|
|
||||||
# Rescue the server
|
|
||||||
self.servers_client.rescue_server(self.server_id,
|
|
||||||
admin_password=self.password)
|
|
||||||
self.servers_client.wait_for_server_status(self.server_id, 'RESCUE')
|
|
||||||
# addCleanup is a LIFO queue
|
|
||||||
self.addCleanup(self._detach, self.server_id, self.volume['id'])
|
|
||||||
self.addCleanup(self._unrescue, self.server_id)
|
|
||||||
|
|
||||||
# Detach the volume from the server expecting failure
|
|
||||||
self.assertRaises(exceptions.Conflict,
|
|
||||||
self.servers_client.detach_volume,
|
|
||||||
self.server_id,
|
|
||||||
self.volume['id'])
|
|
@ -1,113 +0,0 @@
|
|||||||
# Copyright 2012 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.
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class ServersV3Test(base.BaseV3ComputeTest):
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(ServersV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.servers_client
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
self.clear_servers()
|
|
||||||
super(ServersV3Test, self).tearDown()
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_create_server_with_admin_password(self):
|
|
||||||
# If an admin password is provided on server creation, the server's
|
|
||||||
# root password should be set to that password.
|
|
||||||
resp, server = self.create_test_server(admin_password='testpassword')
|
|
||||||
|
|
||||||
# Verify the password is set correctly in the response
|
|
||||||
self.assertEqual('testpassword', server['admin_password'])
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_create_with_existing_server_name(self):
|
|
||||||
# Creating a server with a name that already exists is allowed
|
|
||||||
|
|
||||||
# TODO(sdague): clear out try, we do cleanup one layer up
|
|
||||||
server_name = data_utils.rand_name('server')
|
|
||||||
resp, server = self.create_test_server(name=server_name,
|
|
||||||
wait_until='ACTIVE')
|
|
||||||
id1 = server['id']
|
|
||||||
resp, server = self.create_test_server(name=server_name,
|
|
||||||
wait_until='ACTIVE')
|
|
||||||
id2 = server['id']
|
|
||||||
self.assertNotEqual(id1, id2, "Did not create a new server")
|
|
||||||
resp, server = self.client.get_server(id1)
|
|
||||||
name1 = server['name']
|
|
||||||
resp, server = self.client.get_server(id2)
|
|
||||||
name2 = server['name']
|
|
||||||
self.assertEqual(name1, name2)
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_create_specify_keypair(self):
|
|
||||||
# Specify a keypair while creating a server
|
|
||||||
|
|
||||||
key_name = data_utils.rand_name('key')
|
|
||||||
resp, keypair = self.keypairs_client.create_keypair(key_name)
|
|
||||||
resp, body = self.keypairs_client.list_keypairs()
|
|
||||||
resp, server = self.create_test_server(key_name=key_name)
|
|
||||||
self.assertEqual('202', resp['status'])
|
|
||||||
self.client.wait_for_server_status(server['id'], 'ACTIVE')
|
|
||||||
resp, server = self.client.get_server(server['id'])
|
|
||||||
self.assertEqual(key_name, server['key_name'])
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_update_server_name(self):
|
|
||||||
# The server name should be changed to the the provided value
|
|
||||||
resp, server = self.create_test_server(wait_until='ACTIVE')
|
|
||||||
|
|
||||||
# Update the server with a new name
|
|
||||||
resp, server = self.client.update_server(server['id'],
|
|
||||||
name='newname')
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.client.wait_for_server_status(server['id'], 'ACTIVE')
|
|
||||||
|
|
||||||
# Verify the name of the server has changed
|
|
||||||
resp, server = self.client.get_server(server['id'])
|
|
||||||
self.assertEqual('newname', server['name'])
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_update_access_server_address(self):
|
|
||||||
# The server's access addresses should reflect the provided values
|
|
||||||
resp, server = self.create_test_server(wait_until='ACTIVE')
|
|
||||||
|
|
||||||
# Update the IPv4 and IPv6 access addresses
|
|
||||||
resp, body = self.client.update_server(server['id'],
|
|
||||||
access_ip_v4='1.1.1.1',
|
|
||||||
access_ip_v6='::babe:202:202')
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.client.wait_for_server_status(server['id'], 'ACTIVE')
|
|
||||||
|
|
||||||
# Verify the access addresses have been updated
|
|
||||||
resp, server = self.client.get_server(server['id'])
|
|
||||||
self.assertEqual('1.1.1.1', server['os-access-ips:access_ip_v4'])
|
|
||||||
self.assertEqual('::babe:202:202',
|
|
||||||
server['os-access-ips:access_ip_v6'])
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_create_server_with_ipv6_addr_only(self):
|
|
||||||
# Create a server without an IPv4 address(only IPv6 address).
|
|
||||||
resp, server = self.create_test_server(access_ip_v6='2001:2001::3')
|
|
||||||
self.assertEqual('202', resp['status'])
|
|
||||||
self.client.wait_for_server_status(server['id'], 'ACTIVE')
|
|
||||||
resp, server = self.client.get_server(server['id'])
|
|
||||||
self.assertEqual('2001:2001::3', server['os-access-ips:access_ip_v6'])
|
|
@ -1,451 +0,0 @@
|
|||||||
# Copyright 2012 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 base64
|
|
||||||
import sys
|
|
||||||
|
|
||||||
import testtools
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest import clients
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import config
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
CONF = config.CONF
|
|
||||||
|
|
||||||
|
|
||||||
class ServersNegativeV3Test(base.BaseV3ComputeTest):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(ServersNegativeV3Test, self).setUp()
|
|
||||||
try:
|
|
||||||
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
||||||
except Exception:
|
|
||||||
self.__class__.server_id = self.rebuild_server(self.server_id)
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
self.server_check_teardown()
|
|
||||||
super(ServersNegativeV3Test, self).tearDown()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(ServersNegativeV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.servers_client
|
|
||||||
cls.alt_os = clients.Manager(cls.isolated_creds.get_alt_creds())
|
|
||||||
cls.alt_client = cls.alt_os.servers_v3_client
|
|
||||||
resp, server = cls.create_test_server(wait_until='ACTIVE')
|
|
||||||
cls.server_id = server['id']
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_server_name_blank(self):
|
|
||||||
# Create a server with name parameter empty
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.create_test_server,
|
|
||||||
name='')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_with_invalid_image(self):
|
|
||||||
# Create a server with an unknown image
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.create_test_server,
|
|
||||||
image_id=-1)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_with_invalid_flavor(self):
|
|
||||||
# Create a server with an unknown flavor
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.create_test_server,
|
|
||||||
flavor=-1,)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_invalid_access_ip_v4_address(self):
|
|
||||||
# An access IPv4 address must match a valid address pattern
|
|
||||||
|
|
||||||
IPv4 = '1.1.1.1.1.1'
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.create_test_server, access_ip_v4=IPv4)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_invalid_ip_v6_address(self):
|
|
||||||
# An access IPv6 address must match a valid address pattern
|
|
||||||
|
|
||||||
IPv6 = 'notvalid'
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.create_test_server, access_ip_v6=IPv6)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_resize_nonexistent_server(self):
|
|
||||||
# Resize a non-existent server
|
|
||||||
nonexistent_server = data_utils.rand_uuid()
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.resize,
|
|
||||||
nonexistent_server, self.flavor_ref)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_resize_server_with_non_existent_flavor(self):
|
|
||||||
# Resize a server with non-existent flavor
|
|
||||||
nonexistent_flavor = data_utils.rand_uuid()
|
|
||||||
self.assertRaises(exceptions.BadRequest, self.client.resize,
|
|
||||||
self.server_id, flavor_ref=nonexistent_flavor)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_resize_server_with_null_flavor(self):
|
|
||||||
# Resize a server with null flavor
|
|
||||||
self.assertRaises(exceptions.BadRequest, self.client.resize,
|
|
||||||
self.server_id, flavor_ref="")
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_reboot_non_existent_server(self):
|
|
||||||
# Reboot a non existent server
|
|
||||||
nonexistent_server = data_utils.rand_uuid()
|
|
||||||
self.assertRaises(exceptions.NotFound, self.client.reboot,
|
|
||||||
nonexistent_server, 'SOFT')
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.pause,
|
|
||||||
'Pause is not available.')
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_pause_paused_server(self):
|
|
||||||
# Pause a paused server.
|
|
||||||
self.client.pause_server(self.server_id)
|
|
||||||
self.client.wait_for_server_status(self.server_id, 'PAUSED')
|
|
||||||
self.assertRaises(exceptions.Conflict,
|
|
||||||
self.client.pause_server,
|
|
||||||
self.server_id)
|
|
||||||
self.client.unpause_server(self.server_id)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_rebuild_reboot_deleted_server(self):
|
|
||||||
# Rebuild and Reboot a deleted server
|
|
||||||
_, server = self.create_test_server()
|
|
||||||
self.client.delete_server(server['id'])
|
|
||||||
self.client.wait_for_server_termination(server['id'])
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.rebuild,
|
|
||||||
server['id'], self.image_ref_alt)
|
|
||||||
self.assertRaises(exceptions.NotFound, self.client.reboot,
|
|
||||||
server['id'], 'SOFT')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_rebuild_non_existent_server(self):
|
|
||||||
# Rebuild a non existent server
|
|
||||||
nonexistent_server = data_utils.rand_uuid()
|
|
||||||
meta = {'rebuild': 'server'}
|
|
||||||
new_name = data_utils.rand_name('server')
|
|
||||||
file_contents = 'Test server rebuild.'
|
|
||||||
personality = [{'path': '/etc/rebuild.txt',
|
|
||||||
'contents': base64.b64encode(file_contents)}]
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.rebuild,
|
|
||||||
nonexistent_server,
|
|
||||||
self.image_ref_alt,
|
|
||||||
name=new_name, meta=meta,
|
|
||||||
personality=personality,
|
|
||||||
adminPass='rebuild')
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_numeric_server_name(self):
|
|
||||||
# Create a server with a numeric name
|
|
||||||
server_name = 12345
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.create_test_server,
|
|
||||||
name=server_name)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_server_name_length_exceeds_256(self):
|
|
||||||
# Create a server with name length exceeding 256 characters
|
|
||||||
|
|
||||||
server_name = 'a' * 256
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.create_test_server,
|
|
||||||
name=server_name)
|
|
||||||
|
|
||||||
@test.skip_because(bug="1208743")
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_with_invalid_network_uuid(self):
|
|
||||||
# Pass invalid network uuid while creating a server
|
|
||||||
|
|
||||||
networks = [{'fixed_ip': '10.0.1.1', 'uuid': 'a-b-c-d-e-f-g-h-i-j'}]
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.create_test_server,
|
|
||||||
networks=networks)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_with_non_existent_keypair(self):
|
|
||||||
# Pass a non-existent keypair while creating a server
|
|
||||||
|
|
||||||
key_name = data_utils.rand_name('key')
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.create_test_server,
|
|
||||||
key_name=key_name)
|
|
||||||
|
|
||||||
@test.skip_because(bug="1273948")
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_server_metadata_exceeds_length_limit(self):
|
|
||||||
# Pass really long metadata while creating a server
|
|
||||||
|
|
||||||
metadata = {'a': 'b' * 260}
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.create_test_server,
|
|
||||||
meta=metadata)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_update_name_of_non_existent_server(self):
|
|
||||||
# Update name of a non-existent server
|
|
||||||
|
|
||||||
server_name = data_utils.rand_name('server')
|
|
||||||
new_name = data_utils.rand_name('server') + '_updated'
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.NotFound, self.client.update_server,
|
|
||||||
server_name, name=new_name)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_update_server_set_empty_name(self):
|
|
||||||
# Update name of the server to an empty string
|
|
||||||
|
|
||||||
server_name = data_utils.rand_name('server')
|
|
||||||
new_name = ''
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.BadRequest, self.client.update_server,
|
|
||||||
server_name, name=new_name)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_update_server_of_another_tenant(self):
|
|
||||||
# Update name of a server that belongs to another tenant
|
|
||||||
|
|
||||||
new_name = self.server_id + '_new'
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.alt_client.update_server, self.server_id,
|
|
||||||
name=new_name)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_update_server_name_length_exceeds_256(self):
|
|
||||||
# Update name of server exceed the name length limit
|
|
||||||
|
|
||||||
new_name = 'a' * 256
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.client.update_server,
|
|
||||||
self.server_id,
|
|
||||||
name=new_name)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_delete_non_existent_server(self):
|
|
||||||
# Delete a non existent server
|
|
||||||
|
|
||||||
nonexistent_server = data_utils.rand_uuid()
|
|
||||||
self.assertRaises(exceptions.NotFound, self.client.delete_server,
|
|
||||||
nonexistent_server)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_delete_a_server_of_another_tenant(self):
|
|
||||||
# Delete a server that belongs to another tenant
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.alt_client.delete_server,
|
|
||||||
self.server_id)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_delete_server_pass_negative_id(self):
|
|
||||||
# Pass an invalid string parameter to delete server
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.NotFound, self.client.delete_server, -1)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_delete_server_pass_id_exceeding_length_limit(self):
|
|
||||||
# Pass a server ID that exceeds length limit to delete server
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.NotFound, self.client.delete_server,
|
|
||||||
sys.maxint + 1)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_create_with_nonexistent_security_group(self):
|
|
||||||
# Create a server with a nonexistent security group
|
|
||||||
|
|
||||||
security_groups = [{'name': 'does_not_exist'}]
|
|
||||||
self.assertRaises(exceptions.BadRequest,
|
|
||||||
self.create_test_server,
|
|
||||||
security_groups=security_groups)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_get_non_existent_server(self):
|
|
||||||
# Get a non existent server details
|
|
||||||
nonexistent_server = data_utils.rand_uuid()
|
|
||||||
self.assertRaises(exceptions.NotFound, self.client.get_server,
|
|
||||||
nonexistent_server)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_stop_non_existent_server(self):
|
|
||||||
# Stop a non existent server
|
|
||||||
nonexistent_server = data_utils.rand_uuid()
|
|
||||||
self.assertRaises(exceptions.NotFound, self.servers_client.stop,
|
|
||||||
nonexistent_server)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_pause_non_existent_server(self):
|
|
||||||
# pause a non existent server
|
|
||||||
nonexistent_server = data_utils.rand_uuid()
|
|
||||||
self.assertRaises(exceptions.NotFound, self.client.pause_server,
|
|
||||||
nonexistent_server)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_unpause_non_existent_server(self):
|
|
||||||
# unpause a non existent server
|
|
||||||
nonexistent_server = data_utils.rand_uuid()
|
|
||||||
self.assertRaises(exceptions.NotFound, self.client.unpause_server,
|
|
||||||
nonexistent_server)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_unpause_server_invalid_state(self):
|
|
||||||
# unpause an active server.
|
|
||||||
self.assertRaises(exceptions.Conflict,
|
|
||||||
self.client.unpause_server,
|
|
||||||
self.server_id)
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.suspend,
|
|
||||||
'Suspend is not available.')
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_suspend_non_existent_server(self):
|
|
||||||
# suspend a non existent server
|
|
||||||
nonexistent_server = data_utils.rand_uuid()
|
|
||||||
self.assertRaises(exceptions.NotFound, self.client.suspend_server,
|
|
||||||
nonexistent_server)
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.suspend,
|
|
||||||
'Suspend is not available.')
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_suspend_server_invalid_state(self):
|
|
||||||
# suspend a suspended server.
|
|
||||||
resp, _ = self.client.suspend_server(self.server_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
self.client.wait_for_server_status(self.server_id, 'SUSPENDED')
|
|
||||||
self.assertRaises(exceptions.Conflict,
|
|
||||||
self.client.suspend_server,
|
|
||||||
self.server_id)
|
|
||||||
self.client.resume_server(self.server_id)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_resume_non_existent_server(self):
|
|
||||||
# resume a non existent server
|
|
||||||
nonexistent_server = data_utils.rand_uuid()
|
|
||||||
self.assertRaises(exceptions.NotFound, self.client.resume_server,
|
|
||||||
nonexistent_server)
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.suspend,
|
|
||||||
'Suspend is not available.')
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_resume_server_invalid_state(self):
|
|
||||||
# resume an active server.
|
|
||||||
self.assertRaises(exceptions.Conflict,
|
|
||||||
self.client.resume_server,
|
|
||||||
self.server_id)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_get_console_output_of_non_existent_server(self):
|
|
||||||
# get the console output for a non existent server
|
|
||||||
nonexistent_server = data_utils.rand_uuid()
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.get_console_output,
|
|
||||||
nonexistent_server, 10)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_force_delete_nonexistent_server_id(self):
|
|
||||||
# force-delete a non existent server
|
|
||||||
nonexistent_server = data_utils.rand_uuid()
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.force_delete_server,
|
|
||||||
nonexistent_server)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_force_delete_server_invalid_state(self):
|
|
||||||
# we can only force-delete a server in 'soft-delete' state
|
|
||||||
self.assertRaises(exceptions.Conflict,
|
|
||||||
self.client.force_delete_server,
|
|
||||||
self.server_id)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_restore_nonexistent_server_id(self):
|
|
||||||
# restore-delete a non existent server
|
|
||||||
nonexistent_server = data_utils.rand_uuid()
|
|
||||||
self.assertRaises(exceptions.NotFound,
|
|
||||||
self.client.restore_soft_deleted_server,
|
|
||||||
nonexistent_server)
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_restore_server_invalid_state(self):
|
|
||||||
# we can only restore-delete a server in 'soft-delete' state
|
|
||||||
self.assertRaises(exceptions.Conflict,
|
|
||||||
self.client.restore_soft_deleted_server,
|
|
||||||
self.server_id)
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.shelve,
|
|
||||||
'Shelve is not available.')
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_shelve_non_existent_server(self):
|
|
||||||
# shelve a non existent server
|
|
||||||
nonexistent_server = data_utils.rand_uuid()
|
|
||||||
self.assertRaises(exceptions.NotFound, self.client.shelve_server,
|
|
||||||
nonexistent_server)
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.shelve,
|
|
||||||
'Shelve is not available.')
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_shelve_shelved_server(self):
|
|
||||||
# shelve a shelved server.
|
|
||||||
resp, server = self.client.shelve_server(self.server_id)
|
|
||||||
self.assertEqual(202, resp.status)
|
|
||||||
|
|
||||||
offload_time = CONF.compute.shelved_offload_time
|
|
||||||
if offload_time >= 0:
|
|
||||||
self.client.wait_for_server_status(self.server_id,
|
|
||||||
'SHELVED_OFFLOADED',
|
|
||||||
extra_timeout=offload_time)
|
|
||||||
else:
|
|
||||||
self.client.wait_for_server_status(self.server_id,
|
|
||||||
'SHELVED')
|
|
||||||
|
|
||||||
resp, server = self.client.get_server(self.server_id)
|
|
||||||
image_name = server['name'] + '-shelved'
|
|
||||||
resp, images = self.images_client.image_list(name=image_name)
|
|
||||||
self.assertEqual(1, len(images))
|
|
||||||
self.assertEqual(image_name, images[0]['name'])
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.Conflict,
|
|
||||||
self.client.shelve_server,
|
|
||||||
self.server_id)
|
|
||||||
|
|
||||||
self.client.unshelve_server(self.server_id)
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.shelve,
|
|
||||||
'Shelve is not available.')
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_unshelve_non_existent_server(self):
|
|
||||||
# unshelve a non existent server
|
|
||||||
nonexistent_server = data_utils.rand_uuid()
|
|
||||||
self.assertRaises(exceptions.NotFound, self.client.unshelve_server,
|
|
||||||
nonexistent_server)
|
|
||||||
|
|
||||||
@testtools.skipUnless(CONF.compute_feature_enabled.shelve,
|
|
||||||
'Shelve is not available.')
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_unshelve_server_invalid_state(self):
|
|
||||||
# unshelve an active server.
|
|
||||||
self.assertRaises(exceptions.Conflict,
|
|
||||||
self.client.unshelve_server,
|
|
||||||
self.server_id)
|
|
@ -1,52 +0,0 @@
|
|||||||
# Copyright 2012 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.
|
|
||||||
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest import config
|
|
||||||
from tempest.openstack.common import log as logging
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
CONF = config.CONF
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class ExtensionsV3Test(base.BaseV3ComputeTest):
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_list_extensions(self):
|
|
||||||
# List of all extensions
|
|
||||||
if len(CONF.compute_feature_enabled.api_v3_extensions) == 0:
|
|
||||||
raise self.skipException('There are not any extensions configured')
|
|
||||||
resp, extensions = self.extensions_client.list_extensions()
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
ext = CONF.compute_feature_enabled.api_v3_extensions[0]
|
|
||||||
if ext == 'all':
|
|
||||||
self.assertIn('Hosts', map(lambda x: x['name'], extensions))
|
|
||||||
elif ext:
|
|
||||||
self.assertIn(ext, map(lambda x: x['name'], extensions))
|
|
||||||
else:
|
|
||||||
raise self.skipException('There are not any extensions configured')
|
|
||||||
# Log extensions list
|
|
||||||
extension_list = map(lambda x: x['name'], extensions)
|
|
||||||
LOG.debug("Nova extensions: %s" % ','.join(extension_list))
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_get_extension(self):
|
|
||||||
# get the specified extensions
|
|
||||||
resp, extension = self.extensions_client.get_extension('servers')
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual('servers', extension['alias'])
|
|
@ -1,132 +0,0 @@
|
|||||||
# Copyright 2012 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 testtools
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest import config
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
CONF = config.CONF
|
|
||||||
|
|
||||||
|
|
||||||
class LiveBlockMigrationV3Test(base.BaseV3ComputeAdminTest):
|
|
||||||
_host_key = 'os-extended-server-attributes:host'
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(LiveBlockMigrationV3Test, cls).resource_setup()
|
|
||||||
|
|
||||||
cls.admin_hosts_client = cls.hosts_admin_client
|
|
||||||
cls.admin_servers_client = cls.servers_admin_client
|
|
||||||
|
|
||||||
cls.created_server_ids = []
|
|
||||||
|
|
||||||
def _get_compute_hostnames(self):
|
|
||||||
_resp, body = self.admin_hosts_client.list_hosts()
|
|
||||||
return [
|
|
||||||
host_record['host_name']
|
|
||||||
for host_record in body
|
|
||||||
if host_record['service'] == 'compute'
|
|
||||||
]
|
|
||||||
|
|
||||||
def _get_server_details(self, server_id):
|
|
||||||
_resp, body = self.admin_servers_client.get_server(server_id)
|
|
||||||
return body
|
|
||||||
|
|
||||||
def _get_host_for_server(self, server_id):
|
|
||||||
return self._get_server_details(server_id)[self._host_key]
|
|
||||||
|
|
||||||
def _migrate_server_to(self, server_id, dest_host):
|
|
||||||
_resp, body = self.admin_servers_client.live_migrate_server(
|
|
||||||
server_id, dest_host,
|
|
||||||
CONF.compute_feature_enabled.
|
|
||||||
block_migration_for_live_migration)
|
|
||||||
return body
|
|
||||||
|
|
||||||
def _get_host_other_than(self, host):
|
|
||||||
for target_host in self._get_compute_hostnames():
|
|
||||||
if host != target_host:
|
|
||||||
return target_host
|
|
||||||
|
|
||||||
def _get_server_status(self, server_id):
|
|
||||||
return self._get_server_details(server_id)['status']
|
|
||||||
|
|
||||||
def _get_an_active_server(self):
|
|
||||||
for server_id in self.created_server_ids:
|
|
||||||
if 'ACTIVE' == self._get_server_status(server_id):
|
|
||||||
return server_id
|
|
||||||
else:
|
|
||||||
_, server = self.create_test_server(wait_until="ACTIVE")
|
|
||||||
server_id = server['id']
|
|
||||||
self.password = server['admin_password']
|
|
||||||
self.password = 'password'
|
|
||||||
self.created_server_ids.append(server_id)
|
|
||||||
return server_id
|
|
||||||
|
|
||||||
def _volume_clean_up(self, server_id, volume_id):
|
|
||||||
resp, body = self.volumes_client.get_volume(volume_id)
|
|
||||||
if body['status'] == 'in-use':
|
|
||||||
self.servers_client.detach_volume(server_id, volume_id)
|
|
||||||
self.volumes_client.wait_for_volume_status(volume_id, 'available')
|
|
||||||
self.volumes_client.delete_volume(volume_id)
|
|
||||||
|
|
||||||
@testtools.skipIf(not CONF.compute_feature_enabled.live_migration,
|
|
||||||
'Live migration not available')
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_live_block_migration(self):
|
|
||||||
# Live block migrate an instance to another host
|
|
||||||
if len(self._get_compute_hostnames()) < 2:
|
|
||||||
raise self.skipTest(
|
|
||||||
"Less than 2 compute nodes, skipping migration test.")
|
|
||||||
server_id = self._get_an_active_server()
|
|
||||||
actual_host = self._get_host_for_server(server_id)
|
|
||||||
target_host = self._get_host_other_than(actual_host)
|
|
||||||
self._migrate_server_to(server_id, target_host)
|
|
||||||
self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
|
|
||||||
self.assertEqual(target_host, self._get_host_for_server(server_id))
|
|
||||||
|
|
||||||
@testtools.skipIf(not CONF.compute_feature_enabled.live_migration or not
|
|
||||||
CONF.compute_feature_enabled.
|
|
||||||
block_migration_for_live_migration,
|
|
||||||
'Block Live migration not available')
|
|
||||||
@testtools.skipIf(not CONF.compute_feature_enabled.
|
|
||||||
block_migrate_cinder_iscsi,
|
|
||||||
'Block Live migration not configured for iSCSI')
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_iscsi_volume(self):
|
|
||||||
# Live block migrate an instance to another host
|
|
||||||
if len(self._get_compute_hostnames()) < 2:
|
|
||||||
raise self.skipTest(
|
|
||||||
"Less than 2 compute nodes, skipping migration test.")
|
|
||||||
server_id = self._get_an_active_server()
|
|
||||||
actual_host = self._get_host_for_server(server_id)
|
|
||||||
target_host = self._get_host_other_than(actual_host)
|
|
||||||
|
|
||||||
resp, volume = self.volumes_client.create_volume(1,
|
|
||||||
display_name='test')
|
|
||||||
|
|
||||||
self.volumes_client.wait_for_volume_status(volume['id'],
|
|
||||||
'available')
|
|
||||||
self.addCleanup(self._volume_clean_up, server_id, volume['id'])
|
|
||||||
|
|
||||||
# Attach the volume to the server
|
|
||||||
self.servers_client.attach_volume(server_id, volume['id'],
|
|
||||||
device='/dev/xvdb')
|
|
||||||
self.volumes_client.wait_for_volume_status(volume['id'], 'in-use')
|
|
||||||
|
|
||||||
self._migrate_server_to(server_id, target_host)
|
|
||||||
self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
|
|
||||||
self.assertEqual(target_host, self._get_host_for_server(server_id))
|
|
@ -1,53 +0,0 @@
|
|||||||
# Copyright 2012 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.
|
|
||||||
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest.common.utils import data_utils
|
|
||||||
from tempest import config
|
|
||||||
from tempest import exceptions
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
CONF = config.CONF
|
|
||||||
|
|
||||||
|
|
||||||
class LiveBlockMigrationV3NegativeTest(base.BaseV3ComputeAdminTest):
|
|
||||||
_host_key = 'os-extended-server-attributes:host'
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(LiveBlockMigrationV3NegativeTest, cls).resource_setup()
|
|
||||||
if not CONF.compute_feature_enabled.live_migration:
|
|
||||||
raise cls.skipException("Live migration is not enabled")
|
|
||||||
|
|
||||||
cls.admin_hosts_client = cls.hosts_admin_client
|
|
||||||
cls.admin_servers_client = cls.servers_admin_client
|
|
||||||
|
|
||||||
def _migrate_server_to(self, server_id, dest_host):
|
|
||||||
_resp, body = self.admin_servers_client.live_migrate_server(
|
|
||||||
server_id, dest_host,
|
|
||||||
CONF.compute_feature_enabled.
|
|
||||||
block_migration_for_live_migration)
|
|
||||||
return body
|
|
||||||
|
|
||||||
@test.attr(type=['negative', 'gate'])
|
|
||||||
def test_invalid_host_for_migration(self):
|
|
||||||
# Migrating to an invalid host should not change the status
|
|
||||||
target_host = data_utils.rand_name('host-')
|
|
||||||
_, server = self.create_test_server(wait_until="ACTIVE")
|
|
||||||
server_id = server['id']
|
|
||||||
self.assertRaises(exceptions.BadRequest, self._migrate_server_to,
|
|
||||||
server_id, target_host)
|
|
||||||
self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
|
|
@ -1,76 +0,0 @@
|
|||||||
# Copyright 2012 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.
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest.common import tempest_fixtures as fixtures
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class QuotasV3Test(base.BaseV3ComputeTest):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
# NOTE(mriedem): Avoid conflicts with os-quota-class-sets tests.
|
|
||||||
self.useFixture(fixtures.LockFixture('compute_quotas'))
|
|
||||||
super(QuotasV3Test, self).setUp()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resource_setup(cls):
|
|
||||||
super(QuotasV3Test, cls).resource_setup()
|
|
||||||
cls.client = cls.quotas_client
|
|
||||||
cls.tenant_id = cls.client.tenant_id
|
|
||||||
cls.user_id = cls.client.user_id
|
|
||||||
cls.default_quota_set = set(('metadata_items',
|
|
||||||
'ram', 'floating_ips',
|
|
||||||
'fixed_ips', 'key_pairs',
|
|
||||||
'instances', 'security_group_rules',
|
|
||||||
'cores', 'security_groups'))
|
|
||||||
|
|
||||||
@test.attr(type='smoke')
|
|
||||||
def test_get_quotas(self):
|
|
||||||
# User can get the quota set for it's tenant
|
|
||||||
expected_quota_set = self.default_quota_set | set(['id'])
|
|
||||||
resp, quota_set = self.client.get_quota_set(self.tenant_id)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(sorted(expected_quota_set),
|
|
||||||
sorted(quota_set.keys()))
|
|
||||||
self.assertEqual(quota_set['id'], self.tenant_id)
|
|
||||||
|
|
||||||
# get the quota set using user id
|
|
||||||
resp, quota_set = self.client.get_quota_set(self.tenant_id,
|
|
||||||
self.user_id)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(sorted(expected_quota_set),
|
|
||||||
sorted(quota_set.keys()))
|
|
||||||
self.assertEqual(quota_set['id'], self.tenant_id)
|
|
||||||
|
|
||||||
@test.attr(type='smoke')
|
|
||||||
def test_get_default_quotas(self):
|
|
||||||
# User can get the default quota set for it's tenant
|
|
||||||
expected_quota_set = self.default_quota_set | set(['id'])
|
|
||||||
resp, quota_set = self.client.get_default_quota_set(self.tenant_id)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(sorted(expected_quota_set),
|
|
||||||
sorted(quota_set.keys()))
|
|
||||||
self.assertEqual(quota_set['id'], self.tenant_id)
|
|
||||||
|
|
||||||
@test.attr(type='smoke')
|
|
||||||
def test_compare_tenant_quotas_with_default_quotas(self):
|
|
||||||
# Tenants are created with the default quota values
|
|
||||||
resp, defualt_quota_set = \
|
|
||||||
self.client.get_default_quota_set(self.tenant_id)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
resp, tenant_quota_set = self.client.get_quota_set(self.tenant_id)
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertEqual(defualt_quota_set, tenant_quota_set)
|
|
@ -1,29 +0,0 @@
|
|||||||
# 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.
|
|
||||||
|
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest import test
|
|
||||||
|
|
||||||
|
|
||||||
class VersionV3Test(base.BaseV3ComputeTest):
|
|
||||||
|
|
||||||
@test.attr(type='gate')
|
|
||||||
def test_version(self):
|
|
||||||
# Get version information
|
|
||||||
resp, version = self.version_client.get_version()
|
|
||||||
self.assertEqual(200, resp.status)
|
|
||||||
self.assertIn("id", version)
|
|
||||||
self.assertEqual("v3.0", version["id"])
|
|
Loading…
Reference in New Issue
Block a user