User messages panel
Addds user messages panel for project and admin views. This feature was introduced in Manila API v2.37. Change-Id: Iad130b642e33c08e6d41021a378893a55f4cfec5 Implements: blueprint ui-user-messages
This commit is contained in:
parent
bbfc3f0a4f
commit
62bea909c8
|
@ -639,3 +639,18 @@ def share_group_type_unset_specs(request, share_group_type, keys):
|
|||
def share_group_type_get_specs(request, share_group_type):
|
||||
return manilaclient(request).share_group_types.get(
|
||||
share_group_type).get_keys()
|
||||
|
||||
|
||||
# ####### User Messages # ########
|
||||
def messages_get(request, message_id):
|
||||
return manilaclient(request).messages.get(message_id)
|
||||
|
||||
|
||||
def messages_list(request, search_opts=None, sort_key=None, sort_dir=None):
|
||||
return manilaclient(request).messages.list(search_opts=search_opts,
|
||||
sort_key=sort_key,
|
||||
sort_dir=sort_dir)
|
||||
|
||||
|
||||
def messages_delete(request, message_id):
|
||||
return manilaclient(request).messages.delete(message_id)
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
# Copyright (c) 2020 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
import horizon
|
||||
from openstack_dashboard.dashboards.admin import dashboard
|
||||
|
||||
|
||||
class UserMessages(horizon.Panel):
|
||||
name = _("User Messages")
|
||||
slug = 'user_messages'
|
||||
permissions = (
|
||||
'openstack.services.share',
|
||||
)
|
||||
|
||||
|
||||
dashboard.Admin.register(UserMessages)
|
|
@ -0,0 +1,46 @@
|
|||
# Copyright (c) 2020 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from horizon import tables
|
||||
|
||||
from manila_ui.dashboards.project.user_messages import tables as project_tables
|
||||
|
||||
|
||||
class DeleteUserMessage(project_tables.DeleteUserMessage):
|
||||
pass
|
||||
|
||||
|
||||
class UserMessageIDColumn(project_tables.UserMessageIDColumn):
|
||||
pass
|
||||
|
||||
|
||||
class UserMessagesAdminTable(project_tables.UserMessagesTable):
|
||||
project_name = tables.Column(
|
||||
"project_name",
|
||||
verbose_name=_("Project"),
|
||||
)
|
||||
|
||||
class Meta(object):
|
||||
name = "user_messages"
|
||||
verbose_name = _("User Messages")
|
||||
table_actions = (
|
||||
tables.NameFilterAction,
|
||||
DeleteUserMessage,
|
||||
)
|
||||
row_actions = (
|
||||
DeleteUserMessage,
|
||||
)
|
||||
columns = ('project_name', 'message_id', 'resource_type',
|
||||
'resource_id', 'user_message', 'created_at',)
|
|
@ -0,0 +1,23 @@
|
|||
# Copyright (c) 2020 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from manila_ui.dashboards.project.user_messages import tabs as project_tabs
|
||||
|
||||
|
||||
class UserMessagesOverviewTab(project_tabs.UserMessagesOverviewTab):
|
||||
template_name = "admin/user_messages/_detail.html"
|
||||
|
||||
|
||||
class UserMessagesDetailTabs(project_tabs.UserMessagesDetailTabs):
|
||||
pass
|
|
@ -0,0 +1,26 @@
|
|||
{% load i18n sizeformat parse_date %}
|
||||
|
||||
<h3>{% trans "User Messages Overview" %}</h3>
|
||||
<div class="detail">
|
||||
<hr class="header_rule">
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "ID" %}</dt>
|
||||
<dd>{{ message.id }}</dd>
|
||||
<dt>{% trans "Action" %}</dt>
|
||||
<dd>{{ message.action_id }}</dd>
|
||||
<dt>{% trans "Message" %}</dt>
|
||||
<dd>{{ message.user_message }}</dd>
|
||||
<dt>{% trans "Message Level" %}</dt>
|
||||
<dd>{{ message.message_level }}</dd>
|
||||
<dt>{% trans "Resource Type" %}</dt>
|
||||
<dd>{{ message.resource_type }}</dd>
|
||||
<dt>{% trans "Resource ID" %}</dt>
|
||||
<dd>{{ message.resource_id }}</dd>
|
||||
<dt>{% trans "Created at" %}</dt>
|
||||
<dd>{{ message.created_at|parse_isotime }}</dd>
|
||||
<dt>{% trans "Expires at" %}</dt>
|
||||
<dd>{{ message.expires_at|parse_isotime }}</dd>
|
||||
<dt>{% trans "Request ID" %}</dt>
|
||||
<dd>{{ message.request_id }}</dd>
|
||||
</dl>
|
||||
</div>
|
|
@ -0,0 +1,11 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "User Messages Detail" %}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
{{ tab_group.render }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,11 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "User Messages" %}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
{{ user_messages_table.render }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,29 @@
|
|||
# Copyright (c) 2020 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.conf import urls
|
||||
|
||||
from manila_ui.dashboards.admin.user_messages import views
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
urls.url(
|
||||
r'^$',
|
||||
views.UserMessagesAdminView.as_view(),
|
||||
name='index'),
|
||||
urls.url(
|
||||
r'^(?P<message_id>[^/]+)$',
|
||||
views.UserMessagesAdminDetailView.as_view(),
|
||||
name='user_messages_detail'),
|
||||
]
|
|
@ -0,0 +1,48 @@
|
|||
# Copyright (c) 2020 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from horizon import exceptions
|
||||
from horizon.utils import memoized
|
||||
|
||||
from manila_ui.api import manila
|
||||
from manila_ui.dashboards.admin.user_messages import tables as admin_tables
|
||||
from manila_ui.dashboards.admin.user_messages import tabs as admin_tabs
|
||||
from manila_ui.dashboards.admin import utils
|
||||
from manila_ui.dashboards.project.user_messages import views as project_views
|
||||
|
||||
|
||||
class UserMessagesAdminView(project_views.UserMessagesView):
|
||||
table_classes = (
|
||||
admin_tables.UserMessagesAdminTable,
|
||||
)
|
||||
template_name = "admin/user_messages/index.html"
|
||||
|
||||
@memoized.memoized_method
|
||||
def get_user_messages_data(self):
|
||||
try:
|
||||
messages = manila.messages_list(self.request)
|
||||
utils.set_project_name_to_objects(self.request, messages)
|
||||
except Exception:
|
||||
msg = _("Unable to retrieve messages list.")
|
||||
exceptions.handle(self.request, msg)
|
||||
return []
|
||||
return messages
|
||||
|
||||
|
||||
class UserMessagesAdminDetailView(project_views.UserMessagesDetailView):
|
||||
tab_group_class = admin_tabs.UserMessagesDetailTabs
|
||||
template_name = 'admin/user_messages/detail.html'
|
||||
redirect_url = reverse_lazy('horizon:admin:user_messages:index')
|
|
@ -0,0 +1,28 @@
|
|||
# Copyright (c) 2020 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
import horizon
|
||||
from openstack_dashboard.dashboards.project import dashboard
|
||||
|
||||
|
||||
class UserMessages(horizon.Panel):
|
||||
name = _("User Messages")
|
||||
slug = 'user_messages'
|
||||
permissions = (
|
||||
'openstack.services.share',
|
||||
)
|
||||
|
||||
|
||||
dashboard.Project.register(UserMessages)
|
|
@ -0,0 +1,101 @@
|
|||
# Copyright (c) 2020 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import ungettext_lazy
|
||||
from horizon import exceptions
|
||||
from horizon import tables
|
||||
from horizon.utils.filters import parse_isotime
|
||||
|
||||
from manila_ui.api import manila
|
||||
|
||||
|
||||
def get_date(message):
|
||||
return parse_isotime(message.created_at)
|
||||
|
||||
|
||||
class DeleteUserMessage(tables.DeleteAction):
|
||||
policy_rules = (("share", "share:delete_message"),)
|
||||
|
||||
@staticmethod
|
||||
def action_present(count):
|
||||
return ungettext_lazy(
|
||||
u"Delete User Message",
|
||||
u"Delete User Messages",
|
||||
count
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def action_past(count):
|
||||
return ungettext_lazy(
|
||||
u"Deleted User Message",
|
||||
u"Deleted User Messages",
|
||||
count
|
||||
)
|
||||
|
||||
def get_policy_target(self, request, datum=None):
|
||||
project_id = None
|
||||
if datum:
|
||||
project_id = getattr(datum, "project_id", None)
|
||||
return {"project_id": project_id}
|
||||
|
||||
def delete(self, request, obj_id):
|
||||
obj = self.table.get_object_by_id(obj_id)
|
||||
message_id = self.table.get_object_display(obj)
|
||||
try:
|
||||
manila.messages_delete(request, message_id)
|
||||
except Exception:
|
||||
msg = _('Unable to delete message "%s"')
|
||||
exceptions.handle(self.request, msg % message_id)
|
||||
raise
|
||||
|
||||
|
||||
class UserMessageIDColumn(tables.Column):
|
||||
|
||||
def get_link_url(self, message):
|
||||
return reverse(self.link, args=(message.message_id,))
|
||||
|
||||
|
||||
class UserMessagesTable(tables.DataTable):
|
||||
message_id = tables.Column(
|
||||
"id",
|
||||
verbose_name=_("ID"),
|
||||
link="horizon:project:user_messages:user_messages_detail")
|
||||
resource_type = tables.Column(
|
||||
"resource_type",
|
||||
verbose_name=_("Resource Type"))
|
||||
resource_id = tables.Column(
|
||||
"resource_id",
|
||||
verbose_name=_("Resource ID"))
|
||||
user_message = tables.Column(
|
||||
"user_message",
|
||||
verbose_name=_("User Message"))
|
||||
created_at = tables.Column(
|
||||
get_date,
|
||||
verbose_name=_("Created At"))
|
||||
|
||||
def get_object_display(self, obj):
|
||||
return obj.id
|
||||
|
||||
class Meta(object):
|
||||
name = "user_messages"
|
||||
verbose_name = _("User Messages")
|
||||
table_actions = (
|
||||
tables.NameFilterAction,
|
||||
DeleteUserMessage,
|
||||
)
|
||||
row_actions = (
|
||||
DeleteUserMessage,
|
||||
)
|
|
@ -0,0 +1,32 @@
|
|||
# Copyright (c) 2020 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from horizon import tabs
|
||||
|
||||
|
||||
class UserMessagesOverviewTab(tabs.Tab):
|
||||
name = _("User Messages Overview")
|
||||
slug = "user_messages_overview_tab"
|
||||
template_name = "project/user_messages/_detail.html"
|
||||
|
||||
def get_context_data(self, request):
|
||||
return {"message": self.tab_group.kwargs['message']}
|
||||
|
||||
|
||||
class UserMessagesDetailTabs(tabs.TabGroup):
|
||||
slug = "user_messages_detail"
|
||||
tabs = (
|
||||
UserMessagesOverviewTab,
|
||||
)
|
|
@ -0,0 +1,26 @@
|
|||
{% load i18n sizeformat parse_date %}
|
||||
|
||||
<h3>{% trans "User Messages Overview" %}</h3>
|
||||
<div class="detail">
|
||||
<hr class="header_rule">
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "ID" %}</dt>
|
||||
<dd>{{ message.id }}</dd>
|
||||
<dt>{% trans "Action" %}</dt>
|
||||
<dd>{{ message.action_id }}</dd>
|
||||
<dt>{% trans "Message" %}</dt>
|
||||
<dd>{{ message.user_message }}</dd>
|
||||
<dt>{% trans "Message Level" %}</dt>
|
||||
<dd>{{ message.message_level }}</dd>
|
||||
<dt>{% trans "Resource Type" %}</dt>
|
||||
<dd>{{ message.resource_type }}</dd>
|
||||
<dt>{% trans "Resource ID" %}</dt>
|
||||
<dd>{{ message.resource_id }}</dd>
|
||||
<dt>{% trans "Created at" %}</dt>
|
||||
<dd>{{ message.created_at|parse_isotime }}</dd>
|
||||
<dt>{% trans "Expires at" %}</dt>
|
||||
<dd>{{ message.expires_at|parse_isotime }}</dd>
|
||||
<dt>{% trans "Request ID" %}</dt>
|
||||
<dd>{{ message.request_id }}</dd>
|
||||
</dl>
|
||||
</div>
|
|
@ -0,0 +1,11 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "User Messages Details" %}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
{{ tab_group.render }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,11 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "User Messages" %}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
{{ user_messages_table.render }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,29 @@
|
|||
# Copyright (c) 2020 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.conf import urls
|
||||
|
||||
from manila_ui.dashboards.project.user_messages import views
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
urls.url(
|
||||
r'^$',
|
||||
views.UserMessagesView.as_view(),
|
||||
name='index'),
|
||||
urls.url(
|
||||
r'^(?P<message_id>[^/]+)$',
|
||||
views.UserMessagesDetailView.as_view(),
|
||||
name='user_messages_detail'),
|
||||
]
|
|
@ -0,0 +1,76 @@
|
|||
# Copyright (c) 2020 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from horizon import exceptions
|
||||
from horizon import tables
|
||||
from horizon import tabs
|
||||
from horizon.utils import memoized
|
||||
|
||||
from manila_ui.api import manila
|
||||
from manila_ui.dashboards.project.user_messages import tables as um_tables
|
||||
from manila_ui.dashboards.project.user_messages import tabs as um_tabs
|
||||
|
||||
|
||||
class UserMessagesView(tables.MultiTableView):
|
||||
table_classes = (
|
||||
um_tables.UserMessagesTable,
|
||||
)
|
||||
template_name = "project/user_messages/index.html"
|
||||
page_title = _("User Messages")
|
||||
|
||||
@memoized.memoized_method
|
||||
def get_user_messages_data(self):
|
||||
try:
|
||||
messages = manila.messages_list(self.request)
|
||||
except Exception:
|
||||
msg = _("Unable to retrieve messages list.")
|
||||
exceptions.handle(self.request, msg)
|
||||
return []
|
||||
return messages
|
||||
|
||||
|
||||
class UserMessagesDetailView(tabs.TabView):
|
||||
tab_group_class = um_tabs.UserMessagesDetailTabs
|
||||
template_name = 'project/user_messages/detail.html'
|
||||
redirect_url = reverse_lazy('horizon:project:user_messages:index')
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(UserMessagesDetailView, self).get_context_data(
|
||||
**kwargs)
|
||||
message = self.get_data()
|
||||
message_id = message.id
|
||||
context["message"] = message
|
||||
context["message_id"] = message_id
|
||||
context["page_title"] = _("User Message Details: "
|
||||
"%(message_id)s") % (
|
||||
{'message_id': message_id})
|
||||
return context
|
||||
|
||||
@memoized.memoized_method
|
||||
def get_data(self):
|
||||
try:
|
||||
message_id = self.kwargs['message_id']
|
||||
message = manila.messages_get(self.request, message_id)
|
||||
except Exception:
|
||||
exceptions.handle(
|
||||
self.request,
|
||||
_('Unable to retrieve user message detail.'),
|
||||
redirect=self.redirect_url)
|
||||
return message
|
||||
|
||||
def get_tabs(self, request, *args, **kwargs):
|
||||
message = self.get_data()
|
||||
return self.tab_group_class(request, message=message, **kwargs)
|
|
@ -0,0 +1,19 @@
|
|||
# Copyright 2020 Red Hat Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
PANEL_DASHBOARD = 'admin'
|
||||
PANEL_GROUP = 'share'
|
||||
PANEL = 'user_messages'
|
||||
|
||||
ADD_PANEL = ('manila_ui.dashboards.admin.user_messages.panel.UserMessages')
|
|
@ -0,0 +1,19 @@
|
|||
# Copyright 2020 Red Hat Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
PANEL_DASHBOARD = 'project'
|
||||
PANEL_GROUP = 'share'
|
||||
PANEL = 'user_messages'
|
||||
|
||||
ADD_PANEL = ('manila_ui.dashboards.project.user_messages.panel.UserMessages')
|
|
@ -690,3 +690,39 @@ class ManilaApiTests(base.APITestCase):
|
|||
get_method.return_value.get_keys.return_value, result)
|
||||
get_method.assert_called_once_with(sgt)
|
||||
get_method.return_value.get_keys.assert_called_once_with()
|
||||
|
||||
@ddt.data(None, "some_fake_message_id")
|
||||
def test_share_messages_get(self, message_id):
|
||||
result = api.messages_get(self.request, message_id)
|
||||
|
||||
self.assertIsNotNone(result)
|
||||
self.assertEqual(
|
||||
self.manilaclient.messages.get.return_value,
|
||||
result)
|
||||
self.manilaclient.messages.get.assert_called_once_with(message_id)
|
||||
|
||||
@ddt.data(
|
||||
{},
|
||||
{'search_opts': 'foo', 'sort_key': 'k', 'sort_dir': 'v'},
|
||||
)
|
||||
def test_messages_list(self, kwargs):
|
||||
result = api.messages_list(self.request, **kwargs)
|
||||
|
||||
self.assertIsNotNone(result)
|
||||
self.assertEqual(
|
||||
self.manilaclient.messages.list.return_value,
|
||||
result)
|
||||
self.manilaclient.messages.list.assert_called_once_with(
|
||||
search_opts=kwargs.get('search_opts'),
|
||||
sort_key=kwargs.get('sort_key'),
|
||||
sort_dir=kwargs.get('sort_dir'))
|
||||
|
||||
@ddt.data(None, "some_fake_message_id")
|
||||
def test_messages_delete(self, message_id):
|
||||
result = api.messages_delete(self.request, message_id)
|
||||
|
||||
self.assertIsNotNone(result)
|
||||
self.assertEqual(
|
||||
self.manilaclient.messages.delete.return_value,
|
||||
result)
|
||||
self.manilaclient.messages.delete.assert_called_once_with(message_id)
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
# Copyright 2020 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import ddt
|
||||
from django.urls import reverse
|
||||
from openstack_dashboard.api import keystone as api_keystone
|
||||
from unittest import mock
|
||||
|
||||
from horizon import exceptions as horizon_exceptions
|
||||
|
||||
from manila_ui.api import manila as api_manila
|
||||
from manila_ui.dashboards.admin import utils
|
||||
from manila_ui.tests.dashboards.project import test_data
|
||||
from manila_ui.tests import helpers as test
|
||||
from manila_ui.tests.test_data import keystone_data
|
||||
|
||||
|
||||
INDEX_URL = reverse('horizon:admin:user_messages:index')
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class UserMessagesViewTests(test.BaseAdminViewTests):
|
||||
|
||||
def setUp(self):
|
||||
super(self.__class__, self).setUp()
|
||||
self.mock_object(
|
||||
api_keystone, "tenant_list",
|
||||
mock.Mock(return_value=(keystone_data.projects, None)))
|
||||
# Reset taken list of projects to avoid test interference
|
||||
utils.PROJECTS = {}
|
||||
|
||||
@ddt.data(None, Exception('fake'))
|
||||
def test_view(self, exc):
|
||||
message_1 = test_data.fake_message_1
|
||||
message_2 = test_data.fake_message_2
|
||||
message_3 = test_data.fake_message_3
|
||||
fake_message_list = [message_1, message_2, message_3]
|
||||
url = reverse('horizon:admin:user_messages:index')
|
||||
self.mock_object(
|
||||
api_manila, "messages_list",
|
||||
mock.Mock(side_effect=exc, return_value=fake_message_list))
|
||||
|
||||
self.client.get(url)
|
||||
|
||||
self.assertNoMessages()
|
||||
api_manila.messages_list.assert_called_once_with(mock.ANY)
|
||||
|
||||
@ddt.data(None, Exception('fake'))
|
||||
def test_delete_message(self, exc):
|
||||
message = test_data.fake_message_1
|
||||
formData = {'action': 'user_messages__delete__%s' % message.id}
|
||||
self.mock_object(api_manila, "messages_delete",
|
||||
mock.Mock(side_effect=exc))
|
||||
self.mock_object(
|
||||
api_manila, "messages_list",
|
||||
mock.Mock(return_value=[message]))
|
||||
|
||||
res = self.client.post(INDEX_URL, formData)
|
||||
|
||||
self.assertEqual(res.status_code, 302)
|
||||
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
api_manila.messages_list.assert_called_once_with(mock.ANY)
|
||||
api_manila.messages_delete.assert_called_once_with(
|
||||
mock.ANY, test_data.fake_message_1.id)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class UserMessagesDetailViewTests(test.BaseAdminViewTests):
|
||||
|
||||
def test_detail_view(self):
|
||||
message = test_data.fake_message_1
|
||||
url = reverse('horizon:admin:user_messages:user_messages_detail',
|
||||
args=[message.id])
|
||||
self.mock_object(
|
||||
api_manila, "messages_get", mock.Mock(return_value=message))
|
||||
|
||||
res = self.client.get(url)
|
||||
|
||||
self.assertContains(res, "<h1>User Message Details: %s</h1>"
|
||||
% message.id,
|
||||
1, 200)
|
||||
self.assertContains(res, "<dd>%s</dd>" % message.id, 1, 200)
|
||||
self.assertContains(res, "<dd>%s</dd>" % message.action_id, 1, 200)
|
||||
self.assertContains(res, "<dd>%s</dd>" % message.user_message, 1, 200)
|
||||
self.assertContains(res, "<dd>%s</dd>" % message.message_level, 1, 200)
|
||||
self.assertContains(res, "<dd>%s</dd>" % message.resource_type, 1, 200)
|
||||
self.assertContains(res, "<dd>%s</dd>" % message.resource_id, 1, 200)
|
||||
self.assertContains(res, "<dd>%s</dd>" % message.request_id, 1, 200)
|
||||
|
||||
self.assertNoMessages()
|
||||
api_manila.messages_get.assert_called_once_with(
|
||||
mock.ANY, message.id)
|
||||
|
||||
def test_detail_view_with_exception(self):
|
||||
message = test_data.fake_message_1
|
||||
url = reverse(
|
||||
'horizon:admin:user_messages:user_messages_detail',
|
||||
args=[message.id])
|
||||
self.mock_object(
|
||||
api_manila, "messages_get",
|
||||
mock.Mock(side_effect=horizon_exceptions.NotFound(404)))
|
||||
res = self.client.get(url)
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
api_manila.messages_get.assert_called_once_with(mock.ANY, message.id)
|
|
@ -13,6 +13,7 @@
|
|||
# under the License.
|
||||
import collections
|
||||
|
||||
from manilaclient.v2 import messages
|
||||
from manilaclient.v2 import security_services
|
||||
from manilaclient.v2 import share_export_locations
|
||||
from manilaclient.v2 import share_group_snapshots
|
||||
|
@ -490,3 +491,50 @@ limits_negative = {"totalSharesUsed": 10,
|
|||
"maxTotalShareGigabytes": 1000,
|
||||
"maxTotalSnapshotGigabytes": 1000,
|
||||
}
|
||||
|
||||
# Manila User Messages
|
||||
fake_message_1 = messages.Message(
|
||||
messages.MessageManager(FakeAPIClient),
|
||||
{'resource_id': "351cc796-2d79-4a08-b878-a8ed933b6b68",
|
||||
'message_level': 'ERROR',
|
||||
'user_message': 'allocate host: No storage could be allocated for'
|
||||
' this share request. Trying again with a different'
|
||||
' size or share type may succeed.',
|
||||
'expires_at': '2017-07-10T10:27:43.000000',
|
||||
'id': '4b319d29-d5b7-4b6e-8e7c-8d6e53f3c3d5',
|
||||
'created_at': '2017-07-10T10:26:43.000000',
|
||||
'detail_id': '002',
|
||||
'request_id': 'req-24e7ccb6-a7d5-4ddd-a8e4-d8f72a4509c8',
|
||||
'project_id': '2e3de76b49b444fd9dc7ca9f7048ce6b',
|
||||
'resource_type': 'SHARE',
|
||||
'action_id': '001'})
|
||||
|
||||
fake_message_2 = messages.Message(
|
||||
messages.MessageManager(FakeAPIClient),
|
||||
{'resource_id': "25b4c0cc-e711-4c6f-b9fd-72d6b5c62bce",
|
||||
'message_level': 'ERROR',
|
||||
'user_message': 'Driver does not expect share-network to be provided '
|
||||
'with current configuration.',
|
||||
'expires_at': '2018-09-10T09:37:45.000000',
|
||||
'id': 'd01d03ee-7758-4175-a6b5-853329dd2f4e',
|
||||
'created_at': '2018-09-10T09:36:45.000000',
|
||||
'detail_id': '003',
|
||||
'request_id': 'req-fa568ab0-d6b3-4b32-899d-637ee006fed4',
|
||||
'project_id': '2e3de76b49b444fd9dc7ca9f7048ce6b',
|
||||
'resource_type': 'SHARE',
|
||||
'action_id': '002'})
|
||||
|
||||
fake_message_3 = messages.Message(
|
||||
messages.MessageManager(FakeAPIClient),
|
||||
{'resource_id': "4befdc84-2796-44e1-8645-14b651bfb787",
|
||||
'message_level': 'ERROR',
|
||||
'user_message': 'Share has no replica with "replica_state" '
|
||||
'set to "active"',
|
||||
'expires_at': '2020-09-09T22:37:13.000000',
|
||||
'id': '1e1c493f-d07d-48e9-93a8-ef5ad4b8ca8a',
|
||||
'created_at': '2020-09-09T22:36:13.000000',
|
||||
'detail_id': '004',
|
||||
'request_id': 'req-29449bc8-d0ec-4d6b-b37c-85d0f04251b1',
|
||||
'project_id': '2e3de76b49b444fd9dc7ca9f7048ce6b',
|
||||
'resource_type': 'SHARE_REPLICA',
|
||||
'action_id': '002'})
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
# Copyright 2020 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import ddt
|
||||
from django.urls import reverse
|
||||
from unittest import mock
|
||||
|
||||
from horizon import exceptions as horizon_exceptions
|
||||
|
||||
from manila_ui.api import manila as api_manila
|
||||
from manila_ui.tests.dashboards.project import test_data
|
||||
from manila_ui.tests import helpers as test
|
||||
|
||||
INDEX_URL = reverse('horizon:project:user_messages:index')
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class UserMessagesViewTests(test.TestCase):
|
||||
|
||||
@ddt.data(None, Exception('fake'))
|
||||
def test_view(self, exc):
|
||||
message_1 = test_data.fake_message_1
|
||||
message_2 = test_data.fake_message_2
|
||||
message_3 = test_data.fake_message_3
|
||||
fake_message_list = [message_1, message_2, message_3]
|
||||
url = reverse('horizon:project:user_messages:index')
|
||||
self.mock_object(
|
||||
api_manila, "messages_list",
|
||||
mock.Mock(side_effect=exc, return_value=fake_message_list))
|
||||
|
||||
self.client.get(url)
|
||||
|
||||
self.assertNoMessages()
|
||||
api_manila.messages_list.assert_called_once_with(mock.ANY)
|
||||
|
||||
@ddt.data(None, Exception('fake'))
|
||||
def test_delete_message(self, exc):
|
||||
message = test_data.fake_message_1
|
||||
formData = {'action': 'user_messages__delete__%s' % message.id}
|
||||
self.mock_object(api_manila, "messages_delete",
|
||||
mock.Mock(side_effect=exc))
|
||||
self.mock_object(
|
||||
api_manila, "messages_list",
|
||||
mock.Mock(return_value=[message]))
|
||||
|
||||
res = self.client.post(INDEX_URL, formData)
|
||||
|
||||
self.assertEqual(res.status_code, 302)
|
||||
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
api_manila.messages_list.assert_called_once_with(mock.ANY)
|
||||
api_manila.messages_delete.assert_called_once_with(
|
||||
mock.ANY, test_data.fake_message_1.id)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class UserMessagesDetailViewTests(test.TestCase):
|
||||
|
||||
def test_detail_view(self):
|
||||
message = test_data.fake_message_1
|
||||
url = reverse('horizon:project:user_messages:user_messages_detail',
|
||||
args=[message.id])
|
||||
self.mock_object(
|
||||
api_manila, "messages_get", mock.Mock(return_value=message))
|
||||
|
||||
res = self.client.get(url)
|
||||
|
||||
self.assertContains(res, "<h1>User Message Details: %s</h1>"
|
||||
% message.id,
|
||||
1, 200)
|
||||
self.assertContains(res, "<dd>%s</dd>" % message.id, 1, 200)
|
||||
self.assertContains(res, "<dd>%s</dd>" % message.action_id, 1, 200)
|
||||
self.assertContains(res, "<dd>%s</dd>" % message.user_message, 1, 200)
|
||||
self.assertContains(res, "<dd>%s</dd>" % message.message_level, 1, 200)
|
||||
self.assertContains(res, "<dd>%s</dd>" % message.resource_type, 1, 200)
|
||||
self.assertContains(res, "<dd>%s</dd>" % message.resource_id, 1, 200)
|
||||
self.assertContains(res, "<dd>%s</dd>" % message.request_id, 1, 200)
|
||||
|
||||
self.assertNoMessages()
|
||||
api_manila.messages_get.assert_called_once_with(
|
||||
mock.ANY, message.id)
|
||||
|
||||
def test_detail_view_with_exception(self):
|
||||
message = test_data.fake_message_1
|
||||
url = reverse(
|
||||
'horizon:project:user_messages:user_messages_detail',
|
||||
args=[message.id])
|
||||
self.mock_object(
|
||||
api_manila, "messages_get",
|
||||
mock.Mock(side_effect=horizon_exceptions.NotFound(404)))
|
||||
res = self.client.get(url)
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
api_manila.messages_get.assert_called_once_with(mock.ANY, message.id)
|
|
@ -0,0 +1,20 @@
|
|||
# Copyright (c) 2020 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
from manila_ui.tests.integration.pages.project.share import messagespage
|
||||
|
||||
|
||||
class MessagesPage(messagespage.MessagesPage):
|
||||
pass
|
|
@ -0,0 +1,22 @@
|
|||
# Copyright (c) 2020 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
from openstack_dashboard.test.integration_tests.pages import basepage
|
||||
|
||||
|
||||
class MessagesPage(basepage.BaseNavigationPage):
|
||||
def __init__(self, driver, conf):
|
||||
super(MessagesPage, self).__init__(driver, conf)
|
||||
self._page_title = "User Messages"
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
Implements the user messages graphical interface for the project and admin
|
||||
dashboards.
|
||||
[`blueprint ui-user-messages <https://blueprints.launchpad.net/manila-ui/+spec/ui-user-messages>`_]
|
Loading…
Reference in New Issue