diff --git a/manila_ui/dashboards/project/share_snapshots/tables.py b/manila_ui/dashboards/project/share_snapshots/tables.py index a609e3f5..287224b4 100644 --- a/manila_ui/dashboards/project/share_snapshots/tables.py +++ b/manila_ui/dashboards/project/share_snapshots/tables.py @@ -21,7 +21,6 @@ from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ungettext_lazy from horizon import exceptions from horizon import tables -from openstack_dashboard.usage import quotas from manila_ui.api import manila @@ -57,8 +56,13 @@ class CreateShareSnapshot(tables.LinkAction): return {"project_id": project_id} def allowed(self, request, share=None): - usages = quotas.tenant_quota_usages(request) - if usages['snapshots']['available'] <= 0: + usages = manila.tenant_absolute_limits(request) + snapshots_allowed = (usages['maxTotalShareSnapshots'] > + usages['totalShareSnapshotsUsed'] and + usages['maxTotalSnapshotGigabytes'] > + usages['totalSnapshotGigabytesUsed']) + + if not snapshots_allowed: if "disabled" not in self.classes: self.classes = [c for c in self.classes] + ['disabled'] self.verbose_name = string_concat( @@ -145,6 +149,7 @@ class EditShareSnapshot(tables.LinkAction): class ShareSnapshotShareNameColumn(tables.Column): + def get_link_url(self, snapshot): return reverse(self.link, args=(snapshot.share_id,)) diff --git a/manila_ui/dashboards/project/shares/tables.py b/manila_ui/dashboards/project/shares/tables.py index e75a6225..b3b571ed 100644 --- a/manila_ui/dashboards/project/shares/tables.py +++ b/manila_ui/dashboards/project/shares/tables.py @@ -21,7 +21,6 @@ from django.utils.translation import ungettext_lazy from horizon import exceptions from horizon import messages from horizon import tables -from openstack_dashboard.usage import quotas from manila_ui.api import manila from manila_ui.dashboards.project.share_snapshots import tables as ss_tables @@ -87,8 +86,13 @@ class CreateShare(tables.LinkAction): policy_rules = (("share", "share:create"),) def allowed(self, request, share=None): - usages = quotas.tenant_quota_usages(request) - if usages['shares']['available'] <= 0: + usages = manila.tenant_absolute_limits(request) + shares_allowed = (usages['maxTotalShares'] > + usages['totalSharesUsed'] and + usages['maxTotalShareGigabytes'] > + usages['totalShareGigabytesUsed']) + + if not shares_allowed: if "disabled" not in self.classes: self.classes = [c for c in self.classes] + ['disabled'] self.verbose_name = string_concat(self.verbose_name, ' ', @@ -97,6 +101,7 @@ class CreateShare(tables.LinkAction): self.verbose_name = _("Create Share") classes = [c for c in self.classes if c != "disabled"] self.classes = classes + return True diff --git a/manila_ui/tests/dashboards/admin/shares/tests.py b/manila_ui/tests/dashboards/admin/shares/tests.py index f834c66d..103ff04b 100644 --- a/manila_ui/tests/dashboards/admin/shares/tests.py +++ b/manila_ui/tests/dashboards/admin/shares/tests.py @@ -18,7 +18,6 @@ from django.urls import reverse import mock from openstack_dashboard.api import keystone as api_keystone from openstack_dashboard.api import neutron as api_neutron -from openstack_dashboard.usage import quotas from manila_ui.api import manila as api_manila from manila_ui.dashboards.admin import utils @@ -53,9 +52,6 @@ class SharesTests(test.BaseAdminViewTests): api_manila, "share_snapshot_list", mock.Mock(return_value=snaps)) self.mock_object( api_neutron, "is_service_enabled", mock.Mock(return_value=[True])) - self.mock_object( - quotas, "tenant_quota_usages", - mock.Mock(return_value=test_data.quota_usage)) res = self.client.get(INDEX_URL) diff --git a/manila_ui/tests/dashboards/project/share_snapshots/test_tables.py b/manila_ui/tests/dashboards/project/share_snapshots/test_tables.py index a82ab47c..25780ff4 100644 --- a/manila_ui/tests/dashboards/project/share_snapshots/test_tables.py +++ b/manila_ui/tests/dashboards/project/share_snapshots/test_tables.py @@ -17,7 +17,9 @@ import ddt from django.core.handlers import wsgi import mock +from manila_ui.api import manila as api_manila from manila_ui.dashboards.project.share_snapshots import tables +from manila_ui.tests.dashboards.project import test_data from manila_ui.tests import helpers as base @@ -36,23 +38,38 @@ class CreateSnapshotTests(base.APITestCase): return type("Share", (object, ), kwargs)() @ddt.data(True, False) - @mock.patch('openstack_dashboard.usage.quotas.tenant_quota_usages') - def test_allowed_with_snapshot_support_attr(self, snapshot_support, - mock_quota_usages): - mock_quota_usages.return_value = {'snapshots': {'available': 1}} + def test_allowed_with_snapshot_support_attr(self, snapshot_support): + self.mock_object( + api_manila, "tenant_absolute_limits", + mock.Mock(return_value=test_data.limits)) + share = self._get_fake_share(snapshot_support=snapshot_support) result = self.create_snapshot.allowed(self.request, share) self.assertEqual(snapshot_support, result) - mock_quota_usages.assert_called_once_with(self.request) - @mock.patch('openstack_dashboard.usage.quotas.tenant_quota_usages') - def test_allowed_no_snapshot_support_attr(self, mock_quota_usages): - mock_quota_usages.return_value = {'snapshots': {'available': 1}} + def test_allowed_no_snapshot_support_attr(self): + self.mock_object( + api_manila, "tenant_absolute_limits", + mock.Mock(return_value=test_data.limits)) share = self._get_fake_share() result = self.create_snapshot.allowed(self.request, share) + self.assertNotIn('disabled', self.create_snapshot.classes) + + self.assertTrue(result) + + def test_allowed_no_snapshot_support_attr_no_quota(self): + self.mock_object( + api_manila, "tenant_absolute_limits", + mock.Mock(return_value=test_data.limits_negative)) + + share = self._get_fake_share() + + result = self.create_snapshot.allowed(self.request, share) + + self.assertIn('disabled', self.create_snapshot.classes) + self.assertTrue(result) - mock_quota_usages.assert_called_once_with(self.request) diff --git a/manila_ui/tests/dashboards/project/shares/tests.py b/manila_ui/tests/dashboards/project/shares/tests.py index eacb8b30..5b4f8507 100644 --- a/manila_ui/tests/dashboards/project/shares/tests.py +++ b/manila_ui/tests/dashboards/project/shares/tests.py @@ -18,7 +18,6 @@ from django.urls import reverse from horizon import messages as horizon_messages import mock from openstack_dashboard.api import neutron -from openstack_dashboard.usage import quotas import six from manila_ui.api import manila as api_manila @@ -55,6 +54,9 @@ class ShareViewTests(test.APITestCase): self.mock_object(horizon_messages, "success") FAKE_ENVIRON = {'REQUEST_METHOD': 'GET', 'wsgi.input': 'fake_input'} self.request = wsgi.WSGIRequest(FAKE_ENVIRON) + self.mock_object( + api_manila, "tenant_absolute_limits", + mock.Mock(return_value=test_data.limits)) def test_index(self): snaps = [test_data.snapshot, test_data.snapshot_mount_support] @@ -70,10 +72,10 @@ class ShareViewTests(test.APITestCase): api_manila, "share_network_list", mock.Mock(return_value=share_networks)) self.mock_object( - neutron, "is_service_enabled", mock.Mock(return_value=[True])) + api_manila, "tenant_absolute_limits", + mock.Mock(return_value=test_data.limits)) self.mock_object( - quotas, "tenant_quota_usages", - mock.Mock(return_value=test_data.quota_usage)) + neutron, "is_service_enabled", mock.Mock(return_value=[True])) res = self.client.get(INDEX_URL) @@ -83,6 +85,7 @@ class ShareViewTests(test.APITestCase): mock.ANY, detailed=True) api_manila.share_list.assert_called_with(mock.ANY) api_manila.share_network_list.assert_called_with(mock.ANY) + api_manila.tenant_absolute_limits.assert_called_with(mock.ANY) @mock.patch.object(api_manila, 'availability_zone_list') def test_create_share(self, az_list): @@ -354,14 +357,7 @@ class ShareViewTests(test.APITestCase): def test_extend_share_get(self): share = test_data.share - usage_limit = { - 'maxTotalShareGigabytes': 250, - 'totalShareGigabytesUsed': 20, - } url = reverse('horizon:project:shares:extend', args=[share.id]) - self.mock_object( - api_manila, "tenant_absolute_limits", - mock.Mock(return_value=usage_limit)) self.mock_object( neutron, "is_service_enabled", mock.Mock(return_value=[True])) @@ -373,15 +369,8 @@ class ShareViewTests(test.APITestCase): def test_extend_share_open_form_successfully(self): self.share.size = 5 - usage_limit = { - 'maxTotalShareGigabytes': self.share.size + 50, - 'totalShareGigabytesUsed': self.share.size, - } url = reverse('horizon:project:shares:extend', args=[self.share.id]) self.mock_object(api_manila, "share_extend") - self.mock_object( - api_manila, 'tenant_absolute_limits', - mock.Mock(return_value=usage_limit)) response = self.client.get(url) @@ -392,15 +381,8 @@ class ShareViewTests(test.APITestCase): api_manila.tenant_absolute_limits.assert_called_once_with(mock.ANY) def test_extend_share_get_with_api_exception(self): - usage_limit = { - 'maxTotalShareGigabytes': self.share.size + 50, - 'totalShareGigabytesUsed': self.share.size, - } url = reverse('horizon:project:shares:extend', args=[self.share.id]) self.mock_object(api_manila, "share_extend") - self.mock_object( - api_manila, 'tenant_absolute_limits', - mock.Mock(return_value=usage_limit)) self.mock_object( api_manila, "share_get", mock.Mock(return_value=Exception('Fake share NotFound exception'))) @@ -421,6 +403,7 @@ class ShareViewTests(test.APITestCase): usage_limit = { 'maxTotalShareGigabytes': self.share.size + 50, 'totalShareGigabytesUsed': self.share.size, + } url = reverse('horizon:project:shares:extend', args=[self.share.id]) self.mock_object(api_manila, "share_extend") @@ -443,11 +426,11 @@ class ShareViewTests(test.APITestCase): def test_extend_share_post_with_invalid_value(self, new_size): self.share.size = 5 form_data = {'new_size': new_size} + url = reverse('horizon:project:shares:extend', args=[self.share.id]) usage_limit = { 'maxTotalShareGigabytes': self.share.size + 50, 'totalShareGigabytesUsed': self.share.size, } - url = reverse('horizon:project:shares:extend', args=[self.share.id]) self.mock_object(api_manila, "share_extend") self.mock_object( api_manila, 'tenant_absolute_limits', @@ -464,17 +447,10 @@ class ShareViewTests(test.APITestCase): def test_extend_share_post_with_api_exception(self): self.share.size = 5 form_data = {'new_size': 30} - usage_limit = { - 'maxTotalShareGigabytes': self.share.size + 50, - 'totalShareGigabytesUsed': self.share.size, - } url = reverse('horizon:project:shares:extend', args=[self.share.id]) self.mock_object( api_manila, "share_extend", mock.Mock(return_value=Exception('Fake API exception'))) - self.mock_object( - api_manila, 'tenant_absolute_limits', - mock.Mock(return_value=usage_limit)) response = self.client.post(url, form_data) diff --git a/manila_ui/tests/dashboards/project/test_data.py b/manila_ui/tests/dashboards/project/test_data.py index 8da54517..a12c6a58 100644 --- a/manila_ui/tests/dashboards/project/test_data.py +++ b/manila_ui/tests/dashboards/project/test_data.py @@ -13,7 +13,6 @@ # under the License. import collections -from manilaclient.v2 import quotas from manilaclient.v2 import security_services from manilaclient.v2 import share_export_locations from manilaclient.v2 import share_group_snapshots @@ -28,9 +27,6 @@ from manilaclient.v2 import share_snapshots from manilaclient.v2 import share_types from manilaclient.v2 import shares -from openstack_dashboard import api -from openstack_dashboard.usage import quotas as usage_quotas - class FakeAPIClient(object): client = "fake_client" @@ -474,24 +470,23 @@ share_group_snapshot_nameless = share_group_snapshots.ShareGroupSnapshot( 'members': []} ) -# Quota Sets -quota_data = dict(shares='1', - share_snapshots='1', - share_gigabytes='1000') -quota = quotas.QuotaSet(quotas.QuotaSetManager(FakeAPIClient), quota_data) - -# Quota Usages -quota_usage_data = {'gigabytes': {'used': 0, 'quota': 1000}, - 'shares': {'used': 0, 'quota': 10}, - 'snapshots': {'used': 0, 'quota': 10}, - 'share_networks': {'used': 0, 'quota': 10}} -quota_usage = usage_quotas.QuotaUsage() -for k, v in quota_usage_data.items(): - quota_usage.add_quota(api.base.Quota(k, v['quota'])) - quota_usage.tally(k, v['used']) - # Manila Limits -limits = {"absolute": {"totalSharesUsed": 1, - "totalShareGigabytesUsed": 5, - "maxTotalShareGigabytes": 1000, - "maxTotalShares": 10}} +limits = {"totalSharesUsed": 1, + "totalShareSnapshotsUsed": 1, + "totalShareGigabytesUsed": 500, + "totalSnapshotGigabytesUsed": 500, + "maxTotalShares": 10, + "maxTotalShareSnapshots": 10, + "maxTotalShareGigabytes": 1000, + "maxTotalSnapshotGigabytes": 1000, + } + +limits_negative = {"totalSharesUsed": 10, + "totalShareSnapshotsUsed": 10, + "totalShareGigabytesUsed": 1000, + "totalSnapshotGigabytesUsed": 1000, + "maxTotalShares": 10, + "maxTotalShareSnapshots": 10, + "maxTotalShareGigabytes": 1000, + "maxTotalSnapshotGigabytes": 1000, + } diff --git a/releasenotes/notes/bug-1783232-fix-quotas-retrieval-for-shares-and-snapshots-tables-63a1fc877029eac8.yaml b/releasenotes/notes/bug-1783232-fix-quotas-retrieval-for-shares-and-snapshots-tables-63a1fc877029eac8.yaml new file mode 100644 index 00000000..08d4f17d --- /dev/null +++ b/releasenotes/notes/bug-1783232-fix-quotas-retrieval-for-shares-and-snapshots-tables-63a1fc877029eac8.yaml @@ -0,0 +1,3 @@ +fixes: + - | + Fixed missing "Create Share" button on the "Shares" dashboard.