omf_rc 6.0.0.pre.8 → 6.0.0.pre.9
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/bin/install_omf_rc +79 -0
- data/bin/omf_rc +52 -36
- data/config/config.yml +8 -0
- data/init/debian +51 -0
- data/init/fedora +54 -0
- data/init/run_omf_rc.sh +62 -0
- data/init/ubuntu +12 -0
- data/lib/omf_rc/omf_error.rb +5 -5
- data/lib/omf_rc/resource_factory.rb +7 -11
- data/lib/omf_rc/resource_proxy/abstract_resource.rb +327 -228
- data/lib/omf_rc/resource_proxy/application.rb +61 -56
- data/lib/omf_rc/resource_proxy/net.rb +2 -2
- data/lib/omf_rc/resource_proxy/node.rb +11 -2
- data/lib/omf_rc/resource_proxy/virtual_machine.rb +1 -1
- data/lib/omf_rc/resource_proxy/wlan.rb +2 -0
- data/lib/omf_rc/resource_proxy_dsl.rb +22 -1
- data/lib/omf_rc/util/common_tools.rb +2 -4
- data/lib/omf_rc/util/hostapd.rb +4 -3
- data/lib/omf_rc/util/ip.rb +8 -5
- data/lib/omf_rc/util/iw.rb +18 -8
- data/lib/omf_rc/util/sysfs.rb +14 -0
- data/lib/omf_rc/util/vmbuilder.rb +1 -1
- data/lib/omf_rc/util/wpa.rb +4 -3
- data/lib/omf_rc/version.rb +1 -1
- data/lib/omf_rc.rb +3 -1
- data/omf_rc.gemspec +4 -2
- data/test/omf_rc/message_process_error_spec.rb +3 -3
- data/test/omf_rc/resource_factory_spec.rb +14 -7
- data/test/omf_rc/resource_proxy/abstract_resource_spec.rb +47 -21
- data/test/omf_rc/resource_proxy/application_spec.rb +156 -119
- data/test/omf_rc/resource_proxy/mock_spec.rb +6 -1
- data/test/omf_rc/resource_proxy/node_spec.rb +32 -12
- data/test/omf_rc/resource_proxy_dsl_spec.rb +31 -19
- data/test/omf_rc/util/common_tools_spec.rb +8 -11
- data/test/omf_rc/util/ip_spec.rb +7 -1
- data/test/omf_rc/util/iw_spec.rb +18 -13
- data/test/omf_rc/util/mock_spec.rb +6 -1
- data/test/omf_rc/util/mod_spec.rb +17 -10
- data/test/test_helper.rb +3 -0
- metadata +51 -48
- data/config/omf_rc.yml +0 -70
- data/lib/omf_rc/resource_proxy/openflow_slice.rb +0 -79
- data/lib/omf_rc/resource_proxy/openflow_slice_factory.rb +0 -71
@@ -1,7 +1,8 @@
|
|
1
|
-
require 'omf_rc/deferred_process'
|
1
|
+
#require 'omf_rc/deferred_process'
|
2
2
|
require 'omf_rc/omf_error'
|
3
3
|
require 'securerandom'
|
4
4
|
require 'hashie'
|
5
|
+
require 'monitor'
|
5
6
|
|
6
7
|
# OML Measurement Point (MP)
|
7
8
|
# This MP is for measurements about messages published by the Resource Proxy
|
@@ -10,7 +11,7 @@ class OmfRc::ResourceProxy::MPPublished < OML4R::MPBase
|
|
10
11
|
param :time, :type => :double # Time (s) when this message was published
|
11
12
|
param :uid, :type => :string # UID for this Resource Proxy
|
12
13
|
param :topic, :type => :string # Pubsub topic to publish this message to
|
13
|
-
param :
|
14
|
+
param :mid, :type => :string # Unique ID this message
|
14
15
|
end
|
15
16
|
|
16
17
|
# OML Measurement Point (MP)
|
@@ -20,76 +21,85 @@ class OmfRc::ResourceProxy::MPReceived < OML4R::MPBase
|
|
20
21
|
param :time, :type => :double # Time (s) when this message was received
|
21
22
|
param :uid, :type => :string # UID for this Resource Proxy
|
22
23
|
param :topic, :type => :string # Pubsub topic where this message came from
|
23
|
-
param :
|
24
|
+
param :mid, :type => :string # Unique ID this message
|
24
25
|
end
|
25
26
|
|
26
27
|
class OmfRc::ResourceProxy::AbstractResource
|
28
|
+
include MonitorMixin
|
29
|
+
|
27
30
|
# Time to wait before shutting down event loop, wait for deleting pubsub topics
|
28
31
|
DISCONNECT_WAIT = 5
|
29
32
|
# Time to wait before releasing resource, wait for deleting pubsub topics
|
30
33
|
RELEASE_WAIT = 5
|
31
34
|
|
35
|
+
DEFAULT_CREATION_OPTS = {
|
36
|
+
suppress_create_message: false,
|
37
|
+
create_children_resources: true
|
38
|
+
}
|
39
|
+
|
32
40
|
# @!attribute property
|
33
41
|
# @return [String] the resource's internal meta data storage
|
34
42
|
attr_accessor :uid, :hrn, :type, :comm, :property
|
35
|
-
attr_reader :opts, :children, :membership
|
43
|
+
attr_reader :opts, :children, :membership, :creation_opts, :membership_topics
|
36
44
|
|
37
45
|
# Initialisation
|
38
46
|
#
|
39
47
|
# @param [Symbol] type resource proxy type
|
48
|
+
#
|
40
49
|
# @param [Hash] opts options to be initialised
|
41
50
|
# @option opts [String] :uid Unique identifier
|
42
51
|
# @option opts [String] :hrn Human readable name
|
43
|
-
# @option opts [
|
44
|
-
# @option opts [
|
45
|
-
#
|
46
|
-
# @
|
47
|
-
# @option
|
48
|
-
# @option
|
49
|
-
#
|
50
|
-
def initialize(type, opts =
|
52
|
+
# @option opts [Hash] :property A hash for keeping internal state
|
53
|
+
# @option opts [Hash] :instrument A hash for keeping instrumentation-related state
|
54
|
+
#
|
55
|
+
# @param [Hash] creation_opts options to control the resource creation process
|
56
|
+
# @option creation_opts [Boolean] :suppress_create_message Don't send an initial CREATION.OK Inform message
|
57
|
+
# @option creation_opts [Boolean] :create_children_resources Immediately create 'known' children resources, such as interfaces on nodes
|
58
|
+
#
|
59
|
+
def initialize(type, opts = {}, creation_opts = {}, &creation_callback)
|
51
60
|
@opts = Hashie::Mash.new(opts)
|
61
|
+
@creation_opts = Hashie::Mash.new(DEFAULT_CREATION_OPTS.merge(creation_opts))
|
62
|
+
|
52
63
|
@type = type
|
53
64
|
@uid = @opts.uid || SecureRandom.uuid
|
54
|
-
@hrn = @opts.hrn
|
65
|
+
@hrn = @opts.hrn && @opts.hrn.to_s
|
66
|
+
|
55
67
|
@children ||= []
|
56
68
|
@membership ||= []
|
69
|
+
@topics = []
|
70
|
+
@membership_topics ||= {}
|
71
|
+
|
72
|
+
# FIXME adding hrn to membership too?
|
73
|
+
#@membership << @hrn if @hrn
|
57
74
|
|
58
75
|
@property = @opts.property || Hashie::Mash.new
|
76
|
+
@property.merge!(@opts.except([:uid, :hrn, :property, :instrument]))
|
59
77
|
|
60
|
-
@
|
61
|
-
|
62
|
-
|
63
|
-
logger.info "CONNECTED: #{@comm.jid.inspect}"
|
64
|
-
|
65
|
-
# Once connection established, create a pubsub topic, then subscribe to it
|
66
|
-
@comm.create_topic(uid) do |s|
|
67
|
-
# Creating topic failed, no point to continue; clean up and disconnect
|
68
|
-
# Otherwise go subscribe to this pubsub topic
|
69
|
-
if s.error?
|
70
|
-
warn "Could not create topic '#{uid}', will shutdown, trying to clean up old topics. Please start it again once it has been shutdown."
|
71
|
-
disconnect
|
72
|
-
else
|
73
|
-
@comm.subscribe(uid)
|
74
|
-
end
|
78
|
+
OmfCommon.comm.subscribe(@hrn ? [@uid, @hrn] : @uid) do |t|
|
79
|
+
if t.id.to_s == @uid
|
80
|
+
@topics << t
|
75
81
|
end
|
76
|
-
end
|
77
82
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
83
|
+
if t.error?
|
84
|
+
warn "Could not create topic '#{uid}', will shutdown, trying to clean up old topics. Please start it again once it has been shutdown."
|
85
|
+
OmfCommon.comm.disconnect()
|
86
|
+
else
|
87
|
+
creation_callback.call(self) if creation_callback
|
88
|
+
copts = { res_id: self.resource_address, hrn: @hrn }.merge(@property)
|
89
|
+
t.inform(:creation_ok, copts, copts)
|
90
|
+
|
91
|
+
t.on_message(nil, @uid) do |imsg|
|
92
|
+
process_omf_message(imsg, t)
|
93
|
+
end
|
82
94
|
end
|
83
95
|
end
|
84
96
|
|
85
|
-
|
86
|
-
@comm.pubsub_event do |e|
|
87
|
-
logger.debug "PUBSUB GENERIC EVENT: #{e}"
|
88
|
-
end
|
97
|
+
super()
|
89
98
|
end
|
90
99
|
|
91
100
|
# If method missing, try the property mash
|
92
101
|
def method_missing(method_name, *args)
|
102
|
+
warn "Method missing: '#{method_name}'"
|
93
103
|
if (method_name =~ /request_(.+)/)
|
94
104
|
property.key?($1) ? property.send($1) : (raise OmfRc::UnknownPropertyError, method_name.to_s)
|
95
105
|
elsif (method_name =~ /configure_(.+)/)
|
@@ -99,57 +109,103 @@ class OmfRc::ResourceProxy::AbstractResource
|
|
99
109
|
end
|
100
110
|
end
|
101
111
|
|
102
|
-
|
103
|
-
|
112
|
+
# Overwirte methods to add ghost methods
|
113
|
+
def methods
|
114
|
+
super + property.keys.map { |v| ["configure_#{v}".to_sym, "request_#{v}".to_sym] }.flatten
|
104
115
|
end
|
105
116
|
|
106
|
-
#
|
107
|
-
|
108
|
-
|
117
|
+
# Return the public 'routable' address for this resource
|
118
|
+
#
|
119
|
+
def resource_address()
|
120
|
+
@topics[0].address
|
121
|
+
end
|
122
|
+
|
123
|
+
def get_binding
|
124
|
+
binding
|
109
125
|
end
|
110
126
|
|
111
127
|
# Try to clean up pubsub topics, and wait for DISCONNECT_WAIT seconds, then shutdown event machine loop
|
112
128
|
def disconnect
|
113
|
-
|
114
|
-
logger.info "Disconnecting #{hrn}(#{uid}) in #{DISCONNECT_WAIT} seconds"
|
115
|
-
EM.add_timer(DISCONNECT_WAIT) do
|
116
|
-
@comm.disconnect
|
117
|
-
end
|
129
|
+
OmfCommon.comm.disconnect
|
118
130
|
end
|
119
131
|
|
120
132
|
# Create a new resource in the context of this resource. This resource becomes parent, and newly created resource becomes child
|
121
133
|
#
|
122
134
|
# @param (see #initialize)
|
123
|
-
def create(type, opts =
|
135
|
+
def create(type, opts = {}, creation_opts = {}, &creation_callback)
|
124
136
|
proxy_info = OmfRc::ResourceFactory.proxy_list[type]
|
125
137
|
if proxy_info && proxy_info.create_by && !proxy_info.create_by.include?(self.type.to_sym)
|
126
138
|
raise StandardError, "Resource #{type} is not designed to be created by #{self.type}"
|
127
139
|
end
|
128
140
|
|
129
141
|
before_create(type, opts) if respond_to? :before_create
|
130
|
-
new_resource = OmfRc::ResourceFactory.
|
142
|
+
new_resource = OmfRc::ResourceFactory.create(type.to_sym, opts, creation_opts, &creation_callback)
|
131
143
|
after_create(new_resource) if respond_to? :after_create
|
132
|
-
|
144
|
+
|
145
|
+
self.synchronize do
|
146
|
+
children << new_resource
|
147
|
+
end
|
133
148
|
new_resource
|
134
149
|
end
|
135
150
|
|
136
|
-
# Release a resource
|
151
|
+
# Release a child resource
|
152
|
+
#
|
153
|
+
# @return [AbstractResource] Relsead child or nil if error
|
137
154
|
#
|
138
|
-
def release(
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
155
|
+
def release(res_id)
|
156
|
+
if (child = children.find { |v| v.uid.to_s == res_id.to_s })
|
157
|
+
if child.release_self()
|
158
|
+
self.synchronize do
|
159
|
+
children.delete(child)
|
160
|
+
end
|
161
|
+
child
|
162
|
+
else
|
163
|
+
child = nil
|
164
|
+
end
|
165
|
+
debug "#{child.uid} released"
|
143
166
|
else
|
144
|
-
#
|
145
|
-
|
146
|
-
|
167
|
+
debug "#{res_id} does not belong to #{self.uid}(#{self.hrn}) - #{children.map(&:uid).inspect}"
|
168
|
+
end
|
169
|
+
child
|
170
|
+
end
|
171
|
+
|
172
|
+
# Release this resource. Should ONLY be called by parent resource.
|
173
|
+
#
|
174
|
+
# Return true if successful
|
175
|
+
#
|
176
|
+
def release_self
|
177
|
+
# Release children resource recursively
|
178
|
+
children.each do |c|
|
179
|
+
if c.release_self
|
180
|
+
self.synchronize do
|
181
|
+
children.delete(c)
|
182
|
+
end
|
147
183
|
end
|
148
|
-
|
184
|
+
end
|
185
|
+
|
186
|
+
return false unless children.empty?
|
149
187
|
|
150
|
-
|
151
|
-
|
188
|
+
info "Releasing hrn: #{hrn}, uid: #{uid}"
|
189
|
+
self.before_release if self.respond_to? :before_release
|
190
|
+
props = {
|
191
|
+
res_id: resource_address
|
192
|
+
}
|
193
|
+
props[:hrn] = hrn if hrn
|
194
|
+
inform :released, props
|
195
|
+
|
196
|
+
# clean up topics
|
197
|
+
@topics.each do |t|
|
198
|
+
t.unsubscribe
|
152
199
|
end
|
200
|
+
|
201
|
+
@membership_topics.each_value do |t|
|
202
|
+
if t.respond_to? :delete_on_message_cbk_by_id
|
203
|
+
t.delete_on_message_cbk_by_id(@uid)
|
204
|
+
end
|
205
|
+
t.unsubscribe
|
206
|
+
end
|
207
|
+
|
208
|
+
true
|
153
209
|
end
|
154
210
|
|
155
211
|
# Return a list of all properties can be requested and configured
|
@@ -157,7 +213,7 @@ class OmfRc::ResourceProxy::AbstractResource
|
|
157
213
|
def request_available_properties(*args)
|
158
214
|
Hashie::Mash.new(request: [], configure: []).tap do |mash|
|
159
215
|
methods.each do |m|
|
160
|
-
mash[$1] << $2.to_sym if m =~
|
216
|
+
mash[$1] << $2.to_sym if m =~ /^(request|configure)_(.+)/ && $2 != "available_properties"
|
161
217
|
end
|
162
218
|
end
|
163
219
|
end
|
@@ -167,6 +223,14 @@ class OmfRc::ResourceProxy::AbstractResource
|
|
167
223
|
uid
|
168
224
|
end
|
169
225
|
|
226
|
+
def request_type(*args)
|
227
|
+
type
|
228
|
+
end
|
229
|
+
|
230
|
+
def configure_type(*args)
|
231
|
+
@type = type
|
232
|
+
end
|
233
|
+
|
170
234
|
# Make hrn accessible through pubsub interface
|
171
235
|
def request_hrn(*args)
|
172
236
|
hrn
|
@@ -174,33 +238,43 @@ class OmfRc::ResourceProxy::AbstractResource
|
|
174
238
|
|
175
239
|
alias_method :request_name, :request_hrn
|
176
240
|
alias_method :name, :hrn
|
177
|
-
alias_method :name=, :hrn=
|
178
|
-
|
179
|
-
def request_type(*args)
|
180
|
-
type
|
181
|
-
end
|
182
241
|
|
183
242
|
# Make hrn configurable through pubsub interface
|
184
243
|
def configure_hrn(hrn)
|
185
|
-
|
244
|
+
self.synchronize do
|
245
|
+
@hrn = hrn
|
246
|
+
end
|
186
247
|
@hrn
|
187
248
|
end
|
188
249
|
|
250
|
+
alias_method :configure_name, :configure_hrn
|
251
|
+
alias_method :name=, :hrn=
|
252
|
+
|
189
253
|
# Make resource part of the group topic, it will overwrite existing membership array
|
190
254
|
#
|
191
255
|
# @param [String] name of group topic
|
192
256
|
# @param [Array] name of group topics
|
193
257
|
def configure_membership(*args)
|
194
258
|
new_membership = [args[0]].flatten
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
259
|
+
|
260
|
+
new_membership.each do |new_m|
|
261
|
+
unless @membership.include?(new_m)
|
262
|
+
OmfCommon.comm.subscribe(new_m) do |t|
|
263
|
+
if t.error?
|
264
|
+
warn "Group #{new_m} disappeared"
|
265
|
+
#EM.next_tick do
|
266
|
+
# @membership.delete(m)
|
267
|
+
#end
|
268
|
+
else
|
269
|
+
self.synchronize do
|
270
|
+
@membership << new_m
|
271
|
+
@membership_topics[new_m] = t
|
272
|
+
self.inform(:status, { membership: @membership }, t)
|
273
|
+
end
|
274
|
+
|
275
|
+
t.on_message(nil, @uid) do |imsg|
|
276
|
+
process_omf_message(imsg, t)
|
277
|
+
end
|
204
278
|
end
|
205
279
|
end
|
206
280
|
end
|
@@ -219,184 +293,209 @@ class OmfRc::ResourceProxy::AbstractResource
|
|
219
293
|
children.map { |c| Hashie::Mash.new({ uid: c.uid, name: c.hrn }) }
|
220
294
|
end
|
221
295
|
|
222
|
-
#
|
223
|
-
#
|
224
|
-
# @param [
|
225
|
-
|
226
|
-
|
296
|
+
# Parse omf message and execute as instructed by the message
|
297
|
+
#
|
298
|
+
# @param [OmfCommon::Message]
|
299
|
+
# @param [OmfCommon::Comm::Topic]
|
300
|
+
def process_omf_message(message, topic)
|
301
|
+
return unless check_guard(message)
|
227
302
|
|
228
|
-
|
229
|
-
|
230
|
-
unless inform_data.kind_of? Exception
|
231
|
-
raise ArgumentError, "FAILED message requires an Exception (or MessageProcessError)"
|
232
|
-
end
|
233
|
-
when :created, :released
|
234
|
-
unless inform_data.respond_to?(:resource_id) && !inform_data.resource_id.nil?
|
235
|
-
raise ArgumentError, "CREATED or RELEASED message requires inform_data object respond to resource_id"
|
236
|
-
end
|
237
|
-
when :status
|
238
|
-
unless inform_data.respond_to?(:status) && inform_data.status.kind_of?(Hash)
|
239
|
-
raise ArgumentError, "STATUS message requires a hash represents properties"
|
240
|
-
end
|
303
|
+
unless message.is_a? OmfCommon::Message
|
304
|
+
raise ArgumentError, "Expected OmfCommon::Message, but got '#{message.class}'"
|
241
305
|
end
|
242
306
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
i.element('resource_id', inform_data.resource_id)
|
251
|
-
i.element('resource_address', inform_data.resource_id)
|
252
|
-
when :status
|
253
|
-
inform_data.status.each_pair { |k, v| i.property(k, v) }
|
254
|
-
when :released
|
255
|
-
i.element('resource_id', inform_data.resource_id)
|
256
|
-
when :error, :warn
|
257
|
-
i.element("reason", (inform_data.message rescue inform_data))
|
258
|
-
logger.__send__(inform_type, (inform_data.message rescue inform_data))
|
259
|
-
when :failed
|
260
|
-
i.element("reason", inform_data.message)
|
307
|
+
unless message.valid?
|
308
|
+
raise StandardError, "Invalid message received: #{pubsub_item_payload}. Please check protocol schema of version #{OmfCommon::PROTOCOL_VERSION}."
|
309
|
+
end
|
310
|
+
|
311
|
+
objects_by_topic(topic.id.to_s).each do |obj|
|
312
|
+
if OmfCommon::Measure.enabled?
|
313
|
+
OmfRc::ResourceProxy::MPReceived.inject(Time.now.to_f, self.uid, topic, message.mid)
|
261
314
|
end
|
315
|
+
execute_omf_operation(message, obj, topic)
|
262
316
|
end
|
263
|
-
@comm.publish(inform_to, inform_message)
|
264
|
-
OmfRc::ResourceProxy::MPPublished.inject(Time.now.to_f,
|
265
|
-
self.uid, inform_to, inform_message.msg_id) if OmfCommon::Measure.enabled?
|
266
317
|
end
|
267
318
|
|
268
|
-
|
319
|
+
def execute_omf_operation(message, obj, topic)
|
320
|
+
begin
|
321
|
+
response_h = handle_message(message, obj)
|
322
|
+
rescue Exception => ex
|
323
|
+
err_resp = message.create_inform_reply_message()
|
324
|
+
err_resp[:reason] = ex.to_s
|
325
|
+
error "Encountered exception, returning ERROR message"
|
326
|
+
debug ex.message
|
327
|
+
debug ex.backtrace.join("\n")
|
328
|
+
return inform(:error, err_resp, topic)
|
329
|
+
end
|
269
330
|
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
331
|
+
case message.operation
|
332
|
+
#when :create
|
333
|
+
# inform(:creation_ok, response_h, topic)
|
334
|
+
when :request, :configure
|
335
|
+
inform(:status, response_h, topic)
|
336
|
+
when :release
|
337
|
+
OmfCommon.eventloop.after(RELEASE_WAIT) do
|
338
|
+
inform(:released, response_h, topic) if response_h[:res_id]
|
339
|
+
end
|
276
340
|
end
|
277
341
|
end
|
278
342
|
|
279
|
-
|
280
|
-
|
343
|
+
# Handling all messages, then delegate them to individual handler
|
344
|
+
def handle_message(message, obj)
|
345
|
+
response = message.create_inform_reply_message()
|
346
|
+
response.replyto replyto_address(obj, message.replyto)
|
347
|
+
|
348
|
+
case message.operation
|
349
|
+
when :create
|
350
|
+
handle_create_message(message, obj, response)
|
351
|
+
when :request
|
352
|
+
response = handle_request_message(message, obj, response)
|
353
|
+
when :configure
|
354
|
+
handle_configure_message(message, obj, response)
|
355
|
+
when :release
|
356
|
+
handle_release_message(message, obj, response)
|
357
|
+
when :inform
|
358
|
+
nil # We really don't care about inform messages which created from here
|
359
|
+
else
|
360
|
+
raise StandardError, <<-ERROR
|
361
|
+
Invalid message received (Unknown OMF operation #{message.operation}): #{message}.
|
362
|
+
Please check protocol schema of version #{OmfCommon::PROTOCOL_VERSION}.
|
363
|
+
ERROR
|
364
|
+
end
|
365
|
+
response
|
281
366
|
end
|
282
367
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
368
|
+
def handle_create_message(message, obj, response)
|
369
|
+
new_name = message[:name] || message[:hrn]
|
370
|
+
new_opts = message.properties.merge({ hrn: new_name })
|
371
|
+
new_obj = obj.create(message[:type], new_opts) do |new_obj|
|
372
|
+
begin
|
373
|
+
response[:res_id] = new_obj.resource_address
|
287
374
|
|
288
|
-
|
289
|
-
|
375
|
+
exclude = [:type, :hrn, :name]
|
376
|
+
message.each_property do |key, value|
|
377
|
+
unless exclude.include?(key)
|
378
|
+
method_name = "configure_#{key}"
|
379
|
+
response[key] = new_obj.__send__(method_name, value)
|
380
|
+
end
|
381
|
+
end
|
382
|
+
response[:hrn] = new_obj.hrn
|
383
|
+
response[:uid] = new_obj.uid
|
384
|
+
response[:type] = new_obj.type
|
385
|
+
|
386
|
+
new_obj.after_initial_configured if new_obj.respond_to? :after_initial_configured
|
387
|
+
|
388
|
+
# self here is the parent
|
389
|
+
self.inform(:creation_ok, response)
|
390
|
+
rescue Exception => ex
|
391
|
+
err_resp = message.create_inform_reply_message()
|
392
|
+
err_resp[:reason] = ex.to_s
|
393
|
+
error "Encountered exception, returning ERROR message"
|
394
|
+
debug ex.message
|
395
|
+
debug ex.backtrace.join("\n")
|
396
|
+
return self.inform(:error, err_resp)
|
397
|
+
end
|
290
398
|
end
|
399
|
+
end
|
291
400
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
401
|
+
def handle_configure_message(message, obj, response)
|
402
|
+
message.each_property do |key, value|
|
403
|
+
method_name = "#{message.operation.to_s}_#{key}"
|
404
|
+
p_value = message[key]
|
405
|
+
response[key] ||= obj.__send__(method_name, p_value)
|
296
406
|
end
|
297
407
|
end
|
298
408
|
|
299
|
-
def
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
@comm.subscribe(new_uid) do
|
310
|
-
inform(:created, response)
|
311
|
-
end
|
312
|
-
end
|
313
|
-
when :request, :configure
|
314
|
-
inform(:status, response)
|
315
|
-
when :release
|
316
|
-
EM.add_timer(RELEASE_WAIT) do
|
317
|
-
inform(:released, response)
|
318
|
-
end
|
409
|
+
def handle_request_message(message, obj, response)
|
410
|
+
allowed_properties = obj.request_available_properties.request - [:message]
|
411
|
+
|
412
|
+
have_unbound = false
|
413
|
+
|
414
|
+
message.each_unbound_request_property do |name|
|
415
|
+
puts "NAME>> #{name.inspect}"
|
416
|
+
|
417
|
+
unless allowed_properties.include?(name.to_sym)
|
418
|
+
raise ArgumentError, "Unknown 'requestable' property '#{name}'. Allowed properties are: #{allowed_properties.join(', ')}"
|
319
419
|
end
|
420
|
+
method_name = "request_#{name}"
|
421
|
+
response[name] = obj.__send__(method_name)
|
422
|
+
have_unbound = true
|
423
|
+
end
|
424
|
+
unless have_unbound
|
425
|
+
# return ALL properties
|
426
|
+
allowed_properties.each do |name|
|
427
|
+
method_name = "request_#{name}"
|
428
|
+
response[name] = obj.__send__(method_name)
|
429
|
+
end
|
430
|
+
end
|
431
|
+
response
|
432
|
+
end
|
433
|
+
|
434
|
+
def handle_release_message(message, obj, response)
|
435
|
+
res_id = message.res_id
|
436
|
+
released_obj = obj.release(res_id)
|
437
|
+
# TODO: Under what circumstances would 'realease_obj' be NIL
|
438
|
+
#
|
439
|
+
# When release message send to a group, for bulk releasing,
|
440
|
+
# the proxy might not be aware of a res_id it received
|
441
|
+
response[:res_id] = released_obj.resource_address if released_obj
|
442
|
+
response
|
443
|
+
end
|
444
|
+
|
445
|
+
|
446
|
+
# Publish an inform message
|
447
|
+
# @param [Symbol] itype the type of inform message
|
448
|
+
# @param [Hash | Hashie::Mash | Exception | String] inform_data the type of inform message
|
449
|
+
def inform(itype, inform_data, topic = nil)
|
450
|
+
topic ||= @topics.first
|
451
|
+
|
452
|
+
if inform_data.is_a? Hash
|
453
|
+
inform_data = Hashie::Mash.new(inform_data) if inform_data.class == Hash
|
454
|
+
message = OmfCommon::Message.create_inform_message(itype.to_s.upcase, inform_data.dup)
|
455
|
+
else
|
456
|
+
message = inform_data
|
320
457
|
end
|
321
458
|
|
322
|
-
|
323
|
-
|
324
|
-
|
459
|
+
message.itype = itype
|
460
|
+
unless itype == :released
|
461
|
+
message[:uid] ||= self.uid
|
462
|
+
message[:type] ||= self.type
|
463
|
+
message[:hrn] ||= self.hrn
|
325
464
|
end
|
326
465
|
|
327
|
-
|
328
|
-
dp.fire do
|
329
|
-
begin
|
330
|
-
default_response = {
|
331
|
-
operation: message.operation,
|
332
|
-
context_id: message.msg_id,
|
333
|
-
inform_to: inform_to_address(obj, message.publish_to)
|
334
|
-
}
|
466
|
+
topic.publish(message)
|
335
467
|
|
336
|
-
|
468
|
+
OmfRc::ResourceProxy::MPPublished.inject(Time.now.to_f,
|
469
|
+
self.uid, replyto, inform_message.mid) if OmfCommon::Measure.enabled?
|
470
|
+
end
|
337
471
|
|
338
|
-
|
339
|
-
guard_check = guard.element_children.all? do |g|
|
340
|
-
obj.__send__("request_#{g.attr('key')}") == g.content.ducktype
|
341
|
-
end
|
342
|
-
next nil unless guard_check
|
343
|
-
end
|
472
|
+
private
|
344
473
|
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
properties.each do |p|
|
369
|
-
method_name = "#{message.operation.to_s}_#{p.attr('key')}"
|
370
|
-
p_value = message.read_property(p.attr('key'), obj.get_binding)
|
371
|
-
mash[p.attr('key')] ||= obj.__send__(method_name, p_value)
|
372
|
-
end
|
373
|
-
end
|
374
|
-
end
|
375
|
-
# Always return uid
|
376
|
-
result.uid = obj.uid
|
377
|
-
default_response.merge(status: result)
|
378
|
-
when :release
|
379
|
-
resource_id = message.resource_id
|
380
|
-
released_obj = obj.release(resource_id)
|
381
|
-
released_obj ? default_response.merge(resource_id: released_obj.uid) : nil
|
382
|
-
when :inform
|
383
|
-
nil # We really don't care about inform messages which created from here
|
384
|
-
else
|
385
|
-
raise StandardError, <<-ERROR
|
386
|
-
Invalid message received (Unknown OMF operation #{message.operation}): #{pubsub_item_payload}.
|
387
|
-
Please check protocol schema of version #{OmfCommon::PROTOCOL_VERSION}.
|
388
|
-
ERROR
|
389
|
-
end
|
390
|
-
rescue => e
|
391
|
-
if (e.kind_of? OmfRc::UnknownPropertyError) && (message.operation == :configure || message.operation == :request)
|
392
|
-
msg = "Cannot #{message.operation} unknown property '#{e.message}' for resource '#{obj.type}'. Original message fragment: " +
|
393
|
-
"'#{message.read_element("property")}'"
|
394
|
-
logger.warn msg
|
395
|
-
raise OmfRc::MessageProcessError.new(message.context_id, inform_to_address(obj, message.publish_to), msg)
|
474
|
+
# Find resource object based on topic name
|
475
|
+
def objects_by_topic(name)
|
476
|
+
if name == uid || membership.include?(name)
|
477
|
+
objs = [self]
|
478
|
+
else
|
479
|
+
objs = children.find_all { |v| v.uid == name || v.membership.include?(name)}
|
480
|
+
end
|
481
|
+
end
|
482
|
+
|
483
|
+
def replyto_address(obj, replyto = nil)
|
484
|
+
replyto || obj.uid
|
485
|
+
end
|
486
|
+
|
487
|
+
def check_guard(message)
|
488
|
+
guard = message.guard
|
489
|
+
|
490
|
+
if guard.nil? || guard.empty?
|
491
|
+
return true
|
492
|
+
else
|
493
|
+
guard.keys.all? do |key|
|
494
|
+
value = self.__send__("request_#{key}")
|
495
|
+
if value.kind_of? Symbol
|
496
|
+
value.to_s == guard[key].to_s
|
396
497
|
else
|
397
|
-
|
398
|
-
logger.error e.backtrace.join("\n")
|
399
|
-
raise OmfRc::MessageProcessError.new(message.context_id, inform_to_address(obj, message.publish_to), e.message)
|
498
|
+
value == guard[key]
|
400
499
|
end
|
401
500
|
end
|
402
501
|
end
|