Standardize display name on detail pages

* Standardized overview pages for volume, image and snapshot
as per the instance overview page.

Fixes bug #1207770

Change-Id: I7ae48542f4c8732c92dc4393dbaaea81158d34d6
This commit is contained in:
Abhijeet Malawade
2013-09-10 05:45:34 -07:00
parent 0df6b78422
commit 3686360878
16 changed files with 176 additions and 44 deletions

View File

@@ -3,7 +3,7 @@
{% block title %}{% trans "Volume Details" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Volume Detail") %}
{% include "horizon/common/_page_header.html" with title=_("Volume Details: ")|add:volume.display_name|default:_("Volume Details:") %}
{% endblock page_header %}
{% block main %}

View File

@@ -17,11 +17,8 @@
from django.core.urlresolvers import reverse # noqa
from django.utils.translation import ugettext_lazy as _ # noqa
from horizon import exceptions
from horizon import tabs
from openstack_dashboard import api
class OverviewTab(tabs.Tab):
name = _("Overview")
@@ -29,15 +26,7 @@ class OverviewTab(tabs.Tab):
template_name = "project/images_and_snapshots/images/_detail_overview.html"
def get_context_data(self, request):
image_id = self.tab_group.kwargs['image_id']
try:
image = api.glance.image_get(self.request, image_id)
except Exception:
redirect = reverse('horizon:project:images_and_snapshots:index')
exceptions.handle(request,
_('Unable to retrieve image details.'),
redirect=redirect)
return {'image': image}
return {"image": self.tab_group.kwargs['image']}
class ImageDetailTabs(tabs.TabGroup):

View File

@@ -163,10 +163,13 @@ class ImageViewTests(test.TestCase):
res = self.client.get(
reverse('horizon:project:images_and_snapshots:images:detail',
args=[image.id]))
self.assertTemplateUsed(res,
'project/images_and_snapshots/images/detail.html')
self.assertEqual(res.context['image'].name, image.name)
self.assertEqual(res.context['image'].protected, image.protected)
self.assertContains(res, "<h2>Image Details: %s</h2>" % image.name,
1, 200)
@test.create_stubs({api.glance: ('image_get',)})
def test_protected_image_detail_get(self):

View File

@@ -82,3 +82,25 @@ class UpdateView(forms.ModalFormView):
class DetailView(tabs.TabView):
tab_group_class = project_tabs.ImageDetailTabs
template_name = 'project/images_and_snapshots/images/detail.html'
def get_context_data(self, **kwargs):
context = super(DetailView, self).get_context_data(**kwargs)
context["image"] = self.get_data()
return context
def get_data(self):
if not hasattr(self, "_image"):
try:
image_id = self.kwargs['image_id']
self._image = api.glance.image_get(self.request, image_id)
except Exception:
url = reverse('horizon:project:images_and_snapshots:index')
exceptions.handle(self.request,
_('Unable to retrieve image details.'),
redirect=url)
return self._image
def get_tabs(self, request, *args, **kwargs):
image = self.get_data()
return self.tab_group_class(request, image=image, **kwargs)

View File

@@ -1,10 +1,10 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Image Detail "%}{% endblock %}
{% block title %}{% trans "Image Details"%}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title="Image Detail" %}
{% include "horizon/common/_page_header.html" with title=_("Image Details: ")|add:image.name|default:_("Image Details:") %}
{% endblock page_header %}
{% block main %}

View File

@@ -1,7 +1,7 @@
{% load i18n sizeformat parse_date %}
{% load url from future %}
<h3>{{snapshot.display_name }}</h3>
<h3>{% trans "Volume Snapshot Overview" %}</h3>
<div class="info row-fluid detail">
<h4>{% trans "Info" %}</h4>

View File

