Commit 83beb192 authored by Swann Perarnau's avatar Swann Perarnau

Merge branch 'exec' into 'master'

Add support for command execution in argo_nodeos_config

See merge request !1
parents a8937eb2 f805c49b
...@@ -30,3 +30,13 @@ ...@@ -30,3 +30,13 @@
# Debug files # Debug files
*.dSYM/ *.dSYM/
Makefile
Makefile.in
aclocal.m4
autom4te.cache
config.log
config.status
configure
libtool
m4
.deps
argo_nodeos_config
config.h
config.h.in
stamp-h1
...@@ -524,7 +524,10 @@ enum Option_val ...@@ -524,7 +524,10 @@ enum Option_val
OV_DELETE_SERVICE_OS, OV_DELETE_SERVICE_OS,
OV_RESET OV_RESET,
/*--exec="name:'c0' argv='argv0 argv1'"*/
OV_EXEC
}; };
...@@ -546,6 +549,7 @@ struct option long_options[] = { ...@@ -546,6 +549,7 @@ struct option long_options[] = {
{"detach_from_container", required_argument, NULL, OV_DETACH_FROM_CONTAINER}, {"detach_from_container", required_argument, NULL, OV_DETACH_FROM_CONTAINER},
{"migrate_to_container", required_argument, NULL, OV_MIGRATE_TO_CONTAINER}, {"migrate_to_container", required_argument, NULL, OV_MIGRATE_TO_CONTAINER},
{"reset", no_argument, NULL, OV_RESET}, {"reset", no_argument, NULL, OV_RESET},
{"exec", required_argument, NULL, OV_EXEC},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
...@@ -683,6 +687,9 @@ bool parse_for_node_config(int argc, char** argv, Container_manager& cm) ...@@ -683,6 +687,9 @@ bool parse_for_node_config(int argc, char** argv, Container_manager& cm)
case OV_RESET: case OV_RESET:
cm.reset(); cm.reset();
break; break;
case OV_EXEC:
cm.exec(optarg);
break;
case '?': case '?':
case ':': case ':':
cmd_error = true; cmd_error = true;
...@@ -757,10 +764,19 @@ int main(int argc, char** argv) ...@@ -757,10 +764,19 @@ int main(int argc, char** argv)
argo_exit(EXIT_FAILURE, e.what()); argo_exit(EXIT_FAILURE, e.what());
} }
char** exec_argv = cm->get_exec_argv();
delete cm; delete cm;
rlock.unlock(); rlock.unlock();
release(); release();
/* We perform the execve(2) after all the cleanup is done. */
if (exec_argv)
{
execvp(exec_argv[0], exec_argv);
argo_exit(EXIT_FAILURE, "Command execution failed", errno);
}
argo_exit(EXIT_SUCCESS); argo_exit(EXIT_SUCCESS);
return 0; return 0;
} }
...@@ -275,7 +275,7 @@ void Container_manager::create_root_cgroups() ...@@ -275,7 +275,7 @@ void Container_manager::create_root_cgroups()
void Container_manager::migrate_service_os() void Container_manager::migrate_service_os()
{ {
system("for t in `cat /sys/fs/cgroup/cpuset/tasks`; do /bin/echo $t > /sys/fs/cgroup/cpuset/argo/service_os/tasks; done 2>/dev/null"); int n = system("for t in `cat /sys/fs/cgroup/cpuset/tasks`; do /bin/echo $t > /sys/fs/cgroup/cpuset/argo/service_os/tasks; done 2>/dev/null");
return; return;
vector<int> sos_tasks; vector<int> sos_tasks;
retrieve_from_file<int>( _cgroup_root + "cpuset/tasks", retrieve_from_file<int>( _cgroup_root + "cpuset/tasks",
...@@ -375,6 +375,9 @@ void Container_manager::load_existing_containers_as_root() ...@@ -375,6 +375,9 @@ void Container_manager::load_existing_containers_as_root()
Container_manager::~Container_manager() Container_manager::~Container_manager()
#if __cplusplus >= 201103L
noexcept(false)
#endif
{ {
std::ofstream ownership_map_file; std::ofstream ownership_map_file;
ownership_map_file.open(OWNERSHIP_MAP); ownership_map_file.open(OWNERSHIP_MAP);
...@@ -681,8 +684,8 @@ void Container_manager::alter_service_os(string command) ...@@ -681,8 +684,8 @@ void Container_manager::alter_service_os(string command)
#endif #endif
String_parser sp(command); String_parser sp(command);
sp.parse(); sp.parse();
vector<string> allowed_keys( const char* initkeys[] = {"cpus", "+cpus", "-cpus", "mems", "+mems", "-mems", "mem_migrate"};
{"cpus", "+cpus", "-cpus", "mems", "+mems", "-mems", "mem_migrate"}); vector<string> allowed_keys(initkeys, initkeys + sizeof(initkeys) / sizeof(initkeys[0]));
THROW_ON_BAD_INPUT_IF(sp.has_forbidden_keys(allowed_keys), THROW_ON_BAD_INPUT_IF(sp.has_forbidden_keys(allowed_keys),
"Invalid service_os alteration command"); "Invalid service_os alteration command");
...@@ -766,7 +769,8 @@ void Container_manager::create_service_os(string command) ...@@ -766,7 +769,8 @@ void Container_manager::create_service_os(string command)
"The node already has a service_os"); "The node already has a service_os");
String_parser sp(command); String_parser sp(command);
sp.parse(); sp.parse();
vector<string> allowed_keys({"cpus", "mems"}); const char* initkeys[] = {"cpus", "mems"};
vector<string> allowed_keys(initkeys, initkeys + sizeof(initkeys) / sizeof(initkeys[0]));
THROW_ON_BAD_INPUT_IF(sp.has_forbidden_keys(allowed_keys), THROW_ON_BAD_INPUT_IF(sp.has_forbidden_keys(allowed_keys),
"Invalid service_os creation command"); "Invalid service_os creation command");
...@@ -853,7 +857,7 @@ void Container_manager::reset() ...@@ -853,7 +857,7 @@ void Container_manager::reset()
clean_config(""); clean_config("");
/*Temporary ugly brutal hack [JZ] (\_/)*/ /*Temporary ugly brutal hack [JZ] (\_/)*/
system("rmdir /sys/fs/cgroup/cpuset/argo/argo_containers/ && rmdir /sys/fs/cgroup/cpuset/argo/"); int n = system("rmdir /sys/fs/cgroup/cpuset/argo/argo_containers/ && rmdir /sys/fs/cgroup/cpuset/argo/");
} }
void Container_manager::attach_to_container(string command) void Container_manager::attach_to_container(string command)
...@@ -866,7 +870,7 @@ void Container_manager::attach_to_container(string command) ...@@ -866,7 +870,7 @@ void Container_manager::attach_to_container(string command)
string name; string name;
sp.get_string("name", name); sp.get_string("name", name);
Argo_container *cc = find_by_name(name); Argo_container *cc = find_by_name(name);
THROW_ON_ERRONEOUS_ACTION_IF(!cc, "Container " + name + "does not exists"); THROW_ON_ERRONEOUS_ACTION_IF(!cc, "Container " + name + " does not exists");
vector<int> tasks; vector<int> tasks;
sp.get_int_list("pids", tasks); sp.get_int_list("pids", tasks);
...@@ -921,7 +925,7 @@ void Container_manager::detach_from_container(string command) ...@@ -921,7 +925,7 @@ void Container_manager::detach_from_container(string command)
string name; string name;
sp.get_string("name", name); sp.get_string("name", name);
Argo_container *cc = find_by_name(name); Argo_container *cc = find_by_name(name);
THROW_ON_ERRONEOUS_ACTION_IF(!cc, "Container " + name + "does not exists"); THROW_ON_ERRONEOUS_ACTION_IF(!cc, "Container " + name + " does not exists");
vector<int> tasks; vector<int> tasks;
sp.get_int_list("pids", tasks); sp.get_int_list("pids", tasks);
...@@ -946,7 +950,7 @@ void Container_manager::migrate_to_container(string command) ...@@ -946,7 +950,7 @@ void Container_manager::migrate_to_container(string command)
string name; string name;
sp.get_string("name", name); sp.get_string("name", name);
Argo_container *cc = find_by_name(name); Argo_container *cc = find_by_name(name);
THROW_ON_ERRONEOUS_ACTION_IF(!cc, "Container " + name + "does not exists"); THROW_ON_ERRONEOUS_ACTION_IF(!cc, "Container " + name + " does not exists");
vector<int> tasks; vector<int> tasks;
sp.get_int_list("pids", tasks); sp.get_int_list("pids", tasks);
...@@ -961,12 +965,13 @@ void Container_manager::migrate_to_container(string command) ...@@ -961,12 +965,13 @@ void Container_manager::migrate_to_container(string command)
" because it belongs to another user! Alternatively, the action can be performed as root"); " because it belongs to another user! Alternatively, the action can be performed as root");
std::ostringstream oss; std::ostringstream oss;
for(auto task : tasks) for(vector<int>::iterator task = tasks.begin(); task != tasks.end(); task++)
{ {
bool is_task_contained = false; bool is_task_contained = false;
for(auto cont : _containers) for(vector<Argo_container*>::iterator cont = _containers.begin();
cont != _containers.end(); cont++)
{ {
if(cont->has_task(task)) if((*cont)->has_task(*task))
{ {
is_task_contained = true; is_task_contained = true;
break; break;
...@@ -974,7 +979,7 @@ void Container_manager::migrate_to_container(string command) ...@@ -974,7 +979,7 @@ void Container_manager::migrate_to_container(string command)
} }
if(!is_task_contained) if(!is_task_contained)
{ {
oss<<"Task "<<task<<" is not in any Argo container; it cannot be migrated"; oss<<"Task "<<*task<<" is not in any Argo container; it cannot be migrated";
THROW_ON_ERRONEOUS_ACTION(oss.str()); THROW_ON_ERRONEOUS_ACTION(oss.str());
} }
} }
...@@ -1065,3 +1070,57 @@ void Container_manager::clean_config(string command) ...@@ -1065,3 +1070,57 @@ void Container_manager::clean_config(string command)
_containers.clear(); _containers.clear();
_logger->log(LOG_TYPE_INFO, "Config has been cleaned."); _logger->log(LOG_TYPE_INFO, "Config has been cleaned.");
} }
void Container_manager::exec(string command)
{
String_parser sp(command);
sp.parse();
THROW_ON_BAD_INPUT_IF(!sp.has_key("name") || !sp.has_key("argv"),
"Bad exec command");
string name;
sp.get_string("name", name);
Argo_container *cc = find_by_name(name);
THROW_ON_ERRONEOUS_ACTION_IF(!cc, "Container " + name + " does not exists");
THROW_ON_FORBIDDEN_ACTION_IF(ruid != 0 && (ruid != cc->get_owner()),
"Can't execute in container " + cc->get_name() +
" because it belongs to another user! Alternatively, the action can be performed as root");
string argv;
sp.get_string("argv", argv);
if (argv[0] == '\'') /* Strip ' from both ends. */
argv = argv.substr(1, argv.size() - 2);
vector<string> argvs;
split(argv, ' ', argvs);
/* Remove a single layer of backslashes. */
for (vector<string>::iterator i = argvs.begin(); i != argvs.end(); ++i)
for (string::iterator j = i->begin(); j != i->end(); ++j)
if (*j == '\\')
i->erase(j);
vector<int> tasks(1, getpid());
cc->add_tasks(tasks);
cc->commit_last_changes();
std::ostringstream ss;
ss << "About to execute";
/* We use global allocators so that _exec_argv survives after
the container manager is destroyed. */
_exec_argv = new char*[argvs.size() + 1];
for (int i = 0; i < argvs.size(); i++)
{
_exec_argv[i] = new char[argvs[i].size() + 1];
strcpy(_exec_argv[i], argvs[i].c_str());
ss << " '" << argvs[i] << "'";
}
_exec_argv[argvs.size()] = NULL;
_logger->log(LOG_TYPE_INFO, ss.str());
}
...@@ -33,6 +33,8 @@ class Container_manager ...@@ -33,6 +33,8 @@ class Container_manager
string _argo_service_os_cgroup; string _argo_service_os_cgroup;
string _argo_argo_containers_root; string _argo_argo_containers_root;
char ** _exec_argv;
Container_manager(Container_manager& orig) = delete; Container_manager(Container_manager& orig) = delete;
Container_manager& operator = (const Container_manager& orig) = delete; Container_manager& operator = (const Container_manager& orig) = delete;
...@@ -223,11 +225,16 @@ class Container_manager ...@@ -223,11 +225,16 @@ class Container_manager
Container_manager(ILogger* logger, Container_manager(ILogger* logger,
Error_behavior error_behavior, Error_behavior error_behavior,
string cgroup_root = DEFAULT_CGROUP_ROOT); string cgroup_root = DEFAULT_CGROUP_ROOT);
~Container_manager(); ~Container_manager()
#if __cplusplus >= 201103L
noexcept(false)
#endif
;
inline const string* const get_argo_argo_container_root() const {return &_cgroup_root;} inline const string* const get_argo_argo_container_root() const {return &_cgroup_root;}
inline Error_behavior get_error_behaviour()const {return _error_behavior;} inline Error_behavior get_error_behaviour()const {return _error_behavior;}
inline ILogger* get_logger() const {return _logger;} inline ILogger* get_logger() const {return _logger;}
inline char** get_exec_argv() const {return _exec_argv;}
void show_available_resources(string command); void show_available_resources(string command);
void create_container(string command); void create_container(string command);
...@@ -243,6 +250,7 @@ class Container_manager ...@@ -243,6 +250,7 @@ class Container_manager
void alter_service_os(string command); void alter_service_os(string command);
void delete_service_os(); void delete_service_os();
void reset(); void reset();
void exec(string command);
}; };
#endif // __CONTAINER_MANAGER_HPP__ #endif // __CONTAINER_MANAGER_HPP__
......
...@@ -31,7 +31,7 @@ Resource_locker::Resource_locker(const string& filename, const string& path): ...@@ -31,7 +31,7 @@ Resource_locker::Resource_locker(const string& filename, const string& path):
TRACE_LOC_ON_MASK(RESOURCE_LOCKER_MASK, "euid = %d; ruid = %d\n", TRACE_LOC_ON_MASK(RESOURCE_LOCKER_MASK, "euid = %d; ruid = %d\n",
geteuid(), getuid()); geteuid(), getuid());
_fd = open(fname.c_str(), O_WRONLY|O_CREAT); _fd = open(fname.c_str(), O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
if(_fd == -1) if(_fd == -1)
{ {
argo_exit(EXIT_FAILURE, "Failure to open " + filename); argo_exit(EXIT_FAILURE, "Failure to open " + filename);
......
...@@ -39,5 +39,5 @@ void Syslogger::log(Log_type type, const string& message, int errnum) ...@@ -39,5 +39,5 @@ void Syslogger::log(Log_type type, const string& message, int errnum)
{ {
string msg_out; string msg_out;
if(prepare_log(type, message, msg_out, errnum)) if(prepare_log(type, message, msg_out, errnum))
syslog(log_type_to_priority(type), msg_out.c_str()); syslog(log_type_to_priority(type), "%s", msg_out.c_str());
} }
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
vector<string> &split(const string &str_in, char delim, vector<string> &tokens) vector<string> &split(const string &str_in, char delim, vector<string> &tokens)
{ {
#if 0
std::stringstream ss(str_in); std::stringstream ss(str_in);
string token; string token;
tokens.clear(); tokens.clear();
...@@ -32,6 +33,9 @@ vector<string> &split(const string &str_in, char delim, vector<string> &tokens) ...@@ -32,6 +33,9 @@ vector<string> &split(const string &str_in, char delim, vector<string> &tokens)
tokens.push_back(token); tokens.push_back(token);
} }
return tokens; return tokens;
#endif
string delims(1, delim);
return split(str_in, delims, tokens);
} }
vector<string> &split(const string &str_in, const string &delims, vector<string> &split(const string &str_in, const string &delims,
...@@ -49,12 +53,37 @@ vector<string> &split(const string &str_in, const string &delims, ...@@ -49,12 +53,37 @@ vector<string> &split(const string &str_in, const string &delims,
for(int i=0; i<(int)delims.size(); i++) for(int i=0; i<(int)delims.size(); i++)
{ {
for(int j=start; j<length; j++) for(int j=start; j<length; j++)
{
if(str_in[j] == '\\')
{
j++;
continue;
}
if(str_in[j] == '\'')
{
for (j++; j<length; j++)
{
if(str_in[j] == '\\')
{
j++;
continue;
}
if (str_in[j] == '\'')
break;
}
if (j == length) /* Parse error */
{
tokens.clear();
return tokens;
}
}
if(str_in[j] == delims[i]) if(str_in[j] == delims[i])
{ {
next_delim_pos = MIN(j,next_delim_pos); next_delim_pos = MIN(j,next_delim_pos);
found = true; found = true;
break; break;
} }
}
} }
if(found) if(found)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment