omf_rc 6.0.0.pre.6 → 6.0.0.pre.7

Sign up to get free protection for your applications and to get access to all the features.
data/bin/omf_rc CHANGED
@@ -10,42 +10,50 @@ options = {
10
10
  }
11
11
 
12
12
  executable_name = File.basename($PROGRAM_NAME)
13
+ oml_enabled = false
13
14
 
14
- option_parser = OptionParser.new do |opts|
15
- opts.banner = "usage: #{executable_name} [options]"
15
+ begin
16
+ oml_enabled = OML4R::init(ARGV, :appName => executable_name) do |opts|
17
+ opts.banner = "usage: #{executable_name} [options]"
16
18
 
17
- opts.on("-u USER", "Username") do |user|
18
- options[:user] = user
19
- end
19
+ opts.on("-u USER", "Username") do |user|
20
+ options[:user] = user
21
+ end
20
22
 
21
- opts.on("-p PASSWORD", "Password") do |password|
22
- options[:password] = password
23
- end
23
+ opts.on("-p PASSWORD", "Password") do |password|
24
+ options[:password] = password
25
+ end
24
26
 
25
- opts.on("-s SERVER", "XMPP server") do |server|
26
- options[:server] = server
27
- end
27
+ opts.on("-s SERVER", "PubSub server") do |server|
28
+ options[:server] = server
29
+ end
28
30
 
29
- opts.on("-t TOPIC", "PubSub topic to create, also becomes the uid of the resource, default to hostname") do |topic|
30
- options[:uid] = topic
31
- end
31
+ opts.on("-t TOPIC", "PubSub topic to create, also becomes the uid of the resource, default to hostname") do |topic|
32
+ options[:uid] = topic
33
+ end
32
34
 
33
- opts.on("-d", "--debug", "Debug mode") do
34
- options[:debug] = true
35
+ opts.on("-d", "--debug", "Debug mode") do
36
+ options[:debug] = true
37
+ end
35
38
  end
36
- end
37
-
38
- begin
39
- option_parser.parse!
40
39
  rescue => e
41
- puts e.message
42
- puts ""
43
- puts option_parser.help
44
- exit(1)
40
+ # Right now OML4R does not raise proper exceptions :(
41
+ # OML4R requires --oml-noop to be set if we want to run without doing any
42
+ # measurements... this is too restrictive here, we want to run without OML
43
+ # if no OML parameters were set and this even if --oml-noop is not set.
44
+ if e.message.include?('OML4R: Missing values for parameters :expID ')
45
+ puts "Warning: Missing some OML options to instrument this RC, so it will "+
46
+ "run without instrumentation. (see --oml-help)"
47
+ else
48
+ puts e.message
49
+ exit(1)
50
+ end
45
51
  end
46
52
 
47
- unless options[:server] && options[:user] && options[:server]
48
- puts option_parser.help
53
+ OmfCommon::Measure.enable if oml_enabled
54
+
55
+ unless options[:server] && options[:user] && options[:password]
56
+ puts "Error: Missing parameters to connect to a PubSub Server (see --help)"
49
57
  exit(1)
50
58
  end
51
59
 
data/config/omf_rc.yml CHANGED
@@ -5,35 +5,35 @@
5
5
  #
6
6
  ---
7
7
  :rcontroller:
8
- # Communication settings
8
+ # Communication settings
9
9
  :communicator:
10
-
11
- # Interface to the control network from which this resource can be
10
+
11
+ # Interface to the control network from which this resource can be
12
12
  # controlled & managed
13
13
  :control_if: 'control'
14
14
 
15
- # set this to true or false if you want to enable or disable signature checks and message signing
15
+ # set this to true or false if you want to enable or disable signature checks and message signing
16
16
  :authenticate_messages: false
17
17
  # your RSA/DSA SSH private key file
18
18
  :private_key: '/etc/omf-resctl-5.4/id_rsa'
19
19
  # directory holding the public keys of your OMF peers
20
20
  :public_key_dir: '/etc/omf-resctl-5.4/peer_keys'
21
-
21
+
22
22
  :type: 'xmpp'
23
23
  :xmpp:
24
24
  # Address of the PubSub server to use as gateway for PubSub communication
25
25
  :pubsub_gateway: 'norbit.npc.nicta.com.au'
26
26
  #:pubsub_port: 5222
27
27
  # Address of the PubSub server which host the communication for my slice
28
- # Leave this commented if the pubsub groups for this slice are hosted on
28
+ # Leave this commented if the pubsub groups for this slice are hosted on
29
29
  # the same server as the 'pubsub_gateway'
30
30
  #:pubsub_domain: 10.0.0.200
31
31
  # The following 'home_pubsub_user' and 'home_pubsub_pwd' are optional
