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.
Files changed (45) hide show
  1. data/Rakefile +0 -6
  2. data/bin/omf_rc +2 -2
  3. data/lib/omf_rc/resource_factory.rb +10 -4
  4. data/lib/omf_rc/resource_proxy/abstract_resource.rb +120 -79
  5. data/lib/omf_rc/resource_proxy/generic_application.rb +471 -0
  6. data/lib/omf_rc/resource_proxy/net.rb +7 -0
  7. data/lib/omf_rc/resource_proxy/node.rb +33 -7
  8. data/lib/omf_rc/resource_proxy/openflow_slice.rb +79 -0
  9. data/lib/omf_rc/resource_proxy/openflow_slice_factory.rb +71 -0
  10. data/lib/omf_rc/resource_proxy/wlan.rb +20 -0
  11. data/lib/omf_rc/resource_proxy_dsl.rb +142 -8
  12. data/lib/omf_rc/util/common_tools.rb +61 -0
  13. data/lib/omf_rc/util/hostapd.rb +52 -0
  14. data/lib/omf_rc/util/ip.rb +28 -0
  15. data/lib/omf_rc/util/iw.rb +119 -6
  16. data/lib/omf_rc/util/mock.rb +2 -1
  17. data/lib/omf_rc/util/openflow_tools.rb +103 -0
  18. data/lib/omf_rc/util/platform_tools.rb +164 -0
  19. data/lib/omf_rc/util/wpa.rb +42 -0
  20. data/lib/omf_rc/version.rb +1 -1
  21. data/omf_rc.gemspec +3 -1
  22. data/test/fixture/ip/addr_show +5 -0
  23. data/test/fixture/iw/info +4 -0
  24. data/test/fixture/sys/class/ieee80211/phy0/device/uevent +6 -0
  25. data/test/fixture/sys/class/ieee80211/phy0/uevent +0 -0
  26. data/test/fixture/sys/class/net/eth0/device/uevent +6 -0
  27. data/test/fixture/sys/class/net/eth0/uevent +2 -0
  28. data/test/fixture/sys/class/net/wlan0/device/uevent +6 -0
  29. data/test/fixture/sys/class/net/wlan0/uevent +3 -0
  30. data/test/omf_rc/message_process_error_spec.rb +11 -0
  31. data/test/omf_rc/resource_factory_spec.rb +8 -1
  32. data/test/omf_rc/resource_proxy/abstract_resource_spec.rb +57 -1
  33. data/test/omf_rc/resource_proxy/generic_application_spec.rb +347 -0
  34. data/test/omf_rc/resource_proxy/mock_spec.rb +15 -0
  35. data/test/omf_rc/resource_proxy/node_spec.rb +32 -1
  36. data/test/omf_rc/resource_proxy_dsl_spec.rb +81 -10
  37. data/test/omf_rc/util/common_tools_spec.rb +30 -0
  38. data/test/omf_rc/util/ip_spec.rb +51 -0
  39. data/test/omf_rc/util/iw_spec.rb +136 -25
  40. data/test/omf_rc/util/mock_spec.rb +26 -0
  41. data/test/omf_rc/util/mod_spec.rb +8 -11
  42. data/test/test_helper.rb +11 -0
  43. metadata +62 -6
  44. data/lib/omf_rc/resource_proxy/wifi.rb +0 -8
  45. 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
@@ -1,3 +1,3 @@
1
1
  module OmfRc
2
- VERSION = "6.0.0.pre.5"
2
+ VERSION = "6.0.0.pre.6"
3
3
  end
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.11.3"
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
@@ -0,0 +1,4 @@
1
+ Interface wlan0
2
+ ifindex 3
3
+ type managed
4
+ wiphy 0
@@ -0,0 +1,6 @@
1
+ DRIVER=iwlwifi
2
+ PCI_CLASS=28000
3
+ PCI_ID=8086:4238
4
+ PCI_SUBSYS_ID=8086:1111
5
+ PCI_SLOT_NAME=0000:03:00.0
6
+ MODALIAS=pci:v00008086d00004238sv00008086sd00001111bc02sc80i00
File without changes
@@ -0,0 +1,6 @@
1
+ DRIVER=e1000e
2
+ PCI_CLASS=20000
3
+ PCI_ID=8086:1502
4
+ PCI_SUBSYS_ID=17AA:21CE
5
+ PCI_SLOT_NAME=0000:00:19.0
6
+ MODALIAS=pci:v00008086d00001502sv000017AAsd000021CEbc02sc00i00
@@ -0,0 +1,2 @@
1
+ INTERFACE=eth0
2
+ IFINDEX=2
@@ -0,0 +1,6 @@
1
+ DRIVER=iwlwifi
2
+ PCI_CLASS=28000
3
+ PCI_ID=8086:4238
4
+ PCI_SUBSYS_ID=8086:1111
5
+ PCI_SLOT_NAME=0000:03:00.0
6
+ MODALIAS=pci:v00008086d00004238sv00008086sd00001111bc02sc80i00
@@ -0,0 +1,3 @@
1
+ DEVTYPE=wlan
2
+ INTERFACE=wlan0
3
+ IFINDEX=3
@@ -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.release
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