Move the gathering of flavors into the CollectFlavors action

The imported actions from Mistral (namely, the nova.flavors_list)
will return dictionaries. The nova api returns a Flavor, which has
additional methods (get_keys) that have further properties that are
not returned in the main api call. This works around that.

Change-Id: I3ac99bc5abbae62bfc4352db708e25f5fa551095
Closes-Bug: #1685177
This commit is contained in:
Brad P. Crochet 2017-04-25 10:03:03 -04:00
parent 86c9c8d104
commit 6d487c39fd
3 changed files with 58 additions and 31 deletions

View File

@ -185,9 +185,8 @@ class CheckFlavorsAction(base.TripleOAction):
# TODO(bcrochet): The validation actions are temporary. This logic should
# move to the tripleo-validations project eventually.
def __init__(self, flavors, roles_info):
def __init__(self, roles_info):
super(CheckFlavorsAction, self).__init__()
self.flavors = flavors
self.roles_info = roles_info
def run(self):
@ -198,12 +197,21 @@ class CheckFlavorsAction(base.TripleOAction):
:returns: dictionary flavor name -> (flavor object, scale)
"""
flavors = {f['name']: f for f in self.flavors}
compute_client = self.get_compute_client()
flavors = {f.name: {'name': f.name, 'keys': f.get_keys()}
for f in compute_client.flavors.list()}
result = {}
warnings = []
errors = []
message = "Flavor '{1}' provided for the role '{0}', does not exist"
warning_message = (
'Flavor {0} "capabilities:boot_option" is set to '
'"netboot". Nodes will PXE boot from the ironic '
'conductor instead of using a local bootloader. '
'Make sure that enough nodes are marked with the '
'"boot_option" capability set to "netboot".')
for target, (flavor_name, scale) in self.roles_info.items():
if flavor_name is None or not scale:
@ -217,14 +225,12 @@ class CheckFlavorsAction(base.TripleOAction):
flavor = flavors.get(flavor_name)
if flavor:
if flavor.get('capabilities:boot_option', '') == 'netboot':
warnings.append(
'Flavor %s "capabilities:boot_option" is set to '
'"netboot". Nodes will PXE boot from the ironic '
'conductor instead of using a local bootloader. '
'Make sure that enough nodes are marked with the '
'"boot_option" capability set to "netboot".'
% flavor_name)
keys = flavor.get('keys', None)
if keys:
if keys.get('capabilities:boot_option', '') \
== 'netboot':
warnings.append(
warning_message.format(flavor_name))
result[flavor_name] = (flavor, scale)
else:
@ -322,7 +328,10 @@ class VerifyProfilesAction(base.TripleOAction):
if not scale:
continue
profile = flavor.get('capabilities:profile')
profile = None
keys = flavor.get('keys')
if keys:
profile = keys.get('capabilities:profile')
if not profile and len(self.flavors) > 1:
message = ('Error: The {flavor} flavor has no profile '

View File

@ -287,14 +287,39 @@ class TestCheckBootImagesAction(base.TestCase):
self.assertIn(expected_message, messages)
class FakeFlavor(object):
name = ''
uuid = ''
def __init__(self, name, keys={'capabilities:boot_option': 'local'}):
self.uuid = uuid4()
self.name = name
self.keys = keys
def get_keys(self):
return self.keys
class TestCheckFlavorsAction(base.TestCase):
def setUp(self):
super(TestCheckFlavorsAction, self).setUp()
self.flavors = [
{'name': 'flavor1', 'capabilities:boot_option': 'local'},
{'name': 'flavor2', 'capabilities:boot_option': 'netboot'},
{'name': 'flavor3'}
self.compute = mock.MagicMock()
compute_patcher = mock.patch(
'tripleo_common.actions.base.TripleOAction.get_compute_client',
return_value=self.compute)
self.mock_compute = compute_patcher.start()
self.addCleanup(compute_patcher.stop)
self.mock_flavors = mock.Mock()
self.compute.attach_mock(self.mock_flavors, 'flavors')
self.mock_flavor_list = [
FakeFlavor('flavor1'),
FakeFlavor('flavor2',
keys={'capabilities:boot_option': 'netboot'}),
FakeFlavor('flavor3', None)
]
self.mock_flavors.attach_mock(
mock.Mock(return_value=self.mock_flavor_list), 'list')
def test_run_success(self):
roles_info = {
@ -307,7 +332,7 @@ class TestCheckFlavorsAction(base.TestCase):
'flavor1': (
{
'name': 'flavor1',
'capabilities:boot_option': 'local'
'keys': {'capabilities:boot_option': 'local'}
}, 1)
},
'warnings': [],
@ -316,7 +341,6 @@ class TestCheckFlavorsAction(base.TestCase):
)
action_args = {
'flavors': self.flavors,
'roles_info': roles_info
}
action = validations.CheckFlavorsAction(**action_args)
@ -334,11 +358,12 @@ class TestCheckFlavorsAction(base.TestCase):
'flavor2': (
{
'name': 'flavor2',
'capabilities:boot_option': 'netboot'
'keys': {'capabilities:boot_option': 'netboot'}
}, 1),
'flavor3': (
{
'name': 'flavor3',
'keys': None
}, 1),
},
'warnings': [
@ -353,7 +378,6 @@ class TestCheckFlavorsAction(base.TestCase):
)
action_args = {
'flavors': self.flavors,
'roles_info': roles_info
}
action = validations.CheckFlavorsAction(**action_args)
@ -377,7 +401,6 @@ class TestCheckFlavorsAction(base.TestCase):
)
action_args = {
'flavors': self.flavors,
'roles_info': roles_info
}
action = validations.CheckFlavorsAction(**action_args)
@ -485,8 +508,10 @@ class TestVerifyProfilesAction(base.TestCase):
return {
'name': name,
'profile': the_profile,
'capabilities:boot_option': 'local',
'capabilities:profile': the_profile
'keys': {
'capabilities:boot_option': 'local',
'capabilities:profile': the_profile
}
}
def _test(self, expected_result):

View File

@ -330,19 +330,12 @@ workflows:
tasks:
check_run_validations:
on-complete:
- get_flavors: <% $.run_validations %>
- check_flavors: <% $.run_validations %>
- send_message: <% not $.run_validations %>
get_flavors:
action: nova.flavors_list
on-success: check_flavors
publish:
nova_flavors: <% task(get_flavors).result %>
check_flavors:
action: tripleo.validations.check_flavors
input:
flavors: <% $.nova_flavors %>
roles_info: <% $.roles_info %>
on-success: send_message
on-error: fail_check_flavors