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
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
|