diff --git a/openstack_dashboard/dashboards/admin/snapshots/tables.py b/openstack_dashboard/dashboards/admin/snapshots/tables.py index 5ba0f6645d..61be0c1fa7 100644 --- a/openstack_dashboard/dashboards/admin/snapshots/tables.py +++ b/openstack_dashboard/dashboards/admin/snapshots/tables.py @@ -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): diff --git a/openstack_dashboard/dashboards/admin/snapshots/views.py b/openstack_dashboard/dashboards/admin/snapshots/views.py index cdf5c8381a..9e4086a28e 100644 --- a/openstack_dashboard/dashboards/admin/snapshots/views.py +++ b/openstack_dashboard/dashboards/admin/snapshots/views.py @@ -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 diff --git a/openstack_dashboard/dashboards/admin/volumes/tables.py b/openstack_dashboard/dashboards/admin/volumes/tables.py index a06740c0ed..5f8804c0fc 100644 --- a/openstack_dashboard/dashboards/admin/volumes/tables.py +++ b/openstack_dashboard/dashboards/admin/volumes/tables.py @@ -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',) diff --git a/openstack_dashboard/dashboards/admin/volumes/tabs.py b/openstack_dashboard/dashboards/admin/volumes/tabs.py index b4bddd1328..7535dbd615 100644 --- a/openstack_dashboard/dashboards/admin/volumes/tabs.py +++ b/openstack_dashboard/dashboards/admin/volumes/tabs.py @@ -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', diff --git a/openstack_dashboard/dashboards/admin/volumes/templates/volumes/_detail_overview.html b/openstack_dashboard/dashboards/admin/volumes/templates/volumes/_detail_overview.html new file mode 100644 index 0000000000..d8e4155d04 --- /dev/null +++ b/openstack_dashboard/dashboards/admin/volumes/templates/volumes/_detail_overview.html @@ -0,0 +1,126 @@ +{% load i18n sizeformat parse_date %} + +
+
+
{% trans "Name" %}
+
{{ volume.name }}
+
{% trans "ID" %}
+
{{ volume.id }}
+ {% if volume.description %} +
{% trans "Description" %}
+
{{ volume.description }}
+ {% endif %} +
{% trans "Project ID" %}
+
{{ volume.tenant_id|default:_("-") }}
+
{% trans "Status" %}
+
{{ volume.status_label|capfirst }}
+
{% trans "Group" %}
+ {% if group %} +
{{ group.name_or_id }}
+ {% else %} +
{% trans "-" %}
+ {% endif %} +
+ +

{% trans "Specs" %}

+
+
+
{% trans "Size" %}
+
{{ volume.size }} {% trans "GiB" %}
+ {% if volume.volume_type %} +
{% trans "Type" %}
+
{{ volume.volume_type }}
+ {% endif %} + {% if volume.availabilty_zone %} +
{% trans "Availability zone" %}
+
{{ volume.availability_zone }}
+ {% endif %} +
{% trans "Bootable" %}
+
{{ volume.is_bootable|yesno|capfirst }}
+
{% trans "Encrypted" %}
+ {% if volume.encrypted %} +
{% trans "Yes" %}
+ {% else %} +
{% trans "No" %}
+ {% endif %} +
{% trans "Created" context "Created time" %}
+
{{ volume.created_at|parse_date }}
+
+ +

{% trans "Attachments" %}

+
+
+ {% for attachment in volume.attachments %} +
{% trans "Attached To" %}
+
+ {% url detail_url.instance attachment.server_id as instance_url %} + {% blocktrans trimmed with instance_name=attachment.instance.name device=attachment.device %} + {{ instance_name }} on {{ device }} + {% endblocktrans %} +
+ {% empty %} +
{% trans "Attached To" %}
+
{% trans "Not attached" %}
+ {% endfor %} +
+ +{% if volume.volume_image_metadata %} +

{% trans "Volume Source" %}

+
+
+
{% trans "Image" %}
+
+ {% url detail_url.image volume.volume_image_metadata.image_id as image_url %} + {{ volume.volume_image_metadata.image_name }} +
+
+{% endif %} + +

{% trans "Metadata" %}

+
+
+ {% if volume.metadata.items %} + {% for key, value in volume.metadata.items %} +
{{ key }}
+
{{ value }}
+ {% endfor %} + {% else %} +
{% trans "None" %}
+ {% endif %} +
+ +{% if volume.transfer %} +

{% trans "Volume Transfer" %}

+
+
+
{% trans "ID" %}
+
{{ volume.transfer.id }}
+
+
+
{% trans "Name" %}
+
{{ volume.transfer.name }}
+
+
+
{% trans "Created" context "Created time" %}
+
{{ volume.transfer.created_at|parse_date }}
+
+{% endif %} + +{% if volume.messages %} +

{% trans "Messages" %}

+
+
+ {% for m in volume.messages %} +
+ {{ m.user_message }} +
+ {% endfor %} +
+{% endif %} +
diff --git a/openstack_dashboard/dashboards/admin/volumes/views.py b/openstack_dashboard/dashboards/admin/volumes/views.py index 1779aa49b6..6b4ff822d9 100644 --- a/openstack_dashboard/dashboards/admin/volumes/views.py +++ b/openstack_dashboard/dashboards/admin/volumes/views.py @@ -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)) diff --git a/openstack_dashboard/dashboards/project/volumes/tests.py b/openstack_dashboard/dashboards/project/volumes/tests.py index 8bbcabcf3e..01e459074f 100644 --- a/openstack_dashboard/dashboards/project/volumes/tests.py +++ b/openstack_dashboard/dashboards/project/volumes/tests.py @@ -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()) diff --git a/openstack_dashboard/dashboards/project/volumes/views.py b/openstack_dashboard/dashboards/project/volumes/views.py index 5c68a9e3eb..abd95f7d04 100644 --- a/openstack_dashboard/dashboards/project/volumes/views.py +++ b/openstack_dashboard/dashboards/project/volumes/views.py @@ -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 = {}