Skip to content

Commit

Permalink
add Virtual Openflow Switch Factory
Browse files Browse the repository at this point in the history
  • Loading branch information
kohoumas committed Feb 13, 2013
1 parent 08c501c commit f238895
Show file tree
Hide file tree
Showing 24 changed files with 1,405 additions and 48 deletions.
25 changes: 17 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# OmfRcOpenflow

OMF Resource Controllers related to Openflow
This package includes OMF6 Resource Controllers (RCs) related to the OpenFlow technology.
The OMF6 framework considers everything (hardware, software, etc) as a separate resource.
This version includes the RCs of the Stanford software tools, named FlowVisor and OpenvSwitch.

* FlowVisor creates OpenFlow Slices (slicing the flow space into separate pieces), so the corresponding RC is the OpenFlow_Slice_Factory.
* OpenvSwitch creates Virtual OpenFlow Switches on top of a Linux machine using the machine's interfaces, so the corresponding RC is the Virtual_OpenFlow_Switch_Factory.

## Installation

Expand All @@ -18,12 +23,16 @@ Or install it yourself as:

## Usage

TODO: Write usage instructions here
In a Linux machine that runs FlowVisor or OpenvSwitch software, execute:

$ omf_rc_openflow_slice_factory

Or execute:

$ omf_rc_virtual_openflow_slice_factory

to control the FlowVisor or OpenvSwitch resource in a OMF6 Experiment Controller (EC).

The 'example' subdirectory includes some examples of experiment descriptions, that could be feeded to the omf_ec binary (the OMF6 EC)

## Contributing

1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Added some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request
38 changes: 38 additions & 0 deletions README.md~
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# OmfRcOpenflow

This package includes OMF6 Resource Controllers (RCs) related to the OpenFlow technology.
The OMF6 framework considers everything (hardware, software, etc) as a separate resource.
This version includes the RCs of the Stanford software tools, named FlowVisor and OpenvSwitch.

* FlowVisor creates OpenFlow Slices (slicing the flow space into separate pieces), so the corresponding RC is the OpenFlow_Slice_Factory.
* OpenvSwitch creates Virtual OpenFlow Switches on top of a Linux machine using the machine's interfaces, so the corresponding RC is the Virtual_OpenFlow_Switch_Factory.

## Installation

Add this line to your application's Gemfile:

gem 'omf_rc_openflow'

And then execute:

$ bundle

Or install it yourself as:

$ gem install omf_rc_openflow

## Usage

In a Linux machine that runs FlowVisor or OpenvSwitch software, execute:

$ omf_rc_openflow_slice_factory

Or execute:

$ omf_rc_virtual_openflow_slice_factory

to control the FlowVisor or OpenvSwitch resource in a OMF6 Experiment Controller (EC).

The 'example' subdirectory includes some examples of experiment descriptions, that could be feeded to the omf_ec binary (the OMF6 EC)


83 changes: 83 additions & 0 deletions bin/omf_rc_virtual_openflow_switch_factory
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/usr/bin/env ruby

require "optparse"
require 'omf_rc'
require 'omf_rc/resource_factory'
require 'omf_rc_openflow'

$stdout.sync = true

options = {
uid: `hostname`.chomp
}

executable_name = File.basename($PROGRAM_NAME)
oml_enabled = false

begin
oml_enabled = OML4R::init(ARGV, :appName => executable_name) do |opts|
opts.banner = "usage: #{executable_name} [options]"

opts.on("-u USER", "Username") do |user|
options[:user] = user
end

opts.on("-p PASSWORD", "Password") do |password|
options[:password] = password
end

opts.on("-s SERVER", "PubSub server") do |server|
options[:server] = server
end

opts.on("-t TOPIC", "PubSub topic to create, also becomes the uid of the resource, default to hostname") do |topic|
options[:uid] = topic
end

opts.on("-d", "--debug", "Debug mode") do
options[:debug] = true
end

opts.on("-l LOG_FILE_DIR", "Write log file to this folder") do |file_dir|
options[:log_file_dir] = file_dir
end
end
rescue => e
# Right now OML4R does not raise proper exceptions :(
# OML4R requires --oml-noop to be set if we want to run without doing any
# measurements... this is too restrictive here, we want to run without OML
# if no OML parameters were set and this even if --oml-noop is not set.
if e.message.include?('OML4R: Missing values for parameters :expID ')
puts "Warning: Missing some OML options to instrument this RC, so it will "+
"run without instrumentation. (see --oml-help)"
else
puts e.message
exit(1)
end
end

OmfCommon::Measure.enable if oml_enabled

