| 3482 | |
| 3483 | |
| 3484 | Future<Response> Master::Http::_stopMaintenance( |
| 3485 | const RepeatedPtrField<MachineID>& machineIds, |
| 3486 | const Owned<ObjectApprovers>& approvers) const |
| 3487 | { |
| 3488 | // Validate every machine in the list. |
| 3489 | Try<Nothing> isValid = maintenance::validation::machines(machineIds); |
| 3490 | if (isValid.isError()) { |
| 3491 | return BadRequest(isValid.error()); |
| 3492 | } |
| 3493 | |
| 3494 | // Check that all machines are part of a maintenance schedule. |
| 3495 | foreach (const MachineID& id, machineIds) { |
| 3496 | if (!master->machines.contains(id)) { |
| 3497 | return BadRequest( |
| 3498 | "Machine '" + stringify(JSON::protobuf(id)) + |
| 3499 | "' is not part of a maintenance schedule"); |
| 3500 | } |
| 3501 | |
| 3502 | if (master->machines[id].info.mode() != MachineInfo::DOWN) { |
| 3503 | return BadRequest( |
| 3504 | "Machine '" + stringify(JSON::protobuf(id)) + |
| 3505 | "' is not in DOWN mode and cannot be brought up"); |
| 3506 | } |
| 3507 | |
| 3508 | if (!approvers->approved<STOP_MAINTENANCE>(id)) { |
| 3509 | return Forbidden(); |
| 3510 | } |
| 3511 | } |
| 3512 | |
| 3513 | return master->registrar->apply(Owned<RegistryOperation>( |
| 3514 | new maintenance::StopMaintenance(machineIds))) |
| 3515 | .then(defer(master->self(), [=](bool result) -> Future<Response> { |
| 3516 | // See the top comment in "master/maintenance.hpp" for why this check |
| 3517 | // is here, and is appropriate. |
| 3518 | CHECK(result); |
| 3519 | |
| 3520 | // Update the master's local state with the reactivated machines. |
| 3521 | hashset<MachineID> updated; |
| 3522 | foreach (const MachineID& id, machineIds) { |
| 3523 | master->machines[id].info.set_mode(MachineInfo::UP); |
| 3524 | master->machines[id].info.clear_unavailability(); |
| 3525 | updated.insert(id); |
| 3526 | } |
| 3527 | |
| 3528 | // Delete the machines from the schedule. |
| 3529 | for (list<mesos::maintenance::Schedule>::iterator schedule = |
| 3530 | master->maintenance.schedules.begin(); |
| 3531 | schedule != master->maintenance.schedules.end();) { |
| 3532 | for (int j = schedule->windows().size() - 1; j >= 0; j--) { |
| 3533 | mesos::maintenance::Window* window = schedule->mutable_windows(j); |
| 3534 | |
| 3535 | // Delete individual machines. |
| 3536 | for (int k = window->machine_ids().size() - 1; k >= 0; k--) { |
| 3537 | if (updated.contains(window->machine_ids(k))) { |
| 3538 | window->mutable_machine_ids()->DeleteSubrange(k, 1); |
| 3539 | } |
| 3540 | } |
| 3541 | |