Example #1
0
void GroupProcess::connected(bool reconnect)
{
  if (!reconnect) {
    // Authenticate if necessary (and we are connected for the first
    // time, or after a session expiration).
    if (auth.isSome()) {
      LOG(INFO) << "Authenticating with ZooKeeper using " << auth.get().scheme;

      int code = zk->authenticate(auth.get().scheme, auth.get().credentials);

      if (code != ZOK) { // TODO(benh): Authentication retries?
        Try<string> message = strings::format(
            "Failed to authenticate with ZooKeeper: %s", zk->message(code));
        error = message.isSome()
          ? message.get()
          : "Failed to authenticate with ZooKeeper";
        abort(); // Cancels everything pending.
        return;
      }
    }

    // Create directory path znodes as necessary.
    CHECK(znode.size() == 0 || znode.at(znode.size() - 1) != '/');
    size_t index = znode.find("/", 0);

    while (index < string::npos) {
      // Get out the prefix to create.
      index = znode.find("/", index + 1);
      const string& prefix = znode.substr(0, index);

      LOG(INFO) << "Trying to create '" << prefix << "' in ZooKeeper";

      // Create the node (even if it already exists).
      int code = zk->create(prefix, "", acl, 0, NULL);

      if (code == ZINVALIDSTATE || (code != ZOK && zk->retryable(code))) {
        CHECK(zk->getState() != ZOO_AUTH_FAILED_STATE);
        return; // Try again later.
      } else if (code != ZOK && code != ZNODEEXISTS) {
        Try<string> message = strings::format(
            "Failed to create '%s' in ZooKeeper: %s",
            prefix.c_str(), zk->message(code));
        error = message.isSome()
          ? message.get()
          : "Failed to create node in ZooKeeper";
        abort(); // Cancels everything pending.
        return;
      }
    }
  }

  state = CONNECTED;

  sync(); // Handle pending (and cache memberships).
}
Example #2
0
bool operator==(Try<T> lhs, Try<T> rhs)
{
  if (lhs.isSome() != rhs.isSome()) {
    return false;
  }

  if (lhs.isSome()) {
    return lhs.get() == rhs.get();
  }

  return lhs.error() == rhs.error();
}
Example #3
0
inline Result<Process> process(pid_t pid)
{
  // Page size, used for memory accounting.
  // NOTE: This is more portable than using getpagesize().
  static const long pageSize = sysconf(_SC_PAGESIZE);
  if (pageSize <= 0) {
    return Error("Failed to get sysconf(_SC_PAGESIZE)");
  }

  // Number of clock ticks per second, used for cpu accounting.
  static const long ticks = sysconf(_SC_CLK_TCK);
  if (ticks <= 0) {
    return Error("Failed to get sysconf(_SC_CLK_TCK)");
  }

  const Result<proc::ProcessStatus> status = proc::status(pid);

  if (status.isError()) {
    return Error(status.error());
  }

  if (status.isNone()) {
    return None();
  }

  // There are known bugs with invalid utime / stime values coming
  // from /proc/<pid>/stat on some Linux systems.
  // See the following thread for details:
  // http://mail-archives.apache.org/mod_mbox/incubator-mesos-dev/
  // 201307.mbox/%3CCA+2n2er-Nemh0CsKLbHRkaHd=YCrNt17NLUPM2=TtEfsKOw4
  // Rg@mail.gmail.com%3E
  // These are similar reports:
  // http://lkml.indiana.edu/hypermail/linux/kernel/1207.1/01388.html
  // https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1023214
  Try<Duration> utime = Duration::create(status.get().utime / (double) ticks);
  Try<Duration> stime = Duration::create(status.get().stime / (double) ticks);

  // The command line from 'status.get().comm' is only "arg0" from
  // "argv" (i.e., the canonical executable name). To get the entire
  // command line we grab '/proc/[pid]/cmdline'.
  Result<std::string> cmdline = proc::cmdline(pid);

  return Process(status.get().pid,
                 status.get().ppid,
                 status.get().pgrp,
                 status.get().session,
                 Bytes(status.get().rss * pageSize),
                 utime.isSome() ? utime.get() : Option<Duration>::none(),
                 stime.isSome() ? stime.get() : Option<Duration>::none(),
                 cmdline.isSome() ? cmdline.get() : status.get().comm,
                 status.get().state == 'Z');
}
Example #4
0
TEST(StringsTest, Format)
{
  Try<std::string> result = strings::format("%s %s", "hello", "world");
  ASSERT_TRUE(result.isSome());
  EXPECT_EQ("hello world", result.get());

  result = strings::format("hello %d", 42);
  ASSERT_TRUE(result.isSome());
  EXPECT_EQ("hello 42", result.get());

  result = strings::format("hello %s", "fourty-two");
  ASSERT_TRUE(result.isSome());
  EXPECT_EQ("hello fourty-two", result.get());
}
Example #5
0
Try<string> Environment::mkdtemp()
{
  const ::testing::TestInfo* const testInfo =
    ::testing::UnitTest::GetInstance()->current_test_info();

  if (testInfo == NULL) {
    return Error("Failed to determine the current test information");
  }

  // We replace any slashes present in the test names (e.g. TYPED_TEST),
  // to make sure the temporary directory resides under '/tmp/'.
  const string& testCase =
    strings::replace(testInfo->test_case_name(), "/", "_");

  string testName = strings::replace(testInfo->name(), "/", "_");

  // Adjust the test name to remove any 'DISABLED_' prefix (to make
  // things easier to read). While this might seem alarming, if we are
  // "running" a disabled test it must be the case that the test was
  // explicitly enabled (e.g., via 'gtest_filter').
  if (strings::startsWith(testName, "DISABLED_")) {
    testName = strings::remove(testName, "DISABLED_", strings::PREFIX);
  }

  const string& path =
    path::join("/tmp", strings::join("_", testCase, testName, "XXXXXX"));

  Try<string> mkdtemp = os::mkdtemp(path);
  if (mkdtemp.isSome()) {
    directories.push_back(mkdtemp.get());
  }
  return mkdtemp;
}
Example #6
0
/**
 * Creates a MasterInfo protobuf from the process's UPID.
 *
 * This is only used by the `StandaloneMasterDetector` (used in tests
 * and outside tests when ZK is not used).
 *
 * For example, when we start a slave with
 * `--master=master@127.0.0.1:5050`, since the slave (and consequently
 * its detector) doesn't have enough information about `MasterInfo`, it
 * tries to construct it based on the only available information
 * (`UPID`).
 *
 * @param pid The process's assigned untyped PID.
 * @return A fully formed `MasterInfo` with the IP/hostname information
 *    as derived from the `UPID`.
 */