unless options[:server] && options[:user] && options[:password]
puts "Error: Missing parameters to connect to a PubSub Server (see --help)"
exit(1)
end

Logging.logger.root.level = :debug if options[:debug]
Blather.logger = logger

if options[:log_file_dir] && File.exist?(options[:log_file_dir])
Logging.logger.root.add_appenders(
Logging.appenders.file(
"#{options[:log_file_dir]}/omf_rc.log",
:layout => Logging.layouts.pattern(:date_pattern => '%F %T %z',
:pattern => '[%d] %-5l %c: %m\n')))
end

EM.run do
virtual_openflow_switch_factory = OmfRc::ResourceFactory.new(:virtual_openflow_switch_factory, options)
virtual_openflow_switch_factory

trap(:INT) { virtual_openflow_switch_factory.disconnect }
trap(:TERM) { virtual_openflow_switch_factory.disconnect }
end
83 changes: 83 additions & 0 deletions bin/omf_rc_virtual_openflow_switch_factory~
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/usr/bin/env ruby

require "optparse"
require 'omf_rc'
require 'omf_rc/resource_factory'
require 'omf_rc_openflow'

$stdout.sync = true

options = {
uid: `hostname`.chomp
}

executable_name = File.basename($PROGRAM_NAME)
oml_enabled = false

begin
oml_enabled = OML4R::init(ARGV, :appName => executable_name) do |opts|
opts.banner = "usage: #{executable_name} [options]"

opts.on("-u USER", "Username") do |user|
options[:user] = user
end

opts.on("-p PASSWORD", "Password") do |password|
options[:password] = password
end

opts.on("-s SERVER", "PubSub server") do |server|
options[:server] = server
end

opts.on("-t TOPIC", "PubSub topic to create, also becomes the uid of the resource, default to hostname") do |topic|
options[:uid] = topic
end

opts.on("-d", "--debug", "Debug mode") do
options[:debug] = true
end

opts.on("-l LOG_FILE_DIR", "Write log file to this folder") do |file_dir|
options[:log_file_dir] = file_dir
end
end
rescue => e
# Right now OML4R does not raise proper exceptions :(
# OML4R requires --oml-noop to be set if we want to run without doing any
# measurements... this is too restrictive here, we want to run without OML
# if no OML parameters were set and this even if --oml-noop is not set.
if e.message.include?('OML4R: Missing values for parameters :expID ')
puts "Warning: Missing some OML options to instrument this RC, so it will "+
"run without instrumentation. (see --oml-help)"
else
puts e.message
exit(1)
end
end

OmfCommon::Measure.enable if oml_enabled

unless options[:server] && options[:user] && options[:password]
puts "Error: Missing parameters to connect to a PubSub Server (see --help)"
exit(1)
end

Logging.logger.root.level = :debug if options[:debug]
Blather.logger = logger

if options[:log_file_dir] && File.exist?(options[:log_file_dir])
Logging.logger.root.add_appenders(
Logging.appenders.file(
"#{options[:log_file_dir]}/omf_rc.log",
:layout => Logging.layouts.pattern(:date_pattern => '%F %T %z',
:pattern => '[%d] %-5l %c: %m\n')))
end

EM.run do
virtual_openflow_switch_factory = OmfRc::ResourceFactory.new(:virtual_openflow_switch_factory, options)
virtual_openflow_switch_factory

trap(:INT) { virtual_openflow_switch_factory.disconnect }
trap(:TERM) { virtual_openflow_switch_factory.disconnect }
end
5 changes: 4 additions & 1 deletion example/openflow_slice_factory_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

require 'omf_rc'
require 'omf_rc/resource_factory'
require 'omf_rc_openflow'
#require 'omf_rc_openflow'
$stdout.sync = true

Blather.logger = logger
Expand All @@ -19,6 +19,9 @@

Logging.logger.root.level = :debug if opts[:debug]

OmfRc::ResourceFactory.load_addtional_resource_proxies(File.dirname(__FILE__)+"/../lib/omf_rc/util")
OmfRc::ResourceFactory.load_addtional_resource_proxies(File.dirname(__FILE__)+"/../lib/omf_rc/resource_proxy")

EM.run do
# Use resource factory method to initialise a new instance of garage
info "Starting #{opts[:uid]}"
Expand Down
33 changes: 33 additions & 0 deletions example/openflow_slice_factory_controller.rb~
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env ruby

require 'omf_rc'
require 'omf_rc/resource_factory'
#require 'omf_rc_openflow'
$stdout.sync = true

Blather.logger = logger

