phut 0.1.0 → 0.2.0

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: 38a59abc94f4a6e4dc8d9881736b06e5c461a20c
4
- data.tar.gz: 9e93f07ecb38aef9907182d681655e3ed9712db5
3
+ metadata.gz: 9b2838869618793f7529456e67f55820c6312fd4
4
+ data.tar.gz: b38be67f933c105564abad75ffe2c9e545787757
5
5
  SHA512:
6
- metadata.gz: 342641815042a8dfb0ce100cb5f3605e563a06a6d48ea30396d458b0b6bf1fdedb323dd521c8118d1b8675148eae89a671576279e5418b57f96195de263204dc
7
- data.tar.gz: c92c0c02de7f761540024a219a4a0eb6663dcfa61db066e3f8cf5ae5b6b0ac7b8da6f03f0de119942f809179b068f2562bd0dcf9170fe387f407d32a733e0327
6
+ metadata.gz: b19c285acc17e89ee19d803c1f161b741cfbd1305692af023f057aac4f06a3a7c37d0d84c31e6cfb52d0d02a2024c76609a495de38ff756cba6d2f2761369eef
7
+ data.tar.gz: 3f51908add6cd7e341ed596c2dad7d361b3838ad70337d232248d55b1fc8795f3b7b533e1147f7bba875643b5618ac9a77f590f04657d9da3dbf83d7ccd0e331
data/.hound.yml ADDED
@@ -0,0 +1,3 @@
1
+ ruby:
2
+ enabled: true
3
+ config_file: .rubocop.yml
data/.rubocop.yml CHANGED
@@ -9,3 +9,9 @@ AllCops:
9
9
  - phut.gemspec
10
10
  - spec/**/*.rb