@@ -3,9 +3,8 @@
{% block title %}{% trans "Volume Snapshot Details" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Volume Snapshot Detail") %}
{% include "horizon/common/_page_header.html" with title=_("Volume Snapshot Details: ")|add:snapshot.display_name|default:_("Volume Snapshot Details:") %}
{% endblock page_header %}
{% block main %}
<div class="row-fluid">
<div class="span12">

View File

@@ -22,6 +22,8 @@
"""
Views for managing Images and Snapshots.
"""
from django.core.urlresolvers import reverse # noqa
from django.utils.translation import ugettext_lazy as _ # noqa
from horizon import exceptions
@@ -87,3 +89,26 @@ class IndexView(tables.MultiTableView):
class DetailView(tabs.TabView):
tab_group_class = vol_snsh_tabs.SnapshotDetailTabs
template_name = 'project/images_and_snapshots/snapshots/detail.html'
def get_context_data(self, **kwargs):
context = super(DetailView, self).get_context_data(**kwargs)
context["snapshot"] = self.get_data()
return context
def get_data(self):
if not hasattr(self, "_snapshot"):
try:
snapshot_id = self.kwargs['snapshot_id']
self._snapshot = api.cinder.volume_snapshot_get(self.request,
snapshot_id)
except Exception:
url = reverse('horizon:project:images_and_snapshots:index')
exceptions.handle(self.request,
_('Unable to retrieve snapshot details.'),
redirect=url)
return self._snapshot
def get_tabs(self, request, *args, **kwargs):
snapshot = self.get_data()
return self.tab_group_class(request, snapshot=snapshot, **kwargs)

View File

@@ -30,18 +30,16 @@ class OverviewTab(tabs.Tab):
"_detail_overview.html")
def get_context_data(self, request):
snapshot_id = self.tab_group.kwargs['snapshot_id']
try:
snapshot = cinder.volume_snapshot_get(request, snapshot_id)
snapshot = self.tab_group.kwargs['snapshot']
volume = cinder.volume_get(request, snapshot.volume_id)
volume.display_name = None
except Exception:
redirect = reverse('horizon:project:images_and_snapshots:index')
exceptions.handle(self.request,
_('Unable to retrieve snapshot details.'),
redirect=redirect)
return {'snapshot': snapshot,
'volume': volume}
return {"snapshot": snapshot,
"volume": volume}
class SnapshotDetailTabs(tabs.TabGroup):

View File

@@ -40,7 +40,7 @@ class VolumeSnapshotsViewTests(test.TestCase):
'volumesUsed': len(self.volumes.list()),
'maxTotalVolumes': 6}
quotas.tenant_limit_usages(IsA(http.HttpRequest)).\
AndReturn(usage_limit)
AndReturn(usage_limit)
self.mox.ReplayAll()
url = reverse('horizon:project:volumes:create_snapshot',
@@ -58,7 +58,7 @@ class VolumeSnapshotsViewTests(test.TestCase):
volume.id,
snapshot.display_name,
snapshot.display_description) \
.AndReturn(snapshot)
.AndReturn(snapshot)
self.mox.ReplayAll()
formData = {'method': 'CreateSnapshotForm',
@@ -102,3 +102,64 @@ class VolumeSnapshotsViewTests(test.TestCase):
self.assertIn("Scheduled deletion of Volume Snapshot: test snapshot",
[m.message for m in res.context['messages']])
@test.create_stubs({api.cinder: ('volume_snapshot_get', 'volume_get')})
def test_volume_snapshot_detail_get(self):
volume = self.volumes.first()
snapshot = self.volume_snapshots.first()
api.cinder.volume_get(IsA(http.HttpRequest), volume.id). \
AndReturn(volume)
api.cinder.volume_snapshot_get(IsA(http.HttpRequest), snapshot.id). \
AndReturn(snapshot)
self.mox.ReplayAll()
url = reverse('horizon:project:images_and_snapshots:detail',
args=[snapshot.id])
res = self.client.get(url)
self.assertContains(res,
"<h2>Volume Snapshot Details: %s</h2>" %
snapshot.display_name,
1, 200)
self.assertContains(res, "<dd>test snapshot</dd>", 1, 200)
self.assertContains(res,
"<dd>40f3fabf-3613-4f5e-90e5-6c9a08333fc3</dd>",
1,
200)
self.assertContains(res, "<dd>Available</dd>", 1, 200)
@test.create_stubs({api.cinder: ('volume_snapshot_get',)})
def test_volume_snapshot_detail_get_with_exception(self):
# Test to verify redirect if get volume snapshot fails
snapshot = self.volume_snapshots.first()
api.cinder.volume_snapshot_get(IsA(http.HttpRequest), snapshot.id).\
AndRaise(self.exceptions.cinder)
self.mox.ReplayAll()
url = reverse('horizon:project:images_and_snapshots:detail',
args=[snapshot.id])
res = self.client.get(url)
self.assertRedirectsNoFollow(res, INDEX_URL)
@test.create_stubs({api.cinder: ('volume_snapshot_get', 'volume_get')})
def test_volume_snapshot_detail_with_volume_get_exception(self):
# Test to verify redirect if get volume fails
volume = self.volumes.first()
snapshot = self.volume_snapshots.first()
api.cinder.volume_get(IsA(http.HttpRequest), volume.id). \
AndRaise(self.exceptions.cinder)
api.cinder.volume_snapshot_get(IsA(http.HttpRequest), snapshot.id). \
AndReturn(snapshot)
self.mox.ReplayAll()
url = reverse('horizon:project:images_and_snapshots:detail',
args=[snapshot.id])
res = self.client.get(url)
self.assertRedirectsNoFollow(res, INDEX_URL)

View File

@@ -1,9 +1,9 @@
{% extends 'base.html' %}
{% load i18n sizeformat %}
{% block title %}{% trans "Instance Detail" %}{% endblock %}
{% block title %}{% trans "Instance Details" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title="Instance Detail: "|add:instance.name %}
{% include "horizon/common/_page_header.html" with title=_("Instance Details: ")|add:instance.name %}
{% endblock page_header %}
{% block main %}

View File

@@ -17,12 +17,8 @@
from django.core.urlresolvers import reverse # noqa
from django.utils.translation import ugettext_lazy as _ # noqa
from horizon import exceptions
from horizon import tabs
from openstack_dashboard.api import cinder
from openstack_dashboard.api import nova
class OverviewTab(tabs.Tab):
name = _("Overview")
@@ -31,17 +27,7 @@ class OverviewTab(tabs.Tab):
"_detail_overview.html")
def get_context_data(self, request):
volume_id = self.tab_group.kwargs['volume_id']
try:
volume = cinder.volume_get(request, volume_id)
for att in volume.attachments:
att['instance'] = nova.server_get(request, att['server_id'])
except Exception:
redirect = reverse('horizon:project:volumes:index')
exceptions.handle(self.request,
_('Unable to retrieve volume details.'),
redirect=redirect)
return {'volume': volume}
return {"volume": self.tab_group.kwargs['volume']}
class VolumeDetailTabs(tabs.TabGroup):