opts = {
# XMPP server domain
server: 'srv.mytestbed.net',
user: 'flowvisor',
password: 'pw',
uid: 'flowvisor',
# Debug mode of not
debug: false
}

Logging.logger.root.level = :debug if opts[:debug]

OmfRc::ResourceFactory.load_addtional_resource_proxies(File.dirname(__FILE__)+"/../lib/omf_rc/resource_proxy")

EM.run do
# Use resource factory method to initialise a new instance of garage
info "Starting #{opts[:uid]}"
flowvisor = OmfRc::ResourceFactory.new(:openflow_slice_factory, opts)
flowvisor.connect

# Disconnect garage from XMPP server, when these two signals received
trap(:INT) { flowvisor.disconnect }
trap(:TERM) { flowvisor.disconnect }
end
76 changes: 44 additions & 32 deletions example/openflow_slice_factory_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,49 +4,61 @@

# @comm is default communicator defined in script runner
#
flowvisor_id = "flowvisor"
flowvisor_topic = @comm.get_topic(flowvisor_id)
@flowvisor_id = "flowvisor"
@flowvisor_topic = @comm.get_topic(@flowvisor_id)

flowvisor_topic.on_message lambda {|m| m.operation == :inform && m.read_content('inform_type') == 'CREATION_FAILED' } do |message|
logger.error message
end
@slice_id = nil
@slice_topic = nil

msgs = {
create: @comm.create_message([type: 'openflow_slice', name: 'test1']),
request: @comm.request_message([:flows]),
create_slice: @comm.create_message([type: 'openflow_slice']),
config_slice: @comm.configure_message([name: 'test', contact_email: 'a@a']),
slices: @comm.request_message([:slices]),
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'},
{operation: 'add', device: '00:00:00:00:00:00:00:01', eth_dst: '11:22:33:44:55:77'}]]),
}

%w{request}.each do |s|
msgs[s.to_sym].on_inform_status do |message|
message.each_property do |p|
logger.info "#{p.attr('key')} => #{p.content.strip}"
end
end
end
@flowvisor_topic.subscribe {msgs[:create_slice].publish @flowvisor_id}

msgs[:create].on_inform_creation_failed do |message|
logger.error "Resource creation failed ---"
logger.error message.read_content("reason")
# If flowvisor is not raised, the following rule will be activated.
@flowvisor_topic.on_message lambda {|m| m.operation == :inform && m.read_content('inform_type') == 'CREATION_FAILED' } do |message|
logger.error message.read_content('reason')
done!
end

msgs[:create].on_inform_creation_ok do |message|
slice_topic = @comm.get_topic(message.resource_id)
slice_id = slice_topic.id

msgs[:release] ||= @comm.release_message { |m| m.element('resource_id', slice_id) }

msgs[:release].on_inform_released do |message|
logger.info "Slice (#{message.resource_id}) deleted (resource released)"
done!
msgs[:create_slice].on_inform_creation_ok do |message|
@slice_id = message.resource_id
@slice_topic = @comm.get_topic(@slice_id)

msgs[:release_slice] ||= @comm.release_message {|m| m.element('resource_id', @slice_id)}
msgs[:release_slice].on_inform_released do |message|
logger.info "Slice (#{@slice_id}) released"
m = @comm.request_message([:slices])
m.on_inform_status do |message|
logger.info "Flowvisor (#{message.read_property('uid')}) requested slices: #{message.read_property('slices').join(', ')}"
done!
end
m.publish @flowvisor_id
end

logger.info "Slice (#{@slice_id}) created"
@slice_topic.subscribe {msgs[:config_slice].publish @slice_id}
end

logger.info "Slice #{slice_id} ready for testing"
msgs[:config_slice].on_inform_status do |message|
logger.info "Slice (#{message.read_property('uid')}) configured name: #{message.read_property('name')} & contact_email: #{message.read_property('contact_email')}"
msgs[:slices].publish @flowvisor_id
end

slice_topic.subscribe do
msgs[:request].publish slice_id
end
msgs[:slices].on_inform_status do |message|
logger.info "Flowvisor (#{message.read_property('uid')}) requested slices: #{message.read_property('slices').join(', ')}"
msgs[:config_flows].publish @slice_id
end

flowvisor_topic.subscribe do
msgs[:create].publish flowvisor_topic.id
msgs[:config_flows].on_inform_status do |message|
logger.info "Slice (#{message.read_property('uid')}) configured flows: "
message.read_property('flows').each do |flow|
logger.info " #{flow}"
end
msgs[:release_slice].publish @flowvisor_id
end
Loading

0 comments on commit f238895

Please sign in to comment.