| 431 | |
| 432 | |
| 433 | Future<http::Response> Master::QuotaHandler::update( |
| 434 | const mesos::master::Call& call, const Option<Principal>& principal) const |
| 435 | { |
| 436 | CHECK_EQ(mesos::master::Call::UPDATE_QUOTA, call.type()); |
| 437 | CHECK(call.has_update_quota()); |
| 438 | |
| 439 | const RepeatedPtrField<QuotaConfig>& configs = |
| 440 | call.update_quota().quota_configs(); |
| 441 | |
| 442 | // Validate `QuotaConfig`. |
| 443 | foreach (const auto& config, configs) { |
| 444 | // Check that the role is on the role whitelist, if it exists. |
| 445 | if (!master->isWhitelistedRole(config.role())) { |
| 446 | return BadRequest( |
| 447 | "Invalid QuotaConfig: '" + config.role() + "'" |
| 448 | " is not on the roles whitelist"); |
| 449 | } |
| 450 | |
| 451 | // Setting quota on a nested role is temporarily disabled. |
| 452 | // |
| 453 | // TODO(mzhu): Remove this check when MESOS-7402 is fixed. |
| 454 | bool nestedRole = strings::contains(config.role(), "/"); |
| 455 | if (nestedRole) { |
| 456 | return BadRequest( |
| 457 | "Updating quota on nested role '" + config.role() + |
| 458 | "' is not supported yet"); |
| 459 | } |
| 460 | |
| 461 | Option<Error> error = quota::validate(config); |
| 462 | |
| 463 | if (error.isSome()) { |
| 464 | return BadRequest( |
| 465 | "Invalid QuotaConfig: " + error->message); |
| 466 | } |
| 467 | } |
| 468 | |
| 469 | // Validate a role's requested limit is below its current consumption |
| 470 | // (otherwise a `force` flag is needed). |
| 471 | foreach (const auto& config, configs) { |
| 472 | ResourceLimits limits{config.limits()}; |
| 473 | ResourceQuantities consumedQuota = |
| 474 | RoleResourceBreakdown(master, config.role()).consumedQuota(); |
| 475 | |
| 476 | if (!limits.contains(consumedQuota)) { |
| 477 | if (call.update_quota().force()) { |
| 478 | LOG(INFO) << "Updating '" << config.role() << "' quota limit to" |
| 479 | << " '" + stringify(limits) + "';" |
| 480 | << " this is below its current quota consumption" |
| 481 | << " '" + stringify(consumedQuota) + "';" |
| 482 | << " Ignored violation since the force flag is provided."; |
| 483 | } else { |
| 484 | return BadRequest("Invalid QuotaConfig: Role '" + config.role() + "'" |
| 485 | " is already consuming '" + stringify(consumedQuota) + "';" |
| 486 | " this is more than the requested limits" |
| 487 | " '" + stringify(limits) + "'" |
| 488 | " (use 'force' flag to bypass this check)"); |
| 489 | } |
| 490 | } |
no test coverage detected