omf_rc 6.0.0.pre.5 → 6.0.0.pre.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
data/Rakefile
CHANGED
data/bin/omf_rc
CHANGED
@@ -6,7 +6,7 @@ require 'omf_rc/resource_factory'
|
|
6
6
|
$stdout.sync = true
|
7
7
|
|
8
8
|
options = {
|
9
|
-
uid:
|
9
|
+
uid: `hostname`.chomp
|
10
10
|
}
|
11
11
|
|
12
12
|
executable_name = File.basename($PROGRAM_NAME)
|
@@ -26,7 +26,7 @@ option_parser = OptionParser.new do |opts|
|
|
26
26
|
options[:server] = server
|
27
27
|
end
|
28
28
|
|
29
|
-
opts.on("-t TOPIC", "PubSub topic to create, also becomes the uid of the resource") do |topic|
|
29
|
+
opts.on("-t TOPIC", "PubSub topic to create, also becomes the uid of the resource, default to hostname") do |topic|
|
30
30
|
options[:uid] = topic
|
31
31
|
end
|
32
32
|
|
@@ -7,7 +7,7 @@ require 'omf_rc/resource_proxy/abstract_resource'
|
|
7
7
|
#
|
8
8
|
class OmfRc::ResourceFactory
|
9
9
|
# List of registered resource proxies
|
10
|
-
@@proxy_list =
|
10
|
+
@@proxy_list = Hashie::Mash.new
|
11
11
|
|
12
12
|
# By default, we use xmpp dsl, which based on blather
|
13
13
|
DEFAULT_OPTS = {
|
@@ -21,7 +21,9 @@ class OmfRc::ResourceFactory
|
|
21
21
|
#
|
22
22
|
# @see OmfRc::ResourceProxy::AbstractResource
|
23
23
|
def new(type, opts = nil, comm = nil, &block)
|
24
|
-
|
24
|
+
unless @@proxy_list.include?(type)
|
25
|
+
raise ArgumentError, "Resource type not found: #{type.to_s}" unless @@proxy_list.include?(type)
|
26
|
+
end
|
25
27
|
type = type.to_s
|
26
28
|
opts = opts ? DEFAULT_OPTS.merge(opts) : DEFAULT_OPTS
|
27
29
|
# Create a new instance of abstract resource
|
@@ -39,8 +41,12 @@ class OmfRc::ResourceFactory
|
|
39
41
|
end
|
40
42
|
|
41
43
|
# Add a proxy to the list
|
42
|
-
def register_proxy(
|
43
|
-
|
44
|
+
def register_proxy(proxy_opts)
|
45
|
+
if @@proxy_list.has_key? proxy_opts[:name]
|
46
|
+
raise StandardError, "Resource has been registered already"
|
47
|
+
else
|
48
|
+
@@proxy_list.update(proxy_opts)
|
49
|
+
end
|
44
50
|
end
|
45
51
|
|
46
52
|
# Require files from default resource proxy library folder
|
@@ -12,7 +12,7 @@ class OmfRc::ResourceProxy::AbstractResource
|
|
12
12
|
# @!attribute property
|
13
13
|
# @return [String] the resource's internal meta data storage
|
14
14
|
attr_accessor :uid, :hrn, :type, :comm, :property
|
15
|
-
attr_reader :opts, :children
|
15
|
+
attr_reader :opts, :children
|
16
16
|
|
17
17
|
# Initialisation
|
18
18
|
#
|
@@ -32,20 +32,19 @@ class OmfRc::ResourceProxy::AbstractResource
|
|
32
32
|
@uid = @opts.uid || SecureRandom.uuid
|
33
33
|
@hrn = @opts.hrn
|
34
34
|
@children ||= []
|
35
|
-
|
35
|
+
|
36
36
|
@property = @opts.property || Hashie::Mash.new
|
37
37
|
|
38
38
|
@comm = comm || OmfCommon::Comm.new(@opts.dsl)
|
39
39
|
# Fire when connection to pubsub server established
|
40
40
|
@comm.when_ready do
|
41
41
|
logger.info "CONNECTED: #{@comm.jid.inspect}"
|
42
|
-
@host = @comm.jid.domain
|
43
42
|
|
44
43
|
# Once connection established, create a pubsub topic, then subscribe to it
|
45
|
-
@comm.create_topic(uid
|
44
|
+
@comm.create_topic(uid) do |s|
|
46
45
|
# Creating topic failed, no point to continue; clean up and disconnect
|
47
46
|
# Otherwise go subscribe to this pubsub topic
|
48
|
-
s.error? ? disconnect : @comm.subscribe(uid
|
47
|
+
s.error? ? disconnect : @comm.subscribe(uid)
|
49
48
|
end
|
50
49
|
end
|
51
50
|
|
@@ -62,6 +61,17 @@ class OmfRc::ResourceProxy::AbstractResource
|
|
62
61
|
end
|
63
62
|
end
|
64
63
|
|
64
|
+
# If method missing, try the property mash
|
65
|
+
def method_missing(method_name, *args)
|
66
|
+
if (method_name =~ /request_(.+)/)
|
67
|
+
property.send($1) || super
|
68
|
+
elsif (method_name =~ /configure_(.+)/)
|
69
|
+
property.send($1) ? property.send("[]=", $1, *args) : super
|
70
|
+
else
|
71
|
+
super
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
65
75
|
# Connect to pubsub server
|
66
76
|
def connect
|
67
77
|
@comm.connect(opts.user, opts.password, opts.server)
|
@@ -69,11 +79,11 @@ class OmfRc::ResourceProxy::AbstractResource
|
|
69
79
|
|
70
80
|
# Try to clean up pubsub topics, and wait for DISCONNECT_WAIT seconds, then shutdown event machine loop
|
71
81
|
def disconnect
|
72
|
-
@comm.affiliations
|
82
|
+
@comm.affiliations do |a|
|
73
83
|
my_pubsub_topics = a[:owner] ? a[:owner].size : 0
|
74
84
|
if my_pubsub_topics > 0
|
75
85
|
logger.info "Cleaning #{my_pubsub_topics} pubsub topic(s)"
|
76
|
-
a[:owner].each { |topic| @comm.delete_topic(topic
|
86
|
+
a[:owner].each { |topic| @comm.delete_topic(topic) }
|
77
87
|
else
|
78
88
|
logger.info "Disconnecting now"
|
79
89
|
@comm.disconnect
|
@@ -89,27 +99,36 @@ class OmfRc::ResourceProxy::AbstractResource
|
|
89
99
|
#
|
90
100
|
# @param (see #initialize)
|
91
101
|
def create(type, opts = nil)
|
92
|
-
|
102
|
+
proxy_info = OmfRc::ResourceFactory.proxy_list[type]
|
103
|
+
if proxy_info && proxy_info.create_by && !proxy_info.create_by.include?(self.type.to_sym)
|
104
|
+
raise StandardError, "Resource #{type} is not designed to be created by #{self.type}"
|
105
|
+
end
|
106
|
+
|
107
|
+
before_create(type, opts) if respond_to? :before_create
|
93
108
|
new_resource = OmfRc::ResourceFactory.new(type.to_sym, opts, @comm)
|
109
|
+
after_create(new_resource) if respond_to? :after_create
|
94
110
|
children << new_resource
|
95
111
|
new_resource
|
96
112
|
end
|
97
113
|
|
98
114
|
# Release a resource
|
99
115
|
#
|
100
|
-
def release
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
116
|
+
def release(resource_id)
|
117
|
+
obj = children.find { |v| v.uid == resource_id }
|
118
|
+
raise StandardError, "Resource #{resource_id} could not be found" if obj.nil?
|
119
|
+
|
120
|
+
# Release children resource recursively
|
121
|
+
obj.children.each do |c|
|
122
|
+
obj.release(c.uid)
|
123
|
+
end
|
124
|
+
obj.before_release if obj.respond_to? :before_release
|
125
|
+
|
126
|
+
children.delete(obj)
|
108
127
|
end
|
109
128
|
|
110
129
|
# Return a list of all properties can be requested and configured
|
111
130
|
#
|
112
|
-
def request_available_properties
|
131
|
+
def request_available_properties(*args)
|
113
132
|
Hashie::Mash.new(request: [], configure: []).tap do |mash|
|
114
133
|
methods.each do |m|
|
115
134
|
mash[$1] << $2.to_sym if m =~ /(request|configure)_(.+)/ && $2 != "available_properties"
|
@@ -118,12 +137,12 @@ class OmfRc::ResourceProxy::AbstractResource
|
|
118
137
|
end
|
119
138
|
|
120
139
|
# Make uid accessible through pubsub interface
|
121
|
-
def request_uid
|
140
|
+
def request_uid(*args)
|
122
141
|
uid
|
123
142
|
end
|
124
143
|
|
125
144
|
# Make hrn accessible through pubsub interface
|
126
|
-
def request_hrn
|
145
|
+
def request_hrn(*args)
|
127
146
|
hrn
|
128
147
|
end
|
129
148
|
|
@@ -134,7 +153,7 @@ class OmfRc::ResourceProxy::AbstractResource
|
|
134
153
|
|
135
154
|
# Request child resources
|
136
155
|
# @return [Mash] child resource mash with uid and hrn
|
137
|
-
def request_child_resources
|
156
|
+
def request_child_resources(*args)
|
138
157
|
Hashie::Mash.new.tap do |mash|
|
139
158
|
children.each do |c|
|
140
159
|
mash[c.uid] ||= c.hrn
|
@@ -142,61 +161,78 @@ class OmfRc::ResourceProxy::AbstractResource
|
|
142
161
|
end
|
143
162
|
end
|
144
163
|
|
164
|
+
# Publish an inform message
|
165
|
+
# @param [Symbol] inform_type the type of inform message
|
166
|
+
# @param [Hash | Hashie::Mash | Exception | String] inform_data the type of inform message
|
167
|
+
def inform(inform_type, inform_data)
|
168
|
+
inform_data = Hashie::Mash.new(inform_data) if inform_data.class == Hash
|
169
|
+
|
170
|
+
case inform_type
|
171
|
+
when :failed
|
172
|
+
unless inform_data.kind_of? Exception
|
173
|
+
raise ArgumentError, "FAILED message requires an Exception (or MessageProcessError)"
|
174
|
+
end
|
175
|
+
when :created, :released
|
176
|
+
unless inform_data.respond_to?(:resource_id) && !inform_data.resource_id.nil?
|
177
|
+
raise ArgumentError, "CREATED or RELEASED message requires inform_data object respond to resource_id"
|
178
|
+
end
|
179
|
+
when :status
|
180
|
+
unless inform_data.respond_to?(:status) && inform_data.status.kind_of?(Hash)
|
181
|
+
raise ArgumentError, "STATUS message requires a hash represents properties"
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
context_id = inform_data.context_id if inform_data.respond_to? :context_id
|
186
|
+
inform_to = inform_data.inform_to if inform_data.respond_to? :inform_to
|
187
|
+
inform_to ||= self.uid
|
188
|
+
|
189
|
+
inform_message = OmfCommon::Message.inform(inform_type.to_s.upcase, context_id) do |i|
|
190
|
+
case inform_type
|
191
|
+
when :created
|
192
|
+
i.element('resource_id', inform_data.resource_id)
|
193
|
+
i.element('resource_address', inform_data.resource_id)
|
194
|
+
when :status
|
195
|
+
inform_data.status.each_pair { |k, v| i.property(k, v) }
|
196
|
+
when :released
|
197
|
+
i.element('resource_id', inform_data.resource_id)
|
198
|
+
when :error, :warn
|
199
|
+
i.element("reason", (inform_data.message rescue inform_data))
|
200
|
+
logger.__send__(inform_type, (inform_data.message rescue inform_data))
|
201
|
+
when :failed
|
202
|
+
i.element("reason", inform_data.message)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
@comm.publish(inform_to, inform_message)
|
206
|
+
end
|
207
|
+
|
208
|
+
private
|
209
|
+
|
145
210
|
# Parse omf message and execute as instructed by the message
|
146
211
|
#
|
147
212
|
def process_omf_message(pubsub_item_payload, topic)
|
148
213
|
dp = OmfRc::DeferredProcess.new
|
149
214
|
|
150
|
-
dp.callback do |
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
i.element('resource_id', new_uid)
|
159
|
-
i.element('resource_address', new_uid)
|
160
|
-
end
|
161
|
-
@comm.publish(end_result[:inform_to], inform_msg, host)
|
162
|
-
end
|
163
|
-
end
|
164
|
-
when :request
|
165
|
-
inform_msg = OmfCommon::Message.inform(end_result[:context_id], 'STATUS') do |i|
|
166
|
-
end_result[:result].each_pair do |k, v|
|
167
|
-
i.property(k, v)
|
168
|
-
end
|
169
|
-
end
|
170
|
-
@comm.publish(end_result[:inform_to], inform_msg, host)
|
171
|
-
|
172
|
-
when :configure
|
173
|
-
inform_msg = OmfCommon::Message.inform(end_result[:context_id], 'STATUS') do |i|
|
174
|
-
end_result[:result].each_pair do |k, v|
|
175
|
-
i.property(k, v)
|
176
|
-
end
|
177
|
-
end
|
178
|
-
@comm.publish(end_result[:inform_to], inform_msg, host)
|
179
|
-
when :release
|
180
|
-
inform_msg = OmfCommon::Message.inform(end_result[:context_id], 'RELEASED') do |i|
|
181
|
-
i.element('resource_id', end_result[:inform_to])
|
182
|
-
end
|
183
|
-
|
184
|
-
end_result[:result].each do |n|
|
185
|
-
@comm.delete_topic(n, host)
|
186
|
-
end
|
187
|
-
|
188
|
-
EM.add_timer(RELEASE_WAIT) do
|
189
|
-
@comm.publish(end_result[:inform_to], inform_msg, host)
|
215
|
+
dp.callback do |response|
|
216
|
+
response = Hashie::Mash.new(response)
|
217
|
+
case response.operation
|
218
|
+
when :create
|
219
|
+
new_uid = response.resource_id
|
220
|
+
@comm.create_topic(new_uid) do
|
221
|
+
@comm.subscribe(new_uid) do
|
222
|
+
inform(:created, response)
|
190
223
|
end
|
191
224
|
end
|
225
|
+
when :request, :configure
|
226
|
+
inform(:status, response)
|
227
|
+
when :release
|
228
|
+
EM.add_timer(RELEASE_WAIT) do
|
229
|
+
inform(:released, response)
|
230
|
+
end
|
192
231
|
end
|
193
232
|
end
|
194
233
|
|
195
234
|
dp.errback do |e|
|
196
|
-
|
197
|
-
i.element("error_message", e.message)
|
198
|
-
end
|
199
|
-
@comm.publish(e.inform_to, inform_msg, host)
|
235
|
+
inform(:failed, e)
|
200
236
|
end
|
201
237
|
|
202
238
|
dp.fire do
|
@@ -214,35 +250,33 @@ class OmfRc::ResourceProxy::AbstractResource
|
|
214
250
|
create_opts = opts.dup
|
215
251
|
create_opts.uid = nil
|
216
252
|
result = obj.create(message.read_property(:type), create_opts)
|
217
|
-
message.
|
253
|
+
message.each_property do |p|
|
218
254
|
unless p.attr('key') == 'type'
|
219
255
|
method_name = "configure_#{p.attr('key')}"
|
220
|
-
result.
|
256
|
+
result.__send__(method_name, message.read_property(p.attr('key')))
|
221
257
|
end
|
222
258
|
end
|
223
|
-
|
259
|
+
result.after_initial_configured if result.respond_to? :after_initial_configured
|
260
|
+
{ operation: :create, resource_id: result.uid, context_id: context_id, inform_to: uid }
|
224
261
|
when :request
|
225
262
|
result = Hashie::Mash.new.tap do |mash|
|
226
263
|
message.read_element("//property").each do |p|
|
227
264
|
method_name = "request_#{p.attr('key')}"
|
228
|
-
|
229
|
-
mash[p.attr('key')] ||= obj.send(method_name)
|
230
|
-
end
|
265
|
+
mash[p.attr('key')] ||= obj.__send__(method_name, message.read_property(p.attr('key')))
|
231
266
|
end
|
232
267
|
end
|
233
|
-
{ operation: :request,
|
268
|
+
{ operation: :request, status: result, context_id: context_id, inform_to: obj.uid }
|
234
269
|
when :configure
|
235
270
|
result = Hashie::Mash.new.tap do |mash|
|
236
271
|
message.read_element("//property").each do |p|
|
237
272
|
method_name = "configure_#{p.attr('key')}"
|
238
|
-
|
239
|
-
mash[p.attr('key')] ||= obj.send(method_name, p.content)
|
240
|
-
end
|
273
|
+
mash[p.attr('key')] ||= obj.__send__(method_name, message.read_property(p.attr('key')))
|
241
274
|
end
|
242
275
|
end
|
243
|
-
{ operation: :configure,
|
276
|
+
{ operation: :configure, status: result, context_id: context_id, inform_to: obj.uid }
|
244
277
|
when :release
|
245
|
-
|
278
|
+
resource_id = message.resource_id
|
279
|
+
{ operation: :release, resource_id: obj.release(resource_id).uid, context_id: context_id, inform_to: obj.uid }
|
246
280
|
when :inform
|
247
281
|
# We really don't care about inform messages which created from here
|
248
282
|
nil
|
@@ -250,9 +284,16 @@ class OmfRc::ResourceProxy::AbstractResource
|
|
250
284
|
raise "Unknown OMF operation #{message.operation}"
|
251
285
|
end
|
252
286
|
rescue => e
|
253
|
-
|
254
|
-
|
255
|
-
|
287
|
+
if (e.kind_of? NoMethodError) && (message.operation == :configure || message.operation == :request)
|
288
|
+
msg = "Cannot #{message.operation} unknown property "+
|
289
|
+
"'#{message.read_element("//property")}' for resource '#{type}'"
|
290
|
+
logger.warn msg
|
291
|
+
raise OmfRc::MessageProcessError.new(context_id, obj.uid, msg)
|
292
|
+
else
|
293
|
+
logger.error e.message
|
294
|
+
logger.error e.backtrace.join("\n")
|
295
|
+
raise OmfRc::MessageProcessError.new(context_id, obj.uid, e.message)
|
296
|
+
end
|
256
297
|
end
|
257
298
|
end
|
258
299
|
end
|