diff --git a/tuskar_ui/api/flavor.py b/tuskar_ui/api/flavor.py index 8381ff3b1..fbe84d4ce 100644 --- a/tuskar_ui/api/flavor.py +++ b/tuskar_ui/api/flavor.py @@ -88,6 +88,13 @@ class Flavor(object): def get(cls, request, flavor_id): return cls(nova.flavor_get(request, flavor_id)) + @classmethod + @handle_errors(_("Unable to load flavor.")) + def get_by_name(cls, request, name): + for flavor in cls.list(request): + if flavor.name == name: + return flavor + @classmethod @handle_errors(_("Unable to retrieve flavor list."), []) def list(cls, request): @@ -100,8 +107,11 @@ class Flavor(object): """Get and memoize ID's of deployed flavors.""" servers = nova.server_list(request)[0] deployed_ids = set(server.flavor['id'] for server in servers) + deployed_names = [] for plan in tuskar_ui.api.tuskar.OvercloudPlan.list(request): - deployed_ids |= set( - plan.parameter_value(role.flavor_id_parameter_name) - for role in plan.role_list) - return deployed_ids + deployed_names.extend( + [plan.parameter_value(role.instance_type_parameter_name) + for role in plan.role_list]) + return [flavor.id for flavor in cls.list(request) + if flavor.id not in deployed_ids + and flavor.name not in deployed_names] diff --git a/tuskar_ui/api/tuskar.py b/tuskar_ui/api/tuskar.py index 80783bd33..51dac19b9 100644 --- a/tuskar_ui/api/tuskar.py +++ b/tuskar_ui/api/tuskar.py @@ -158,7 +158,7 @@ class OvercloudPlan(base.APIResourceWrapper): for role in self.role_list: key_params.extend([role.node_count_parameter_name, role.image_id_parameter_name, - role.flavor_id_parameter_name]) + role.instance_type_parameter_name]) params = [p for p in params if p['name'] not in key_params] return params @@ -254,17 +254,13 @@ class OvercloudRole(base.APIResourceWrapper): def node_count_parameter_name(self): return self.parameter_prefix + 'count' - # TODO(tzumainn): fix this once we know how this connection can be - # made @property def image_id_parameter_name(self): - return self.parameter_prefix + 'ImageID' + return self.parameter_prefix + 'image_id' - # TODO(tzumainn): fix this once we know how this connection can be - # made @property - def flavor_id_parameter_name(self): - return self.parameter_prefix + 'FlavorID' + def instance_type_parameter_name(self): + return self.parameter_prefix + 'instance_type' def image(self, plan): image_id = plan.parameter_value(self.image_id_parameter_name) @@ -272,9 +268,10 @@ class OvercloudRole(base.APIResourceWrapper): return glance.image_get(self._request, image_id) def flavor(self, plan): - flavor_id = plan.parameter_value(self.flavor_id_parameter_name) - if flavor_id: - return flavor.Flavor.get(self._request, flavor_id) + instance_type = plan.parameter_value( + self.instance_type_parameter_name) + if instance_type: + return flavor.Flavor.get_by_name(self._request, instance_type) @property def id(self): diff --git a/tuskar_ui/infrastructure/flavors/tests.py b/tuskar_ui/infrastructure/flavors/tests.py index 27020579b..319acd717 100644 --- a/tuskar_ui/infrastructure/flavors/tests.py +++ b/tuskar_ui/infrastructure/flavors/tests.py @@ -85,7 +85,7 @@ class FlavorsTest(test.BaseAdminViewTests): res = self.client.get(INDEX_URL) self.assertEqual(plans_mock.call_count, 1) self.assertEqual(roles_mock.call_count, 4) - self.assertEqual(flavors_mock.call_count, 1) + self.assertEqual(flavors_mock.call_count, 2) self.assertEqual(servers_mock.call_count, 1) self.assertTemplateUsed(res, 'infrastructure/flavors/index.html') diff --git a/tuskar_ui/infrastructure/roles/tables.py b/tuskar_ui/infrastructure/roles/tables.py index bbe99ea0c..a9d27c1cc 100644 --- a/tuskar_ui/infrastructure/roles/tables.py +++ b/tuskar_ui/infrastructure/roles/tables.py @@ -23,7 +23,7 @@ class RolesTable(tables.DataTable): name = tables.Column('name', link="horizon:infrastructure:roles:detail", - verbose_name=_("Image Name")) + verbose_name=_("Role")) flavor = tables.Column('flavor', verbose_name=_("Flavor")) image = tables.Column('image', diff --git a/tuskar_ui/infrastructure/roles/tests.py b/tuskar_ui/infrastructure/roles/tests.py index 04f23fdd1..f0716c7dd 100644 --- a/tuskar_ui/infrastructure/roles/tests.py +++ b/tuskar_ui/infrastructure/roles/tests.py @@ -47,6 +47,7 @@ class RolesTest(test.BaseAdminViewTests): plans = [api.tuskar.OvercloudPlan(plan) for plan in self.tuskarclient_plans.list()] flavor = self.novaclient_flavors.first() + image = self.glanceclient_images.first() with contextlib.nested( patch('tuskar_ui.api.tuskar.OvercloudPlan.list', @@ -54,8 +55,8 @@ class RolesTest(test.BaseAdminViewTests): patch('tuskar_ui.api.tuskar.OvercloudRole.list', return_value=roles), patch('openstack_dashboard.api.glance.image_get', - return_value=None), - patch('tuskar_ui.api.flavor.Flavor.get', + return_value=image), + patch('tuskar_ui.api.flavor.Flavor.get_by_name', return_value=flavor)): res = self.client.get(INDEX_URL) @@ -67,6 +68,7 @@ class RolesTest(test.BaseAdminViewTests): plans = [api.tuskar.OvercloudPlan(plan) for plan in self.tuskarclient_plans.list()] flavor = self.novaclient_flavors.first() + image = self.glanceclient_images.first() with contextlib.nested( patch('tuskar_ui.api.tuskar.OvercloudRole.list', @@ -75,7 +77,9 @@ class RolesTest(test.BaseAdminViewTests): return_value=[]), patch('tuskar_ui.api.tuskar.OvercloudPlan.list', return_value=plans), - patch('tuskar_ui.api.flavor.Flavor.get', + patch('openstack_dashboard.api.glance.image_get', + return_value=image), + patch('tuskar_ui.api.flavor.Flavor.get_by_name', return_value=flavor)): res = self.client.get(DETAIL_URL) diff --git a/tuskar_ui/infrastructure/roles/views.py b/tuskar_ui/infrastructure/roles/views.py index b411862ae..c56856a65 100644 --- a/tuskar_ui/infrastructure/roles/views.py +++ b/tuskar_ui/infrastructure/roles/views.py @@ -114,6 +114,6 @@ class DetailView(horizon_tables.DataTableView, OvercloudRoleMixin, StackMixin): context['flavor'] = role.flavor(plan) # TODO(tzumainn): we don't mock images, so calling role.image(plan) # won't work right now - context['image'] = None + context['image'] = role.image(plan) return context diff --git a/tuskar_ui/test/test_data/tuskar_data.py b/tuskar_ui/test/test_data/tuskar_data.py index 2f3db1644..facb75fb2 100644 --- a/tuskar_ui/test/test_data/tuskar_data.py +++ b/tuskar_ui/test/test_data/tuskar_data.py @@ -66,37 +66,37 @@ def data(TEST): 'hidden': 'false', 'value': 5, }, { - 'name': 'controller-1::FlavorID', - 'label': 'Controller Flavor ID', - 'description': 'Controller flavor ID', + 'name': 'Controller-1::instance_type', + 'label': 'Controller Instance Type', + 'description': 'Controller instance type', 'hidden': 'false', - 'value': '1', + 'value': 'flavor-1', }, { - 'name': 'compute-1::FlavorID', - 'label': 'Compute Flavor ID', - 'description': 'Compute flavor ID', + 'name': 'Compute-1::instance_type', + 'label': 'Compute Instance Type', + 'description': 'Compute instance type', 'hidden': 'false', - 'value': '1', + 'value': 'flavor-1', }, { - 'name': 'Block Storage-1::FlavorID', - 'label': 'Block Storage Flavor ID', - 'description': 'Block storage flavor ID', + 'name': 'Block Storage-1::instance_type', + 'label': 'Block Storage Instance Type', + 'description': 'Block storage instance type', 'hidden': 'false', - 'value': '2', + 'value': 'flavor-2', }, { - 'name': 'Controller-1::ImageID', + 'name': 'Controller-1::image_id', 'label': 'Controller Image ID', 'description': 'Controller image ID', 'hidden': 'false', 'value': '2', }, { - 'name': 'Compute-1::ImageID', + 'name': 'Compute-1::image_id', 'label': 'Compute Image ID', 'description': 'Compute image ID', 'hidden': 'false', 'value': '1', }, { - 'name': 'Block Storage-1::ImageID', + 'name': 'Block Storage-1::image_id', 'label': 'Block Storage Image ID', 'description': 'Block storage image ID', 'hidden': 'false',