32
32
  # RC will create a unique user/pwd for itself if this is not provided
33
33
  # In a typical OMF install, you should not uncomment these lines
34
- # (do so only if you need to manually set user/password for
34
+ # (do so only if you need to manually set user/password for
35
35
  # your client to connect to your pubsub server)
36
- #:pubsub_user: 'my_RC_name'
36
+ #:pubsub_user: 'my_RC_name'
37
37
  #:pubsub_pwd: 'my_RC_password'
38
38
  # set this to "true" if you have a DNS SRV record pointing to the
39
39
  # real pubsub server hostname
@@ -45,7 +45,7 @@
45
45
  # Name (i.e. unique HRN ID) of this resource
46
46
  # Or this could also be passed as a command line parameter "--name"
47
47
  # This is either a fully defined string, e.g. "my_resource_name"
48
- # Or a string for which some values will be replaced by the running RC,
48
+ # Or a string for which some values will be replaced by the running RC,
49
49
  # currently we support the values: %hostname%, %macaddr%, %fqdn%
50
50
  # For example, if you use "some_prefix.%hostname%.some_suffix"
51
51
  # Then if your hostname is 'node1', then your RC name will be
@@ -56,7 +56,7 @@
56
56
 
57
57
  # Name (i.e. unique HRN ID) of the slice to which this resource is assigned
58
58
  :slice: default_slice
59
-
59
+
60
60
  # shrink the filesystem size before saving an image
61
61
  # grow the filesystem to match the disk size after loading an image
62
62
  # enabling this may slow down load/save significantly
@@ -9,3 +9,11 @@ class OmfRc::MessageProcessError < StandardError
9
9
  super(msg)
10
10
  end
11
11
  end
12
+
13
+ # No method error that caused by configure/request unknown property
14
+ #
15
+ class OmfRc::UnknownPropertyError < NoMethodError
16
+ def initialize(msg = nil)
17
+ super(msg)
18
+ end
19
+ end
@@ -30,6 +30,10 @@ class OmfRc::ResourceFactory
30
30
  resource = OmfRc::ResourceProxy::AbstractResource.new(type, opts, comm)
31
31
  # Then extend this instance with relevant module identified by type
32
32
  resource.extend("OmfRc::ResourceProxy::#{type.camelize}".constantize)
33
+ # Initiate property hash
34
+ resource.methods.each do |m|
35
+ resource.__send__(m) if m =~ /def_property_(.+)/
36
+ end
33
37
  # Execute resource before_ready hook if any
34
38
  resource.before_ready if resource.respond_to? :before_ready
35
39
  resource
@@ -1,8 +1,28 @@
1
1
  require 'omf_rc/deferred_process'
2
- require 'omf_rc/message_process_error'
2
+ require 'omf_rc/omf_error'
3
3
  require 'securerandom'
4
4
  require 'hashie'
5
5
 
6
+ # OML Measurement Point (MP)
7
+ # This MP is for measurements about messages published by the Resource Proxy
8
+ class OmfRc::ResourceProxy::MPPublished < OML4R::MPBase
9
+ name :proxy_published
10
+ param :time, :type => :double # Time (s) when this message was published
11
+ param :uid, :type => :string # UID for this Resource Proxy
12
+ param :topic, :type => :string # Pubsub topic to publish this message to
13
+ param :msg_id, :type => :string # Unique ID this message
14
+ end
15
+
16
+ # OML Measurement Point (MP)
17
+ # This MP is for measurements about messages received by the Resource Proxy
18
+ class OmfRc::ResourceProxy::MPReceived < OML4R::MPBase
19
+ name :proxy_received
20
+ param :time, :type => :double # Time (s) when this message was received
21
+ param :uid, :type => :string # UID for this Resource Proxy
22
+ param :topic, :type => :string # Pubsub topic where this message came from
23
+ param :msg_id, :type => :string # Unique ID this message
24
+ end
25
+
6
26
  class OmfRc::ResourceProxy::AbstractResource
7
27
  # Time to wait before shutting down event loop, wait for deleting pubsub topics
8
28
  DISCONNECT_WAIT = 5
@@ -12,7 +32,7 @@ class OmfRc::ResourceProxy::AbstractResource
12
32
  # @!attribute property
13
33
  # @return [String] the resource's internal meta data storage
14
34
  attr_accessor :uid, :hrn, :type, :comm, :property
15
- attr_reader :opts, :children
35
+ attr_reader :opts, :children, :membership
16
36
 
17
37
  # Initialisation
18
38
  #
@@ -25,6 +45,7 @@ class OmfRc::ResourceProxy::AbstractResource
25
45
  # @option opts [String] :password pubsub user password
26
46
  # @option opts [String] :server pubsub server domain
27
47
  # @option opts [String] :property A hash for keeping internal state
