omf_rc 6.0.0.pre.5 → 6.0.0.pre.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|