omf_rc 6.0.0.pre.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Rakefile +16 -0
- data/bin/omf_rc +64 -0
- data/config/omf_rc.yml +70 -0
- data/integration_test/omf_rc/resource_proxy/app_spec.rb +25 -0
- data/integration_test/omf_rc/resource_proxy/interface_spec.rb +26 -0
- data/integration_test/omf_rc/resource_proxy/mock_spec.rb +58 -0
- data/integration_test/omf_rc/resource_proxy/node_spec.rb +26 -0
- data/integration_test/omf_rc/resource_proxy/wifi_spec.rb +30 -0
- data/integration_test/test_helper.rb +5 -0
- data/lib/omf_rc/deferred_process.rb +20 -0
- data/lib/omf_rc/message_process_error.rb +11 -0
- data/lib/omf_rc/resource_factory.rb +74 -0
- data/lib/omf_rc/resource_proxy/abstract_resource.rb +257 -0
- data/lib/omf_rc/resource_proxy/interface.rb +48 -0
- data/lib/omf_rc/resource_proxy/mock.rb +16 -0
- data/lib/omf_rc/resource_proxy/node.rb +17 -0
- data/lib/omf_rc/resource_proxy/wifi.rb +8 -0
- data/lib/omf_rc/resource_proxy_dsl.rb +170 -0
- data/lib/omf_rc/util/iw.rb +22 -0
- data/lib/omf_rc/util/mock.rb +27 -0
- data/lib/omf_rc/util/mod.rb +23 -0
- data/lib/omf_rc/util/package.rb +17 -0
- data/lib/omf_rc/version.rb +3 -0
- data/lib/omf_rc.rb +6 -0
- data/omf_rc.gemspec +25 -0
- data/test/omf_rc/deferred_process_spec.rb +39 -0
- data/test/omf_rc/resource_factory_spec.rb +18 -0
- data/test/omf_rc/resource_proxy/abstract_resource_spec.rb +82 -0
- data/test/omf_rc/resource_proxy_dsl_spec.rb +43 -0
- data/test/test_helper.rb +11 -0
- metadata +128 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
|
4
|
+
task :default => :test
|
5
|
+
|
6
|
+
Rake::TestTask.new do |t|
|
7
|
+
t.libs << 'test'
|
8
|
+
t.pattern = "test/**/*_spec.rb"
|
9
|
+
t.verbose = true
|
10
|
+
end
|
11
|
+
|
12
|
+
Rake::TestTask.new(:integration) do |t|
|
13
|
+
t.libs << 'integration_test'
|
14
|
+
t.pattern = "integration_test/**/*_spec.rb"
|
15
|
+
t.verbose = true
|
16
|
+
end
|
data/bin/omf_rc
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "optparse"
|
4
|
+
require 'omf_common'
|
5
|
+
require 'omf_rc'
|
6
|
+
require 'omf_rc/resource_factory'
|
7
|
+
$stdout.sync = true
|
8
|
+
|
9
|
+
options = {
|
10
|
+
uid: 'interlagos'
|
11
|
+
}
|
12
|
+
|
13
|
+
executable_name = File.basename($PROGRAM_NAME)
|
14
|
+
|
15
|
+
option_parser = OptionParser.new do |opts|
|
16
|
+
opts.banner = "usage: #{executable_name} [options]"
|
17
|
+
|
18
|
+
opts.on("-u USER", "Username") do |user|
|
19
|
+
options[:user] = user
|
20
|
+
end
|
21
|
+
|
22
|
+
opts.on("-p PASSWORD", "Password") do |password|
|
23
|
+
options[:password] = password
|
24
|
+
end
|
25
|
+
|
26
|
+
opts.on("-s SERVER", "XMPP server") do |server|
|
27
|
+
options[:server] = server
|
28
|
+
end
|
29
|
+
|
30
|
+
opts.on("-n NODE", "PubSub node to create, also becomes the uid of the resource") do |node|
|
31
|
+
options[:uid] = node
|
32
|
+
end
|
33
|
+
|
34
|
+
opts.on("-d", "--debug", "Debug mode") do
|
35
|
+
options[:debug] = true
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
begin
|
40
|
+
option_parser.parse!
|
41
|
+
rescue => e
|
42
|
+
puts e.message
|
43
|
+
puts ""
|
44
|
+
puts option_parser.help
|
45
|
+
exit(1)
|
46
|
+
end
|
47
|
+
|
48
|
+
unless options[:server] && options[:user] && options[:server]
|
49
|
+
puts option_parser.help
|
50
|
+
exit(1)
|
51
|
+
end
|
52
|
+
|
53
|
+
Logging.logger.root.level = :debug if options[:debug]
|
54
|
+
Blather.logger = logger
|
55
|
+
|
56
|
+
OmfRc::ResourceFactory.load_default_resource_proxies
|
57
|
+
|
58
|
+
EM.run do
|
59
|
+
node = OmfRc::ResourceFactory.new(:node, options)
|
60
|
+
node.connect
|
61
|
+
|
62
|
+
trap(:INT) { node.disconnect }
|
63
|
+
trap(:TERM) { node.disconnect }
|
64
|
+
end
|
data/config/omf_rc.yml
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# This is an example configuration for the Resource Controller at NICTA
|
2
|
+
#
|
3
|
+
# NOTE: use only 'spaces' to indent !
|
4
|
+
# ('tab' indents are not supported by the ruby yaml parser used to read this file)
|
5
|
+
#
|
6
|
+
---
|
7
|
+
:rcontroller:
|
8
|
+
# Communication settings
|
9
|
+
:communicator:
|
10
|
+
|
11
|
+
# Interface to the control network from which this resource can be
|
12
|
+
# controlled & managed
|
13
|
+
:control_if: 'control'
|
14
|
+
|
15
|
+
# set this to true or false if you want to enable or disable signature checks and message signing
|
16
|
+
:authenticate_messages: false
|
17
|
+
# your RSA/DSA SSH private key file
|
18
|
+
:private_key: '/etc/omf-resctl-5.4/id_rsa'
|
19
|
+
# directory holding the public keys of your OMF peers
|
20
|
+
:public_key_dir: '/etc/omf-resctl-5.4/peer_keys'
|
21
|
+
|
22
|
+
:type: 'xmpp'
|
23
|
+
:xmpp:
|
24
|
+
# Address of the PubSub server to use as gateway for PubSub communication
|
25
|
+
:pubsub_gateway: 'norbit.npc.nicta.com.au'
|
26
|
+
#:pubsub_port: 5222
|
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
|
29
|
+
# the same server as the 'pubsub_gateway'
|
30
|
+
#:pubsub_domain: 10.0.0.200
|
31
|
+
# The following 'home_pubsub_user' and 'home_pubsub_pwd' are optional
|
32
|
+
# RC will create a unique user/pwd for itself if this is not provided
|
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
|
35
|
+
# your client to connect to your pubsub server)
|
36
|
+
#:pubsub_user: 'my_RC_name'
|
37
|
+
#:pubsub_pwd: 'my_RC_password'
|
38
|
+
# set this to "true" if you have a DNS SRV record pointing to the
|
39
|
+
# real pubsub server hostname
|
40
|
+
:pubsub_use_dnssrv: false
|
41
|
+
|
42
|
+
# Agent settings
|
43
|
+
:agent:
|
44
|
+
|
45
|
+
# Name (i.e. unique HRN ID) of this resource
|
46
|
+
# Or this could also be passed as a command line parameter "--name"
|
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,
|
49
|
+
# currently we support the values: %hostname%, %macaddr%, %fqdn%
|
50
|
+
# For example, if you use "some_prefix.%hostname%.some_suffix"
|
51
|
+
# Then if your hostname is 'node1', then your RC name will be
|
52
|
+
# 'some_prefix.node1.some_suffix'
|
53
|
+
# %macaddr% is replaced with the MAC address of the control interface
|
54
|
+
# %fqdn% is the fully qualified hostname (incl. domain part)
|
55
|
+
:name: 'omf.nicta.%hostname%'
|
56
|
+
|
57
|
+
# Name (i.e. unique HRN ID) of the slice to which this resource is assigned
|
58
|
+
:slice: default_slice
|
59
|
+
|
60
|
+
# shrink the filesystem size before saving an image
|
61
|
+
# grow the filesystem to match the disk size after loading an image
|
62
|
+
# enabling this may slow down load/save significantly
|
63
|
+
:resizefs: false
|
64
|
+
|
65
|
+
# Mote settings
|
66
|
+
# Uncomment and set the following parameters if this resource has
|
67
|
+
# a Mote device attached to it
|
68
|
+
#:mote:
|
69
|
+
#:moteport: /dev/ttyUSB0
|
70
|
+
#:motetype: telosb
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'omf_rc/resource_proxy'
|
3
|
+
|
4
|
+
include OmfRc::ResourceProxy
|
5
|
+
|
6
|
+
describe App do
|
7
|
+
before do
|
8
|
+
@resource = AbstractResource.new(properties: { pubsub: "mytestbed.net" })
|
9
|
+
@app1 = @resource.create(:type => 'app', :uid => 'zathura')
|
10
|
+
@app2 = @resource.create(:type => 'app', :uid => 'bob')
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "when configured with properties" do
|
14
|
+
it "must run the underline commands" do
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "when properties requested" do
|
19
|
+
it "must return an array with actual properties" do
|
20
|
+
@resource.request([:version], {:uid => 'zathura'}).first.version.must_match /[\d|\.|-]+/
|
21
|
+
@resource.request([:version], {:uid => 'bob'}).first.version.must_be_nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'omf_rc/resource_proxy'
|
3
|
+
|
4
|
+
include OmfRc::ResourceProxy
|
5
|
+
|
6
|
+
describe Interface do
|
7
|
+
before do
|
8
|
+
@resource = AbstractResource.new(properties: { pubsub: "mytestbed.net" })
|
9
|
+
@interface = @resource.create(:type => 'interface', :uid => 'eth0')
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "when configured with properties" do
|
13
|
+
it "must run the underline commands" do
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "when properties requested" do
|
18
|
+
it "must return an array with actual properties" do
|
19
|
+
@resource.request([:mac, :ip], {:type => 'interface'}).each do |interface|
|
20
|
+
interface.mac.must_match /([\da-fA-F]+:){5}[\da-fA-F]+/
|
21
|
+
interface.ip.must_match /([.\d]+\.){3}[.\d]+/
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'omf_rc/resource_factory'
|
3
|
+
|
4
|
+
include OmfRc::ResourceProxy
|
5
|
+
|
6
|
+
module OmfRc::Util::UMock
|
7
|
+
include OmfRc::ResourceProxyDSL
|
8
|
+
|
9
|
+
register_utility :u_mock
|
10
|
+
|
11
|
+
register_configure :very_important_property do
|
12
|
+
raise StandardError, 'We just did something very important, I need your attention'
|
13
|
+
end
|
14
|
+
|
15
|
+
register_request :very_important_property do
|
16
|
+
"Very important property's value"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module OmfRc::ResourceProxy::Mock
|
21
|
+
include OmfRc::ResourceProxyDSL
|
22
|
+
|
23
|
+
register_proxy :mock
|
24
|
+
|
25
|
+
utility :u_mock
|
26
|
+
|
27
|
+
register_bootstrap do
|
28
|
+
logger.debug 'I am starting up, but have nothing to do there'
|
29
|
+
end
|
30
|
+
|
31
|
+
register_cleanup do
|
32
|
+
logger.debug 'I am shutting down, but have nothing to do there'
|
33
|
+
end
|
34
|
+
|
35
|
+
def test
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe Mock do
|
40
|
+
before do
|
41
|
+
@resource = OmfRc::ResourceFactory.new(:mock, :uid => 'suzuka', :properties => {:mock_property => "test"})
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "when child resource with a known type" do
|
45
|
+
it "must load methods from related module correctly" do
|
46
|
+
@resource.create(:mock, uid: 'mock') do |mock|
|
47
|
+
mock.must_respond_to :test
|
48
|
+
mock.must_respond_to :configure_very_important_property
|
49
|
+
mock.must_respond_to :request_very_important_property
|
50
|
+
proc { mock.configure_very_important_property('test') }.must_raise StandardError
|
51
|
+
mock.request_very_important_property do |value|
|
52
|
+
value.must_equal "Very important property's value"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'omf_rc/resource_proxy'
|
3
|
+
|
4
|
+
include OmfRc::ResourceProxy
|
5
|
+
|
6
|
+
describe Node do
|
7
|
+
before do
|
8
|
+
@resource = AbstractResource.new(properties: { pubsub: "mytestbed.net" })
|
9
|
+
@node = @resource.create(:type => 'node', :uid => 'monaco')
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "when configured with properties" do
|
13
|
+
it "must run the underline commands" do
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "when properties requested" do
|
18
|
+
it "must return an array with actual properties" do
|
19
|
+
@resource.request([:devices], {:uid => 'monaco'}).first.devices.each do |device|
|
20
|
+
device.type.wont_be_nil
|
21
|
+
device.name.wont_be_nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'omf_rc/resource_proxy'
|
3
|
+
|
4
|
+
include OmfRc::ResourceProxy
|
5
|
+
|
6
|
+
describe Wifi do
|
7
|
+
before do
|
8
|
+
@resource = AbstractResource.new(properties: { pubsub: "mytestbed.net" })
|
9
|
+
@wifi = @resource.create(:type => 'wifi', :uid => 'wlan0')
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "when configured with properties" do
|
13
|
+
it "must run the underline commands" do
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "when properties requested" do
|
18
|
+
it "must return an array with actual properties" do
|
19
|
+
@resource.request([:ssid, :freq, :rx, :tx, :signal, :tx_bitrate], {:type => 'wifi'}).each do |wifi|
|
20
|
+
wifi.ssid.wont_be_nil
|
21
|
+
wifi.freq.wont_be_nil
|
22
|
+
wifi.rx.wont_be_nil
|
23
|
+
wifi.tx.wont_be_nil
|
24
|
+
wifi.signal.wont_be_nil
|
25
|
+
wifi.tx_bitrate.wont_be_nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# To be used for handling long running processes
|
2
|
+
#
|
3
|
+
class OmfRc::DeferredProcess
|
4
|
+
include EM::Deferrable
|
5
|
+
|
6
|
+
# Pass a block of long running process
|
7
|
+
#
|
8
|
+
def fire(&block)
|
9
|
+
raise ArgumentError, "Missing code block to be executed" if block.nil?
|
10
|
+
|
11
|
+
EM.defer do
|
12
|
+
begin
|
13
|
+
result = block.call
|
14
|
+
succeed result
|
15
|
+
rescue => e
|
16
|
+
fail e
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Error during message processing, include message related information context_id and inform_to, for publishing errors to pubsub server
|
2
|
+
#
|
3
|
+
class OmfRc::MessageProcessError < StandardError
|
4
|
+
attr_reader :context_id, :inform_to
|
5
|
+
|
6
|
+
def initialize(context_id, inform_to, msg = nil)
|
7
|
+
@context_id = context_id
|
8
|
+
@inform_to = inform_to
|
9
|
+
super(msg)
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'omf_common'
|
2
|
+
require 'securerandom'
|
3
|
+
require 'hashie'
|
4
|
+
require 'omf_rc/resource_proxy_dsl'
|
5
|
+
require 'omf_rc/resource_proxy/abstract_resource'
|
6
|
+
|
7
|
+
# Factory class for managing available proxies and creating new resource proxy instances
|
8
|
+
#
|
9
|
+
class OmfRc::ResourceFactory
|
10
|
+
# List of registered resource proxies
|
11
|
+
@@proxy_list = []
|
12
|
+
# List of registered utilities
|
13
|
+
@@utility_list = []
|
14
|
+
|
15
|
+
# By default, we use xmpp_blather dsl, which based on blather
|
16
|
+
DEFAULT_OPTS = {
|
17
|
+
dsl: 'xmpp_blather',
|
18
|
+
pubsub_host: 'pubsub'
|
19
|
+
}
|
20
|
+
|
21
|
+
class << self
|
22
|
+
# Factory method to initiate new resource proxy
|
23
|
+
#
|
24
|
+
# @param (see OmfRc::ResourceProxy::AbstractResource#initialize)
|
25
|
+
#
|
26
|
+
# @see OmfRc::ResourceProxy::AbstractResource
|
27
|
+
def new(type, opts = nil, comm = nil, &block)
|
28
|
+
raise ArgumentError, "Resource type not found: #{type.to_s}" unless @@proxy_list.include?(type)
|
29
|
+
type = type.to_s
|
30
|
+
opts = opts ? DEFAULT_OPTS.merge(opts) : DEFAULT_OPTS
|
31
|
+
# Create a new instance of abstract resource
|
32
|
+
resource = OmfRc::ResourceProxy::AbstractResource.new(type, opts, comm)
|
33
|
+
# Then extend this instance with relevant module identified by type
|
34
|
+
resource.extend("OmfRc::ResourceProxy::#{type.camelcase}".constant)
|
35
|
+
# Execute resource before_ready hook if any
|
36
|
+
resource.before_ready if resource.respond_to? :before_ready
|
37
|
+
resource
|
38
|
+
end
|
39
|
+
|
40
|
+
# Return the proxy list
|
41
|
+
def proxy_list
|
42
|
+
@@proxy_list
|
43
|
+
end
|
44
|
+
|
45
|
+
# Add a proxy to the list
|
46
|
+
def register_proxy(proxy)
|
47
|
+
@@proxy_list << proxy
|
48
|
+
end
|
49
|
+
|
50
|
+
# Return the utility list
|
51
|
+
def utility_list
|
52
|
+
@@utility_list
|
53
|
+
end
|
54
|
+
|
55
|
+
# Add a utility to the list
|
56
|
+
def register_utility(utility)
|
57
|
+
@@utility_list << utility
|
58
|
+
end
|
59
|
+
|
60
|
+
# Require files from default resource proxy library folder
|
61
|
+
#
|
62
|
+
def load_default_resource_proxies
|
63
|
+
Dir["#{File.dirname(__FILE__)}/resource_proxy/*.rb"].each do |file|
|
64
|
+
require "omf_rc/resource_proxy/#{File.basename(file).gsub(/\.rb/, '')}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def load_addtional_resource_proxies(folder)
|
69
|
+
Dir["#{folder}/*.rb"].each do |file|
|
70
|
+
require "#{folder}/#{File.basename(file).gsub(/\.rb/, '')}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|