container_manager.hpp 7.88 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
#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;

Kamil Iskra's avatar
Kamil Iskra committed
36
37
	char ** _exec_argv;

Swann Perarnau's avatar
Swann Perarnau committed
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
	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);
Kamil Iskra's avatar
Kamil Iskra committed
228
229
230
231
232
		~Container_manager()
#if __cplusplus >= 201103L
		noexcept(false)
#endif
		;
Swann Perarnau's avatar
Swann Perarnau committed
233
234
235
236

		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;}
Kamil Iskra's avatar
Kamil Iskra committed
237
		inline char** get_exec_argv() const {return _exec_argv;}
Swann Perarnau's avatar
Swann Perarnau committed
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252

		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();
Kamil Iskra's avatar
Kamil Iskra committed
253
		void exec(string command);
Swann Perarnau's avatar
Swann Perarnau committed
254
255
256
257
};
#endif // __CONTAINER_MANAGER_HPP__