diff --git a/starlingx-dashboard/starlingx-dashboard/starlingx_dashboard/api/sysinv.py b/starlingx-dashboard/starlingx-dashboard/starlingx_dashboard/api/sysinv.py
index e3ff35fa..9831c874 100644
--- a/starlingx-dashboard/starlingx-dashboard/starlingx_dashboard/api/sysinv.py
+++ b/starlingx-dashboard/starlingx-dashboard/starlingx_dashboard/api/sysinv.py
@@ -850,7 +850,7 @@ class Host(base.APIResourceWrapper):
'requires_reboot', 'boot_device', 'rootfs_device',
'install_output', 'console', 'ttys_dcd', 'patch_state',
'allow_insvc_patching', 'install_state', 'install_state_info',
- 'clock_synchronization']
+ 'clock_synchronization', 'max_cpu_frequency', 'max_cpu_default']
PERSONALITY_DISPLAY_CHOICES = (
(PERSONALITY_CONTROLLER, _("Controller")),
diff --git a/starlingx-dashboard/starlingx-dashboard/starlingx_dashboard/dashboards/admin/inventory/templates/inventory/_create.html b/starlingx-dashboard/starlingx-dashboard/starlingx_dashboard/dashboards/admin/inventory/templates/inventory/_create.html
index aa2970c5..607c12ff 100644
--- a/starlingx-dashboard/starlingx-dashboard/starlingx_dashboard/dashboards/admin/inventory/templates/inventory/_create.html
+++ b/starlingx-dashboard/starlingx-dashboard/starlingx_dashboard/dashboards/admin/inventory/templates/inventory/_create.html
@@ -1,4 +1,4 @@
- {% extends "horizon/common/_modal_form.html" %}
+{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block form_id %}create_host_form{% endblock %}
diff --git a/starlingx-dashboard/starlingx-dashboard/starlingx_dashboard/dashboards/admin/inventory/templates/inventory/_detail_cpufunctions.html b/starlingx-dashboard/starlingx-dashboard/starlingx_dashboard/dashboards/admin/inventory/templates/inventory/_detail_cpufunctions.html
index ff270ac5..955d4a78 100644
--- a/starlingx-dashboard/starlingx-dashboard/starlingx_dashboard/dashboards/admin/inventory/templates/inventory/_detail_cpufunctions.html
+++ b/starlingx-dashboard/starlingx-dashboard/starlingx_dashboard/dashboards/admin/inventory/templates/inventory/_detail_cpufunctions.html
@@ -11,6 +11,12 @@
{{ host.physical_cores|get_value:0 }}
{% trans "Hyper-Threading " %}
{{ host.hyperthreading }}
+ {% if host.personality == 'Worker' %}
+ {% trans "Max CPU Frequency " %}
+ {{ host.max_cpu_frequency }}
+ {% trans "Max CPU Default " %}
+ {{ host.max_cpu_default }}
+ {% endif %}
{{ cpufunctions_table.render }}
diff --git a/starlingx-dashboard/starlingx-dashboard/starlingx_dashboard/dashboards/admin/inventory/views.py b/starlingx-dashboard/starlingx-dashboard/starlingx_dashboard/dashboards/admin/inventory/views.py
index 4f4139ba..c1656fa1 100644
--- a/starlingx-dashboard/starlingx-dashboard/starlingx_dashboard/dashboards/admin/inventory/views.py
+++ b/starlingx-dashboard/starlingx-dashboard/starlingx_dashboard/dashboards/admin/inventory/views.py
@@ -80,7 +80,8 @@ class UpdateView(workflows.WorkflowView):
'bm_ip': host.bm_ip,
'bm_username': host.bm_username,
'ttys_dcd': host.ttys_dcd,
- 'clock_synchronization': host.clock_synchronization}
+ 'clock_synchronization': host.clock_synchronization,
+ 'max_cpu_frequency': host.max_cpu_frequency}
class DetailView(tabs.TabbedTableView):
diff --git a/starlingx-dashboard/starlingx-dashboard/starlingx_dashboard/dashboards/admin/inventory/workflows.py b/starlingx-dashboard/starlingx-dashboard/starlingx_dashboard/dashboards/admin/inventory/workflows.py
index 3460e93f..77379ebf 100644
--- a/starlingx-dashboard/starlingx-dashboard/starlingx_dashboard/dashboards/admin/inventory/workflows.py
+++ b/starlingx-dashboard/starlingx-dashboard/starlingx_dashboard/dashboards/admin/inventory/workflows.py
@@ -55,6 +55,11 @@ BM_TYPES_CHOICES = (
(sysinv.HOST_BM_TYPE_REDFISH, _("Redfish")),
)
+MAX_CPU_FREQUENCY_CHOICES = (
+ ('max_cpu_default', _("Default")),
+ ('custom', _("Custom")),
+)
+
class AddHostInfoAction(workflows.Action):
FIELD_LABEL_PERSONALITY = _("Personality")
@@ -170,6 +175,32 @@ class UpdateHostInfoAction(workflows.Action):
stx_api.sysinv.PERSONALITY_WORKER:
_("Host Name")}))
+ cpu_freq_config = forms.ChoiceField(
+ label=_("CPU Frequency Configuration"),
+ required=True,
+ initial='max_cpu_default',
+ choices=MAX_CPU_FREQUENCY_CHOICES,
+ widget=forms.Select(
+ attrs={
+ 'class': 'switchable switched',
+ 'data-switch-on': 'personality',
+ 'data-personality-' + stx_api.sysinv.PERSONALITY_WORKER:
+ _("CPU Frequency Configuration"),
+ 'data-slug': 'cpu_freq_config'}))
+
+ max_cpu_frequency = forms.IntegerField(
+ label=_("Max CPU Frequency (MHz)"),
+ initial=1,
+ min_value=1,
+ required=True,
+ widget=forms.TextInput(
+ attrs={
+ 'class': 'switched',
+ 'data-switch-on': 'cpu_freq_config',
+ 'data-cpu_freq_config-custom':
+ 'Max CPU Frequency (MHz)'}),
+ help_text='Host CPU Cores maximum frequency.')
+
location = forms.CharField(label=_("Location"),
initial='location',
required=False,
@@ -198,6 +229,9 @@ class UpdateHostInfoAction(workflows.Action):
def __init__(self, request, *args, **kwargs):
super(UpdateHostInfoAction, self).__init__(request, *args, **kwargs)
+ host_id = self.initial['host_id']
+ host = stx_api.sysinv.host_get(request, host_id)
+
# pesonality cannot be storage if ceph is not configured
storage_backend = stx_api.sysinv.get_storage_backend(request)
if stx_api.sysinv.STORAGE_BACKEND_CEPH not in storage_backend:
@@ -222,6 +256,17 @@ class UpdateHostInfoAction(workflows.Action):
self.fields['subfunctions'].widget.attrs['readonly'] = 'readonly'
self.fields['subfunctions'].required = False
+ if (host._capabilities.get(
+ 'max_cpu_config') in [None, 'not-configurable'] or
+ sysinv_const.CONTROLLER in host.subfunctions):
+ self.fields['cpu_freq_config'].widget.attrs['readonly'] = \
+ 'readonly'
+ self.fields['cpu_freq_config'].required = False
+
+ if (self.initial['max_cpu_frequency'] is not None and
+ self.initial['max_cpu_frequency'] != host.max_cpu_default):
+ self.fields['cpu_freq_config'].initial = 'custom'
+
def clean_location(self):
try:
host_id = self.cleaned_data['host_id']
@@ -236,6 +281,10 @@ class UpdateHostInfoAction(workflows.Action):
def clean(self):
cleaned_data = super(UpdateHostInfoAction, self).clean()
+
+ if cleaned_data['cpu_freq_config'] == 'max_cpu_default':
+ cleaned_data['max_cpu_frequency'] = 'max_cpu_default'
+
disabled = self.fields['personality'].widget.attrs.get('disabled')
if disabled == 'disabled':
if self.system_type == constants.TS_AIO:
@@ -256,6 +305,23 @@ class UpdateHostInfoAction(workflows.Action):
return cleaned_data
+ def handle(self, request, data):
+ host_id = self.initial['host_id']
+ try:
+ max_cpu_frequency = data['max_cpu_frequency']
+ patch = {'max_cpu_frequency': max_cpu_frequency}
+ stx_api.sysinv.host_update(request, host_id, **patch)
+ except exc.ClientException as ce:
+ LOG.error(ce)
+ msg = self.failure_message + " " + str(ce)
+ self.failure_message = msg
+ exceptions.handle(request, msg)
+ return False
+ except Exception as e:
+ msg = str(e)
+ exceptions.handle(request, msg)
+ return False
+
class AddHostInfo(workflows.Step):
action_class = AddHostInfoAction
@@ -273,7 +339,8 @@ class UpdateHostInfo(workflows.Step):
"hostname",
"location",
"ttys_dcd",
- "clock_synchronization")
+ "clock_synchronization",
+ "max_cpu_frequency")
class UpdateInstallParamsAction(workflows.Action):