MasterInfo createMasterInfo(const UPID& pid)
{
  MasterInfo info;
  info.set_id(stringify(pid) + "-" + UUID::random().toString());

  // NOTE: Currently, we store the ip in network order, which should
  // be fixed. See MESOS-1201 for more details.
  // TODO(marco): `ip` and `port` are deprecated in favor of `address`;
  //     remove them both after the deprecation cycle.
  info.set_ip(pid.address.ip.in().get().s_addr);
  info.set_port(pid.address.port);

  info.mutable_address()->set_ip(stringify(pid.address.ip));
  info.mutable_address()->set_port(pid.address.port);

  info.set_pid(pid);

  Try<string> hostname = net::getHostname(pid.address.ip);
  if (hostname.isSome()) {
    // Hostname is deprecated; but we need to update it
    // to maintain backward compatibility.
    // TODO(marco): Remove once we deprecate it.
    info.set_hostname(hostname.get());
    info.mutable_address()->set_hostname(hostname.get());
  }

  return info;
}
Example #7
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);
    }
  }
Example #8
0
inline bool isdir(
    const std::string& path,
    const FollowSymlink follow = FollowSymlink::FOLLOW_SYMLINK)
{
  Try<struct ::stat> s = internal::stat(path, follow);
  return s.isSome() && S_ISDIR(s->st_mode);
}
Example #9
0
inline bool islink(const std::string& path)
{
  Try<internal::windows::SymbolicLink> symlink =
    internal::windows::query_symbolic_link_data(path);

  return symlink.isSome();
}
Example #10
0
inline Try<long> mtime(const std::string& path)
{
  Try<::internal::windows::SymbolicLink> symlink =
    ::internal::windows::query_symbolic_link_data(path);

  if (symlink.isSome()) {
    return Error(
        "Requested mtime for '" + path +
        "', but symbolic links don't have an mtime on Windows");
  }

  struct _stat s;

  if (::_stat(path.c_str(), &s) < 0) {
    return ErrnoError("Error invoking stat for '" + path + "'");
  }

  // To be safe, we assert that `st_mtime` is represented as `__int64`. To
  // conform to the POSIX, we also cast `st_mtime` to `long`; we choose to make
  // this conversion explicit because we expect the truncation to not cause
  // information loss.
  static_assert(
      std::is_same<__int64, __time64_t>::value,
      "Mesos assumes `__time64_t` is represented as `__int64`");
  return static_cast<long>(s.st_mtime);
}
Example #11
0
 Future<double> _mem_free_bytes()
 {
   Try<os::Memory> memory = os::memory();
   if (memory.isSome()) {
     return memory.get().free.bytes();
   }
   return Failure("memory not available.");
 }
