container_manager.hpp 7.72 KB
Newer Older
Swann Perarnau's avatar
Swann Perarnau committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
#ifndef __CONTAINER_MANAGER_HPP__
#define __CONTAINER_MANAGER_HPP__
#include "utils.hpp"
#include "argo_container.hpp"
#include <string>
#include "resource_ownership.hpp"
#include "ilogger.hpp"
#include "string_parser.hpp"
#include "resource_ownership_set.hpp"
#include <vector>
#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<Argo_container*> _containers;
	Resource_ownership_set<int> _cpu_ownerships;
	Resource_ownership_set<int> _mem_ownerships;
	Resource_ownership_set<int> _sos_cpu_ownerships;
	Resource_ownership_set<int> _sos_mem_ownerships;
	string _cgroup_root;
	string _argo_argo_container_root;
	string _argo_service_os_cgroup;
	string _argo_argo_containers_root;

	Container_manager(Container_manager& orig) = delete;
	Container_manager& operator = (const Container_manager& orig) = delete;

	void get_cpus_breakdown(vector<int>& all_cpus, 
			vector<int>& service_cpus, vector<int>& compute_cpus);
	void get_mems_breakdown(vector<int>& all_mems,
		   	vector<int>& service_mems, 
			vector<int>& 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 <typename T>
	bool are_resources_available(Resource_ownership_set<T>& res_ownship_set,
			const vector<T>& res, bool exclusively = false)
	{
		for(int i=0; i<(int)res.size(); i++)
		{
			Resource_ownership<T> *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<typename T>
	void simulate_containers_final_resource_state(
			const Resource_ownership_set<T> &ros,
			const vector<T> &current, const vector<T> &the_overwrite, 
			const vector<T> &added, const vector<T> &removed, bool is_exclcusive,
			vector<T> &simulated_final_res_state,
			Resource_ownership_set<T> &simulated_final_ros_state)
	{
		const vector<T>* ref_content = the_overwrite.empty() ? &current :
		   	&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<T>::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<typename T>
	void simulate_sos_final_resource_state(
			const Resource_ownership_set<T> &sos_ros,
			const Resource_ownership_set<T> &cc_ros,
			const vector<T> &current, const vector<T> &the_overwrite, 
			const vector<T> &added, const vector<T> &removed,
			vector<T> &simulated_final_res_state,
			Resource_ownership_set<T> &simulated_final_sos_ros,
			Resource_ownership_set<T> &simulated_final_cc_ros)
	{
		const vector<T>* ref_content = the_overwrite.empty() ? &current :
		   	&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<T>::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 <typename T>
	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<T>* simulated_final_ros_state;

		Resource_type rtype;
		if(res_name == "cpus")
			rtype = RT_CPU;
		else if(res_name == "mems")
			rtype = RT_MEM;
		vector<T> current_ac_res;
		ac->get_resource<T>(current_ac_res, rtype);
		vector<T> added;
		vector<T> 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();

		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;}

		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();
};
#endif // __CONTAINER_MANAGER_HPP__