-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use OVSDB client in order to retrive port list #41
base: develop
Are you sure you want to change the base?
Changes from all commits
df55d62
239eacd
7ee0730
6cba466
e7c153b
42a37e4
4af7df1
88513b6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,3 +5,4 @@ | |
require 'phut/version' | ||
require 'phut/vhost_daemon' | ||
require 'phut/vswitch' | ||
require 'phut/ovsdb' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
require 'phut/ovsdb/client' | ||
require 'phut/ovsdb/transaction' | ||
|
||
module Phut | ||
# OVSDB client core | ||
module OVSDB; end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
|
||
Primitive OVSDB client implementation | ||
=== | ||
|
||
Supports [RFC7047](https://tools.ietf.org/html/rfc7047). | ||
|
||
## Examples | ||
|
||
### Transaction | ||
|
||
* Create Bridge | ||
|
||
```ruby | ||
require 'active_flow' | ||
|
||
class OVSDBTest | ||
extend ActiveFlow::OVSDB::Transact | ||
|
||
def self.create_bridge(name, ofc_target, bridge_options = {}) | ||
client = ActiveFlow::OVSDB::Client.new('localhost', 6632) | ||
ovs_rows_query = select('Open_vSwitch', [], [:_uuid, :bridges]) | ||
ovs_row = client.transact(1, 'Open_vSwitch', [ovs_rows_query]).first[:rows].first | ||
ovs_bridges = ovs_row[:bridges] | ||
new_ovs_bridges = case ovs_bridges.include?('set') | ||
when true | ||
ovs_bridges_content = ovs_bridges[1] | ||
case ovs_bridges_content.empty? | ||
when true | ||
['named-uuid', "bridge_br_#{name}"] | ||
else | ||
['set', ovs_bridges_content << ['named-uuid', "bridge_br_#{name}"]] | ||
end | ||
else | ||
ovs_bridges_content = ovs_bridges[1] | ||
['set', [ovs_bridges_content] << ['named-uuid', "bridge_br_#{name}"]] | ||
end | ||
ovs_uuid = ovs_row[:_uuid] | ||
interface = { name: "br-#{name}", type: "internal" } | ||
port = { name: "br-#{name}", interfaces: ['named-uuid', "interface_br_#{name}"] } | ||
controller = { target: ofc_target } | ||
bridge = { name: "br-#{name}", ports: ['named-uuid', "port_br_#{name}"], controller: ['named-uuid', "ofc_br_#{name}"], protocols: 'OpenFlow10' } | ||
transactions = [ | ||
insert('Interface', interface, "interface_br_#{name}"), | ||
insert('Port', port, "port_br_#{name}"), | ||
insert('Controller', controller, "ofc_br_#{name}"), | ||
insert('Bridge', bridge, "bridge_br_#{name}"), | ||
update('Open_vSwitch', [[:_uuid, :==, ovs_uuid]], { bridges: new_ovs_bridges }), | ||
mutate('Open_vSwitch', [[:_uuid, :==, ovs_uuid]], [[:next_cfg, '+=', 1]]) | ||
] | ||
client.transact(1, 'Open_vSwitch', transactions) | ||
transactions = [ | ||
update('Bridge', [[:name, :==, "br-#{name}"]], { other_config: [:map, bridge_options.to_a] }), | ||
mutate('Open_vSwitch', [[:_uuid, :==, ovs_uuid]], [[:next_cfg, '+=', 1]]) | ||
] | ||
client.transact(1, 'Open_vSwitch', transactions) | ||
end | ||
|
||
def self.connect_with_patch(br1, br2) | ||
patch_br1 = "patch-#{br1}" | ||
patch_br2 = "patch-#{br2}" | ||
client = ActiveFlow::OVSDB::Client.new('localhost', 6632) | ||
ovs_rows_query = select('Open_vSwitch', [], [:_uuid]) | ||
ovs_row = client.transact(1, 'Open_vSwitch', [ovs_rows_query]).first[:rows].first | ||
ovs_uuid = ovs_row[:_uuid] | ||
selects = [ | ||
select('Bridge', [[:name, :==, br1]], [:ports]), | ||
select('Bridge', [[:name, :==, br2]], [:ports]) | ||
] | ||
br1_ports, br2_ports = client.transact(1, 'Open_vSwitch', selects) | ||
new_br1_ports = br1_ports.map do |_, item| | ||
ports = item[0][:ports].include?('set') ? item[0][:ports][1] : [item[0][:ports]] | ||
[:set, ports << ['named-uuid', :patch_br1]] | ||
end.first | ||
new_br2_ports = br2_ports.map do |_, item| | ||
ports = item[0][:ports].include?('set') ? item[0][:ports][1] : [item[0][:ports]] | ||
[:set, ports << ['named-uuid', :patch_br2]] | ||
end.first | ||
|
||
patch_br1_port = {name: patch_br1, interfaces: ['named-uuid', :patch_br1_iface]} | ||
patch_br2_port = {name: patch_br2, interfaces: ['named-uuid', :patch_br2_iface]} | ||
|
||
patch_br1_iface = {name: patch_br1, type: :patch, options: [:map, {peer: patch_br2}.to_a]} | ||
patch_br2_iface = {name: patch_br2, type: :patch, options: [:map, {peer: patch_br1}.to_a]} | ||
|
||
transactions = [ | ||
insert('Interface', patch_br1_iface, :patch_br1_iface), | ||
insert('Interface', patch_br2_iface, :patch_br2_iface), | ||
insert('Port', patch_br1_port, :patch_br1), | ||
insert('Port', patch_br2_port, :patch_br2), | ||
update('Bridge', [[:name, :==, br1]], { ports: new_br1_ports }), | ||
update('Bridge', [[:name, :==, br2]], { ports: new_br2_ports }), | ||
mutate('Open_vSwitch', [[:_uuid, :==, ovs_uuid]], [[:next_cfg, '+=', 1]]) | ||
] | ||
client.transact(1, 'Open_vSwitch', transactions) | ||
end | ||
end | ||
|
||
# OVSDBTest.create_bridge('def', 'tcp:127.0.0.1:6653', 'datapath-id' => '0000000000000def') | ||
# OVSDBTest.connect_with_patch('nts0xabc', 'br-def') | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
require 'phut/ovsdb/method' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing frozen string literal comment. |
||
require 'phut/ovsdb/transport' | ||
require 'yajl' | ||
|
||
module Phut | ||
module OVSDB | ||
# OVSDB Client core | ||
class Client | ||
include Phut::OVSDB::Method | ||
|
||
attr_reader :transport | ||
attr_reader :database | ||
|
||
def initialize(host, port, options = {}) | ||
@mut = Mutex.new | ||
@queue = Queue.new | ||
@transport = Transport.new(host, port, self, options) | ||
@database = options.fetch(:database, nil) | ||
initialize_codec | ||
end | ||
|
||
def handle_tcp(data) | ||
@parser << data | ||
end | ||
|
||
def handle_message(data) | ||
case data[:method] | ||
when 'echo' | ||
echo_reply | ||
else | ||
maybe_handle_reply(data) | ||
end | ||
end | ||
|
||
private | ||
|
||
def maybe_handle_reply(data) | ||
id = data[:id] | ||
case id | ||
when 'echo' | ||
:noop | ||
else | ||
@queue.enq(data) | ||
end | ||
end | ||
|
||
def initialize_codec | ||
@parser = Yajl::Parser.new(symbolize_keys: true) | ||
@parser.on_parse_complete = method(:handle_message) | ||
@encoder = Yajl::Encoder.new | ||
end | ||
|
||
def json_async_send(jsonable) | ||
json_data = @encoder.encode(jsonable) | ||
transport.send(json_data) | ||
end | ||
|
||
def json_send(jsonable) | ||
json_async_send(jsonable) | ||
th = Thread.new do | ||
result = nil | ||
continue = true | ||
while continue | ||
next if @queue.empty? | ||
@mut.synchronize { result = @queue.deq } | ||
continue = false | ||
end | ||
result | ||
end | ||
th.join.value | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
require 'e2mmap' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing frozen string literal comment. |
||
|
||
module Phut | ||
module OVSDB | ||
# OVSDB methods | ||
module Method | ||
extend Exception2MessageMapper | ||
|
||
def_exception :GetSchemaError, '%s' | ||
def_exception :TransactionError, '%s' | ||
|
||
def echo_reply | ||
json_async_send(id: 'echo', result: [], error: nil) | ||
end | ||
|
||
def transact(id, db_name, operations) | ||
data = json_send( | ||
id: id, | ||
method: 'transact', | ||
params: [db_name, *operations] | ||
) | ||
data[:result] | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
module Phut | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing frozen string literal comment. |
||
module OVSDB | ||
# Transaction | ||
module Transaction | ||
def select(table, conds, cols = nil) | ||
select = { | ||
op: :select, | ||
table: table, | ||
where: Array(conds) | ||
} | ||
select = { columns: Array(cols) }.merge(select) if cols | ||
select | ||
end | ||
|
||
def insert(table, row, uuid_name = nil) | ||
insert = { | ||
op: :insert, | ||
table: table, | ||
row: row | ||
} | ||
insert = { 'uuid-name' => uuid_name }.merge(insert) if uuid_name | ||
insert | ||
end | ||
|
||
def update(table, conds, row) | ||
{ | ||
op: :update, | ||
table: table, | ||
where: Array(conds), | ||
row: row | ||
} | ||
end | ||
|
||
def delete(table, conds) | ||
{ | ||
op: :delete, | ||
table: table, | ||
where: Array(conds) | ||
} | ||
end | ||
|
||
def mutate(table, conds, mutes) | ||
{ | ||
op: :mutate, | ||
table: table, | ||
where: Array(conds), | ||
mutations: Array(mutes) | ||
} | ||
end | ||
|
||
def commit(mode = true) | ||
{ | ||
op: :commit, | ||
durable: mode | ||
} | ||
end | ||
|
||
def abort | ||
{ | ||
op: :abort | ||
} | ||
end | ||
|
||
def wait(table, cond, cols, until_cond, rows, timeout = nil) | ||
wait = { | ||
op: :wait, | ||
table: table, | ||
where: Array(cond), | ||
columns: Array(cols), | ||
until: until_cond, | ||
rows: Array(rows) | ||
} | ||
wait = { timeout: timeout }.merge(wait) if timeout | ||
wait | ||
end | ||
|
||
def comment(string) | ||
{ | ||
op: :comment, | ||
comment: string | ||
} | ||
end | ||
|
||
def assert(lock_id) | ||
{ | ||
op: :assert, | ||
lock: lock_id | ||
} | ||
end | ||
end | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing frozen string literal comment.