Example #12
0
 Future<double> _cpus_total()
 {
   Try<long> cpus = os::cpus();
   if (cpus.isSome()) {
     return cpus.get();
   }
   return Failure("cpus not available.");
 }
Example #13
0
inline bool islink(const std::string& path)
{
  // By definition, you don't followsymlinks when trying
  // to find whether a path is a link. If you followed it,
  // it wouldn't ever be a link.
  Try<struct ::stat> s = internal::stat(path, DO_NOT_FOLLOW_SYMLINK);
  return s.isSome() && S_ISLNK(s->st_mode);
}
Example #14
0
 Future<double> _load_15min()
 {
   Try<os::Load> load = os::loadavg();
   if (load.isSome()) {
     return load.get().fifteen;
   }
   return Failure("Failed to get loadavg: " + load.error());
 }
Example #15
0
 // Gauge handlers.
 Future<double> _load_1min()
 {
   Try<os::Load> load = os::loadavg();
   if (load.isSome()) {
     return load.get().one;
   }
   return Failure("loadavg not available.");
 }
Example #16
0
 Future<double> _cpus_total()
 {
   Try<long> cpus = os::cpus();
   if (cpus.isSome()) {
     return cpus.get();
   }
   return Failure("Failed to get cpus: " + cpus.error());
 }
Example #17
0
 Future<double> _mem_free_bytes()
 {
   Try<os::Memory> memory = os::memory();
   if (memory.isSome()) {
     return static_cast<double>(memory.get().free.bytes());
   }
   return Failure("Failed to get memory: " + memory.error());
 }
