Merge "Add Group and Group Snapshot colunm"
This commit is contained in:
commit
4c82dda11c
|
@ -63,6 +63,10 @@ class VolumeSnapshotsTable(volumes_tables.VolumesTableBase):
|
|||
link="horizon:admin:volumes:detail")
|
||||
host = tables.Column("host_name", verbose_name=_("Host"))
|
||||
tenant = tables.Column("tenant_name", verbose_name=_("Project"))
|
||||
group_snapshot = snapshots_tables.GroupSnapshotNameColumn(
|
||||
"name",
|
||||
verbose_name=_("Group Snapshot"),
|
||||
link="horizon:admin:vg_snapshots:detail")
|
||||
|
||||
class Meta(object):
|
||||
name = "volume_snapshots"
|
||||
|
@ -77,7 +81,7 @@ class VolumeSnapshotsTable(volumes_tables.VolumesTableBase):
|
|||
row_class = UpdateRow
|
||||
status_columns = ("status",)
|
||||
columns = ('tenant', 'host', 'name', 'description', 'size', 'status',
|
||||
'volume_name',)
|
||||
'group_snapshot', 'volume_name',)
|
||||
|
||||
|
||||
class VolumeDetailsSnapshotsTable(VolumeSnapshotsTable):
|
||||
|
|
|
@ -37,6 +37,7 @@ class SnapshotsView(tables.PagedTableMixin, tables.DataTableView):
|
|||
page_title = _("Volume Snapshots")
|
||||
|
||||
def get_data(self):
|
||||
needs_gs = False
|
||||
if cinder.is_volume_service_enabled(self.request):
|
||||
try:
|
||||
marker, sort_dir = self._get_marker()
|
||||
|
@ -54,6 +55,18 @@ class SnapshotsView(tables.PagedTableMixin, tables.DataTableView):
|
|||
exceptions.handle(self.request, _("Unable to retrieve "
|
||||
"volume snapshots."))
|
||||
|
||||
needs_gs = any(getattr(snapshot, 'group_snapshot_id', None)
|
||||
for snapshot in snapshots)
|
||||
if needs_gs:
|
||||
try:
|
||||
group_snapshots = cinder.group_snapshot_list(
|
||||
self.request, search_opts={'all_tenants': True})
|
||||
group_snapshots = dict((gs.id, gs) for gs
|
||||
in group_snapshots)
|
||||
except Exception:
|
||||
group_snapshots = {}
|
||||
exceptions.handle(self.request,
|
||||
_("Unable to retrieve group snapshots."))
|
||||
# Gather our tenants to correlate against volume IDs
|
||||
try:
|
||||
tenants, has_more = keystone.tenant_list(self.request)
|
||||
|
@ -66,6 +79,12 @@ class SnapshotsView(tables.PagedTableMixin, tables.DataTableView):
|
|||
tenant_dict = dict((t.id, t) for t in tenants)
|
||||
for snapshot in snapshots:
|
||||
volume = volumes.get(snapshot.volume_id)
|
||||
if needs_gs:
|
||||
group_snapshot = group_snapshots.get(
|
||||
snapshot.group_snapshot_id)
|
||||
snapshot.group_snapshot = group_snapshot
|
||||
else:
|
||||
snapshot.group_snapshot = None
|
||||
tenant_id = snapshot.project_id
|
||||
tenant = tenant_dict.get(tenant_id, None)
|
||||
snapshot._volume = volume
|
||||
|
|
|
@ -105,6 +105,10 @@ class VolumesTable(volumes_tables.VolumesTable):
|
|||
host = tables.Column("os-vol-host-attr:host", verbose_name=_("Host"))
|
||||
tenant = tables.Column(lambda obj: getattr(obj, 'tenant_name', None),
|
||||
verbose_name=_("Project"))
|
||||
group = volumes_tables.GroupNameColumn(
|
||||
"name",
|
||||
verbose_name=_("Group"),
|
||||
link="horizon:admin:volume_groups:detail")
|
||||
|
||||
class Meta(object):
|
||||
name = "volumes"
|
||||
|
@ -119,5 +123,5 @@ class VolumesTable(volumes_tables.VolumesTable):
|
|||
UnmanageVolumeAction,
|
||||
MigrateVolume,
|
||||
volumes_tables.UpdateMetadata)
|
||||
columns = ('tenant', 'host', 'name', 'size', 'status', 'volume_type',
|
||||
'attachments', 'bootable', 'encryption',)
|
||||
columns = ('tenant', 'host', 'name', 'size', 'status', 'group',
|
||||
'volume_type', 'attachments', 'bootable', 'encryption',)
|
||||
|
|
|
@ -15,10 +15,13 @@ from openstack_dashboard.dashboards.project.volumes import tabs as project_tabs
|
|||
|
||||
|
||||
class OverviewTab(project_tabs.OverviewTab):
|
||||
template_name = ("admin/volumes/_detail_overview.html")
|
||||
|
||||
def get_context_data(self, request):
|
||||
volume = self.tab_group.kwargs['volume']
|
||||
return {
|
||||
'volume': self.tab_group.kwargs['volume'],
|
||||
'volume': volume,
|
||||
'group': volume.group,
|
||||
'detail_url': {
|
||||
'instance': 'horizon:admin:instances:detail',
|
||||
'image': 'horizon:admin:images:detail',
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
{% load i18n sizeformat parse_date %}
|
||||
|
||||
<div class="detail">
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "Name" %}</dt>
|
||||
<dd data-display="{{ volume.name|default:volume.id }}" class="word-wrap">{{ volume.name }}</dd>
|
||||
<dt>{% trans "ID" %}</dt>
|
||||
<dd>{{ volume.id }}</dd>
|
||||
{% if volume.description %}
|
||||
<dt>{% trans "Description" %}</dt>
|
||||
<dd>{{ volume.description }}</dd>
|
||||
{% endif %}
|
||||
<dt>{% trans "Project ID" %}</dt>
|
||||
<dd>{{ volume.tenant_id|default:_("-") }}</dd>
|
||||
<dt>{% trans "Status" %}</dt>
|
||||
<dd>{{ volume.status_label|capfirst }}</dd>
|
||||
<dt>{% trans "Group" %}</dt>
|
||||
{% if group %}
|
||||
<dd><a href="{% url 'horizon:admin:volume_groups:detail' volume.group_id %}">{{ group.name_or_id }}</a></dd>
|
||||
{% else %}
|
||||
<dd>{% trans "-" %}</dd>
|
||||
{% endif %}
|
||||
</dl>
|
||||
|
||||
<h4>{% trans "Specs" %}</h4>
|
||||
<hr class="header_rule">
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "Size" %}</dt>
|
||||
<dd>{{ volume.size }} {% trans "GiB" %}</dd>
|
||||
{% if volume.volume_type %}
|
||||
<dt>{% trans "Type" %}</dt>
|
||||
<dd>{{ volume.volume_type }}</dd>
|
||||
{% endif %}
|
||||
{% if volume.availabilty_zone %}
|
||||
<dt>{% trans "Availability zone" %}</dt>
|
||||
<dd>{{ volume.availability_zone }}</dd>
|
||||
{% endif %}
|
||||
<dt>{% trans "Bootable" %}</dt>
|
||||
<dd>{{ volume.is_bootable|yesno|capfirst }}</dd>
|
||||
<dt>{% trans "Encrypted" %}</dt>
|
||||
{% if volume.encrypted %}
|
||||
<dd><a href="{% url detail_url.encryption volume.id %}">{% trans "Yes" %}</a></dd>
|
||||
{% else %}
|
||||
<dd>{% trans "No" %}</dd>
|
||||
{% endif %}
|
||||
<dt>{% trans "Created" context "Created time" %}</dt>
|
||||
<dd>{{ volume.created_at|parse_date }}</dd>
|
||||
</dl>
|
||||
|
||||
<h4>{% trans "Attachments" %}</h4>
|
||||
<hr class="header_rule">
|
||||
<dl class="dl-horizontal">
|
||||
{% for attachment in volume.attachments %}
|
||||
<dt>{% trans "Attached To" %}</dt>
|
||||
<dd class="word-wrap">
|
||||
{% url detail_url.instance attachment.server_id as instance_url %}
|
||||
{% blocktrans trimmed with instance_name=attachment.instance.name device=attachment.device %}
|
||||
<a href="{{ instance_url }}">{{ instance_name }}</a> on {{ device }}
|
||||
{% endblocktrans %}
|
||||
</dd>
|
||||
{% empty %}
|
||||
<dt>{% trans "Attached To" %}</dt>
|
||||
<dd><em>{% trans "Not attached" %}</em></dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
|
||||
{% if volume.volume_image_metadata %}
|
||||
<h4>{% trans "Volume Source" %}</h4>
|
||||
<hr class="header_rule">
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "Image" %}</dt>
|
||||
<dd class="word-wrap">
|
||||
{% url detail_url.image volume.volume_image_metadata.image_id as image_url %}
|
||||
<a href="{{ image_url }}">{{ volume.volume_image_metadata.image_name }}</a>
|
||||
</dd>
|
||||
</dl>
|
||||
{% endif %}
|
||||
|
||||
<h4>{% trans "Metadata" %}</h4>
|
||||
<hr class="header_rule">
|
||||
<dl class="dl-horizontal">
|
||||
{% if volume.metadata.items %}
|
||||
{% for key, value in volume.metadata.items %}
|
||||
<dt>{{ key }}</dt>
|
||||
<dd>{{ value }}</dd>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<dd>{% trans "None" %}</dd>
|
||||
{% endif %}
|
||||
</dl>
|
||||
|
||||
{% if volume.transfer %}
|
||||
<h4>{% trans "Volume Transfer" %}</h4>
|
||||
<hr class="header_rule">
|
||||
<dl>
|
||||
<dt>{% trans "ID" %}</dt>
|
||||
<dd>{{ volume.transfer.id }}</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>{% trans "Name" %}</dt>
|
||||
<dd class="word-wrap">{{ volume.transfer.name }}</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>{% trans "Created" context "Created time" %}</dt>
|
||||
<dd>{{ volume.transfer.created_at|parse_date }}</dd>
|
||||
</dl>
|
||||
{% endif %}
|
||||
|
||||
{% if volume.messages %}
|
||||
<h4>{% trans "Messages" %}</h4>
|
||||
<hr class="header_rule">
|
||||
<div>
|
||||
{% for m in volume.messages %}
|
||||
<div class="alert
|
||||
{% if m.message_level == 'ERROR' %}alert-danger
|
||||
{% elif m.message_level == 'WARNING' %}alert-warning
|
||||
{% elif m.message_level == 'INFO' %}alert-info
|
||||
{% else %}alert-success
|
||||
{% endif %}
|
||||
">
|
||||
{{ m.user_message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
|
@ -100,6 +100,8 @@ class VolumesView(tables.PagedTableMixin, volumes_views.VolumeTableMixIn,
|
|||
|
||||
def _task_get_volumes():
|
||||
volumes.extend(self._get_volumes(search_opts=filters))
|
||||
# update group name for volumes
|
||||
self._get_groups(volumes, search_opts={'all_tenants': True})
|
||||
attached_instance_ids.extend(
|
||||
self._get_attached_instance_ids(volumes))
|
||||
|
||||
|
|
|
@ -79,7 +79,8 @@ class VolumeIndexViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
|
|||
self.mock_volume_snapshot_list.assert_called_once()
|
||||
|
||||
if with_groups:
|
||||
self.mock_group_list.assert_called_once_with(test.IsHttpRequest())
|
||||
self.mock_group_list.assert_called_once_with(test.IsHttpRequest(),
|
||||
search_opts=None)
|
||||
|
||||
self.mock_volume_backup_supported.assert_called_with(
|
||||
test.IsHttpRequest())
|
||||
|
|
|
@ -104,13 +104,14 @@ class VolumeTableMixIn(object):
|
|||
attached_instance_ids.append(server_id)
|
||||
return attached_instance_ids
|
||||
|
||||
def _get_groups(self, volumes):
|
||||
def _get_groups(self, volumes, search_opts=None):
|
||||
needs_group = False
|
||||
if volumes and hasattr(volumes[0], 'group_id'):
|
||||
needs_group = True
|
||||
if needs_group:
|
||||
try:
|
||||
groups_list = cinder.group_list(self.request)
|
||||
groups_list = cinder.group_list(self.request,
|
||||
search_opts=search_opts)
|
||||
groups = dict((g.id, g) for g in groups_list)
|
||||
except Exception:
|
||||
groups = {}
|
||||
|
|
Loading…
Reference in New Issue