haconiwa 0.0.1.pre → 0.0.1.pre2
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|