Rename node profile to flavor

Implements: blueprint rename-node-profiles-to-flavors
Change-Id: Ic530041615d04878ff9586038abaf9e8dc7f707a
This commit is contained in:
Tzu-Mainn Chen 2014-04-03 18:51:41 +02:00
parent 1126213b1a
commit d010384fd3
20 changed files with 167 additions and 167 deletions

View File

@ -135,10 +135,10 @@ def transform_sizing(overcloud_sizing):
} for (role, flavor), sizing in overcloud_sizing.items()]
class NodeProfile(object):
class Flavor(object):
def __init__(self, flavor):
"""Construct node profile by wrapping flavor
"""Construct by wrapping Nova flavor
:param flavor: Nova flavor
:type flavor: novaclient.v1_1.flavors.Flavor
@ -166,7 +166,7 @@ class NodeProfile(object):
@cached_property
def extras_dict(self):
"""Return extra parameters of node profile
"""Return extra flavor parameters
:return: Nova flavor keys
:rtype: dict
@ -195,12 +195,12 @@ class NodeProfile(object):
metadata=extras_dict))
@classmethod
@handle_errors(_("Unable to load node profile"))
def get(cls, request, node_profile_id):
return cls(nova.flavor_get(request, node_profile_id))
@handle_errors(_("Unable to load flavor."))
def get(cls, request, flavor_id):
return cls(nova.flavor_get(request, flavor_id))
@classmethod
@handle_errors(_("Unable to retrieve node profile list."), [])
@handle_errors(_("Unable to retrieve flavor list."), [])
def list(cls, request):
return [cls(item) for item in nova.flavor_list(request)]
@ -208,7 +208,7 @@ class NodeProfile(object):
@memoized.memoized
@handle_errors(_("Unable to retrieve existing servers list."), [])
def list_deployed_ids(cls, request):
"""Get and memoize ID's of deployed node profiles."""
"""Get and memoize ID's of deployed flavors."""
servers = nova.server_list(request)[0]
return set(server.flavor['id'] for server in servers)

View File

@ -22,7 +22,7 @@ class BasePanels(horizon.PanelGroup):
panels = (
'overcloud',
'nodes',
'node_profiles',
'flavors',
)

View File

@ -19,9 +19,9 @@ import horizon
from tuskar_ui.infrastructure import dashboard
class NodeProfiles(horizon.Panel):
name = _("Node Profiles")
slug = "node_profiles"
class Flavors(horizon.Panel):
name = _("Flavors")
slug = "flavors"
dashboard.Infrastructure.register(NodeProfiles)
dashboard.Infrastructure.register(Flavors)

View File

