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

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