server: charge snapshot copy primary storage to the snapshot owner ac… - #14036
nagaboinaramgopal wants to merge 3 commits into
Conversation
…count copySnapshotOnPool passed CallContext.getCallingUserId() to incrementResourceCount, whose first argument is an account id, not a user id. User ids and account ids are independent sequences, so the primary_storage count was charged to whichever account happened to share the caller's user id (and never to the real owner), corrupting quota accounting. The following guard also compared the calling user id against Account.ACCOUNT_ID_SYSTEM. Use the snapshot owner's account id for the count and the calling account id for the system check.
|
@DaanHoogland Could you pls take a look at this |
| } | ||
|
|
||
| private boolean copySnapshotOnPool(SnapshotInfo snapshot, SnapshotStrategy snapshotStrategy, Long storagePoolId) { | ||
| protected boolean copySnapshotOnPool(SnapshotInfo snapshot, SnapshotStrategy snapshotStrategy, Long storagePoolId) { |
There was a problem hiding this comment.
| protected boolean copySnapshotOnPool(SnapshotInfo snapshot, SnapshotStrategy snapshotStrategy, Long storagePoolId) { | |
| boolean copySnapshotOnPool(SnapshotInfo snapshot, SnapshotStrategy snapshotStrategy, Long storagePoolId) { |
we can make it package private as the test should be from the same package anyway
DaanHoogland
left a comment
There was a problem hiding this comment.
clgtm, one nit though
The test is in the same package, so the method does not need to be protected.
|
Good point, thank you. Made it package-private in 5a5e884. |
| _resourceLimitMgr.incrementResourceCount(snapshot.getAccountId(), ResourceType.primary_storage, snapshot.getSize()); | ||
| if (CallContext.current().getCallingAccountId() != Account.ACCOUNT_ID_SYSTEM) { | ||
| SnapshotVO snapshotVO = _snapshotDao.findByIdIncludingRemoved(snapshot.getSnapshotId()); | ||
| UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_COPY, CallContext.current().getCallingAccountId(), snapshotOnStore.getDataCenterId(), snapshotVO.getId(), null, null, null, snapshotVO.getSize(), |
There was a problem hiding this comment.
should the usage record go to the snapshot owner too? right now if an admin makes the copy, the admin gets billed for it
There was a problem hiding this comment.
Good catch, thank you. You're right, that was inconsistent: the resource count went to the owner but the usage record used the caller. Fixed in f2dfb46 so the usage event is attributed to the snapshot owner (snapshot.getAccountId()), which also matches the snapshot create and delete events.
The resource count already goes to the owner, so the usage event should too, otherwise an admin copying a user's snapshot is billed for it. Matches the snapshot create and delete usage events, which also use the owner account.
Description
When a snapshot is copied to an extra primary storage pool (createSnapshot with
storagepoolids), copySnapshotOnPool incremented the primary_storage resource count
using CallContext.getCallingUserId(). That method's first argument is an account
id, but getCallingUserId() returns a user id, and user ids and account ids are
independent sequences. So the usage was charged to whatever account happens to
share the caller's user id, never to the snapshot's real owner, and the delete
path never decrements it. The following guard also compared the user id against
Account.ACCOUNT_ID_SYSTEM.
Charge the snapshot owner's account id, and use the calling account id for the
system check.
Types of changes
Feature/Enhancement Scale or Bug Severity
Bug Severity
How Has This Been Tested?
Added a unit test asserting the primary_storage count is charged to the snapshot
owner's account rather than the calling user id. Also built the standard packages
and deployed on a KVM advanced zone.