48
+ # @option opts [hash] :instrument A hash for keeping instrumentation-related state
28
49
  # @param [Comm] comm communicator instance, pass this to new resource proxy instance if want to use a common communicator instance.
29
50
  def initialize(type, opts = nil, comm = nil)
30
51
  @opts = Hashie::Mash.new(opts)
@@ -32,6 +53,7 @@ class OmfRc::ResourceProxy::AbstractResource
32
53
  @uid = @opts.uid || SecureRandom.uuid
33
54
  @hrn = @opts.hrn
34
55
  @children ||= []
56
+ @membership ||= []
35
57
 
36
58
  @property = @opts.property || Hashie::Mash.new
37
59
 
@@ -64,9 +86,9 @@ class OmfRc::ResourceProxy::AbstractResource
64
86
  # If method missing, try the property mash
65
87
  def method_missing(method_name, *args)
66
88
  if (method_name =~ /request_(.+)/)
67
- property.send($1) || super
89
+ property.key?($1) ? property.send($1) : (raise OmfRc::UnknownPropertyError)
68
90
  elsif (method_name =~ /configure_(.+)/)
69
- property.send($1) ? property.send("[]=", $1, *args) : super
91
+ property.key?($1) ? property.send("[]=", $1, *args) : (raise OmfRc::UnknownPropertyError)
70
92
  else
71
93
  super
72
94
  end
@@ -149,16 +171,26 @@ class OmfRc::ResourceProxy::AbstractResource
149
171
  # Make hrn configurable through pubsub interface
150
172
  def configure_hrn(hrn)
151
173
  @hrn = hrn
174
+ @hrn
175
+ end
176
+
177
+ # Make resource part of the group topic, it will overwrite existing membership array
178
+ #
179
+ # @param [String] name of group topic
180
+ # @param [Array] name of group topics
181
+ def configure_membership(*args)
182
+ new_membership = [args[0]].flatten
183
+ @membership = new_membership
184
+ @membership.each do |m|
185
+ @comm.subscribe(m)
186
+ end
187
+ @membership
152
188
  end
153
189
 
154
190
  # Request child resources
155
- # @return [Mash] child resource mash with uid and hrn
191
+ # @return [Hashie::Mash] child resource mash with uid and hrn
156
192
  def request_child_resources(*args)
157
- Hashie::Mash.new.tap do |mash|
158
- children.each do |c|
159
- mash[c.uid] ||= c.hrn
160
- end
161
- end
193
+ children.map { |c| Hashie::Mash.new({ uid: c.uid, name: c.hrn }) }
162
194
  end
163
195
 
164
196
  # Publish an inform message
@@ -203,15 +235,45 @@ class OmfRc::ResourceProxy::AbstractResource
203
235
  end
204
236
  end
205
237
  @comm.publish(inform_to, inform_message)
238
+ OmfRc::ResourceProxy::MPPublished.inject(Time.now.to_f,
239
+ self.uid, inform_to, inform_message.msg_id) if OmfCommon::Measure.enabled?
206
240
  end
207
241
 
208
242
  private
209
243
 
244
+ # Find resource object based on topic name
245
+ def objects_by_topic(name)
246
+ if name == uid || membership.include?(name)
247
+ objs = [self]
248
+ else
249
+ objs = children.find_all { |v| v.uid == name || v.membership.include?(name)}
250
+ end
251
+ end
252
+
253
+ def inform_to_address(obj, publish_to = nil)
254
+ publish_to || obj.uid
255
+ end
256
+
210
257
  # Parse omf message and execute as instructed by the message
211
258
  #
212
259
  def process_omf_message(pubsub_item_payload, topic)
260
+ message = OmfCommon::Message.parse(pubsub_item_payload)
261
+
262
+ unless message.valid?
263
+ raise StandardError, "Invalid message received: #{pubsub_item_payload}. Please check protocol schema of version #{OmfCommon::PROTOCOL_VERSION}."
264
+ end
265
+
266
+ objects_by_topic(topic).each do |obj|
267
+ OmfRc::ResourceProxy::MPReceived.inject(Time.now.to_f,
268
+ self.uid, topic, message.msg_id) if OmfCommon::Measure.enabled?
269
+ execute_omf_operation(message, obj)
270
+ end
271
+ end
272
+
273
+ def execute_omf_operation(message, obj)
213
274
  dp = OmfRc::DeferredProcess.new
214
275
 
276
+ # When successfully executed
215
277
  dp.callback do |response|
216
278
  response = Hashie::Mash.new(response)
217
279
  case response.operation
@@ -231,68 +293,69 @@ class OmfRc::ResourceProxy::AbstractResource
231
293
  end
232
294
  end
233
295
 
296
+ # When failed
234
297
  dp.errback do |e|
