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

Add exec support

parent cb21d37e
......@@ -524,7 +524,10 @@ enum Option_val
OV_DELETE_SERVICE_OS,
OV_RESET
OV_RESET,
/*--exec="name:'c0' argv='argv0 argv1'"*/
OV_EXEC
};
......@@ -546,6 +549,7 @@ struct option long_options[] = {
{"detach_from_container", required_argument, NULL, OV_DETACH_FROM_CONTAINER},
{"migrate_to_container", required_argument, NULL, OV_MIGRATE_TO_CONTAINER},
{"reset", no_argument, NULL, OV_RESET},
{"exec", required_argument, NULL, OV_EXEC},
{0, 0, 0, 0}
};
......@@ -683,6 +687,9 @@ bool parse_for_node_config(int argc, char** argv, Container_manager& cm)
case OV_RESET:
cm.reset();
break;
case OV_EXEC:
cm.exec(optarg);
break;
case '?':
case ':':
cmd_error = true;
......@@ -757,10 +764,19 @@ int main(int argc, char** argv)
argo_exit(EXIT_FAILURE, e.what());
}
char** exec_argv = cm->get_exec_argv();
delete cm;
rlock.unlock();
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);
return 0;
}
......@@ -869,7 +869,7 @@ void Container_manager::attach_to_container(string 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_ERRONEOUS_ACTION_IF(!cc, "Container " + name + " does not exists");
vector<int> tasks;
sp.get_int_list("pids", tasks);
......@@ -924,7 +924,7 @@ void Container_manager::detach_from_container(string 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_ERRONEOUS_ACTION_IF(!cc, "Container " + name + " does not exists");
vector<int> tasks;
sp.get_int_list("pids", tasks);
......@@ -949,7 +949,7 @@ void Container_manager::migrate_to_container(string 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_ERRONEOUS_ACTION_IF(!cc, "Container " + name + " does not exists");
vector<int> tasks;
sp.get_int_list("pids", tasks);
......@@ -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");
std::ostringstream oss;
for(auto task : tasks)
for(vector<int>::iterator task = tasks.begin(); task != tasks.end(); task++)
{
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;
break;
......@@ -977,7 +978,7 @@ void Container_manager::migrate_to_container(string command)
}
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());
}
}
......@@ -1068,3 +1069,57 @@ void Container_manager::clean_config(string command)
_containers.clear();
_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
string _argo_service_os_cgroup;
string _argo_argo_containers_root;
char ** _exec_argv;
Container_manager(Container_manager& orig) = delete;
Container_manager& operator = (const Container_manager& orig) = delete;
......@@ -232,6 +234,7 @@ class Container_manager
inline const string* const get_argo_argo_container_root() const {return &_cgroup_root;}
inline Error_behavior get_error_behaviour()const {return _error_behavior;}
inline ILogger* get_logger() const {return _logger;}
inline char** get_exec_argv() const {return _exec_argv;}
void show_available_resources(string command);
void create_container(string command);
......@@ -247,6 +250,7 @@ class Container_manager
void alter_service_os(string command);
void delete_service_os();
void reset();
void exec(string command);
};
#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