TODO(benh): Consider sending a boolean that specifies if the shut down should be graceful or immediate. Likewise, consider sending back a shut down acknowledgement, because otherwise you could get into a state where a shut down was sent, dropped, and therefore never processed.
| 4268 | // could get into a state where a shut down was sent, dropped, and |
| 4269 | // therefore never processed. |
| 4270 | void Slave::shutdownFramework( |
| 4271 | const UPID& from, |
| 4272 | const FrameworkID& frameworkId) |
| 4273 | { |
| 4274 | // Allow shutdownFramework() only if |
| 4275 | // its called directly (e.g. Slave::finalize()) or |
| 4276 | // its a message from the currently registered master. |
| 4277 | if (from && master != from) { |
| 4278 | LOG(WARNING) << "Ignoring shutdown framework message for " << frameworkId |
| 4279 | << " from " << from |
| 4280 | << " because it is not from the registered master (" |
| 4281 | << (master.isSome() ? stringify(master.get()) : "None") << ")"; |
| 4282 | return; |
| 4283 | } |
| 4284 | |
| 4285 | VLOG(1) << "Asked to shut down framework " << frameworkId |
| 4286 | << " by " << from; |
| 4287 | |
| 4288 | CHECK(state == RECOVERING || state == DISCONNECTED || |
| 4289 | state == RUNNING || state == TERMINATING) |
| 4290 | << state; |
| 4291 | |
| 4292 | if (state == RECOVERING || state == DISCONNECTED) { |
| 4293 | LOG(WARNING) << "Ignoring shutdown framework message for " << frameworkId |
| 4294 | << " because the agent has not yet registered with the master"; |
| 4295 | return; |
| 4296 | } |
| 4297 | |
| 4298 | Framework* framework = getFramework(frameworkId); |
| 4299 | if (framework == nullptr) { |
| 4300 | VLOG(1) << "Cannot shut down unknown framework " << frameworkId; |
| 4301 | return; |
| 4302 | } |
| 4303 | |
| 4304 | switch (framework->state) { |
| 4305 | case Framework::TERMINATING: |
| 4306 | LOG(WARNING) << "Ignoring shutdown framework " << framework->id() |
| 4307 | << " because it is terminating"; |
| 4308 | break; |
| 4309 | case Framework::RUNNING: |
| 4310 | LOG(INFO) << "Shutting down framework " << framework->id(); |
| 4311 | |
| 4312 | framework->state = Framework::TERMINATING; |
| 4313 | |
| 4314 | // Shut down all executors of this framework. |
| 4315 | // NOTE: We use 'executors.keys()' here because 'shutdownExecutor' |
| 4316 | // and 'removeExecutor' can remove an executor from 'executors'. |
| 4317 | foreach (const ExecutorID& executorId, framework->executors.keys()) { |
| 4318 | Executor* executor = framework->executors[executorId]; |
| 4319 | CHECK(executor->state == Executor::REGISTERING || |
| 4320 | executor->state == Executor::RUNNING || |
| 4321 | executor->state == Executor::TERMINATING || |
| 4322 | executor->state == Executor::TERMINATED) |
| 4323 | << executor->state; |
| 4324 | |
| 4325 | if (executor->state == Executor::REGISTERING || |
| 4326 | executor->state == Executor::RUNNING) { |
| 4327 | _shutdownExecutor(framework, executor); |