Check node trait before creating server

Placement may fail to update trait because of Conflict
the trait may be updated by the Nova compute
update_available_resource periodic task.
We need node status is enabled, so we check the node
trait and delay if it is not the correct status.
the max delay time is 10 minutes.

Depends-on: Ie98e2c000568ecac63e8981a8b7087029c0d3705

Change-Id: I3e45d4a66a6e1bf55499def8550da38ddf01b638
This commit is contained in:
licanwei 2019-08-21 10:46:36 +08:00
parent 4d6b4b3b49
commit 447fc7b7d2
3 changed files with 61 additions and 1 deletions

View File

@ -7,3 +7,4 @@ six>=1.10.0 # MIT
oslo.log>=3.36.0 # Apache-2.0 oslo.log>=3.36.0 # Apache-2.0
oslo.utils>=3.33.0 # Apache-2.0 oslo.utils>=3.33.0 # Apache-2.0
tempest>=17.1.0 # Apache-2.0 tempest>=17.1.0 # Apache-2.0
os-traits>=0.15.0 # Apache-2.0

View File

@ -16,10 +16,13 @@
import abc import abc
from oslo_serialization import jsonutils as json
import six import six
from tempest import clients from tempest import clients
from tempest.common import credentials_factory as creds_factory from tempest.common import credentials_factory as creds_factory
from tempest import config from tempest import config
from tempest.lib.common import rest_client
from tempest.lib.services.placement import placement_client
from watcher_tempest_plugin.services.infra_optim.v1.json import client as ioc from watcher_tempest_plugin.services.infra_optim.v1.json import client as ioc
from watcher_tempest_plugin.services.metric.v1.json import client as gc from watcher_tempest_plugin.services.metric.v1.json import client as gc
@ -36,6 +39,8 @@ class BaseManager(clients.Manager):
self.auth_provider, 'infra-optim', CONF.identity.region) self.auth_provider, 'infra-optim', CONF.identity.region)
self.gn_client = gc.GnocchiClientJSON( self.gn_client = gc.GnocchiClientJSON(
self.auth_provider, 'metric', CONF.identity.region) self.auth_provider, 'metric', CONF.identity.region)
self.placement_client = ExtendPlacementClient(
self.auth_provider, 'placement', CONF.identity.region)
class AdminManager(BaseManager): class AdminManager(BaseManager):
@ -43,3 +48,20 @@ class AdminManager(BaseManager):
super(AdminManager, self).__init__( super(AdminManager, self).__init__(
creds_factory.get_configured_admin_credentials(), creds_factory.get_configured_admin_credentials(),
) )
class ExtendPlacementClient(placement_client.PlacementClient):
def list_provider_traits(self, rp_uuid):
"""List resource provider traits.
For full list of available parameters, please refer to the official
API reference:
https://docs.openstack.org/api-ref/placement/#
list-resource-provider-traits-detail
"""
url = '/resource_providers/%s/traits' % rp_uuid
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)

View File

@ -24,6 +24,7 @@ import time
from datetime import datetime from datetime import datetime
from datetime import timedelta from datetime import timedelta
import os_traits
from oslo_log import log from oslo_log import log
from tempest.common import waiters from tempest.common import waiters
from tempest import config from tempest import config
@ -60,11 +61,14 @@ class BaseInfraOptimScenarioTest(manager.ScenarioTest):
super(BaseInfraOptimScenarioTest, cls).setup_clients() super(BaseInfraOptimScenarioTest, cls).setup_clients()
cls.client = cls.mgr.io_client cls.client = cls.mgr.io_client
cls.gnocchi = cls.mgr.gn_client cls.gnocchi = cls.mgr.gn_client
cls.placement_client = cls.mgr.placement_client
def setUp(self): def setUp(self):
super(BaseInfraOptimScenarioTest, self).setUp() super(BaseInfraOptimScenarioTest, self).setUp()
self.useFixture(api_microversion_fixture.APIMicroversionFixture( self.useFixture(api_microversion_fixture.APIMicroversionFixture(
compute_microversion=CONF.compute.min_microversion)) compute_microversion=CONF.compute.min_microversion))
self.useFixture(api_microversion_fixture.APIMicroversionFixture(
placement_microversion=CONF.placement.min_microversion))
@classmethod @classmethod
def resource_setup(cls): def resource_setup(cls):
@ -202,8 +206,28 @@ class BaseInfraOptimScenarioTest(manager.ScenarioTest):
if instances: if instances:
return instances return instances
hypervisors = self.get_hypervisors_setup()
created_instances = [] created_instances = []
for _ in compute_nodes[:CONF.compute.min_compute_nodes]: for node in compute_nodes[:CONF.compute.min_compute_nodes]:
hyp_id = [
hyp['id'] for hyp in hypervisors
if hyp['hypervisor_hostname'] == node['host']]
# Placement may fail to update trait because of Conflict
# the trait may be updated by the Nova compute
# update_available_resource periodic task.
# We need node status is enabled, so we check the node
# trait and delay if it is not the correct status.
# the max delay time is 10 minutes.
node_trait = os_traits.COMPUTE_STATUS_DISABLED
retry = 20
trait_status = True
while trait_status and retry:
trait_status = self.check_node_trait(hyp_id[0], node_trait)
if not trait_status:
break
time.sleep(30)
retry -= 1
self.assertNotEqual(0, retry)
# by getting to active state here, this means this has # by getting to active state here, this means this has
# landed on the host in question. # landed on the host in question.
instance = self.create_server(image_id=CONF.compute.image_ref, instance = self.create_server(image_id=CONF.compute.image_ref,
@ -520,3 +544,16 @@ class BaseInfraOptimScenarioTest(manager.ScenarioTest):
for action in action_list['actions']: for action in action_list['actions']:
self.assertEqual('SUCCEEDED', action.get('state')) self.assertEqual('SUCCEEDED', action.get('state'))
def check_node_trait(self, node_id, trait):
"""Check if trait is in node traits
:param node_id: The unique identifier of the node.
:param trait: node trait
:return: True if node has the trait else False
"""
traits = self.placement_client.list_provider_traits(node_id)
if trait in traits.get('traits'):
return True
else:
return False