@ -21,43 +21,43 @@ from openstack_dashboard.dashboards.admin.flavors \
from tuskar_ui import api
class CreateNodeProfile(flavor_tables.CreateFlavor):
verbose_name = _("New Node Profile")
url = "horizon:infrastructure:node_profiles:create"
class CreateFlavor(flavor_tables.CreateFlavor):
verbose_name = _("New Flavor")
url = "horizon:infrastructure:flavors:create"
class CreateSuggestedNodeProfile(CreateNodeProfile):
class CreateSuggestedFlavor(CreateFlavor):
verbose_name = _("Create")
class DeleteNodeProfile(flavor_tables.DeleteFlavor):
class DeleteFlavor(flavor_tables.DeleteFlavor):
def __init__(self, **kwargs):
super(DeleteNodeProfile, self).__init__(**kwargs)
super(DeleteFlavor, self).__init__(**kwargs)
# NOTE(dtantsur): setting class attributes doesn't work
# probably due to metaclass magic in actions
self.data_type_singular = _("Node Profile")
self.data_type_plural = _("Node Profiles")
self.data_type_singular = _("Flavor")
self.data_type_plural = _("Flavors")
def allowed(self, request, datum=None):
"""Check that action is allowed on node profile
"""Check that action is allowed on flavor
This is overridden method from horizon.tables.BaseAction.
:param datum: node profile we're operating on
:type datum: tuskar_ui.api.NodeProfile
:param datum: flavor we're operating on
:type datum: tuskar_ui.api.Flavor
"""
if datum is not None:
deployed_profiles = api.NodeProfile.list_deployed_ids(
deployed_flavors = api.Flavor.list_deployed_ids(
request, _error_default=None)
if deployed_profiles is None or datum.id in deployed_profiles:
if deployed_flavors is None or datum.id in deployed_flavors:
return False
return super(DeleteNodeProfile, self).allowed(request, datum)
return super(DeleteFlavor, self).allowed(request, datum)
class NodeProfilesTable(tables.DataTable):
name = tables.Column('name', verbose_name=_('Node Profile'),
link="horizon:infrastructure:node_profiles:details")
class FlavorsTable(tables.DataTable):
name = tables.Column('name', verbose_name=_('Flavor'),
link="horizon:infrastructure:flavors:details")
arch = tables.Column('cpu_arch', verbose_name=_('Architecture'))
vcpus = tables.Column('vcpus', verbose_name=_('CPUs'))
ram = tables.Column(flavor_tables.get_size,
@ -73,15 +73,15 @@ class NodeProfilesTable(tables.DataTable):
verbose_name=_('Deploy Ramdisk Image ID'))
class Meta:
name = "node_profiles"
verbose_name = _("Node Profiles")
table_actions = (CreateNodeProfile,
DeleteNodeProfile,
name = "flavors"
verbose_name = _("Flavors")
table_actions = (CreateFlavor,
DeleteFlavor,
flavor_tables.FlavorFilterAction)
row_actions = (DeleteNodeProfile,)
row_actions = (DeleteFlavor,)
class NodeProfileRolesTable(tables.DataTable):
class FlavorRolesTable(tables.DataTable):
name = tables.Column('name', verbose_name=_('Role Name'))
def __init__(self, request, *args, **kwargs):
@ -96,10 +96,10 @@ class NodeProfileRolesTable(tables.DataTable):
count_getter,
verbose_name=_("Instances Count")
)
super(NodeProfileRolesTable, self).__init__(request, *args, **kwargs)
super(FlavorRolesTable, self).__init__(request, *args, **kwargs)
class ProfileSuggestionsTable(tables.DataTable):
class FlavorSuggestionsTable(tables.DataTable):
arch = tables.Column('cpu_arch', verbose_name=_('Architecture'))
vcpus = tables.Column('vcpus', verbose_name=_('CPUs'))
ram = tables.Column(flavor_tables.get_size, verbose_name=_('Memory'),
@ -108,7 +108,7 @@ class ProfileSuggestionsTable(tables.DataTable):
verbose_name=_('Disk'), attrs={'data-type': 'size'})
class Meta:
name = "profile_suggestions"
verbose_name = _("Profile Suggestions")
name = "flavor_suggestions"
verbose_name = _("Flavor Suggestions")
table_actions = ()
row_actions = (CreateSuggestedNodeProfile,)
row_actions = (CreateSuggestedFlavor,)

View File

@ -16,41 +16,41 @@ from django.utils.translation import ugettext_lazy as _
import horizon.tabs
from tuskar_ui import api
from tuskar_ui.infrastructure.node_profiles import tables
from tuskar_ui.infrastructure.flavors import tables
def _get_unmatched_suggestions(request):
unmatched_suggestions = []
profile_suggestions = [ProfileSuggestion.from_node_profile(node_profile)
for node_profile in api.NodeProfile.list(request)]
flavor_suggestions = [FlavorSuggestion.from_flavor(flavor)
for flavor in api.Flavor.list(request)]
for node in api.Node.list(request):
node_suggestion = ProfileSuggestion.from_node(node)
for profile_suggestion in profile_suggestions:
if profile_suggestion == node_suggestion:
node_suggestion = FlavorSuggestion.from_node(node)
for flavor_suggestion in flavor_suggestions:
if flavor_suggestion == node_suggestion:
break
else:
unmatched_suggestions.append(node_suggestion)
return unmatched_suggestions
def get_profile_suggestions(request):
def get_flavor_suggestions(request):
return set(_get_unmatched_suggestions(request))
class NodeProfilesTab(horizon.tabs.TableTab):
name = _("Node Profiles")
slug = 'node_profiles'
table_classes = (tables.NodeProfilesTable,)
class FlavorsTab(horizon.tabs.TableTab):
name = _("Flavors")
slug = 'flavors'
table_classes = (tables.FlavorsTable,)
template_name = ("horizon/common/_detail_table.html")
preload = False
def get_node_profiles_data(self):
node_profiles = api.NodeProfile.list(self.request)
node_profiles.sort(key=lambda np: (np.vcpus, np.ram, np.disk))
return node_profiles
def get_flavors_data(self):
flavors = api.Flavor.list(self.request)
flavors.sort(key=lambda np: (np.vcpus, np.ram, np.disk))
return flavors
class ProfileSuggestion(object):
class FlavorSuggestion(object):
"""Describe node parameters in a way that is easy to compare."""
def __init__(self, vcpus=None, ram=None, disk=None, cpu_arch=None,
@ -72,11 +72,11 @@ class ProfileSuggestion(object):
)
@classmethod
def from_node_profile(cls, node_profile):
def from_flavor(cls, flavor):
return cls(
vcpus=node_profile.vcpus,
ram_bytes=node_profile.ram_bytes,
disk_bytes=node_profile.disk_bytes,
vcpus=flavor.vcpus,
ram_bytes=flavor.ram_bytes,
disk_bytes=flavor.disk_bytes,
# TODO(rdopieralski) Add architecture when available.
)
@ -120,21 +120,21 @@ class ProfileSuggestion(object):
)
class ProfileSuggestionsTab(horizon.tabs.TableTab):
name = _("Profile Suggestions")
slug = 'profile_suggestions'
table_classes = (tables.ProfileSuggestionsTable,)
class FlavorSuggestionsTab(horizon.tabs.TableTab):
name = _("Flavor Suggestions")
slug = 'flavor_suggestions'
table_classes = (tables.FlavorSuggestionsTable,)
template_name = ("horizon/common/_detail_table.html")
preload = False
def get_profile_suggestions_data(self):
return list(get_profile_suggestions(self.request))
def get_flavor_suggestions_data(self):
return list(get_flavor_suggestions(self.request))
class NodeProfileTabs(horizon.tabs.TabGroup):
slug = 'node_profile_tabs'
class FlavorTabs(horizon.tabs.TabGroup):
slug = 'flavor_tabs'
tabs = (
NodeProfilesTab,
ProfileSuggestionsTab,
FlavorsTab,
FlavorSuggestionsTab,
)
sticky = True

View File

@ -1,9 +1,9 @@
{% extends 'infrastructure/base.html' %}
{% load i18n %}
{% block title %}{% trans "Create Node Profile" %}{% endblock %}
{% block title %}{% trans "Create Flavor" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Create Node Profile") %}
{% include "horizon/common/_page_header.html" with title=_("Create Flavor") %}
{% endblock page_header %}
{% block main %}

View File

@ -1,9 +1,9 @@
{% extends 'infrastructure/base.html' %}
{% load i18n %}
{% block title %}{% trans 'Node Profile Details' %}{% endblock %}
{% block title %}{% trans 'Flavor Details' %}{% endblock %}
{% block page_header %}
{% include 'horizon/common/_page_header.html' with title=_('Node Profile Details') %}
{% include 'horizon/common/_page_header.html' with title=_('Flavor Details') %}
{% endblock page_header %}
{% block main %}
@ -12,13 +12,13 @@
<h4>{% trans "Hardware Info" %}</h4>
<dl class="clearfix">
<dt>{% trans "Architecture" %}</dt>
<dd>{{ node_profile.cpu_arch|default:"&mdash;" }}</dd>
<dd>{{ flavor.cpu_arch|default:"&mdash;" }}</dd>
<dt>{% trans "CPUs" %}</dt>
<dd>{{ node_profile.vcpus|default:"&mdash;" }}</dd>
<dd>{{ flavor.vcpus|default:"&mdash;" }}</dd>
<dt>{% trans "Memory" %}</dt>
<dd>{{ node_profile.ram_bytes|filesizeformat|default:"&mdash;" }}</dd>
<dd>{{ flavor.ram_bytes|filesizeformat|default:"&mdash;" }}</dd>
<dt>{% trans "Disk" %}</dt>
<dd>{{ node_profile.disk_bytes|filesizeformat|default:"&mdash;" }}</dd>
<dd>{{ flavor.disk_bytes|filesizeformat|default:"&mdash;" }}</dd>
</dl>
<h4>{% trans "Deploy Images" %}</h4>
<dl class="clearfix">

View File

@ -1,10 +1,10 @@
{% extends 'infrastructure/base.html' %}
{% load i18n %}
{% load url from future %}
{% block title %}{% trans 'Node Profiles' %}{% endblock %}
{% block title %}{% trans 'Flavors' %}{% endblock %}
{% block page_header %}
{% include 'horizon/common/_domain_page_header.html' with title=_('Node Profiles') %}
{% include 'horizon/common/_domain_page_header.html' with title=_('Flavors') %}
{% endblock page_header %}
{% block main %}

View File

@ -30,10 +30,10 @@ from tuskar_ui.test.test_data import tuskar_data
TEST_DATA = utils.TestDataContainer()
tuskar_data.data(TEST_DATA)
INDEX_URL = urlresolvers.reverse(
'horizon:infrastructure:node_profiles:index')
'horizon:infrastructure:flavors:index')
CREATE_URL = urlresolvers.reverse(
'horizon:infrastructure:node_profiles:create')
DETAILS_VIEW = 'horizon:infrastructure:node_profiles:details'
'horizon:infrastructure:flavors:create')
DETAILS_VIEW = 'horizon:infrastructure:flavors:details'
@contextlib.contextmanager
@ -49,7 +49,7 @@ def _prepare_create():
'kernel_image_id': images[0].id,
'ramdisk_image_id': images[1].id}
with contextlib.nested(
patch('tuskar_ui.api.NodeProfile.create',
patch('tuskar_ui.api.Flavor.create',
return_value=flavor),
patch('openstack_dashboard.api.glance.image_list_detailed',
return_value=(TEST_DATA.glanceclient_images.list(), False)),
@ -60,7 +60,7 @@ def _prepare_create():
yield mocks[0], data
class NodeProfilesTest(test.BaseAdminViewTests):
class FlavorsTest(test.BaseAdminViewTests):
def test_index(self):
with contextlib.nested(
@ -74,7 +74,7 @@ class NodeProfilesTest(test.BaseAdminViewTests):
self.assertEqual(servers_mock.call_count, 1)
self.assertTemplateUsed(res,
'infrastructure/node_profiles/index.html')
'infrastructure/flavors/index.html')
def test_index_recoverable_failure(self):
with patch('openstack_dashboard.api.nova.flavor_list',
@ -89,7 +89,7 @@ class NodeProfilesTest(test.BaseAdminViewTests):
res = self.client.get(CREATE_URL)
self.assertEqual(mock.call_count, 2)
self.assertTemplateUsed(res,
'infrastructure/node_profiles/create.html')
'infrastructure/flavors/create.html')
def test_create_get_recoverable_failure(self):
with patch('openstack_dashboard.api.glance.image_list_detailed',
@ -119,7 +119,7 @@ class NodeProfilesTest(test.BaseAdminViewTests):
def test_delete_ok(self):
flavors = TEST_DATA.novaclient_flavors.list()
data = {'action': 'node_profiles__delete',
data = {'action': 'flavors__delete',
'object_ids': [flavors[0].id, flavors[1].id]}
with contextlib.nested(
patch('openstack_dashboard.api.nova.flavor_delete'),
@ -146,7 +146,7 @@ class NodeProfilesTest(test.BaseAdminViewTests):
'status': 'ACTIVE',
'flavor': {'id': flavors[0].id}}
)
data = {'action': 'node_profiles__delete',
data = {'action': 'flavors__delete',
'object_ids': [flavors[0].id, flavors[1].id]}
with contextlib.nested(
patch('openstack_dashboard.api.nova.flavor_delete'),
@ -165,14 +165,14 @@ class NodeProfilesTest(test.BaseAdminViewTests):
self.assertEqual(server_list_mock.call_count, 1)
def test_details_no_overcloud(self):
flavor = api.NodeProfile(TEST_DATA.novaclient_flavors.first())
flavor = api.Flavor(TEST_DATA.novaclient_flavors.first())
images = TEST_DATA.glanceclient_images.list()[:2]
roles = TEST_DATA.tuskarclient_overcloud_roles.list()
roles[0].flavor_id = flavor.id
with contextlib.nested(
patch('openstack_dashboard.api.glance.image_get',
side_effect=images),
patch('tuskar_ui.api.NodeProfile.get',
patch('tuskar_ui.api.Flavor.get',
return_value=flavor),
patch('tuskar_ui.api.OvercloudRole.list',
return_value=roles),
@ -186,10 +186,10 @@ class NodeProfilesTest(test.BaseAdminViewTests):
self.assertEqual(roles_mock.call_count, 1)
self.assertEqual(overcloud_mock.call_count, 1)
self.assertTemplateUsed(res,
'infrastructure/node_profiles/details.html')
'infrastructure/flavors/details.html')
def test_details(self):
flavor = api.NodeProfile(TEST_DATA.novaclient_flavors.first())
flavor = api.Flavor(TEST_DATA.novaclient_flavors.first())
images = TEST_DATA.glanceclient_images.list()[:2]
roles = TEST_DATA.tuskarclient_overcloud_roles.list()
roles[0].flavor_id = flavor.id
@ -197,7 +197,7 @@ class NodeProfilesTest(test.BaseAdminViewTests):
with contextlib.nested(
patch('openstack_dashboard.api.glance.image_get',
side_effect=images),
patch('tuskar_ui.api.NodeProfile.get',
patch('tuskar_ui.api.Flavor.get',
return_value=flavor),
patch('tuskar_ui.api.OvercloudRole.list',
return_value=roles),
@ -216,4 +216,4 @@ class NodeProfilesTest(test.BaseAdminViewTests):
self.assertEqual(count_mock.call_count, 1)
self.assertListEqual(count_mock.call_args_list, [call(roles[0])])
self.assertTemplateUsed(res,
'infrastructure/node_profiles/details.html')
'infrastructure/flavors/details.html')

View File

@ -14,11 +14,11 @@
from django.conf import urls
from tuskar_ui.infrastructure.node_profiles import views
from tuskar_ui.infrastructure.flavors import views
urlpatterns = urls.patterns(
'tuskar_ui.infrastructure.node_profiles.views',
'tuskar_ui.infrastructure.flavors.views',
urls.url(r'^$', views.IndexView.as_view(), name='index'),
urls.url(r'^create/(?P<suggestion_id>[^/]+)$', views.CreateView.as_view(),
name='create'),

View File

@ -21,9 +21,9 @@ import horizon.tabs
import horizon.workflows
import tuskar_ui.api
from tuskar_ui.infrastructure.node_profiles import tables
from tuskar_ui.infrastructure.node_profiles import tabs
from tuskar_ui.infrastructure.node_profiles import workflows
from tuskar_ui.infrastructure.flavors import tables
from tuskar_ui.infrastructure.flavors import tabs
from tuskar_ui.infrastructure.flavors import workflows
def image_get(request, image_id, error_message):
@ -35,20 +35,20 @@ def image_get(request, image_id, error_message):
class IndexView(horizon.tabs.TabbedTableView):
tab_group_class = tabs.NodeProfileTabs
template_name = 'infrastructure/node_profiles/index.html'
tab_group_class = tabs.FlavorTabs
template_name = 'infrastructure/flavors/index.html'
class CreateView(horizon.workflows.WorkflowView):
workflow_class = workflows.CreateNodeProfile
template_name = 'infrastructure/node_profiles/create.html'
workflow_class = workflows.CreateFlavor
template_name = 'infrastructure/flavors/create.html'
def get_initial(self):
suggestion_id = self.kwargs.get('suggestion_id')
if not suggestion_id:
return super(CreateView, self).get_initial()
node = tuskar_ui.api.Node.get(self.request, suggestion_id)
suggestion = tabs.ProfileSuggestion.from_node(node)
suggestion = tabs.FlavorSuggestion.from_node(node)
return {
'name': suggestion.name,
'vcpus': suggestion.vcpus,
@ -59,25 +59,25 @@ class CreateView(horizon.workflows.WorkflowView):
class DetailView(horizon.tables.DataTableView):
table_class = tables.NodeProfileRolesTable
template_name = 'infrastructure/node_profiles/details.html'
error_redirect = reverse_lazy('horizon:infrastructure:node_profiles:index')
table_class = tables.FlavorRolesTable
template_name = 'infrastructure/flavors/details.html'
error_redirect = reverse_lazy('horizon:infrastructure:flavors:index')
def get_context_data(self, **kwargs):
context = super(DetailView, self).get_context_data(**kwargs)
context['node_profile'] = tuskar_ui.api.NodeProfile.get(
context['flavor'] = tuskar_ui.api.Flavor.get(
self.request,
kwargs.get('flavor_id'),
_error_redirect=self.error_redirect
)
context['kernel_image'] = image_get(
self.request,
context['node_profile'].kernel_image_id,
context['flavor'].kernel_image_id,
error_message=_("Cannot get kernel image details")
)
context['ramdisk_image'] = image_get(
self.request,
context['node_profile'].ramdisk_image_id,
context['flavor'].ramdisk_image_id,
error_message=_("Cannot get ramdisk image details")
)
return context

View File

@ -24,7 +24,7 @@ from openstack_dashboard.dashboards.admin.flavors \
from tuskar_ui import api
class CreateNodeProfileAction(flavor_workflows.CreateFlavorInfoAction):
class CreateFlavorAction(flavor_workflows.CreateFlavorInfoAction):
arch = fields.ChoiceField(choices=(('i386', 'i386'), ('amd64', 'amd64')),
label=_("Architecture"))
kernel_image_id = fields.ChoiceField(choices=(),
@ -33,7 +33,7 @@ class CreateNodeProfileAction(flavor_workflows.CreateFlavorInfoAction):
label=_("Deploy Ramdisk Image"))
def __init__(self, *args, **kwrds):
super(CreateNodeProfileAction, self).__init__(*args, **kwrds)
super(CreateFlavorAction, self).__init__(*args, **kwrds)
try:
kernel_images = glance.image_list_detailed(
self.request,
@ -62,14 +62,14 @@ class CreateNodeProfileAction(flavor_workflows.CreateFlavorInfoAction):
del self.fields['flavor_id']
class Meta:
name = _("Node Profile")
name = _("Flavor")
# FIXME(dtantsur): maybe better help text?
help_text = _("From here you can create a new "
"node profile to organize instance resources.")
"flavor to organize instance resources.")
class CreateNodeProfileStep(workflows.Step):
action_class = CreateNodeProfileAction
class CreateFlavorStep(workflows.Step):
action_class = CreateFlavorAction
contributes = ("name",
"vcpus",
"memory_mb",
@ -79,18 +79,18 @@ class CreateNodeProfileStep(workflows.Step):
"ramdisk_image_id")
class CreateNodeProfile(flavor_workflows.CreateFlavor):
slug = "create_node_profile"
name = _("Create Node Profile")
finalize_button_name = _("Create Node Profile")
success_message = _('Created new node profile "%s".')
failure_message = _('Unable to create node profile "%s".')
success_url = "horizon:infrastructure:node_profiles:index"
default_steps = (CreateNodeProfileStep,)
class CreateFlavor(flavor_workflows.CreateFlavor):
slug = "create_flavor"
name = _("Create Flavor")
finalize_button_name = _("Create Flavor")
success_message = _('Created new flavor "%s".')
failure_message = _('Unable to create flavor "%s".')
success_url = "horizon:infrastructure:flavors:index"
default_steps = (CreateFlavorStep,)
def handle(self, request, data):
try:
self.object = api.NodeProfile.create(
self.object = api.Flavor.create(
request,
name=data['name'],
memory=data['memory_mb'],
@ -101,6 +101,6 @@ class CreateNodeProfile(flavor_workflows.CreateFlavor):
ramdisk_image_id=data['ramdisk_image_id']
)
except Exception:
exceptions.handle(request, _("Unable to create node profile"))
exceptions.handle(request, _("Unable to create flavor"))
return False
return True

View File

@ -63,7 +63,7 @@ class OvercloudRoleForm(horizon.forms.SelfHandlingForm):
widget=django.forms.TextInput(
attrs={'readonly': 'readonly', 'disabled': 'disabled'}))
flavor_id = django.forms.ChoiceField(
label=_("Node Profile"), required=False, choices=())
label=_("Flavor"), required=False, choices=())
def __init__(self, *args, **kwargs):
super(OvercloudRoleForm, self).__init__(*args, **kwargs)

View File

@ -5,7 +5,7 @@
<table class="table">
<tr>
<th>{% trans "Name" %}</th>
<th>{% trans "Node profiles" %}</th>
<th>{% trans "Flavors" %}</th>
<th>{% trans "Nodes" %}</th>
{% if show_change %}
<th>{% trans "Change" %}</th>
@ -33,9 +33,9 @@
(<a
href="{% url 'horizon:infrastructure:overcloud:role_edit' role_id %}"
class="ajax-modal"
>{% trans "Add a node profile" %}</a>)
>{% trans "Add a flavor" %}</a>)
{% else %}
({% trans "No node profile" %})
({% trans "No flavor" %})
{% endif %}
</td>
<td>

View File

@ -12,7 +12,7 @@
<div class="span12">
<p><strong>{% blocktrans count counter=nodes|length %}{{ counter }} instance{% plural %}{{ counter }} instances{% endblocktrans %}</strong></p>
<dl>
<dt>{% trans 'Node Profile' %}</dt>
<dt>{% trans 'Flavor' %}</dt>
<dd><em>{{ flavor.name }}</em> {{ flavor.get_keys.cpu_arch }} | {{ flavor.vcpus }} {% trans "CPU" %} | {{ flavor.ram }} {% trans "MB RAM" %} | {{ flavor.disk }} {% trans "GB HDD" %}</dd>
<dt>{% trans 'Image' %}</dt>
<dd>{{ image_name }}</dd>

View File

@ -172,7 +172,7 @@ class OvercloudRoleView(horizon_tables.DataTableView,
try:
context['flavor'] = nova.flavor_get(self.request, role.flavor_id)
except Exception:
msg = _('Unable to retrieve node profile.')
msg = _('Unable to retrieve flavor.')
horizon.exceptions.handle(self.request, msg)
return context

View File

@ -29,7 +29,7 @@ class Step(undeployed_overview.Step):
template_name = 'infrastructure/overcloud/scale_node_counts.html'
def prepare_action_context(self, request, context):
for (role_id, profile_id), count in context['role_counts'].items():
name = 'count__%s__%s' % (role_id, profile_id)
for (role_id, flavor_id), count in context['role_counts'].items():
name = 'count__%s__%s' % (role_id, flavor_id)
context[name] = count
return context

View File

@ -22,17 +22,17 @@ from tuskar_ui import api
import tuskar_ui.forms
def get_role_id_and_profile_id_from_field_name(field_name):
"""Extract the ids of overcloud role and node profile from the field
def get_role_id_and_flavor_id_from_field_name(field_name):
"""Extract the ids of overcloud role and flavor from the field
name.
"""
_count, role_id, profile_id = field_name.split('__', 2)
return role_id, profile_id
_count, role_id, flavor_id = field_name.split('__', 2)
return role_id, flavor_id
def get_field_name_from_role_id_and_profile_id(role_id, profile_id=''):
"""Compose the ids of overcloud role and node profile into a field name."""
return 'count__%s__%s' % (role_id, profile_id)
def get_field_name_from_role_id_and_flavor_id(role_id, flavor_id=''):
"""Compose the ids of overcloud role and flavor into a field name."""
return 'count__%s__%s' % (role_id, flavor_id)
class Action(horizon.workflows.Action):
@ -40,7 +40,7 @@ class Action(horizon.workflows.Action):
slug = 'undeployed_overview'
name = _("Overview")
def _get_profile_names(self):
def _get_flavor_names(self):
# Get all flavors in one call, instead of getting them one by one.
try:
flavors = horizon_api.nova.flavor_list(self.request, None)
@ -50,21 +50,21 @@ class Action(horizon.workflows.Action):
flavors = []
return dict((str(flavor.id), flavor.name) for flavor in flavors)
def _get_profiles(self, role, profile_names):
# TODO(rdopieralski) Get a list of hardware profiles for each
# role here, when we support multiple profiles per role.
if role.flavor_id and role.flavor_id in profile_names:
profiles = [(
def _get_flavors(self, role, flavor_names):
# TODO(rdopieralski) Get a list of flavors for each
# role here, when we support multiple flavors per role.
if role.flavor_id and role.flavor_id in flavor_names:
flavors = [(
role.flavor_id,
profile_names[role.flavor_id],
flavor_names[role.flavor_id],
)]
else:
profiles = []
return profiles
flavors = []
return flavors
def __init__(self, *args, **kwargs):
super(Action, self).__init__(*args, **kwargs)
profile_names = self._get_profile_names()
flavor_names = self._get_flavor_names()
for role in self._get_roles():
if role.name == 'Controller':
initial = 1
@ -72,16 +72,16 @@ class Action(horizon.workflows.Action):
else:
initial = 0
attrs = {}
profiles = self._get_profiles(role, profile_names)
if not profiles:
name = get_field_name_from_role_id_and_profile_id(str(role.id))
flavors = self._get_flavors(role, flavor_names)
if not flavors:
name = get_field_name_from_role_id_and_flavor_id(str(role.id))
attrs = {'readonly': 'readonly'}
self.fields[name] = django.forms.IntegerField(
label='', initial=initial, min_value=initial,
widget=tuskar_ui.forms.NumberPickerInput(attrs=attrs))
for profile_id, label in profiles:
name = get_field_name_from_role_id_and_profile_id(
str(role.id), profile_id)
for flavor_id, label in flavors:
name = get_field_name_from_role_id_and_flavor_id(
str(role.id), flavor_id)
self.fields[name] = django.forms.IntegerField(
label=label, initial=initial, min_value=initial,
widget=tuskar_ui.forms.NumberPickerInput(attrs=attrs))
@ -93,7 +93,7 @@ class Action(horizon.workflows.Action):
role.id,
role.name,
list(tuskar_ui.forms.fieldset(
self, prefix=get_field_name_from_role_id_and_profile_id(
self, prefix=get_field_name_from_role_id_and_flavor_id(
str(role.id)))),
)
@ -106,10 +106,10 @@ class Action(horizon.workflows.Action):
for key, value in self.cleaned_data.iteritems():
if not key.startswith('count_'):
continue
role_id, profile = get_role_id_and_profile_id_from_field_name(key)
if int(value) and not profile:
role_id, flavor = get_role_id_and_flavor_id_from_field_name(key)
if int(value) and not flavor:
raise django.forms.ValidationError(
_("Can't deploy nodes without a node profile assigned."))
_("Can't deploy nodes without a flavor assigned."))
return self.cleaned_data
@ -128,7 +128,7 @@ class Step(horizon.workflows.Step):
for key, value in data.iteritems():
if not key.startswith('count_'):
continue
count, role_id, profile = key.split('__', 2)
counts[role_id, profile] = int(value)
count, role_id, flavor = key.split('__', 2)
counts[role_id, flavor] = int(value)
context['role_counts'] = counts
return context

View File

@ -421,8 +421,8 @@ def data(TEST):
'name': 'Block Storage Image'})
TEST.glanceclient_images.add(image_1, image_2, image_3, image_4)
# Nova flavors aka node profiles
# Do not include fields irrelevant for node profiles
# Nova flavors
# Do not include fields irrelevant for our usage
TEST.novaclient_flavors = test_data_utils.TestDataContainer()
flavor_1 = flavors.Flavor(
flavors.FlavorManager(None),