Merge "Fix quotas retrieval for shares and snapshots tables"

This commit is contained in:
Zuul 2018-08-07 06:22:22 +00:00 committed by Gerrit Code Review
commit 01a7b5773a
7 changed files with 73 additions and 76 deletions

View File

@ -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,))

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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,
}

View File

@ -0,0 +1,3 @@
fixes:
- |
Fixed missing "Create Share" button on the "Shares" dashboard.