Beispiel #1
0
// Creates a null-terminated array of null-terminated strings that will be
// passed to `CreateProcess` as the `lpEnvironment` argument, as described by
// MSDN[1]. This array needs to be sorted in alphabetical order, but the `map`
// already takes care of that. Note that this function does not handle Unicode
// environments, so it should not be used in conjunction with the
// `CREATE_UNICODE_ENVIRONMENT` flag.
//
// NOTE: This function will add the system's environment variables into
// the returned string. These variables take precedence over the provided
// `env` and are generally necessary in order to launch things on Windows.
//
// [1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx
inline Option<std::string> createProcessEnvironment(
    const Option<std::map<std::string, std::string>>& env)
{
  if (env.isNone() || (env.isSome() && env.get().size() == 0)) {
    return None();
  }

  Option<std::map<std::string, std::string>> systemEnvironment =
    getSystemEnvironment();

  // The system environment must be non-empty.
  // No subprocesses will be able to launch if the system environment is blank.
  CHECK(systemEnvironment.isSome() && systemEnvironment.get().size() > 0);

  std::map<std::string, std::string> combinedEnvironment = env.get();

  foreachpair (const std::string& key,
               const std::string& value,
               systemEnvironment.get()) {
    combinedEnvironment[key] = value;
  }

  std::string environmentString;
  foreachpair (const std::string& key,
               const std::string& value,
               combinedEnvironment) {
    environmentString += key + '=' + value + '\0';
  }
Beispiel #2
0
// NOTE: We only set the volume in DiskInfo if 'containerPath' is set.
// If volume mode is not specified, Volume::RW will be used (assuming
// 'containerPath' is set).
inline Resource::DiskInfo createDiskInfo(
    const Option<std::string>& persistenceId,
    const Option<std::string>& containerPath,
    const Option<Volume::Mode>& mode = None(),
    const Option<std::string>& hostPath = None())
{
  Resource::DiskInfo info;

  if (persistenceId.isSome()) {
    info.mutable_persistence()->set_id(persistenceId.get());
  }

  if (containerPath.isSome()) {
    Volume volume;
    volume.set_container_path(containerPath.get());
    volume.set_mode(mode.isSome() ? mode.get() : Volume::RW);

    if (hostPath.isSome()) {
      volume.set_host_path(hostPath.get());
    }

    info.mutable_volume()->CopyFrom(volume);
  }

  return info;
}
Beispiel #3
0
OperationStatus createOperationStatus(
    const OperationState& state,
    const Option<OperationID>& operationId,
    const Option<string>& message,
    const Option<Resources>& convertedResources,
    const Option<id::UUID>& uuid)
{
  OperationStatus status;
  status.set_state(state);

  if (operationId.isSome()) {
    status.mutable_operation_id()->CopyFrom(operationId.get());
  }

  if (message.isSome()) {
    status.set_message(message.get());
  }

  if (convertedResources.isSome()) {
    status.mutable_converted_resources()->CopyFrom(convertedResources.get());
  }

  if (uuid.isSome()) {
    status.mutable_uuid()->set_value(uuid->toBytes());
  }

  return status;
}
Beispiel #4
0
Future<bool> Master::QuotaHandler::authorizeRemoveQuota(
    const Option<string>& requestPrincipal,
    const Option<string>& quotaPrincipal) const
{
  if (master->authorizer.isNone()) {
    return true;
  }

  LOG(INFO) << "Authorizing principal '"
            << (requestPrincipal.isSome() ? requestPrincipal.get() : "ANY")
            << "' to remove quota set by '"
            << (quotaPrincipal.isSome() ? quotaPrincipal.get() : "ANY")
            << "'";

  mesos::ACL::RemoveQuota request;

  if (requestPrincipal.isSome()) {
    request.mutable_principals()->add_values(requestPrincipal.get());
  } else {
    request.mutable_principals()->set_type(mesos::ACL::Entity::ANY);
  }

  if (quotaPrincipal.isSome()) {
    request.mutable_quota_principals()->add_values(quotaPrincipal.get());
  } else {
    request.mutable_quota_principals()->set_type(mesos::ACL::Entity::ANY);
  }

  return master->authorizer.get()->authorize(request);
}
Beispiel #5
0
inline Contention createContention(
  Option<double_t> severity,
  const Contention_Type contentionType = Contention_Type_IPC,
  Option<WorkID> victim = None(),
  Option<double_t> timestamp = None(),
  Option<WorkID> aggressor = None()) {
  Contention contention;
  contention.set_type(contentionType);
  if (severity.isSome()) {
    contention.set_severity(severity.get());
  }

  if (timestamp.isSome()) {
    contention.set_timestamp(timestamp.get());
  }

  if (victim.isSome()) {
    contention.mutable_victim()->CopyFrom(victim.get());
  }

  if (aggressor.isSome())
    contention.mutable_aggressor()->CopyFrom(aggressor.get());

  return contention;
}
Beispiel #6
0
TaskStatus createTaskStatus(
    TaskStatus status,
    const id::UUID& uuid,
    double timestamp,
    const Option<TaskState>& state,
    const Option<string>& message,
    const Option<TaskStatus::Source>& source,
    const Option<TaskStatus::Reason>& reason,
    const Option<string>& data,
    const Option<bool>& healthy,
    const Option<CheckStatusInfo>& checkStatus,
    const Option<Labels>& labels,
    const Option<ContainerStatus>& containerStatus,
    const Option<TimeInfo>& unreachableTime)
{
  status.set_uuid(uuid.toBytes());
  status.set_timestamp(timestamp);

  if (state.isSome()) {
    status.set_state(state.get());
  }

  if (message.isSome()) {
    status.set_message(message.get());
  }

  if (source.isSome()) {
    status.set_source(source.get());
  }

  if (reason.isSome()) {
    status.set_reason(reason.get());
  }

  if (data.isSome()) {
    status.set_data(data.get());
  }

  if (healthy.isSome()) {
    status.set_healthy(healthy.get());
  }

  if (checkStatus.isSome()) {
    status.mutable_check_status()->CopyFrom(checkStatus.get());
  }

  if (labels.isSome()) {
    status.mutable_labels()->CopyFrom(labels.get());
  }

  if (containerStatus.isSome()) {
    status.mutable_container_status()->CopyFrom(containerStatus.get());
  }

  if (unreachableTime.isSome()) {
    status.mutable_unreachable_time()->CopyFrom(unreachableTime.get());
  }

  return status;
}
Beispiel #7
0
// TODO(vinod): Make SlaveID optional because 'StatusUpdate.SlaveID'
// is optional.
StatusUpdate createStatusUpdate(
    const FrameworkID& frameworkId,
    const Option<SlaveID>& slaveId,
    const TaskID& taskId,
    const TaskState& state,
    const std::string& message = "",
    const Option<ExecutorID>& executorId = None())
{
  StatusUpdate update;

  update.set_timestamp(process::Clock::now().secs());
  update.set_uuid(UUID::random().toBytes());
  update.mutable_framework_id()->MergeFrom(frameworkId);

  if (slaveId.isSome()) {
    update.mutable_slave_id()->MergeFrom(slaveId.get());
  }

  if (executorId.isSome()) {
    update.mutable_executor_id()->MergeFrom(executorId.get());
  }

  TaskStatus* status = update.mutable_status();
  status->mutable_task_id()->MergeFrom(taskId);

  if (slaveId.isSome()) {
    status->mutable_slave_id()->MergeFrom(slaveId.get());
  }

  status->set_state(state);
  status->set_message(message);
  status->set_timestamp(update.timestamp());

  return update;
}
Beispiel #8
0
Option<T> max(const Option<T>& left, const Option<T>& right)
{
  if (left.isSome() && right.isSome()) {
    return std::max(left.get(), right.get());
  } else if (left.isSome()) {
    return left.get();
  } else if (right.isSome()) {
    return right.get();
  } else {
    return Option<T>::none();
  }
}
Beispiel #9
0
  Resource createDiskResource(
      const string& value,
      const string& role,
      const Option<string>& persistenceID,
      const Option<string>& containerPath)
  {
    Resource resource = Resources::parse("disk", value, role).get();

    if (persistenceID.isSome() || containerPath.isSome()) {
      resource.mutable_disk()->CopyFrom(
          createDiskInfo(persistenceID, containerPath));
    }

    return resource;
  }
Beispiel #10
0
Future<bool> LeaderContenderProcess::withdraw()
{
  if (contending.isNone()) {
    // Nothing to withdraw because the contender has not contended.
    return false;
  }

  if (withdrawing.isSome()) {
    // Repeated calls to withdraw get the same result.
    return withdrawing.get();
  }

  withdrawing = new Promise<bool>();

  CHECK(!candidacy.isDiscarded());

  if (candidacy.isPending()) {
    // If we have not obtained the candidacy yet, we withdraw after
    // it is obtained.
    LOG(INFO) << "Withdraw requested before the candidacy is obtained; will "
              << "withdraw after it happens";
    candidacy.onAny(defer(self(), &Self::cancel));
  } else if (candidacy.isReady()) {
    cancel();
  } else {
    // We have failed to obtain the candidacy so we do not need to
    // cancel it.
    return false;
  }

  return withdrawing.get()->future();
}
Beispiel #11
0
  static int on_message_complete(http_parser* p)
  {
    DataDecoder* decoder = (DataDecoder*) p->data;
//     std::cout << "http::Request:" << std::endl;
//     std::cout << "  method: " << decoder->request->method << std::endl;
//     std::cout << "  path: " << decoder->request->path << std::endl;
    // Parse the query key/values.
    Try<std::string> decoded = http::decode(decoder->query);
    if (decoded.isError()) {
      return 1;
    }
    decoder->request->query = http::query::parse(decoded.get());

    Option<std::string> encoding =
      decoder->request->headers.get("Content-Encoding");
    if (encoding.isSome() && encoding.get() == "gzip") {
      Try<std::string> decompressed = gzip::decompress(decoder->request->body);
      if (decompressed.isError()) {
        return 1;
      }
      decoder->request->body = decompressed.get();
      decoder->request->headers["Content-Length"] =
        decoder->request->body.length();
    }

    decoder->requests.push_back(decoder->request);
    decoder->request = NULL;
    return 0;
  }
void V0ToV1AdapterProcess::disconnected()
{
  // Upon noticing a disconnection with the master, we drain the pending
  // events in the queue that were waiting to be sent to the scheduler
  // upon receiving the subscribe call.
  // It's fine to do so because:
  // - Any outstanding offers are invalidated by the master upon a scheduler
  //   (re-)registration.
  // - Any task status updates could be reconciled by the scheduler.
  LOG(INFO) << "Dropping " << pending.size() << " pending event(s)"
            << " because master disconnected";

  pending = queue<Event>();
  subscribeCall = false;

  if (heartbeatTimer.isSome()) {
    Clock::cancel(heartbeatTimer.get());
    heartbeatTimer = None();
  }

  LOG(INFO) << "Disconnected with the Mesos master;"
            << " invoking disconnected callback";

  disconnect();
}
Beispiel #13
0
Future<Response> FilesProcess::browse(const Request& request)
{
  Option<string> path = request.url.query.get("path");

  if (!path.isSome() || path.get().empty()) {
    return BadRequest("Expecting 'path=value' in query.\n");
  }

  Result<string> resolvedPath = resolve(path.get());

  if (resolvedPath.isError()) {
    return InternalServerError(resolvedPath.error() + ".\n");
  } else if (resolvedPath.isNone()) {
    return NotFound();
  }

  // The result will be a sorted (on path) array of files and dirs:
  // [{"name": "README", "path": "dir/README" "dir":False, "size":42}, ...]
  map<string, JSON::Object> files;
  Try<list<string> > entries = os::ls(resolvedPath.get());
  if (entries.isSome()) {
    foreach (const string& entry, entries.get()) {
      struct stat s;
      string fullPath = path::join(resolvedPath.get(), entry);

      if (stat(fullPath.c_str(), &s) < 0) {
        PLOG(WARNING) << "Found " << fullPath << " in ls but stat failed";
        continue;
      }

      files[fullPath] = jsonFileInfo(path::join(path.get(), entry), s);
    }
  }
Beispiel #14
0
    static int on_message_complete(http_parser* p)
    {
        ResponseDecoder* decoder = (ResponseDecoder*) p->data;

        CHECK_NOTNULL(decoder->response);

        // 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 can only provide the gzip encoding.
        Option<std::string> encoding =
            decoder->response->headers.get("Content-Encoding");
        if (encoding.isSome() && encoding.get() == "gzip") {
            Try<std::string> decompressed = gzip::decompress(decoder->response->body);
            if (decompressed.isError()) {
                decoder->failure = true;
                return 1;
            }
            decoder->response->body = decompressed.get();
            decoder->response->headers["Content-Length"] =
                decoder->response->body.length();
        }

        decoder->responses.push_back(decoder->response);
        decoder->response = NULL;
        return 0;
    }
Beispiel #15
0
Future<bool> LevelDBStorageProcess::set(const Entry& entry, const UUID& uuid)
{
  if (error.isSome()) {
    return Failure(error.get());
  }

  // We do a read first to make sure the version has not changed. This
  // could be optimized in the future, for now it will probably hit
  // the cache anyway.
  Try<Option<Entry> > option = read(entry.name());

  if (option.isError()) {
    return Failure(option.error());
  }

  if (option.get().isSome()) {
    if (UUID::fromBytes(option.get().get().uuid()) != uuid) {
      return false;
    }
  }

  // Note that the read (i.e., DB::Get) and the write (i.e., DB::Put)
  // are inherently "atomic" because only one db can be opened at a
  // time, so there can not be any writes that occur concurrently.

  Try<bool> result = write(entry);

  if (result.isError()) {
    return Failure(result.error());
  }

  return result.get();
}
Beispiel #16
0
Try<Nothing> initModules(const Option<Modules>& modules)
{
  // First get the user provided modules.
  Modules mergedModules;
  if (modules.isSome()) {
    mergedModules = modules.get();
  }

  // Add isolator modules from testisolator library.
  addIsolatorModules(&mergedModules);

  // Add authentication modules from testauthentication library.
  addAuthenticationModules(&mergedModules);

  // Add hook modules from testhook library.
  addHookModules(&mergedModules);

  // Add anonymous modules from testanonymous library.
  addAnonymousModules(&mergedModules);

  // Add allocator modules from testallocator library.
  addAllocatorModules(&mergedModules);

  // Add resource estimator modules from testresource_estimator library.
  addResourceEstimatorModules(&mergedModules);

  // Add authorizer modules from testauthorizer library.
  addAuthorizerModules(&mergedModules);

  return ModuleManager::load(mergedModules);
}
Beispiel #17
0
Future<Future<Nothing> > ZooKeeperMasterContenderProcess::contend()
{
  if (masterInfo.isNone()) {
    return Failure("Initialize the contender first");
  }

  // Should not recontend if the last election is still ongoing.
  if (candidacy.isSome() && candidacy.get().isPending()) {
    return candidacy.get();
  }

  if (contender != NULL) {
    LOG(INFO) << "Withdrawing the previous membership before recontending";
    delete contender;
  }

  // Serialize the MasterInfo to JSON.
  JSON::Object json = JSON::protobuf(masterInfo.get());

  contender = new LeaderContender(
      group.get(),
      stringify(json),
      master::MASTER_INFO_JSON_LABEL);
  candidacy = contender->contend();
  return candidacy.get();
}
Beispiel #18
0
// Tokenizes the string using the delimiters.
// Empty tokens will not be included in the result.
// Optionally, maximum number of tokens to be returned
// can be specified.
inline std::vector<std::string> tokenize(
    const std::string& s,
    const std::string& delims,
    const Option<size_t>& maxTokens = None())
{
  size_t offset = 0;
  std::vector<std::string> tokens;

  while (maxTokens.isNone() || maxTokens.get() > 0) {
    size_t nonDelim = s.find_first_not_of(delims, offset);

    if (nonDelim == std::string::npos) {
      break; // Nothing left
    }

    size_t delim = s.find_first_of(delims, nonDelim);

    // Finish tokenizing if this is the last token,
    // or we've found enough tokens.
    if (delim == std::string::npos ||
        (maxTokens.isSome() && tokens.size() == maxTokens.get() - 1)) {
      tokens.push_back(s.substr(nonDelim));
      break;
    }

    tokens.push_back(s.substr(nonDelim, delim - nonDelim));
    offset = delim;
  }

  return tokens;
}
Beispiel #19
0
Future<bool> LevelDBStateProcess::swap(const Entry& entry, const UUID& uuid)
{
    if (error.isSome()) {
        return Future<bool>::failed(error.get());
    }

    // We do a fetch first to make sure the version has not changed. This
    // could be optimized in the future, for now it will probably hit
    // the cache anyway.
    Try<Option<Entry> > option = get(entry.name());

    if (option.isError()) {
        return Future<bool>::failed(option.error());
    }

    if (option.get().isSome()) {
        if (UUID::fromBytes(option.get().get().uuid()) != uuid) {
            return false;
        }
    }

    // Note that there is no need to do the DB::Get and DB::Put
    // "atomically" because only one db can be opened at a time, so
    // there can not be any writes that occur concurrently.

    Try<bool> result = put(entry);

    if (result.isError()) {
        return Future<bool>::failed(result.error());
    }

    return result.get();
}
Beispiel #20
0
// Splits the string using the provided delimiters.
// The string is split each time at the first character
// that matches any of the characters specified in delims.
// Empty tokens are allowed in the result.
// Optionally, maximum number of tokens to be returned
// can be specified.
inline std::vector<std::string> split(
    const std::string& s,
    const std::string& delims,
    const Option<size_t>& maxTokens = None())
{
  size_t offset = 0;
  std::vector<std::string> tokens;

  while (maxTokens.isNone() || maxTokens.get() > 0) {
    size_t next = s.find_first_of(delims, offset);

    // Finish splitting if this is the last token,
    // or we've found enough tokens.
    if (next == std::string::npos ||
        (maxTokens.isSome() && tokens.size() == maxTokens.get() - 1)) {
      tokens.push_back(s.substr(offset));
      break;
    }

    tokens.push_back(s.substr(offset, next - offset));
    offset = next + 1;
  }

  return tokens;
}
Beispiel #21
0
string createExecutorDirectory(
    const string& rootDir,
    const SlaveID& slaveId,
    const FrameworkID& frameworkId,
    const ExecutorID& executorId,
    const ContainerID& containerId,
    const Option<string>& user)
{
  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;
}
Beispiel #22
0
inline Try<Nothing> FlagsBase::load(
    const Option<std::string>& prefix,
    int argc,
    const char* const *argv,
    bool unknowns,
    bool duplicates)
{
  std::map<std::string, Option<std::string>> envValues;
  std::map<std::string, Option<std::string>> cmdValues;

  // Grab the program name from argv[0].
  programName_ = argc > 0 ? Path(argv[0]).basename() : "";

  if (prefix.isSome()) {
    envValues = extract(prefix.get());
  }

  // Read flags from the command line.
  for (int i = 1; i < argc; i++) {
    const std::string arg(strings::trim(argv[i]));

    // Stop parsing flags after '--' is encountered.
    if (arg == "--") {
      break;
    }

    // Skip anything that doesn't look like a flag.
    if (arg.find("--") != 0) {
      continue;
    }

    std::string name;
    Option<std::string> value = None();

    size_t eq = arg.find_first_of("=");
    if (eq == std::string::npos && arg.find("--no-") == 0) { // --no-name
      name = arg.substr(2);
    } else if (eq == std::string::npos) {                    // --name
      name = arg.substr(2);
    } else {                                                 // --name=value
      name = arg.substr(2, eq - 2);
      value = arg.substr(eq + 1);
    }

    name = strings::lower(name);

    if (!duplicates) {
      if (cmdValues.count(name) > 0 ||
          (name.find("no-") == 0 && cmdValues.count(name.substr(3)) > 0)) {
        return Error("Duplicate flag '" + name + "' on command line");
      }
    }

    cmdValues[name] = value;
  }

  cmdValues.insert(envValues.begin(), envValues.end());

  return load(cmdValues, unknowns);
}
Beispiel #23
0
Future<http::Response> RegistryClientProcess::doHttpGet(
    const http::URL& url,
    const Option<http::Headers>& headers,
    bool isStreaming,
    bool resend,
    const Option<string>& lastResponseStatus) const
{
  Future<http::Response> response;

  if (isStreaming) {
    response = process::http::streaming::get(url, headers);
  } else {
    response = process::http::get(url, headers);
  }

  return response
    .then(defer(self(), [=](const http::Response& httpResponse)
        -> Future<http::Response> {
      VLOG(1) << "Response status for url '" << url << "': "
              << httpResponse.status;

      // Set the future if we get a OK response.
      if (httpResponse.status == "200 OK") {
        return httpResponse;
      }

      if (httpResponse.status == "400 Bad Request") {
        return handleHttpBadResponse(httpResponse, isStreaming)
          .then([](const string& errorResponse) -> Future<http::Response> {
            return Failure(errorResponse);
          });
      }

      // Prevent infinite recursion.
      if (lastResponseStatus.isSome() &&
          (lastResponseStatus.get() == httpResponse.status)) {
        return Failure("Invalid response: " + httpResponse.status);
      }

      // If resend is not set, we dont try again and stop here.
      if (!resend) {
        return Failure("Bad response: " + httpResponse.status);
      }

      // Handle 401 Unauthorized.
      if (httpResponse.status == "401 Unauthorized") {
        return handleHttpUnauthResponse(
            httpResponse,
            url,
            isStreaming);
      }

      // Handle redirect.
      if (httpResponse.status == "307 Temporary Redirect") {
        return handleHttpRedirect(httpResponse, headers, isStreaming);
      }

      return Failure("Invalid response: " + httpResponse.status);
    }));
}
Beispiel #24
0
// The customized clone function which will be used by 'subprocess()'.
static pid_t clone(
    const lambda::function<int()>& func,
    const Option<int>& namespaces)
{
  // Stack for the child.
  // - unsigned long long used for best alignment.
  // - static is ok because each child gets their own copy after the clone.
  // - 8 MiB appears to be the default for "ulimit -s" on OSX and Linux.
  //
  // NOTE: We need to allocate the stack dynamically. This is because
  // glibc's 'clone' will modify the stack passed to it, therefore the
  // stack must NOT be shared as multiple 'clone's can be invoked
  // simultaneously.
  int stackSize = 8 * 1024 * 1024;

  unsigned long long *stack =
    new unsigned long long[stackSize/sizeof(unsigned long long)];

  int flags = namespaces.isSome() ? namespaces.get() : 0;
  flags |= SIGCHLD; // Specify SIGCHLD as child termination signal.

  LOG(INFO) << "Cloning child process with flags = "
            << ns::stringify(flags);

  pid_t pid = ::clone(
      childMain,
      &stack[stackSize/sizeof(stack[0]) - 1],  // stack grows down.
      flags,
      (void*) &func);

  delete[] stack;

  return pid;
}
Beispiel #25
0
MockSlave::MockSlave(const slave::Flags& flags,
                     MasterDetector* detector,
                     slave::Containerizer* containerizer,
                     const Option<mesos::slave::QoSController*>& _qosController)
  : slave::Slave(
      flags,
      detector,
      containerizer,
      &files,
      &gc,
      statusUpdateManager = new slave::StatusUpdateManager(flags),
      &resourceEstimator,
      _qosController.isSome() ? _qosController.get() : &qosController)
{
  // Set up default behaviors, calling the original methods.
  EXPECT_CALL(*this, runTask(_, _, _, _, _))
    .WillRepeatedly(Invoke(this, &MockSlave::unmocked_runTask));
  EXPECT_CALL(*this, _runTask(_, _, _, _))
    .WillRepeatedly(Invoke(this, &MockSlave::unmocked__runTask));
  EXPECT_CALL(*this, killTask(_, _, _))
    .WillRepeatedly(Invoke(this, &MockSlave::unmocked_killTask));
  EXPECT_CALL(*this, removeFramework(_))
    .WillRepeatedly(Invoke(this, &MockSlave::unmocked_removeFramework));
  EXPECT_CALL(*this, __recover(_))
    .WillRepeatedly(Invoke(this, &MockSlave::unmocked___recover));
  EXPECT_CALL(*this, qosCorrections())
    .WillRepeatedly(Invoke(this, &MockSlave::unmocked_qosCorrections));
}
Beispiel #26
0
// Splits the string using the provided delimiters.
// The string is split each time at the first character
// that matches any of the characters specified in delims.
// Empty tokens are allowed in the result.
// Optionally, maximum number of tokens to be returned
// can be specified.
inline std::vector<std::string> split(
    const std::string& s,
    const std::string& delims,
    const Option<unsigned int>& n = None())
{
  std::vector<std::string> tokens;
  size_t offset = 0;
  size_t next = 0;

  while (n.isNone() || n.get() > 0) {
    next = s.find_first_of(delims, offset);
    if (next == std::string::npos) {
      tokens.push_back(s.substr(offset));
      break;
    }

    tokens.push_back(s.substr(offset, next - offset));
    offset = next + 1;

    // Finish splitting if we've found enough tokens.
    if (n.isSome() && tokens.size() == n.get() - 1) {
      tokens.push_back(s.substr(offset));
      break;
    }
  }
  return tokens;
}
Beispiel #27
0
    static int on_message_complete(http_parser* p)
    {
        DataDecoder* decoder = (DataDecoder*) p->data;

        // Parse the query key/values.
        Try<hashmap<std::string, std::string>> decoded =
                                                http::query::decode(decoder->query);

        if (decoded.isError()) {
            return 1;
        }

        CHECK_NOTNULL(decoder->request);

        decoder->request->query =  decoded.get();

        Option<std::string> encoding =
            decoder->request->headers.get("Content-Encoding");

        if (encoding.isSome() && encoding.get() == "gzip") {
            Try<std::string> decompressed = gzip::decompress(decoder->request->body);
            if (decompressed.isError()) {
                return 1;
            }
            decoder->request->body = decompressed.get();
            decoder->request->headers["Content-Length"] =
                decoder->request->body.length();
        }

        decoder->requests.push_back(decoder->request);
        decoder->request = NULL;
        return 0;
    }
Beispiel #28
0
inline std::string trim(
    const std::string& from,
    Mode mode = ANY,
    const std::string& chars = WHITESPACE)
{
  size_t start = 0;
  Option<size_t> end = None();

  if (mode == ANY) {
    start = from.find_first_not_of(chars);
    end = from.find_last_not_of(chars);
  } else if (mode == PREFIX) {
    start = from.find_first_not_of(chars);
  } else if (mode == SUFFIX) {
    end = from.find_last_not_of(chars);
  }

  // Bail early if 'from' contains only characters in 'chars'.
  if (start == std::string::npos) {
    return "";
  }

  // Calculate the length of the substring, defaulting to the "end" of
  // string if there were no characters to remove from the suffix.
  size_t length = std::string::npos;

  // Found characters to trim at the end.
  if (end.isSome() && end.get() != std::string::npos) {
    length = end.get() + 1 - start;
  }

  return from.substr(start, length);
}
Beispiel #29
0
inline Result<std::string> cmdline(const Option<pid_t>& pid = None())
{
  const std::string path = pid.isSome()
    ? "/proc/" + stringify(pid.get()) + "/cmdline"
    : "/proc/cmdline";

  std::ifstream file(path.c_str());

  if (!file.is_open()) {
    // Need to check if file exists AFTER we open it to guarantee
    // process hasn't terminated (or if it has, we at least have a
    // file which the kernel _should_ respect until a close).
    if (!os::exists(path)) {
      return None();
    }
    return Error("Failed to open '" + path + "'");
  }

  std::stringbuf buffer;

  do {
    // Read each argument in "argv", separated by null bytes.
    file.get(buffer, '\0');

    // Check for any read errors.
    if (file.fail() && !file.eof()) {
      return Error("Failed to read '" + path + "'");
    } else if (!file.eof()) {
      file.get(); // Read the null byte.
      buffer.sputc(' '); // Put a space between each command line argument.
    }
  } while (!file.eof());

  return buffer.str();
}
Beispiel #30
0
// Wait for a subprocess and test the status code for the following
// conditions of 'expected_status':
//   1. 'None' = Anything but '0'.
//   2. 'Some' = the value of 'expected_status'.
// Returns Nothing if the resulting status code matches the
// expectation otherwise a Failure with the output of the subprocess.
// TODO(jmlvanre): Turn this into a generally useful abstraction for
// gtest where we can have a more straigtforward 'expected_status'.
Future<Nothing> await_subprocess(
    const Subprocess& subprocess,
    const Option<int>& expected_status = None())
{
  // Dup the pipe fd of the subprocess so we can read the output if
  // needed.
  int out = dup(subprocess.out().get());

  // Once we get the status of the process.
  return subprocess.status()
    .then([=](const Option<int>& status) -> Future<Nothing> {
      // If the status is not set, fail out.
      if (status.isNone()) {
        return Failure("Subprocess status is none");
      }

      // If the status is not what we expect then fail out with the
      // output of the subprocess. The failure message will include
      // the assertion failures of the subprocess.
      if ((expected_status.isSome() && status.get() != expected_status.get()) ||
          (expected_status.isNone() && status.get() == 0)) {
        return io::read(out)
          .then([](const string& output) -> Future<Nothing> {
            return Failure("\n[++++++++++] Subprocess output.\n" + output +
                           "[++++++++++]\n");
          });
      }

      // If the subprocess ran successfully then return nothing.
      return Nothing();
    }).onAny([=]() {
      os::close(out);
    });
}