Commit 174a63f7 authored by Kamil Iskra's avatar Kamil Iskra

Add exec support

parent cb21d37e
...@@ -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)
{
execv(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;
} }
...@@ -869,7 +869,7 @@ void Container_manager::attach_to_container(string command) ...@@ -869,7 +869,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);
...@@ -924,7 +924,7 @@ void Container_manager::detach_from_container(string command) ...@@ -924,7 +924,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);
...@@ -949,7 +949,7 @@ void Container_manager::migrate_to_container(string command) ...@@ -949,7 +949,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);
...@@ -964,12 +964,13 @@ void Container_manager::migrate_to_container(string command) ...@@ -964,12 +964,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;
...@@ -977,7 +978,7 @@ void Container_manager::migrate_to_container(string command) ...@@ -977,7 +978,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());
} }
} }
...@@ -1068,3 +1069,57 @@ void Container_manager::clean_config(string command) ...@@ -1068,3 +1069,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 (auto 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;
...@@ -232,6 +234,7 @@ class Container_manager ...@@ -232,6 +234,7 @@ class Container_manager
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);
...@@ -247,6 +250,7 @@ class Container_manager ...@@ -247,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__
......
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