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
|
||||
def snapshot_data_get_for_project(context, project_id, session=None):
|
||||
# TODO(yportnova): Uncomment when snapshot size implemented
|
||||
raise NotImplementedError()
|
||||
#
|
||||
# query = model_query(context,
|
||||
# func.count(models.ShareSnapshot.id),
|
||||
# func.sum(models.ShareSnapshot.size),
|
||||
# read_deleted="no",
|
||||
# session=session).\
|
||||
# filter_by(project_id=project_id)
|
||||
#
|
||||
# result = query.first()
|
||||
#
|
||||
# return (result[0] or 0, result[1] or 0)
|
||||
query = model_query(context,
|
||||
func.count(models.ShareSnapshot.id),
|
||||
func.sum(models.ShareSnapshot.size),
|
||||
read_deleted="no",
|
||||
session=session).\
|
||||
filter_by(project_id=project_id)
|
||||
|
||||
result = query.first()
|
||||
|
||||
return (result[0] or 0, result[1] or 0)
|
||||
|
||||
|
||||
@require_context
|
||||
|
@ -16,7 +16,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""Quotas for volumes."""
|
||||
"""Quotas for shares."""
|
||||
|
||||
import datetime
|
||||
|
||||
@ -775,10 +775,10 @@ class QuotaEngine(object):
|
||||
|
||||
|
||||
def _sync_shares(context, project_id, session):
|
||||
(volumes, gigs) = db.share_data_get_for_project(context,
|
||||
project_id,
|
||||
session=session)
|
||||
return {'volumes': volumes}
|
||||
(shares, gigs) = db.share_data_get_for_project(context,
|
||||
project_id,
|
||||
session=session)
|
||||
return {'shares': shares}
|
||||
|
||||
|
||||
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):
|
||||
(_junk, share_gigs) = db.share_data_get_for_project(context,
|
||||
project_id,
|
||||
session=session)
|
||||
project_id,
|
||||
session=session)
|
||||
if FLAGS.no_snapshot_gb_quota:
|
||||
return {'gigabytes': share_gigs}
|
||||
|
||||
# TODO(yportnova): Uncomment when Snapshot size is implemented
|
||||
# (_junk, snap_gigs) = db.snapshot_data_get_for_project(context,
|
||||
# project_id,
|
||||
# session=session)
|
||||
# return {'gigabytes': share_gigs + snap_gigs}
|
||||
return {'gigabytes': share_gigs}
|
||||
(_junk, snap_gigs) = db.snapshot_data_get_for_project(context,
|
||||
project_id,
|
||||
session=session)
|
||||
return {'gigabytes': share_gigs + snap_gigs}
|
||||
|
||||
|
||||
QUOTAS = QuotaEngine()
|
||||
@ -808,8 +806,7 @@ QUOTAS = QuotaEngine()
|
||||
|
||||
resources = [
|
||||
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'), ]
|
||||
|
||||
|
||||
|
@ -227,6 +227,35 @@ class API(base.Base):
|
||||
msg = _("must be available")
|
||||
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'],
|
||||
'size': share['size'],
|
||||
'user_id': context.user_id,
|
||||
@ -239,7 +268,16 @@ class API(base.Base):
|
||||
'share_proto': share['share_proto'],
|
||||
'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)
|
||||
return snapshot
|
||||
|
||||
|
@ -185,8 +185,14 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
|
||||
def delete_snapshot(self, context, snapshot_id):
|
||||
"""Delete share snapshot."""
|
||||
context = context.elevated()
|
||||
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:
|
||||
self.driver.delete_snapshot(context, snapshot_ref)
|
||||
except exception.ShareSnapshotIsBusy:
|
||||
@ -198,6 +204,17 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
{'status': 'error_deleting'})
|
||||
else:
|
||||
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):
|
||||
"""Allow access to some share."""
|
||||
|
Loading…
Reference in New Issue
Block a user