wf_node_api 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|