wf_node_api 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/Gemfile +28 -0
- data/Gemfile.lock +66 -0
- data/LICENSE +340 -0
- data/Makefile +19 -0
- data/README.md +78 -0
- data/Rakefile +2 -0
- data/Vagrantfile +102 -0
- data/_docs/api/Api/NodeApi.html +123 -0
- data/_docs/api/Api.html +149 -0
- data/_docs/api/Config/Check.html +331 -0
- data/_docs/api/Config.html +115 -0
- data/_docs/api/ConfigCheck.html +365 -0
- data/_docs/api/ContainerManager.html +1632 -0
- data/_docs/api/ContainerManagerAdapter/Lxc.html +1352 -0
- data/_docs/api/ContainerManagerAdapter/Vserver.html +1358 -0
- data/_docs/api/ContainerManagerAdapter.html +151 -0
- data/_docs/api/Error/NotFound.html +134 -0
- data/_docs/api/Error.html +115 -0
- data/_docs/api/NotFoundError.html +157 -0
- data/_docs/api/OS.html +234 -0
- data/_docs/api/ResourceManager.html +322 -0
- data/_docs/api/ResourceManagerAdapter/Linux.html +326 -0
- data/_docs/api/ResourceManagerAdapter.html +149 -0
- data/_docs/api/WfNodeApi.html +163 -0
- data/_docs/api/_index.html +239 -0
- data/_docs/api/class_list.html +58 -0
- data/_docs/api/css/common.css +1 -0
- data/_docs/api/css/full_list.css +57 -0
- data/_docs/api/css/style.css +339 -0
- data/_docs/api/file.README.html +146 -0
- data/_docs/api/file_list.html +60 -0
- data/_docs/api/frames.html +26 -0
- data/_docs/api/index.html +146 -0
- data/_docs/api/js/app.js +219 -0
- data/_docs/api/js/full_list.js +181 -0
- data/_docs/api/js/jquery.js +4 -0
- data/_docs/api/method_list.html +273 -0
- data/_docs/api/top-level-namespace.html +244 -0
- data/_docs/rest/api_data.js +1 -0
- data/_docs/rest/api_data.json +1 -0
- data/_docs/rest/api_project.js +1 -0
- data/_docs/rest/api_project.json +1 -0
- data/_docs/rest/css/style.css +538 -0
- data/_docs/rest/header.md +3 -0
- data/_docs/rest/img/favicon.ico +0 -0
- data/_docs/rest/img/glyphicons-halflings-white.png +0 -0
- data/_docs/rest/img/glyphicons-halflings.png +0 -0
- data/_docs/rest/index.html +658 -0
- data/_docs/rest/locales/de.js +25 -0
- data/_docs/rest/locales/fr.js +25 -0
- data/_docs/rest/locales/locale.js +43 -0
- data/_docs/rest/locales/nl.js +25 -0
- data/_docs/rest/locales/pl.js +25 -0
- data/_docs/rest/locales/pt_br.js +25 -0
- data/_docs/rest/locales/ru.js +25 -0
- data/_docs/rest/locales/zh.js +25 -0
- data/_docs/rest/main.js +691 -0
- data/_docs/rest/utils/handlebars_helper.js +327 -0
- data/_docs/rest/utils/send_sample_request.js +158 -0
- data/_docs/rest/vendor/bootstrap-responsive.min.css +9 -0
- data/_docs/rest/vendor/bootstrap.min.css +9 -0
- data/_docs/rest/vendor/bootstrap.min.js +6 -0
- data/_docs/rest/vendor/diff_match_patch.min.js +49 -0
- data/_docs/rest/vendor/handlebars.min.js +28 -0
- data/_docs/rest/vendor/jquery.min.js +4 -0
- data/_docs/rest/vendor/lodash.min.js +61 -0
- data/_docs/rest/vendor/path-to-regexp/LICENSE +21 -0
- data/_docs/rest/vendor/path-to-regexp/index.js +205 -0
- data/_docs/rest/vendor/polyfill.js +100 -0
- data/_docs/rest/vendor/prettify/lang-apollo.js +2 -0
- data/_docs/rest/vendor/prettify/lang-basic.js +3 -0
- data/_docs/rest/vendor/prettify/lang-clj.js +18 -0
- data/_docs/rest/vendor/prettify/lang-css.js +2 -0
- data/_docs/rest/vendor/prettify/lang-dart.js +3 -0
- data/_docs/rest/vendor/prettify/lang-erlang.js +2 -0
- data/_docs/rest/vendor/prettify/lang-go.js +1 -0
- data/_docs/rest/vendor/prettify/lang-hs.js +2 -0
- data/_docs/rest/vendor/prettify/lang-lisp.js +3 -0
- data/_docs/rest/vendor/prettify/lang-llvm.js +1 -0
- data/_docs/rest/vendor/prettify/lang-lua.js +2 -0
- data/_docs/rest/vendor/prettify/lang-matlab.js +6 -0
- data/_docs/rest/vendor/prettify/lang-ml.js +2 -0
- data/_docs/rest/vendor/prettify/lang-mumps.js +2 -0
- data/_docs/rest/vendor/prettify/lang-n.js +4 -0
- data/_docs/rest/vendor/prettify/lang-pascal.js +3 -0
- data/_docs/rest/vendor/prettify/lang-proto.js +1 -0
- data/_docs/rest/vendor/prettify/lang-r.js +2 -0
- data/_docs/rest/vendor/prettify/lang-rd.js +1 -0
- data/_docs/rest/vendor/prettify/lang-scala.js +2 -0
- data/_docs/rest/vendor/prettify/lang-sql.js +2 -0
- data/_docs/rest/vendor/prettify/lang-tcl.js +3 -0
- data/_docs/rest/vendor/prettify/lang-tex.js +1 -0
- data/_docs/rest/vendor/prettify/lang-vb.js +2 -0
- data/_docs/rest/vendor/prettify/lang-vhdl.js +3 -0
- data/_docs/rest/vendor/prettify/lang-wiki.js +2 -0
- data/_docs/rest/vendor/prettify/lang-xq.js +3 -0
- data/_docs/rest/vendor/prettify/lang-yaml.js +2 -0
- data/_docs/rest/vendor/prettify/prettify.css +1 -0
- data/_docs/rest/vendor/prettify/prettify.js +30 -0
- data/_docs/rest/vendor/prettify/run_prettify.js +34 -0
- data/_docs/rest/vendor/prettify.css +101 -0
- data/_docs/rest/vendor/require.min.js +36 -0
- data/apidoc.json +23 -0
- data/bin/wf_node_api +80 -0
- data/lib/wf_node_api/api/node_api.rb +360 -0
- data/lib/wf_node_api/config/config_template.erb +50 -0
- data/lib/wf_node_api/config_check.rb +50 -0
- data/lib/wf_node_api/container_manager.rb +286 -0
- data/lib/wf_node_api/container_manager_adapter/lxc.rb +431 -0
- data/lib/wf_node_api/container_manager_adapter/vserver.rb +448 -0
- data/lib/wf_node_api/error/not_found.rb +27 -0
- data/lib/wf_node_api/os.rb +32 -0
- data/lib/wf_node_api/resource_manager.rb +49 -0
- data/lib/wf_node_api/resource_manager_adapter/linux.rb +53 -0
- data/lib/wf_node_api/translations.rb +38 -0
- data/lib/wf_node_api/version.rb +28 -0
- data/lib/wf_node_api.rb +57 -0
- data/manifests/files/dhozac-vserver.repo +4 -0
- data/wf-node-api.gemspec +53 -0
- metadata +221 -0
@@ -0,0 +1,431 @@
|
|
1
|
+
=begin
|
2
|
+
__ ___ _ _ _____ ____ __ __
|
3
|
+
\ \ / / |__ (_) |_ ___| ___| _ ___ ___ / ___| \/ |
|
4
|
+
\ \ /\ / /| '_ \| | __/ _ \ |_ | | | / __|/ _ \ | | |\/| |
|
5
|
+
\ V V / | | | | | || __/ _|| |_| \__ \ __/ |___| | | |
|
6
|
+
\_/\_/ |_| |_|_|\__\___|_| \__,_|___/\___|\____|_| |_|
|
7
|
+
Container Manager
|
8
|
+
|
9
|
+
Copyright (C) 2015 David Prandzioch <kontakt@davidprandzioch.de>
|
10
|
+
|
11
|
+
This program is free software; you can redistribute it and/or
|
12
|
+
modify it under the terms of the GNU General Public License
|
13
|
+
as published by the Free Software Foundation; either version 2
|
14
|
+
of the License, or (at your option) any later version.
|
15
|
+
|
16
|
+
This program is distributed in the hope that it will be useful,
|
17
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
18
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
19
|
+
GNU General Public License for more details.
|
20
|
+
|
21
|
+
You should have received a copy of the GNU General Public License
|
22
|
+
along with this program; if not, write to the Free Software
|
23
|
+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
24
|
+
=end
|
25
|
+
|
26
|
+
module ContainerManagerAdapter
|
27
|
+
# Container adapter for LXC. Encapsulates all LXC specific command line
|
28
|
+
# wrapping
|
29
|
+
class Lxc
|
30
|
+
# Lists all available containers
|
31
|
+
#
|
32
|
+
# @return [Array]
|
33
|
+
def containers
|
34
|
+
container_list = []
|
35
|
+
|
36
|
+
self.container_names.each do |item|
|
37
|
+
container_list << container(item)
|
38
|
+
end
|
39
|
+
|
40
|
+
container_list
|
41
|
+
end
|
42
|
+
|
43
|
+
# Starts a container with the given name
|
44
|
+
#
|
45
|
+
# @param name [String] The container name
|
46
|
+
#
|
47
|
+
# @raise [RuntimeError]
|
48
|
+
#
|
49
|
+
# @return [String] CLI output
|
50
|
+
def start(name)
|
51
|
+
res = Open3.capture3($lxc_cmd_start.gsub('[name]', name))
|
52
|
+
|
53
|
+
if res[1].empty? && res[2].exitstatus == 0
|
54
|
+
$logger.info("container " + name + " successfully started")
|
55
|
+
return res[0].strip
|
56
|
+
end
|
57
|
+
|
58
|
+
$logger.warn("container " + name + " could not be started")
|
59
|
+
raise RuntimeError, res[1].strip
|
60
|
+
end
|
61
|
+
|
62
|
+
# Stops a container with the given name
|
63
|
+
#
|
64
|
+
# @param name [String] The container name
|
65
|
+
#
|
66
|
+
# @raise [RuntimeError]
|
67
|
+
#
|
68
|
+
# @return [String] CLI output
|
69
|
+
def stop(name)
|
70
|
+
res = Open3.capture3($lxc_cmd_stop.gsub('[name]', name))
|
71
|
+
|
72
|
+
if res[1].empty? && res[2].exitstatus == 0
|
73
|
+
$logger.info("container " + name + " successfully stopped")
|
74
|
+
return res[0].strip
|
75
|
+
end
|
76
|
+
|
77
|
+
$logger.warn("container " + name + " could not be stopped")
|
78
|
+
raise RuntimeError, res[1].strip
|
79
|
+
end
|
80
|
+
|
81
|
+
# Kills a container with the given name
|
82
|
+
#
|
83
|
+
# @param name [String] The container name
|
84
|
+
#
|
85
|
+
# @raise [RuntimeError]
|
86
|
+
#
|
87
|
+
# @return [String] CLI output
|
88
|
+
def kill(name)
|
89
|
+
res = Open3.capture3($lxc_cmd_kill.gsub('[name]', name))
|
90
|
+
|
91
|
+
if res[1].empty? && res[2].exitstatus == 0
|
92
|
+
$logger.info("container " + name + " successfully killed")
|
93
|
+
return res[0].strip
|
94
|
+
end
|
95
|
+
|
96
|
+
$logger.warn("container " + name + " could not be killed")
|
97
|
+
raise RuntimeError, res[1].strip
|
98
|
+
end
|
99
|
+
|
100
|
+
# Deletes a container with the given name
|
101
|
+
#
|
102
|
+
# @param name [String] The container name
|
103
|
+
#
|
104
|
+
# @raise [RuntimeError]
|
105
|
+
#
|
106
|
+
# @return [String] CLI output
|
107
|
+
def delete(name)
|
108
|
+
res = Open3.capture3($lxc_cmd_destroy.gsub('[name]', name))
|
109
|
+
|
110
|
+
if res[1].empty? && res[2].exitstatus == 0
|
111
|
+
$logger.info("container " + name + " successfully deleted")
|
112
|
+
return res[0].strip
|
113
|
+
end
|
114
|
+
|
115
|
+
$logger.warn("container" + name + " could not be deleted")
|
116
|
+
raise RuntimeError, res[1].strip
|
117
|
+
end
|
118
|
+
|
119
|
+
# Returns information for a single container
|
120
|
+
#
|
121
|
+
# @param name [String] The container name
|
122
|
+
#
|
123
|
+
# @return [Hash] Hash with information about the container
|
124
|
+
def container(name)
|
125
|
+
data = {}
|
126
|
+
|
127
|
+
data[:name] = name
|
128
|
+
data[:state] = translate_state(state(name))
|
129
|
+
data[:ip_address] = ip_addr(name)
|
130
|
+
data[:cpu_cores] = assigned_cpu_cores(name).count
|
131
|
+
data[:memory_limit_bytes] = memory_limit(name).to_i
|
132
|
+
data[:memory_usage_bytes] = memory_usage(name).to_i
|
133
|
+
data[:disk_space_gb] = 0
|
134
|
+
data[:disk_usage_gb] = 0
|
135
|
+
data[:container_type] = 'lxc'
|
136
|
+
|
137
|
+
data
|
138
|
+
end
|
139
|
+
|
140
|
+
# Creates a container with the given parameters
|
141
|
+
#
|
142
|
+
# @param name [String] The container name
|
143
|
+
# @param ip_address [String] A valid IPv4 address
|
144
|
+
# @param disk_size_gb [Integer] The disk size in GB
|
145
|
+
# @param memory_limit_mb [Integer] The memory limit in MB
|
146
|
+
# @param cpu_core_count [Integer] Amount of Vcores to assign. 0 if no limit should be set
|
147
|
+
#
|
148
|
+
# @raise [RuntimeError]
|
149
|
+
#
|
150
|
+
# @return [String] CLI output
|
151
|
+
def create_container(name, ip_address, disk_size_gb, memory_limit_mb, cpu_core_count)
|
152
|
+
output = ''
|
153
|
+
|
154
|
+
begin
|
155
|
+
if cpu_core_count != 0
|
156
|
+
cpuset = self.generate_cpu_set(cpu_core_count, ResourceManager.new('linux'))
|
157
|
+
end
|
158
|
+
|
159
|
+
create_result = Open3.capture3($lxc_cmd_create.gsub('[name]', name))
|
160
|
+
|
161
|
+
output += create_result[0]
|
162
|
+
output += create_result[1]
|
163
|
+
|
164
|
+
config_path = $lxc_container_config_path.gsub('[name]', name)
|
165
|
+
|
166
|
+
open(config_path, 'a') do |f|
|
167
|
+
f << "lxc.network.ipv4=#{ip_address}/#{$lxc_ip_netmask}\n"
|
168
|
+
f << "lxc.start.auto=1\n"
|
169
|
+
f << "lxc.start.delay=5\n"
|
170
|
+
|
171
|
+
if cpu_core_count != 0
|
172
|
+
f << "lxc.cgroup.cpuset.cpus=#{cpuset}\n"
|
173
|
+
end
|
174
|
+
|
175
|
+
f << "lxc.cgroup.memory.limit_in_bytes=#{memory_limit_mb.to_s}M\n"
|
176
|
+
end
|
177
|
+
|
178
|
+
$logger.info("creation of container " + name + " successful")
|
179
|
+
return output.strip
|
180
|
+
rescue => e
|
181
|
+
$logger.warn("container " + name + " could not be created, rolling back...")
|
182
|
+
|
183
|
+
# rollback
|
184
|
+
delete(name) if exist?(name)
|
185
|
+
|
186
|
+
output += e.message
|
187
|
+
raise RuntimeError, output.strip
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# Checks if a container with the given name exists
|
192
|
+
#
|
193
|
+
# @param name [String] The container name
|
194
|
+
#
|
195
|
+
# @return [Boolean] Existing/not existing
|
196
|
+
def exist?(name)
|
197
|
+
self.container_names().include?(name)
|
198
|
+
end
|
199
|
+
|
200
|
+
# Returns the amount of free cpu cores
|
201
|
+
#
|
202
|
+
# @param resman [ResourceManager] A ResourceManager instance
|
203
|
+
#
|
204
|
+
# @return [Integer] The amount of free cpu cores
|
205
|
+
def free_cpu_core_count(resman)
|
206
|
+
self.free_cpu_cores(resman).count
|
207
|
+
end
|
208
|
+
|
209
|
+
protected
|
210
|
+
# Reads the config file of a LXC container
|
211
|
+
#
|
212
|
+
# @param name [String] The container name
|
213
|
+
#
|
214
|
+
# @raise [StandardError]
|
215
|
+
#
|
216
|
+
# @return [String] Contents of the configuration file
|
217
|
+
def read_config(name)
|
218
|
+
config = config_path(name)
|
219
|
+
|
220
|
+
if File.exists?(config) == false
|
221
|
+
raise 'config file does not exist'
|
222
|
+
end
|
223
|
+
|
224
|
+
if File.readable?(config) == false
|
225
|
+
raise 'config file not readable'
|
226
|
+
end
|
227
|
+
|
228
|
+
File.read(config)
|
229
|
+
end
|
230
|
+
|
231
|
+
# Returns the config path for a container
|
232
|
+
#
|
233
|
+
# @param name [String] The container name
|
234
|
+
#
|
235
|
+
# @return [String] The config path
|
236
|
+
def config_path(name)
|
237
|
+
$lxc_container_config_path.gsub('[name]', name)
|
238
|
+
end
|
239
|
+
|
240
|
+
# Returns the info string for a container using lxc-info
|
241
|
+
#
|
242
|
+
# @param name [String] The container name
|
243
|
+
#
|
244
|
+
# @return [String] info string
|
245
|
+
def get_info(name)
|
246
|
+
output = `#{$lxc_cmd_info.gsub('[name]', name)}`
|
247
|
+
|
248
|
+
if output.nil?
|
249
|
+
return ''
|
250
|
+
end
|
251
|
+
|
252
|
+
return output
|
253
|
+
end
|
254
|
+
|
255
|
+
# Returns the assigned IP addresses for the container
|
256
|
+
#
|
257
|
+
# @param name [String] The container name
|
258
|
+
#
|
259
|
+
# @return [String|NilClass] IP address
|
260
|
+
def ip_addr(name)
|
261
|
+
result = get_info(name).scan(/^IP:\s+([0-9.]+)$/).flatten
|
262
|
+
|
263
|
+
result.first.nil? || result.first.empty? ? nil : result.first
|
264
|
+
end
|
265
|
+
|
266
|
+
# Returns the state of the container
|
267
|
+
#
|
268
|
+
# @param name [String] The container name
|
269
|
+
#
|
270
|
+
# @return [String|NilClass] State
|
271
|
+
def state(name)
|
272
|
+
result = get_info(name).scan(/^State:\s+([A-Za-z]+)$/).flatten
|
273
|
+
|
274
|
+
result.first.nil? || result.first.empty? ? nil : result.first
|
275
|
+
end
|
276
|
+
|
277
|
+
# Returns cgroup information for a container
|
278
|
+
#
|
279
|
+
# @param name [String] The container name
|
280
|
+
# @param param [String] The cgroup parameter to read
|
281
|
+
#
|
282
|
+
# @return [String|NilClass] The result
|
283
|
+
def cgroup_info(name, param)
|
284
|
+
res = `lxc-cgroup -n #{name} #{param}`
|
285
|
+
res.empty? ? nil : res.strip
|
286
|
+
end
|
287
|
+
|
288
|
+
# Returns the current cpu usage for a container
|
289
|
+
#
|
290
|
+
# @param name [String] The container name
|
291
|
+
#
|
292
|
+
# @return [String|NilClass] CPU usage
|
293
|
+
def cpu_usage(name)
|
294
|
+
cgroup_info(name, 'cpuacct.usage')
|
295
|
+
end
|
296
|
+
|
297
|
+
# Returns the memory limit for a container
|
298
|
+
#
|
299
|
+
# @param name [String] The container name
|
300
|
+
#
|
301
|
+
# @return [Integer|NilClass] Memory limit in bytes
|
302
|
+
def memory_limit(name)
|
303
|
+
cgroup_info(name, 'memory.limit_in_bytes').to_i
|
304
|
+
end
|
305
|
+
|
306
|
+
# Returns the memory usage for a container
|
307
|
+
#
|
308
|
+
# @param name [String] The container name
|
309
|
+
#
|
310
|
+
# @return [Integer|NilClass] Memory usage in bytes
|
311
|
+
def memory_usage(name)
|
312
|
+
cgroup_info(name, 'memory.usage_in_bytes').to_i
|
313
|
+
end
|
314
|
+
|
315
|
+
# Returns a list of all container names
|
316
|
+
#
|
317
|
+
# @return [Array] Container names
|
318
|
+
def container_names
|
319
|
+
`#{$lxc_cmd_ls}`.lines.map(&:strip).uniq
|
320
|
+
end
|
321
|
+
|
322
|
+
# Returns an array with assigned CPU core ids
|
323
|
+
#
|
324
|
+
# return [Array] assigned cpu cores
|
325
|
+
def globally_assigned_cpu_cores
|
326
|
+
assigned_cores = []
|
327
|
+
|
328
|
+
container_names.each do |c|
|
329
|
+
self.assigned_cpu_cores(c).each do |cpu|
|
330
|
+
assigned_cores.push(cpu)
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
assigned_cores
|
335
|
+
end
|
336
|
+
|
337
|
+
# Reads a config value from the containers config file
|
338
|
+
#
|
339
|
+
# @param name [String] The container name
|
340
|
+
# @param regex [Regexp] The pattern to search for
|
341
|
+
#
|
342
|
+
# @return [Boolean|String] The config result
|
343
|
+
def read_config_value(name, regex)
|
344
|
+
config = self.read_config(name)
|
345
|
+
line = config.scan(regex)
|
346
|
+
|
347
|
+
if line.empty?
|
348
|
+
return false
|
349
|
+
end
|
350
|
+
|
351
|
+
value = line.flatten.first.strip
|
352
|
+
|
353
|
+
value
|
354
|
+
end
|
355
|
+
|
356
|
+
# Returns an array with Vcores assigend to a container
|
357
|
+
#
|
358
|
+
# @param name [String] The container name
|
359
|
+
#
|
360
|
+
# @return [Array] Array with cpu core ids
|
361
|
+
def assigned_cpu_cores(name)
|
362
|
+
value = self.read_config_value(name, /lxc\.cgroup\.cpuset\.cpus\s*\=(.*)$/)
|
363
|
+
used_cores = []
|
364
|
+
|
365
|
+
if value == false
|
366
|
+
return used_cores
|
367
|
+
end
|
368
|
+
|
369
|
+
value.split(',').each do |cpu|
|
370
|
+
if cpu.include?('-')
|
371
|
+
range = Range.new(*cpu.split('-').map(&:to_i))
|
372
|
+
|
373
|
+
range.each do |i|
|
374
|
+
used_cores.push(i)
|
375
|
+
end
|
376
|
+
else
|
377
|
+
used_cores.push(cpu.to_i)
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
used_cores
|
382
|
+
end
|
383
|
+
|
384
|
+
# Returns an array of unassigned cpu cores
|
385
|
+
#
|
386
|
+
# @param resman [ResourceManager] A ResourceManager instance
|
387
|
+
#
|
388
|
+
# @raise [ArgumentError]
|
389
|
+
#
|
390
|
+
# @return [Array]
|
391
|
+
def free_cpu_cores(resman)
|
392
|
+
raise ArgumentError, 'no valid ResourceManager instance' unless resman.is_a?(ResourceManager)
|
393
|
+
|
394
|
+
free_cores = []
|
395
|
+
used_cores = self.globally_assigned_cpu_cores()
|
396
|
+
|
397
|
+
(0..(resman.total_cpu_cores-1)).each do |i|
|
398
|
+
if used_cores.include?(i) == false
|
399
|
+
free_cores.push(i)
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
free_cores
|
404
|
+
end
|
405
|
+
|
406
|
+
# Generates a cpu set for a container
|
407
|
+
#
|
408
|
+
# @param count [Integer] Number of cpu cores to use
|
409
|
+
# @param resman [ResourceManager] A ResourceManager instance
|
410
|
+
#
|
411
|
+
# @raise [RuntimeError]
|
412
|
+
#
|
413
|
+
# @return [String] cpuset string
|
414
|
+
def generate_cpu_set(count, resman)
|
415
|
+
count = count.to_i
|
416
|
+
free_cores = self.free_cpu_cores(resman)
|
417
|
+
|
418
|
+
if count > free_cores.count
|
419
|
+
raise RuntimeError, 'not enough cpu cores left'
|
420
|
+
end
|
421
|
+
|
422
|
+
cores_to_use = []
|
423
|
+
|
424
|
+
count.times do
|
425
|
+
cores_to_use.push(free_cores.shift)
|
426
|
+
end
|
427
|
+
|
428
|
+
cores_to_use.join(',')
|
429
|
+
end
|
430
|
+
end
|
431
|
+
end
|