This repository has been archived by the owner on Aug 14, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
container
executable file
·85 lines (67 loc) · 2.03 KB
/
container
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
36
37
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
#!/usr/bin/env ruby
require 'bundler/setup'
require 'childprocess'
require_relative 'lib_c'
HOSTNAME = 'container'.freeze
def must(exit_code)
unless exit_code == 0
$stderr.puts caller
abort "exit code: #{exit_code}; errno: #{Fiddle.last_error}"
end
end
def cg
cgroups = Pathname.new('/sys/fs/cgroup/')
pids = cgroups.join('pids')
FileUtils.mkdir_p(pids.join('james'), mode: 0755)
File.write(pids.join('james/pids.max'), '20', perm: 0700)
# Removes the new cgroup in place after the container exits
File.write(pids.join('james/notify_on_release'), '1', perm: 0700)
File.write(pids.join('james/cgroup.procs'), Process.pid.to_s, perm: 0700)
end
def run(*args)
puts "run: Running #{args.inspect} as PID #{Process.pid}"
process = ChildProcess.build(__FILE__, 'child', *args)
process.io.inherit!
process.start
process.wait
abort "run: exit code #{process.exit_code}" unless process.exit_code == 0
end
def child(*args)
puts "child: Running #{args.inspect} as PID #{Process.pid}"
must(LibC.unshare(LibC::CLONE_NEWUTS | LibC::CLONE_NEWPID | LibC::CLONE_NEWNS))
must(LibC.sethostname(HOSTNAME, HOSTNAME.length))
process = ChildProcess.build(__FILE__, 'grandchild', *args)
process.io.inherit!
process.start
process.wait
abort "child: exit code #{process.exit_code}" unless process.exit_code == 0
end
def grandchild(*args)
puts "grandchild: Running #{args.inspect} as PID #{Process.pid}"
cg
must(LibC.mount('none', '/', Fiddle::NULL, LibC::MS_REC | LibC::MS_PRIVATE, Fiddle::NULL))
Dir.chroot('/home/ubuntu/ubuntufs')
must(LibC.mount('proc', '/proc', 'proc', 0, Fiddle::NULL))
begin
process = ChildProcess.build(*args)
process.io.inherit!
process.cwd = '/'
process.start
process.wait
abort "grandchild: exit code #{process.exit_code}" unless process.exit_code == 0
ensure
must(LibC.umount('/proc'))
end
end
args = ARGV
type = args.shift
case type
when 'run'
run(*args)
when 'child'
child(*args)
when 'grandchild'
grandchild(*args)
else
abort "Unknown type: #{type}"
end