haconiwa 0.0.1.pre → 0.0.1.pre2
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/Gemfile +0 -1
- data/Vagrantfile +5 -5
- data/bin/console +1 -1
- data/examples/chroot.rb +7 -3
- data/examples/cpu.rb +24 -0
- data/lib/haconiwa/base.rb +7 -0
- data/lib/haconiwa/cgroup.rb +13 -0
- data/lib/haconiwa/filesystem.rb +8 -4
- data/lib/haconiwa/namespace.rb +52 -2
- data/lib/haconiwa/runners/linux.rb +31 -13
- data/lib/haconiwa/small_cgroup.rb +65 -0
- data/lib/haconiwa/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5118b20649292936469ac7f8c20186aba2b43609
|
4
|
+
data.tar.gz: ce1583a83126f75f922bc83d40098df36afb6340
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 423cff4515ed3116b3ca8f317cc8d7cfaf392c77a6725948041edb35b92b4e24fd32da208d1b73b885178e971eeeb24f01da871ddeabc541ffc5377fb83ea8c6
|
7
|
+
data.tar.gz: 3ce74b9dde1970f2a8b87fe27f4f0d988f83620c968010e98e1b6dffced9d2436e91b3397fadf8f602c6cf9b8ec4fe591d98ad32c91cb799bf300a352ad2f788
|
data/Gemfile
CHANGED
data/Vagrantfile
CHANGED
@@ -44,11 +44,11 @@ Vagrant.configure(2) do |config|
|
|
44
44
|
|
45
45
|
yum -y install lxc lxc-templates lxc-doc lxc-libs rsync debootstrap
|
46
46
|
|
47
|
-
mkdir /var/
|
48
|
-
mkdir /var/
|
49
|
-
mkdir /var/
|
50
|
-
mkdir /var/
|
51
|
-
mkdir /var/
|
47
|
+
mkdir /var/haconiwa
|
48
|
+
mkdir /var/haconiwa/root
|
49
|
+
mkdir /var/haconiwa/rootfs
|
50
|
+
mkdir /var/haconiwa/bundle
|
51
|
+
mkdir /var/haconiwa/user_homes
|
52
52
|
EOS
|
53
53
|
fi
|
54
54
|
SHELL
|
data/bin/console
CHANGED
data/examples/chroot.rb
CHANGED
@@ -7,11 +7,15 @@ haconiwa = Haconiwa::Base.define do |config|
|
|
7
7
|
config.add_mount_point "/var/haconiwa/rootfs", to: root, readonly: true
|
8
8
|
config.add_mount_point "/lib64", to: root.join("lib64"), readonly: true
|
9
9
|
config.add_mount_point "/usr/bin", to: root.join("usr/bin"), readonly: true
|
10
|
-
config.add_mount_point "
|
11
|
-
config.add_mount_point "
|
10
|
+
config.add_mount_point "tmpfs", to: root.join("tmp"), fs: "tmpfs"
|
11
|
+
config.add_mount_point "/var/haconiwa/user_homes/hakoniwa-test001/home/hakoniwa", to: root.join("home/hakoniwa")
|
12
|
+
config.mount_independent_procfs
|
12
13
|
config.chroot_to root
|
13
14
|
|
14
|
-
|
15
|
+
config.namespace.unshare "mount"
|
16
|
+
config.namespace.unshare "ipc"
|
17
|
+
config.namespace.unshare "uts"
|
18
|
+
config.namespace.unshare "pid"
|
15
19
|
end
|
16
20
|
|
17
21
|
haconiwa.start("/bin/bash")
|
data/examples/cpu.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'haconiwa'
|
2
|
+
require 'pathname'
|
3
|
+
haconiwa = Haconiwa::Base.define do |config|
|
4
|
+
config.name = "cpu-quota001" # to be hostname
|
5
|
+
|
6
|
+
root = Pathname.new("/var/haconiwa/root")
|
7
|
+
config.add_mount_point "/var/haconiwa/rootfs", to: root, readonly: true
|
8
|
+
config.add_mount_point "/lib64", to: root.join("lib64"), readonly: true
|
9
|
+
config.add_mount_point "/usr/bin", to: root.join("usr/bin"), readonly: true
|
10
|
+
config.add_mount_point "/usr/local/rbenv", to: root.join("usr/local/rbenv")
|
11
|
+
config.add_mount_point "tmpfs", to: root.join("tmp"), fs: "tmpfs"
|
12
|
+
config.mount_independent_procfs
|
13
|
+
config.chroot_to root
|
14
|
+
|
15
|
+
config.namespace.unshare "mount"
|
16
|
+
config.namespace.unshare "ipc"
|
17
|
+
config.namespace.unshare "uts"
|
18
|
+
config.namespace.unshare "pid"
|
19
|
+
|
20
|
+
config.cgroup["cpu.cfs_period_us"] = 100000
|
21
|
+
config.cgroup["cpu.cfs_quota_us"] = 30000
|
22
|
+
end
|
23
|
+
|
24
|
+
haconiwa.start("/bin/bash")
|
data/lib/haconiwa/base.rb
CHANGED
@@ -22,6 +22,7 @@ module Haconiwa
|
|
22
22
|
@cgroup = CGroup.new
|
23
23
|
@namespace = Namespace.new
|
24
24
|
@capabilities = Capabilities.new
|
25
|
+
@name = "haconiwa-#{Time.now.to_i}"
|
25
26
|
end
|
26
27
|
|
27
28
|
# aliases
|
@@ -30,9 +31,15 @@ module Haconiwa
|
|
30
31
|
end
|
31
32
|
|
32
33
|
def add_mount_point(point, options)
|
34
|
+
self.namespace.unshare "mount"
|
33
35
|
self.filesystem.mount_points << MountPoint.new(point, options)
|
34
36
|
end
|
35
37
|
|
38
|
+
def mount_independent_procfs
|
39
|
+
self.namespace.unshare "mount"
|
40
|
+
self.filesystem.mount_independent_procfs = true
|
41
|
+
end
|
42
|
+
|
36
43
|
def start(init_command='/sbin/init')
|
37
44
|
Runners::Linux.run(self, init_command)
|
38
45
|
end
|
data/lib/haconiwa/cgroup.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'haconiwa/small_cgroup'
|
2
|
+
|
1
3
|
module Haconiwa
|
2
4
|
class CGroup
|
3
5
|
def initialize
|
@@ -12,5 +14,16 @@ module Haconiwa
|
|
12
14
|
def []=(key, value)
|
13
15
|
@groups[key] = value
|
14
16
|
end
|
17
|
+
|
18
|
+
def to_dirs
|
19
|
+
groups.keys.map{|k| k.split('.').first }.uniq
|
20
|
+
end
|
21
|
+
|
22
|
+
def register_all!(to: nil)
|
23
|
+
cg = SmallCgroup.new(name: to)
|
24
|
+
groups.each do |k, v|
|
25
|
+
cg.register k, v
|
26
|
+
end
|
27
|
+
end
|
15
28
|
end
|
16
29
|
end
|
data/lib/haconiwa/filesystem.rb
CHANGED
@@ -2,15 +2,19 @@ module Haconiwa
|
|
2
2
|
class Filesystem
|
3
3
|
def initialize
|
4
4
|
@mount_points = []
|
5
|
+
@mount_independent_procfs = false
|
5
6
|
end
|
6
|
-
attr_accessor :chroot, :mount_points
|
7
|
+
attr_accessor :chroot, :mount_points,
|
8
|
+
:mount_independent_procfs
|
7
9
|
|
8
10
|
def mount_all!
|
9
11
|
Dir.chdir "/"
|
10
|
-
|
12
|
+
unless mount_points.empty?
|
13
|
+
system "mount --make-private /"
|
11
14
|
|
12
|
-
|
13
|
-
|
15
|
+
mount_points.each do |mount|
|
16
|
+
mount.apply!
|
17
|
+
end
|
14
18
|
end
|
15
19
|
end
|
16
20
|
end
|
data/lib/haconiwa/namespace.rb
CHANGED
@@ -1,16 +1,66 @@
|
|
1
1
|
module Haconiwa
|
2
2
|
class Namespace
|
3
|
+
UNSHARE = 272
|
4
|
+
|
5
|
+
# from linux/sched.h
|
6
|
+
|
7
|
+
CLONE_FS = 0x00000200
|
8
|
+
CLONE_FILES = 0x00000400
|
9
|
+
CLONE_NEWNS = 0x00020000
|
10
|
+
CLONE_SYSVSEM = 0x00040000
|
11
|
+
CLONE_NEWCGROUP = 0x02000000
|
12
|
+
CLONE_NEWUTS = 0x04000000
|
13
|
+
CLONE_NEWIPC = 0x08000000
|
14
|
+
CLONE_NEWUSER = 0x10000000
|
15
|
+
CLONE_NEWPID = 0x20000000
|
16
|
+
CLONE_NEWNET = 0x40000000
|
17
|
+
|
18
|
+
NS_MAPPINGS = {
|
19
|
+
"cgroup" => CLONE_NEWCGROUP,
|
20
|
+
"ipc" => CLONE_NEWIPC,
|
21
|
+
"net" => CLONE_NEWNET,
|
22
|
+
"mount" => CLONE_NEWNS,
|
23
|
+
"pid" => CLONE_NEWPID,
|
24
|
+
"user" => CLONE_NEWUSER,
|
25
|
+
"uts" => CLONE_NEWUTS,
|
26
|
+
}
|
27
|
+
|
3
28
|
def initialize
|
4
29
|
@use_ns = []
|
5
30
|
@netns_name = nil
|
6
31
|
end
|
7
32
|
|
8
|
-
def unshare(
|
9
|
-
|
33
|
+
def unshare(ns)
|
34
|
+
flag = case ns
|
35
|
+
when String, Symbol
|
36
|
+
NS_MAPPINGS[ns.to_s]
|
37
|
+
when Integer
|
38
|
+
ns
|
39
|
+
end
|
40
|
+
if flag == CLONE_NEWPID
|
41
|
+
@use_pid_ns = true
|
42
|
+
else
|
43
|
+
@use_ns << flag
|
44
|
+
end
|
10
45
|
end
|
46
|
+
attr_reader :use_pid_ns
|
11
47
|
|
12
48
|
def use_netns(name)
|
13
49
|
@netns_name = name
|
14
50
|
end
|
51
|
+
|
52
|
+
def apply!
|
53
|
+
flag = to_ns_flag
|
54
|
+
STDERR.puts "unshare(2) flag: 0x%s" % flag.to_s(16)
|
55
|
+
Kernel.syscall(UNSHARE, flag)
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def to_ns_flag
|
61
|
+
@use_ns.inject(0x00000000) { |dst, flag|
|
62
|
+
dst |= flag
|
63
|
+
}
|
64
|
+
end
|
15
65
|
end
|
16
66
|
end
|
@@ -1,29 +1,47 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'bundler'
|
4
|
+
|
1
5
|
module Haconiwa::Runners
|
2
6
|
# see http://d.hatena.ne.jp/hiboma/20120518/1337337393
|
3
7
|
|
4
8
|
class Linux
|
5
|
-
UNSHARE = 272
|
6
|
-
CLONE_NEWNS = 0x00020000
|
7
|
-
|
8
9
|
def self.run(base, init_command)
|
9
|
-
fork {
|
10
|
-
|
11
|
-
|
10
|
+
container = fork {
|
11
|
+
base.namespace.apply!
|
12
|
+
base.cgroup.register_all!(to: base.name)
|
12
13
|
|
13
14
|
base.filesystem.mount_all!
|
14
15
|
|
15
16
|
Dir.chroot base.filesystem.chroot
|
16
17
|
Dir.chdir "/"
|
17
|
-
|
18
|
+
|
19
|
+
wrapper = Tempfile.open("haconiwa-wrapper-#{$$}-#{Time.now.to_i}.sh")
|
20
|
+
|
21
|
+
wrapper.puts "#!/bin/bash"
|
22
|
+
wrapper.puts "/bin/bash -c \""
|
23
|
+
if base.filesystem.mount_independent_procfs
|
24
|
+
wrapper.puts "mount -t proc proc /proc;"
|
25
|
+
end
|
26
|
+
wrapper.puts "exec $1;"
|
27
|
+
wrapper.puts "\""
|
28
|
+
wrapper.close
|
29
|
+
FileUtils.chmod 0700, wrapper.path
|
30
|
+
|
31
|
+
if base.namespace.use_pid_ns
|
32
|
+
Bundler.with_clean_env {
|
33
|
+
exec "unshare", "--pid", "--", wrapper.path, init_command
|
34
|
+
}
|
35
|
+
else
|
36
|
+
Bundler.with_clean_env { exec wrapper.path, init_command }
|
37
|
+
end
|
18
38
|
}
|
19
39
|
|
20
|
-
|
21
|
-
|
22
|
-
loop {} # to be in front
|
23
|
-
end
|
40
|
+
Haconiwa::SmallCgroup.register_at_exit(pid: container, name: base.name, dirs: base.cgroup.to_dirs)
|
41
|
+
puts "New container: PID = #{container}"
|
24
42
|
|
25
|
-
|
26
|
-
|
43
|
+
Process.waitpid container
|
44
|
+
puts "Successfully exit container."
|
27
45
|
end
|
28
46
|
end
|
29
47
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module Haconiwa
|
5
|
+
class SmallCgroup
|
6
|
+
class << self
|
7
|
+
attr_accessor :fs_root
|
8
|
+
|
9
|
+
def register_at_exit(pid: nil, name: nil, dirs: nil)
|
10
|
+
at_exit do
|
11
|
+
dirs.each do |dir|
|
12
|
+
begin
|
13
|
+
cleanup = fs_root.join(dir, name)
|
14
|
+
FileUtils.rmdir(cleanup)
|
15
|
+
rescue
|
16
|
+
STDERR.puts "Failed to remove: #{cleanup}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
self.fs_root = Pathname.new("/sys/fs/cgroup")
|
23
|
+
|
24
|
+
def initialize(name: "haconiwa-#{$$}", pid: $$)
|
25
|
+
@name = name
|
26
|
+
@pid = pid
|
27
|
+
@active_dirs = []
|
28
|
+
end
|
29
|
+
attr_reader :name, :pid
|
30
|
+
|
31
|
+
def activate(dir)
|
32
|
+
dirroot = root_of(dir)
|
33
|
+
FileUtils.mkdir_p dirroot
|
34
|
+
append_write dirroot.join("tasks"), self.pid
|
35
|
+
@active_dirs << dir
|
36
|
+
end
|
37
|
+
|
38
|
+
def activated?(dir)
|
39
|
+
@active_dirs.include? dir
|
40
|
+
end
|
41
|
+
|
42
|
+
def register(key, value)
|
43
|
+
dir = key.split('.').first
|
44
|
+
unless activated?(dir)
|
45
|
+
activate(dir)
|
46
|
+
end
|
47
|
+
|
48
|
+
overwrite root_of(dir).join(key), value
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def root_of(dir)
|
54
|
+
SmallCgroup.fs_root.join(dir, self.name)
|
55
|
+
end
|
56
|
+
|
57
|
+
def append_write(file, value)
|
58
|
+
File.open(file, 'a') {|f| f.puts value }
|
59
|
+
end
|
60
|
+
|
61
|
+
def overwrite(file, value)
|
62
|
+
File.open(file, 'w') {|f| f.puts value }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/haconiwa/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: haconiwa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.1.
|
4
|
+
version: 0.0.1.pre2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Uchio KONDO
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-05-
|
11
|
+
date: 2016-05-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|
@@ -127,6 +127,7 @@ files:
|
|
127
127
|
- bin/console
|
128
128
|
- bin/setup
|
129
129
|
- examples/chroot.rb
|
130
|
+
- examples/cpu.rb
|
130
131
|
- haconiwa.gemspec
|
131
132
|
- lib/haconiwa.rb
|
132
133
|
- lib/haconiwa/base.rb
|
@@ -137,6 +138,7 @@ files:
|
|
137
138
|
- lib/haconiwa/namespace.rb
|
138
139
|
- lib/haconiwa/runners.rb
|
139
140
|
- lib/haconiwa/runners/linux.rb
|
141
|
+
- lib/haconiwa/small_cgroup.rb
|
140
142
|
- lib/haconiwa/version.rb
|
141
143
|
homepage: https://github.com/udzura/haconiwa
|
142
144
|
licenses:
|