omf_rc_openflow 6.0.0.pre
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.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/bin/omf_rc_openflow_slice_factory +83 -0
- data/example/openflow_slice_factory_controller.rb +33 -0
- data/example/openflow_slice_factory_test.rb +64 -0
- data/lib/omf_rc/resource_proxy/openflow_slice.rb +82 -0
- data/lib/omf_rc/resource_proxy/openflow_slice_factory.rb +72 -0
- data/lib/omf_rc/util/openflow_tools.rb +103 -0
- data/lib/omf_rc_openflow/version.rb +3 -0
- data/lib/omf_rc_openflow.rb +5 -0
- data/omf_rc_openflow.gemspec +18 -0
- metadata +72 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Jack C Hong
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# OmfRcOpenflow
|
2
|
+
|
3
|
+
OMF Resource Controllers related to Openflow
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'omf_rc_openflow'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install omf_rc_openflow
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "optparse"
|
4
|
+
require 'omf_rc'
|
5
|
+
require 'omf_rc/resource_factory'
|
6
|
+
require 'omf_rc_openflow'
|
7
|
+
|
8
|
+
$stdout.sync = true
|
9
|
+
|
10
|
+
options = {
|
11
|
+
uid: `hostname`.chomp
|
12
|
+
}
|
13
|
+
|
14
|
+
executable_name = File.basename($PROGRAM_NAME)
|
15
|
+
oml_enabled = false
|
16
|
+
|
17
|
+
begin
|
18
|
+
oml_enabled = OML4R::init(ARGV, :appName => executable_name) do |opts|
|
19
|
+
opts.banner = "usage: #{executable_name} [options]"
|
20
|
+
|
21
|
+
opts.on("-u USER", "Username") do |user|
|
22
|
+
options[:user] = user
|
23
|
+
end
|
24
|
+
|
25
|
+
opts.on("-p PASSWORD", "Password") do |password|
|
26
|
+
options[:password] = password
|
27
|
+
end
|
28
|
+
|
29
|
+
opts.on("-s SERVER", "PubSub server") do |server|
|
30
|
+
options[:server] = server
|
31
|
+
end
|
32
|
+
|
33
|
+
opts.on("-t TOPIC", "PubSub topic to create, also becomes the uid of the resource, default to hostname") do |topic|
|
34
|
+
options[:uid] = topic
|
35
|
+
end
|
36
|
+
|
37
|
+
opts.on("-d", "--debug", "Debug mode") do
|
38
|
+
options[:debug] = true
|
39
|
+
end
|
40
|
+
|
41
|
+
opts.on("-l LOG_FILE_DIR", "Write log file to this folder") do |file_dir|
|
42
|
+
options[:log_file_dir] = file_dir
|
43
|
+
end
|
44
|
+
end
|
45
|
+
rescue => e
|
46
|
+
# Right now OML4R does not raise proper exceptions :(
|
47
|
+
# OML4R requires --oml-noop to be set if we want to run without doing any
|
48
|
+
# measurements... this is too restrictive here, we want to run without OML
|
49
|
+
# if no OML parameters were set and this even if --oml-noop is not set.
|
50
|
+
if e.message.include?('OML4R: Missing values for parameters :expID ')
|
51
|
+
puts "Warning: Missing some OML options to instrument this RC, so it will "+
|
52
|
+
"run without instrumentation. (see --oml-help)"
|
53
|
+
else
|
54
|
+
puts e.message
|
55
|
+
exit(1)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
OmfCommon::Measure.enable if oml_enabled
|
60
|
+
|
61
|
+
unless options[:server] && options[:user] && options[:password]
|
62
|
+
puts "Error: Missing parameters to connect to a PubSub Server (see --help)"
|
63
|
+
exit(1)
|
64
|
+
end
|
65
|
+
|
66
|
+
Logging.logger.root.level = :debug if options[:debug]
|
67
|
+
Blather.logger = logger
|
68
|
+
|
69
|
+
if options[:log_file_dir] && File.exist?(options[:log_file_dir])
|
70
|
+
Logging.logger.root.add_appenders(
|
71
|
+
Logging.appenders.file(
|
72
|
+
"#{options[:log_file_dir]}/omf_rc.log",
|
73
|
+
:layout => Logging.layouts.pattern(:date_pattern => '%F %T %z',
|
74
|
+
:pattern => '[%d] %-5l %c: %m\n')))
|
75
|
+
end
|
76
|
+
|
77
|
+
EM.run do
|
78
|
+
openflow_slice_factory = OmfRc::ResourceFactory.new(:openflow_slice_factory, options)
|
79
|
+
openflow_slice_factory.connect
|
80
|
+
|
81
|
+
trap(:INT) { openflow_slice_factory.disconnect }
|
82
|
+
trap(:TERM) { openflow_slice_factory.disconnect }
|
83
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'omf_rc'
|
4
|
+
require 'omf_rc/resource_factory'
|
5
|
+
#require 'omf_rc_openflow'
|
6
|
+
$stdout.sync = true
|
7
|
+
|
8
|
+
Blather.logger = logger
|
9
|
+
|
10
|
+
opts = {
|
11
|
+
# XMPP server domain
|
12
|
+
server: 'srv.mytestbed.net',
|
13
|
+
user: 'flowvisor',
|
14
|
+
password: 'pw',
|
15
|
+
uid: 'flowvisor',
|
16
|
+
# Debug mode of not
|
17
|
+
debug: false
|
18
|
+
}
|
19
|
+
|
20
|
+
Logging.logger.root.level = :debug if opts[:debug]
|
21
|
+
|
22
|
+
OmfRc::ResourceFactory.load_addtional_resource_proxies(File.dirname(__FILE__)+"/../lib/omf_rc/resource_proxy")
|
23
|
+
|
24
|
+
EM.run do
|
25
|
+
# Use resource factory method to initialise a new instance of garage
|
26
|
+
info "Starting #{opts[:uid]}"
|
27
|
+
flowvisor = OmfRc::ResourceFactory.new(:openflow_slice_factory, opts)
|
28
|
+
flowvisor.connect
|
29
|
+
|
30
|
+
# Disconnect garage from XMPP server, when these two signals received
|
31
|
+
trap(:INT) { flowvisor.disconnect }
|
32
|
+
trap(:TERM) { flowvisor.disconnect }
|
33
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# OMF_VERSIONS = 6.0
|
2
|
+
|
3
|
+
@comm = OmfEc.comm
|
4
|
+
|
5
|
+
# @comm is default communicator defined in script runner
|
6
|
+
#
|
7
|
+
@flowvisor_id = "flowvisor"
|
8
|
+
@flowvisor_topic = @comm.get_topic(@flowvisor_id)
|
9
|
+
|
10
|
+
@slice_id = nil
|
11
|
+
@slice_topic = nil
|
12
|
+
|
13
|
+
msgs = {
|
14
|
+
create_slice: @comm.create_message([type: 'openflow_slice']),
|
15
|
+
config_slice: @comm.configure_message([name: 'test', contact_email: 'a@a']),
|
16
|
+
slices: @comm.request_message([:slices]),
|
17
|
+
config_flows: @comm.configure_message([flows: [{operation: 'add', device: '00:00:00:00:00:00:00:01', eth_dst: '11:22:33:44:55:66'},
|
18
|
+
{operation: 'add', device: 1, in_port: 10}]]),
|
19
|
+
}
|
20
|
+
|
21
|
+
@flowvisor_topic.subscribe {msgs[:create_slice].publish @flowvisor_id}
|
22
|
+
|
23
|
+
# If flowvisor is not raised, the following rule will be activated.
|
24
|
+
@flowvisor_topic.on_message lambda {|m| m.operation == :inform && m.read_content('inform_type') == 'CREATION_FAILED' } do |message|
|
25
|
+
logger.error message.read_content('reason')
|
26
|
+
done!
|
27
|
+
end
|
28
|
+
|
29
|
+
msgs[:create_slice].on_inform_creation_ok do |message|
|
30
|
+
@slice_id = message.resource_id
|
31
|
+
@slice_topic = @comm.get_topic(@slice_id)
|
32
|
+
|
33
|
+
msgs[:release_slice] ||= @comm.release_message {|m| m.element('resource_id', @slice_id)}
|
34
|
+
msgs[:release_slice].on_inform_released do |message|
|
35
|
+
logger.info "Slice (#{@slice_id}) released"
|
36
|
+
m = @comm.request_message([:slices])
|
37
|
+
m.on_inform_status do |message|
|
38
|
+
logger.info "Flowvisor (#{message.read_property('uid')}) requested slices: #{message.read_property('slices').join(', ')}"
|
39
|
+
done!
|
40
|
+
end
|
41
|
+
m.publish @flowvisor_id
|
42
|
+
end
|
43
|
+
|
44
|
+
logger.info "Slice (#{@slice_id}) created"
|
45
|
+
@slice_topic.subscribe {msgs[:config_slice].publish @slice_id}
|
46
|
+
end
|
47
|
+
|
48
|
+
msgs[:config_slice].on_inform_status do |message|
|
49
|
+
logger.info "Slice (#{message.read_property('uid')}) configured name: #{message.read_property('name')} & contact_email: #{message.read_property('contact_email')}"
|
50
|
+
msgs[:slices].publish @flowvisor_id
|
51
|
+
end
|
52
|
+
|
53
|
+
msgs[:slices].on_inform_status do |message|
|
54
|
+
logger.info "Flowvisor (#{message.read_property('uid')}) requested slices: #{message.read_property('slices').join(', ')}"
|
55
|
+
msgs[:config_flows].publish @slice_id
|
56
|
+
end
|
57
|
+
|
58
|
+
msgs[:config_flows].on_inform_status do |message|
|
59
|
+
logger.info "Slice (#{message.read_property('uid')}) configured flows: "
|
60
|
+
message.read_property('flows').each do |flow|
|
61
|
+
logger.info " #{flow}"
|
62
|
+
end
|
63
|
+
msgs[:release_slice].publish @flowvisor_id
|
64
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# This resource is created from the parent :openflow_slice_factory resource.
|
2
|
+
# It is related with a slice of a flowvisor instance, and behaves as a proxy between experimenter and the actual flowvisor slice.
|
3
|
+
#
|
4
|
+
module OmfRc::ResourceProxy::OpenflowSlice
|
5
|
+
include OmfRc::ResourceProxyDSL
|
6
|
+
|
7
|
+
# The default parameters of a new slice. The openflow controller is assumed to be in the same working station with flowvisor instance
|
8
|
+
SLICE_DEFAULTS = {
|
9
|
+
passwd: "1234",
|
10
|
+
url: "tcp:127.0.0.1:9933",
|
11
|
+
email: "nothing@nowhere"
|
12
|
+
}
|
13
|
+
|
14
|
+
|
15
|
+
register_proxy :openflow_slice, :create_by => :openflow_slice_factory
|
16
|
+
|
17
|
+
utility :openflow_tools
|
18
|
+
|
19
|
+
|
20
|
+
# Slice's name is initiated with value "nil"
|
21
|
+
hook :before_ready do |resource|
|
22
|
+
resource.property.name = nil
|
23
|
+
end
|
24
|
+
|
25
|
+
# Before release, the related flowvisor instance should also remove the corresponding slice
|
26
|
+
hook :before_release do |resource|
|
27
|
+
resource.flowvisor_connection.call("api.deleteSlice", resource.property.name)
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
# The name is one-time configured
|
32
|
+
configure :name do |resource, name|
|
33
|
+
raise "The name cannot be changed" if resource.property.name
|
34
|
+
resource.property.name = name.to_s
|
35
|
+
begin
|
36
|
+
resource.flowvisor_connection.call("api.createSlice", name.to_s, *SLICE_DEFAULTS.values)
|
37
|
+
rescue Exception => e
|
38
|
+
if e.message["Cannot create slice with existing name"]
|
39
|
+
logger.warn message = "The requested slice already existed in Flowvisor"
|
40
|
+
else
|
41
|
+
raise e
|
42
|
+
end
|
43
|
+
end
|
44
|
+
resource.property.name
|
45
|
+
end
|
46
|
+
|
47
|
+
# Configures the slice password
|
48
|
+
configure :passwd do |resource, passwd|
|
49
|
+
resource.flowvisor_connection.call("api.changePasswd", resource.property.name, passwd.to_s)
|
50
|
+
passwd.to_s
|
51
|
+
end
|
52
|
+
|
53
|
+
# Configures the slice parameters
|
54
|
+
[:contact_email, :drop_policy, :controller_hostname, :controller_port].each do |configure_sym|
|
55
|
+
configure configure_sym do |resource, value|
|
56
|
+
resource.flowvisor_connection.call("api.changeSlice", resource.property.name, configure_sym.to_s, value.to_s)
|
57
|
+
value.to_s
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Adds/removes a flow to this slice, specified by device, port, etc.
|
62
|
+
configure :flows do |resource, array_parameters|
|
63
|
+
array_parameters = [array_parameters] if !array_parameters.kind_of?(Array)
|
64
|
+
array_parameters.each do |parameters|
|
65
|
+
resource.flowvisor_connection.call("api.changeFlowSpace", resource.transformed_parameters(parameters))
|
66
|
+
end
|
67
|
+
resource.flows
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
# Returns a hash table with the name of this slice, its controller (ip and port) and other related information
|
72
|
+
request :info do |resource|
|
73
|
+
result = resource.flowvisor_connection.call("api.getSliceInfo", resource.property.name)
|
74
|
+
result[:name] = resource.property.name
|
75
|
+
result
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns a string with statistics about the use of this slice
|
79
|
+
request :stats do |resource|
|
80
|
+
resource.flowvisor_connection.call("api.getSliceStats", resource.property.name)
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# This resourse is related with a flowvisor instance and behaves as a proxy between experimenter and flowvisor.
|
2
|
+
#
|
3
|
+
module OmfRc::ResourceProxy::OpenflowSliceFactory
|
4
|
+
include OmfRc::ResourceProxyDSL
|
5
|
+
|
6
|
+
# The default arguments of the communication between this resource and the flowvisor instance
|
7
|
+
FLOWVISOR_CONNECTION_DEFAULTS = {
|
8
|
+
host: "localhost",
|
9
|
+
path: "/xmlrc",
|
10
|
+
port: "8080",
|
11
|
+
proxy_host: nil,
|
12
|
+
proxy_port: nil,
|
13
|
+
user: "fvadmin",
|
14
|
+
password: "openflow",
|
15
|
+
use_ssl: "true",
|
16
|
+
timeout: nil
|
17
|
+
}
|
18
|
+
|
19
|
+
|
20
|
+
register_proxy :openflow_slice_factory
|
21
|
+
|
22
|
+
utility :openflow_tools
|
23
|
+
|
24
|
+
|
25
|
+
# Checks if the created child is an :openflow_slice resource and passes the connection arguments that are essential for the connection with flowvisor instance
|
26
|
+
hook :before_create do |resource, type, opts = nil|
|
27
|
+
if type.to_sym != :openflow_slice
|
28
|
+
raise "This resource doesn't create resources of type "+type
|
29
|
+
end
|
30
|
+
begin
|
31
|
+
resource.flowvisor_connection
|
32
|
+
rescue
|
33
|
+
raise "This resource is not connected with a flowvisor instance, so it cannot create openflow slices"
|
34
|
+
end
|
35
|
+
opts.property ||= Hashie::Mash.new
|
36
|
+
opts.property.provider = ">> #{resource.uid}"
|
37
|
+
opts.property.flowvisor_connection_args = resource.property.flowvisor_connection_args
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
# A new resource uses the default connection arguments (ip adress, port, etc) to connect with a flowvisor instance
|
42
|
+
hook :before_ready do |resource|
|
43
|
+
resource.property.flowvisor_connection_args = FLOWVISOR_CONNECTION_DEFAULTS
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
# Configures the flowvisor connection arguments (ip adress, port, etc)
|
48
|
+
configure :flowvisor_connection do |resource, flowvisor_connection_args|
|
49
|
+
raise "Connection with a new flowvisor instance is not allowed if there exist created slices" if !resource.children.empty?
|
50
|
+
resource.property.flowvisor_connection_args.update(flowvisor_connection_args)
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
# Returns the flowvisor connection arguments (ip adress, port, etc)
|
55
|
+
request :flowvisor_connection do |resource|
|
56
|
+
resource.property.flowvisor_connection_args
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns a list of the existed slices or the connected devices
|
60
|
+
{:slices => "listSlices", :devices => "listDevices"}.each do |request_sym, handler_name|
|
61
|
+
request request_sym do |resource|
|
62
|
+
resource.flowvisor_connection.call("api.#{handler_name}")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns information or statistics for a device specified by the given id
|
67
|
+
{:device_info => "getDeviceInfo", :device_stats => "getSwitchStats"}.each do |request_sym, handler_name|
|
68
|
+
request request_sym do |resource, device|
|
69
|
+
resource.flowvisor_connection.call("api.#{handler_name}", device.to_s)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'xmlrpc/client'
|
2
|
+
|
3
|
+
module OmfRc::Util::OpenflowTools
|
4
|
+
include OmfRc::ResourceProxyDSL
|
5
|
+
|
6
|
+
# The version of the flowvisor that this resource is able to control
|
7
|
+
FLOWVISOR_VERSION = "FV version=flowvisor-0.8.4"
|
8
|
+
|
9
|
+
# Parts of the regular expression that describes a flow entry for flowvisor
|
10
|
+
FLOWVISOR_FLOWENTRY_REGEXP_DEVIDED = [
|
11
|
+
/dpid=\[(?<device>.+)\]/,
|
12
|
+
/ruleMatch=\[OFMatch\[(?<match>.+)\]\]/,
|
13
|
+
/actionsList=\[Slice:(?<slice>.+)=(?<actions>.+)\]/,
|
14
|
+
/id=\[(?<id>.+)\]/,
|
15
|
+
/priority=\[(?<priority>.+)\]/
|
16
|
+
]
|
17
|
+
|
18
|
+
# The regular expression that describes a flow entry for flowvisor
|
19
|
+
FLOWVISOR_FLOWENTRY_REGEXP = /FlowEntry\[#{FLOWVISOR_FLOWENTRY_REGEXP_DEVIDED.join(',')},\]/
|
20
|
+
|
21
|
+
# The names of the flow (or flow entry) features
|
22
|
+
FLOW_FEATURES = %w{device match slice actions id priority}
|
23
|
+
|
24
|
+
# The names of the flow (or flow entry) features that are specified by the "match" feature
|
25
|
+
FLOW_MATCH_FEATURES = %w{in_port eth_src eth_dst ip_src ip_dst}
|
26
|
+
|
27
|
+
# The default features of a new flow (or flow entry)
|
28
|
+
FLOW_DEFAULTS = {
|
29
|
+
priority: "10",
|
30
|
+
actions: "4"
|
31
|
+
}
|
32
|
+
|
33
|
+
|
34
|
+
# Returns the flows (flow entries) that exist for this flowvisor
|
35
|
+
request :flows do |resource, filter = nil|
|
36
|
+
resource.flows(filter)
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
# Internal function that creates a connection with a flowvisor instance and checks it
|
41
|
+
work :flowvisor_connection do |resource|
|
42
|
+
xmlrpc_client = XMLRPC::Client.new_from_hash(resource.property.flowvisor_connection_args)
|
43
|
+
xmlrpc_client.instance_variable_get("@http").verify_mode = OpenSSL::SSL::VERIFY_NONE
|
44
|
+
ping_msg = "test"
|
45
|
+
pong_msg = "PONG(#{resource.property.flowvisor_connection_args[:user]}): #{FLOWVISOR_VERSION}::#{ping_msg}"
|
46
|
+
raise "Connection with #{FLOWVISOR_VERSION} was not successful" if xmlrpc_client.call("api.ping", ping_msg) != pong_msg
|
47
|
+
xmlrpc_client
|
48
|
+
end
|
49
|
+
|
50
|
+
# Internal function that returns the flows (flow entries) that exist in the connected flowvisor instance
|
51
|
+
work :flows do |resource, filter = nil|
|
52
|
+
result = resource.flowvisor_connection.call("api.listFlowSpace")
|
53
|
+
result.map! do |line|
|
54
|
+
array_values = line.match(FLOWVISOR_FLOWENTRY_REGEXP)[1..-1]
|
55
|
+
# Example of above array's content: %w{00:00:...:01 in_port=1 test 4 30 10}
|
56
|
+
array_features_values_zipped = FLOW_FEATURES.zip(array_values)
|
57
|
+
# Example of above array's content: %w{device 00:00:...:01 match in_port=1 slice test actions 4 id 30 priority 10}
|
58
|
+
hash = Hashie::Mash.new(Hash[array_features_values_zipped])
|
59
|
+
# The following code adds extra features that are specified by the "match" feature
|
60
|
+
hash["match"].split(",").each do |couple|
|
61
|
+
array = couple.split("=")
|
62
|
+
hash[array[0]] = array[1]
|
63
|
+
end
|
64
|
+
hash
|
65
|
+
end
|
66
|
+
result.delete_if {|hash| hash["slice"] != resource.property.name} if resource.type.to_sym == :openflow_slice
|
67
|
+
FLOW_FEATURES.each do |feature|
|
68
|
+
result.delete_if {|hash| hash[feature] != filter[feature].to_s} if filter[feature]
|
69
|
+
end if filter
|
70
|
+
result
|
71
|
+
end
|
72
|
+
|
73
|
+
work :transformed_parameters do |resource, parameters|
|
74
|
+
|
75
|
+
match = []
|
76
|
+
FLOW_MATCH_FEATURES.each do |feature|
|
77
|
+
match << "#{feature}=#{parameters[feature]}" if parameters[feature]
|
78
|
+
end
|
79
|
+
match = match.join(",")
|
80
|
+
|
81
|
+
result = []
|
82
|
+
case parameters.operation
|
83
|
+
when "add"
|
84
|
+
h = Hashie::Mash.new
|
85
|
+
h.operation = parameters.operation.upcase
|
86
|
+
h.priority = parameters.priority ? parameters.priority.to_s : FLOW_DEFAULTS[:priority]
|
87
|
+
h.dpid = parameters.device.to_s
|
88
|
+
h.actions = "Slice:#{resource.property.name}=#{(parameters.actions ? parameters.actions : FLOW_DEFAULTS[:actions])}"
|
89
|
+
h.match = "OFMatch[#{match}]"
|
90
|
+
result << h
|
91
|
+
when "remove"
|
92
|
+
resource.flows(parameters).each do |f|
|
93
|
+
if f.match == match
|
94
|
+
h = Hashie::Mash.new
|
95
|
+
h.operation = parameters.operation.upcase
|
96
|
+
h.id = f.id
|
97
|
+
result << h
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
result
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/omf_rc_openflow/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Kostas Choumas"]
|
6
|
+
gem.email = ["kohoumas@gmail.com"]
|
7
|
+
gem.description = %q{OMF Resource Controllers related to Openflow}
|
8
|
+
gem.summary = %q{OMF Resource Controllers related to Openflow}
|
9
|
+
gem.homepage = "http://nitlab.inf.uth.gr"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "omf_rc_openflow"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = OmfRcOpenflow::VERSION
|
17
|
+
gem.add_runtime_dependency "omf_rc", "~> 6.0.0.pre"
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: omf_rc_openflow
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 6.0.0.pre
|
5
|
+
prerelease: 6
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Kostas Choumas
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-01-19 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: omf_rc
|
16
|
+
requirement: &20473800 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 6.0.0.pre
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *20473800
|
25
|
+
description: OMF Resource Controllers related to Openflow
|
26
|
+
email:
|
27
|
+
- kohoumas@gmail.com
|
28
|
+
executables:
|
29
|
+
- omf_rc_openflow_slice_factory
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- .gitignore
|
34
|
+
- Gemfile
|
35
|
+
- LICENSE
|
36
|
+
- README.md
|
37
|
+
- Rakefile
|
38
|
+
- bin/omf_rc_openflow_slice_factory
|
39
|
+
- example/openflow_slice_factory_controller.rb
|
40
|
+
- example/openflow_slice_factory_test.rb
|
41
|
+
- lib/omf_rc/resource_proxy/openflow_slice.rb
|
42
|
+
- lib/omf_rc/resource_proxy/openflow_slice_factory.rb
|
43
|
+
- lib/omf_rc/util/openflow_tools.rb
|
44
|
+
- lib/omf_rc_openflow.rb
|
45
|
+
- lib/omf_rc_openflow/version.rb
|
46
|
+
- omf_rc_openflow.gemspec
|
47
|
+
homepage: http://nitlab.inf.uth.gr
|
48
|
+
licenses: []
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options: []
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ! '>='
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ! '>'
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 1.3.1
|
65
|
+
requirements: []
|
66
|
+
rubyforge_project:
|
67
|
+
rubygems_version: 1.8.11
|
68
|
+
signing_key:
|
69
|
+
specification_version: 3
|
70
|
+
summary: OMF Resource Controllers related to Openflow
|
71
|
+
test_files: []
|
72
|
+
has_rdoc:
|