omf_rc_openflow 6.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|