View File

@@ -1,7 +1,7 @@
{% load i18n sizeformat parse_date %}
{% load url from future %}
<h3>{% trans "Volume Overview" %}: {{volume.display_name }}</h3>
<h3>{% trans "Volume Overview" %}</h3>
<div class="info row-fluid detail">
<h4>{% trans "Info" %}</h4>

View File

@@ -3,7 +3,7 @@
{% block title %}{% trans "Volume Details" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Volume Detail") %}
{% include "horizon/common/_page_header.html" with title=_("Volume Details: ")|add:volume.display_name|default:_("Volume Details:") %}
{% endblock page_header %}
{% block main %}

View File

@@ -32,6 +32,9 @@ from openstack_dashboard.test import helpers as test
from openstack_dashboard.usage import quotas
VOLUME_INDEX_URL = reverse('horizon:project:volumes:index')
class VolumeViewTests(test.TestCase):
@test.create_stubs({cinder: ('volume_create',
'volume_snapshot_list',
@@ -674,6 +677,8 @@ class VolumeViewTests(test.TestCase):
args=[volume.id])
res = self.client.get(url)
self.assertContains(res, "<h2>Volume Details: Volume name</h2>",
1, 200)
self.assertContains(res, "<dd>Volume name</dd>", 1, 200)
self.assertContains(res,
"<dd>41023e92-8008-4c8b-8059-7f2293ff3775</dd>",
@@ -706,3 +711,21 @@ class VolumeViewTests(test.TestCase):
self.assertEqual(res.status_code, 200)
self.assertEqual(volume.display_name, volume.id)
@test.create_stubs({cinder: ('volume_get',)})
def test_detail_view_with_exception(self):
volume = self.volumes.first()
server = self.servers.first()
volume.attachments = [{"server_id": server.id}]
cinder.volume_get(IsA(http.HttpRequest), volume.id).\
AndRaise(self.exceptions.cinder)
self.mox.ReplayAll()
url = reverse('horizon:project:volumes:detail',
args=[volume.id])
res = self.client.get(url)
self.assertRedirectsNoFollow(res, VOLUME_INDEX_URL)

View File

@@ -18,6 +18,7 @@
Views for managing volumes.
"""
from django.core.urlresolvers import reverse # noqa
from django.core.urlresolvers import reverse_lazy # noqa
from django.utils.datastructures import SortedDict # noqa
from django.utils.translation import ugettext_lazy as _ # noqa
@@ -91,6 +92,31 @@ class DetailView(tabs.TabView):
tab_group_class = project_tabs.VolumeDetailTabs
template_name = 'project/volumes/detail.html'
def get_context_data(self, **kwargs):
context = super(DetailView, self).get_context_data(**kwargs)
context["volume"] = self.get_data()
return context
def get_data(self):
if not hasattr(self, "_volume"):
try:
volume_id = self.kwargs['volume_id']
self._volume = cinder.volume_get(self.request, volume_id)
for att in self._volume.attachments:
att['instance'] = api.nova.server_get(self.request,
att['server_id'])
except Exception:
redirect = reverse('horizon:project:volumes:index')
exceptions.handle(self.request,
_('Unable to retrieve volume details.'),
redirect=redirect)
return self._volume
def get_tabs(self, request, *args, **kwargs):
volume = self.get_data()
return self.tab_group_class(request, volume=volume, **kwargs)
class CreateView(forms.ModalFormView):
form_class = project_forms.CreateForm