omf_rc 6.0.0.pre.5 → 6.0.0.pre.6
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +0 -6
- data/bin/omf_rc +2 -2
- data/lib/omf_rc/resource_factory.rb +10 -4
- data/lib/omf_rc/resource_proxy/abstract_resource.rb +120 -79
- data/lib/omf_rc/resource_proxy/generic_application.rb +471 -0
- data/lib/omf_rc/resource_proxy/net.rb +7 -0
- data/lib/omf_rc/resource_proxy/node.rb +33 -7
- data/lib/omf_rc/resource_proxy/openflow_slice.rb +79 -0
- data/lib/omf_rc/resource_proxy/openflow_slice_factory.rb +71 -0
- data/lib/omf_rc/resource_proxy/wlan.rb +20 -0
- data/lib/omf_rc/resource_proxy_dsl.rb +142 -8
- data/lib/omf_rc/util/common_tools.rb +61 -0
- data/lib/omf_rc/util/hostapd.rb +52 -0
- data/lib/omf_rc/util/ip.rb +28 -0
- data/lib/omf_rc/util/iw.rb +119 -6
- data/lib/omf_rc/util/mock.rb +2 -1
- data/lib/omf_rc/util/openflow_tools.rb +103 -0
- data/lib/omf_rc/util/platform_tools.rb +164 -0
- data/lib/omf_rc/util/wpa.rb +42 -0
- data/lib/omf_rc/version.rb +1 -1
- data/omf_rc.gemspec +3 -1
- data/test/fixture/ip/addr_show +5 -0
- data/test/fixture/iw/info +4 -0
- data/test/fixture/sys/class/ieee80211/phy0/device/uevent +6 -0
- data/test/fixture/sys/class/ieee80211/phy0/uevent +0 -0
- data/test/fixture/sys/class/net/eth0/device/uevent +6 -0
- data/test/fixture/sys/class/net/eth0/uevent +2 -0
- data/test/fixture/sys/class/net/wlan0/device/uevent +6 -0
- data/test/fixture/sys/class/net/wlan0/uevent +3 -0
- data/test/omf_rc/message_process_error_spec.rb +11 -0
- data/test/omf_rc/resource_factory_spec.rb +8 -1
- data/test/omf_rc/resource_proxy/abstract_resource_spec.rb +57 -1
- data/test/omf_rc/resource_proxy/generic_application_spec.rb +347 -0
- data/test/omf_rc/resource_proxy/mock_spec.rb +15 -0
- data/test/omf_rc/resource_proxy/node_spec.rb +32 -1
- data/test/omf_rc/resource_proxy_dsl_spec.rb +81 -10
- data/test/omf_rc/util/common_tools_spec.rb +30 -0
- data/test/omf_rc/util/ip_spec.rb +51 -0
- data/test/omf_rc/util/iw_spec.rb +136 -25
- data/test/omf_rc/util/mock_spec.rb +26 -0
- data/test/omf_rc/util/mod_spec.rb +8 -11
- data/test/test_helper.rb +11 -0
- metadata +62 -6
- data/lib/omf_rc/resource_proxy/wifi.rb +0 -8
- data/test/mock_helper.rb +0 -15
@@ -0,0 +1,20 @@
|
|
1
|
+
module OmfRc::ResourceProxy::Wlan
|
2
|
+
include OmfRc::ResourceProxyDSL
|
3
|
+
|
4
|
+
register_proxy :wlan
|
5
|
+
|
6
|
+
utility :ip
|
7
|
+
utility :mod
|
8
|
+
utility :iw
|
9
|
+
|
10
|
+
hook :before_release do |device|
|
11
|
+
case device.property.mode.to_sym
|
12
|
+
when :master
|
13
|
+
device.stop_hostapd
|
14
|
+
when :managed
|
15
|
+
device.stop_wpa
|
16
|
+
end
|
17
|
+
#TODO need to remove all virtual interfaces of that phy device
|
18
|
+
#device.remove_all_interfaces
|
19
|
+
end
|
20
|
+
end
|
@@ -14,6 +14,9 @@ module OmfRc::ResourceProxyDSL
|
|
14
14
|
# Register a named proxy entry with factory class, normally this should be done in the proxy module
|
15
15
|
#
|
16
16
|
# @param [Symbol] name of the resource proxy
|
17
|
+
# @param [Hash] opts options to be passed to proxy registration
|
18
|
+
# @option opts [String, Array] :create_by resource can only be created by these resources.
|
19
|
+
#
|
17
20
|
# @example suppose we define a module for wifi
|
18
21
|
#
|
19
22
|
# module OmfRc::ResourceProxy::Wifi
|
@@ -21,19 +24,26 @@ module OmfRc::ResourceProxyDSL
|
|
21
24
|
#
|
22
25
|
# # Let the factory know it is available
|
23
26
|
# register_proxy :wifi
|
27
|
+
#
|
28
|
+
# # or use option :create_by
|
29
|
+
# register_proxy :wifi, :create_by => :node
|
24
30
|
# end
|
25
31
|
#
|
26
|
-
def register_proxy(name)
|
32
|
+
def register_proxy(name, opts = {})
|
27
33
|
name = name.to_sym
|
28
|
-
|
34
|
+
if opts[:create_by] && !opts[:create_by].kind_of?(Array)
|
35
|
+
opts[:create_by] = [opts[:create_by]]
|
36
|
+
end
|
37
|
+
OmfRc::ResourceFactory.register_proxy(name => opts)
|
29
38
|
end
|
30
39
|
|
31
40
|
# Register some hooks which can be called at certain stage of the operation
|
32
41
|
#
|
33
|
-
# Currently the system supports
|
42
|
+
# Currently the system supports these hooks:
|
34
43
|
#
|
35
44
|
# * before_ready, called when a resource created, before creating an associated pubsub topic
|
36
45
|
# * before_release, called before a resource released
|
46
|
+
# * before_create, called before parent creates the child resource. (in the context of parent resource)
|
37
47
|
#
|
38
48
|
# @param [Symbol] name hook name. :before_create or :before_release
|
39
49
|
# @yieldparam [AbstractResource] resource pass the current resource object to the block
|
@@ -44,6 +54,26 @@ module OmfRc::ResourceProxyDSL
|
|
44
54
|
#
|
45
55
|
# register_proxy :node
|
46
56
|
#
|
57
|
+
# # before_create hook
|
58
|
+
# #
|
59
|
+
# # the optional block will have access to three variables:
|
60
|
+
# # * resource: the parent resource itself
|
61
|
+
# # * new_resource_type: a string or symbol represents the new resource to be created
|
62
|
+
# # * new_resource_options: the options hash to be passed to the new resource
|
63
|
+
# #
|
64
|
+
# # this hook enable us to do things like:
|
65
|
+
# # * validating child resources: e.g. if parent could create this new resource
|
66
|
+
# # * setting up default child properties based on parent's property value
|
67
|
+
# hook :before_create do |resource, new_resource_type, new_resource_options|
|
68
|
+
# if new_resource_type.to_sym == :wifi
|
69
|
+
# logger.info "Resource type wifi is allowed"
|
70
|
+
# else
|
71
|
+
# raise "Go away, I can't create #{new_resource_type}"
|
72
|
+
# end
|
73
|
+
# new_resource_options.property ||= Hashie::Mash.new
|
74
|
+
# new_resource_options.property.node_info = "Node #{resource.uid}"
|
75
|
+
# end
|
76
|
+
#
|
47
77
|
# hook :before_ready do |resource|
|
48
78
|
# logger.info "#{resource.uid} is now ready"
|
49
79
|
# end
|
@@ -53,8 +83,8 @@ module OmfRc::ResourceProxyDSL
|
|
53
83
|
# end
|
54
84
|
# end
|
55
85
|
def hook(name, ®ister_block)
|
56
|
-
define_method(name) do
|
57
|
-
register_block.call(self) if register_block
|
86
|
+
define_method(name) do |*args, &block|
|
87
|
+
register_block.call(self, *args, block) if register_block
|
58
88
|
end
|
59
89
|
end
|
60
90
|
|
@@ -76,11 +106,13 @@ module OmfRc::ResourceProxyDSL
|
|
76
106
|
begin
|
77
107
|
# In case of module defined inline
|
78
108
|
include "OmfRc::Util::#{name.camelize}".constantize
|
109
|
+
extend "OmfRc::Util::#{name.camelize}".constantize
|
79
110
|
rescue NameError
|
80
111
|
begin
|
81
112
|
# Then we try to require the file and include the module
|
82
113
|
require "#{UTIL_DIR}/#{name}"
|
83
114
|
include "OmfRc::Util::#{name.camelize}".constantize
|
115
|
+
extend "OmfRc::Util::#{name.camelize}".constantize
|
84
116
|
rescue LoadError => le
|
85
117
|
logger.error le.message
|
86
118
|
rescue NameError => ne
|
@@ -122,7 +154,8 @@ module OmfRc::ResourceProxyDSL
|
|
122
154
|
#
|
123
155
|
def configure(name, ®ister_block)
|
124
156
|
define_method("configure_#{name.to_s}") do |*args, &block|
|
125
|
-
|
157
|
+
args[0] = Hashie::Mash.new(args[0]) if args[0].class == Hash
|
158
|
+
register_block.call(self, *args, block) if register_block
|
126
159
|
end
|
127
160
|
end
|
128
161
|
|
@@ -146,9 +179,110 @@ module OmfRc::ResourceProxyDSL
|
|
146
179
|
# end
|
147
180
|
# end
|
148
181
|
def request(name, ®ister_block)
|
149
|
-
define_method("request_#{name.to_s}") do |*args|
|
150
|
-
|
182
|
+
define_method("request_#{name.to_s}") do |*args, &block|
|
183
|
+
args[0] = Hashie::Mash.new(args[0]) if args[0].class == Hash
|
184
|
+
register_block.call(self, *args, block) if register_block
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
# Define an arbitrary method to do some work, can be included in configure & request block
|
189
|
+
#
|
190
|
+
# @param (see #configure)
|
191
|
+
# @yieldparam [AbstractResource] resource pass the current resource object to the block
|
192
|
+
# @example suppose we define a simple os checking method
|
193
|
+
#
|
194
|
+
# work :os do
|
195
|
+
# Command.execute("uname")
|
196
|
+
# end
|
197
|
+
#
|
198
|
+
# # then this os method will be available in all proxy definitions which includes this work method definition.
|
199
|
+
# # if for some reason you need to call 'os' method within the same module, you need to access it via the resource instance.
|
200
|
+
#
|
201
|
+
# work :install_software do |resource|
|
202
|
+
# raise 'Can not support non-linux distro yet' if resource.os == 'Linux'
|
203
|
+
# end
|
204
|
+
def work(name, ®ister_block)
|
205
|
+
define_method(name) do |*args, &block|
|
206
|
+
register_block.call(self, *args, block) if register_block
|
151
207
|
end
|
152
208
|
end
|
209
|
+
|
210
|
+
# Extend existing hook definition by alias existing method name as "orig_[method_name]"
|
211
|
+
#
|
212
|
+
# @param [#to_s] hook_name name of existing hook
|
213
|
+
# @example extend a hook definition
|
214
|
+
#
|
215
|
+
# # suppose existing hook defined as this:
|
216
|
+
# hook :before_ready do |resource|
|
217
|
+
# logger.info "I am ready"
|
218
|
+
# end
|
219
|
+
#
|
220
|
+
# # now in a new proxy where we want to extend this hook, add more functionality:
|
221
|
+
#
|
222
|
+
# extend_hook :before_ready
|
223
|
+
#
|
224
|
+
# hook :before_ready do |resource|
|
225
|
+
# resource.orig_before_ready
|
226
|
+
#
|
227
|
+
# logger.info "Now I am really ready"
|
228
|
+
# end
|
229
|
+
#
|
230
|
+
# # if we simply want to overwrite the existing hook, just define the same hook without using extend_hook
|
231
|
+
#
|
232
|
+
# hook :before_ready do |resource|
|
233
|
+
# logger.info "Not sure if I am ready or not"
|
234
|
+
# end
|
235
|
+
#
|
236
|
+
def extend_hook(hook_name)
|
237
|
+
hook_name = hook_name.to_s
|
238
|
+
alias_method "orig_#{hook_name}", hook_name
|
239
|
+
end
|
240
|
+
|
241
|
+
# Extend existing work definition by alias existing method name as "orig_[method_name]"
|
242
|
+
#
|
243
|
+
# @see #extend_hook
|
244
|
+
#
|
245
|
+
def extend_work(work_name)
|
246
|
+
work_name = work_name.to_s
|
247
|
+
alias_method "orig_#{work_name}", work_name
|
248
|
+
end
|
249
|
+
|
250
|
+
# Extend existing configure definition
|
251
|
+
#
|
252
|
+
# @param [#to_s] configure_name name of existing configurable property
|
253
|
+
#
|
254
|
+
# Slightly different to extend_hook, the actual method_name defined by a configure property is "configure_[configurable_property_name]"
|
255
|
+
#
|
256
|
+
# @example to extend a configurable property
|
257
|
+
#
|
258
|
+
# configure :bob do |resource, value|
|
259
|
+
# resource.property.bob = value
|
260
|
+
# end
|
261
|
+
#
|
262
|
+
# # To extend this, simply do
|
263
|
+
#
|
264
|
+
# extend_configure :bob
|
265
|
+
#
|
266
|
+
# configure :bob do |resource, value|
|
267
|
+
# resource.orig_configure_bob(value)
|
268
|
+
# resource.property.bob = "New value: #{value}"
|
269
|
+
# end
|
270
|
+
#
|
271
|
+
# @see #extend_hook
|
272
|
+
#
|
273
|
+
def extend_configure(configure_name)
|
274
|
+
configure_name = configure_name.to_s
|
275
|
+
alias_method "orig_configure_#{configure_name}", "configure_#{configure_name}"
|
276
|
+
end
|
277
|
+
|
278
|
+
# Extend existing request definition
|
279
|
+
#
|
280
|
+
# @see #extend_hook
|
281
|
+
# @see #extend_configure
|
282
|
+
def extend_request(request_name)
|
283
|
+
request_name = request_name.to_s
|
284
|
+
alias_method "orig_request_#{request_name}", "request_#{request_name}"
|
285
|
+
end
|
286
|
+
|
153
287
|
end
|
154
288
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2012 National ICT Australia (NICTA), Australia
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#
|
22
|
+
|
23
|
+
#
|
24
|
+
# This module defines a Utility with some common work blocks that could be
|
25
|
+
# useful to any type of Resource Proxy (RP)
|
26
|
+
#
|
27
|
+
module OmfRc::Util::CommonTools
|
28
|
+
include OmfRc::ResourceProxyDSL
|
29
|
+
|
30
|
+
# This utility block logs an error/warn String S on the resource proxy side
|
31
|
+
# and publish an INFORM message on the resources pubsub topic. This INFORM
|
32
|
+
# message will have the type ERROR/WARN, and its 'reason' element set to the
|
33
|
+
# String S
|
34
|
+
#
|
35
|
+
# @yieldparam [String] msg the error or warning message
|
36
|
+
#
|
37
|
+
%w(error warn).each do |type|
|
38
|
+
work("log_inform_#{type}") do |res, msg|
|
39
|
+
logger.send(type, msg)
|
40
|
+
res.comm.publish(
|
41
|
+
res.uid,
|
42
|
+
OmfCommon::Message.inform(type.upcase) do |message|
|
43
|
+
message.element('reason' , msg)
|
44
|
+
end
|
45
|
+
)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# This utility block returns true if its given value parameter is a Boolean,
|
50
|
+
# which in Ruby means that it is either of the class TrueClass or FalseClass
|
51
|
+
#
|
52
|
+
# @yieldparam [Object] obj the Object to test as Boolean
|
53
|
+
#
|
54
|
+
# [Boolean] true or fals
|
55
|
+
#
|
56
|
+
work('boolean?') do |res,obj|
|
57
|
+
result = false
|
58
|
+
result = true if obj.kind_of?(TrueClass) || obj.kind_of?(FalseClass)
|
59
|
+
result
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'hashie'
|
2
|
+
require 'cocaine'
|
3
|
+
|
4
|
+
module OmfRc::Util::Hostapd
|
5
|
+
include OmfRc::ResourceProxyDSL
|
6
|
+
include Cocaine
|
7
|
+
|
8
|
+
# Initialise access point conf and pid location
|
9
|
+
#
|
10
|
+
work :init_ap_conf_pid do |device|
|
11
|
+
device.property.ap_conf = "/tmp/hostapd.#{device.hrn}.conf"
|
12
|
+
device.property.ap_pid = "/tmp/hostapd.#{device.hrn}.pid"
|
13
|
+
end
|
14
|
+
# Set up and run a hostapd instance
|
15
|
+
#
|
16
|
+
work :hostapd do |device|
|
17
|
+
device.init_ap_conf_pid
|
18
|
+
|
19
|
+
File.open(device.property.ap_conf, "w") do |f|
|
20
|
+
f << "driver=nl80211\ninterface=#{device.hrn}\nssid=#{device.property.essid}\nchannel=#{device.property.channel}\n"
|
21
|
+
f << "hw_mode=#{device.property.hw_mode}\n" if %w(a b g).include? device.property.hw_mode
|
22
|
+
if device.property.hw_mode == 'n'
|
23
|
+
if device.property.channel.to_i < 15
|
24
|
+
f << "hw_mode=g\n"
|
25
|
+
else device.property.channel.to_i > 15
|
26
|
+
f << "hw_mode=a\n"
|
27
|
+
end
|
28
|
+
f << "wmm_enabled=1\nieee80211n=1\nht_capab=[HT20-]\n"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
CommandLine.new("hostapd", "-B -P :ap_pid :ap_conf",
|
33
|
+
:ap_pid => device.property.ap_pid,
|
34
|
+
:ap_conf => device.property.ap_conf).run
|
35
|
+
end
|
36
|
+
|
37
|
+
work :stop_hostapd do |device|
|
38
|
+
begin
|
39
|
+
File.open(device.property.ap_pid,'r') do |f|
|
40
|
+
logger.debug "Stopping hostapd process at PID: #{device.property.ap_pid}"
|
41
|
+
CommandLine.new("kill", "-9 :pid", :pid => f.read.chomp).run
|
42
|
+
end
|
43
|
+
|
44
|
+
CommandLine.new("rm", "-f :ap_pid :ap_conf",
|
45
|
+
:ap_pid => device.property.ap_pid,
|
46
|
+
:ap_conf => device.property.ap_conf).run
|
47
|
+
rescue => e
|
48
|
+
logger.warn "Failed to clean hostapd and its related files '#{device.property.ap_pid}' and '#{device.property.ap_conf}'!"
|
49
|
+
logger.warn e.message
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'cocaine'
|
2
|
+
|
3
|
+
module OmfRc::Util::Ip
|
4
|
+
include OmfRc::ResourceProxyDSL
|
5
|
+
include Cocaine
|
6
|
+
|
7
|
+
request :ip_addr do |resource|
|
8
|
+
addr = CommandLine.new("ip", "addr show dev :device", :device => resource.hrn).run
|
9
|
+
addr && addr.chomp.match(/inet ([[0-9]\:\/\.]+)/) && $1
|
10
|
+
end
|
11
|
+
|
12
|
+
request :mac_addr do |resource|
|
13
|
+
addr = CommandLine.new("ip", "addr show dev :device", :device => resource.hrn).run
|
14
|
+
addr && addr.chomp.match(/link\/ether ([\d[a-f][A-F]\:]+)/) && $1
|
15
|
+
end
|
16
|
+
|
17
|
+
configure :ip_addr do |resource, value|
|
18
|
+
CommandLine.new("ip", "addr add :ip_address dev :device",
|
19
|
+
:ip_address => value,
|
20
|
+
:device => resource.hrn
|
21
|
+
).run
|
22
|
+
resource.request_ip_addr
|
23
|
+
end
|
24
|
+
|
25
|
+
work :interface_up do |resource|
|
26
|
+
CommandLine.new("ip", "link set :dev up", :dev => resource.hrn).run
|
27
|
+
end
|
28
|
+
end
|
data/lib/omf_rc/util/iw.rb
CHANGED
@@ -1,18 +1,34 @@
|
|
1
1
|
require 'hashie'
|
2
|
+
require 'cocaine'
|
2
3
|
|
3
4
|
module OmfRc::Util::Iw
|
4
5
|
include OmfRc::ResourceProxyDSL
|
6
|
+
include Cocaine
|
7
|
+
include Hashie
|
5
8
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
+
utility :ip
|
10
|
+
utility :wpa
|
11
|
+
utility :hostapd
|
12
|
+
|
13
|
+
# Parse iw help page and set up all configure methods available for iw command
|
14
|
+
#
|
15
|
+
CommandLine.new("iw", "help").run.chomp.gsub(/^\t/, '').split("\n").map {|v| v.match(/[phy|dev] <.+> set (\w+) .*/) && $1 }.compact.uniq.each do |p|
|
16
|
+
configure p do |device, value|
|
17
|
+
CommandLine.new("iw", "dev :dev set :property :value",
|
18
|
+
:dev => device.hrn,
|
19
|
+
:property => p,
|
20
|
+
:value => value).run
|
9
21
|
end
|
10
22
|
end
|
11
23
|
|
12
|
-
|
13
|
-
|
24
|
+
# Parse iw link command output and return as a mash
|
25
|
+
#
|
26
|
+
request :link do |device|
|
27
|
+
known_properties = Mash.new
|
28
|
+
|
29
|
+
command = CommandLine.new("iw", "dev :dev link", :dev => device.hrn)
|
14
30
|
|
15
|
-
|
31
|
+
command.run.chomp.gsub(/^\t/, '').split("\n").drop(1).each do |v|
|
16
32
|
v.match(/^(.+):\W*(.+)$/).tap do |m|
|
17
33
|
m && known_properties[m[1].downcase.gsub(/\W+/, '_')] = m[2].gsub(/^\W+/, '')
|
18
34
|
end
|
@@ -20,4 +36,101 @@ module OmfRc::Util::Iw
|
|
20
36
|
|
21
37
|
known_properties
|
22
38
|
end
|
39
|
+
|
40
|
+
# Parse iw info command output and return as a mash
|
41
|
+
#
|
42
|
+
request :info do |device|
|
43
|
+
known_properties = Mash.new
|
44
|
+
|
45
|
+
command = CommandLine.new("iw", "dev :dev info", :dev => device.hrn)
|
46
|
+
|
47
|
+
command.run.chomp.split("\n").drop(1).each do |v|
|
48
|
+
v.match(/^\W*(.+) (.+)$/).tap do |m|
|
49
|
+
m && known_properties[m[1].downcase.gsub(/\W+/, '_')] = m[2].gsub(/^\W+/, '')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
known_properties
|
54
|
+
end
|
55
|
+
|
56
|
+
# Delete current interface, clean up
|
57
|
+
#
|
58
|
+
work :delele_interface do |device|
|
59
|
+
CommandLine.new("iw", "dev :dev del", :dev => device.hrn).run
|
60
|
+
end
|
61
|
+
|
62
|
+
# Add interface to device
|
63
|
+
#
|
64
|
+
work :add_interface do |device, type|
|
65
|
+
CommandLine.new("iw", "phy :phy interface add :dev type :type",
|
66
|
+
:phy => device.property.phy,
|
67
|
+
:dev => device.hrn,
|
68
|
+
:type => type.to_s).run
|
69
|
+
end
|
70
|
+
|
71
|
+
# Set up or join a ibss network
|
72
|
+
#
|
73
|
+
work :join_ibss do |device|
|
74
|
+
CommandLine.new("iw", "dev :device ibss join :essid :frequency",
|
75
|
+
:device => device.hrn.to_s,
|
76
|
+
:essid => device.property.essid.to_s,
|
77
|
+
:frequency => device.property.frequency.to_s).run
|
78
|
+
end
|
79
|
+
|
80
|
+
# Validate internal properties based on interface mode
|
81
|
+
#
|
82
|
+
work :validate_iw_properties do |device|
|
83
|
+
raise ArgumentError, "Missing phyical device name" if device.property.phy.nil?
|
84
|
+
|
85
|
+
unless %w(master managed adhoc monitor).include? device.property.mode
|
86
|
+
raise ArgumentError, "Mode must be master, managed, adhoc, or monitor, got #{device.property.mode}"
|
87
|
+
end
|
88
|
+
|
89
|
+
case device.property.mode.to_sym
|
90
|
+
when :master
|
91
|
+
unless %w(a b g n).include? device.property.hw_mode
|
92
|
+
raise ArgumentError, "Hardware mode must be a, b, g, or n, got #{device.property.hw_mode}"
|
93
|
+
end
|
94
|
+
%w(channel essid).each do |p|
|
95
|
+
raise ArgumentError, "#{p} must not be nil" if device.property.send(p).nil?
|
96
|
+
end
|
97
|
+
when :managed
|
98
|
+
%w(essid).each do |p|
|
99
|
+
raise ArgumentError, "#{p} must not be nil" if device.property.send(p).nil?
|
100
|
+
end
|
101
|
+
when :adhoc
|
102
|
+
%w(essid frequency).each do |p|
|
103
|
+
raise ArgumentError, "#{p} must not be nil" if device.property.send(p).nil?
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Configure the interface with mode managed, master, adhoc or monitor
|
109
|
+
#
|
110
|
+
configure :mode do |device, value|
|
111
|
+
# capture value hash and store internally
|
112
|
+
device.property.update(value)
|
113
|
+
|
114
|
+
device.validate_iw_properties
|
115
|
+
|
116
|
+
device.delele_interface rescue logger.warn "Interface #{device.hrn} not found"
|
117
|
+
|
118
|
+
# TODO should just remove all interfaces from physical device, at least make it optional
|
119
|
+
|
120
|
+
case device.property.mode.to_sym
|
121
|
+
when :master
|
122
|
+
device.add_interface(:managed)
|
123
|
+
device.hostapd
|
124
|
+
when :managed
|
125
|
+
device.add_interface(:managed)
|
126
|
+
device.wpasup
|
127
|
+
when :adhoc
|
128
|
+
device.add_interface(:adhoc)
|
129
|
+
device.interface_up
|
130
|
+
device.join_ibss
|
131
|
+
when :monitor
|
132
|
+
device.add_interface(:monitor)
|
133
|
+
device.interface_up
|
134
|
+
end
|
135
|
+
end
|
23
136
|
end
|
data/lib/omf_rc/util/mock.rb
CHANGED
@@ -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
|