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 ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in omf_rc_foo.gemspec
4
+ gemspec
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,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -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,3 @@
1
+ module OmfRcOpenflow
2
+ VERSION = "6.0.0.pre"
3
+ end
@@ -0,0 +1,5 @@
1
+ require "omf_rc_openflow/version"
2
+
3
+ require 'omf_rc/resource_proxy/openflow_slice_factory.rb'
4
+ require 'omf_rc/resource_proxy/openflow_slice.rb'
5
+ require 'omf_rc/util/openflow_tools.rb'
@@ -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: