Merge "Properly handle provisioning images"

This commit is contained in:
Jenkins 2015-08-25 08:08:34 +00:00 committed by Gerrit Code Review
commit 16f80e78c0
11 changed files with 69 additions and 89 deletions

View File

@ -256,7 +256,7 @@ class Plan(base.APIResourceWrapper):
key_params = []
for role in self.role_list:
key_params.extend([role.node_count_parameter_name,
role.image_id_parameter_name,
role.image_parameter_name,
role.flavor_parameter_name])
params = [p for p in params if p['name'] not in key_params]
return [Parameter(p, plan=self) for p in params]
@ -389,9 +389,17 @@ class Role(base.APIResourceWrapper):
@classmethod
@memoized.memoized
def _roles_by_image_id(cls, request, plan):
return {plan.parameter_value(role.image_id_parameter_name): role
for role in Role.list(request)}
def _roles_by_image(cls, request, plan):
roles_by_image = {}
for role in Role.list(request):
image = plan.parameter_value(role.image_parameter_name)
if image in roles_by_image:
roles_by_image[image].append(role)
else:
roles_by_image[image] = [role]
return roles_by_image
@classmethod
@handle_errors(_("Unable to retrieve overcloud role"))
@ -411,11 +419,11 @@ class Role(base.APIResourceWrapper):
Role can be found
:rtype: tuskar_ui.api.tuskar.Role
"""
roles = cls._roles_by_image_id(request, plan)
roles = cls._roles_by_image(request, plan)
try:
return roles[image.id]
return roles[image.name]
except KeyError:
return None
return []
@classmethod
@memoized.memoized
@ -445,7 +453,7 @@ class Role(base.APIResourceWrapper):
return self.parameter_prefix + 'count'
@property
def image_id_parameter_name(self):
def image_parameter_name(self):
return self.parameter_prefix + 'Image'
@property
@ -453,12 +461,13 @@ class Role(base.APIResourceWrapper):
return self.parameter_prefix + 'Flavor'
def image(self, plan):
image_id = plan.parameter_value(self.image_id_parameter_name)
if image_id:
image_name = plan.parameter_value(self.image_parameter_name)
if image_name:
try:
return glance.image_get(self._request, image_id)
except glance_exceptions.HTTPNotFound:
LOG.error("Couldn't obtain image with id %s" % image_id)
return glance.image_list_detailed(
self._request, filters={'name': image_name})[0][0]
except (glance_exceptions.HTTPNotFound, IndexError):
LOG.error("Couldn't obtain image with name %s" % image_name)
return None
def flavor(self, plan):

View File

@ -61,9 +61,9 @@ class ImagesTable(tables.DataTable):
verbose_name=_("Image Name"))
disk_format = tables.Column('disk_format',
verbose_name=_("Format"))
role = tables.Column(lambda image:
image.role.name if image.role else '-',
verbose_name=_("Deployment Role"))
roles = tables.Column(lambda image:
', '.join([r.name for r in image.roles]),
verbose_name=_("Deployment Roles"))
class Meta(object):
name = "images"

View File

@ -57,7 +57,7 @@ class IndexView(infrastructure_views.ItemCountMixin,
plan = tuskar_api.tuskar.Plan.get_the_plan(self.request)
for image in images:
image.role = tuskar_api.tuskar.Role.get_by_image(
image.roles = tuskar_api.tuskar.Role.get_by_image(
self.request, plan, image)
return images

View File

@ -162,8 +162,8 @@ class NodesTests(test.BaseAdminViewTests):
'register_nodes-0-cpus': '1',
'register_nodes-0-memory_mb': '2',
'register_nodes-0-local_gb': '3',
'register_nodes-0-deployment_kernel': images[6].id,
'register_nodes-0-deployment_ramdisk': images[7].id,
'register_nodes-0-deployment_kernel': images[3].id,
'register_nodes-0-deployment_ramdisk': images[4].id,
'register_nodes-1-driver': 'pxe_ipmitool',
'register_nodes-1-ipmi_address': '127.0.0.2',
@ -172,8 +172,8 @@ class NodesTests(test.BaseAdminViewTests):
'register_nodes-1-cpus': '4',
'register_nodes-1-memory_mb': '5',
'register_nodes-1-local_gb': '6',
'register_nodes-1-deployment_kernel': images[6].id,
'register_nodes-1-deployment_ramdisk': images[7].id,
'register_nodes-1-deployment_kernel': images[3].id,
'register_nodes-1-deployment_ramdisk': images[4].id,
}
with mock.patch('tuskar_ui.api.node.Node', **{
'spec_set': ['create', 'get_all_mac_addresses'],
@ -198,8 +198,8 @@ class NodesTests(test.BaseAdminViewTests):
ipmi_username=u'username',
ipmi_password=u'password',
driver='pxe_ipmitool',
deployment_kernel=images[6].id,
deployment_ramdisk=images[7].id,
deployment_kernel=images[3].id,
deployment_ramdisk=images[4].id,
),
mock.call(
mock.ANY,
@ -212,8 +212,8 @@ class NodesTests(test.BaseAdminViewTests):
ipmi_username=None,
ipmi_password=None,
driver='pxe_ipmitool',
deployment_kernel=images[6].id,
deployment_ramdisk=images[7].id,
deployment_kernel=images[3].id,
deployment_ramdisk=images[4].id,
),
])
@ -234,8 +234,8 @@ class NodesTests(test.BaseAdminViewTests):
'register_nodes-0-cpus': '1',
'register_nodes-0-memory_mb': '2',
'register_nodes-0-local_gb': '3',
'register_nodes-0-deployment_kernel': images[6].id,
'register_nodes-0-deployment_ramdisk': images[7].id,
'register_nodes-0-deployment_kernel': images[3].id,
'register_nodes-0-deployment_ramdisk': images[4].id,
'register_nodes-1-driver': 'pxe_ipmitool',
'register_nodes-1-ipmi_address': '127.0.0.2',
@ -244,8 +244,8 @@ class NodesTests(test.BaseAdminViewTests):
'register_nodes-1-cpus': '4',
'register_nodes-1-memory_mb': '5',
'register_nodes-1-local_gb': '6',
'register_nodes-1-deployment_kernel': images[6].id,
'register_nodes-1-deployment_ramdisk': images[7].id,
'register_nodes-1-deployment_kernel': images[3].id,
'register_nodes-1-deployment_ramdisk': images[4].id,
}
with mock.patch('tuskar_ui.api.node.Node', **{
'spec_set': ['create', 'get_all_mac_addresses'],
@ -269,8 +269,8 @@ class NodesTests(test.BaseAdminViewTests):
ipmi_username=u'username',
ipmi_password=u'password',
driver='pxe_ipmitool',
deployment_kernel=images[6].id,
deployment_ramdisk=images[7].id,
deployment_kernel=images[3].id,
deployment_ramdisk=images[4].id,
),
mock.call(
mock.ANY,
@ -283,8 +283,8 @@ class NodesTests(test.BaseAdminViewTests):
ipmi_username=None,
ipmi_password=None,
driver='pxe_ipmitool',
deployment_kernel=images[6].id,
deployment_ramdisk=images[7].id,
deployment_kernel=images[3].id,
deployment_ramdisk=images[4].id,
),
])
self.assertTemplateUsed(

View File

@ -48,15 +48,15 @@ class RolesTest(test.BaseAdminViewTests):
plans = [api.tuskar.Plan(plan)
for plan in self.tuskarclient_plans.list()]
flavor = self.novaclient_flavors.first()
image = self.glanceclient_images.first()
images = self.glanceclient_images.list()
with contextlib.nested(
patch('tuskar_ui.api.tuskar.Plan.list',
return_value=plans),
patch('tuskar_ui.api.tuskar.Role.list',
return_value=roles),
patch('openstack_dashboard.api.glance.image_get',
return_value=image),
patch('openstack_dashboard.api.glance.image_list_detailed',
return_value=[images]),
patch('tuskar_ui.api.flavor.Flavor.get_by_name',
return_value=flavor)):
res = self.client.get(INDEX_URL)
@ -69,7 +69,7 @@ class RolesTest(test.BaseAdminViewTests):
plans = [api.tuskar.Plan(plan)
for plan in self.tuskarclient_plans.list()]
flavor = self.novaclient_flavors.first()
image = self.glanceclient_images.first()
images = self.glanceclient_images.list()
stack = api.heat.Stack(TEST_DATA.heatclient_stacks.first())
with contextlib.nested(
@ -83,8 +83,8 @@ class RolesTest(test.BaseAdminViewTests):
return_value=[]),
patch('tuskar_ui.api.tuskar.Plan.list',
return_value=plans),
patch('openstack_dashboard.api.glance.image_get',
return_value=image),
patch('openstack_dashboard.api.glance.image_list_detailed',
return_value=[images]),
patch('tuskar_ui.api.flavor.Flavor.get_by_name',
return_value=flavor)):
res = self.client.get(DETAIL_URL)
@ -137,7 +137,7 @@ class RolesTest(test.BaseAdminViewTests):
'name': 'controller',
'description': 'The controller node role.',
'flavor': self.novaclient_flavors.first().name,
'image': self.glanceclient_images.first().id,
'image': self.glanceclient_images.first().name,
'nodes': '0',
}
@ -163,4 +163,4 @@ class RolesTest(test.BaseAdminViewTests):
args = mock_patch.call_args_list[0][0]
self.assertEqual(args[1], plan.id)
self.assertEqual(args[2]['Controller-1::Flavor'], u'flavor-1')
self.assertEqual(args[2]['Controller-1::Image'], u'2')
self.assertEqual(args[2]['Controller-1::Image'], u'overcloud-full')

View File

@ -143,7 +143,7 @@ class UpdateView(workflows.WorkflowView, views.StackMixin, views.RoleMixin):
role_flavor = '' if role_flavor is None else role_flavor.name
role_image = role.image(plan)
role_image = '' if role_image is None else role_image.id
role_image = '' if role_image is None else role_image.name
free_nodes = len(api.node.Node.list(self.request, associated=False,
maintenance=False))

View File

@ -78,7 +78,7 @@ class UpdateRoleInfoAction(workflows.Action):
images = [image for image in images
if tuskar_utils.check_image_type(image,
'overcloud provisioning')]
choices = [(i.id, i.name) for i in images]
choices = [(i.name, i.name) for i in images]
return [('', _('Unknown'))] + choices
def clean_nodes(self):
@ -170,7 +170,7 @@ class UpdateRole(workflows.Workflow):
redirect=reverse_lazy(self.index_url))
parameters = data['parameters']
parameters[role.image_id_parameter_name] = data['image']
parameters[role.image_parameter_name] = data['image']
parameters[role.node_count_parameter_name] = data['nodes']
if utils.matching_deployment_mode():
parameters[role.flavor_parameter_name] = data['flavor']

View File

@ -158,4 +158,4 @@ class NodeAPITests(test.APITestCase):
return_value=([instance], False),
):
ret_val = api.node.Node(node).image_name
self.assertEqual(ret_val, 'overcloud-control')
self.assertEqual(ret_val, 'overcloud-full')

View File

@ -108,8 +108,8 @@ class TuskarAPITests(test.APITestCase):
return_value=roles):
ret_val = api.tuskar.Role.get_by_image(
self.request, plan, image)
self.assertIsInstance(ret_val, api.tuskar.Role)
self.assertEqual(ret_val.name, 'Controller')
self.assertIsInstance(ret_val, list)
self.assertEqual(len(ret_val), 3)
def test_parameter_stripped_name(self):
plan = api.tuskar.Plan(self.tuskarclient_plans.first())

View File

@ -202,8 +202,8 @@ def data(TEST):
TEST.glanceclient_images = test_data_utils.TestDataContainer()
image_1 = images.Image(
images.ImageManager(None),
{'id': '2',
'name': 'overcloud-control',
{'id': '1',
'name': 'overcloud-full',
'is_public': True,
'protected': False,
'properties': {
@ -211,66 +211,38 @@ def data(TEST):
}})
image_2 = images.Image(
images.ImageManager(None),
{'id': '1',
'name': 'overcloud-compute',
'is_public': True,
'protected': False,
'properties': {
'type': 'overcloud provisioning'
}})
image_3 = images.Image(
images.ImageManager(None),
{'id': '3',
'name': 'Object Storage Image',
'is_public': True,
'protected': False,
'properties': {
'type': 'overcloud provisioning'
}})
image_4 = images.Image(
images.ImageManager(None),
{'id': '4',
'name': 'Block Storage Image',
'is_public': True,
'protected': False,
'properties': {
'type': 'overcloud provisioning'
}})
image_5 = images.Image(
images.ImageManager(None),
{'id': '5',
{'id': '2',
'name': 'Discovery Ramdisk',
'is_public': True,
'protected': False,
'properties': {
'type': 'discovery ramdisk'
}})
image_6 = images.Image(
image_3 = images.Image(
images.ImageManager(None),
{'id': '6',
{'id': '3',
'name': 'Discovery Kernel',
'is_public': True,
'protected': False,
'properties': {
'type': 'discovery kernel'
}})
image_7 = images.Image(
image_4 = images.Image(
images.ImageManager(None),
{'id': '7',
{'id': '4',
'name': 'Baremetal Deployment Kernel',
'is_public': True,
'protected': False,
'properties': {
'type': 'deploy kernel'
}})
image_8 = images.Image(
image_5 = images.Image(
images.ImageManager(None),
{'id': '8',
{'id': '5',
'name': 'Baremetal Deployment Ramdisk',
'is_public': True,
'protected': False,
'properties': {
'type': 'deploy ramdisk'
}})
TEST.glanceclient_images.add(image_1, image_2, image_3, image_4,
image_5, image_6, image_7, image_8)
TEST.glanceclient_images.add(image_1, image_2, image_3, image_4, image_5)

View File

@ -29,7 +29,6 @@ def data(TEST):
'template': '',
'created_at': '2014-05-27T21:11:09Z',
'modified_at': '2014-05-30T21:11:09Z',
'uuid': '1234567890',
'roles': [
{
'uuid': 'role-1',
@ -108,7 +107,7 @@ def data(TEST):
'description': 'Controller image ID',
'hidden': False,
'default': '',
'value': '2',
'value': 'overcloud-full',
'parameter_type': 'string',
'constraints': [],
}, {
@ -117,7 +116,7 @@ def data(TEST):
'description': 'Compute image ID',
'hidden': False,
'default': '',
'value': '1',
'value': 'overcloud-full',
'parameter_type': 'string',
'constraints': [],
}, {
@ -126,7 +125,7 @@ def data(TEST):
'description': 'Block storage image ID',
'hidden': False,
'default': '',
'value': '4',
'value': 'overcloud-full',
'parameter_type': 'string',
'constraints': [],
}, {