Permalink
Browse files

Allow nesting via `allow_nested_warden` config flag

Setting this flag will create a number of bind mounts into /tmp/warden
inside the container such that warden can run inside of a container.
  • Loading branch information...
1 parent 2ab01c5 commit c8446d7f14635e5e2b505de16cb09bc2fefce0e8 David Sabeti and Pieter Noordhuis committed Apr 5, 2013
View
@@ -37,6 +37,8 @@ server:
quota:
disk_quota_enabled: true
+ allow_nested_warden: false
+
health_check_server:
port: 2345
@@ -14,6 +14,7 @@ def self.server_defaults
"quota" => {
"disk_quota_enabled" => true,
},
+ "allow_nested_warden" => false,
}
end
@@ -59,6 +60,8 @@ def self.server_schema
"quota" => {
optional("disk_quota_enabled") => bool,
},
+
+ "allow_nested_warden" => bool,
}
end
end
@@ -203,6 +206,10 @@ def rlimits
@server["container_rlimits"] || {}
end
+ def allow_nested_warden?
+ !!@server["allow_nested_warden"]
+ end
+
def to_hash
{
"server" => server,
@@ -194,38 +194,51 @@ def perform_rsync(src_path, dst_path)
end
def write_bind_mount_commands(request)
- return if request.bind_mounts.nil? || request.bind_mounts.empty?
-
- File.open(File.join(container_path, "lib", "hook-parent-before-clone.sh"), "a") do |file|
+ File.open(File.join(container_path, "lib", "hook-child-before-pivot.sh"), "a") do |file|
file.puts
file.puts
- request.bind_mounts.each do |bind_mount|
- src_path = bind_mount.src_path
- dst_path = bind_mount.dst_path
-
- # Check that the source path exists
- stat = File.stat(src_path) rescue nil
- if stat.nil?
- raise WardenError.new("Source path for bind mount does not exist: #{src_path}")
- end
-
- # Fix up destination path to be an absolute path inside the union
+ add_bind_mount = lambda do |src_path, dst_path, mode|
dst_path = File.join(container_path, "mnt", dst_path[1..-1])
- mode = case bind_mount.mode
- when Protocol::CreateRequest::BindMount::Mode::RO
- "ro"
- when Protocol::CreateRequest::BindMount::Mode::RW
- "rw"
- else
- raise "Unknown mode"
- end
-
file.puts "mkdir -p #{dst_path}" % [dst_path]
file.puts "mount -n --bind #{src_path} #{dst_path}"
file.puts "mount -n --bind -o remount,#{mode} #{src_path} #{dst_path}"
end
+
+ if request.bind_mounts.respond_to?(:each)
+ request.bind_mounts.each do |bind_mount|
+ src_path = bind_mount.src_path
+ dst_path = bind_mount.dst_path
+
+ mode = case bind_mount.mode
+ when Protocol::CreateRequest::BindMount::Mode::RO
+ "ro"
+ when Protocol::CreateRequest::BindMount::Mode::RW
+ "rw"
+ else
+ raise "Unknown mode"
+ end
+
+ add_bind_mount.call(src_path, dst_path, mode)
+ end
+ end
+
+ if Server.config.allow_nested_warden?
+ tmp_warden = File.join(container_path, "tmp", "warden")
+ FileUtils.mkdir_p(tmp_warden)
+
+ # Bind-mount containers
+ add_bind_mount.call(tmp_warden, "/tmp/warden", "rw")
+
+ # Bind-mount rootfs
+ add_bind_mount.call(container_rootfs_path, "/tmp/warden/rootfs", "ro")
+
+ # Bind-mount cgroups
+ %w(cpu cpuacct devices memory).each do |subsystem|
+ add_bind_mount.call(cgroup_path(subsystem), "/tmp/warden/cgroup/#{subsystem}", "rw")
+ end
+ end
end
end
end
@@ -670,9 +670,12 @@ def create
@bind_mount.mode = Warden::Protocol::CreateRequest::BindMount::Mode::RO
@bind_mount.src_path = tmpdir + ".doesnt.exist"
+ # This will fail from the hook-child-before-pivot hook. It is not
+ # possible to check if a bind mount exists before create is executed,
+ # because the bind mount may be created _during_ create.
expect do
create
- end.to raise_error(Warden::Client::ServerError, /\bdoes not exist\b/i)
+ end.to raise_error(Warden::Client::ServerError)
end
end

0 comments on commit c8446d7

Please sign in to comment.