string createSlaveDirectory( const string& rootDir, const SlaveID& slaveId) { // `slaveId` should be valid because it's assigned by the master but // we do a sanity check here before using it to create a directory. CHECK_NONE(common::validation::validateSlaveID(slaveId)); const string directory = getSlavePath(rootDir, slaveId); Try<Nothing> mkdir = os::mkdir(directory); CHECK_SOME(mkdir) << "Failed to create agent directory '" << directory << "'"; // Remove the previous "latest" symlink. const string latest = getLatestSlavePath(rootDir); if (os::exists(latest)) { CHECK_SOME(os::rm(latest)) << "Failed to remove latest symlink '" << latest << "'"; } // Symlink the new slave directory to "latest". Try<Nothing> symlink = ::fs::symlink(directory, latest); CHECK_SOME(symlink) << "Failed to symlink directory '" << directory << "' to '" << latest << "'"; return directory; }
Try<Option<Entry> > LevelDBStorageProcess::read(const string& name) { CHECK_NONE(error); leveldb::ReadOptions options; string value; leveldb::Status status = db->Get(options, name, &value); if (status.IsNotFound()) { return None(); } else if (!status.ok()) { return Error(status.ToString()); } google::protobuf::io::ArrayInputStream stream(value.data(), value.size()); Entry entry; if (!entry.ParseFromZeroCopyStream(&stream)) { return Error("Failed to deserialize Entry"); } return Some(entry); }
string getPersistentVolumePath( const string& rootDir, const Resource& volume) { CHECK(volume.has_role()); CHECK(volume.has_disk()); CHECK(volume.disk().has_persistence()); // Additionally check that the role and the persistent ID are valid // before using them to construct a directory path. CHECK_NONE(roles::validate(volume.role())); CHECK_NONE(common::validation::validateID(volume.disk().persistence().id())); // If no `source` is provided in `DiskInfo` volumes are mapped into // the `rootDir`. if (!volume.disk().has_source()) { return getPersistentVolumePath( rootDir, volume.role(), volume.disk().persistence().id()); } // If a `source` was provided for the volume, we map it according // to the `type` of disk. Currently only the `PATH` and 'MOUNT' // types are supported. if (volume.disk().source().type() == Resource::DiskInfo::Source::PATH) { // For `PATH` we mount a directory inside the `root`. CHECK(volume.disk().source().has_path()); return getPersistentVolumePath( volume.disk().source().path().root(), volume.role(), volume.disk().persistence().id()); } else if ( volume.disk().source().type() == Resource::DiskInfo::Source::MOUNT) { // For `MOUNT` we map straight onto the root of the mount. CHECK(volume.disk().source().has_mount()); return volume.disk().source().mount().root(); } UNREACHABLE(); }
static int on_message_begin(http_parser* p) { StreamingResponseDecoder* decoder = (StreamingResponseDecoder*) p->data; CHECK(!decoder->failure); decoder->header = HEADER_FIELD; decoder->field.clear(); decoder->value.clear(); CHECK(decoder->response == NULL); CHECK_NONE(decoder->writer); decoder->response = new http::Response(); decoder->response->type = http::Response::PIPE; decoder->writer = None(); return 0; }
Try<bool> LevelDBStorageProcess::write(const Entry& entry) { CHECK_NONE(error); leveldb::WriteOptions options; options.sync = true; string value; if (!entry.SerializeToString(&value)) { return Error("Failed to serialize Entry"); } leveldb::Status status = db->Put(options, entry.name(), value); if (!status.ok()) { return Error(status.ToString()); } return true; }
static int on_headers_complete(http_parser* p) { StreamingResponseDecoder* decoder = (StreamingResponseDecoder*) p->data; CHECK_NOTNULL(decoder->response); // Add final header. decoder->response->headers[decoder->field] = decoder->value; decoder->field.clear(); decoder->value.clear(); // Get the response status string. if (http::statuses.contains(decoder->parser.status_code)) { decoder->response->status = http::statuses[decoder->parser.status_code]; } else { decoder->failure = true; return 1; } // We cannot provide streaming gzip decompression! Option<std::string> encoding = decoder->response->headers.get("Content-Encoding"); if (encoding.isSome() && encoding.get() == "gzip") { decoder->failure = true; return 1; } CHECK_NONE(decoder->writer); http::Pipe pipe; decoder->writer = pipe.writer(); decoder->response->reader = pipe.reader(); // Send the response to the caller, but keep a Pipe::Writer for // streaming the body content into the response. decoder->responses.push_back(decoder->response); decoder->response = NULL; return 0; }
void LeaderContenderProcess::joined() { CHECK(!candidacy.isDiscarded()); // Cannot be watching because the candidacy is not obtained yet. CHECK_NONE(watching); CHECK_SOME(contending); if (candidacy.isFailed()) { // The promise 'withdrawing' will be set to false in cancel(). contending.get()->fail(candidacy.failure()); return; } if (withdrawing.isSome()) { LOG(INFO) << "Joined group after the contender started withdrawing"; // The promise 'withdrawing' will be set to 'false' in subsequent // 'cancel()' call. return; } LOG(INFO) << "New candidate (id='" << candidacy->id() << "') has entered the contest for leadership"; // Transition to 'watching' state. watching = new Promise<Nothing>(); // Notify the client. if (contending.get()->set(watching.get()->future())) { // Continue to watch that our membership is not removed (if the // client still cares about it). candidacy->cancelled() .onAny(defer(self(), &Self::cancelled, lambda::_1)); } }
string createExecutorDirectory( const string& rootDir, const SlaveID& slaveId, const FrameworkID& frameworkId, const ExecutorID& executorId, const ContainerID& containerId, const Option<string>& user) { // These IDs should be valid as they are either assigned by the // master/agent or validated by the master but we do a sanity check // here before using them to create a directory. CHECK_NONE(common::validation::validateSlaveID(slaveId)); CHECK_NONE(common::validation::validateFrameworkID(frameworkId)); CHECK_NONE(common::validation::validateExecutorID(executorId)); CHECK_NONE(slave::validation::container::validateContainerId(containerId)); const string directory = getExecutorRunPath(rootDir, slaveId, frameworkId, executorId, containerId); Try<Nothing> mkdir = os::mkdir(directory); CHECK_SOME(mkdir) << "Failed to create executor directory '" << directory << "'"; // Remove the previous "latest" symlink. const string latest = getExecutorLatestRunPath(rootDir, slaveId, frameworkId, executorId); if (os::exists(latest)) { CHECK_SOME(os::rm(latest)) << "Failed to remove latest symlink '" << latest << "'"; } // Symlink the new executor directory to "latest". Try<Nothing> symlink = ::fs::symlink(directory, latest); CHECK_SOME(symlink) << "Failed to symlink directory '" << directory << "' to '" << latest << "'"; // `os::chown()` is not available on Windows. #ifndef __WINDOWS__ if (user.isSome()) { // Per MESOS-2592, we need to set the ownership of the executor // directory during its creation. We should not rely on subsequent // phases of the executor creation to ensure the ownership as // those may be conditional and in some cases leave the executor // directory owned by the slave user instead of the specified // framework or per-executor user. LOG(INFO) << "Trying to chown '" << directory << "' to user '" << user.get() << "'"; Try<Nothing> chown = os::chown(user.get(), directory); if (chown.isError()) { // TODO(nnielsen): We currently have tests which depend on using // user names which may not be available on the test machines. // Therefore, we cannot make the chown validation a hard // CHECK(). LOG(WARNING) << "Failed to chown executor directory '" << directory << "'. This may be due to attempting to run the executor " << "as a nonexistent user on the agent; see the description" << " for the `--switch_user` flag for more information: " << chown.error(); } } #endif // __WINDOWS__ return directory; }
// Forwards the status update on the specified update stream. // // If `checkpoint` is `false`, the update will be retried as long as it is in // memory, but it will not be checkpointed. process::Future<Nothing> update( const UpdateType& update, const IDType& streamId, bool checkpoint) { LOG(INFO) << "Received " << statusUpdateType << " " << update; if (!streams.contains(streamId)) { Try<Nothing> create = createStatusUpdateStream( streamId, update.has_framework_id() ? Option<FrameworkID>(update.framework_id()) : None(), checkpoint); if (create.isError()) { return process::Failure(create.error()); } } CHECK(streams.contains(streamId)); StatusUpdateStream* stream = streams[streamId].get(); if (update.has_latest_status()) { return process::Failure( "Expected " + statusUpdateType + " to not contain 'latest_status'"); } // Verify that we didn't get a non-checkpointable update for a // stream that is checkpointable, and vice-versa. if (stream->checkpointed() != checkpoint) { return process::Failure( "Mismatched checkpoint value for " + statusUpdateType + " " + stringify(update) + " (expected checkpoint=" + stringify(stream->checkpointed()) + " actual checkpoint=" + stringify(checkpoint) + ")"); } // Verify that the framework ID of the update matches the framework ID // of the stream. if (update.has_framework_id() != stream->frameworkId.isSome()) { return process::Failure( "Mismatched framework ID for " + statusUpdateType + " " + stringify(update) + " (expected " + (stream->frameworkId.isSome() ? stringify(stream->frameworkId.get()) : "no framework ID") + " got " + (update.has_framework_id() ? stringify(update.framework_id()) : "no framework ID") + ")"); } if (update.has_framework_id() && update.framework_id() != stream->frameworkId.get()) { return process::Failure( "Mismatched framework ID for " + statusUpdateType + " " + stringify(update) + " (expected " + stringify(stream->frameworkId.get()) + " actual " + stringify(update.framework_id()) + ")"); } // Handle the status update. Try<bool> result = stream->update(update); if (result.isError()) { return process::Failure(result.error()); } // This only happens if the status update is a duplicate. if (!result.get()) { return Nothing(); } // Forward the status update if this is at the front of the queue. // Subsequent status updates will be sent in `acknowledgement()`. if (!paused && stream->pending.size() == 1) { CHECK_NONE(stream->timeout); const Result<UpdateType>& next = stream->next(); if (next.isError()) { return process::Failure(next.error()); } CHECK_SOME(next); stream->timeout = forward(stream, next.get(), slave::STATUS_UPDATE_RETRY_INTERVAL_MIN); } return Nothing(); }