| 195 | |
| 196 | |
| 197 | Option<Error> Master::QuotaHandler::overcommitCheck( |
| 198 | const vector<Resources>& agents, |
| 199 | const hashmap<string, Quota>& quotas, |
| 200 | const QuotaInfo& request) |
| 201 | { |
| 202 | ResourceQuantities totalGuarantees = [&]() { |
| 203 | QuotaTree quotaTree({}); |
| 204 | |
| 205 | foreachpair (const string& role, const Quota& quota, quotas) { |
| 206 | quotaTree.update(role, quota); |
| 207 | } |
| 208 | |
| 209 | quotaTree.update(request.role(), Quota{request}); |
| 210 | |
| 211 | // Hard CHECK since this is already validated earlier |
| 212 | // during request validation. |
| 213 | CHECK_NONE(quotaTree.validate()); |
| 214 | |
| 215 | return quotaTree.totalGuarantees(); |
| 216 | }(); |
| 217 | |
| 218 | // Determine whether quota overcommits the cluster. |
| 219 | ResourceQuantities capacity; |
| 220 | |
| 221 | foreach (const Resources& agent, agents) { |
| 222 | capacity += ResourceQuantities::fromScalarResources( |
| 223 | agent.nonRevocable().scalars()); |
| 224 | } |
| 225 | |
| 226 | if (!capacity.contains(totalGuarantees)) { |
| 227 | // TODO(bmahler): Specialize this message based on whether |
| 228 | // this request leads to the overcommit vs the quota was |
| 229 | // already overcommitted. |
| 230 | return Error( |
| 231 | "Total quota guarantees '" + stringify(totalGuarantees) + "'" |
| 232 | " exceed cluster capacity '" + stringify(capacity) + "'"); |
| 233 | } |
| 234 | |
| 235 | return None(); |
| 236 | } |
| 237 | |
| 238 | |
| 239 | void Master::QuotaHandler::rescindOffers(const QuotaInfo& request) const |