quotas for snapshot
This commit is contained in:
parent
6026fc0244
commit
d20f8e92ab
|
@ -972,19 +972,16 @@ def share_snapshot_create(context, values):
|
||||||
|
|
||||||
@require_admin_context
|
@require_admin_context
|
||||||
def snapshot_data_get_for_project(context, project_id, session=None):
|
def snapshot_data_get_for_project(context, project_id, session=None):
|
||||||
# TODO(yportnova): Uncomment when snapshot size implemented
|
query = model_query(context,
|
||||||
raise NotImplementedError()
|
func.count(models.ShareSnapshot.id),
|
||||||
#
|
func.sum(models.ShareSnapshot.size),
|
||||||
# query = model_query(context,
|
read_deleted="no",
|
||||||
# func.count(models.ShareSnapshot.id),
|
session=session).\
|
||||||
# func.sum(models.ShareSnapshot.size),
|
filter_by(project_id=project_id)
|
||||||
# read_deleted="no",
|
|
||||||
# session=session).\
|
result = query.first()
|
||||||
# filter_by(project_id=project_id)
|
|
||||||
#
|
return (result[0] or 0, result[1] or 0)
|
||||||
# result = query.first()
|
|
||||||
#
|
|
||||||
# return (result[0] or 0, result[1] or 0)
|
|
||||||
|
|
||||||
|
|
||||||
@require_context
|
@require_context
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
"""Quotas for volumes."""
|
"""Quotas for shares."""
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
@ -775,10 +775,10 @@ class QuotaEngine(object):
|
||||||
|
|
||||||
|
|
||||||
def _sync_shares(context, project_id, session):
|
def _sync_shares(context, project_id, session):
|
||||||
(volumes, gigs) = db.share_data_get_for_project(context,
|
(shares, gigs) = db.share_data_get_for_project(context,
|
||||||
project_id,
|
project_id,
|
||||||
session=session)
|
session=session)
|
||||||
return {'volumes': volumes}
|
return {'shares': shares}
|
||||||
|
|
||||||
|
|
||||||
def _sync_snapshots(context, project_id, session):
|
def _sync_snapshots(context, project_id, session):
|
||||||
|
@ -790,17 +790,15 @@ def _sync_snapshots(context, project_id, session):
|
||||||
|
|
||||||
def _sync_gigabytes(context, project_id, session):
|
def _sync_gigabytes(context, project_id, session):
|
||||||
(_junk, share_gigs) = db.share_data_get_for_project(context,
|
(_junk, share_gigs) = db.share_data_get_for_project(context,
|
||||||
project_id,
|
project_id,
|
||||||
session=session)
|
session=session)
|
||||||
if FLAGS.no_snapshot_gb_quota:
|
if FLAGS.no_snapshot_gb_quota:
|
||||||
return {'gigabytes': share_gigs}
|
return {'gigabytes': share_gigs}
|
||||||
|
|
||||||
# TODO(yportnova): Uncomment when Snapshot size is implemented
|
(_junk, snap_gigs) = db.snapshot_data_get_for_project(context,
|
||||||
# (_junk, snap_gigs) = db.snapshot_data_get_for_project(context,
|
project_id,
|
||||||
# project_id,
|
session=session)
|
||||||
# session=session)
|
return {'gigabytes': share_gigs + snap_gigs}
|
||||||
# return {'gigabytes': share_gigs + snap_gigs}
|
|
||||||
return {'gigabytes': share_gigs}
|
|
||||||
|
|
||||||
|
|
||||||
QUOTAS = QuotaEngine()
|
QUOTAS = QuotaEngine()
|
||||||
|
@ -808,8 +806,7 @@ QUOTAS = QuotaEngine()
|
||||||
|
|
||||||
resources = [
|
resources = [
|
||||||
ReservableResource('shares', _sync_shares, 'quota_shares'),
|
ReservableResource('shares', _sync_shares, 'quota_shares'),
|
||||||
# TODO(yportnova): Uncomment when Snapshot size is implemented
|
ReservableResource('snapshots', _sync_snapshots, 'quota_snapshots'),
|
||||||
# ReservableResource('snapshots', _sync_snapshots, 'quota_snapshots'),
|
|
||||||
ReservableResource('gigabytes', _sync_gigabytes, 'quota_gigabytes'), ]
|
ReservableResource('gigabytes', _sync_gigabytes, 'quota_gigabytes'), ]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -227,6 +227,35 @@ class API(base.Base):
|
||||||
msg = _("must be available")
|
msg = _("must be available")
|
||||||
raise exception.InvalidShare(reason=msg)
|
raise exception.InvalidShare(reason=msg)
|
||||||
|
|
||||||
|
size = share['size']
|
||||||
|
|
||||||
|
try:
|
||||||
|
reservations = QUOTAS.reserve(context, snapshots=1, gigabytes=size)
|
||||||
|
except exception.OverQuota as e:
|
||||||
|
overs = e.kwargs['overs']
|
||||||
|
usages = e.kwargs['usages']
|
||||||
|
quotas = e.kwargs['quotas']
|
||||||
|
|
||||||
|
def _consumed(name):
|
||||||
|
return (usages[name]['reserved'] + usages[name]['in_use'])
|
||||||
|
|
||||||
|
if 'gigabytes' in overs:
|
||||||
|
msg = _("Quota exceeded for %(s_pid)s, tried to create "
|
||||||
|
"%(s_size)sG snapshot (%(d_consumed)dG of %(d_quota)dG "
|
||||||
|
"already consumed)")
|
||||||
|
LOG.warn(msg % {'s_pid': context.project_id,
|
||||||
|
's_size': size,
|
||||||
|
'd_consumed': _consumed('gigabytes'),
|
||||||
|
'd_quota': quotas['gigabytes']})
|
||||||
|
raise exception.ShareSizeExceedsAvailableQuota()
|
||||||
|
elif 'snapshots' in overs:
|
||||||
|
msg = _("Quota exceeded for %(s_pid)s, tried to create "
|
||||||
|
"snapshot (%(d_consumed)d snapshots "
|
||||||
|
"already consumed)")
|
||||||
|
LOG.warn(msg % {'s_pid': context.project_id,
|
||||||
|
'd_consumed': _consumed('snapshots')})
|
||||||
|
raise exception.SnapshotLimitExceeded(
|
||||||
|
allowed=quotas['snapshots'])
|
||||||
options = {'share_id': share['id'],
|
options = {'share_id': share['id'],
|
||||||
'size': share['size'],
|
'size': share['size'],
|
||||||
'user_id': context.user_id,
|
'user_id': context.user_id,
|
||||||
|
@ -239,7 +268,16 @@ class API(base.Base):
|
||||||
'share_proto': share['share_proto'],
|
'share_proto': share['share_proto'],
|
||||||
'export_location': share['export_location']}
|
'export_location': share['export_location']}
|
||||||
|
|
||||||
snapshot = self.db.share_snapshot_create(context, options)
|
try:
|
||||||
|
snapshot = self.db.share_snapshot_create(context, options)
|
||||||
|
QUOTAS.commit(context, reservations)
|
||||||
|
except Exception:
|
||||||
|
with excutils.save_and_reraise_exception():
|
||||||
|
try:
|
||||||
|
self.db.snapshot_delete(context, share['id'])
|
||||||
|
finally:
|
||||||
|
QUOTAS.rollback(context, reservations)
|
||||||
|
|
||||||
self.share_rpcapi.create_snapshot(context, share, snapshot)
|
self.share_rpcapi.create_snapshot(context, share, snapshot)
|
||||||
return snapshot
|
return snapshot
|
||||||
|
|
||||||
|
|
|
@ -185,8 +185,14 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||||
|
|
||||||
def delete_snapshot(self, context, snapshot_id):
|
def delete_snapshot(self, context, snapshot_id):
|
||||||
"""Delete share snapshot."""
|
"""Delete share snapshot."""
|
||||||
|
context = context.elevated()
|
||||||
snapshot_ref = self.db.share_snapshot_get(context, snapshot_id)
|
snapshot_ref = self.db.share_snapshot_get(context, snapshot_id)
|
||||||
|
|
||||||
|
if context.project_id != snapshot_ref['project_id']:
|
||||||
|
project_id = snapshot_ref['project_id']
|
||||||
|
else:
|
||||||
|
project_id = context.project_id
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.driver.delete_snapshot(context, snapshot_ref)
|
self.driver.delete_snapshot(context, snapshot_ref)
|
||||||
except exception.ShareSnapshotIsBusy:
|
except exception.ShareSnapshotIsBusy:
|
||||||
|
@ -198,6 +204,17 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||||
{'status': 'error_deleting'})
|
{'status': 'error_deleting'})
|
||||||
else:
|
else:
|
||||||
self.db.share_snapshot_destroy(context, snapshot_id)
|
self.db.share_snapshot_destroy(context, snapshot_id)
|
||||||
|
try:
|
||||||
|
reservations = QUOTAS.reserve(context,
|
||||||
|
project_id=project_id,
|
||||||
|
shares=-1,
|
||||||
|
gigabytes=-snapshot_ref['size'])
|
||||||
|
except Exception:
|
||||||
|
reservations = None
|
||||||
|
LOG.exception(_("Failed to update usages deleting snapshot"))
|
||||||
|
|
||||||
|
if reservations:
|
||||||
|
QUOTAS.commit(context, reservations, project_id=project_id)
|
||||||
|
|
||||||
def allow_access(self, context, access_id):
|
def allow_access(self, context, access_id):
|
||||||
"""Allow access to some share."""
|
"""Allow access to some share."""
|
||||||
|
|
Loading…
Reference in New Issue