installer.py 15 KB

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