| <!DOCTYPE html> |
| <html> |
| <head> |
| <meta charset="utf-8"> |
| <title>Apache Mesos - Modules</title> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| |
| <meta property="og:locale" content="en_US"/> |
| <meta property="og:type" content="website"/> |
| <meta property="og:title" content="Apache Mesos"/> |
| <meta property="og:site_name" content="Apache Mesos"/> |
| <meta property="og:url" content="http://mesos.apache.org/"/> |
| <meta property="og:image" content="http://mesos.apache.org/assets/img/mesos_logo_fb_preview.png"/> |
| <meta property="og:description" |
| content="Apache Mesos abstracts resources away from machines, |
| enabling fault-tolerant and elastic distributed systems |
| to easily be built and run effectively."/> |
| |
| <meta name="twitter:card" content="summary"/> |
| <meta name="twitter:site" content="@ApacheMesos"/> |
| <meta name="twitter:title" content="Apache Mesos"/> |
| <meta name="twitter:image" content="http://mesos.apache.org/assets/img/mesos_logo_fb_preview.png"/> |
| <meta name="twitter:description" |
| content="Apache Mesos abstracts resources away from machines, |
| enabling fault-tolerant and elastic distributed systems |
| to easily be built and run effectively."/> |
| |
| <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet"> |
| <link rel="alternate" type="application/atom+xml" title="Apache Mesos Blog" href="/blog/feed.xml"> |
| <link href="../../../assets/css/main.css" media="screen" rel="stylesheet" type="text/css" /> |
| |
| |
| |
| <!-- Google Analytics Magic --> |
| <script type="text/javascript"> |
| var _gaq = _gaq || []; |
| _gaq.push(['_setAccount', 'UA-20226872-1']); |
| _gaq.push(['_setDomainName', 'apache.org']); |
| _gaq.push(['_trackPageview']); |
| |
| (function() { |
| var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; |
| ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; |
| var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); |
| })(); |
| </script> |
| |
| </head> |
| <body> |
| <!-- magical breadcrumbs --> |
| <div class="topnav"> |
| <div class="container"> |
| <ul class="breadcrumb"> |
| <li> |
| <div class="dropdown"> |
| <a data-toggle="dropdown" href="#">Apache Software Foundation <span class="caret"></span></a> |
| <ul class="dropdown-menu" role="menu" aria-labelledby="dLabel"> |
| <li><a href="http://www.apache.org">Apache Homepage</a></li> |
| <li><a href="http://www.apache.org/licenses/">License</a></li> |
| <li><a href="http://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li> |
| <li><a href="http://www.apache.org/foundation/thanks.html">Thanks</a></li> |
| <li><a href="http://www.apache.org/security/">Security</a></li> |
| </ul> |
| </div> |
| </li> |
| |
| <li><a href="http://mesos.apache.org">Apache Mesos</a></li> |
| |
| |
| <li><a href="/documentation |
| /">Documentation |
| </a></li> |
| |
| |
| </ul><!-- /.breadcrumb --> |
| </div><!-- /.container --> |
| </div><!-- /.topnav --> |
| |
| <!-- navbar excitement --> |
| <div class="navbar navbar-default navbar-static-top" role="navigation"> |
| <div class="container"> |
| <div class="navbar-header"> |
| <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#mesos-menu" aria-expanded="false"> |
| <span class="sr-only">Toggle navigation</span> |
| <span class="icon-bar"></span> |
| <span class="icon-bar"></span> |
| <span class="icon-bar"></span> |
| </button> |
| <a class="navbar-brand" href="/"><img src="/assets/img/mesos_logo.png" alt="Apache Mesos logo"/></a> |
| </div><!-- /.navbar-header --> |
| |
| <div class="navbar-collapse collapse" id="mesos-menu"> |
| <ul class="nav navbar-nav navbar-right"> |
| <li><a href="/gettingstarted/">Getting Started</a></li> |
| <li><a href="/blog/">Blog</a></li> |
| <li><a href="/documentation/latest/">Documentation</a></li> |
| <li><a href="/downloads/">Downloads</a></li> |
| <li><a href="/community/">Community</a></li> |
| </ul> |
| </div><!-- /#mesos-menu --> |
| </div><!-- /.container --> |
| </div><!-- /.navbar --> |
| |
| <div class="content"> |
| <div class="container"> |
| <div class="row-fluid"> |
| <div class="col-md-4"> |
| <h4>If you're new to Mesos</h4> |
| <p>See the <a href="/gettingstarted/">getting started</a> page for more |
| information about downloading, building, and deploying Mesos.</p> |
| |
| <h4>If you'd like to get involved or you're looking for support</h4> |
| <p>See our <a href="/community/">community</a> page for more details.</p> |
| </div> |
| <div class="col-md-8"> |
| <h1>Mesos Modules</h1> |
| |
| <p>Experimental support for Mesos modules was introduced in Mesos 0.21.0.</p> |
| |
| <h3>Disclaimer</h3> |
| |
| <ul> |
| <li><p>Use and development of Mesos modules is at own risk!</p></li> |
| <li><p>Please direct all questions to the relevant module writer and/or write to |
| modules@mesos.apache.org. Questions related to modules sent to user and dev list |
| will be redirected to the modules list.</p></li> |
| </ul> |
| |
| |
| <h2>What are Mesos modules?</h2> |
| |
| <p>Mesos modules provide a way to easily extend inner workings of Mesos by creating |
| and using shared libraries that are loaded on demand. Modules can be used to |
| customize Mesos without having to recompiling/relinking for each specific use |
| case. Modules can isolate external dependencies into separate libraries, thus |
| resulting into a smaller Mesos core. |
| Modules also make it easy to experiment with new features. |
| For example, imagine loadable allocators that contain a VM (Lua, Python, …) |
| which makes it possible to try out new allocator algorithms written in |
| scripting languages without forcing those dependencies into the project. |
| Finally, modules provide an easy way for third parties to easily extend Mesos |
| without having to know all the internal details.</p> |
| |
| <h2>Where can Mesos modules be used?</h2> |
| |
| <p>Modules can be specified for master, agent and tests. Modules can also be used |
| with schedulers that link against libmesos. Currently, modules cannot be |
| used with executors.</p> |
| |
| <h2><a name="Invoking"></a>Invoking Mesos modules</h2> |
| |
| <p>There are two ways to specify a list of modules to be loaded and be available to |
| the internal subsystems.</p> |
| |
| <ul> |
| <li><code>--modules=filepath</code> to specify the list of modules via a manifest file |
| containing a JSON-formatted string. ‘filepath’ can be of the form |
| ‘file:///path/to/file’ or ‘/path/to/file’.</li> |
| </ul> |
| |
| |
| <p>Use <code>--modules="{...}"</code> to specify the list of modules inline.</p> |
| |
| <ul> |
| <li><code>--modules_dir=dirpath</code>to specify a directory name that contains several |
| module manifest files. Each file must contain a valid JSON-formatted |
| string containing module description. The module manifest files are processed |
| in alphabetical order.</li> |
| </ul> |
| |
| |
| <p>NOTE: Only one of <code>--modules</code> or <code>--modules_dir</code> flag can be used at time.</p> |
| |
| <h3>Example JSON strings:</h3> |
| |
| <ol> |
| <li><p>Load a library <code>libfoo.so</code> with two modules <code>org_apache_mesos_bar</code> and |
| <code>org_apache_mesos_baz</code>.</p> |
| |
| <pre><code> { |
| "libraries": [ |
| { |
| "file": "/path/to/libfoo.so", |
| "modules": [ |
| { |
| "name": "org_apache_mesos_bar", |
| }, |
| { |
| "name": "org_apache_mesos_baz" |
| } |
| ] |
| } |
| ] |
| } |
| </code></pre></li> |
| <li><p>Load the module <code>org_apache_mesos_bar</code> from the library <code>foo</code> and pass |
| the command-line argument <code>X</code> with value <code>Y</code> (module <code>org_apache_mesos_baz</code> |
| is loaded without any command-line parameters):</p> |
| |
| <pre><code> { |
| "libraries": [ |
| { |
| "name": "foo", |
| "modules": [ |
| { |
| "name": "org_apache_mesos_bar" |
| "parameters": [ |
| { |
| "key": "X", |
| "value": "Y", |
| } |
| ] |
| }, |
| { |
| "name": "org_apache_mesos_baz" |
| } |
| ] |
| } |
| ] |
| } |
| </code></pre></li> |
| <li><p>Specifying modules inline:</p> |
| |
| <pre><code> --modules='{"libraries":[{"file":"/path/to/libfoo.so", "modules":[{"name":"org_apache_mesos_bar"}]}]}' |
| </code></pre></li> |
| </ol> |
| |
| |
| <h3>Library names</h3> |
| |
| <p>For each library, at least one of the “file” or “name” parameter must be |
| specified. The “file” parameter may refer to a filename (e.g., “libfoo.so”), a |
| relative path (e.g., “myLibs/libfoo.so”), or an absolute path (e.g., |
| “/home/mesos/lib/libfoo.so”). The “name” parameter refers to a library name |
| (e.g., “foo”). If “name” is specified, it is automatically expanded to a proper |
| library name for the current platform (e.g., “foo” gets expanded to “libfoo.so” |
| on Linux, and “libfoo.dylib” on OS X).</p> |
| |
| <p>If a library path is not specified in the “file” parameter, the library is |
| searched in the standard library paths or directories pointed to by the |
| <code>LD_LIBRARY_PATH</code> (<code>DYLD_LIBRARY_PATH</code> on OS X) environment variable.</p> |
| |
| <p>If both “file” and “name” are specified, “name” is ignored.</p> |
| |
| <h2>What kinds of modules are supported?</h2> |
| |
| <p>Here are the various module kinds currently available.</p> |
| |
| <h3>Allocator</h3> |
| |
| <p>The Mesos master’s <em>allocator</em> periodically determines which framework(s) should be offered the cluster’s available resources. Allocator modules enable experimenting with specialized resource allocation algorithms. An example of these could be an allocator that provides a feature currently not supported by the built-in Hierarchical Dominant Resource Fairness allocator, like oversubscription with preemption.</p> |
| |
| <p>To load a custom allocator into Mesos master, you need to:</p> |
| |
| <ul> |
| <li><p>Introduce it to the Mesos master by listing it in the <code>--modules</code> configuration,</p></li> |
| <li><p>Select it as the allocator via the <code>--allocator</code> flag.</p></li> |
| </ul> |
| |
| |
| <p>For example, the following command will run the Mesos master with <code>ExternalAllocatorModule</code> (see <a href="#Example-JSON-strings">this section</a> for JSON format):</p> |
| |
| <pre><code>./bin/mesos-master.sh --work_dir=m/work --modules="file://<modules-including-allocator>.json" --allocator=ExternalAllocatorModule |
| </code></pre> |
| |
| <h3>Anonymous</h3> |
| |
| <p>Anonymous modules do <strong>not</strong> receive any callbacks but simply |
| coexists with their parent process.</p> |
| |
| <p>Unlike other named modules, an anonymous module does not directly |
| replace or provide essential Mesos functionality (such as an |
| Isolator module does). Unlike a decorator module it does not |
| directly add or inject data into Mesos core either.</p> |
| |
| <p>Anonymous modules do not require any specific selectors (flags) as |
| they are immediately instantiated when getting loaded via the |
| <code>--modules</code> flag by the Mesos master or agent.</p> |
| |
| <h3>Authentication</h3> |
| |
| <p>Authenticatee and Authenticator modules allow for third parties to quickly |
| develop and plug-in new authentication methods. An example for such modules |
| could be to support PAM (LDAP, MySQL, NIS, UNIX) backed authentication.</p> |
| |
| <h3>Hook</h3> |
| |
| <p>Similar to Apache Webserver Modules, hooks allows module writers to tie into |
| internal components which may not be suitable to be abstracted entirely behind |
| modules but rather lets them define actions on so-called hooks.</p> |
| |
| <p>The available hooks API is defined in mesos/hook.hpp and for each hook defines |
| the insertion point and available context. An example of this context is the |
| task information which is passed to masterLaunchTaskHook.</p> |
| |
| <p>Some hooks take in an object (e.g. TaskInfo) and return all or part of that |
| object (e.g. task labels), so that the hook can modify or replace the contents |
| in-flight. These hooks are referred to as <em>decorators</em>.</p> |
| |
| <p>In order to enable decorator modules to remove metadata (environment variables |
| or labels), the effect of the return value for decorator hooks changed in |
| Mesos 0.23.0.</p> |
| |
| <p>The Result<T> return values before and after Mesos 0.23.0 means:</p> |
| |
| <table class="table table-striped"> |
| <tr> |
| <th>State</th> |
| <th>Before (0.22.x)</th> |
| <th>After (0.23.0+)</th> |
| </tr> |
| <tr> |
| <td>Error</td> |
| <td>Error is propagated to the call-site</td> |
| <td>No change</td> |
| </tr> |
| <tr> |
| <td>None</td> |
| <td>The result of the decorator is not applied</td> |
| <td>No change</td> |
| </tr> |
| <tr> |
| <td>Some</td> |
| <td>The result of the decorator is appended</td> |
| <td>The result of the decorator overwrites the final labels/environment |
| object</td> |
| </tr> |
| </table> |
| |
| |
| <p>To load a hook into Mesos, you need to:</p> |
| |
| <ul> |
| <li><p>introduce it to Mesos by listing it in the <code>--modules</code> configuration,</p></li> |
| <li><p>select it as a hook module via the <code>--hooks</code> flag.</p></li> |
| </ul> |
| |
| |
| <p>For example, the following command will run the Mesos agent with the |
| <code>TestTaskHook</code> hook:</p> |
| |
| <pre><code>./bin/mesos-agent.sh --master=<IP>:<PORT> --modules="file://<path-to-modules-config>.json" --hooks=TestTaskHook |
| </code></pre> |
| |
| <h3>Isolator</h3> |
| |
| <p>Isolator modules enable experimenting with specialized isolation and monitoring |
| capabilities. Examples of these could be 3rdparty resource isolation mechanisms |
| for GPGPU hardware, networking, etc.</p> |
| |
| <p>If a custom isolator module needs to checkpoint state to disk, it should do this |
| on its own; Mesos does not provide public helpers to checkpoint module state. |
| The standard location for such stored state is:</p> |
| |
| <pre><code><runtime_dir>/isolators/<name_of_isolator>/ |
| </code></pre> |
| |
| <h3>Master Contender and Detector</h3> |
| |
| <p>Contender and Detector modules enable developers to implement custom leader |
| election and master detection mechanisms, other than relying on Zookeeper by |
| default.</p> |
| |
| <p>An example for such modules could be to use distributed Key-Value storage such |
| as <a href="https://coreos.com/etcd/">etcd</a> and <a href="https://www.consul.io/">consul</a>.</p> |
| |
| <p>To load custom contender and detector module, you need to:</p> |
| |
| <ul> |
| <li><p>Supply <code>--modules</code> when running Mesos master,</p></li> |
| <li><p>Specify selected contender and detector modules with <code>--master_contender</code> and |
| <code>--master_detector</code> flags on Mesos Master and <code>--master_detector</code> on Mesos Slave.</p></li> |
| </ul> |
| |
| |
| <p>For example, the following command runs Mesos master with |
| <code>org_apache_mesos_TestMasterContender</code> and <code>org_apache_mesos_TestMasterDetector</code>:</p> |
| |
| <p><code>./bin/mesos-master.sh --modules="file://<path-to-modules-config>.json" --master_contender=org_apache_mesos_TestMasterContender --master_detector=org_apache_mesos_TestMasterDetector</code></p> |
| |
| <p>And this one runs Mesos slave with <code>org_apache_mesos_TestMasterDetector</code>:</p> |
| |
| <p><code>./bin/mesos-slave.sh --modules="file://<path-to-modules-config>.json" --master_detector=org_apache_mesos_TestMasterDetector</code></p> |
| |
| <h2>Writing Mesos modules</h2> |
| |
| <h3>A HelloWorld module</h3> |
| |
| <p>The following snippet describes the implementation of a module named |
| “org_apache_mesos_bar” of “TestModule” kind:</p> |
| |
| <pre><code class="{.cpp}">#include <iostream> |
| #include "test_module.hpp" |
| |
| class TestModuleImpl : public TestModule |
| { |
| public: |
| TestModuleImpl() |
| { |
| std::cout << "HelloWorld!" << std::endl; |
| } |
| |
| virtual int foo(char a, long b) |
| { |
| return a + b; |
| } |
| |
| virtual int bar(float a, double b) |
| { |
| return a * b; |
| } |
| }; |
| |
| static TestModule* create() |
| { |
| return new TestModule(); |
| } |
| |
| static bool compatible() |
| { |
| return true; |
| } |
| |
| // Declares a module named 'org_apache_mesos_TestModule' of |
| // 'TestModule' kind. |
| // Mesos core binds the module instance pointer as needed. |
| // The compatible() hook is provided by the module for compatibility checks. |
| // The create() hook returns an object of type 'TestModule'. |
| mesos::modules::Module<TestModule> org_apache_mesos_TestModule( |
| MESOS_MODULE_API_VERSION, |
| MESOS_VERSION, |
| "Apache Mesos", |
| "modules@mesos.apache.org", |
| "This is a test module.", |
| compatible, |
| create); |
| </code></pre> |
| |
| <h3>Building a module</h3> |
| |
| <p> The following assumes that Mesos is installed in the standard location, i.e. |
| the Mesos dynamic library and header files are available.</p> |
| |
| <pre><code>g++ -lmesos -fpic -o test_module.o test_module.cpp |
| $ gcc -shared -o libtest_module.so test_module.o |
| </code></pre> |
| |
| <h3>Testing a module</h3> |
| |
| <p>Apart from testing the module by hand with explicit use of –modules flag, one |
| can run the entire mesos test suite with the given module. For example, the |
| following command will run the mesos test suite with the |
| <code>org_apache_mesos_TestCpuIsolator</code> module selected for isolation:</p> |
| |
| <pre><code>./bin/mesos-tests.sh --modules="/home/kapil/mesos/isolator-module/modules.json" --isolation="org_apache_mesos_TestCpuIsolator" |
| </code></pre> |
| |
| <h3>Module naming convention</h3> |
| |
| <p>Each module name should be unique. Having duplicate module names in the Json |
| string will cause the process to abort.</p> |
| |
| <p>Therefore, we encourage module writers to name their modules according to Java |
| package naming scheme |
| (http://docs.oracle.com/javase/tutorial/java/package/namingpkgs.html).</p> |
| |
| <p>For example:</p> |
| |
| <table class="table table-striped"> |
| <tr> |
| <th> Module Name </th> <th> Module Domain name </th> <th> Module Symbol Name </th> |
| </tr> |
| |
| <tr> |
| <td> foobar </td> <td> mesos.apache.org </td> <td> org_apache_mesos_foobar </td> |
| </tr> |
| |
| <tr> |
| <td> barBaz </td> <td> example.com </td> <td> com_example_barBaz </td> |
| </table> |
| |
| |
| <p>In short: |
| - Keep case of module name. |
| - Lower case and reverse domain. |
| - Separate with underscore. |
| - Do not simply use the kind name as module name. |
| - Different modules from the same organization still need different names.</p> |
| |
| <h2>Module Versioning and backwards compatibility</h2> |
| |
| <p>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 |
| kinds. 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 <code>src/module/manager.cpp</code>. It |
| contains an entry for every possible module kind 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.</p> |
| |
| <p>For successfully loading the module, the following relationship |
| must exist between the various versions:</p> |
| |
| <p><code> kind version <= Library version <= Mesos version</code></p> |
| |
| <table class="table table-striped"> |
| <tr> |
| <td>Mesos </td> <td>kind version </td> <td> Library </td> <td>Is module loadable </td> <td>Reason </td> |
| </tr> |
| |
| <tr> |
| <td>0.18.0 </td> <td> 0.18.0 </td> <td> 0.18.0 </td> <td> yes </td> <td> </td> |
| </tr> |
| |
| <tr> |
| <td>1.0.0 </td> <td> 0.18.0 </td> <td> 0.18.0 </td> <td> yes </td> <td> </td> |
| </tr> |
| |
| <tr> |
| <td>1.0.0 </td> <td> 0.18.0 </td> <td> 0.21.0 </td> <td> yes </td> <td> </td> |
| </tr> |
| |
| <tr> |
| <td>0.18.0 </td> <td> 0.18.0 </td> <td> 1.0.0 </td> <td> NO </td> <td> Library compiled against a newer Mesos release. </td> |
| </tr> |
| |
| <tr> |
| <td>1.0.0 </td> <td> 0.21.0 </td> <td> 0.18.0 </td> <td> NO </td> <td> Module/Library older than the kind version supported by Mesos. </td> |
| </tr> |
| |
| <tr> |
| <td>1.0.0 </td> <td> 1.0.0 </td> <td> 0.18.0 </td> <td> NO </td> <td> Module/Library older than the kind version supported by Mesos. </td> |
| </tr> |
| </table> |
| |
| |
| <h2>Mesos module API changes</h2> |
| |
| <p>Record of incompatible changes to the modules API.</p> |
| |
| <h3>Version 2</h3> |
| |
| <ul> |
| <li>Added support for module-specific command-line parameters.</li> |
| <li>Changed function signature for create().</li> |
| </ul> |
| |
| |
| <h3>Version 1</h3> |
| |
| <p>Initial version of the modules API.</p> |
| |
| <h2>Appendix:</h2> |
| |
| <h3>JSON Schema:</h3> |
| |
| <pre><code>{ |
| "type":"object", |
| "required":false, |
| "properties":{ |
| "libraries":{ |
| "type":"array", |
| "required":false, |
| "items":{ |
| "type":"object", |
| "required":false, |
| "properties":{ |
| "file":{ |
| "type":"string", |
| "required":false |
| }, |
| "name":{ |
| "type":"string", |
| "required":false |
| }, |
| "modules":{ |
| "type":"array", |
| "required":false, |
| "items":{ |
| "type":"object", |
| "required":false, |
| "properties":{ |
| "name":{ |
| "type":"string", |
| "required":true |
| }, |
| "parameters":{ |
| "type":"array", |
| "required":false, |
| "items":{ |
| "type":"object", |
| "required":false, |
| "properties":{ |
| "key":{ |
| "type":"string", |
| "required":true |
| }, |
| "value":{ |
| "type":"string", |
| "required":true |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| </code></pre> |
| |
| </div> |
| </div> |
| |
| </div><!-- /.container --> |
| </div><!-- /.content --> |
| |
| <hr> |
| |
| |
| |
| <!-- footer --> |
| <div class="footer"> |
| <div class="container"> |
| <div class="col-md-4 social-blk"> |
| <span class="social"> |
| <a href="https://twitter.com/ApacheMesos" |
| class="twitter-follow-button" |
| data-show-count="false" data-size="large">Follow @ApacheMesos</a> |
| <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script> |
| <a href="https://twitter.com/intent/tweet?button_hashtag=mesos" |
| class="twitter-hashtag-button" |
| data-size="large" |
| data-related="ApacheMesos">Tweet #mesos</a> |
| <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script> |
| </span> |
| </div> |
| |
| <div class="col-md-8 trademark"> |
| <p>© 2012-2017 <a href="http://apache.org">The Apache Software Foundation</a>. |
| Apache Mesos, the Apache feather logo, and the Apache Mesos project logo are trademarks of The Apache Software Foundation. |
| <p> |
| </div> |
| </div><!-- /.container --> |
| </div><!-- /.footer --> |
| |
| <!-- JS --> |
| <script src="//code.jquery.com/jquery-1.11.0.min.js" type="text/javascript"></script> |
| <script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js" type="text/javascript"></script> |
| </body> |
| </html> |