summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesper Schmitz Mouridsen <jesper@schmitz.computer>2022-06-14 21:32:18 +0000
committerJesper Schmitz Mouridsen <jesper@schmitz.computer>2022-09-06 07:29:40 +0000
commit20a571fdd299f18c497bbb22ab0af7ead1bc4690 (patch)
tree8bc0fc4652e8484bbd397c0bc38b63134ab3f55d
parentf044c4b0a30da4b4b5e3df1b7888811efddce447 (diff)
downloadhorizon-20a571fdd299f18c497bbb22ab0af7ead1bc4690.tar.gz
Add cinder-user-facing messages for Backup
This patch adds a tab for cinder user messages for volume backups. Cinder user messages show error details for cinder resources like if we are unable to create a volume backup due to some failure in cinder it will show us the reason for failure. It also updates project and admin SnapshotDetailsTabs to use DetailTabsGroup instead of TabGroup to improve top padding. Also adds the fail_reason in the detail view, if backup errored. Related-Bug https://bugs.launchpad.net/cinder/+bug/1978729 Change-Id: I4e639211043270e814fac489f915588af03f966a
-rw-r--r--openstack_dashboard/api/cinder.py2
-rw-r--r--openstack_dashboard/dashboards/admin/backups/tabs.py8
-rw-r--r--openstack_dashboard/dashboards/admin/backups/templates/backups/_detail_overview.html4
-rw-r--r--openstack_dashboard/dashboards/admin/snapshots/tabs.py2
-rw-r--r--openstack_dashboard/dashboards/project/backups/tables.py18
-rw-r--r--openstack_dashboard/dashboards/project/backups/tabs.py26
-rw-r--r--openstack_dashboard/dashboards/project/backups/templates/backups/_detail_overview.html4
-rw-r--r--openstack_dashboard/dashboards/project/backups/tests.py36
-rw-r--r--openstack_dashboard/dashboards/project/snapshots/tabs.py2
-rw-r--r--openstack_dashboard/test/test_data/cinder_data.py14
-rw-r--r--releasenotes/notes/cinder-backup-cinder-messages-2127d04da3c82033.yaml4
11 files changed, 113 insertions, 7 deletions
diff --git a/openstack_dashboard/api/cinder.py b/openstack_dashboard/api/cinder.py
index 03ac5aee3..89319cd4a 100644
--- a/openstack_dashboard/api/cinder.py
+++ b/openstack_dashboard/api/cinder.py
@@ -121,7 +121,7 @@ class VolumeBackup(BaseCinderAPIResourceWrapper):
_attrs = ['id', 'name', 'description', 'container', 'size', 'status',
'created_at', 'volume_id', 'availability_zone', 'snapshot_id',
- 'os-backup-project-attr:project_id']
+ 'os-backup-project-attr:project_id', 'fail_reason']
_volume = None
_snapshot = None
diff --git a/openstack_dashboard/dashboards/admin/backups/tabs.py b/openstack_dashboard/dashboards/admin/backups/tabs.py
index d4631822c..dfb40ddaa 100644
--- a/openstack_dashboard/dashboards/admin/backups/tabs.py
+++ b/openstack_dashboard/dashboards/admin/backups/tabs.py
@@ -11,6 +11,8 @@
# under the License.
from openstack_dashboard.dashboards.project.backups \
+ import tables as backup_messages_tables
+from openstack_dashboard.dashboards.project.backups \
import tabs as project_tabs
@@ -19,5 +21,9 @@ class AdminBackupOverviewTab(project_tabs.BackupOverviewTab):
redirect_url = 'horizon:admin:backups:index'
+class BackupMessagesTab(project_tabs.BackupMessagesTab):
+ table_classes = (backup_messages_tables.BackupMessagesTable,)
+
+
class AdminBackupDetailTabs(project_tabs.BackupDetailTabs):
- tabs = (AdminBackupOverviewTab,)
+ tabs = (AdminBackupOverviewTab, BackupMessagesTab)
diff --git a/openstack_dashboard/dashboards/admin/backups/templates/backups/_detail_overview.html b/openstack_dashboard/dashboards/admin/backups/templates/backups/_detail_overview.html
index 948df205b..c878d33bf 100644
--- a/openstack_dashboard/dashboards/admin/backups/templates/backups/_detail_overview.html
+++ b/openstack_dashboard/dashboards/admin/backups/templates/backups/_detail_overview.html
@@ -14,6 +14,10 @@
<dd>{{ backup.project_id|default:_("-") }}</dd>
<dt>{% trans "Status" %}</dt>
<dd>{{ backup.status|capfirst }}</dd>
+ {% if backup.status == 'error' %}
+ <dt>{%trans "Fail reason"%}</dt>
+ <dd>{{ backup.fail_reason }} <dd>
+ {% endif %}
{% if volume %}
<dt>{% trans "Volume" %}</dt>
<dd>
diff --git a/openstack_dashboard/dashboards/admin/snapshots/tabs.py b/openstack_dashboard/dashboards/admin/snapshots/tabs.py
index 940fb074f..7ef2f5616 100644
--- a/openstack_dashboard/dashboards/admin/snapshots/tabs.py
+++ b/openstack_dashboard/dashboards/admin/snapshots/tabs.py
@@ -34,6 +34,6 @@ class SnapshotMessagesTab(project_tab.SnapshotMessagesTab):
table_classes = (snap_messages_tables.SnapshotMessagesTable,)
-class SnapshotDetailsTabs(tabs.TabGroup):
+class SnapshotDetailsTabs(tabs.DetailTabsGroup):
slug = "snapshot_details"
tabs = (OverviewTab, SnapshotMessagesTab)
diff --git a/openstack_dashboard/dashboards/project/backups/tables.py b/openstack_dashboard/dashboards/project/backups/tables.py
index 4cbf34ef8..6c0a1c46d 100644
--- a/openstack_dashboard/dashboards/project/backups/tables.py
+++ b/openstack_dashboard/dashboards/project/backups/tables.py
@@ -197,3 +197,21 @@ class BackupsTable(tables.DataTable):
row_class = UpdateRow
table_actions = (DeleteBackup,)
row_actions = (RestoreBackup, DeleteBackup)
+
+
+class BackupMessagesTable(tables.DataTable):
+ message_id = tables.Column("id", verbose_name=_("ID"))
+ message_level = tables.Column("message_level",
+ verbose_name=_("Message Level"))
+ event_id = tables.Column("event_id",
+ verbose_name=_("Event Id"))
+ user_message = tables.Column("user_message",
+ verbose_name=_("User Message"))
+ created_at = tables.Column("created_at",
+ verbose_name=_("Created At"))
+ guaranteed_until = tables.Column("guaranteed_until",
+ verbose_name=_("Guaranteed Until"))
+
+ class Meta(object):
+ name = "backup_messages"
+ verbose_name = _("Messages")
diff --git a/openstack_dashboard/dashboards/project/backups/tabs.py b/openstack_dashboard/dashboards/project/backups/tabs.py
index d867af485..74606fa45 100644
--- a/openstack_dashboard/dashboards/project/backups/tabs.py
+++ b/openstack_dashboard/dashboards/project/backups/tabs.py
@@ -18,6 +18,8 @@ from horizon import exceptions
from horizon import tabs
from openstack_dashboard.api import cinder
+from openstack_dashboard.dashboards.project.backups \
+ import tables as backup_messages_tables
class BackupOverviewTab(tabs.Tab):
@@ -53,6 +55,26 @@ class BackupOverviewTab(tabs.Tab):
redirect=redirect)
-class BackupDetailTabs(tabs.TabGroup):
+class BackupMessagesTab(tabs.TableTab):
+ table_classes = (backup_messages_tables.BackupMessagesTable,)
+ name = _("Messages")
+ slug = "messages_tab"
+ template_name = ("horizon/common/_detail_table.html")
+ preload = False
+
+ def get_backup_messages_data(self):
+ messages = []
+ backup = self.tab_group.kwargs['backup']
+ backup_id = backup.id
+ try:
+ messages = cinder.message_list(self.request, search_opts={
+ 'resource_type': 'volume_backup', 'resource_uuid': backup_id})
+ except Exception:
+ exceptions.handle(self.request, _("Unable to retrieve "
+ "backup messages."))
+ return messages
+
+
+class BackupDetailTabs(tabs.DetailTabsGroup):
slug = "backup_details"
- tabs = (BackupOverviewTab,)
+ tabs = (BackupOverviewTab, BackupMessagesTab)
diff --git a/openstack_dashboard/dashboards/project/backups/templates/backups/_detail_overview.html b/openstack_dashboard/dashboards/project/backups/templates/backups/_detail_overview.html
index 26e78b518..6567b88be 100644
--- a/openstack_dashboard/dashboards/project/backups/templates/backups/_detail_overview.html
+++ b/openstack_dashboard/dashboards/project/backups/templates/backups/_detail_overview.html
@@ -12,6 +12,10 @@
{% endif %}
<dt>{% trans "Status" %}</dt>
<dd>{{ backup.status|capfirst }}</dd>
+ {% if backup.status == 'error' %}
+ <dt>{%trans "Fail reason"%}</dt>
+ <dd>{{ backup.fail_reason }} <dd>
+ {% endif %}
{% if volume %}
<dt>{% trans "Volume" %}</dt>
<dd>
diff --git a/openstack_dashboard/dashboards/project/backups/tests.py b/openstack_dashboard/dashboards/project/backups/tests.py
index 4a93d782a..d769f10a8 100644
--- a/openstack_dashboard/dashboards/project/backups/tests.py
+++ b/openstack_dashboard/dashboards/project/backups/tests.py
@@ -9,7 +9,7 @@
# 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 unittest import mock
from urllib import parse
from django.conf import settings
@@ -20,6 +20,8 @@ from django.utils.http import urlencode
from openstack_dashboard import api
from openstack_dashboard.dashboards.project.backups \
import tables as backup_tables
+from openstack_dashboard.dashboards.project.backups \
+ import tabs
from openstack_dashboard.test import helpers as test
@@ -399,6 +401,38 @@ class VolumeBackupsViewTests(test.TestCase):
self.mock_volume_get.assert_called_once_with(
test.IsHttpRequest(), backup.volume_id)
+ @test.create_mocks({api.cinder: ('volume_backup_get',
+ 'volume_get',
+ 'message_list')})
+ def test_volume_backup_detail_view_with_messages_tab(self):
+
+ backup = self.cinder_volume_backups.first()
+ volume = self.cinder_volumes.first()
+
+ self.mock_volume_backup_get.return_value = backup
+ self.mock_volume_get.return_value = volume
+ messages = [msg for msg in self.cinder_messages.list()
+ if msg.resource_type == 'VOLUME_BACKUP']
+ self.mock_message_list.return_value = messages
+ url = reverse('horizon:project:backups:detail',
+ args=[backup.id])
+ detail_view = tabs.BackupDetailTabs(self.request)
+ messages_tab_link = "?%s=%s" % (
+ detail_view.param_name,
+ detail_view.get_tab("messages_tab").get_id())
+ url += messages_tab_link
+ res = self.client.get(url)
+ self.assertTemplateUsed(res, 'horizon/common/_detail.html')
+ self.assertContains(res, messages[0].user_message)
+ self.assertNoMessages()
+ self.mock_volume_backup_get.assert_has_calls([
+ mock.call(test.IsHttpRequest(), backup.id),
+ ])
+ search_opts = {'resource_type': 'volume_backup',
+ 'resource_uuid': backup.id}
+ self.mock_message_list.assert_called_once_with(
+ test.IsHttpRequest(), search_opts=search_opts)
+
@test.create_mocks({api.cinder: ('volume_list',
'volume_backup_restore')})
def test_restore_backup(self):
diff --git a/openstack_dashboard/dashboards/project/snapshots/tabs.py b/openstack_dashboard/dashboards/project/snapshots/tabs.py
index 5a3f63deb..34957b8a4 100644
--- a/openstack_dashboard/dashboards/project/snapshots/tabs.py
+++ b/openstack_dashboard/dashboards/project/snapshots/tabs.py
@@ -68,6 +68,6 @@ class SnapshotMessagesTab(tabs.TableTab):
return messages
-class SnapshotDetailTabs(tabs.TabGroup):
+class SnapshotDetailTabs(tabs.DetailTabsGroup):
slug = "snapshot_details"
tabs = (OverviewTab, SnapshotMessagesTab)
diff --git a/openstack_dashboard/test/test_data/cinder_data.py b/openstack_dashboard/test/test_data/cinder_data.py
index cc2f72681..8aa0b5e6c 100644
--- a/openstack_dashboard/test/test_data/cinder_data.py
+++ b/openstack_dashboard/test/test_data/cinder_data.py
@@ -579,6 +579,20 @@ def data(TEST):
'user_message': ('schedule allocate volume:'
'Could not find any available weighted backend.'),
})
+ messages_4 = messages.Message(
+ messages.MessageManager(None),
+ {'created_at': '2020-09-24T11:03:31.000000',
+ 'event_id': 'VOLUME_VOLUME_BACKUP_001_004',
+ 'guaranteed_until': '2020-10-24T11:03:31.000000',
+ 'id': '029c84a0-5810-47ed-94b6-c2aa61c5aaaf',
+ 'resource_type': 'VOLUME_BACKUP',
+ 'resource_uuid': '3c2106cb-ebef-490e-803d-b92f061e7308',
+ 'message_level': 'ERROR',
+ 'user_message': ('create backup:'
+ 'Backup driver failed to create backup.'),
+ })
+
TEST.cinder_messages.add(api.cinder.Message(messages_1))
TEST.cinder_messages.add(api.cinder.Message(messages_2))
TEST.cinder_messages.add(api.cinder.Message(messages_3))
+ TEST.cinder_messages.add(api.cinder.Message(messages_4))
diff --git a/releasenotes/notes/cinder-backup-cinder-messages-2127d04da3c82033.yaml b/releasenotes/notes/cinder-backup-cinder-messages-2127d04da3c82033.yaml
new file mode 100644
index 000000000..aa52ddfce
--- /dev/null
+++ b/releasenotes/notes/cinder-backup-cinder-messages-2127d04da3c82033.yaml
@@ -0,0 +1,4 @@
+---
+features:
+ - |
+ Cinder user messages are now available for volume backups in a messages tab.