PageRenderTime 47ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/omf/stress.rb

https://bitbucket.org/romoore/gnrs
Ruby | 524 lines | 368 code | 93 blank | 63 comment | 34 complexity | 5e76ac0c0410195867f4dd5889c42707 MD5 | raw file
  1. #!/bin/ruby
  2. #
  3. # Simple GNRS experiment that performs the tasks outlined in the project Wiki.
  4. # See <https://bitbucket.org/romoore/gnrs/wiki/Running%20an%20Experiment%20on%20Orbit>
  5. # for more details.
  6. #
  7. # Author: Robert Moore
  8. # Last Modified: Jan 4, 2013
  9. #
  10. # Runtime configuration of propertes can be effected like this:
  11. # omf exec simple.rb -- --prop1 value1 --prop2 value2
  12. # Import the GNRSNode class
  13. require ('./gnrs_node.rb')
  14. require ('./gnrs_config.rb')
  15. # Resources file location can be configured with:
  16. # --resourceFile /path/to/file.rb
  17. defProperty('resourceFile', './resources.rb', 'Experiment resources configuration')
  18. # Read the resources file and execute its code
  19. eval(File.new(property.resourceFile).read)
  20. # Global constants
  21. CLIENT_GRP_NAME = 'client'
  22. SERVER_GRP_NAME = 'server'
  23. # Initial work of configuring topology, groups, and readying for node "up"
  24. def doInitSetup
  25. # Check initial parameters, make sure everything is sane.
  26. success = checkParams
  27. if success != 0
  28. error "*** One or more parameters was invalid. See messages above for more details. ***"
  29. return success
  30. end
  31. serversMap = Hash.new
  32. clientsMap = Hash.new
  33. # Grab the imaged topology (successful nodes) and break them into groups
  34. info "## Selecting servers and clients from available nodes ##"
  35. success = defineGroups(serversMap, clientsMap)
  36. if success == 0
  37. info "\t#{serversMap.length} servers and #{clientsMap.length} clients available."
  38. else
  39. error "\tUnable to select nodes. Exiting."
  40. return success
  41. end
  42. info "## Defining OMF node groups ##"
  43. success = buildGroups(serversMap, clientsMap)
  44. if success == 0
  45. info "\tNode groups defined."
  46. else
  47. error "\tUnable to define groups. Exiting."
  48. return success
  49. end
  50. return success, serversMap, clientsMap
  51. end
  52. # Verify that the input parameters are sensible and won't cause any problems
  53. # later on in the experiment.
  54. def checkParams
  55. if property.numServers.to_s.to_i < 1
  56. error "Must define at least 1 server."
  57. return -1
  58. elsif property.numClients.to_s.to_i < 1
  59. error "Must define at least 1 client."
  60. return -1
  61. end
  62. return 0
  63. end # checkParams
  64. # Main function, used so we can "return" from the experiment early when
  65. # errors are detected.
  66. def doMainExperiment(serversMap, clientsMap)
  67. info "## Configuring node network interfaces ##"
  68. success = prepareNodes(serversMap, clientsMap)
  69. if success == 0
  70. info "\tNetwork configuration complete."
  71. else
  72. error "\tUnable to configure networking. Exiting."
  73. return;
  74. end
  75. if (property.disableDelay.to_s == "")
  76. info "## Preparing the delay modules ##"
  77. success = prepareDelayModule(serversMap, clientsMap, property.dataUrl, property.clickModule)
  78. if success == 0
  79. info "\tSuccessfully installed and configured delay module on all nodes."
  80. else
  81. error "\tUnable to configure delay module on one or more nodes. Exiting."
  82. return;
  83. end
  84. end
  85. info "## Installing configuration files ##"
  86. success = installConfigs(serversMap, clientsMap)
  87. if success == 0
  88. info "\tSuccessfully installed configuration files."
  89. else
  90. error "\tUnable to install configuration files."
  91. return;
  92. end
  93. info "## Launching servers ##"
  94. success = launchServers(serversMap)
  95. if success == 0
  96. info "\tSuccessfully launched servers."
  97. else
  98. error "\tUnable to launch servers."
  99. return;
  100. end
  101. info "## Waiting 5 seconds for servers to start ##"
  102. wait property.miniWait
  103. info "## Loading GUIDs ##"
  104. success = loadGUIDs(clientsMap)
  105. if success == 0
  106. info "\tSuccessfully launched clients."
  107. else
  108. error "\tUnable to launch clients."
  109. stopServers(serversMap)
  110. return;
  111. end
  112. info "Press <RETURN> when all GUIDs are loaded."
  113. wait property.clientWait
  114. info "## Generating lookups ##"
  115. success = genLookups(clientsMap)
  116. if success == 0
  117. info "\tSuccessfully launched clients."
  118. else
  119. error "\tUnable to launch clients."
  120. stopServers(serversMap)
  121. return;
  122. end
  123. info "Press <RETURN> when all lookups are complete."
  124. wait property.clientWait
  125. info "## Shutting down servers ##"
  126. success = stopServers(serversMap)
  127. if success == 0
  128. info "\tTerminated servers successfully."
  129. else
  130. error "\tUnable to terminate servers."
  131. return
  132. end
  133. end # main
  134. def defineGroups(serversMap, clientsMap)
  135. successTopology = Topology["#{property.topology}"]
  136. nodelist = successTopology.nodes
  137. totalNodes = nodelist.size
  138. if totalNodes < (property.numServers + property.numClients)
  139. puts "Not enough nodes available. Need #{property.numServers + property.numClients}, but only have #{totalNodes}"
  140. puts "Consider using a smaller number of servers (numServers) or clients (numClients)."
  141. return -1
  142. end
  143. asMap = Hash.new
  144. for serverCount in 1..property.numServers
  145. node = GNRSNode.new
  146. node.hostname = nodelist.pop().to_s
  147. node.asNumber = serverCount
  148. node.ipAddress = "192.168.1.#{serverCount + 1}"
  149. node.port = "5001"
  150. serversMap[node.hostname] = node
  151. asMap[node.asNumber] = node
  152. end
  153. info "Servers:"
  154. serversMap.each do |key, value|
  155. info "\t#{key} => #{value}"
  156. end
  157. for clientCount in 1..property.numClients
  158. node = GNRSNode.new
  159. node.hostname = nodelist.pop().to_s
  160. node.asNumber = clientCount
  161. node.ipAddress = "192.168.1.#{clientCount + 101}"
  162. node.port = "4001"
  163. node.server = asMap[node.asNumber]
  164. # Randomly pick a server for this client
  165. if node.server.nil?
  166. node.asNumber = rand(property.numServers.to_s.to_i)+1
  167. node.server = asMap[node.asNumber]
  168. end
  169. clientsMap[node.hostname] = node
  170. end
  171. info "Clients:"
  172. clientsMap.each do |key, value|
  173. info "\t#{key} => #{value}"
  174. end
  175. return 0
  176. end # defineGroups
  177. def buildGroups(serversMap, clientsMap)
  178. # Split the nodes into servers and clients
  179. serversMap.each_value do |node|
  180. grp = defGroup(node.hostname, node.hostname)
  181. node.group = grp
  182. end
  183. # Now the clients
  184. clientsMap.each_value do |node|
  185. grp = defGroup(node.hostname, node.hostname)
  186. node.group = grp
  187. end
  188. return 0
  189. end
  190. def prepareNodes(serversMap, clientsMap)
  191. serversMap.each_value { | node |
  192. info "Setting IP of #{node.hostname} to #{node.ipAddress}"
  193. node.group.net.e0.ip = node.ipAddress
  194. }
  195. clientsMap.each_value { | node |
  196. info "Setting IP of #{node.hostname} to #{node.ipAddress}"
  197. node.group.net.e0.ip = node.ipAddress
  198. }
  199. return 0
  200. end # prepareNodes
  201. def prepareDelayModule(serversMap, clientsMap, baseUrl, clickScript)
  202. # Download delay module click script
  203. info "Downloading delay module script"
  204. cmd = "#{property.wget} #{property.scriptUrl}/#{property.clickModule}"
  205. serversMap.each_value { |node|
  206. node.group.exec(cmd)
  207. }
  208. clientsMap.each_value { |node|
  209. node.group.exec(cmd)
  210. }
  211. wait property.miniWait
  212. # Install the delay module click script
  213. info "Installing Click delay module"
  214. cmd = "#{property.clickInstall} -u #{property.clickModule}"
  215. serversMap.each_value { |node|
  216. node.group.exec(cmd)
  217. }
  218. clientsMap.each_value { |node|
  219. node.group.exec(cmd)
  220. }
  221. wait property.miniWait
  222. # Download and install the delay module configuration file
  223. info "Retrieving node delay configurations"
  224. server = "#{property.wget} #{property.dataUrl}/#{property.delayConfigServer}"
  225. client = "#{property.wget} #{property.dataUrl}/#{property.delayConfigClient}"
  226. serversMap.each_value { |node|
  227. node.group.exec(server.gsub(/XxX/,node.asNumber.to_s))
  228. }
  229. clientsMap.each_value { |node|
  230. node.group.exec(client.gsub(/XxX/,node.asNumber.to_s))
  231. }
  232. wait property.miniWait
  233. info "Installing node delay configurations"
  234. client = "cp #{property.delayConfigClient} /click/delayMod/config"
  235. server = "cp #{property.delayConfigServer} /click/delayMod/config"
  236. serversMap.each_value { |node|
  237. node.group.exec(server.gsub(/XxX/,node.asNumber.to_s))
  238. }
  239. clientsMap.each_value { |node|
  240. node.group.exec(client.gsub(/XxX/,node.asNumber.to_s))
  241. }
  242. wait property.miniWait
  243. # Delete any files we downloaded and no longer need
  244. info "Cleaning up temporary files"
  245. serversMap.each_value { |node|
  246. cmd = "rm #{property.clickModule}"
  247. node.group.exec(cmd)
  248. cmd = "rm #{property.delayConfigServer}".gsub(/XxX/,node.asNumber.to_s)
  249. node.group.exec(cmd)
  250. }
  251. clientsMap.each_value { |node|
  252. cmd = "rm #{property.clickModule}"
  253. node.group.exec(cmd)
  254. cmd = "rm #{property.delayConfigClient}".gsub(/XxX/,node.asNumber.to_s)
  255. node.group.exec(cmd)
  256. }
  257. return 0
  258. end # prepareDelayModule
  259. def installConfigs(serversMap, clientsMap)
  260. info "Creating required directories"
  261. mkVar = "mkdir -p /var/gnrs/stats"
  262. mkEtc = "mkdir -p /etc/gnrs"
  263. mkBin = "mkdir -p /usr/local/bin/gnrs/"
  264. serversMap.each_value { |node|
  265. node.group.exec(mkVar)
  266. node.group.exec(mkEtc)
  267. node.group.exec(mkBin)
  268. }
  269. clientsMap.each_value { |node|
  270. node.group.exec(mkVar)
  271. node.group.exec(mkEtc)
  272. node.group.exec(mkBin)
  273. }
  274. wait property.microWait
  275. info "Creating server configuration files."
  276. serversMap.each_value { |node|
  277. # Main server config
  278. configContents = makeServerConfig(node)
  279. cmd = "echo '#{configContents}' >/etc/gnrs/server.xml"
  280. node.group.exec(cmd)
  281. # Networking config
  282. configContents = makeServerNetConfig(node)
  283. cmd = "echo '#{configContents}' >/etc/gnrs/net-ipv4_#{node.asNumber}.xml"
  284. node.group.exec(cmd)
  285. # Download static files
  286. # Binding file
  287. cmd = "#{property.wget} #{property.dataUrl}/#{property.bindingFile}"
  288. node.group.exec(cmd)
  289. # IPv4 Prefix File (BGP Table)
  290. cmd = "#{property.wget} #{property.dataUrl}/#{property.prefixIpv4}"
  291. node.group.exec(cmd)
  292. # BerkeleyDB Config
  293. cmd = "#{property.wget} #{property.scriptUrl}/#{property.serverBDB}"
  294. node.group.exec(cmd)
  295. # IPv4 Mapper Configuration
  296. cmd = "#{property.wget} #{property.scriptUrl}/#{property.mapIpv4}"
  297. node.group.exec(cmd)
  298. # Jar file
  299. cmd = "#{property.wget} #{property.scriptUrl}/#{property.jarFile}"
  300. node.group.exec(cmd)
  301. # GNRSD script
  302. cmd = "#{property.wget} #{property.scriptUrl}/#{property.gnrsd}"
  303. node.group.exec(cmd)
  304. # GNRSD Init script
  305. cmd = "#{property.wget} #{property.scriptUrl}/#{property.gnrsdInit}"
  306. node.group.exec(cmd)
  307. }
  308. info "Creating client configuration files."
  309. clientsMap.each_value { |node|
  310. # Main client config
  311. configContents = makeClientConfig(node,node.server)
  312. cmd = "echo '#{configContents}' >/etc/gnrs/client.xml"
  313. node.group.exec(cmd)
  314. # Download static files
  315. # Jar file
  316. cmd = "#{property.wget} #{property.scriptUrl}/#{property.jarFile}"
  317. node.group.exec(cmd)
  318. # GGen script
  319. cmd = "#{property.wget} #{property.scriptUrl}/#{property.ggen}"
  320. node.group.exec(cmd)
  321. # GBench script
  322. cmd = "#{property.wget} #{property.scriptUrl}/#{property.gbench}"
  323. node.group.exec(cmd)
  324. # Client trace file
  325. cmd = "#{property.wget} #{property.dataUrl}/#{property.clientTrace}".gsub(/XxX/,node.asNumber.to_s)
  326. node.group.exec(cmd)
  327. }
  328. wait property.miniWait
  329. info "Installing server files"
  330. # Install static files
  331. serversMap.each_value { |node|
  332. # Binding file
  333. cmd = "mv #{property.bindingFile} /etc/gnrs/"
  334. node.group.exec(cmd)
  335. # BerkeleyDB Config
  336. cmd = "mv #{property.serverBDB} /etc/gnrs/"
  337. node.group.exec(cmd)
  338. # IPv4 Mapper Configuration
  339. cmd = "mv #{property.mapIpv4} /etc/gnrs/"
  340. node.group.exec(cmd)
  341. # IPv4 Prefix File (BGP Table)
  342. cmd = "mv #{property.prefixIpv4} /etc/gnrs/"
  343. node.group.exec(cmd)
  344. # Jar file
  345. cmd = "mv #{property.jarFile} /usr/local/bin/gnrs/"
  346. node.group.exec(cmd)
  347. # GNRSD Script
  348. cmd = "chmod +x #{property.gnrsd}"
  349. node.group.exec(cmd)
  350. cmd = "mv #{property.gnrsd} /usr/local/bin/gnrs/"
  351. node.group.exec(cmd)
  352. # GNRSD Init script
  353. cmd = "chmod +x #{property.gnrsdInit}"
  354. node.group.exec(cmd)
  355. cmd = "mv #{property.gnrsdInit} /etc/init.d/gnrsd"
  356. node.group.exec(cmd)
  357. # Update rc.d scripts
  358. cmd = "#{property.updateRc} gnrsd stop 2 0 1 2 3 4 5 6 ."
  359. node.group.exec(cmd)
  360. }
  361. info "Installing client files"
  362. clientsMap.each_value { |node|
  363. # JAR file
  364. cmd = "mv #{property.jarFile} /usr/local/bin/gnrs/"
  365. node.group.exec(cmd)
  366. # GBench script
  367. cmd = "chmod +x #{property.gbench}"
  368. node.group.exec(cmd)
  369. cmd = "mv #{property.gbench} /usr/local/bin/gnrs/"
  370. node.group.exec(cmd)
  371. # GGen script
  372. cmd = "chmod +x #{property.ggen}"
  373. node.group.exec(cmd)
  374. cmd = "mv #{property.ggen} /usr/local/bin/gnrs/"
  375. node.group.exec(cmd)
  376. # Trace file
  377. cmd = "mv #{property.clientTrace} /etc/gnrs/".gsub(/XxX/,node.asNumber.to_s)
  378. node.group.exec(cmd)
  379. }
  380. return 0
  381. end # installConfigs
  382. def launchServers(serversMap)
  383. cmd = "service gnrsd start"
  384. serversMap.each_value { |node|
  385. info "Launching server on #{node.to_s}"
  386. node.group.exec(cmd)
  387. }
  388. return 0
  389. end #launchServers
  390. def loadGUIDs(clientsMap)
  391. # 3 parameters to gbench: client config, trace file, inter-message send time in microseconds
  392. baseCmd = "/usr/local/bin/gnrs/#{property.gbench} /etc/gnrs/client.xml /etc/gnrs/#{property.clientTrace} #{property.messageDelay}"
  393. clientsMap.each_value { |node|
  394. cmd = baseCmd.gsub(/XxX/,node.asNumber.to_s)
  395. info "#{node.to_s}: Execing '#{cmd}'"
  396. node.group.exec(cmd)
  397. }
  398. return 0
  399. end # loadGUIDs
  400. def genLookups(clientsMap)
  401. baseCmd = "/usr/local/bin/gnrs/#{property.ggen} /etc/gnrs/client.xml #{property.numLookups} #{property.messageDelay} 1"
  402. clientsMap.each_value { |node|
  403. info "#{node.to_s}: Execing '#{baseCmd}'"
  404. node.group.exec(baseCmd)
  405. }
  406. return 0
  407. end # genLookups
  408. def stopServers(serversMap)
  409. info "Stopping GNRS servers"
  410. cmd = "service gnrsd stop"
  411. serversMap.each_value { |node|
  412. node.group.exec(cmd)
  413. }
  414. return 0
  415. end # stopServers
  416. # Load resources, get topology, define groups
  417. success, serversMap, clientsMap = doInitSetup
  418. # Only register callback if we were able to prepare the experiment.
  419. if success == 0
  420. info "Awaiting node readiness"
  421. # Called when all nodes are available for use.
  422. onEvent(:ALL_UP) do |event|
  423. if success
  424. info "GNRS: All nodes are up."
  425. doMainExperiment(serversMap, clientsMap)
  426. end
  427. Experiment.done
  428. end # onEvent
  429. else
  430. Experiment.done
  431. end