module ChefMetalLXC
#
# This class is intended to be created before ct.attach. You can listen
# to it for messages from The Other Side.
#
# Shorthand Usage:
# listener = LXCMessagePasser.attach(container) do |host, number|
# "received #{number} INSIDE!"
# if number > 10
# host.stop
# else
# host.send_message(number+1)
# end
# end
# listener.listen do |container, number|
# "received #{number} OUTSIDE!"
# container.send_message(number+1) unless number > 10
# end
#
# Usage:
# listener = LXCMessagePasser.new
# ct.attach do
# listener.listen do |host, number|
# "received #{number} INSIDE!"
# if number > 10
# host.stop
# else
# host.send(number+1)
# end
# end
# end
# listener.listen do |container, number|
# "received #{number} OUTSIDE!"
# container.send(number+1)
# end
#
class LXCMessagePasser
def self.attach(container, &block)
listener = LXCMessagePasser.new
container.attach do
listener.listen(&block)
end
listener
end
def initialize
@from_container, @to_host = IO.pipe
@from_host, @to_container = IO.pipe
@host_pid = Process.pid
end
def listen(&block)
while true
args = self.next
if args.size == 1 && args[0].is_a?(Stop)
return
end
begin
block.call(self, *args)
rescue
raise
end
end
end
def send_message(*args)
if Process.pid == @host_pid
Marshal.dump(args, @to_container)
else
Marshal.dump(args, @to_host)
end
end
def next
if Process.pid == @host_pid
args = Marshal.load(@from_container)
else
args = Marshal.load(@from_host)
end
args
end
def stop
send_message(Stop.new)
@from_container.close
@to_host.close
@from_host.close
@to_container.close
end
private
class Stop
end
end
end