11
11
  - tasks/*.rake
12
+
13
+ Style/StringLiterals:
14
+ EnforcedStyle: single_quotes
15
+
16
+ Style/DotPosition:
17
+ EnforcedStyle: trailing
data/CHANGELOG.md CHANGED
@@ -3,6 +3,11 @@
3
3
  ## develop (unreleased)
4
4
 
5
5
 
6
+ ## 0.2.0 (3/2/2015)
7
+ ### New features
8
+ * [#19](https://github.com/trema/phut/pull/19): Add `bin/vhost`.
9
+
10
+
6
11
  ## 0.1.0 (2/23/2015)
7
12
  ### Misc
8
13
  * The initial release version of phut.
data/Rakefile CHANGED
@@ -2,7 +2,7 @@ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), 'lib')
2
2
 
3
3
  require 'rake/clean'
4
4
 
5
- task default: [:openvswitch, :vhost]
5
+ task default: :openvswitch
6
6
  task test: [:spec, :cucumber, :quality]
7
7
  task quality: [:rubocop, :reek, :flog]
8
8
  task travis: [:spec, 'cucumber:travis', :quality]
data/bin/phut CHANGED
@@ -62,9 +62,9 @@ module Phut
62
62
  logger.formatter = proc { |_sev, _dtm, _name, msg| msg + "\n" }
63
63
  logger.level = global_options[:verbose] ? Logger::DEBUG : Logger::INFO
64
64
  end
65
- Phut.pid_dir = options[:pid_dir]
66
- Phut.log_dir = options[:log_dir]
67
- Phut.socket_dir = options[:socket_dir]
65
+ Phut.pid_dir = options.fetch(:pid_dir)
66
+ Phut.log_dir = options.fetch(:log_dir)
67
+ Phut.socket_dir = options.fetch(:socket_dir)
68
68
  Phut::Parser.new(stdout_logger).parse(args[0]).run
69
69
  end
70
70
  end
data/bin/vhost ADDED
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
3
+
4
+ require 'gli'
5
+ require 'phut'
6
+
7
+ module Phut
8
+ class VhostDaemon
9
+ # /bin/vhost command
10
+ module App
11
+ extend GLI::App
12
+
13
+ version Phut::VERSION
14
+
15
+ desc 'Runs a vhost process'
16
+ command :run do |c|
17
+ desc 'Host name'
18
+ c.flag [:n, :name]
19
+ desc 'Network interface'
20
+ c.flag [:I, :interface]
21
+ desc 'IP address'
22
+ c.flag [:i, :ip_address]
23
+ desc 'MAC address'
24
+ c.flag [:m, :mac_address]
25
+ c.desc 'ARP entries'
26
+ c.flag [:a, :arp_entries], negatable: false
27
+ c.desc 'Promisc mode'
28
+ c.switch [:p, :promisc], negatable: false
29
+
30
+ c.desc 'Location to put pid files'
31
+ c.flag [:P, :pid_dir], default_value: Phut.pid_dir
32
+ c.desc 'Location to put log files'
33
+ c.flag [:L, :log_dir], default_value: Phut.log_dir
34
+ c.desc 'Location to put socket files'
35
+ c.flag [:S, :socket_dir], default_value: Phut.socket_dir
36
+
37
+ c.action do |_global_options, options, _args|
38
+ fail '--name option is mandatory' if options[:name].nil?
39
+ fail '--interface option is mandatory' if options[:interface].nil?
40
+ fail '--ip_address option is mandatory' if options[:ip_address].nil?
41
+ fail '--mac_address option is mandatory' if options[:mac_address].nil?
42
+ options[:arp_table] =
43
+ options[:arp_entries].split(',').
44
+ each_with_object({}) do |each, table|
45
+ ip_address, mac_address = each.split('/')
46
+ table[ip_address] = mac_address
47
+ end
48
+ VhostDaemon.new(options).run
49
+ end
50
+ end
51
+
52
+ desc 'Terminates a vhost process'
53
+ command :stop do |c|
54
+ desc 'Host name'
55
+ c.flag [:n, :name]
56
+
57
+ c.desc 'Location to put socket files'
58
+ c.flag [:S, :socket_dir], default_value: Phut.socket_dir
59
+
60
+ c.action do |_global_options, options, _args|
61
+ fail '--name option is mandatory' if options[:name].nil?
62
+ begin
63
+ VhostDaemon.process(options[:name], options[:socket_dir]).stop
64
+ rescue DRb::DRbConnError
65
+ true # OK
66
+ end
67
+ end
68
+ end
69
+
70
+ desc 'Sends UDP packets to destination host'
71
+ command :send_packets do |c|
72
+ desc 'Source host name'
73
+ c.flag [:s, :source]
74
+
75
+ c.action do |_global_options, options, _args|
76
+ fail '--source option is mandatory' if options[:source].nil?
77
+ VhostDaemon.process(options[:source], options[:socket_dir]).
78
+ send_packets
79
+ end
80
+ end
81
+
82
+ default_command :help
83
+
84
+ exit run(ARGV)
85
+ end
86
+ end
87
+ end
data/features/dsl.feature CHANGED
@@ -22,5 +22,5 @@ Feature: DSL parser
22
22
  Then the exit status should not be 0
23
23
  And the stderr should contain:
24
24
  """
25
- The name 192.168.0.1 conflicts with vhost (name = 192.168.0.1, ip = 192.168.0.1).
25
+ The name 192.168.0.1 conflicts with vhost (name = 192.168.0.1, IP address = 192.168.0.1).
26
26
  """
@@ -15,7 +15,7 @@ end
15
15
 
16
16
  Then(/^a vhost named "(.*?)" launches$/) do |name|
17
17
  in_current_dir do
18
- pid_file = File.join(File.expand_path(@pid_dir), "phost.#{name}.pid")
18
+ pid_file = File.join(File.expand_path(@pid_dir), "vhost.#{name}.pid")
19
19
  step %(a file named "#{pid_file}" should exist)
20
20
  end
21
21
  end
data/lib/phut.rb CHANGED
@@ -1,5 +1,5 @@
1
- require 'phut/cli'
2
1
  require 'phut/open_vswitch'
3
2
  require 'phut/parser'
4
3
  require 'phut/setting'
5
4
  require 'phut/version'
5
+ require 'phut/vhost_daemon'
@@ -19,7 +19,7 @@ module Phut
19
19
  end
20
20
 
21
21
  def vhosts
22
- @all.values.select { |each| each.is_a? Phost }
22
+ @all.values.select { |each| each.is_a? Vhost }
23
23
  end
24
24
 
25
25
  def links
@@ -45,7 +45,7 @@ module Phut
45
45
 
46
46
  def add_vhost(name, attrs)
47
47
  check_name_conflict name
48
- @all[name] = Phost.new(attrs[:ip], attrs[:promisc], name, @logger)
48
+ @all[name] = Vhost.new(attrs[:ip], attrs[:promisc], name, @logger)
49
49
  end
50
50
 
51
51
  # This method smells of :reek:LongParameterList
@@ -0,0 +1,26 @@
1
+ require 'socket'
2
+
3
+ module Phut
4
+ # raw socket
5
+ class RawSocket
6
+ ETH_P_ALL = 0x0300
7
+ SIOCGIFINDEX = 0x8933
8
+
9
+ def initialize(interface)
10
+ @socket =
11
+ Socket.new(Socket::PF_PACKET, Socket::SOCK_RAW, ETH_P_ALL).tap do |sock|
12
+ ifreq = [interface].pack('a32')
13
+ sock.ioctl SIOCGIFINDEX, ifreq
14
+ sock.bind([Socket::AF_PACKET].pack('s').tap do |sll|
15
+ sll << ([ETH_P_ALL].pack 's')
16
+ sll << ifreq[16..20]
17
+ sll << ("\x00" * 12)
18
+ end)
19
+ end
20
+ end
21
+
22
+ def method_missing(method, *args)
23
+ @socket.__send__ method, *args
24
+ end
25
+ end
26
+ end
data/lib/phut/setting.rb CHANGED
@@ -5,7 +5,7 @@ module Phut
5
5
  # Central configuration repository.
6
6
  class Setting
7
7
  DEFAULTS = {
8
- root: File.expand_path(File.join(__dir__, '..', '..')),
8
+ root: File.expand_path(File.join(File.dirname(__FILE__), '..', '..')),
9
9
  pid_dir: Dir.tmpdir,
10
10
  log_dir: Dir.tmpdir,
11
11
  socket_dir: Dir.tmpdir
data/lib/phut/syntax.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'phut/phost'
1
+ require 'phut/vhost'
2
2
  require 'phut/virtual_link'
3
3
 
4
4
  module Phut
data/lib/phut/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # Base module.
2
2
  module Phut
3
- VERSION = '0.1.0'
3
+ VERSION = '0.2.0'
4
4
  end
data/lib/phut/vhost.rb ADDED
@@ -0,0 +1,73 @@
1
+ require 'phut/null_logger'
2
+ require 'phut/setting'
3
+ require 'phut/shell_runner'
4
+ require 'pio/mac'
5
+
6
+ module Phut
7
+ # An interface class to vhost emulation utility program.
8
+ class Vhost
9
+ include ShellRunner
10
+
11
+ attr_reader :ip_address
12
+ attr_reader :mac_address
13
+ attr_accessor :interface
14
+
15
+ def initialize(ip_address, promisc, name = nil, logger = NullLogger.new)
16
+ @ip_address = ip_address
17
+ @promisc = promisc
18
+ @name = name
19
+ @mac_address = Pio::Mac.new(rand(0xffffffffffff + 1))
20
+ @logger = logger
21
+ end
22
+
23
+ def name
24
+ @name || @ip_address
25
+ end
26
+
27
+ def to_s
28
+ "vhost (name = #{name}, IP address = #{@ip_address})"
29
+ end
30
+
31
+ def run(all_hosts = [])
32
+ sh "rvmsudo vhost run #{run_options all_hosts}"
33
+ end
34
+
35
+ def stop
36
+ fail "vhost (name = #{name}) is not running!" unless running?
37
+ sh "vhost stop -n #{name} -s #{Phut.socket_dir}"
38
+ end
39
+
40
+ def maybe_stop
41
+ return unless running?
42
+ stop
43
+ end
44
+
45
+ def running?
46
+ FileTest.exists?(pid_file)
47
+ end
48
+
49
+ private
50
+
51
+ def run_options(all_hosts)
52
+ ["-n #{name}",
53
+ "-I #{interface}",
54
+ "-i #{@ip_address}",
55
+ "-m #{@mac_address}",
56
+ "-a #{arp_entries all_hosts}",
57
+ @promisc ? '--promisc' : nil,
58
+ "-P #{Phut.pid_dir}",
59
+ "-L #{Phut.log_dir}",
60
+ "-S #{Phut.socket_dir}"].compact.join(' ')
61
+ end
62
+
63
+ def arp_entries(all_hosts)
64
+ all_hosts.map do |each|
65
+ "#{each.ip_address}/#{each.mac_address}"
66
+ end.join(',')
67
+ end
68
+
69
+ def pid_file
70
+ "#{Phut.pid_dir}/vhost.#{name}.pid"
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,148 @@
1
+ require 'drb'
2
+ require 'logger'
3
+ require 'phut/raw_socket'
4
+ require 'pio'
5
+
6
+ module Phut
7
+ # vhost daemon process
8
+ # rubocop:disable ClassLength
9
+ class VhostDaemon
10
+ def self.unix_domain_socket(name, socket_dir)
11
+ "drbunix:#{socket_dir}/vhost.#{name}.ctl"
12
+ end
13
+
14
+ def self.process(name, socket_dir)
15
+ DRbObject.new_with_uri(unix_domain_socket(name, socket_dir))
16
+ end
17
+
18
+ def initialize(options)
19
+ @options = options
20
+ @packets_sent = []
21
+ @packets_received = []
22
+ end
23
+
24
+ def run
25
+ start_logging
26
+ create_pid_file
27
+ start_daemon
28
+ rescue
29
+ shutdown
30
+ end
31
+
32
+ def stop
33
+ @stop = true
34
+ end
35
+
36
+ def send_packets(dest, npackets)
37
+ return unless lookup_arp_table(dest.ip_address)
38
+ udp = create_udp_packet(dest)
39
+ npackets.times do
40
+ write_to_raw_socket udp
41
+ @logger.info "Sent to #{dest.name}: #{udp}"
42
+ end
43
+ end
44
+
45
+ def stats
46
+ { tx: @packets_sent, rx: @packets_received }
47
+ end
48
+
49
+ private
50
+
51
+ def start_logging
52
+ @logger = Logger.new(log_file)
53
+ @logger.info("#{@options.fetch(:name)} started " \
54
+ "(interface = #{@options.fetch(:interface)}," \
55
+ " IP address = #{@options.fetch(:ip_address)}," \
56
+ " MAC address = #{@options.fetch(:mac_address)}," \
57
+ " arp_entries = #{@options.fetch(:arp_entries)})")
58
+ end
59
+
60
+ def raw_socket
61
+ @raw_socket ||= RawSocket.new(@options.fetch(:interface))
62
+ end
63
+
64
+ def lookup_arp_table(ip_address)
65
+ @options.fetch(:arp_table)[ip_address]
66
+ end
67
+
68
+ def write_to_raw_socket(packet)
69
+ @packets_sent << packet.snapshot
70
+ raw_socket.write packet.to_binary_s
71
+ end
72
+
73
+ def create_udp_packet(dest)
74
+ Pio::Udp.new(source_mac: @options.fetch(:mac_address),
75
+ destination_mac: dest.mac_address,
76
+ ip_source_address: @options.fetch(:ip_address),
77
+ ip_destination_address: dest.ip_address)
78
+ end
79
+
80
+ def log_file
81
+ "#{@options.fetch(:log_dir)}/vhost.#{@options.fetch(:name)}.log"
82
+ end
83
+
84
+ def read_loop
85
+ loop do
86
+ raw_data, = raw_socket.recvfrom(8192)
87
+ udp = Pio::Udp.read(raw_data)
88
+ # TODO: Check @options[:promisc]
89
+ @logger.info "Received: #{udp}"
90
+ @packets_received << udp.snapshot
91
+ end
92
+ end
93
+
94
+ def start_daemon
95
+ Process.daemon
96
+ trap_sigint
97
+ update_pid_file
98
+ start_threads_and_join
99
+ end
100
+
101
+ def start_threads_and_join
102
+ unix_domain_socket =
103
+ self.class.unix_domain_socket(@options.fetch(:name),
104
+ @options.fetch(:socket_dir))
105
+ DRb.start_service(unix_domain_socket, self, UNIXFileMode: 0666)
106
+ Thread.start { read_loop }.abort_on_exception = true
107
+ DRb.thread.join
108
+ end
109
+
110
+ def shutdown
111
+ @logger.error $ERROR_INFO if $ERROR_INFO
112
+ @logger.info 'Shutting down...'
113
+ FileUtils.rm pid_file if running?
114
+ fail $ERROR_INFO if $ERROR_INFO
115
+ end
116
+
117
+ def trap_sigint
118
+ Thread.start { shutdown_loop }.abort_on_exception = true
119
+ Signal.trap(:INT) { stop }
120
+ end
121
+
122
+ def shutdown_loop
123
+ loop do
124
+ break if @stop
125
+ sleep 0.1
126
+ end
127
+ shutdown
128
+ end
129
+
130
+ def create_pid_file
131
+ fail "#{@options.fetch(:name)} is already running." if running?
132
+ update_pid_file
133
+ end
134
+
135
+ def update_pid_file
136
+ File.open(pid_file, 'w') { |file| file << Process.pid }
137
+ end
138
+
139
+ def running?
140
+ FileTest.exists?(pid_file)
141
+ end
142
+
143
+ def pid_file
144
+ File.join @options.fetch(:pid_dir), "vhost.#{@options.fetch(:name)}.pid"
145
+ end
146
+ end
147
+ # rubocop:enable ClassLength
148
+ end
data/phut.gemspec CHANGED
@@ -15,7 +15,7 @@ Gem::Specification.new do |gem|
15
15
  gem.email = ['yasuhito@gmail.com']
16
16
  gem.homepage = 'http://github.com/trema/phut'
17
17
 
18
- gem.executables = %w(phut)
18
+ gem.executables = %w(phut vhost)
19
19
  gem.files = `git ls-files`.split("\n")
20
20
 
21
21
  gem.extensions = ['Rakefile']
@@ -26,7 +26,7 @@ Gem::Specification.new do |gem|
26
26
  gem.required_ruby_version = '>= 2.0.0'
27
27
 
28
28
  gem.add_dependency 'gli', '~> 2.12.3'
29
- gem.add_dependency 'pio', '~> 0.15.2'
29
+ gem.add_dependency 'pio', '~> 0.16.0'
30
30
  gem.add_dependency 'pry', '~> 0.10.1'
31
31
 
32
32
  # Docs
@@ -47,7 +47,7 @@ CONFIG
47
47
 
48
48
  describe '#vhost' do
49
49
  Then { config.vhosts.size == 2 }
50
- Then { config.fetch('192.168.0.1').ip == '192.168.0.1' }
50
+ Then { config.fetch('192.168.0.1').ip_address == '192.168.0.1' }
51
51
  end
52
52
  end
53
53
 
@@ -62,7 +62,7 @@ CONFIG
62
62
 
63
63
  describe '#vhost' do
64
64
  Then { config.vhosts.size == 2 }
65
- Then { config.fetch('host1').ip == '192.168.0.1' }
65
+ Then { config.fetch('host1').ip_address == '192.168.0.1' }
66
66
  end
67
67
  end
68
68
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phut
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yasuhito Takamiya
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-23 00:00:00.000000000 Z
11
+ date: 2015-03-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gli
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - ~>
32
32
  - !ruby/object:Gem::Version
33
- version: 0.15.2
33
+ version: 0.16.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ~>
39
39
  - !ruby/object:Gem::Version
40
- version: 0.15.2
40
+ version: 0.16.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: pry
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -309,12 +309,14 @@ email:
309
309
  - yasuhito@gmail.com
310
310
  executables:
311
311
  - phut
312
+ - vhost
312
313
  extensions:
313
314
  - Rakefile
314
315
  extra_rdoc_files:
315
316
  - README.md
316
317
  files:
317
318
  - .gitignore
319
+ - .hound.yml
318
320
  - .rspec
319
321
  - .rubocop.yml
320
322
  - .ruby-version
@@ -327,6 +329,7 @@ files:
327
329
  - README.md
328
330
  - Rakefile
329
331
  - bin/phut
332
+ - bin/vhost
330
333
  - features/dsl.feature
331
334
  - features/dsl_link.feature
332
335
  - features/dsl_vhost.feature
@@ -337,16 +340,17 @@ files:
337
340
  - features/support/env.rb
338
341
  - features/support/hooks.rb
339
342
  - lib/phut.rb
340
- - lib/phut/cli.rb
341
343
  - lib/phut/configuration.rb
342
344
  - lib/phut/null_logger.rb
343
345
  - lib/phut/open_vswitch.rb
344
346
  - lib/phut/parser.rb
345
- - lib/phut/phost.rb
347
+ - lib/phut/raw_socket.rb
346
348
  - lib/phut/setting.rb
347
349
  - lib/phut/shell_runner.rb
348
350
  - lib/phut/syntax.rb
349
351
  - lib/phut/version.rb
352
+ - lib/phut/vhost.rb
353
+ - lib/phut/vhost_daemon.rb
350
354
  - lib/phut/virtual_link.rb
351
355
  - phut.gemspec
352
356
  - spec/phut/open_vswitch_spec.rb
@@ -361,43 +365,10 @@ files:
361
365
  - tasks/relish.rake
362
366
  - tasks/rspec.rake
363
367
  - tasks/rubocop.rake
364
- - tasks/vhost.rake
365
368
  - vendor/.gitignore
366
369
  - vendor/README.md
367
370
  - vendor/openvswitch-1.2.2.trema1.tar.gz
368
371
  - vendor/openvswitch-1.2.2_librt-check.diff
369
- - vendor/phost/src/.gitignore
370
- - vendor/phost/src/Makefile
371
- - vendor/phost/src/arp.c
372
- - vendor/phost/src/arp.h
373
- - vendor/phost/src/cli.c
374
- - vendor/phost/src/cli.h
375
- - vendor/phost/src/cmdif.c
376
- - vendor/phost/src/cmdif.h
377
- - vendor/phost/src/common.c
378
- - vendor/phost/src/common.h
379
- - vendor/phost/src/eth.c
380
- - vendor/phost/src/eth.h
381
- - vendor/phost/src/ethdev.c
382
- - vendor/phost/src/ethdev.h
383
- - vendor/phost/src/icmp.c
384
- - vendor/phost/src/icmp.h
385
- - vendor/phost/src/ipv4.c
386
- - vendor/phost/src/ipv4.h
387
- - vendor/phost/src/log.c
388
- - vendor/phost/src/log.h
389
- - vendor/phost/src/phost.c
390
- - vendor/phost/src/phost.h
391
- - vendor/phost/src/stats.c
392
- - vendor/phost/src/stats.h
393
- - vendor/phost/src/tap.c
394
- - vendor/phost/src/tap.h
395
- - vendor/phost/src/trx.c
396
- - vendor/phost/src/trx.h
397
- - vendor/phost/src/udp.c
398
- - vendor/phost/src/udp.h
399
- - vendor/phost/src/utils.c
400
- - vendor/phost/src/utils.h
401
372
  homepage: http://github.com/trema/phut
402
373
  licenses:
403
374
  - GPL3
data/lib/phut/cli.rb DELETED
@@ -1,61 +0,0 @@
1
- require 'phut/null_logger'
2
- require 'phut/setting'
3
- require 'phut/shell_runner'
4
-
5
- module Phut
6
- # cli command wrapper.
7
- class Cli
8
- include ShellRunner
9
-
10
- def initialize(host, logger = NullLogger.new)
11
- @host = host
12
- @logger = logger
13
- end
14
-
15
- def send_packets(dest, options = {})
16
- n_pkts = options[:n_pkts]
17
- sh [executable,
18
- "-i #{@host.interface} send_packets",
19
- "--ip_dst #{dest.ip}",
20
- "--ip_src #{@host.ip}",
21
- '--tp_src 1',
22
- '--tp_dst 1',
23
- '--pps 1',
24
- '--length 22',
25
- n_pkts ? "--n_pkts=#{n_pkts}" : '--duration 1'].join(' ')
26
- end
27
-
28
- def show_tx_stats
29
- puts stats(:tx)
30
- end
31
-
32
- def show_rx_stats
33
- puts stats(:rx)
34
- end
35
-
36
- def add_arp_entry(other)
37
- sh "sudo #{executable} -i #{@host.interface} add_arp_entry " \
38
- "--ip_addr #{other.ip} --mac_addr #{other.mac}"
39
- end
40
-
41
- def set_ip_and_mac_address
42
- sh "sudo #{executable} -i #{@host.interface} set_host_addr " \
43
- "--ip_addr #{@host.ip} --ip_mask #{@host.netmask} " \
44
- "--mac_addr #{@host.mac}"
45
- end
46
-
47
- def enable_promisc
48
- sh "sudo #{executable} -i #{@host.interface} enable_promisc"
49
- end
50
-
51
- private
52
-
53
- def executable
54
- "#{Phut.root}/vendor/phost/src/cli"
55
- end
56
-
57
- def stats(type)
58
- `sudo #{executable} -i #{@host.interface} show_stats --#{type}`
59
- end
60
- end
61
- end
data/lib/phut/phost.rb DELETED
@@ -1,92 +0,0 @@
1
- require 'phut/cli'
2
- require 'phut/null_logger'
3
- require 'phut/setting'
4
- require 'phut/shell_runner'
5
- require 'pio/mac'
6
-
7
- module Phut
8
- # An interface class to phost emulation utility program.
9
- class Phost
10
- include ShellRunner
11
-
12
- attr_reader :ip
13
- attr_reader :mac
14
- attr_accessor :interface
15
-
16
- def initialize(ip_address, promisc, name = nil, logger = NullLogger.new)
17
- @ip = ip_address
18
- @promisc = promisc
19
- @name = name
20
- @mac = Pio::Mac.new(rand(0xffffffffffff + 1))
21
- @logger = logger
22
- end
23
-
24
- def name
25
- @name || @ip
26
- end
27
-
28
- def to_s
29
- "vhost (name = #{name}, ip = #{@ip})"
30
- end
31
-
32
- def run(hosts = [])
33
- sh "sudo #{executable} #{options.join ' '}"
34
- sleep 1
35
- set_ip_and_mac_address
36
- maybe_enable_promisc
37
- add_arp_entries hosts
38
- end
39
-
40
- def stop
41
- fail "phost (name = #{name}) is not running!" unless running?
42
- pid = IO.read(pid_file)
43
- sh "sudo kill #{pid}"
44
- end
45
-
46
- def maybe_stop
47
- return unless running?
48
- stop
49
- end
50
-
51
- def netmask
52
- '255.255.255.255'
53
- end
54
-
55
- def running?
56
- FileTest.exists?(pid_file)
57
- end
58
-
59
- private
60
-
61
- def set_ip_and_mac_address
62
- Phut::Cli.new(self, @logger).set_ip_and_mac_address
63
- end
64
-
65
- def maybe_enable_promisc
66
- return unless @promisc
67
- Phut::Cli.new(self).enable_promisc
68
- end
69
-
70
- def add_arp_entries(hosts)
71
- hosts.each do |each|
72
- Phut::Cli.new(self).add_arp_entry each
73
- end
74
- end
75
-
76
- def pid_file
77
- "#{Phut.pid_dir}/phost.#{name}.pid"
78
- end
79
-
80
- def executable
81
- "#{Phut.root}/vendor/phost/src/phost"
82
- end
83
-
84
- def options
85
- %W(-p #{Phut.pid_dir}
86
- -l #{Phut.log_dir}
87
- -n #{name}
88
- -i #{interface}
89
- -D)
90
- end
91
- end
92
- end
data/tasks/vhost.rake DELETED
@@ -1,32 +0,0 @@
1
- require 'phut'
2
-
3
- def phost_src
4
- File.join Phut.root, 'vendor', 'phost', 'src'
5
- end
6
-
7
- def phost_objects
8
- FileList[File.join(phost_src, '*.o')]
9
- end
10
-
11
- def phost_vendor_binary
12
- File.join phost_src, 'phost'
13
- end
14
-
15
- def phost_cli_vendor_binary
16
- File.join phost_src, 'cli'
17
- end
18
-
19
- desc 'Build vhost executables'
20
- task vhost: [phost_vendor_binary, phost_cli_vendor_binary]
21
-
22
- file phost_vendor_binary do
23
- cd phost_src do
24
- sh 'make'
25
- end
26
- end
27
-
28
- file phost_cli_vendor_binary do
29
- cd phost_src do
30
- sh 'make'
31
- end
32
- end