Skip to content

Instantly share code, notes, and snippets.

@jkeiser
Last active August 29, 2015 13:57
Show Gist options
  • Save jkeiser/9631780 to your computer and use it in GitHub Desktop.
Save jkeiser/9631780 to your computer and use it in GitHub Desktop.
root@test:/mnt/host_src/chef-metal-lxc# ruby -I lib lxccheck.rb
received 1 INSIDE!
received 2 OUTSIDE!
received 3 INSIDE!
received 4 OUTSIDE!
received 5 INSIDE!
received 6 OUTSIDE!
received 7 INSIDE!
received 8 OUTSIDE!
received 9 INSIDE!
received 10 OUTSIDE!
received 11 INSIDE!
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
container = LXC::Container.new('foo')
listener = ChefMetalLXC::LXCMessagePasser.attach(container) do |host, number|
puts "received #{number} INSIDE!"
if number > 10
host.stop
else
host.send_message(number+1)
end
end
listener.send_message(1)
listener.listen do |container, number|
puts "received #{number} OUTSIDE!"
container.send_message(number+1) unless number > 10
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment