Merge pull request #13 from Telecominfraproject/exec

mux: add exec platform adapter
This commit is contained in:
Wataru Ishida
2020-10-21 15:55:36 -07:00
committed by GitHub
7 changed files with 174 additions and 2 deletions

View File

@@ -16,7 +16,9 @@ modules and decides which `libtai.so` to use for detected modules.
platform adapter. User can choose which platform adapter to use by
passing an environment variable `TAI_MUX_PLATFORM_ADAPTER`.
Currently, only `static` platform adapter is supported.
Currently, `static` platform adapter and `exec` platform adapter is supported.
By default, `TAI_MUX_PLATFORM_ADAPTER` is set to `static`.
#### static platform adapter
@@ -48,6 +50,24 @@ is 5,6,7,8.
An environment variable `TAI_MUX_STATIC_CONFIG_FILE` is used to let the
static platform adapter know the location of the configuration file.
#### exec platform adapter
exec platform adapter is a platform adapter which executes a prespecified script.
User can choose what script to execute by using an environment variable `TAI_MUX_EXEC_SCRIPT`.
By default, `TAI_MUX_EXEC_SCRIPT` is set to `/etc/tai/mux/exec.sh`.
exec platform adapter executes this script in two ways.
The first way is to get the list of modules during the initialization phase.
In this case, exec platform adapter passes 'list' as the first argument.
The script must return the list of modules which is separated by a newline, or "\n".
The second way is to get the actual TAI library to use for a module when TAI adapter host tries to create a module.
In this case, exec platform adapter passes the module location as the first argument.
The script must return the TAI library name. If the module doesn't exist in the specified location, the script must exit with non-zero value.
### HOW TO BUILD
```

View File

@@ -7,6 +7,7 @@ typedef enum _tai_mux_platform_adapter_type_t
{
TAI_MUX_PLATFORM_ADAPTER_TYPE_UNKNOWN,
TAI_MUX_PLATFORM_ADAPTER_TYPE_STATIC,
TAI_MUX_PLATFORM_ADAPTER_TYPE_EXEC,
TAI_MUX_PLATFORM_ADAPTER_TYPE_MAX,
} tai_mux_platform_adapter_type_t;

View File

@@ -0,0 +1,92 @@
#include "exec_platform_adapter.hpp"
#include <cstdlib>
#include <cstdio>
#include <sstream>
namespace tai::mux {
// trim from end (in place)
static inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
return std::isgraph(ch);
}).base(), s.end());
}
static int exec(const std::string& cmd, std::string& output) {
FILE* pipe = popen(cmd.c_str(), "r");
if (!pipe) return -1;
char buffer[128] = {};
while (!feof(pipe)) {
if (fgets(buffer, 128, pipe) != NULL)
output += buffer;
}
return WEXITSTATUS(pclose(pipe));
}
static int exec_script(const std::string& arg, std::string& output) {
std::stringstream ss;
std::string script = TAI_MUX_EXEC_DEFAULT_SCRIPT;
auto e = std::getenv(TAI_MUX_EXEC_SCRIPT.c_str());
if ( e != nullptr ) {
script = e;
}
ss << script;
ss << " ";
ss << arg;
auto ret = exec(ss.str(), output);
if ( ret != 0 ) {
TAI_ERROR("failed to execute %s: ret: %d", script.c_str(), ret);
return ret;
}
rtrim(output);
return 0;
}
ExecPlatformAdapter::ExecPlatformAdapter(uint64_t flags, const tai_service_method_table_t* services) : m_flags(flags) {
m_services.module_presence = nullptr;
if ( services != nullptr ) {
m_services.get_module_io_handler = services->get_module_io_handler;
}
if ( services != nullptr && services->module_presence != nullptr ) {
std::string output;
auto ret = exec_script("list", output);
if ( ret != 0 ) {
throw Exception(TAI_STATUS_FAILURE);
}
TAI_DEBUG("result of list: %s", output.c_str());
std::stringstream ss(output);
std::string location;
while(getline(ss, location)) {
services->module_presence(true, const_cast<char*>(location.c_str()));
}
}
}
ExecPlatformAdapter::~ExecPlatformAdapter() {
for ( auto& m : m_ma_map ) {
m.second->tai_api_uninitialize();
}
}
S_ModuleAdapter ExecPlatformAdapter::get_module_adapter(const std::string& location) {
std::string lib;
auto ret = exec_script(location, lib);
if ( ret != 0 ) {
TAI_ERROR("script failed: %d", ret);
return nullptr;
}
auto dl = ModuleAdapter::dl_address(lib);
S_ModuleAdapter ma;
if ( dl == 0 ) {
ma = std::make_shared<ModuleAdapter>(lib, m_flags, &m_services);
dl = ModuleAdapter::dl_address(lib);
m_lib_map[dl] = ma;
} else {
ma = m_lib_map[dl];
}
m_ma_map[location] = ma;
return ma;
}
}

View File

@@ -0,0 +1,48 @@
#ifndef __EXEC_PLATFORM_ADAPTER_HPP__
#define __EXEC_PLATFORM_ADAPTER_HPP__
#include <thread>
#include <map>
#include <cstdlib>
#include <fstream>
#include <string>
#include "platform_adapter.hpp"
#include "module_adapter.hpp"
#include "tai.h"
#include "json.hpp"
namespace tai::mux {
using json = nlohmann::json;
const std::string TAI_MUX_EXEC_SCRIPT = "TAI_MUX_EXEC_SCRIPT";
const std::string TAI_MUX_EXEC_DEFAULT_SCRIPT = "/etc/tai/mux/exec.sh";
class ExecPlatformAdapter : public PlatformAdapter {
public:
ExecPlatformAdapter(uint64_t flags, const tai_service_method_table_t* services);
~ExecPlatformAdapter();
S_ModuleAdapter get_module_adapter(const std::string& location);
const std::unordered_set<S_ModuleAdapter> list_module_adapters() {
std::unordered_set<S_ModuleAdapter> set;
for ( auto m : m_ma_map ) {
set.emplace(m.second);
}
return set;
};
virtual tai_mux_platform_adapter_type_t type() const {
return TAI_MUX_PLATFORM_ADAPTER_TYPE_EXEC;
}
private:
std::map<uint64_t, S_ModuleAdapter> m_lib_map;
std::map<std::string, S_ModuleAdapter> m_ma_map;
std::thread m_th;
tai_service_method_table_t m_services;
const uint64_t m_flags;
};
};
#endif

View File

@@ -14,6 +14,7 @@ namespace tai::mux {
ModuleAdapter::ModuleAdapter(const std::string& name, uint64_t flags, const tai_service_method_table_t* services) : m_name(name) {
m_dl = dlopen(name.c_str(), RTLD_NOW | RTLD_DEEPBIND);
if ( m_dl == nullptr ) {
TAI_ERROR("dlerror: %s", dlerror());
throw std::runtime_error(dlerror());
}
LOAD_TAI_API(tai_api_initialize)

View File

@@ -1,6 +1,8 @@
#include "mux.hpp"
#include <iostream>
#include "taimetadata.h"
#include "static_platform_adapter.hpp"
#include "exec_platform_adapter.hpp"
namespace tai::mux {
@@ -35,11 +37,16 @@ namespace tai::mux {
tai_mux_platform_adapter_type_t pa_type;
if ( pa_name == "static" ) {
pa_type = TAI_MUX_PLATFORM_ADAPTER_TYPE_STATIC;
} else if ( pa_name == "exec" ) {
pa_type = TAI_MUX_PLATFORM_ADAPTER_TYPE_EXEC;
}
switch ( pa_type ) {
case TAI_MUX_PLATFORM_ADAPTER_TYPE_STATIC:
m_pa = std::make_shared<StaticPlatformAdapter>(0, services);
break;
case TAI_MUX_PLATFORM_ADAPTER_TYPE_EXEC:
m_pa = std::make_shared<ExecPlatformAdapter>(0, services);
break;
default:
TAI_ERROR("unsupported platform_adapter: %s", pa_name.c_str());
throw Exception(TAI_STATUS_NOT_SUPPORTED);
@@ -162,6 +169,10 @@ namespace tai::mux {
}
tai_status_t Platform::set_log(tai_api_t api, tai_log_level_t level, tai_log_fn log_fn) {
auto ret = tai::Logger::get_instance().set_log(api, level, log_fn);
if ( ret != TAI_STATUS_SUCCESS ) {
return ret;
}
auto set = m_pa->list_module_adapters();
for ( const auto& a : set ) {
auto ret = a->tai_log_set(api, level, log_fn);

View File

@@ -3,7 +3,6 @@
#include <string>
#include "platform_adapter.hpp"
#include "static_platform_adapter.hpp"
#include "module_adapter.hpp"
#include "tai.h"
#include <mutex>