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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0e0bf510cbf025ea63a38a250e57fa7b857c936a
4
- data.tar.gz: 037ea036c4c88bb4e68e54bc7c7f1c4da34cc8ac
3
+ metadata.gz: 5118b20649292936469ac7f8c20186aba2b43609
4
+ data.tar.gz: ce1583a83126f75f922bc83d40098df36afb6340
5
5
  SHA512:
6
- metadata.gz: 9bcbf2fdeeebc9263365f3f0321e5fa285832cfe37ff8f4d81404c5e75d06e3115fac31059d89f1564f715accddb43ecd66bbb5976ebad25f5ffb91b42f6a56f
7
- data.tar.gz: ebb6c08bbc85a91edda488a60c994ee62c61307d5c5de3060f65f7450c05f0a75b993474b9f38033b810a919416128fdaa61129138d8da5e5460812b48a641e0
6
+ metadata.gz: 423cff4515ed3116b3ca8f317cc8d7cfaf392c77a6725948041edb35b92b4e24fd32da208d1b73b885178e971eeeb24f01da871ddeabc541ffc5377fb83ea8c6
7
+ data.tar.gz: 3ce74b9dde1970f2a8b87fe27f4f0d988f83620c968010e98e1b6dffced9d2436e91b3397fadf8f602c6cf9b8ec4fe591d98ad32c91cb799bf300a352ad2f788
data/Gemfile CHANGED
@@ -1,4 +1,3 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in hakoniwa.gemspec
4
3
  gemspec
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/hakoniwa
48
- mkdir /var/hakoniwa/root
49
- mkdir /var/hakoniwa/rootfs
50
- mkdir /var/hakoniwa/bundle
51
- mkdir /var/hakoniwa/user_homes
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
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require "bundler/setup"
4
- require "hakoniwa"
4
+ require "haconiwa"
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
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 "/var/haconiwa/user_homes/haconiwa-test001/home/haconiwa", to: root.join("home/haconiwa")
11
- config.add_mount_point "proc", to: root.join("proc"), fs: "proc"
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
- # config.namespace.unshare "mount"
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
@@ -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
@@ -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
- system "mount --make-private /"
12
+ unless mount_points.empty?
13
+ system "mount --make-private /"
11
14
 
12
- mount_points.each do |mount|
13
- mount.apply!
15
+ mount_points.each do |mount|
16
+ mount.apply!
17
+ end
14
18
  end
15
19
  end
16
20
  end
@@ -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(ns_type)
9
- @use_ns << ns_type
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
- unshare(CLONE_NEWNS)
11
- system "readlink /proc/$$/ns/mnt"
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
- exec init_command
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
- puts "New container: is OK?"
21
- system "readlink /proc/$$/ns/mnt"
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
- def self.unshare(flag)
26
- Kernel.syscall(UNSHARE, flag)
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
@@ -1,3 +1,3 @@
1
1
  module Haconiwa
2
- VERSION = "0.0.1.pre"
2
+ VERSION = "0.0.1.pre2"
3
3
  end
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.pre
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-24 00:00:00.000000000 Z
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: