You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@mesos.apache.org by "Bernd Mathiske (JIRA)" <ji...@apache.org> on 2014/09/17 16:04:34 UTC

[jira] [Comment Edited] (MESOS-1384) Add support for loadable MesosModule

    [ https://issues.apache.org/jira/browse/MESOS-1384?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14137280#comment-14137280 ] 

Bernd Mathiske edited comment on MESOS-1384 at 9/17/14 2:04 PM:
----------------------------------------------------------------

[~karya], [~nnielsen], and I have yet another design that I will describe here. We also have a prototype that seems to work for at least some simple example modules. We stripped down the API for the module writer to as little as possible and we also reduced versioning to as little as we could think of that still makes sense and can be expanded later.

Definitions
--------------
Mesos version := Mesos releases.
Module API version := Bumped when the module management system changes.
Role  := The purpose that a module fulfills. In a given Mesos implementation this is tied to a specific object type, e.g. “Allocator”, “Isolator”, “Authenticator”.

The API from the point of view of a module writer
-----------------------------------------------------------------
To write a Mesos module, include the module API header file and a module role type declaration, then place one macro call inside your library source code to capture version information and add another macro call to declare a module. Then add a function body that returns a module instance. That’s all. Here is a minimal example that declares a module with the role “Calculator” and the name “example”.


#include <mesos/module.hpp> // module system API
#include <calculator.hpp> // module role type declaration is in here

MESOS_MODULE_LIBRARY() // declares the module library (and its versions)

class ExampleCalculator: public Calculator
{
public:
  // An example function that the module implements.
  virtual int compute(char a, long b)
  {
    return a + b;
  }
};

MESOS_MODULE(Calculator, example) // declares the module
{
  return new ExampleCalculator(); // creating and returning the module instance
}

Additional compatibility checks
-----------------------------------------
By default the above only works when the module client Mesos version and the Mesos version against which the library has been compiled are exactly the same. However, with this extra declaration, you can enable backwards compatibility controlled by a table inside Mesos that allows earlier library versions.

MESOS_IS_MODULE_COMPATIBLE(example) 
{
  return true;
}

Here, instead of simply returning true, the module could also perform its own checks, and return false under certain conditions. In the latter case the module will not be admitted, no matter what the results of any other checks by Mesos indicate. The module’s own checks are open-ended. In particular, they may include queries about other loaded libraries and modules and their respective versions. We will later provide an API for that.

The API from the point of view of a Mesos implementor
Only modules with pre-declared roles and binding sites can be loaded by Mesos. There is no means of dynamic discovery or binding of extra roles. To declare a loadable module, a Mesos developer needs to specify an abstract class with at least one virtual method. Here is an example that matches the module code above.

class Calculator {
public:
  Calculator() {}
  virtual ~Calculator() {}

  virtual int foo(char a, long b) = 0;
};

That’s all. To employ a specific instantiation of this module role/type, you can write something like this.

#include <module/module_manager.hpp>

Try<Calculator*> module = mesos::ModuleManager::loadModule<Calculator>("example");
if (module.isError()) {
  … // error handling
}
Calculator calculator = loadedModule.get();

And then you can already use the module.

int n = calculator.compute(‘A’, 10);

Module Libraries and Module Versioning
------------------------------------------------------
Before loading the above module, a dynamic library that contains the module needs to be loaded into Mesos. This happens early in Mesos startup code. The Mesos developer does not need to touch that code when introducing new module roles.

However, the developer is responsible for registering what versions of any given module are expected to remain compatible with Mesos as it progresses. This information is maintained in a table in src/module/module_manager.cpp. It contains an entry for every possible module role that Mesos recognizes, each with a corresponding Mesos release version number. This number needs to be adjusted by the Mesos developer to reflect the current Mesos version whenever compatibility between Mesos and modules that get compiled against it gets broken. Given that module implementation for older Mesos versions can still be written in the future, this may be impossible to tell and so in doubt it is best to just bump the required module version to the current Mesos version. But if one can be reasonably sure, assuming cooperative module developers, that a certain kind of module will continue to function across several Mesos versions, the table provides an easy way to specify this.


was (Author: bernd-mesos):
[~karya], [~nnielsen], and I have yet another design that I will describe here. We also have a prototype that seems to work for at least some simple example modules. We stripped down the API for the module writer to as little as possible and we also reduced versioning to as little as we could think of that still makes sense and can be expanded later.

Definitions
--------------
Mesos version := Mesos releases.
Module API version := Bumped when the module management system changes.
Role  := The purpose that a module fulfills. In a given Mesos implementation this is tied to a specific object type, e.g. “Allocator”, “Isolator”, “Authenticator”.

The API from the point of view of a module writer
To write a Mesos module, include the module API header file and a module role type declaration, then place one macro call inside your library source code to capture version information and add another macro call to declare a module. Then add a function body that returns a module instance. That’s all. Here is a minimal example that declares a module with the role “Calculator” and the name “example”.


#include <mesos/module.hpp> // module system API
#include <calculator.hpp> // module role type declaration is in here

MESOS_MODULE_LIBRARY() // declares the module library (and its versions)

class ExampleCalculator: public Calculator
{
public:
  // An example function that the module implements.
  virtual int compute(char a, long b)
  {
    return a + b;
  }
};

MESOS_MODULE(Calculator, example) // declares the module
{
  return new ExampleCalculator(); // creating and returning the module instance
}

Additional compatibility checks
By default the above only works when the module client Mesos version and the Mesos version against which the library has been compiled are exactly the same. However, with this extra declaration, you can enable backwards compatibility controlled by a table inside Mesos that allows earlier library versions.

MESOS_IS_MODULE_COMPATIBLE(example) 
{
  return true;
}

Here, instead of simply returning true, the module could also perform its own checks, and return false under certain conditions. In the latter case the module will not be admitted, no matter what the results of any other checks by Mesos indicate. The module’s own checks are open-ended. In particular, they may include queries about other loaded libraries and modules and their respective versions. We will later provide an API for that.

The API from the point of view of a Mesos implementor
Only modules with pre-declared roles and binding sites can be loaded by Mesos. There is no means of dynamic discovery or binding of extra roles. To declare a loadable module, a Mesos developer needs to specify an abstract class with at least one virtual method. Here is an example that matches the module code above.

class Calculator {
public:
  Calculator() {}
  virtual ~Calculator() {}

  virtual int foo(char a, long b) = 0;
};

That’s all. To employ a specific instantiation of this module role/type, you can write something like this.

#include <module/module_manager.hpp>

Try<Calculator*> module = mesos::ModuleManager::loadModule<Calculator>("example");
if (module.isError()) {
  … // error handling
}
Calculator calculator = loadedModule.get();

And then you can already use the module.

int n = calculator.compute(‘A’, 10);

Module Libraries and Module Versioning
Before loading the above module, a dynamic library that contains the module needs to be loaded into Mesos. This happens early in Mesos startup code. The Mesos developer does not need to touch that code when introducing new module roles.

However, the developer is responsible for registering what versions of any given module are expected to remain compatible with Mesos as it progresses. This information is maintained in a table in src/module/module_manager.cpp. It contains an entry for every possible module role that Mesos recognizes, each with a corresponding Mesos release version number. This number needs to be adjusted by the Mesos developer to reflect the current Mesos version whenever compatibility between Mesos and modules that get compiled against it gets broken. Given that module implementation for older Mesos versions can still be written in the future, this may be impossible to tell and so in doubt it is best to just bump the required module version to the current Mesos version. But if one can be reasonably sure, assuming cooperative module developers, that a certain kind of module will continue to function across several Mesos versions, the table provides an easy way to specify this.

> Add support for loadable MesosModule
> ------------------------------------
>
>                 Key: MESOS-1384
>                 URL: https://issues.apache.org/jira/browse/MESOS-1384
>             Project: Mesos
>          Issue Type: Improvement
>    Affects Versions: 0.19.0
>            Reporter: Timothy St. Clair
>            Assignee: Niklas Quarfot Nielsen
>
> I think we should break this into multiple phases.
> -(1) Let's get the dynamic library loading via a "stout-ified" version of https://github.com/timothysc/tests/blob/master/plugin_modules/DynamicLibrary.h. -
> *DONE*
> (2) Use (1) to instantiate some classes in Mesos (like an Authenticator and/or isolator) from a dynamic library. This will give us some more experience with how we want to name the underlying library symbol, how we want to specify flags for finding the library, what types of validation we want when loading a library.
> *TARGET* 
> (3) After doing (2) for one or two classes in Mesos I think we can formalize the approach in a "mesos-ified" version of https://github.com/timothysc/tests/blob/master/plugin_modules/MesosModule.h.
> *NEXT*



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)