Class: LXC::Extra::Channel

Inherits:
Object
  • Object
show all
Defined in:
lib/lxc/extra/channel.rb

Overview

Bidirectional Ruby communications between a host and an LXC container. It handles bidirectional communications: the host can send a message to the container using channel.send_message, and the container can send to the host using channel.send_message as well.

This class is intended to be created before ct.attach and used by both the host and the container.

Shorthand Usage

require ‘lxc’ require ‘lxc/extra’

container = LXC::Container.new(‘simple’) channel, pid = container.open_channel do |host, number|

puts "received #{number} INSIDE!"
if number > 10
  host.stop
else
  host.send_message(number+1)
end

end channel.send_message(1) channel.listen do |container, number|

puts "received #{number} OUTSIDE!"
container.send_message(number+1) unless number > 10

end

Extended Usage

channel = Channel.new
ct.attach do
  channel.listen do |host, number|
    "received #{number} INSIDE!"
    if number > 10
      host.stop
    else
      host.send(number+1)
    end
  end
end
channel.listen do |container, number|
  "received #{number} OUTSIDE!"
  container.send(number+1)
end

Defined Under Namespace

Classes: Stop

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeChannel

Create a new LXC channel.



54
55
56
57
58
# File 'lib/lxc/extra/channel.rb', line 54

def initialize
  @from_container, @to_host = IO.pipe
  @from_host, @to_container = IO.pipe
  @host_pid = Process.pid
end

Instance Attribute Details

#from_containerObject (readonly)

Returns the value of attribute from_container.



60
61
62
# File 'lib/lxc/extra/channel.rb', line 60

def from_container
  @from_container
end

#from_hostObject (readonly)

Returns the value of attribute from_host.



62
63
64
# File 'lib/lxc/extra/channel.rb', line 62

def from_host
  @from_host
end

#host_pidObject (readonly)

Returns the value of attribute host_pid.



64
65
66
# File 'lib/lxc/extra/channel.rb', line 64

def host_pid
  @host_pid
end

#to_containerObject (readonly)

Returns the value of attribute to_container.



63
64
65
# File 'lib/lxc/extra/channel.rb', line 63

def to_container
  @to_container
end

#to_hostObject (readonly)

Returns the value of attribute to_host.



61
62
63
# File 'lib/lxc/extra/channel.rb', line 61

def to_host
  @to_host
end

Instance Method Details

#listen(&block) ⇒ Object

Listen for data from the other side. Loops until stop is received.

Arguments

&block

callback

Example

channel.listen do |*args|
  puts "Received #{args} from the other side."
end


78
79
80
81
82
83
84
85
86
# File 'lib/lxc/extra/channel.rb', line 78

def listen(&block)
  while true
    args = self.next
    if args.is_a?(Stop)
      return
    end
    block.call(self, *args)
  end
end

#next(stop_result = Stop.singleton) ⇒ Object

Get the next result.

Arguments

stop_result

result to return when the channel wants to shut down. Defaults to LXC::Extra::Channel::Stop.singleton

Returns

Returns nextLXC::Extra::Channel::Stop instance if the channel closes.



108
109
110
111
112
113
114
# File 'lib/lxc/extra/channel.rb', line 108

def next(stop_result = Stop.singleton)
  if read_fd.closed?
    stop_result
  else
    Marshal.load(read_fd)
  end
end

#pretend_message_was_sent(*args) ⇒ Object

Pretend a message was sent from the other side.

For debug purposes.



132
133
134
135
136
137
138
# File 'lib/lxc/extra/channel.rb', line 132

def pretend_message_was_sent(*args)
  if Process.pid == @host_pid
    Marshal.dump(args, @to_host)
  else
    Marshal.dump(args, @to_container)
  end
end

#read_fdObject

File descriptor that receives data from the other side.



154
155
156
157
158
159
160
# File 'lib/lxc/extra/channel.rb', line 154

def read_fd
  if Process.pid == @host_pid
    @from_container
  else
    @from_host
  end
end

#send_message(*args) ⇒ Object

Send a message to the other side. You may send arbitrary Ruby, which will be sent with Marshal.dump.

Arguments

args

a list of arguments to send. Arbitrary Ruby objects may be sent. The other side’s listen callback will receive these arguments.



96
97
98
# File 'lib/lxc/extra/channel.rb', line 96

def send_message(*args)
  Marshal.dump(args, write_fd)
end

#stopObject

Stop the channel. Sends a message to the other side to stop it, too.



119
120
121
122
123
124
125
# File 'lib/lxc/extra/channel.rb', line 119

def stop
  send_message(Stop.singleton)
  @from_container.close
  @to_host.close
  @from_host.close
  @to_container.close
end

#write_fdObject

File descriptor that sends data to the other side.



143
144
145
146
147
148
149
# File 'lib/lxc/extra/channel.rb', line 143

def write_fd
  if Process.pid == @host_pid
    @to_container
  else
    @to_host
  end
end