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,448 @@
|
|
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 linux-vserver. Encapsulates all vserver specific command line
|
28
|
+
# wrapping
|
29
|
+
class Vserver
|
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($vserver_cmd_start.gsub('[name]', name))
|
52
|
+
|
53
|
+
if res[2].exitstatus == 0 && state(name) == 'RUNNING'
|
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
|
+
if state(name) == 'STOPPED'
|
71
|
+
$logger.warn("container " + name + " could not be stopped, because it is not running")
|
72
|
+
raise RuntimeError, 'container is not running'
|
73
|
+
end
|
74
|
+
|
75
|
+
res = Open3.capture3($vserver_cmd_stop.gsub('[name]', name))
|
76
|
+
|
77
|
+
if res[2].exitstatus == 0 && state(name) == 'STOPPED'
|
78
|
+
$logger.info("container " + name + " successfully stopped")
|
79
|
+
return res[0].strip
|
80
|
+
end
|
81
|
+
|
82
|
+
$logger.warn("container " + name + " could not be stopped")
|
83
|
+
raise RuntimeError, res[1].strip
|
84
|
+
end
|
85
|
+
|
86
|
+
# Kills a container with the given name
|
87
|
+
#
|
88
|
+
# @param name [String] The container name
|
89
|
+
#
|
90
|
+
# @raise [RuntimeError]
|
91
|
+
#
|
92
|
+
# @return [String] CLI output
|
93
|
+
def kill(name)
|
94
|
+
return stop(name)
|
95
|
+
end
|
96
|
+
|
97
|
+
# Deletes a container with the given name
|
98
|
+
#
|
99
|
+
# @param name [String] The container name
|
100
|
+
#
|
101
|
+
# @raise [RuntimeError]
|
102
|
+
#
|
103
|
+
# @return [String] CLI output
|
104
|
+
def delete(name)
|
105
|
+
res = Open3.capture3($vserver_cmd_destroy.gsub('[name]', name))
|
106
|
+
|
107
|
+
if res[1].empty? && res[2].exitstatus == 0
|
108
|
+
$logger.info("container " + name + " successfully deleted")
|
109
|
+
return res[0].strip
|
110
|
+
end
|
111
|
+
|
112
|
+
$logger.warn("container" + name + " could not be deleted")
|
113
|
+
raise RuntimeError, res[1].strip
|
114
|
+
end
|
115
|
+
|
116
|
+
# Returns information for a single container
|
117
|
+
#
|
118
|
+
# @param name [String] The container name
|
119
|
+
#
|
120
|
+
# @return [Hash] Hash with information about the container
|
121
|
+
def container(name)
|
122
|
+
data = {}
|
123
|
+
|
124
|
+
data[:name] = name
|
125
|
+
data[:state] = translate_state(state(name))
|
126
|
+
data[:ip_address] = ip_addr(name)
|
127
|
+
data[:cpu_usage] = 0
|
128
|
+
data[:cpu_cores] = assigned_cpu_cores(name).count
|
129
|
+
data[:memory_limit_bytes] = memory_limit(name).to_i
|
130
|
+
data[:memory_usage_bytes] = memory_usage(name).to_i
|
131
|
+
data[:disk_space_gb] = 0
|
132
|
+
data[:disk_usage_gb] = 0
|
133
|
+
data[:container_type] = 'vserver'
|
134
|
+
|
135
|
+
data
|
136
|
+
end
|
137
|
+
|
138
|
+
# Creates a container with the given parameters
|
139
|
+
#
|
140
|
+
# @param name [String] The container name
|
141
|
+
# @param ip_address [String] A valid IPv4 address
|
142
|
+
# @param disk_size_gb [Integer] The disk size in GB
|
143
|
+
# @param memory_limit_mb [Integer] The memory limit in MB
|
144
|
+
# @param cpu_core_count [Integer] Amount of Vcores to assign. 0 for no limit
|
145
|
+
#
|
146
|
+
# @raise [RuntimeError]
|
147
|
+
#
|
148
|
+
# @return [String] CLI output
|
149
|
+
def create_container(name, ip_address, disk_size_gb, memory_limit_mb, cpu_core_count)
|
150
|
+
output = ''
|
151
|
+
|
152
|
+
begin
|
153
|
+
if cpu_core_count != 0
|
154
|
+
cpuset = generate_cpu_set(cpu_core_count, ResourceManager.new('linux'))
|
155
|
+
end
|
156
|
+
|
157
|
+
new_context = highest_context() + 1
|
158
|
+
cmd = $vserver_cmd_create.gsub('[name]', name).gsub('[ip_address]', ip_address).gsub('[context]', new_context.to_s)
|
159
|
+
|
160
|
+
create_result = Open3.capture3(cmd)
|
161
|
+
|
162
|
+
output += create_result[0]
|
163
|
+
output += create_result[1]
|
164
|
+
|
165
|
+
if create_result[2].exitstatus != 0
|
166
|
+
raise RuntimeError, 'command did not exit with status 0'
|
167
|
+
end
|
168
|
+
|
169
|
+
# memory limit
|
170
|
+
memory_limit_bytes = memory_limit_mb.to_i * 1024 * 1024
|
171
|
+
page_size = `#{$page_size_cmd}`.to_i
|
172
|
+
memory_limit_pages = memory_limit_bytes / page_size
|
173
|
+
|
174
|
+
write_config_file(name, '/rlimits/rss.hard', memory_limit_pages.to_s)
|
175
|
+
|
176
|
+
if cpu_core_count != 0
|
177
|
+
# cpu core limit
|
178
|
+
write_config_file(name, '/cgroup/cpuset.cpus', cpuset)
|
179
|
+
end
|
180
|
+
|
181
|
+
$logger.info("creation of container " + name + " successful")
|
182
|
+
return output.strip
|
183
|
+
rescue => e
|
184
|
+
$logger.warn("container " + name + " could not be created, rolling back...")
|
185
|
+
|
186
|
+
# rollback
|
187
|
+
delete(name) if exist?(name)
|
188
|
+
|
189
|
+
output += e.message
|
190
|
+
raise RuntimeError, output.strip
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
# Checks if a container with the given name exists
|
195
|
+
#
|
196
|
+
# @param name [String] The container name
|
197
|
+
#
|
198
|
+
# @return [Boolean] Existing/not existing
|
199
|
+
def exist?(name)
|
200
|
+
self.container_names.include?(name)
|
201
|
+
end
|
202
|
+
|
203
|
+
# Returns the amount of free cpu cores
|
204
|
+
#
|
205
|
+
# @param resman [ResourceManager] A ResourceManager instance
|
206
|
+
#
|
207
|
+
# @return [Integer] The amount of free cpu cores
|
208
|
+
def free_cpu_core_count(resman)
|
209
|
+
self.free_cpu_cores(resman).count
|
210
|
+
end
|
211
|
+
|
212
|
+
protected
|
213
|
+
# Writes the config file of a vserver
|
214
|
+
#
|
215
|
+
# @param name [String] The container name
|
216
|
+
# @param path [String] Filepath
|
217
|
+
# @param content [String] File contents
|
218
|
+
#
|
219
|
+
# @return [Boolean] Result of File.write
|
220
|
+
def write_config_file(name, path, content)
|
221
|
+
config_path = "#{$vserver_config_dir.gsub('[name]', name)}#{path}"
|
222
|
+
`mkdir -p #{File.dirname(config_path)}`
|
223
|
+
|
224
|
+
File.write(config_path, content)
|
225
|
+
end
|
226
|
+
|
227
|
+
# Reads the config file of a vserver
|
228
|
+
#
|
229
|
+
# @param name [String] The container name
|
230
|
+
#
|
231
|
+
# @raise [StandardError]
|
232
|
+
#
|
233
|
+
# @return [String] Contents of the configuration file
|
234
|
+
def read_config_file(name, path)
|
235
|
+
config_path = "#{$vserver_config_dir.gsub('[name]', name)}#{path}"
|
236
|
+
|
237
|
+
if File.exists?(config_path) == false
|
238
|
+
return nil
|
239
|
+
end
|
240
|
+
|
241
|
+
File.read(config_path).strip
|
242
|
+
end
|
243
|
+
|
244
|
+
# Creates a map of the vserver contexts
|
245
|
+
#
|
246
|
+
# @return [Hash]
|
247
|
+
def context_map
|
248
|
+
map = {}
|
249
|
+
|
250
|
+
containers.each() do |container|
|
251
|
+
map[container[:name]] = context(container[:name])
|
252
|
+
end
|
253
|
+
|
254
|
+
map
|
255
|
+
end
|
256
|
+
|
257
|
+
# Reads the context for a specific container
|
258
|
+
#
|
259
|
+
# @param name [String] The container name
|
260
|
+
#
|
261
|
+
# @raise [RuntimeError]
|
262
|
+
#
|
263
|
+
# @return [Integer] The context ID
|
264
|
+
def context(name)
|
265
|
+
file = "#{$vserver_config_dir.gsub('[name]', name)}/context"
|
266
|
+
|
267
|
+
if false == File.readable?(file)
|
268
|
+
raise RuntimeError, "file #{file} is not readable"
|
269
|
+
end
|
270
|
+
|
271
|
+
context = File.read(file)
|
272
|
+
|
273
|
+
context.to_i
|
274
|
+
end
|
275
|
+
|
276
|
+
# Returns the stats for a container
|
277
|
+
#
|
278
|
+
# @param name [String] The container name
|
279
|
+
#
|
280
|
+
# @return [Array] Stats
|
281
|
+
def vserver_stat(name)
|
282
|
+
res = `#{$vserver_cmd_stat.gsub('[name]', name)}`
|
283
|
+
|
284
|
+
res.split(' ').map(&:strip)
|
285
|
+
end
|
286
|
+
|
287
|
+
# Returns the current memory usage
|
288
|
+
#
|
289
|
+
# @param name [String] The container name
|
290
|
+
#
|
291
|
+
# @return [Integer] Memory usage
|
292
|
+
def memory_usage(name)
|
293
|
+
stat = vserver_stat(name)
|
294
|
+
|
295
|
+
if stat[2] == nil
|
296
|
+
return nil
|
297
|
+
end
|
298
|
+
|
299
|
+
(stat[2][0..-2].to_f * 1024.0 * 1024.0).to_i
|
300
|
+
end
|
301
|
+
|
302
|
+
# Finds the highest context
|
303
|
+
#
|
304
|
+
# @return [Integer] The highest context
|
305
|
+
def highest_context
|
306
|
+
contextmap = context_map()
|
307
|
+
|
308
|
+
if contextmap.empty?
|
309
|
+
return 1
|
310
|
+
end
|
311
|
+
|
312
|
+
contextmap.max_by{|k, v| v}.last
|
313
|
+
end
|
314
|
+
|
315
|
+
# Returns the ip address for a container
|
316
|
+
#
|
317
|
+
# @return [String] The IP address
|
318
|
+
def ip_addr(name)
|
319
|
+
read_config_file(name, '/interfaces/0/ip')
|
320
|
+
end
|
321
|
+
|
322
|
+
# Returns the state for a container
|
323
|
+
#
|
324
|
+
# @param name [String] The container name
|
325
|
+
#
|
326
|
+
# @return [String] Container status, STOPPED or RUNNING
|
327
|
+
def state(name)
|
328
|
+
output = `#{$vserver_cmd_stat.gsub('[name]', name)}`
|
329
|
+
|
330
|
+
if output.empty?
|
331
|
+
return 'STOPPED'
|
332
|
+
else
|
333
|
+
return 'RUNNING'
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
# Returns the memory limit for a container
|
338
|
+
#
|
339
|
+
# @param name [String] The container name
|
340
|
+
#
|
341
|
+
# @return [Integer|NilClass] Memory limit in bytes
|
342
|
+
def memory_limit(name)
|
343
|
+
ctx = context(name)
|
344
|
+
page_size = `#{$page_size_cmd}`.to_i
|
345
|
+
|
346
|
+
memory_limit_result = `#{$vserver_cmd_get_memory_limit.gsub('[context]', ctx.to_s)}`
|
347
|
+
parts = memory_limit_result.split(' ').map(&:strip)
|
348
|
+
|
349
|
+
if parts.empty?
|
350
|
+
return nil
|
351
|
+
else
|
352
|
+
return (parts.last.to_i * page_size)
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
# Gets the globally assigned cpu cores
|
357
|
+
#
|
358
|
+
# @return [Array]
|
359
|
+
def used_cpu_cores
|
360
|
+
used_cores = []
|
361
|
+
|
362
|
+
container_names.each do |c|
|
363
|
+
self.assigned_cpu_cores(c).each do |cpu|
|
364
|
+
used_cores.push(cpu)
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
used_cores
|
369
|
+
end
|
370
|
+
|
371
|
+
# Gets the cpu cores assigned to a container
|
372
|
+
#
|
373
|
+
# @param name [String] The container name
|
374
|
+
#
|
375
|
+
# @return [Array] with cpu core ids
|
376
|
+
def assigned_cpu_cores(name)
|
377
|
+
value = self.read_config_file(name, '/cgroup/cpuset.cpus')
|
378
|
+
used_cores = []
|
379
|
+
|
380
|
+
if value == nil
|
381
|
+
return used_cores
|
382
|
+
end
|
383
|
+
|
384
|
+
value.split(',').each do |cpu|
|
385
|
+
if cpu.include?('-')
|
386
|
+
range = Range.new(*cpu.split('-').map(&:to_i))
|
387
|
+
|
388
|
+
range.each do |i|
|
389
|
+
used_cores.push(i)
|
390
|
+
end
|
391
|
+
else
|
392
|
+
used_cores.push(cpu.to_i)
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
used_cores
|
397
|
+
end
|
398
|
+
|
399
|
+
# Finds free cpu cores
|
400
|
+
#
|
401
|
+
# @param resman [ResourceManager] A ResourceManager instance
|
402
|
+
#
|
403
|
+
# @return [Array] Free cpu cores
|
404
|
+
def free_cpu_cores(resman)
|
405
|
+
raise ArgumentError, 'no valid ResourceManager instance' unless resman.is_a?(ResourceManager)
|
406
|
+
|
407
|
+
free_cores = []
|
408
|
+
used_cores = self.used_cpu_cores()
|
409
|
+
|
410
|
+
(0..(resman.total_cpu_cores-1)).each do |i|
|
411
|
+
if used_cores.include?(i) == false
|
412
|
+
free_cores.push(i)
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
free_cores
|
417
|
+
end
|
418
|
+
|
419
|
+
# Generates a cpu set for a container
|
420
|
+
#
|
421
|
+
# @param count [Integer] Number of cpu cores to use
|
422
|
+
# @param resman [ResourceManager] A ResourceManager instance
|
423
|
+
#
|
424
|
+
# @raise [RuntimeError]
|
425
|
+
#
|
426
|
+
# @return [String] cpuset string
|
427
|
+
def generate_cpu_set(count, resman)
|
428
|
+
count = count.to_i
|
429
|
+
free_cores = self.free_cpu_cores(resman)
|
430
|
+
|
431
|
+
if count > free_cores.count
|
432
|
+
raise RuntimeError, 'not enough cpu cores left'
|
433
|
+
end
|
434
|
+
|
435
|
+
cores_to_use = []
|
436
|
+
|
437
|
+
count.times do
|
438
|
+
cores_to_use.push(free_cores.shift)
|
439
|
+
end
|
440
|
+
|
441
|
+
cores_to_use.join(',')
|
442
|
+
end
|
443
|
+
|
444
|
+
def container_names
|
445
|
+
`#{$vserver_cmd_ls}`.lines.map(&:strip).uniq
|
446
|
+
end
|
447
|
+
end
|
448
|
+
end
|
@@ -0,0 +1,27 @@
|
|
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
|
+
class NotFoundError < StandardError
|
27
|
+
end
|
@@ -0,0 +1,32 @@
|
|
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 OS
|
27
|
+
# Returns true if this is a linux system
|
28
|
+
# @return [Boolean]
|
29
|
+
def self.linux?
|
30
|
+
RUBY_PLATFORM.include?('linux')
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,49 @@
|
|
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
|
+
# Top level class for resource management
|
27
|
+
class ResourceManager
|
28
|
+
|
29
|
+
# Initializes the ResourceManager with a matching adapter
|
30
|
+
#
|
31
|
+
# @raise [ArgumentError]
|
32
|
+
def initialize(type)
|
33
|
+
@resman = nil
|
34
|
+
|
35
|
+
if type == 'linux'
|
36
|
+
@resman = ResourceManagerAdapter::Linux.new
|
37
|
+
else
|
38
|
+
raise ArgumentError, 'invalid resourcemanager type supplied'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns the total number of cpu cores available on the system
|
43
|
+
#
|
44
|
+
# @return [Integer]
|
45
|
+
def total_cpu_cores
|
46
|
+
@resman.total_cpu_cores
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,53 @@
|
|
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 ResourceManagerAdapter
|
27
|
+
# ResourceManager adapter for Linux
|
28
|
+
class Linux
|
29
|
+
|
30
|
+
# Initializes the adapter
|
31
|
+
#
|
32
|
+
# @raise [RuntimeError]
|
33
|
+
def initialize
|
34
|
+
if $container_type == 'LXC' && File.exists?($lxc_cgroup_mount_path) == false
|
35
|
+
raise RuntimeError, 'no cgroup node found'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Finds the total amount of cpu cores
|
40
|
+
#
|
41
|
+
# @return [Integer]
|
42
|
+
def total_cpu_cores
|
43
|
+
cpu_cores = `nproc`.strip.to_i
|
44
|
+
|
45
|
+
if $?.exitstatus != 0
|
46
|
+
raise RuntimeError, 'could not run nproc'
|
47
|
+
end
|
48
|
+
|
49
|
+
return cpu_cores
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,38 @@
|
|
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
|
+
# Translates a container state to the whitefuses states
|
27
|
+
#
|
28
|
+
# @param state [String] Original state
|
29
|
+
#
|
30
|
+
# @return [String] The translated state
|
31
|
+
def translate_state(state)
|
32
|
+
case state
|
33
|
+
when 'RUNNING'
|
34
|
+
return 'RUNNING'
|
35
|
+
else
|
36
|
+
return 'STOPPED'
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,28 @@
|
|
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 WfNodeApi
|
27
|
+
VERSION = '0.6.0'
|
28
|
+
end
|