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
This commit is contained in:
parent
f044c4b0a3
commit
20a571fdd2
@ -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
|
||||
|
||||
|
@ -10,6 +10,8 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# 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)
|
||||
|
@ -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>
|
||||
|
@ -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)
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -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):
|
||||
|
@ -68,6 +68,6 @@ class SnapshotMessagesTab(tabs.TableTab):
|
||||
return messages
|
||||
|
||||
|
||||
class SnapshotDetailTabs(tabs.TabGroup):
|
||||
class SnapshotDetailTabs(tabs.DetailTabsGroup):
|
||||
slug = "snapshot_details"
|
||||
tabs = (OverviewTab, SnapshotMessagesTab)
|
||||
|
@ -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))
|
||||
|
@ -0,0 +1,4 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Cinder user messages are now available for volume backups in a messages tab.
|
Loading…
Reference in New Issue
Block a user