#ifndef __CONTAINER_MANAGER_HPP__ #define __CONTAINER_MANAGER_HPP__ #include "utils.hpp" #include "argo_container.hpp" #include #include "resource_ownership.hpp" #include "ilogger.hpp" #include "string_parser.hpp" #include "resource_ownership_set.hpp" #include #include "resource_type.hpp" using std::string; using std::vector; class Container_manager { bool _no_separate_service_os; Error_behavior _error_behavior; ILogger* _logger; Argo_container* _root; //is named argo for all resource controllers Argo_container* _service_os_root; Argo_container* _argo_containers_root; vector _containers; Resource_ownership_set _cpu_ownerships; Resource_ownership_set _mem_ownerships; Resource_ownership_set _sos_cpu_ownerships; Resource_ownership_set _sos_mem_ownerships; string _cgroup_root; string _argo_argo_container_root; 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; void get_cpus_breakdown(vector& all_cpus, vector& service_cpus, vector& compute_cpus); void get_mems_breakdown(vector& all_mems, vector& service_mems, vector& compute_mems); void init_cgroup_fs(); Argo_container* find_by_name(const string& name); void create_root_cgroups(); void migrate_service_os(); void load_root_cgroups(); void load_existing_containers_as_root(); //After this, everything first belong to root void apply_ownership_map(); void grant_resources(Argo_container* cc); void reclaim_resources(Argo_container* cc); /*Here, exclusively means that the ownership does not exist yet; but when it * is obtained, it is expected to be exclusively if exclusively is true * */ template bool are_resources_available(Resource_ownership_set& res_ownship_set, const vector& res, bool exclusively = false) { for(int i=0; i<(int)res.size(); i++) { Resource_ownership *ro = res_ownship_set.find_resource_ownership(res[i]); THROW_ON_BAD_INPUT_IF(!ro, "At least 1 requested hardware resource does not exist on the system"); if(!ro->can_increment_owners()) return false; if(exclusively && !ro->can_own_exclusively()) return false; } return true; }; bool is_name_available(const string& name); bool is_legal_create_command(String_parser& sp); /*The resource ownership manipulation methods will throw * on invalid, inconsistent or conflicting situations*/ template void simulate_containers_final_resource_state( const Resource_ownership_set &ros, const vector ¤t, const vector &the_overwrite, const vector &added, const vector &removed, bool is_exclcusive, vector &simulated_final_res_state, Resource_ownership_set &simulated_final_ros_state) { const vector* ref_content = the_overwrite.empty() ? ¤t : &the_overwrite; THROW_ON_BAD_INPUT_IF(!is_superset(*ref_content, removed), "Trying to remove from a container resources that it does not own."); #if 0 THROW_ON_BAD_INPUT_IF(has_intersect(*ref_content, added), "Trying to add to a container resources that it already owns."); THROW_ON_BAD_INPUT_IF(has_intersect(removed, added), "Resources are simultaneously removed and added."); #endif simulated_final_res_state.clear(); if(!the_overwrite.empty()) { simulated_final_ros_state.reclaim(current); simulated_final_ros_state.grant(the_overwrite, is_exclcusive); simulated_final_res_state.assign(the_overwrite.begin(), the_overwrite.end()); } else { simulated_final_res_state.assign(current.begin(), current.end()); } simulated_final_ros_state.grant(added, is_exclcusive); simulated_final_res_state.insert(simulated_final_res_state.end(), added.begin(), added.end()); simulated_final_ros_state.reclaim(removed); for(int i=0; i<(int)removed.size(); i++) { typename vector::iterator it; it = std::find(simulated_final_res_state.begin(), simulated_final_res_state.end(), removed[i]); if(it != simulated_final_res_state.end()) simulated_final_res_state.erase(it); } } /*The resource ownership manipulation methods will throw * on invalid, inconsistent or conflicting situations*/ template void simulate_sos_final_resource_state( const Resource_ownership_set &sos_ros, const Resource_ownership_set &cc_ros, const vector ¤t, const vector &the_overwrite, const vector &added, const vector &removed, vector &simulated_final_res_state, Resource_ownership_set &simulated_final_sos_ros, Resource_ownership_set &simulated_final_cc_ros) { const vector* ref_content = the_overwrite.empty() ? ¤t : &the_overwrite; THROW_ON_BAD_INPUT_IF(!is_superset(*ref_content, removed), "Trying to remove from the service_os resources that it does not own."); THROW_ON_BAD_INPUT_IF(!has_intersect(*ref_content, added), "Trying to add to rthe service_os resources that it already owns."); THROW_ON_BAD_INPUT_IF(!has_intersect(removed, added), "Resources are simultaneously removed and added."); simulated_final_res_state.clear(); if(!the_overwrite.empty()) { simulated_final_sos_ros.transfer_to(current, simulated_final_cc_ros); simulated_final_cc_ros.transfer_to(the_overwrite, simulated_final_sos_ros); simulated_final_res_state.assign(the_overwrite.begin(), the_overwrite.end()); } else simulated_final_res_state.assign(current.begin(), current.end()); simulated_final_sos_ros.transfer_to(removed, simulated_final_cc_ros); simulated_final_cc_ros.transfer_to(added, simulated_final_sos_ros); for(int i=0; i<(int)removed.size(); i++) { typename vector::iterator it; it = std::find(simulated_final_res_state.begin(), simulated_final_res_state.end(), removed[i]); if(it != simulated_final_res_state.end()) simulated_final_res_state.erase(it); } simulated_final_res_state.insert(simulated_final_res_state.end(), added.begin(), added.end()); } /*Check if the alteration wouldn't violate resource ownership rules. * Is used for alter command and assumes an existing container whose name * is provided by sp. Assume that the caller already tested the existence of the * Argo_container*/ template bool has_infeasible_resource_set(String_parser& sp, const string& res_name) { string name; sp.get_string("name", name); Argo_container* ac = find_by_name(name); Resource_ownership_set* simulated_final_ros_state; Resource_type rtype; if(res_name == "cpus") rtype = RT_CPU; else if(res_name == "mems") rtype = RT_MEM; vector current_ac_res; ac->get_resource(current_ac_res, rtype); vector added; vector substracted; return false; } Argo_container* find_host_of_task(int pid); public: Container_manager(ILogger* logger, Error_behavior error_behavior, string cgroup_root = DEFAULT_CGROUP_ROOT); ~Container_manager() #if __cplusplus >= 201103L noexcept(false) #endif ; 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); void delete_container(string command); void alter_container(string command); void attach_to_container(string command); void detach_from_container(string command); void migrate_to_container(string command); void show_config(); void clean_config(string command); void create_service_os(string command); void alter_service_os(string command); void delete_service_os(); void reset(); void exec(string command); }; #endif // __CONTAINER_MANAGER_HPP__