openflow-controller 0.1.9 → 0.1.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 21f97d89fd5cca91d616a17cc08cb2923bc04752
4
- data.tar.gz: f1025ee07213791f7d3472d8b76026a0ac9ba00f
3
+ metadata.gz: f74e50e943f426a39779802e1598be2a3ec7e718
4
+ data.tar.gz: 5bf304ebd253f6dc4978b92db08b4468c0c433f8
5
5
  SHA512:
6
- metadata.gz: 38f589db1750a5395e5b32efa14a249d06b0530c178fcf649a9c5933ae63cba3f1ce9f3b482f996fc979b6e38e017d4c75d5aa551f82aee3ef201c270fa795c0
7
- data.tar.gz: 6ed5c77459538dd5a16fabe2689886a1a6360b41512998f62d284fe2b19f43ea9b843649ea4d3ea2544c2c3a97954be8be898562d85d680692678ae51fe39545
6
+ metadata.gz: ac6728d86881f6aaad177fc65ba88d96b7dc7490cce185f35f13d4c46ee46f70a15cf5c535892f67e4b027ec4b218f7b9ba7aa437ecf751001faa2c4c86c3a2f
7
+ data.tar.gz: 510b7f3df83fc98ed7dbb137f5e8f68278e6b1a2ebf58954624db81c5a4ae1efba98e0d125cd2140abcfbcefb593c0a404d9260164b5945825bfd212ea2c914c
data/bin/ofctl CHANGED
@@ -1,73 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
- require 'cri'
3
- require 'readline'
4
2
  $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
