Fix volume qos spec list

This has been sporadically failing in functional tests due to the way
the volume qos spec list command calls get_associations() for each spec.
When tests run in parallel occasionally a spec from another test is present
in the list returned and is deleted before the get_associations() call is
made, causing a NotFound exception.  We should just keep going when this
occurs.

* make v1 match v2
* add tests to ensure the exception is being caught and handled

Closes-Bug: #1687083
Change-Id: If2d17c1deb53d293fc2c7f0c527a4e4ef6f69976
This commit is contained in:
Dean Troyer 2017-04-28 14:25:00 -05:00
parent dd7da49325
commit 2c5405ed5e
5 changed files with 106 additions and 28 deletions

View File

@ -10,9 +10,10 @@
# License for the specific language governing permissions and limitations
# under the License.
from openstackclient.tests.functional.volume.v2 import test_qos as v2
import os
from openstackclient.tests.functional.volume.v2 import test_qos as v2
class QosTests(v2.QosTests):
"""Functional tests for volume qos. """

View File

@ -13,6 +13,7 @@
# under the License.
#
import copy
import mock
from mock import call
@ -309,13 +310,30 @@ class TestQosDisassociate(TestQos):
class TestQosList(TestQos):
qos_spec = volume_fakes.FakeQos.create_one_qos()
qos_specs = volume_fakes.FakeQos.create_qoses(count=2)
qos_association = volume_fakes.FakeQos.create_one_qos_association()
columns = (
'ID',
'Name',
'Consumer',
'Associations',
'Properties',
)
data = []
for q in qos_specs:
data.append((
q.id,
q.name,
q.consumer,
qos_association.name,
utils.format_dict(q.specs),
))
def setUp(self):
super(TestQosList, self).setUp()
self.qos_mock.list.return_value = [self.qos_spec]
self.qos_mock.list.return_value = self.qos_specs
self.qos_mock.get_associations.return_value = [self.qos_association]
# Get the command object to test
@ -330,22 +348,35 @@ class TestQosList(TestQos):
columns, data = self.cmd.take_action(parsed_args)
self.qos_mock.list.assert_called_with()
collist = (
'ID',
'Name',
'Consumer',
'Associations',
'Properties',
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, list(data))
def test_qos_list_no_association(self):
self.qos_mock.reset_mock()
self.qos_mock.get_associations.side_effect = [
[self.qos_association],
exceptions.NotFound("NotFound"),
]
arglist = []
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.qos_mock.list.assert_called_with()
self.assertEqual(self.columns, columns)
ex_data = copy.deepcopy(self.data)
ex_data[1] = (
self.qos_specs[1].id,
self.qos_specs[1].name,
self.qos_specs[1].consumer,
None,
utils.format_dict(self.qos_specs[1].specs),
)
self.assertEqual(collist, columns)
datalist = ((
self.qos_spec.id,
self.qos_spec.name,
self.qos_spec.consumer,
self.qos_association.name,
utils.format_dict(self.qos_spec.specs),
), )
self.assertEqual(datalist, tuple(data))
self.assertEqual(ex_data, list(data))
class TestQosSet(TestQos):

View File

@ -13,6 +13,7 @@
# under the License.
#
import copy
import mock
from mock import call
@ -342,6 +343,33 @@ class TestQosList(TestQos):
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, list(data))
def test_qos_list_no_association(self):
self.qos_mock.reset_mock()
self.qos_mock.get_associations.side_effect = [
[self.qos_association],
exceptions.NotFound("NotFound"),
]
arglist = []
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.qos_mock.list.assert_called_with()
self.assertEqual(self.columns, columns)
ex_data = copy.deepcopy(self.data)
ex_data[1] = (
self.qos_specs[1].id,
self.qos_specs[1].name,
self.qos_specs[1].consumer,
None,
utils.format_dict(self.qos_specs[1].specs),
)
self.assertEqual(ex_data, list(data))
class TestQosSet(TestQos):

View File

@ -186,11 +186,20 @@ class ListQos(command.Lister):
qos_specs_list = volume_client.qos_specs.list()
for qos in qos_specs_list:
qos_associations = volume_client.qos_specs.get_associations(qos)
if qos_associations:
associations = [association.name
for association in qos_associations]
qos._info.update({'associations': associations})
try:
qos_associations = volume_client.qos_specs.get_associations(
qos,
)
if qos_associations:
associations = [
association.name for association in qos_associations
]
qos._info.update({'associations': associations})
except Exception as ex:
if type(ex).__name__ == 'NotFound':
qos._info.update({'associations': None})
else:
raise
display_columns = (
'ID', 'Name', 'Consumer', 'Associations', 'Properties')

View File

@ -187,11 +187,20 @@ class ListQos(command.Lister):
qos_specs_list = volume_client.qos_specs.list()
for qos in qos_specs_list:
qos_associations = volume_client.qos_specs.get_associations(qos)
if qos_associations:
associations = [association.name
for association in qos_associations]
qos._info.update({'associations': associations})
try:
qos_associations = volume_client.qos_specs.get_associations(
qos,
)
if qos_associations:
associations = [
association.name for association in qos_associations
]
qos._info.update({'associations': associations})
except Exception as ex:
if type(ex).__name__ == 'NotFound':
qos._info.update({'associations': None})
else:
raise
display_columns = (
'ID', 'Name', 'Consumer', 'Associations', 'Properties')