Merge "Create a new Filesystems tab for hosts"
This commit is contained in:
commit
6f0db62cd0
|
@ -1593,6 +1593,14 @@ class ControllerFS(base.APIResourceWrapper):
|
|||
return self._replicated
|
||||
|
||||
|
||||
class HostFilesystem(base.APIResourceWrapper):
|
||||
_attrs = ['uuid', 'id', 'name', 'size', 'logical_volume', 'forihostid',
|
||||
'ihost_uuid']
|
||||
|
||||
def __init__(self, apiresource):
|
||||
super(HostFilesystem, self).__init__(apiresource)
|
||||
|
||||
|
||||
class CephMon(base.APIResourceWrapper):
|
||||
"""..."""
|
||||
_attrs = ['device_path', 'ceph_mon_gib', 'hostname',
|
||||
|
@ -1837,6 +1845,24 @@ def get_cinder_backend(request):
|
|||
return cinder_backends
|
||||
|
||||
|
||||
def host_filesystems_list(request, host_id):
|
||||
filesystems = cgtsclient(request).host_fs.list(host_id)
|
||||
return [HostFilesystem(n) for n in filesystems]
|
||||
|
||||
|
||||
def host_filesystems_update(request, host_id, **kwargs):
|
||||
patch_list = []
|
||||
|
||||
for key, value in kwargs.items():
|
||||
patch = []
|
||||
patch.append({'op': 'replace', 'path': '/name', 'value': key})
|
||||
patch.append({'op': 'replace', 'path': '/size', 'value': value})
|
||||
patch_list.append(patch)
|
||||
|
||||
LOG.info("host_filesystems_update patch_list=%s", patch_list)
|
||||
return cgtsclient(request).host_fs.update_many(host_id, patch_list)
|
||||
|
||||
|
||||
def host_node_list(request, host_id):
|
||||
nodes = cgtsclient(request).inode.list(host_id)
|
||||
return [Node(n) for n in nodes]
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
#
|
||||
# Copyright (c) 2019 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
import logging
|
||||
|
||||
from django.core.urlresolvers import reverse # noqa
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
|
||||
from starlingx_dashboard import api as stx_api
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class UpdateFilesystems(forms.SelfHandlingForm):
|
||||
|
||||
host_id = forms.CharField(label=_("host_id"),
|
||||
required=False,
|
||||
widget=forms.widgets.HiddenInput)
|
||||
|
||||
host_uuid = forms.CharField(label=_("host_uuid"),
|
||||
required=False,
|
||||
widget=forms.widgets.HiddenInput)
|
||||
|
||||
backup = forms.IntegerField(
|
||||
label=_("Backup Storage (GiB)"),
|
||||
required=False,
|
||||
help_text=_("Backup storage space in gibibytes."),
|
||||
min_value=0)
|
||||
|
||||
docker = forms.IntegerField(
|
||||
label=_("Docker Storage (GiB)"),
|
||||
required=True,
|
||||
help_text=_("Docker storage space in gibibytes."),
|
||||
min_value=0)
|
||||
|
||||
kubelet = forms.IntegerField(
|
||||
label=_("Kubelet Storage (GiB)"),
|
||||
required=True,
|
||||
help_text=_("Kubelet storage space in gibibytes."),
|
||||
min_value=0)
|
||||
|
||||
scratch = forms.IntegerField(
|
||||
label=_("Scratch Storage (GiB)"),
|
||||
required=True,
|
||||
help_text=_("Scratch storage space in gibibytes."),
|
||||
min_value=0)
|
||||
|
||||
failure_url = 'horizon:admin:inventory:detail'
|
||||
failure_message = 'Failed to update host filesystems configuration.'
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(UpdateFilesystems, self).__init__(request, *args, **kwargs)
|
||||
|
||||
# The backup fs is only used on controller nodes. Removed from form if
|
||||
# its not in the list.
|
||||
if not kwargs['initial'].get('backup'):
|
||||
del self.fields['backup']
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super(UpdateFilesystems, self).clean()
|
||||
return cleaned_data
|
||||
|
||||
def handle(self, request, data):
|
||||
host_uuid = data['host_uuid']
|
||||
data.pop('host_uuid')
|
||||
data.pop('host_id')
|
||||
|
||||
new_data = {k.replace("_", "-"): v for k, v in data.items()}
|
||||
|
||||
try:
|
||||
fs_list = stx_api.sysinv.host_filesystems_list(
|
||||
self.request, host_uuid)
|
||||
|
||||
fs_data = {fs.name: fs.size for fs in fs_list}
|
||||
|
||||
for k, v in fs_data.items():
|
||||
if new_data.get(k, None) == v:
|
||||
del new_data[k]
|
||||
|
||||
if new_data:
|
||||
stx_api.sysinv.host_filesystems_update(request,
|
||||
host_uuid,
|
||||
**new_data)
|
||||
return True
|
||||
except Exception as exc:
|
||||
msg = _('Failed to update host filesystems (%(e)s).') \
|
||||
% ({'e': exc})
|
||||
LOG.info(msg)
|
||||
redirect = reverse(self.failure_url, args=[host_uuid])
|
||||
exceptions.handle(request, msg, redirect=redirect)
|
|
@ -0,0 +1,44 @@
|
|||
#
|
||||
# Copyright (c) 2019 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import logging
|
||||
|
||||
from django.core.urlresolvers import reverse # noqa
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from horizon import tables
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class UpdateFilesystems(tables.LinkAction):
|
||||
name = "updatefilesystems"
|
||||
verbose_name = _("Update Filesystems")
|
||||
url = "horizon:admin:inventory:updatefilesystems"
|
||||
classes = ("ajax-modal", "btn-edit")
|
||||
|
||||
def get_link_url(self, datum=None):
|
||||
host_id = self.table.kwargs['host_id']
|
||||
return reverse(self.url, args=(host_id,))
|
||||
|
||||
def allowed(self, request, datum):
|
||||
return True
|
||||
|
||||
|
||||
class FilesystemsTable(tables.DataTable):
|
||||
name = tables.Column('name', verbose_name=_('Name'))
|
||||
|
||||
size = tables.Column('size', verbose_name=_('Size (GiB)'))
|
||||
|
||||
def get_object_id(self, datum):
|
||||
return str(datum.uuid)
|
||||
|
||||
class Meta(object):
|
||||
name = "filesystems"
|
||||
verbose_name = _("Filesystems")
|
||||
multi_select = False
|
||||
table_actions = (UpdateFilesystems,)
|
|
@ -0,0 +1,76 @@
|
|||
#
|
||||
# Copyright (c) 2019 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
import logging
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
|
||||
from starlingx_dashboard import api as stx_api
|
||||
|
||||
from starlingx_dashboard.dashboards.admin.inventory.filesystems.forms \
|
||||
import UpdateFilesystems
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class UpdateFilesystemsView(forms.ModalFormView):
|
||||
form_class = UpdateFilesystems
|
||||
template_name = 'admin/inventory/filesystems/update_filesystems_table.html'
|
||||
success_url = 'horizon:admin:inventory:detail'
|
||||
failure_url = 'horizon:admin:inventory:detail'
|
||||
context_object_name = "filesystems"
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse(self.success_url,
|
||||
args=(self.kwargs['host_id'],))
|
||||
|
||||
def get_failure_url(self):
|
||||
return reverse(self.failure_url,
|
||||
args=(self.kwargs['host_id'],))
|
||||
|
||||
def _get_object(self, *args, **kwargs):
|
||||
if not hasattr(self, "_object"):
|
||||
host_id = self.kwargs['host_id']
|
||||
|
||||
try:
|
||||
host = stx_api.sysinv.host_get(self.request, host_id)
|
||||
host.filesystems = stx_api.sysinv.host_filesystems_list(
|
||||
self.request, host.uuid)
|
||||
host.nodes = \
|
||||
stx_api.sysinv.host_node_list(self.request, host.uuid)
|
||||
self._object = host
|
||||
self._object.host_id = host_id
|
||||
except Exception as e:
|
||||
LOG.exception(e)
|
||||
redirect = reverse(self.failure_url,
|
||||
args=host_id)
|
||||
msg = _('Unable to retrieve host filesystems details')
|
||||
exceptions.handle(self.request, msg, redirect=redirect)
|
||||
return self._object
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = super(UpdateFilesystemsView, self).get_context_data(**kwargs)
|
||||
host = self._get_object()
|
||||
context['host_id'] = host.host_id
|
||||
|
||||
return context
|
||||
|
||||
def get_initial(self):
|
||||
|
||||
host = self._get_object()
|
||||
fs_form_data = \
|
||||
{fs.name.replace("-", "_"): fs.size for fs in host.filesystems}
|
||||
fs_form_data.update({'host_uuid': host.uuid})
|
||||
fs_form_data.update({'host_id': host.id})
|
||||
|
||||
return fs_form_data
|
|
@ -20,6 +20,8 @@ from starlingx_dashboard.dashboards.admin.inventory.cpu_functions import \
|
|||
tables as cpufunctions_tables
|
||||
from starlingx_dashboard.dashboards.admin.inventory.devices import \
|
||||
tables as device_tables
|
||||
from starlingx_dashboard.dashboards.admin.inventory.filesystems import \
|
||||
tables as filesystems_tables
|
||||
from starlingx_dashboard.dashboards.admin.inventory.interfaces import \
|
||||
tables as interface_tables
|
||||
from starlingx_dashboard.dashboards.admin.inventory.kubernetes_labels import \
|
||||
|
@ -699,8 +701,21 @@ class LabelsTab(tabs.TableTab):
|
|||
return host.labels
|
||||
|
||||
|
||||
class FilesystemsTab(tabs.TableTab):
|
||||
table_classes = (filesystems_tables.FilesystemsTable, )
|
||||
name = _("Filesystems")
|
||||
slug = "filesystems"
|
||||
template_name = ("admin/inventory/_detail_filesystems.html")
|
||||
|
||||
def get_filesystems_data(self):
|
||||
host = self.tab_group.kwargs['host']
|
||||
host.filesystems.sort(key=lambda f: (f.name))
|
||||
return host.filesystems
|
||||
|
||||
|
||||
class HostDetailTabs(tabs.TabGroup):
|
||||
slug = "inventory_details"
|
||||
tabs = (OverviewTab, CpuFunctionsTab, MemorysTab, StorageTab, PortsTab,
|
||||
InterfacesTab, LldpTab, SensorTab, DevicesTab, LabelsTab, )
|
||||
tabs = (OverviewTab, CpuFunctionsTab, MemorysTab, StorageTab,
|
||||
FilesystemsTab, PortsTab, InterfacesTab, LldpTab, SensorTab,
|
||||
DevicesTab, LabelsTab,)
|
||||
sticky = True
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
{% load i18n sizeformat %}
|
||||
|
||||
{% block main %}
|
||||
{% autoescape off %}
|
||||
<div id="filesystems">
|
||||
{{ filesystems_table.render }}
|
||||
</div>
|
||||
{% endautoescape %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,32 @@
|
|||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block form_id %}edit_iconfig_form{% endblock %}
|
||||
{% block form_action %}{% url 'horizon:admin:inventory:updatefilesystems' host_id %}{% endblock %}
|
||||
|
||||
{% block modal_id %}edit_iconfig_modal{% endblock %}
|
||||
{% block modal-header %}{% trans "Edit Filesystems" %}{% endblock %}
|
||||
|
||||
{% block modal-body %}
|
||||
<div class="left">
|
||||
<fieldset>
|
||||
{% include "horizon/common/_form_fields.html" %}
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<div class="right">
|
||||
<h3>{% trans "Description" %}:</h3>
|
||||
<p>{% trans "From here you can update the configuration of the host filesystems." %}</p>
|
||||
<p>{% trans "WARNING: Filesystem sizes can not be decreased after configuration operation. " %}</p>
|
||||
<p>{% trans "Major Alarms will be raised against the affected hosts until the configuration operation is successfully completed." %}</p>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block modal-footer %}
|
||||
<a class="btn btn-default cancel" data-dismiss="modal">{% trans "Cancel" %}</a>
|
||||
<input class="btn btn-primary btn-danger" type="submit" onclick="return confirm('WARNING:' +
|
||||
'Filesystem sizes can not be decreased after configuration operation. ' +
|
||||
'Major Alarms will be raised against the affected hosts until the configuration operation is successfully completed. ');"
|
||||
value="{% trans "Save" %}" />
|
||||
{% endblock %}
|
|
@ -0,0 +1,11 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Edit Filesystem" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Edit Filesystem") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include "admin/system_config/_update_filesystems_table.html" %}
|
||||
{% endblock %}
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# Copyright (c) 2013-2018 Wind River Systems, Inc.
|
||||
# Copyright (c) 2013-2019 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
@ -13,6 +13,8 @@ from starlingx_dashboard.dashboards.admin.inventory.cpu_functions import \
|
|||
views as cpu_functions_views
|
||||
from starlingx_dashboard.dashboards.admin.inventory.devices import \
|
||||
views as device_views
|
||||
from starlingx_dashboard.dashboards.admin.inventory.filesystems import \
|
||||
views as fs_views
|
||||
from starlingx_dashboard.dashboards.admin.inventory.interfaces.address import \
|
||||
views as address_views
|
||||
from starlingx_dashboard.dashboards.admin.inventory.interfaces.route import \
|
||||
|
@ -155,5 +157,8 @@ urlpatterns = [
|
|||
name='editpartition'),
|
||||
url(r'^(?P<host_id>[^/]+)/assignlabel/$',
|
||||
label_views.AssignLabelView.as_view(),
|
||||
name='assignlabel')
|
||||
name='assignlabel'),
|
||||
url(r'^(?P<host_id>[^/]+)/updatefilesystems/$',
|
||||
fs_views.UpdateFilesystemsView.as_view(),
|
||||
name='updatefilesystems')
|
||||
]
|
||||
|
|
|
@ -138,6 +138,9 @@ class DetailView(tabs.TabbedTableView):
|
|||
host.partitions = stx_api.sysinv.host_disk_partition_list(
|
||||
self.request, host.uuid)
|
||||
|
||||
host.filesystems = stx_api.sysinv.host_filesystems_list(
|
||||
self.request, host.uuid)
|
||||
|
||||
# Translate partition state codes:
|
||||
for p in host.partitions:
|
||||
p.status = stx_api.sysinv.PARTITION_STATUS_MSG[p.status]
|
||||
|
|
Loading…
Reference in New Issue