5
- require 'openflow-controller'
6
-
7
- PROMPT = '> '
8
- BYE_MSG = 'Bye!'
9
-
10
- command = Cri::Command.define do
11
- name 'ofctl'
12
- usage 'ofctl [options] [args]'
13
- summary 'OpenFlow Controller command-line tool'
14
- description 'OpenFlow Controller command-line tool'
15
-
16
- flag :h, :help, 'show help for this command' do |value, cmd|
17
- puts cmd.help
18
- exit 0
19
- end
20
- flag :d, :debug, 'run controller in debug mode'
21
-
22
- option :i, :ip, 'IP address of the controller', argument: :optional
23
- option :p, :port, 'port number of the controller', argument: :optional
24
- option :c, :controller, 'custom controller file', argument: :optional
25
-
26
- run do |opts, args, _cmd|
27
- load opts[:controller] unless opts[:controller].nil?
28
-
29
- debug = opts[:debug] || false
30
-
31
- ctl = OpenFlow::Controller::Controller.create(debug)
32
-
33
- init_form = ctl.logger.formatter
34
- ctl.logger.formatter = proc do |severity, datetime, progname, msg|
35
- buf = PROMPT + Readline::line_buffer
36
- "\r" + ' ' * buf.length + "\r" +
37
- init_form.call(severity, datetime, progname, msg).blue +
38
- buf
39
- end
40
-
41
- ip = opts[:ip] || OpenFlow::Controller::Controller::DEFAULT_IP_ADDRESS
42
- port = opts[:port] || OpenFlow::Controller::Controller::DEFAULT_TCP_PORT
43
-
44
- Thread.abort_on_exception = true
45
- Thread.new do
46
- begin
47
- ctl.run ip, port, args
48
- rescue StandardError => e
49
- puts "#{e.class}: #{e.message}".red
50
- exit 1
51
- end
52
- end
53
-
54
- loop do
55
- begin
56
- input = Readline.readline(PROMPT, true)
57
- if input == 'exit'
58
- puts BYE_MSG
59
- exit
60
- end
61
- output = ctl.eval(input).inspect
62
- puts " => #{output}".green
63
- rescue StandardError => e
64
- puts "#{e.class}: #{e.message}".red
65
- rescue SignalException => e
66
- puts "\n#{BYE_MSG}"
67
- exit
68
- end
69
- end
70
- end
71
- end
72
-
73
- command.run(ARGV)
3
+ require 'openflow-controller/cli'
4
+ OpenFlow::Controller::CLI.run
@@ -0,0 +1,95 @@
1
+ require 'cri'
2
+ require 'openflow-controller/completion'
3
+ require 'openflow-controller/controller'
4
+
5
+ module OpenFlow
6
+ module Controller
7
+ class CLI
8
+ PROMPT = '> '
9
+ BYE_MSG = 'Bye!'
10
+
11
+ def self.run
12
+ create_command.run(ARGV)
13
+ end
14
+
15
+ private
16
+
17
+ def self.print_error(e)
18
+ puts "#{e.class}: #{e.message}".red
19
+ puts e.backtrace.join("\n\t").red
20
+ end
21
+
22
+ def self.run_controller_on_thread(ctl, ip, port, args)
23
+ Thread.abort_on_exception = true
24
+ Thread.new do
25
+ begin
26
+ ctl.run ip, port, args
27
+ rescue StandardError => e
28
+ CLI.print_error e
29
+ exit 1
30
+ end
31
+ end
32
+ end
33
+
34
+ def self.run_cli(ctl)
35
+ loop do
36
+ begin
37
+ input = Readline.readline(PROMPT, true)
38
+ if input.nil? || input == 'exit'
39
+ puts if input.nil?
40
+ puts BYE_MSG
41
+ exit
42
+ end
43
+ output = eval(input, ctl.get_binding).inspect
44
+ # output = ctl.eval(input).inspect
45
+ puts " => #{output}".green
46
+ rescue StandardError, SyntaxError => e
47
+ print_error e
48
+ rescue SignalException
49
+ puts
50
+ end
51
+ end
52
+ end
53
+
54
+ def self.create_command
55
+ Cri::Command.define do
56
+ name 'ofctl'
57
+ usage 'ofctl [options] [args]'
58
+ summary 'OpenFlow Controller command-line tool'
59
+ description 'OpenFlow Controller command-line tool'
60
+
61
+ flag :h, :help, 'show help for this command' do |_value, cmd|
62
+ puts cmd.help
63
+ exit 0
64
+ end
65
+ flag :d, :debug, 'run controller in debug mode'
66
+
67
+ option :i, :ip, 'IP address of the controller', argument: :optional
68
+ option :p, :port, 'port number of the controller', argument: :optional
69
+ option :c, :controller, 'custom controller file', argument: :optional
70
+
71
+ run do |opts, args, _cmd|
72
+ load opts[:controller] unless opts[:controller].nil?
73
+
74
+ ctl = Controller.create
75
+ ctl.set_debug if opts[:debug]
76
+
77
+ init_form = ctl.logger.formatter
78
+ ctl.logger.formatter = proc do |severity, datetime, progname, msg|
79
+ buf = PROMPT + Readline::line_buffer
80
+ "\r" + ' ' * buf.length + "\r" +
81
+ init_form.call(severity, datetime, progname, msg).blue +
82
+ buf
83
+ end
84
+
85
+ ip = opts[:ip] || Controller::DEFAULT_IP_ADDRESS
86
+ port = opts[:port] || Controller::DEFAULT_TCP_PORT
87
+
88
+ CLI.run_controller_on_thread ctl, ip, port, args
89
+ CLI.run_cli ctl
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,219 @@
1
+ require 'readline'
2
+ require 'openflow-controller/controller'
3
+
4
+ module OpenFlow
5
+ module Controller
6
+ module Completion
7
+ # Set of reserved words used by Ruby, you should not use these for
8
+ # constants or variables
9
+ RESERVED_WORDS = %w[
10
+ BEGIN END
11
+ alias and
12
+ begin break
13
+ case class
14
+ def defined do
15
+ else elsif end ensure
16
+ false for
17
+ if in
18
+ module
19
+ next nil not
20
+ or
21
+ redo rescue retry return
22
+ self super
23
+ then true
24
+ undef unless until
25
+ when while
26
+ yield
27
+ ]
28
+
29
+ Proc = proc do |input|
30
+ bind = Controller.instance.get_binding
31
+
32
+ case input
33
+ when /^((["'`]).*\2)\.([^.]*)$/
34
+ # String
35
+ receiver = $1
36
+ message = Regexp.quote($3)
37
+
38
+ candidates = String.instance_methods.map(&:to_s)
39
+ select_message(receiver, message, candidates)
40
+
41
+ when /^(\/[^\/]*\/)\.([^.]*)$/
42
+ # Regexp
43
+ receiver = $1
44
+ message = Regexp.quote($2)
45
+
46
+ candidates = Regexp.instance_methods.map(&:to_s)
47
+ select_message(receiver, message, candidates)
48
+
49
+ when /^([^\]]*\])\.([^.]*)$/
50
+ # Array
51
+ receiver = $1
52
+ message = Regexp.quote($2)
53
+
54
+ candidates = Array.instance_methods.map(&:to_s)
55
+ select_message(receiver, message, candidates)
56
+
57
+ when /^([^\}]*\})\.([^.]*)$/
58
+ # Proc or Hash
59
+ receiver = $1
60
+ message = Regexp.quote($2)
61
+
62
+ candidates = Proc.instance_methods.map(&:to_s)
63
+ candidates |= Hash.instance_methods.map(&:to_s)
64
+ select_message(receiver, message, candidates)
65
+
66
+ when /^(:[^:.]*)$/
67
+ # Symbol
68
+ if Symbol.respond_to?(:all_symbols)
69
+ sym = $1
70
+ candidates = Symbol.all_symbols.map { |s| ':' + s.id2name }
71
+ candidates.grep(/^#{Regexp.quote(sym)}/)
72
+ else
73
+ []
74
+ end
75
+
76
+ when /^::([A-Z][^:\.\(]*)$/
77
+ # Absolute Constant or class methods
78
+ receiver = $1
79
+ candidates = Object.constants.map(&:to_s)
80
+ candidates.grep(/^#{receiver}/).map { |s| '::' + s }
81
+
82
+ when /^([A-Z].*)::([^:.]*)$/
83
+ # Constant or class methods
84
+ receiver = $1
85
+ message = Regexp.quote($2)
86
+ begin
87
+ candidates = eval("#{receiver}.constants.map(&:to_s)", bind)
88
+ candidates |= eval("#{receiver}.methods.map(&:to_s)", bind)
89
+ rescue Exception
90
+ candidates = []
91
+ end
92
+ select_message(receiver, message, candidates, '::')
93
+
94
+ when /^(:[^:.]+)(\.|::)([^.]*)$/
95
+ # Symbol
96
+ receiver = $1
97
+ sep = $2
98
+ message = Regexp.quote($3)
99
+
100
+ candidates = Symbol.instance_methods.map(&:to_s)
101
+ select_message(receiver, message, candidates, sep)
102
+
103
+ when /^(-?(0[dbo])?[0-9_]+(\.[0-9_]+)?([eE]-?[0-9]+)?)(\.|::)([^.]*)$/
104
+ # Numeric
105
+ receiver = $1
106
+ sep = $5
107
+ message = Regexp.quote($6)
108
+
109
+ begin
110
+ candidates = eval(receiver, bind).methods.map(&:to_s)
111
+ rescue Exception
112
+ candidates = []
113
+ end
114
+ select_message(receiver, message, candidates, sep)
115
+
116
+ when /^(-?0x[0-9a-fA-F_]+)(\.|::)([^.]*)$/
117
+ # Numeric(0xFFFF)
118
+ receiver = $1
119
+ sep = $2
120
+ message = Regexp.quote($3)
121
+
122
+ begin
123
+ candidates = eval(receiver, bind).methods.map(&:to_s)
124
+ rescue Exception
125
+ candidates = []
126
+ end
127
+ select_message(receiver, message, candidates, sep)
128
+
129
+ when /^(\$[^.]*)$/
130
+ # global var
131
+ regmessage = Regexp.new(Regexp.quote($1))
132
+ candidates = global_variables.map(&:to_s).grep(regmessage)
133
+
134
+ when /^([^."].*)(\.|::)([^.]*)$/
135
+ # variable.func or func.func
136
+ receiver = $1
137
+ sep = $2
138
+ message = Regexp.quote($3)
139
+
140
+ gv = eval('global_variables', bind).map(&:to_s)
141
+ lv = eval('local_variables', bind).map(&:to_s)
142
+ iv = eval('instance_variables', bind).map(&:to_s)
143
+ cv = eval('self.class.constants', bind).map(&:to_s)
144
+
145
+ if (gv | lv | iv | cv).include?(receiver) or /^[A-Z]/ =~ receiver && /\./ !~ receiver
146
+ # foo.func and foo is var. OR
147
+ # foo::func and foo is var. OR
148
+ # foo::Const and foo is var. OR
149
+ # Foo::Bar.func
150
+ begin
151
+ candidates = []
152
+ rec = eval(receiver, bind)
153
+ if sep == '::' and rec.kind_of?(Module)
154
+ candidates = rec.constants.map(&:to_s)
155
+ end
156
+ candidates |= rec.methods.map(&:to_s)
157
+ rescue Exception
158
+ candidates = []
159
+ end
160
+ else
161
+ # func1.func2
162
+ candidates = []
163
+ ObjectSpace.each_object(Module) do |m|
164
+ begin
165
+ name = m.name
166
+ rescue Exception
167
+ name = ''
168
+ end
169
+ begin
170
+ next if name != "IRB::Context" and
171
+ /^(IRB|SLex|RubyLex|RubyToken)/ =~ name
172
+ rescue Exception
173
+ next
174
+ end
175
+ candidates.concat m.instance_methods(false).map(&:to_s)
176
+ end
177
+ candidates.sort!
178
+ candidates.uniq!
179
+ end
180
+ select_message(receiver, message, candidates, sep)
181
+
182
+ when /^\.([^.]*)$/
183
+ # unknown(maybe String)
184
+ receiver = ''
185
+ message = Regexp.quote($1)
186
+
187
+ candidates = String.instance_methods(true).map(&:to_s)
188
+ select_message(receiver, message, candidates)
189
+
190
+ else
191
+ candidates = eval('methods | private_methods | local_variables | instance_variables | self.class.constants | Object.constants | OpenFlow.constants | OpenFlow::Controller.constants', bind).map(&:to_s)
192
+
193
+ (candidates | RESERVED_WORDS).grep(/^#{Regexp.quote(input)}/)
194
+ end
195
+ end
196
+
197
+ # Set of available operators in Ruby
198
+ OPERATORS = %w[% & * ** + - / < << <= <=> == === =~ > >= >> [] []= ^ ! != !~]
199
+
200
+ def self.select_message(receiver, message, candidates, sep = '.')
201
+ candidates.grep(/^#{message}/).map do |e|
202
+ case e
203
+ when /^[a-zA-Z_]/
204
+ receiver + sep + e
205
+ when /^[0-9]/
206
+ when *OPERATORS
207
+ #receiver + " " + e
208
+ end
209
+ end
210
+ end
211
+ end
212
+ end
213
+ end
214
+
215
+ if Readline.respond_to?('basic_word_break_characters=')
216
+ Readline.basic_word_break_characters = " \t\n`><=;|&{("
217
+ end
218
+ Readline.completion_append_character = nil
219
+ Readline.completion_proc = OpenFlow::Controller::Completion::Proc
@@ -10,6 +10,7 @@ module OpenFlow
10
10
  module Controller
11
11
  class Controller
12
12
  include Protocol
13
+ include PacketProtocols
13
14
 
14
15
  DEFAULT_IP_ADDRESS = '0.0.0.0'
15
16
  DEFAULT_TCP_PORT = 6633
@@ -18,8 +19,12 @@ module OpenFlow
18
19
  @controller_class = subclass
19
20
  end
20
21
 
21
- def self.create(*args)
22
- (@controller_class || self).new(*args)
22
+ def self.create
23
+ @instance = (@controller_class || self).new
24
+ end
25
+
26
+ def self.instance
27
+ @instance
23
28
  end
24
29
 
25
30
  def self.timer_event(handler, options)
@@ -33,19 +38,23 @@ module OpenFlow
33
38
 
34
39
  attr_reader :logger
35
40
 
36
- def initialize(debug = false)
41
+ def initialize
37
42
  @switches = {}
38
43
  @messages = {}
39
44
  @logger = Logger.new($stdout).tap do |logger|
40
45
  logger.formatter = proc do |severity, datetime, _progname, msg|
41
46
  "#{datetime} (#{severity}) -- #{msg}\n"
42
47
  end
43
- logger.level = debug ? Logger::DEBUG : Logger::INFO
48
+ logger.level = Logger::INFO
44
49
  end
45
50
  end
46
51
 
47
- def eval(input)
48
- binding.eval(input)
52
+ def set_debug
53
+ @logger.level = Logger::DEBUG
54
+ end
55
+
56
+ def get_binding
57
+ binding
49
58
  end
50
59
 
51
60
  def run(ip = DEFAULT_IP_ADDRESS, port = DEFAULT_TCP_PORT, *args)
@@ -1,5 +1,5 @@
1
1
  module OpenFlow
2
2
  module Controller
3
- VERSION = '0.1.9'
3
+ VERSION = '0.1.10'
4
4
  end
5
5
  end
@@ -18,6 +18,7 @@ describe Controller do
18
18
  end
19
19
 
20
20
  it 'should handle start' do
21
+ sleep(0.001)
21
22
  expect(@ctl.start_args).to eq(['Hello World!', 42])
22
23
  end
23
24
 
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,6 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
1
3
  require 'openflow-controller'
4
+
2
5
  include OpenFlow::Controller
3
6
  include OpenFlow::Protocol
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openflow-controller
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.1.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jérémy Pagé
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-12 00:00:00.000000000 Z
11
+ date: 2016-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: openflow-protocol
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.1.8
19
+ version: 0.1.9
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 0.1.8
26
+ version: 0.1.9
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: colored
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -56,16 +56,16 @@ dependencies:
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '10.4'
61
+ version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '10.4'
68
+ version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '3.2'
83
+ - !ruby/object:Gem::Dependency
84
+ name: coveralls
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  description: An OpenFlow Controller.
84
98
  email:
85
99
  - contact@jeremypage.me
@@ -90,6 +104,8 @@ extra_rdoc_files: []
90
104
  files:
91
105
  - bin/ofctl
92
106
  - lib/openflow-controller.rb
107
+ - lib/openflow-controller/cli.rb
108
+ - lib/openflow-controller/completion.rb
93
109
  - lib/openflow-controller/controller.rb
94
110
  - lib/openflow-controller/switch.rb
95
111
  - lib/openflow-controller/version.rb