diff --git a/starlingx_dashboard/api/sysinv.py b/starlingx_dashboard/api/sysinv.py index be00e1ef..97971409 100755 --- a/starlingx_dashboard/api/sysinv.py +++ b/starlingx_dashboard/api/sysinv.py @@ -1153,7 +1153,7 @@ def dns_list(request): class NTP(base.APIResourceWrapper): """...""" - _attrs = ['isystem_uuid', 'ntpservers', 'uuid', 'link'] + _attrs = ['isystem_uuid', 'enabled', 'ntpservers', 'uuid', 'link'] def __init__(self, apiresource): super(NTP, self).__init__(apiresource) @@ -1188,6 +1188,43 @@ def ntp_list(request): return [NTP(n) for n in ntp] +class PTP(base.APIResourceWrapper): + """...""" + + _attrs = ['isystem_uuid', 'enabled', 'mode', + 'transport', 'mechanism', 'uuid', 'link'] + + def __init__(self, apiresource): + super(PTP, self).__init__(apiresource) + + +def ptp_update(request, ptp_id, **kwargs): + LOG.debug("ptp_update(): ptp_id=%s, kwargs=%s", ptp_id, kwargs) + mypatch = [] + + for key, value in kwargs.iteritems(): + mypatch.append(dict(path='/' + key, value=value, op='replace')) + + return cgtsclient(request).ptp.update(ptp_id, mypatch) + + +def ptp_delete(request, ptp_id): + LOG.debug("ptp_delete(): ptp_id=%s", ptp_id) + return cgtsclient(request).ptp.delete(ptp_id) + + +def ptp_get(request, ptp_id): + ptp = cgtsclient(request).ptp.get(ptp_id) + if not ptp: + raise ValueError('No match found for ptp_id "%s".' % ptp_id) + return PTP(ptp) + + +def ptp_list(request): + ptp = cgtsclient(request).ptp.list() + return [PTP(n) for n in ptp] + + class EXTOAM(base.APIResourceWrapper): """...""" diff --git a/starlingx_dashboard/dashboards/admin/system_config/forms.py b/starlingx_dashboard/dashboards/admin/system_config/forms.py index 61fc48e1..1e5b5b9e 100755 --- a/starlingx_dashboard/dashboards/admin/system_config/forms.py +++ b/starlingx_dashboard/dashboards/admin/system_config/forms.py @@ -219,6 +219,10 @@ class UpdatecDNS(forms.SelfHandlingForm): class UpdatecNTP(forms.SelfHandlingForm): uuid = forms.CharField(widget=forms.widgets.HiddenInput) + enabled = forms.BooleanField( + label=_("Enabled"), + help_text=_('Enable NTP service.'), + required=False) NTP_SERVER_1 = forms.CharField(label=_("NTP Server 1 Address"), initial='NTP_SERVER_1', @@ -262,6 +266,12 @@ class UpdatecNTP(forms.SelfHandlingForm): else: data['uuid'] = ' ' + if 'enabled' in data.keys(): + if not data['enabled']: + data['enabled'] = 'False' + else: + data['enabled'] = 'False' + for index in range(1, max_ntp_servers + 1): if data['NTP_SERVER_%s' % index] and data[ 'NTP_SERVER_%s' % index] != ' ': @@ -273,28 +283,32 @@ class UpdatecNTP(forms.SelfHandlingForm): if hasattr(ntp_config, 'uuid'): ntp_config_uuid = ntp_config.uuid + ntp_enabled = ntp_config.enabled if ntp_config.ntpservers: ntpservers = ntp_config.ntpservers.split(',') else: ntpservers = [] - # if their sizes are different, then action=apply - if len(NTPSERVERS) != len(ntpservers): + if ntp_enabled != data['enabled']: data['action'] = 'apply' + data['enabled'] = str(data['enabled']) send_to_sysinv = True - else: - # If lengths are same, - # check if order of values have been changed - if set(ntpservers) != set(NTPSERVERS.values()): - for index in range(len(ntpservers)): - - if ntpservers[index] != NTPSERVERS[ - 'NTP_SERVER_%s' % (index + 1)]: - data['action'] = 'apply' - send_to_sysinv = True - # we need to do action=apply only once - break + # if their sizes are different, then action=apply + if len(NTPSERVERS) != len(ntpservers): + data['action'] = 'apply' + send_to_sysinv = True + else: + # If lengths are same, + # check if order of values have been changed + if set(ntpservers) != set(NTPSERVERS.values()): + for index in range(len(ntpservers)): + if ntpservers[index] != NTPSERVERS[ + 'NTP_SERVER_%s' % (index + 1)]: + data['action'] = 'apply' + send_to_sysinv = True + # we need to do action=apply only once + break # sysinv accepts csv values as the ntpservers data['ntpservers'] = ','.join(NTPSERVERS.values()) @@ -309,7 +323,7 @@ class UpdatecNTP(forms.SelfHandlingForm): else: ntp_config_uuid = ' ' - data = {'ntpservers': ''} + data = {'enabled': 'False', 'ntpservers': ''} LOG.debug(data) @@ -326,7 +340,7 @@ class UpdatecNTP(forms.SelfHandlingForm): return False else: - msg = _('No NTP Server changes have been made.') + msg = _('No NTP configuration changes have been made.') LOG.debug(msg) messages.info(request, msg) return True @@ -346,6 +360,141 @@ class UpdatecNTP(forms.SelfHandlingForm): return False +class UpdatecPTP(forms.SelfHandlingForm): + uuid = forms.CharField(widget=forms.widgets.HiddenInput) + enabled = forms.BooleanField( + label=_("Enabled"), + help_text=_('Enable PTP service.'), + required=False) + + PTP_MODE_CHOICES = ( + ('hardware', _('Hardware time stamping')), + ('software', _('Software time stamping')), + ('legacy', _('Legacy hardware time stamping')), + ) + mode = forms.ChoiceField(label=_("PTP Time Stamping Mode"), + required=False, + choices=PTP_MODE_CHOICES) + + PTP_TRANSPORT_CHOICES = ( + ('l2', _('IEEE 802.3 network transport (L2)')), + ('udp', _('UDP IPv4/v6 network transport(UDP)')), + ) + transport = forms.ChoiceField(label=_("PTP Network Transport"), + required=False, + choices=PTP_TRANSPORT_CHOICES) + + PTP_MECHANISM_CHOICES = ( + ('e2e', _('Delay request-response (E2E)')), + ('p2p', _('Peer delay (P2P)')), + ) + mechanism = forms.ChoiceField(label=_("PTP Delay Mechanism"), + required=False, + choices=PTP_MECHANISM_CHOICES) + + failure_url = 'horizon:admin:system_config:index' + failure_message = 'Failed to update PTP configurations.' + + def __init__(self, request, *args, **kwargs): + super(UpdatecPTP, self).__init__(request, *args, **kwargs) + + def handle(self, request, data): + send_to_sysinv = False + + try: + if data: + if 'uuid' in data.keys(): + if not data['uuid']: + data['uuid'] = ' ' + else: + data['uuid'] = ' ' + + if 'enabled' in data.keys(): + if not data['enabled']: + data['enabled'] = 'False' + else: + data['enabled'] = 'False' + + if 'mode' in data.keys(): + if not data['mode']: + data['mode'] = 'hardware' + else: + data['mode'] = 'False' + + if 'transport' in data.keys(): + if not data['transport']: + data['transport'] = 'l2' + else: + data['transport'] = 'l2' + + if 'mechanism' in data.keys(): + if not data['mechanism']: + data['mechanism'] = 'e2e' + else: + data['mechanism'] = 'e2e' + + ptp_config = stx_api.sysinv.ptp_get(request, data['uuid']) + + if hasattr(ptp_config, 'uuid'): + ptp_config_uuid = ptp_config.uuid + ptp_enabled = ptp_config.enabled + if ptp_enabled != data['enabled']: + data['enabled'] = str(data['enabled']) + send_to_sysinv = True + if ptp_config.mode != data['mode']: + send_to_sysinv = True + if ptp_config.transport != data['transport']: + send_to_sysinv = True + if ptp_config.mechanism != data['mechanism']: + send_to_sysinv = True + + else: + ptp_config_uuid = ' ' + + data.pop('uuid') + + else: + ptp_config_uuid = ' ' + data = {'enabled': 'False', + 'mode': '', + 'transport': '', + 'mechanism': ''} + + LOG.debug(data) + + if send_to_sysinv: + my_ptp = \ + stx_api.sysinv.ptp_update(request, ptp_config_uuid, **data) + + if my_ptp: + msg = _('PTP configuration was successfully updated. ') + LOG.debug(msg) + messages.success(request, msg) + return True + else: + return False + + else: + msg = _('No PTP configuratiom changes have been made.') + LOG.debug(msg) + messages.info(request, msg) + return True + + except exc.ClientException as ce: + messages.error(request, ce) + # Display REST API error on the GUI + LOG.error(ce) + # redirect = reverse(self.failure_url) + return False + + except Exception: + msg = _('Failed to update PTP configuration.') + messages.error(request, msg) + LOG.info(msg) + # redirect = reverse(self.failure_url) + return False + + class UpdatecEXT_OAM(forms.SelfHandlingForm): uuid = forms.CharField(widget=forms.widgets.HiddenInput) diff --git a/starlingx_dashboard/dashboards/admin/system_config/tables.py b/starlingx_dashboard/dashboards/admin/system_config/tables.py index 86c54215..f2a846b2 100644 --- a/starlingx_dashboard/dashboards/admin/system_config/tables.py +++ b/starlingx_dashboard/dashboards/admin/system_config/tables.py @@ -89,6 +89,13 @@ class EditcNTP(tables.LinkAction): classes = ("ajax-modal", "btn-edit") +class EditcPTP(tables.LinkAction): + name = "update_cptp" + verbose_name = _("Edit PTP") + url = "horizon:admin:system_config:update_cptp_table" + classes = ("ajax-modal", "btn-edit") + + class EditcOAM(tables.LinkAction): name = "update_coam" verbose_name = _("Edit OAM IP") @@ -156,6 +163,10 @@ class UpdateNTPRow(tables.Row): class cNTPTable(tables.DataTable): + enabled = tables.Column( + 'enabled', + verbose_name=_('NTP Enabled')) + ntpserver_1 = tables.Column( 'ntpserver_1', # link="horizon:admin:system_config:detail_cdns", @@ -185,6 +196,44 @@ class cNTPTable(tables.DataTable): table_actions = (EditcNTP,) +class UpdatePTPRow(tables.Row): + ajax = True + + def get_data(self, request, obj_id): + return stx_api.sysinv.ptp_get(request, obj_id) + + +class cPTPTable(tables.DataTable): + enabled = tables.Column( + 'enabled', + verbose_name=_('PTP Enabled')) + + mode = tables.Column( + 'mode', + verbose_name=_('PTP Time Stamping Mode')) + + transport = tables.Column( + 'transport', + verbose_name=_('PTP Network Transport')) + + mechanism = tables.Column( + 'mechanism', + verbose_name=_('PTP Delay Mechanism')) + + def get_object_id(self, datum): + return unicode(datum.uuid) + + def get_object_display(self, datum): + return datum.uuid + + class Meta(object): + name = "cptp_table" + verbose_name = _("PTP") + row_class = UpdatePTPRow + multi_select = False + table_actions = (EditcPTP,) + + class UpdateOAMRow(tables.Row): ajax = True diff --git a/starlingx_dashboard/dashboards/admin/system_config/tabs.py b/starlingx_dashboard/dashboards/admin/system_config/tabs.py index 02884254..1e1078a8 100755 --- a/starlingx_dashboard/dashboards/admin/system_config/tabs.py +++ b/starlingx_dashboard/dashboards/admin/system_config/tabs.py @@ -105,6 +105,7 @@ class cNTPTab(tabs.TableTab): try: ntp_data = {'uuid': ' ', + 'enabled': False, 'ntpserver_1': ' ', 'ntpserver_2': ' ', 'ntpserver_3': ' '} @@ -114,6 +115,7 @@ class cNTPTab(tabs.TableTab): ntp = ntp_list[0] ntp_data['uuid'] = ntp.uuid + ntp_data['enabled'] = ntp.enabled if ntp.ntpservers: servers = ntp.ntpservers.split(",") for index, server in enumerate(servers): @@ -128,6 +130,42 @@ class cNTPTab(tabs.TableTab): return data +class cPTPTab(tabs.TableTab): + table_classes = (toplevel_tables.cPTPTable, ) + name = _("PTP") + slug = "cptp_table" + template_name = ("admin/system_config/_cptp_table.html") + + def get_cptp_table_data(self): + request = self.request + data = [] + + try: + ptp_data = {'uuid': ' ', + 'enabled': False, + 'mode': ' ', + 'transport': ' ', + 'mechanism': ' '} + + ptp_list = stx_api.sysinv.ptp_list(request) + if ptp_list: + ptp = ptp_list[0] + + ptp_data['uuid'] = ptp.uuid + ptp_data['enabled'] = ptp.enabled + ptp_data['mode'] = ptp.mode + ptp_data['transport'] = ptp.transport + ptp_data['mechanism'] = ptp.mechanism + + data.append(type('PTP', (object,), ptp_data)()) + + except Exception: + exceptions.handle(request, + _('Unable to retrieve ptp list.')) + + return data + + class cEXTOAMTab(tabs.TableTab): table_classes = (toplevel_tables.cOAMTable, ) name = _("OAM IP") @@ -251,7 +289,7 @@ class CeilometerConfigTab(tabs.TableTab): class ConfigTabs(tabs.TabGroup): slug = "system_config_tab" - tabs = (SystemsTab, AddressPoolsTab, cDNSTab, cNTPTab, cEXTOAMTab, - iStorageTab, iStoragePoolsTab, SDNControllerTab, + tabs = (SystemsTab, AddressPoolsTab, cDNSTab, cNTPTab, cPTPTab, + cEXTOAMTab, iStorageTab, iStoragePoolsTab, SDNControllerTab, CeilometerConfigTab) sticky = True diff --git a/starlingx_dashboard/dashboards/admin/system_config/templates/system_config/_cptp_table.html b/starlingx_dashboard/dashboards/admin/system_config/templates/system_config/_cptp_table.html new file mode 100644 index 00000000..acbfd87e --- /dev/null +++ b/starlingx_dashboard/dashboards/admin/system_config/templates/system_config/_cptp_table.html @@ -0,0 +1,7 @@ +{% load i18n sizeformat %} + +{% block main %} +
+ {{ cptp_table_table.render }} +
+{% endblock %} diff --git a/starlingx_dashboard/dashboards/admin/system_config/templates/system_config/_update_cntp_table.html b/starlingx_dashboard/dashboards/admin/system_config/templates/system_config/_update_cntp_table.html index c0823497..1f2ddc87 100755 --- a/starlingx_dashboard/dashboards/admin/system_config/templates/system_config/_update_cntp_table.html +++ b/starlingx_dashboard/dashboards/admin/system_config/templates/system_config/_update_cntp_table.html @@ -15,7 +15,7 @@

{% trans "Description" %}:

-

{% trans "From here you can update the configuration of the NTP servers." %}

+

{% trans "From here you can update the configuration of the NTP service." %}

{% trans "WARNING: Completion of NTP configuration change will require lock and unlock of affected hosts." %}

{% trans "Major Alarms will be raised against the affected hosts until the lock unlock operation is successfully completed." %}

diff --git a/starlingx_dashboard/dashboards/admin/system_config/templates/system_config/_update_cptp_table.html b/starlingx_dashboard/dashboards/admin/system_config/templates/system_config/_update_cptp_table.html new file mode 100644 index 00000000..3dcd6013 --- /dev/null +++ b/starlingx_dashboard/dashboards/admin/system_config/templates/system_config/_update_cptp_table.html @@ -0,0 +1,30 @@ +{% extends "horizon/common/_modal_form.html" %} +{% load i18n %} + +{% block form_id %}edit_iconfig_form{% endblock %} +{% block form_action %}{% url 'horizon:admin:system_config:update_cptp_table' %}{% endblock %} + +{% block modal_id %}edit_iconfig_modal{% endblock %} +{% block modal-header %}{% trans "Edit PTP" %}{% endblock %} + +{% block modal-body %} +
+
+ {% include "horizon/common/_form_fields.html" %} +
+
+
+

{% trans "Description" %}:

+

{% trans "From here you can update the configuration of the PTP service." %}

+

{% trans "WARNING: Completion of PTP configuration change will require lock and unlock of affected hosts." %}

+

{% trans "Major Alarms will be raised against the affected hosts until the lock unlock operation is successfully completed." %}

+
+{% endblock %} + +{% block modal-footer %} + {% trans "Cancel" %} + +{% endblock %} diff --git a/starlingx_dashboard/dashboards/admin/system_config/templates/system_config/update_cptp_table.html b/starlingx_dashboard/dashboards/admin/system_config/templates/system_config/update_cptp_table.html new file mode 100644 index 00000000..46ff1e79 --- /dev/null +++ b/starlingx_dashboard/dashboards/admin/system_config/templates/system_config/update_cptp_table.html @@ -0,0 +1,11 @@ +{% extends 'base.html' %} +{% load i18n %} +{% block title %}{% trans "Edit PTP" %}{% endblock %} + +{% block page_header %} + {% include "horizon/common/_page_header.html" with title=_("Edit PTP") %} +{% endblock page_header %} + +{% block main %} + {% include "admin/system_config/_update_cptp_table.html" %} +{% endblock %} diff --git a/starlingx_dashboard/dashboards/admin/system_config/urls.py b/starlingx_dashboard/dashboards/admin/system_config/urls.py index 585ffc0c..de97b07e 100755 --- a/starlingx_dashboard/dashboards/admin/system_config/urls.py +++ b/starlingx_dashboard/dashboards/admin/system_config/urls.py @@ -20,6 +20,8 @@ from starlingx_dashboard.dashboards.admin.system_config.views \ import UpdatecEXT_OAMView from starlingx_dashboard.dashboards.admin.system_config.views \ import UpdatecNTPView +from starlingx_dashboard.dashboards.admin.system_config.views \ + import UpdatecPTPView from starlingx_dashboard.dashboards.admin.system_config.views import \ UpdateiStoragePoolsView from starlingx_dashboard.dashboards.admin.system_config.views import \ @@ -51,6 +53,8 @@ urlpatterns = [ name='update_cdns_table'), url(r'^update_cntp_table/$', UpdatecNTPView.as_view(), name='update_cntp_table'), + url(r'^update_cptp_table/$', UpdatecPTPView.as_view(), + name='update_cptp_table'), url(r'^update_coam_table/$', UpdatecEXT_OAMView.as_view(), name='update_coam_table'), diff --git a/starlingx_dashboard/dashboards/admin/system_config/views.py b/starlingx_dashboard/dashboards/admin/system_config/views.py index 13ea338d..78b7773a 100755 --- a/starlingx_dashboard/dashboards/admin/system_config/views.py +++ b/starlingx_dashboard/dashboards/admin/system_config/views.py @@ -28,6 +28,8 @@ from starlingx_dashboard.dashboards.admin.system_config.forms \ import UpdatecEXT_OAM from starlingx_dashboard.dashboards.admin.system_config.forms \ import UpdatecNTP +from starlingx_dashboard.dashboards.admin.system_config.forms \ + import UpdatecPTP from starlingx_dashboard.dashboards.admin.system_config.forms \ import UpdateiStorage from starlingx_dashboard.dashboards.admin.system_config.forms \ @@ -149,6 +151,7 @@ class UpdatecNTPView(forms.ModalFormView): def get_initial(self): ntp_form_data = {'uuid': ' ', + 'enabled': False, 'NTP_SERVER_1': None, 'NTP_SERVER_2': None, 'NTP_SERVER_3': None} @@ -160,6 +163,7 @@ class UpdatecNTPView(forms.ModalFormView): ntp = ntp_list[0] ntp_form_data['uuid'] = ntp.uuid + ntp_form_data['enabled'] = ntp.enabled if ntp.ntpservers: servers = ntp.ntpservers.split(",") for index, server in enumerate(servers): @@ -172,6 +176,53 @@ class UpdatecNTPView(forms.ModalFormView): return ntp_form_data +class UpdatecPTPView(forms.ModalFormView): + form_class = UpdatecPTP + template_name = 'admin/system_config/update_cptp_table.html' + success_url = reverse_lazy('horizon:admin:system_config:index') + + def get_context_data(self, **kwargs): + context = super(UpdatecPTPView, self).get_context_data(**kwargs) + ptp_list = stx_api.sysinv.ptp_list(self.request) + + if ptp_list: + if "uuid" in ptp_list[0]._attrs: + uuid = ptp_list[0].uuid + + else: + uuid = " " + + else: + uuid = " " + + context['uuid'] = uuid + return context + + def get_initial(self): + ptp_form_data = {'uuid': ' ', + 'enabled': False, + 'mode': None, + 'transport': None, + 'mechanism': None} + + try: + ptp_list = stx_api.sysinv.ptp_list(self.request) + + if ptp_list: + ptp = ptp_list[0] + ptp_form_data['uuid'] = ptp.uuid + ptp_form_data['enabled'] = ptp.enabled + ptp_form_data['mode'] = ptp.mode + ptp_form_data['transport'] = ptp.transport + ptp_form_data['mechanism'] = ptp.mechanism + + except Exception: + exceptions.handle(self.request, + _("Unable to retrieve PTP data.")) + + return ptp_form_data + + class UpdatecEXT_OAMView(forms.ModalFormView): form_class = UpdatecEXT_OAM template_name = 'admin/system_config/update_coam_table.html'