235
298
  inform(:failed, e)
236
299
  end
237
300
 
301
+ # Fire the process
238
302
  dp.fire do
239
- message = OmfCommon::Message.parse(pubsub_item_payload)
240
- # Get the context id, which will be included when informing
241
- context_id = message.read_content("context_id")
242
-
243
- obj = topic == uid ? self : children.find { |v| v.uid == topic }
244
-
245
303
  begin
246
- raise "Resource disappeard #{topic}" if obj.nil?
304
+ default_response = {
305
+ operation: message.operation,
306
+ context_id: message.context_id,
307
+ inform_to: inform_to_address(obj, message.publish_to)
308
+ }
247
309
 
248
310
  case message.operation
249
311
  when :create
250
- create_opts = opts.dup
251
- create_opts.uid = nil
252
- result = obj.create(message.read_property(:type), create_opts)
312
+ new_opts = opts.dup.merge(uid: nil)
313
+ new_obj = obj.create(message.read_property(:type), new_opts)
253
314
  message.each_property do |p|
254
315
  unless p.attr('key') == 'type'
255
- method_name = "configure_#{p.attr('key')}"
256
- result.__send__(method_name, message.read_property(p.attr('key')))
257
- end
258
- end
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 }
261
- when :request
262
- result = Hashie::Mash.new.tap do |mash|
263
- message.read_element("//property").each do |p|
264
- method_name = "request_#{p.attr('key')}"
265
- mash[p.attr('key')] ||= obj.__send__(method_name, message.read_property(p.attr('key')))
316
+ method_name = "configure_#{p.attr('key')}"
317
+ new_obj.__send__(method_name, message.read_property(p.attr('key')))
266
318
  end
267
319
  end
268
- { operation: :request, status: result, context_id: context_id, inform_to: obj.uid }
269
- when :configure
320
+ new_obj.after_initial_configured if new_obj.respond_to? :after_initial_configured
321
+ default_response.merge(resource_id: new_obj.uid)
322
+ when :request, :configure
270
323
  result = Hashie::Mash.new.tap do |mash|
271
- message.read_element("//property").each do |p|
272
- method_name = "configure_#{p.attr('key')}"
273
- mash[p.attr('key')] ||= obj.__send__(method_name, message.read_property(p.attr('key')))
324
+ properties = message.read_element("//property")
325
+ if message.operation == :request && properties.empty?
326
+ obj.request_available_properties.request.each do |r_p|
327
+ method_name = "request_#{r_p.to_s}"
328
+ mash[r_p] ||= obj.__send__(method_name)
329
+ end
330
+ else
331
+ properties.each do |p|
332
+ method_name = "#{message.operation.to_s}_#{p.attr('key')}"
333
+ mash[p.attr('key')] ||= obj.__send__(method_name, message.read_property(p.attr('key')))
334
+ end
274
335
  end
275
336
  end
276
- { operation: :configure, status: result, context_id: context_id, inform_to: obj.uid }
337
+ default_response.merge(status: result)
277
338
  when :release
278
339
  resource_id = message.resource_id
279
- { operation: :release, resource_id: obj.release(resource_id).uid, context_id: context_id, inform_to: obj.uid }
340
+ default_response.merge(resource_id: obj.release(resource_id).uid)
280
341
  when :inform
281
- # We really don't care about inform messages which created from here
282
- nil
342
+ nil # We really don't care about inform messages which created from here
283
343
  else
284
- raise "Unknown OMF operation #{message.operation}"
344
+ raise StandardError, <<-ERROR
345
+ Invalid message received (Unknown OMF operation #{message.operation}): #{pubsub_item_payload}.
346
+ Please check protocol schema of version #{OmfCommon::PROTOCOL_VERSION}.
347
+ ERROR
285
348
  end
286
349
  rescue => e
287
- if (e.kind_of? NoMethodError) && (message.operation == :configure || message.operation == :request)
350
+ if (e.kind_of? OmfRc::UnknownPropertyError) && (message.operation == :configure || message.operation == :request)
288
351
  msg = "Cannot #{message.operation} unknown property "+
289
352
  "'#{message.read_element("//property")}' for resource '#{type}'"
290
353
  logger.warn msg
291
- raise OmfRc::MessageProcessError.new(context_id, obj.uid, msg)
354
+ raise OmfRc::MessageProcessError.new(message.context_id, inform_to_address(obj, message.publish_to), msg)
292
355
  else
293
356
  logger.error e.message
294
357
  logger.error e.backtrace.join("\n")
295
- raise OmfRc::MessageProcessError.new(context_id, obj.uid, e.message)
358
+ raise OmfRc::MessageProcessError.new(message.context_id, inform_to_address(obj, message.publish_to), e.message)
296
359
  end
297
360
  end
298
361
  end