Example #18
0
static hashset<string> listfiles(const string& directory)
{
  hashset<string> fileset;
  Try<std::list<std::string> > entries = os::ls(directory);
  if (entries.isSome()) {
    foreach (const string& entry, entries.get()) {
      fileset.insert(entry);
    }
  }
Example #19
0
void FlagsBase::add(
    T1* t1,
    const Name& name,
    const Option<Name>& alias,
    const std::string& help,
    const T2& t2,
    F validate)
{
  // Don't bother adding anything if the pointer is NULL.
  if (t1 == NULL) {
    return;
  }

  *t1 = t2; // Set the default.

  Flag flag;
  flag.name = name;
  flag.alias = alias;
  flag.help = help;
  flag.boolean = typeid(T1) == typeid(bool);

  // NOTE: We need to take FlagsBase* (or const FlagsBase&) as the
  // first argument to match the function signature of the 'load',
  // 'stringify', and 'validate' lambdas used in other overloads of
  // FlagsBase::add. Since we don't need to use the pointer here we
  // don't name it as a parameter.

  flag.load = [t1](FlagsBase*, const std::string& value) -> Try<Nothing> {
    // NOTE: 'fetch' "retrieves" the value if necessary and then
    // invokes 'parse'. See 'fetch' for more details.
    Try<T1> t = fetch<T1>(value);
    if (t.isSome()) {
      *t1 = t.get();
    } else {
      return Error("Failed to load value '" + value + "': " + t.error());
    }

    return Nothing();
  };

  flag.stringify = [t1](const FlagsBase&) -> Option<std::string> {
    return stringify(*t1);
  };

  flag.validate = [t1, validate](const FlagsBase&) -> Option<Error> {
    return validate(*t1);
  };

  // Update the help string to include the default value.
  flag.help += help.size() > 0 && help.find_last_of("\n\r") != help.size() - 1
    ? " (default: " // On same line, add space.
    : "(default: "; // On newline.
  flag.help += stringify(t2);
  flag.help += ")";

  add(flag);
}
Example #20
0
inline bool isJailed() {
  int mib[4];
  size_t len = 4;
  ::sysctlnametomib("security.jail.jailed", mib, &len);
  Try<int> jailed = os::sysctl(mib[0], mib[1], mib[2]).integer();
  if (jailed.isSome()) {
      return jailed.get() == 1;
  }

  return false;
}
Example #21
0
void usage(const char* argv0)
{
  // Get a list of available commands.
  const string& PATH = os::getenv("PATH");

  list<string> commands;

  foreach (const string& path, strings::split(PATH, ":")) {
    Try<list<string> > matches = os::glob(path::join(path, "mesos-*"));
    if (matches.isSome()) {
      foreach (const string& match, matches.get()) {
        Try<bool> access = os::access(match, X_OK);
        if (access.isSome() && access.get()) {
          Try<string> basename = os::basename(match);
          if (basename.isSome()) {
            commands.push_back(basename.get().substr(6));
          }
        }
      }
    }
  }
Example #22
0
Try<Nothing> ModuleManager::load(const Modules& modules)
{
  Lock lock(&mutex);
  initialize();

  foreach (const Modules::Library& library, modules.libraries()) {
    string libraryName;
    if (library.has_file()) {
      libraryName = library.file();
    } else if (library.has_name()) {
      libraryName = os::libraries::expandName(library.name());
    } else {
      return Error("Library name or path not provided");
    }

    if (!dynamicLibraries.contains(libraryName)) {
      Owned<DynamicLibrary> dynamicLibrary(new DynamicLibrary());
      Try<Nothing> result = dynamicLibrary->open(libraryName);
      if (!result.isSome()) {
        return Error("Error opening library: '" + libraryName + "'");
      }

      dynamicLibraries[libraryName] = dynamicLibrary;
    }

    // Load module manifests.
    foreach (const string& moduleName, library.modules()) {
      if (moduleName.empty()) {
        return Error(
            "Error: module name not provided with library '" +
            library.file() + "'");
      }
      // Check for possible duplicate module names.
      if (moduleBases.contains(moduleName)) {
        return Error("Error loading duplicate module '" + moduleName + "'");
      }
      Try<void*> symbol = dynamicLibraries[libraryName]->loadSymbol(moduleName);
      if (symbol.isError()) {
        return Error(
            "Error loading module '" + moduleName + "': " + symbol.error());
      }
      ModuleBase* moduleBase = (ModuleBase*) symbol.get();
      Try<Nothing> result = verifyModule(moduleName, moduleBase);
      if (result.isError()) {
        return Error(
            "Error verifying module '" + moduleName + "': " + result.error());
      }
      moduleBases[moduleName] = (ModuleBase*) symbol.get();
    }
  }

  return Nothing();
}
Example #23
0
// Returns a gzip decompressed version of the provided string.
inline Try<std::string> decompress(const std::string& compressed)
{
  Decompressor decompressor;
  Try<std::string> decompressed = decompressor.decompress(compressed);

  // Ensure that the decompression stream does not expect more input.
  if (decompressed.isSome() && !decompressor.finished()) {
    return Error("More input is expected");
  }

  return decompressed;
}
Example #24
0
void usage(const char* argv0)
{
  // Get a list of available commands.
  const Option<string> PATH = os::getenv("PATH");

  list<string> commands;

  if (PATH.isSome()) {
    foreach (const string& path, strings::split(PATH.get(), ":")) {
      Try<list<string> > matches = fs::list(path::join(path, "mesos-*"));
      if (matches.isSome()) {
        foreach (const string& match, matches.get()) {
          Try<bool> access = os::access(match, X_OK);
          if (access.isSome() && access.get()) {
            string basename = Path(match).basename();
            if (basename != "mesos-slave") {
              commands.push_back(basename.substr(6));
            }
          }
        }
      }
    }
Example #25
0
Result<T> numify(const Option<std::string>& s)
{
    if (s.isSome()) {
        Try<T> t = numify<T>(s.get());
        if (t.isSome()) {
            return t.get();
        } else if (t.isError()) {
            return Error(t.error());
        }
    }

    return None();
}
Example #26
0
File: ns.cpp Project: ederst/mesos
// TODO(jpeach): As we move namespace parameters from strings to CLONE
// constants, we should be able to eventually remove the internal uses
// of this function.
static set<string> namespaces()
{
  set<string> result;

  Try<std::list<string>> entries = os::ls("/proc/self/ns");
  if (entries.isSome()) {
    foreach (const string& entry, entries.get()) {
      // Introduced in Linux 4.12, pid_for_children is a handle for the PID
      // namespace of child processes created by the current process.
      if (entry != "pid_for_children") {
        result.insert(entry);
      }
    }
  }
Example #27
0
  // HTTP endpoints.
  Future<http::Response> stats(const http::Request& request)
  {
    JSON::Object object;
    Try<os::Load> load = os::loadavg();
    if (load.isSome()) {
      object.values["avg_load_1min"] = load.get().one;
      object.values["avg_load_5min"] = load.get().five;
      object.values["avg_load_15min"] = load.get().fifteen;
    }

    Try<long> cpus = os::cpus();
    if (cpus.isSome()) {
      object.values["cpus_total"] = cpus.get();
    }

    Try<os::Memory> memory = os::memory();
    if (memory.isSome()) {
      object.values["mem_total_bytes"] = memory.get().total.bytes();
      object.values["mem_free_bytes"] = memory.get().free.bytes();
    }

    return http::OK(object, request.query.get("jsonp"));
  }
Example #28
0
 static Try<Nothing> load(
     Option<T>* flag,
     const std::tr1::function<Try<T>(const std::string&)>& parse,
     const std::string& name,
     const std::string& value)
 {
   Try<T> t = parse(value);
   if (t.isSome()) {
     *flag = Option<T>::some(t.get());
   } else {
     return Error("Failed to load value '" + value + "': " + t.error());
   }
   return Nothing();
 }
Example #29
0
MasterInfo createMasterInfo(const process::UPID& pid)
{
  MasterInfo info;
  info.set_id(stringify(pid) + "-" + UUID::random().toString());
  info.set_ip(pid.address.ip);
  info.set_port(pid.address.port);
  info.set_pid(pid);

  Try<string> hostname = net::getHostname(pid.address.ip);
  if (hostname.isSome()) {
    info.set_hostname(hostname.get());
  }

  return info;
}
Example #30
0
void FlagsBase::add(
    Option<T>* option,
    const Name& name,
    const Option<Name>& alias,
    const std::string& help,
    F validate)
{
  // Don't bother adding anything if the pointer is NULL.
  if (option == NULL) {
    return;
  }

  Flag flag;
  flag.name = name;
  flag.alias = alias;
  flag.help = help;
  flag.boolean = typeid(T) == typeid(bool);

  // NOTE: See comment above in T* overload of FlagsBase::add for why
  // we need to take the FlagsBase* parameter.

  flag.load = [option](FlagsBase*, const std::string& value) -> Try<Nothing> {
    // NOTE: 'fetch' "retrieves" the value if necessary and then
    // invokes 'parse'. See 'fetch' for more details.
    Try<T> t = fetch<T>(value);
    if (t.isSome()) {
      *option = Some(t.get());
    } else {
      return Error("Failed to load value '" + value + "': " + t.error());
    }

    return Nothing();
  };

  flag.stringify = [option](const FlagsBase&) -> Option<std::string> {
    if (option->isSome()) {
      return stringify(option->get());
    }
    return None();
  };

  flag.validate = [option, validate](const FlagsBase&) -> Option<Error> {
    return validate(*option);
  };

  add(flag);
}