omf_rc 6.0.0.pre.5 → 6.0.0.pre.6
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/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
@@ -0,0 +1,164 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2012 National ICT Australia (NICTA), Australia
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#
|
22
|
+
|
23
|
+
#
|
24
|
+
# This module defines a Utility with some common work blocks that handle the
|
25
|
+
# installation of software on a given OS platform
|
26
|
+
#
|
27
|
+
module OmfRc::Util::PlatformTools
|
28
|
+
include OmfRc::ResourceProxyDSL
|
29
|
+
|
30
|
+
utility :common_tools
|
31
|
+
|
32
|
+
# This utility block logs attempts to detect the OS platform on which it is
|
33
|
+
# currently running. Right now it can recognise the following platform:
|
34
|
+
# - Ubuntu (by looking for an Ubuntu string in /etc/*release files)
|
35
|
+
# - Fedora (by looking for a Fedora string in /etc/*release files)
|
36
|
+
#
|
37
|
+
# Further methods and OS platform may be supported later
|
38
|
+
#
|
39
|
+
# [Symbol] either :unknown | :ubuntu | :fedora
|
40
|
+
#
|
41
|
+
work('detect_platform') do
|
42
|
+
r = `cat /etc/*release`.upcase
|
43
|
+
platform = :unknown
|
44
|
+
platform = :ubuntu if r.include?('UBUNTU')
|
45
|
+
platform = :fedora if r.include?('FEDORA')
|
46
|
+
platform
|
47
|
+
end
|
48
|
+
|
49
|
+
# This utility block logs attempts to validate if a given package name is
|
50
|
+
# a valid one or not. Right now it checks the following:
|
51
|
+
# - if the given pkg name is not nil
|
52
|
+
# - if the given pkg name has a size > 0
|
53
|
+
#
|
54
|
+
# Further checks may be implemented later
|
55
|
+
# (e.g. is the pkg provided by any known repository, etc...)
|
56
|
+
#
|
57
|
+
# @yieldparam [String] pkg_name the package name to check
|
58
|
+
#
|
59
|
+
# [Boolean] true or fals
|
60
|
+
#
|
61
|
+
work('valid_pkg_name') do |res, pkg_name|
|
62
|
+
valid_name = false
|
63
|
+
plat = res.detect_platform
|
64
|
+
logger.debug "Platform: '#{plat}' - Installing: '#{pkg_name}'"
|
65
|
+
valid_name = true unless pkg_name.nil? || (pkg_name.to_s.size == 0)
|
66
|
+
res.log_inform_error "Package name is not defined for "+
|
67
|
+
"platform: '#{plat}'. Abort install!" unless valid_name
|
68
|
+
valid_name
|
69
|
+
end
|
70
|
+
|
71
|
+
# This utility block install a package on an Ubuntu platform using
|
72
|
+
# the underlying apt-get tool
|
73
|
+
#
|
74
|
+
# @yieldparam [String] pkg_name the package name to install
|
75
|
+
#
|
76
|
+
work('install_ubuntu') do |res, pkg_name|
|
77
|
+
next false unless res.valid_pkg_name(pkg_name)
|
78
|
+
ExecApp.new("#{res.hrn.nil? ? res.uid : res.hrn}_INSTALL",
|
79
|
+
res,
|
80
|
+
"LANGUAGE='C' LANG='C' "+
|
81
|
+
"LC_ALL='C' DEBIAN_FRONTEND='noninteractive' "+
|
82
|
+
"apt-get install --reinstall --allow-unauthenticated -qq "+
|
83
|
+
"#{pkg_name}")
|
84
|
+
end
|
85
|
+
|
86
|
+
# This utility block install a package on an Fedora platform using
|
87
|
+
# the underlying yum tool
|
88
|
+
#
|
89
|
+
# @yieldparam [String] pkg_name the package name to install
|
90
|
+
#
|
91
|
+
work('install_fedora') do |res, pkg_name|
|
92
|
+
next false unless res.valid_pkg_name(pkg_name)
|
93
|
+
ExecApp.new("#{res.hrn.nil? ? res.uid : res.hrn}_INSTALL",
|
94
|
+
res,
|
95
|
+
"/usr/bin/yum -y install #{pkg_name}")
|
96
|
+
end
|
97
|
+
|
98
|
+
# This utility block install a software from a tarball archive. It first
|
99
|
+
# tries to download the tarball at a given URI (if it has not been
|
100
|
+
# downloaded earlier), then it unarchives it at the given install_path
|
101
|
+
#
|
102
|
+
# @yieldparam [String] pkg_name the package name to install
|
103
|
+
# @yieldparam [String] install_path the path where to install this package
|
104
|
+
#
|
105
|
+
work('install_tarball') do |res, pkg_name, install_path|
|
106
|
+
next false unless res.valid_pkg_name(pkg_name)
|
107
|
+
require 'net/http'
|
108
|
+
require 'uri'
|
109
|
+
require 'digest/md5'
|
110
|
+
|
111
|
+
file = "/tmp/#{File.basename(pkg_name)}"
|
112
|
+
if file.empty?
|
113
|
+
res.log_inform_error "Failed to parse URI '#{pkg_name}'. Abort install!"
|
114
|
+
next false
|
115
|
+
end
|
116
|
+
|
117
|
+
eTagFile = "#{file}.etag"
|
118
|
+
download = true
|
119
|
+
cmd = ""
|
120
|
+
remoteETag = nil
|
121
|
+
|
122
|
+
# get the ETag from the HTTP header
|
123
|
+
begin
|
124
|
+
uri = URI.parse(pkg_name)
|
125
|
+
result = Net::HTTP.start(uri.host, uri.port) do |http|
|
126
|
+
header = http.request_head(pkg_name)
|
127
|
+
remoteETag = header['etag']
|
128
|
+
end
|
129
|
+
rescue => err
|
130
|
+
res.log_inform_error "Failed to access URL '#{pkg_name}'"+
|
131
|
+
" (error: #{err}). Abort install!"
|
132
|
+
next false
|
133
|
+
end
|
134
|
+
|
135
|
+
# if we have the file and its ETag locally,
|
136
|
+
# compare it to the ETag of the remote file
|
137
|
+
if File.exists?(file) && File.exists?(eTagFile)
|
138
|
+
f=File.open(eTagFile,'r')
|
139
|
+
localETag=f.gets
|
140
|
+
f.close
|
141
|
+
download = false if remoteETag == localETag
|
142
|
+
end
|
143
|
+
|
144
|
+
# download the file & store the ETag if necessary
|
145
|
+
if download
|
146
|
+
logger.debug "Downloading '#{pkg_name}'"
|
147
|
+
# -m -nd overwrites existing files
|
148
|
+
cmd="wget -P /tmp -m -nd -q #{pkg_name};"
|
149
|
+
unless remoteETag.empty?
|
150
|
+
f=File.open(eTagFile,'w')
|
151
|
+
f.write remoteETag
|
152
|
+
f.close
|
153
|
+
end
|
154
|
+
else
|
155
|
+
logger.debug "Local file '#{file}' already exists and is "+
|
156
|
+
"identical to '#{pkg_name}'"
|
157
|
+
end
|
158
|
+
# Finally unarchive the file at the requested install path
|
159
|
+
cmd += "tar -C #{install_path} -xf #{file}"
|
160
|
+
id = "#{res.hrn.nil? ? res.uid : res.hrn}_INSTALL"
|
161
|
+
ExecApp.new(id, res, cmd, false)
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'hashie'
|
2
|
+
require 'cocaine'
|
3
|
+
|
4
|
+
module OmfRc::Util::Wpa
|
5
|
+
include OmfRc::ResourceProxyDSL
|
6
|
+
include Cocaine
|
7
|
+
|
8
|
+
# Initialise wpa related conf and pid location
|
9
|
+
#
|
10
|
+
work :init_wpa_conf_pid do |device|
|
11
|
+
device.property.wpa_conf = "/tmp/wpa.#{device.hrn}.conf"
|
12
|
+
device.property.wpa_pid = "/tmp/wpa.#{device.hrn}.pid"
|
13
|
+
end
|
14
|
+
|
15
|
+
work :wpasup do |device|
|
16
|
+
device.init_wpa_conf_pid
|
17
|
+
|
18
|
+
File.open(device.property.wpa_conf, "w") do |f|
|
19
|
+
f << "network={\n ssid=\"#{device.property.essid}\"\n scan_ssid=1\n key_mgmt=NONE\n}"
|
20
|
+
end
|
21
|
+
CommandLine.new("wpa_supplicant", "-B -P :wpa_pid -i:dev -c:wpa_conf",
|
22
|
+
:dev => device.hrn,
|
23
|
+
:wpa_conf => device.property.wpa_conf,
|
24
|
+
:wpa_pid => device.property.wpa_pid).run
|
25
|
+
end
|
26
|
+
|
27
|
+
work :stop_wpa do |device|
|
28
|
+
begin
|
29
|
+
File.open(device.property.wpa_pid,'r') do |f|
|
30
|
+
logger.debug "Stopping wpa supplicant at PID: #{device.property.wpa_pid}"
|
31
|
+
CommandLine.new("kill", "-9 :pid", :pid => f.read.chomp).run
|
32
|
+
end
|
33
|
+
|
34
|
+
CommandLine.new("rm", "-f :wpa_pid :wpa_conf",
|
35
|
+
:wpa_pid => device.property.wpa_pid,
|
36
|
+
:wpa_conf => device.property.wpa_conf).run
|
37
|
+
rescue => e
|
38
|
+
logger.warn "Failed to clean wpa supplicant and its related files '#{device.property.wpa_pid}' and '#{device.property.wpa_conf}'!"
|
39
|
+
logger.warn e.message
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/omf_rc/version.rb
CHANGED
data/omf_rc.gemspec
CHANGED
@@ -19,7 +19,9 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
21
|
# specify any dependencies here; for example:
|
22
|
-
s.add_development_dependency "minitest", "~> 2
|
22
|
+
s.add_development_dependency "minitest", "~> 3.2"
|
23
23
|
s.add_development_dependency "em-minitest-spec", "~> 1.1.1"
|
24
|
+
s.add_development_dependency "simplecov"
|
24
25
|
s.add_runtime_dependency "omf_common", "~> 6.0.0.pre"
|
26
|
+
s.add_runtime_dependency "cocaine", "~> 0.3.0"
|
25
27
|
end
|
@@ -0,0 +1,5 @@
|
|
1
|
+
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
|
2
|
+
link/ether 00:00:00:29:00:00 brd ff:ff:ff:ff:ff:ff
|
3
|
+
inet 192.168.1.124/24 brd 192.168.1.255 scope global wlan0
|
4
|
+
inet6 fe80::2677:3ff:fe29:4d5c/64 scope link
|
5
|
+
valid_lft forever preferred_lft forever
|
File without changes
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe OmfRc::MessageProcessError do
|
4
|
+
it "must be able to initialised" do
|
5
|
+
mpe = OmfRc::MessageProcessError.new('test_context_id', 'inform_to_address', 'error_messsage')
|
6
|
+
mpe.context_id.must_equal 'test_context_id'
|
7
|
+
mpe.inform_to.must_equal 'inform_to_address'
|
8
|
+
mpe.message.must_equal 'error_messsage'
|
9
|
+
mpe.must_be_kind_of StandardError
|
10
|
+
end
|
11
|
+
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'test_helper'
|
2
|
-
require 'mock_helper'
|
3
2
|
require 'omf_rc/resource_factory'
|
4
3
|
|
5
4
|
describe OmfRc::ResourceFactory do
|
@@ -17,5 +16,13 @@ describe OmfRc::ResourceFactory do
|
|
17
16
|
mock.request_nothing.must_equal mock.uid
|
18
17
|
mock.must_respond_to :configure_nothing
|
19
18
|
end
|
19
|
+
|
20
|
+
it "must be able to load addtional proxies from local folder" do
|
21
|
+
Dir.stub :[], ["non_exist_folder/test.rb"] do
|
22
|
+
proc do
|
23
|
+
OmfRc::ResourceFactory.load_addtional_resource_proxies("non_exist_folder")
|
24
|
+
end.must_raise LoadError
|
25
|
+
end
|
26
|
+
end
|
20
27
|
end
|
21
28
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'test_helper'
|
2
|
+
require 'em/minitest/spec'
|
2
3
|
require 'omf_rc/resource_factory'
|
3
4
|
|
4
5
|
include OmfRc::ResourceProxy
|
@@ -63,7 +64,9 @@ describe AbstractResource do
|
|
63
64
|
|
64
65
|
describe "when destroyed" do
|
65
66
|
it "must destroy itself together with any resources created by it" do
|
66
|
-
@node.
|
67
|
+
child = @node.create(:wifi, { hrn: 'default_wifi' })
|
68
|
+
@node.children.wont_be_empty
|
69
|
+
@node.release(child.uid)
|
67
70
|
@node.children.must_be_empty
|
68
71
|
end
|
69
72
|
end
|
@@ -81,4 +84,57 @@ describe AbstractResource do
|
|
81
84
|
@node.request_hrn.must_equal 'bob'
|
82
85
|
end
|
83
86
|
end
|
87
|
+
|
88
|
+
describe "when interacted with communication layer" do
|
89
|
+
include EM::MiniTest::Spec
|
90
|
+
|
91
|
+
before do
|
92
|
+
@client = Blather::Client.new
|
93
|
+
@stream = MiniTest::Mock.new
|
94
|
+
@stream.expect(:send, true, [Blather::Stanza])
|
95
|
+
@client.post_init @stream, Blather::JID.new('n@d/r')
|
96
|
+
@xmpp = Class.new { include OmfCommon::DSL::Xmpp }.new
|
97
|
+
end
|
98
|
+
|
99
|
+
it "must be able to send inform message" do
|
100
|
+
@node.comm.stub :publish, proc { |inform_to, message| message.valid?.must_equal true} do
|
101
|
+
@node.inform(:created, resource_id: 'bob', context_id: 'id', inform_to: 'topic')
|
102
|
+
@node.inform(:released, resource_id: 'bob', context_id: 'id', inform_to: 'topic')
|
103
|
+
@node.inform(:status, status: { key: 'value' }, context_id: 'id', inform_to: 'topic')
|
104
|
+
@node.inform(:created, resource_id: 'bob', context_id: 'id', inform_to: 'topic')
|
105
|
+
@node.inform(:warn, 'going to fail')
|
106
|
+
@node.inform(:error, 'failed')
|
107
|
+
@node.inform(:warn, Exception.new('going to fail'))
|
108
|
+
@node.inform(:error, Exception.new('failed'))
|
109
|
+
@node.inform(:failed, Exception.new('failed'))
|
110
|
+
end
|
111
|
+
|
112
|
+
lambda { @node.inform(:failed, 'bob') }.must_raise ArgumentError
|
113
|
+
lambda { @node.inform(:created, 'topic') }.must_raise ArgumentError
|
114
|
+
lambda { @node.inform(:status, 'topic') }.must_raise ArgumentError
|
115
|
+
end
|
116
|
+
|
117
|
+
it "must be able to connect & disconnect" do
|
118
|
+
Blather::Client.stub :new, @client do
|
119
|
+
Blather::Stream::Client.stub(:start, @client) do
|
120
|
+
@node = OmfRc::ResourceFactory.new(:node, { hrn: 'default_node', user: 'bob', password: 'pw', server: 'example.com'}, @xmpp)
|
121
|
+
@client.stub(:connected?, true) do
|
122
|
+
@node.connect
|
123
|
+
@node.comm.jid.inspect.must_equal "bob@example.com"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe "when request/configure property not pre-defined in proxy" do
|
131
|
+
it "must try property hash" do
|
132
|
+
@node.property[:bob] = "bob"
|
133
|
+
@node.request_bob.must_equal "bob"
|
134
|
+
@node.configure_bob("not_bob")
|
135
|
+
@node.request_bob.must_equal "not_bob"
|
136
|
+
proc { @node.request_bobs_cousin }.must_raise NoMethodError
|
137
|
+
proc { @node.bobs_cousin }.must_raise NoMethodError
|
138
|
+
end
|
139
|
+
end
|
84
140
|
end
|