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 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: