hrr_rb_lxns 0.1.1 → 0.2.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 +4 -4
- data/README.md +33 -0
- data/hrr_rb_lxns.gemspec +2 -0
- data/lib/hrr_rb_lxns/version.rb +1 -1
- data/lib/hrr_rb_lxns.rb +102 -4
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f96ad9d7f1439e815c23aebf272ff8ca0984dba7ec9775e22483d33a390e82b1
|
4
|
+
data.tar.gz: 0eba5185a5c6c23660b69acd7982b5982830a50e2dad726b09c1f89f93325780
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: af3f529c576999c3f11371b0ea4ffaf59ad62f0500185a3b238026d41744251732f24d1123590f981d9eeb260188599358b626fd634d69f25a13aafe5cfbb694
|
7
|
+
data.tar.gz: d28a267db5871149c88a145aef192612d8f007826670ded888b5a96836593211431cf4d038e6fb314427ccefdc3dba7dd5b3439b14374f36a6d813dad201a0da
|
data/README.md
CHANGED
@@ -45,6 +45,39 @@ File.readlink "/proc/self/ns/uts" # => uts:[xxx]
|
|
45
45
|
File.readlink "/proc/self/ns/mnt" # => mnt:[yyy]
|
46
46
|
```
|
47
47
|
|
48
|
+
HrrRbLxns.unshare supports creating persistent namespaces files by bind-mount. The files are specified in an options hash. The keys which are available in the hash for each namespace are `:mount`, `:uts`, `:ipc`, `:network`, `:pid`, `:user`, `:cgroup`, and `:time`.
|
49
|
+
Note that files that namespaces are bind-mounted must exist. The library does just bind-mount, not create the files. And the files and their mount information are kept after the caller process is finished.
|
50
|
+
When unsharing pid namespace, the namespace file should be bind-mounted against the caller's child process. For this case, `:fork` option is supported.
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
File.readlink "/proc/self/ns/uts" # => uts:[aaa]
|
54
|
+
# Prepare an options hash to specify a file that namespaces are bind-mounted
|
55
|
+
options = {:uts => "/path/to/myns/uts"}
|
56
|
+
HrrRbLxns.unshare HrrRbLxns::NEWUTS, options # => 0
|
57
|
+
File.readlink "/proc/self/ns/uts" # => uts:[xxx]
|
58
|
+
File.stat(options[:uts]).ino # => xxx
|
59
|
+
|
60
|
+
# For mount namespace, the parent directory's propagation needs to be private
|
61
|
+
FileUtils.mkdir "/path/to/myns"
|
62
|
+
HrrRbMount.bind "/path/to/myns" "/path/to/myns"
|
63
|
+
HrrRbMount.make_private "/path/to/myns"
|
64
|
+
FileUtils.touch "/path/to/myns/mnt"
|
65
|
+
options = {:mount => "/path/to/myns/mnt"}
|
66
|
+
HrrRbLxns.unshare HrrRbLxns::NEWNS, options # => 0
|
67
|
+
|
68
|
+
# For pid namespace, :fork option is available
|
69
|
+
options = {:pid => "/path/to/myns/pid", :fork => true}
|
70
|
+
# .unshare method with :fork option works like Kernel.#fork after unshare(2)
|
71
|
+
if pid = HrrRbLxns.unshare HrrRbLxns::NEWPID, options
|
72
|
+
# In parent, .unshare returns the child process's PID (In this case, it is 1 because unsharing PID namespace)
|
73
|
+
# Do something
|
74
|
+
Process.waitpid pid
|
75
|
+
else
|
76
|
+
# In child, .unshare returns nil
|
77
|
+
# Do something
|
78
|
+
end
|
79
|
+
```
|
80
|
+
|
48
81
|
### Setns
|
49
82
|
|
50
83
|
HrrRbLxns.setns method wraps around setns(2) system call. The system call associate the caller process's namespace to an existing one, which is disassociated by some other process.
|
data/hrr_rb_lxns.gemspec
CHANGED
data/lib/hrr_rb_lxns/version.rb
CHANGED
data/lib/hrr_rb_lxns.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "hrr_rb_lxns/version"
|
2
2
|
require "hrr_rb_lxns/hrr_rb_lxns"
|
3
|
+
require "hrr_rb_mount"
|
3
4
|
|
4
5
|
# Utilities working with Linux namespaces for CRuby.
|
5
6
|
module HrrRbLxns
|
@@ -33,14 +34,29 @@ module HrrRbLxns
|
|
33
34
|
# "U" : NEWUSER <br>
|
34
35
|
# "C" : NEWCGROUP <br>
|
35
36
|
# "T" : NEWTIME <br>
|
36
|
-
# @param options [Hash]
|
37
|
-
# @
|
37
|
+
# @param options [Hash] Optional arguments.
|
38
|
+
# @option options [String] :mount A persistent mount namespace to be created by bind mount.
|
39
|
+
# @option options [String] :uts A persistent uts namespace to be created by bind mount.
|
40
|
+
# @option options [String] :ipc A persistent ipc namespace to be created by bind mount.
|
41
|
+
# @option options [String] :network A persistent network namespace to be created by bind mount.
|
42
|
+
# @option options [String] :pid A persistent pid namespace to be created by bind mount.
|
43
|
+
# @option options [String] :user A persistent user namespace to be created by bind mount.
|
44
|
+
# @option options [String] :cgroup A persistent cgroup namespace to be created by bind mount.
|
45
|
+
# @option options [String] :time A persistent time namespace to be created by bind mount.
|
46
|
+
# @option options [Boolean] :fork If specified, the caller process forks after unshare.
|
47
|
+
# @return [Integer, nil] Usually 0. If :fork is specified in options, then PID of the child process in parent, nil in child (as same as Kernel.#fork).
|
38
48
|
# @raise [ArgumentError] When given flags argument is not appropriate.
|
39
49
|
# @raise [Errno::EXXX] In case unshare(2) system call failed.
|
40
|
-
|
41
50
|
def self.unshare flags, options={}
|
42
51
|
_flags = interpret_flags flags
|
43
|
-
|
52
|
+
bind_ns_files_from_child(_flags, options) do
|
53
|
+
if fork? options
|
54
|
+
__unshare__ _flags
|
55
|
+
fork
|
56
|
+
else
|
57
|
+
__unshare__ _flags
|
58
|
+
end
|
59
|
+
end
|
44
60
|
end
|
45
61
|
|
46
62
|
# A wrapper around setns(2) system call.
|
@@ -120,6 +136,88 @@ module HrrRbLxns
|
|
120
136
|
end
|
121
137
|
end
|
122
138
|
|
139
|
+
def self.fork? options
|
140
|
+
options[:fork]
|
141
|
+
end
|
142
|
+
|
143
|
+
def self.bind_ns_files? options
|
144
|
+
list = Array.new
|
145
|
+
list.push :ipc if const_defined?(:NEWIPC)
|
146
|
+
list.push :mount if const_defined?(:NEWNS)
|
147
|
+
list.push :network if const_defined?(:NEWNET)
|
148
|
+
list.push :pid if const_defined?(:NEWPID)
|
149
|
+
list.push :uts if const_defined?(:NEWUTS)
|
150
|
+
list.push :user if const_defined?(:NEWUSER)
|
151
|
+
list.push :cgroup if const_defined?(:NEWCGROUP)
|
152
|
+
list.push :time if const_defined?(:NEWTIME)
|
153
|
+
(list & options.keys).empty?.!
|
154
|
+
end
|
155
|
+
|
156
|
+
# In some cases, namespace files need to be created by an external process.
|
157
|
+
# Thus, this method calls fork and the child process creates the namespace files.
|
158
|
+
def self.bind_ns_files_from_child flags, options
|
159
|
+
if bind_ns_files? options
|
160
|
+
pid_to_bind = Process.pid
|
161
|
+
pid = nil
|
162
|
+
begin
|
163
|
+
io_r, io_w = IO.pipe
|
164
|
+
if pid = fork
|
165
|
+
ret = yield
|
166
|
+
io_w.write "1"
|
167
|
+
io_w.close
|
168
|
+
if pid_to_bind == Process.pid
|
169
|
+
_, status = Process.waitpid2 pid
|
170
|
+
raise Marshal.load(io_r.read) if status.exitstatus != 0
|
171
|
+
end
|
172
|
+
ret
|
173
|
+
else
|
174
|
+
begin
|
175
|
+
exit_status = true
|
176
|
+
io_r.read 1
|
177
|
+
bind_ns_files flags, options, pid_to_bind
|
178
|
+
rescue Exception => e
|
179
|
+
exit_status = false
|
180
|
+
io_w.write Marshal.dump(e)
|
181
|
+
ensure
|
182
|
+
exit! exit_status
|
183
|
+
end
|
184
|
+
end
|
185
|
+
ensure
|
186
|
+
io_w.write "1" rescue nil # just in case getting an error before io_w.write
|
187
|
+
io_w.close rescue nil
|
188
|
+
io_r.close rescue nil
|
189
|
+
if pid_to_bind == Process.pid
|
190
|
+
begin
|
191
|
+
Process.waitpid pid
|
192
|
+
rescue Errno::ECHILD
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
else
|
197
|
+
yield
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def self.bind_ns_files flags, options, pid
|
202
|
+
list = Array.new
|
203
|
+
list.push ["ipc", NEWIPC, :ipc ] if const_defined?(:NEWIPC)
|
204
|
+
list.push ["mnt", NEWNS, :mount ] if const_defined?(:NEWNS)
|
205
|
+
list.push ["net", NEWNET, :network] if const_defined?(:NEWNET)
|
206
|
+
list.push ["pid", NEWPID, :pid ] if const_defined?(:NEWPID)
|
207
|
+
if File.exist? "/proc/#{pid}/ns/pid_for_children"
|
208
|
+
list.last[0] = "pid_for_children"
|
209
|
+
end
|
210
|
+
list.push ["uts", NEWUTS, :uts ] if const_defined?(:NEWUTS)
|
211
|
+
list.push ["user", NEWUSER, :user ] if const_defined?(:NEWUSER)
|
212
|
+
list.push ["cgroup", NEWCGROUP, :cgroup ] if const_defined?(:NEWCGROUP)
|
213
|
+
list.push ["time", NEWTIME, :time ] if const_defined?(:NEWTIME)
|
214
|
+
list.each do |name, flag, key|
|
215
|
+
if (flags & flag).zero?.! && options[key]
|
216
|
+
HrrRbMount.bind "/proc/#{pid}/ns/#{name}", options[key]
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
123
221
|
def self.do_setns nstype_file_h
|
124
222
|
nstype_file_h.each do |nstype, file|
|
125
223
|
File.open(file, File::RDONLY) do |f|
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hrr_rb_lxns
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- hirura
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-04-
|
12
|
-
dependencies:
|
11
|
+
date: 2020-04-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: hrr_rb_mount
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.3.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.3.0
|
13
27
|
description: Utilities working with Linux namespaces for CRuby.
|
14
28
|
email:
|
15
29
|
- hirura@gmail.com
|