installer.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. import subprocess
  2. import os
  3. import os.path
  4. import time
  5. import traceback
  6. import sys
  7. import glob
  8. import logging
  9. import setup_util
  10. class Installer:
  11. ############################################################
  12. # install_software
  13. ############################################################
  14. def install_software(self):
  15. if self.benchmarker.install == 'all' or self.benchmarker.install == 'server':
  16. self.__install_server_software()
  17. if self.benchmarker.install == 'all' or self.benchmarker.install == 'database':
  18. self.__install_database_software()
  19. if self.benchmarker.install == 'all' or self.benchmarker.install == 'client':
  20. self.__install_client_software()
  21. ############################################################
  22. # End install_software
  23. ############################################################
  24. ############################################################
  25. # __install_server_software
  26. ############################################################
  27. def __install_server_software(self):
  28. print("\nINSTALL: Installing server software (strategy=%s)\n"%self.strategy)
  29. # Install global prerequisites
  30. bash_functions_path='$FWROOT/toolset/setup/linux/bash_functions.sh'
  31. prereq_path='$FWROOT/toolset/setup/linux/prerequisites.sh'
  32. self.__run_command(". %s && . %s" % (bash_functions_path, prereq_path))
  33. # Pull in benchmarker include and exclude list
  34. exclude = self.benchmarker.exclude
  35. include = self.benchmarker.test
  36. if exclude == None:
  37. exclude = []
  38. # Locate all known tests
  39. install_files = glob.glob("%s/*/install.sh" % self.fwroot)
  40. # Run install for selected tests
  41. for test_install_file in install_files:
  42. test_dir = os.path.dirname(test_install_file)
  43. test_name = os.path.basename(test_dir)
  44. test_rel_dir = setup_util.path_relative_to_root(test_dir)
  45. if test_name in exclude:
  46. logging.debug("%s has been excluded", test_name)
  47. continue
  48. elif include is not None and test_name not in include:
  49. logging.debug("%s not in include list", test_name)
  50. continue
  51. else:
  52. logging.info("Running installation for %s"%test_name)
  53. # Find installation directory
  54. # e.g. FWROOT/installs or FWROOT/installs/pertest/<test-name>
  55. test_install_dir="%s/%s" % (self.fwroot, self.install_dir)
  56. if self.strategy is 'pertest':
  57. test_install_dir="%s/pertest/%s" % (test_install_dir, test_name)
  58. test_rel_install_dir=setup_util.path_relative_to_root(test_install_dir)
  59. if not os.path.exists(test_install_dir):
  60. os.makedirs(test_install_dir)
  61. # Load profile for this installation
  62. test_profile_file="%s/bash_profile.sh" % test_dir
  63. if os.path.exists(test_profile_file):
  64. setup_util.replace_environ(config=test_profile_file)
  65. else:
  66. logging.warning("Framework %s does not have a bash_profile"%test_name)
  67. setup_util.replace_environ(config="$FWROOT/config/benchmark_profile")
  68. # Find relative installation file
  69. test_rel_install_file = "$FWROOT%s" % setup_util.path_relative_to_root(test_install_file)
  70. # Then run test installer file
  71. # Give all installers a number of variables
  72. # FWROOT - Path of the FwBm root
  73. # IROOT - Path of this test's install directory
  74. # TROOT - Path to this test's directory
  75. self.__run_command('''
  76. export TROOT=$FWROOT%s &&
  77. export IROOT=$FWROOT%s &&
  78. . %s &&
  79. . %s''' %
  80. (test_rel_dir, test_rel_install_dir,
  81. bash_functions_path, test_rel_install_file),
  82. cwd=test_install_dir)
  83. self.__run_command("sudo apt-get -y autoremove");
  84. print("\nINSTALL: Finished installing server software\n")
  85. ############################################################
  86. # End __install_server_software
  87. ############################################################
  88. ############################################################
  89. # __install_error
  90. ############################################################
  91. def __install_error(self, message):
  92. print("\nINSTALL ERROR: %s\n" % message)
  93. if self.benchmarker.install_error_action == 'abort':
  94. sys.exit("Installation aborted.")
  95. ############################################################
  96. # End __install_error
  97. ############################################################
  98. ############################################################
  99. # __install_database_software
  100. ############################################################
  101. def __install_database_software(self):
  102. print("\nINSTALL: Installing database software\n")
  103. self.__run_command("cd .. && " + self.benchmarker.database_sftp_string(batch_file="../config/database_sftp_batch"), True)
  104. remote_script = """
  105. ##############################
  106. # Prerequisites
  107. ##############################
  108. sudo apt-get -y update
  109. sudo apt-get -y install build-essential git libev-dev libpq-dev libreadline6-dev postgresql
  110. sudo sh -c "echo '* - nofile 65535' >> /etc/security/limits.conf"
  111. sudo mkdir -p /ssd
  112. sudo mkdir -p /ssd/log
  113. ##############################
  114. # MySQL
  115. ##############################
  116. sudo sh -c "echo mysql-server mysql-server/root_password_again select secret | debconf-set-selections"
  117. sudo sh -c "echo mysql-server mysql-server/root_password select secret | debconf-set-selections"
  118. sudo apt-get -y install mysql-server
  119. sudo stop mysql
  120. # disable checking of disk size
  121. sudo cp mysql /etc/init.d/mysql
  122. sudo chmod +x /etc/init.d/mysql
  123. sudo cp mysql.conf /etc/init/mysql.conf
  124. # use the my.cnf file to overwrite /etc/mysql/my.cnf
  125. sudo mv /etc/mysql/my.cnf /etc/mysql/my.cnf.orig
  126. sudo mv my.cnf /etc/mysql/my.cnf
  127. sudo cp -R -p /var/lib/mysql /ssd/
  128. sudo cp -R -p /var/log/mysql /ssd/log
  129. sudo cp usr.sbin.mysqld /etc/apparmor.d/
  130. sudo /etc/init.d/apparmor reload
  131. sudo start mysql
  132. # Insert data
  133. mysql -uroot -psecret < create.sql
  134. ##############################
  135. # Postgres
  136. ##############################
  137. sudo useradd benchmarkdbuser -p benchmarkdbpass
  138. sudo -u postgres psql template1 < create-postgres-database.sql
  139. sudo -u benchmarkdbuser psql hello_world < create-postgres.sql
  140. sudo -u postgres -H /etc/init.d/postgresql stop
  141. sudo mv postgresql.conf /etc/postgresql/9.3/main/postgresql.conf
  142. sudo mv pg_hba.conf /etc/postgresql/9.3/main/pg_hba.conf
  143. sudo cp -R -p /var/lib/postgresql/9.3/main /ssd/postgresql
  144. sudo -u postgres -H /etc/init.d/postgresql start
  145. sudo mv 60-postgresql-shm.conf /etc/sysctl.d/60-postgresql-shm.conf
  146. ##############################
  147. # MongoDB
  148. ##############################
  149. sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
  150. sudo cp 10gen.list /etc/apt/sources.list.d/10gen.list
  151. sudo apt-get -y update
  152. sudo apt-get -y remove mongodb-clients
  153. sudo apt-get -y install mongodb-10gen
  154. sudo stop mongodb
  155. sudo mv /etc/mongodb.conf /etc/mongodb.conf.orig
  156. sudo mv mongodb.conf /etc/mongodb.conf
  157. sudo cp -R -p /var/lib/mongodb /ssd/
  158. sudo cp -R -p /var/log/mongodb /ssd/log/
  159. sudo start mongodb
  160. """
  161. print("\nINSTALL: %s" % self.benchmarker.database_ssh_string)
  162. p = subprocess.Popen(self.benchmarker.database_ssh_string.split(" "), stdin=subprocess.PIPE)
  163. p.communicate(remote_script)
  164. returncode = p.returncode
  165. if returncode != 0:
  166. self.__install_error("status code %s running subprocess '%s'." % (returncode, self.benchmarker.database_ssh_string))
  167. print("\nINSTALL: Finished installing database software\n")
  168. ############################################################
  169. # End __install_database_software
  170. ############################################################
  171. ############################################################
  172. # __install_client_software
  173. ############################################################
  174. def __install_client_software(self):
  175. print("\nINSTALL: Installing client software\n")
  176. remote_script = """
  177. ##############################
  178. # Prerequisites
  179. ##############################
  180. sudo apt-get -y update
  181. sudo apt-get -y install build-essential git libev-dev libpq-dev libreadline6-dev
  182. sudo sh -c "echo '* - nofile 65535' >> /etc/security/limits.conf"
  183. ##############################
  184. # wrk
  185. ##############################
  186. git clone https://github.com/wg/wrk.git
  187. cd wrk
  188. make
  189. sudo cp wrk /usr/local/bin
  190. cd ~
  191. #############################
  192. # pipeline.lua
  193. #############################
  194. cat << EOF | tee pipeline.lua
  195. init = function(args)
  196. wrk.init(args)
  197. local r = {}
  198. local depth = tonumber(args[1]) or 1
  199. for i=1,depth do
  200. r[i] = wrk.format()
  201. end
  202. req = table.concat(r)
  203. end
  204. request = function()
  205. return req
  206. end
  207. EOF
  208. """
  209. print("\nINSTALL: %s" % self.benchmarker.client_ssh_string)
  210. p = subprocess.Popen(self.benchmarker.client_ssh_string.split(" "), stdin=subprocess.PIPE)
  211. p.communicate(remote_script)
  212. returncode = p.returncode
  213. if returncode != 0:
  214. self.__install_error("status code %s running subprocess '%s'." % (returncode, self.benchmarker.client_ssh_string))
  215. print("\nINSTALL: Finished installing client software\n")
  216. ############################################################
  217. # End __install_client_software
  218. ############################################################
  219. ############################################################
  220. # __path_exists
  221. ############################################################
  222. def __path_exists(self, path, cwd=None):
  223. full_path = os.path.join(cwd or self.install_dir, path)
  224. if os.path.exists(full_path):
  225. print("\nEXISTS: %s " % full_path)
  226. return True
  227. print("\nNOT_EXISTS: %s" % full_path)
  228. return False
  229. ############################################################
  230. # End __path_exists
  231. ############################################################
  232. ############################################################
  233. # __run_command
  234. ############################################################
  235. def __run_command(self, command, send_yes=False, cwd=None, retry=False):
  236. if cwd is None:
  237. cwd = self.install_dir
  238. if retry:
  239. max_attempts = 5
  240. else:
  241. max_attempts = 1
  242. attempt = 1
  243. delay = 0
  244. if send_yes:
  245. command = "yes yes | " + command
  246. rel_cwd = setup_util.path_relative_to_root(cwd)
  247. print("INSTALL: %s (cwd=$FWROOT/%s)" % (command, rel_cwd))
  248. while attempt <= max_attempts:
  249. error_message = ""
  250. try:
  251. # Execute command.
  252. subprocess.check_call(command, shell=True, cwd=cwd, executable='/bin/bash')
  253. break # Exit loop if successful.
  254. except:
  255. exceptionType, exceptionValue, exceptionTraceBack = sys.exc_info()
  256. error_message = "".join(traceback.format_exception_only(exceptionType, exceptionValue))
  257. # Exit if there are no more attempts left.
  258. attempt += 1
  259. if attempt > max_attempts:
  260. break
  261. # Delay before next attempt.
  262. if delay == 0:
  263. delay = 5
  264. else:
  265. delay = delay * 2
  266. print("Attempt %s/%s starting in %s seconds." % (attempt, max_attempts, delay))
  267. time.sleep(delay)
  268. if error_message:
  269. self.__install_error(error_message)
  270. ############################################################
  271. # End __run_command
  272. ############################################################
  273. ############################################################
  274. # __bash_from_string
  275. # Runs bash -c "command" in install_dir.
  276. ############################################################
  277. def __bash_from_string(self, command):
  278. self.__run_command('bash -c "%s"' % command)
  279. ############################################################
  280. # End __bash_from_string
  281. ############################################################
  282. ############################################################
  283. # __download
  284. # Downloads a file from a URI.
  285. ############################################################
  286. def __download(self, uri, filename=""):
  287. if filename:
  288. if os.path.exists(filename):
  289. return
  290. filename_option = "-O %s " % filename
  291. else:
  292. filename_option = ""
  293. command = "wget -nv --no-check-certificate --trust-server-names %s%s" % (filename_option, uri)
  294. self.__run_command(command, retry=True)
  295. ############################################################
  296. # End __download
  297. ############################################################
  298. ############################################################
  299. # __init__(benchmarker)
  300. ############################################################
  301. def __init__(self, benchmarker, install_strategy):
  302. self.benchmarker = benchmarker
  303. self.install_dir = "installs"
  304. self.fwroot = benchmarker.fwroot
  305. self.strategy = install_strategy
  306. # setup logging
  307. logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
  308. try:
  309. os.mkdir(self.install_dir)
  310. except OSError:
  311. pass
  312. ############################################################
  313. # End __init__
  314. ############################################################
  315. # vim: sw=2