Class: RSpecSystem::NodeSet::Base Abstract
- Inherits:
-
Object
- Object
- RSpecSystem::NodeSet::Base
- Defined in:
- lib/rspec-system/node_set/base.rb
Overview
Subclass and override methods to create a new NodeSet variant.
Base class for a NodeSet driver. If you want to create a new driver, you should sub-class this and override all the methods below.
Direct Known Subclasses
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
Returns the value of attribute config.
-
#custom_prefabs_path ⇒ Object
readonly
Returns the value of attribute custom_prefabs_path.
-
#destroy ⇒ Object
readonly
Returns the value of attribute destroy.
-
#nodes ⇒ Object
readonly
Returns the value of attribute nodes.
-
#setname ⇒ Object
readonly
Returns the value of attribute setname.
Abstract Methods collapse
-
#configure ⇒ void
abstract
Configure nodes.
-
#connect ⇒ void
abstract
Connect nodes.
-
#initialize(setname, config, custom_prefabs_path, options) ⇒ Base
constructor
abstract
Create new NodeSet, populating necessary data structures.
-
#launch ⇒ void
abstract
Launch nodes.
-
#rcp(opts) ⇒ Boolean
abstract
Copy a file to the host in the NodeSet.
-
#run(opts) ⇒ Hash
abstract
Run a command on a host in the NodeSet.
-
#setup ⇒ void
Setup the NodeSet by starting all nodes.
-
#teardown ⇒ void
abstract
Shutdown the NodeSet by shutting down or pausing all nodes.
Common Methods collapse
-
#default_node ⇒ RSpecSystem::Node
Return default node.
-
#provider_type ⇒ Object
Return environment type.
-
#randmac ⇒ String
Return a random mac address.
-
#random_string(length = 50) ⇒ String
Return a random string of chars, used for temp dir creation.
-
#ssh_connect(opts = {}) ⇒ Net::SSH::Connection::Session
Connect via SSH in a resilient way.
-
#ssh_exec!(ssh, command) ⇒ Hash
Execute command via SSH.
-
#tmppath ⇒ String
Generates a random string for use in remote transfers.
Constructor Details
#initialize(setname, config, custom_prefabs_path, options) ⇒ Base
override for providing global storage and setup-level code
Create new NodeSet, populating necessary data structures.
18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/rspec-system/node_set/base.rb', line 18 def initialize(setname, config, custom_prefabs_path, ) @setname = setname @config = config @custom_prefabs_path = custom_prefabs_path @destroy = [:destroy] @nodes = {} config['nodes'].each do |k,v| @nodes[k] = RSpecSystem::Node.node_from_yaml(self, k, v, custom_prefabs_path) end end |
Instance Attribute Details
#config ⇒ Object (readonly)
Returns the value of attribute config.
7 8 9 |
# File 'lib/rspec-system/node_set/base.rb', line 7 def config @config end |
#custom_prefabs_path ⇒ Object (readonly)
Returns the value of attribute custom_prefabs_path.
9 10 11 |
# File 'lib/rspec-system/node_set/base.rb', line 9 def custom_prefabs_path @custom_prefabs_path end |
#destroy ⇒ Object (readonly)
Returns the value of attribute destroy.
11 12 13 |
# File 'lib/rspec-system/node_set/base.rb', line 11 def destroy @destroy end |
#nodes ⇒ Object (readonly)
Returns the value of attribute nodes.
10 11 12 |
# File 'lib/rspec-system/node_set/base.rb', line 10 def nodes @nodes end |
#setname ⇒ Object (readonly)
Returns the value of attribute setname.
8 9 10 |
# File 'lib/rspec-system/node_set/base.rb', line 8 def setname @setname end |
Instance Method Details
#configure ⇒ void
Override this method and provide your own configure code
This method returns an undefined value.
Configure nodes
This is the global configure method that sets up a node before tests are run, making sure any important preparation steps are executed.
-
fixup profile to stop using mesg to avoid extraneous noise
-
ntp synchronisation
-
hostname & hosts setup
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/rspec-system/node_set/base.rb', line 66 def configure nodes.each do |k,v| rs_storage = RSpec.configuration.rs_storage[:nodes][k] # Fixup profile to avoid noise if v.facts['osfamily'] == 'Debian' shell(:n => k, :c => "sed -i 's/^mesg n/# mesg n/' /root/.profile") end # Setup ntp if v.facts['osfamily'] == 'Debian' then shell(:n => k, :c => 'apt-get install -y ntpdate') elsif v.facts['osfamily'] == 'RedHat' then if v.facts['lsbmajdistrelease'] == '5' then shell(:n => k, :c => 'yum install -y ntp') else shell(:n => k, :c => 'yum install -y ntpdate') end end shell(:n => k, :c => 'ntpdate -u pool.ntp.org') # Grab IP address for host, if we don't already have one rs_storage[:ipaddress] ||= shell(:n => k, :c => "ip a|awk '/g/{print$2}' | cut -d/ -f1 | head -1").stdout.chomp # Configure local hostname and hosts file shell(:n => k, :c => "hostname #{k}") if v.facts['osfamily'] == 'Debian' then shell(:n => k, :c => "echo '#{k}' > /etc/hostname") end hosts = <<-EOS #{rs_storage[:ipaddress]} #{k} 127.0.0.1 #{k} localhost ::1 #{k} localhost EOS shell(:n => k, :c => "echo '#{hosts}' > /etc/hosts") # Display setup for diagnostics shell(:n => k, :c => 'cat /etc/hosts') shell(:n => k, :c => 'hostname') shell(:n => k, :c => 'hostname -f') end nil end |
#connect ⇒ void
Override this method and provide your own connect code
This method returns an undefined value.
Connect nodes
51 52 53 |
# File 'lib/rspec-system/node_set/base.rb', line 51 def connect raise RuntimeError "Unimplemented method #connect" end |
#default_node ⇒ RSpecSystem::Node
Return default node
169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/rspec-system/node_set/base.rb', line 169 def default_node dn = config['default_node'] if dn.nil? if nodes.length == 1 dn = nodes.first[1] return dn else raise "No default node" end else return nodes[dn] end end |
#launch ⇒ void
Override this method and provide your own launch code
This method returns an undefined value.
Launch nodes
43 44 45 |
# File 'lib/rspec-system/node_set/base.rb', line 43 def launch raise RuntimeError "Unimplemented method #launch" end |
#provider_type ⇒ Object
Return environment type
162 163 164 |
# File 'lib/rspec-system/node_set/base.rb', line 162 def provider_type self.class::PROVIDER_TYPE end |
#randmac ⇒ String
Return a random mac address
286 287 288 |
# File 'lib/rspec-system/node_set/base.rb', line 286 def randmac "080027" + (1..3).map{"%0.2X"%rand(256)}.join end |
#random_string(length = 50) ⇒ String
Return a random string of chars, used for temp dir creation
186 187 188 189 |
# File 'lib/rspec-system/node_set/base.rb', line 186 def random_string(length = 50) o = [('a'..'z'),('A'..'Z')].map{|i| i.to_a}.flatten (0...length).map{ o[rand(o.length)] }.join end |
#rcp(opts) ⇒ Boolean
Override this method providing your own file transfer code
Copy a file to the host in the NodeSet.
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/rspec-system/node_set/base.rb', line 141 def rcp(opts) dest = opts[:d].name source = opts[:sp] dest_path = opts[:dp] # Do the copy and print out results for debugging ssh = RSpec.configuration.rs_storage[:nodes][dest][:ssh] begin ssh.scp.upload! source.to_s, dest_path.to_s, :recursive => true rescue => e log.error("Error with scp of file #{source} to #{dest}:#{dest_path}") raise e end true end |
#run(opts) ⇒ Hash
Override this method providing your own shell running code
Run a command on a host in the NodeSet.
125 126 127 128 129 130 131 |
# File 'lib/rspec-system/node_set/base.rb', line 125 def run(opts) dest = opts[:n].name cmd = opts[:c] ssh = RSpec.configuration.rs_storage[:nodes][dest][:ssh] ssh_exec!(ssh, cmd) end |
#setup ⇒ void
This method returns an undefined value.
Setup the NodeSet by starting all nodes.
33 34 35 36 37 |
# File 'lib/rspec-system/node_set/base.rb', line 33 def setup launch connect configure end |
#ssh_connect(opts = {}) ⇒ Net::SSH::Connection::Session
Connect via SSH in a resilient way
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/rspec-system/node_set/base.rb', line 208 def ssh_connect(opts = {}) ssh_sleep = RSpec.configuration.rs_ssh_sleep ssh_tries = RSpec.configuration.rs_ssh_tries ssh_timeout = RSpec.configuration.rs_ssh_timeout tries = 0 begin timeout(ssh_timeout) do output << bold(color("localhost$", :green)) << " ssh -l #{opts[:user]} #{opts[:host]}\n" Net::SSH.start(opts[:host], opts[:user], opts[:net_ssh_options]) end rescue Timeout::Error, SystemCallError, Net::SSH::Exception, SocketError => e tries += 1 output << e. << "\n" if tries < ssh_tries log.info("Sleeping for #{ssh_sleep} seconds then trying again ...") sleep ssh_sleep retry else log.error("Inability to connect to host, already tried #{tries} times, throwing exception") raise e end end end |
#ssh_exec!(ssh, command) ⇒ Hash
Execute command via SSH.
A special version of exec! from Net::SSH that returns exit code and exit signal as well. This method is blocking.
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
# File 'lib/rspec-system/node_set/base.rb', line 241 def ssh_exec!(ssh, command) r = { :stdout => '', :stderr => '', :exit_code => nil, :exit_signal => nil, } ssh.open_channel do |channel| channel.exec(command) do |ch, success| unless success abort "FAILED: couldn't execute command (ssh.channel.exec)" end channel.on_data do |ch,data| d = data output << d r[:stdout]+=d end channel.on_extended_data do |ch,type,data| d = data output << d r[:stderr]+=d end channel.on_request("exit-status") do |ch,data| c = data.read_long output << bold("Exit code:") << " #{c}\n" r[:exit_code] = c end channel.on_request("exit-signal") do |ch, data| s = data.read_string output << bold("Exit signal:") << " #{s}\n" r[:exit_signal] = s end end end ssh.loop r end |
#teardown ⇒ void
Override this method and provide your own node teardown code
This method returns an undefined value.
Shutdown the NodeSet by shutting down or pausing all nodes.
116 117 118 |
# File 'lib/rspec-system/node_set/base.rb', line 116 def teardown raise RuntimeError "Unimplemented method #teardown" end |
#tmppath ⇒ String
Very Linux dependant, probably need to consider OS X and Windows at least.
Generates a random string for use in remote transfers.
196 197 198 |
# File 'lib/rspec-system/node_set/base.rb', line 196 def tmppath '/tmp/' + random_string end |