deploy-java-files.sh.in 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. #!/bin/bash
  2. ################################################################################
  3. # HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  4. #
  5. # Licensed under the Apache License, Version 2.0 (the "License");
  6. # you may not use this file except in compliance with the License.
  7. # You may obtain a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS,
  13. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. # See the License for the specific language governing permissions and
  15. # limitations under the License.
  16. ################################################################################
  17. #
  18. # Usage: deploy-java-files.sh <from> <to>
  19. #
  20. # This is acomplished with a standard scp command with the use of the
  21. # runtime users id_rsa file.
  22. ###<REPLACE>###
  23. source ${INSTALL_DIR}/etc/init.d/hpcc_common
  24. usage() {
  25. echo ""
  26. echo "usage: deploy-java-files.sh [OPTIONS]"
  27. echo " -c|--classpath: When specified, this option add the target directory or"
  28. echo " jar file path to classpath in environment.conf."
  29. echo " -e|--delete: When specified, this denotes the target is to be removed"
  30. echo " from the classpath."
  31. echo " This option will be ignored if used with the reset (-r) option"
  32. echo " -H|--hosts: Host IP list. When specified, will target the IP addresses"
  33. echo " specified, one IP address per line. If this option is not used will"
  34. echo " run on the IP list generated from the environment.xml"
  35. echo " -n|--concurrent: When specified, denotes the number of concurrent"
  36. echo " executions threads. The default is 5. You must have python installed,"
  37. echo " otherwise this option will be ignored and the action will run on each"
  38. echo " host sequentially."
  39. echo " -r|--reset: Reset classpath. When specified, will reset the classpath to"
  40. echo " <install_directory>/classes. If used in conjunction with the -t adds"
  41. echo " the new entries to the classpath after reset."
  42. echo " -s|--source: Source file or directory."
  43. echo " -t|--target: target directory. The default is <install_directory>/classes."
  44. echo " If it is only for adding to classpath, the value can be the full path"
  45. echo " of the java jar file."
  46. echo " -u|--user: The username to ssh to the access remote system. Provide this"
  47. echo " option means the specified user does not use a password to run ssh/scp."
  48. echo " Without specifiying this option you will be prompted to supply a"
  49. echo " username and password. We strongly recommand not using <hpcc user>"
  50. echo " to avoid security issues."
  51. echo " -x: When specified, this option excludes execution on the current host."
  52. echo ""
  53. echo "Examples:"
  54. echo " Deploy java files and update classpath in a cluster:"
  55. echo " deploy-java-files.sh -c -s \"/tmp/java/*\" -t /opt/HPCCSystems/classes"
  56. echo ""
  57. echo " Deploy java files and update classpath in a cluster with user ubuntu using"
  58. echo " ssh private key file"
  59. echo " deploy-java-files.sh -c -s /home/ubuntu/java/myjavaapp.jar -u ubuntu"
  60. echo ""
  61. echo " Deploy java files to a list of hosts:"
  62. echo " deploy-java-files.sh -H <host list file> -s <source> -t <target>"
  63. echo ""
  64. echo " Update classpath in a cluster:"
  65. echo " deploy-java-files.sh -c -t /opt/HPCCSystems/classes/myjavaapp.jar"
  66. echo ""
  67. exit 1
  68. }
  69. ######################################################################
  70. #
  71. # Write script head
  72. #
  73. ######################################################################
  74. createScriptFileHead() {
  75. cat > $SCRIPT_FILE <<SCRIPTHEAD
  76. #!/bin/bash
  77. IP=\$1
  78. ping -c 1 -w 5 -n \$IP > /dev/null 2>&1;
  79. if [ \$? -ne 0 ]
  80. then
  81. echo "\$IP: Cannot Ping host? (Host Alive?)"
  82. exit 1
  83. fi
  84. echo "\$IP: Host is alive."
  85. SCRIPTHEAD
  86. }
  87. ######################################################################
  88. #
  89. # Write script foot
  90. #
  91. ######################################################################
  92. createScriptFileFoot() {
  93. chmod +x ${SCRIPT_FILE}
  94. }
  95. ######################################################################
  96. #
  97. # Write script copy Java files to targets
  98. #
  99. ######################################################################
  100. addScriptDeployFiles() {
  101. user_home=$(cat /etc/passwd | grep -e "^${file_transfer_user}:" | cut -d':' -f 6)
  102. _options="--userhome $user_home"
  103. [ $run_as_sudo -eq 1 ] && _options="$_options --sudo"
  104. cat >> $SCRIPT_FILE <<SCRIPTMARKER
  105. ${INSTALL_DIR}/sbin/deploy-java-files.exp --ip \$IP --source "${source}" \
  106. --target ${target} --user ${file_transfer_user} ${_options} || exit 1
  107. SCRIPTMARKER
  108. }
  109. ######################################################################
  110. #
  111. # Reset classpath to ${INSTALL_DIR}/classes
  112. #
  113. ######################################################################
  114. resetClasspath() {
  115. cat >> $SCRIPT_FILE <<SCRIPTPATH
  116. NEW_JAVA_CLASSPATH="${INSTALL_DIR}/classes"
  117. SCRIPTPATH
  118. }
  119. ######################################################################
  120. #
  121. # Remove duplicate entries in classpath
  122. #
  123. ######################################################################
  124. removeDuplicateFromClasspath() {
  125. cat >> $SCRIPT_FILE <<SCRIPTPATH
  126. # get current classpath
  127. JAVA_CLASSPATH=\$(cat ${HPCC_CONFIG} | sed -n "s/\[${SECTION}\]/,/\[/p" | grep "^classpath *= *" | sed 's/^classpath *= *//')
  128. # make sure current classpath has unique entries
  129. for path in \$JAVA_CLASSPATH
  130. do
  131. [ -z "\$path" ] && continue
  132. echo ":\$NEW_JAVA_CLASSPATH:" | grep -q ":\$path:"
  133. [ \$? -ne 0 ] && NEW_JAVA_CLASSPATH="\${NEW_JAVA_CLASSPATH:+"\$NEW_JAVA_CLASSPATH:"}\$path"
  134. done
  135. SCRIPTPATH
  136. }
  137. ######################################################################
  138. #
  139. # Add new entries to classpath
  140. #
  141. ######################################################################
  142. addToClasspath() {
  143. cat >> $SCRIPT_FILE <<SCRIPTPATH
  144. # add new entries to classpath
  145. entries="$classpath_entries"
  146. for path in \$entries
  147. do
  148. [ -z "\$path" ] && continue
  149. echo ":\$NEW_JAVA_CLASSPATH:" | grep -q ":\$path:"
  150. [ \$? -ne 0 ] && NEW_JAVA_CLASSPATH="\${NEW_JAVA_CLASSPATH:+"\$NEW_JAVA_CLASSPATH:"}\$path"
  151. done
  152. SCRIPTPATH
  153. }
  154. ######################################################################
  155. #
  156. # Delete entries from classpath
  157. #
  158. ######################################################################
  159. deleteFromClasspath() {
  160. cat >> $SCRIPT_FILE <<SCRIPTPATH
  161. entries="$classpath_entries"
  162. JAVA_CLASSPATH=\${NEW_JAVA_CLASSPATH}
  163. NEW_JAVA_CLASSPATH=
  164. for path in \$JAVA_CLASSPATH
  165. do
  166. [ -z "\$path" ] && continue
  167. found=0
  168. for path_to_delete in \$entries
  169. do
  170. if [ "\$path_to_delete" = "\$path" ]
  171. then
  172. found=1
  173. break
  174. fi
  175. done
  176. [ \$found -eq 0 ] && NEW_JAVA_CLASSPATH="\${NEW_JAVA_CLASSPATH:+"\$NEW_JAVA_CLASSPATH:"}\$path"
  177. done
  178. SCRIPTPATH
  179. }
  180. ######################################################################
  181. #
  182. # Write script update Java Classpath
  183. # Following code is embeded in ssh command. Another options
  184. # is written to a script file and scp to remote and invoke
  185. # from ssh command, particularly when code is complicated.
  186. #
  187. ######################################################################
  188. createScriptFileUpdateClasspath() {
  189. [ $update_classpath -ne 1 ] && return
  190. composeClasspath
  191. cat >> $SCRIPT_FILE <<SCRIPTPATH
  192. CAN_SSH="\$(ssh -i $home/$user/.ssh/id_rsa -o BatchMode=yes -o LogLevel=QUIET -o StrictHostKeyChecking=no $user@\$IP exit > /dev/null 2>&1; echo \$?)"
  193. if [ "\$CAN_SSH" -eq 255 ]; then
  194. echo "\$IP: Cannot SSH to host as user $user.";
  195. exit 1
  196. fi
  197. ssh -i $home/$user/.ssh/id_rsa -o BatchMode=yes -o LogLevel=QUIET -o StrictHostKeyChecking=no $user@\$IP << 'SSHCMD'
  198. NEW_JAVA_CLASSPATH=
  199. SCRIPTPATH
  200. # Reset classpath
  201. [ $reset_classpath -eq 1 ] && resetClasspath
  202. # if has other update beside reset set IFS=:
  203. if [ $delete_from_classpath -eq 1 ] || [ -n "$target" ]
  204. then
  205. cat >> $SCRIPT_FILE <<SCRIPTPATH
  206. OIFS=\$IFS
  207. IFS=:
  208. SCRIPTPATH
  209. fi
  210. # remove duplicate entries from classpath if not reset
  211. [ $reset_classpath -eq 0 ] && removeDuplicateFromClasspath
  212. if [ $delete_from_classpath -eq 1 ] && [ $reset_classpath -eq 0 ]
  213. then
  214. deleteFromClasspath
  215. elif [ -n "$classpath_entries" ]
  216. then
  217. addToClasspath
  218. fi
  219. # if has other update beside reset restore IFS
  220. if [ $delete_from_classpath -eq 1 ] || [ -n "$classpath_entries" ]
  221. then
  222. cat >> $SCRIPT_FILE <<SCRIPTPATH
  223. IFS=\$OIFS
  224. SCRIPTPATH
  225. fi
  226. # Replace classpath in environment.conf
  227. cat >> $SCRIPT_FILE <<SCRIPTPATH
  228. echo "CLASSPATH: \$NEW_JAVA_CLASSPATH"
  229. tmp_conf=/tmp/hpcc_conf_\$\$
  230. # ecapse '/' before processed by sed
  231. NEW_JAVA_CLASSPATH=\$(echo \$NEW_JAVA_CLASSPATH | sed "s/\//\\\\\\\\\//g")
  232. echo "Ecapsed CLASSPATH: \$NEW_JAVA_CLASSPATH"
  233. # Update classpath in environment.conf
  234. cat ${HPCC_CONFIG} | sed "/\[${SECTION}\]/,/\[/ { s/^classpath *= *.*/classpath=\${NEW_JAVA_CLASSPATH}/ }" > \$tmp_conf
  235. if [ -s \$tmp_conf ]
  236. then
  237. [ ! -e ${HPCC_CONFIG}.bk ] && cp $HPCC_CONFIG ${HPCC_CONFIG}.bk
  238. mv \$tmp_conf $HPCC_CONFIG
  239. chmod 644 $HPCC_CONFIG
  240. else
  241. echo "Failed to update $HPCC_CONFIG. Update file size is 0"
  242. exit 1
  243. fi
  244. SSHCMD
  245. SCRIPTPATH
  246. }
  247. ######################################################################
  248. #
  249. # Create classpath entries base on source
  250. #
  251. ######################################################################
  252. composeClasspath() {
  253. [ -z "$target" ] && return
  254. if [ -z "$source" ]
  255. then
  256. classpath_entries="$target"
  257. return
  258. fi
  259. add_target_dir=0
  260. for _file in $(ls -d ${source})
  261. do
  262. _file=$(basename $_file)
  263. if [[ $_file = *.jar ]]
  264. then
  265. classpath_entries="${classpath_entries:+"$classpath_entries:"}${target}/$_file"
  266. else
  267. add_target_dir=1
  268. fi
  269. done
  270. [ $add_target_dir -eq 1 ] && classpath_entries="${classpath_entries:+"$classpath_entries:"}${target}"
  271. }
  272. ######################################################################
  273. #
  274. # Set ssh user
  275. #
  276. ######################################################################
  277. setUser() {
  278. if [ -z "${file_transfer_user}" ]
  279. then
  280. trial=0
  281. max_trial=3
  282. while [ 1 ]
  283. do
  284. if [ -z "${file_transfer_user}" ]
  285. then
  286. echo ""
  287. read -p "Please enter ssh/scp user name: " file_transfer_user;
  288. echo ""
  289. echo "Please enter ssh/scp user password. If this is no password required (assume"
  290. echo "the user has ssh private key: /home/<user>/.ssh/id_rsa) just press 'Enter':"
  291. read -s password
  292. echo ""
  293. fi
  294. echo ""
  295. echo "You entered user $file_transfer_user and a password."
  296. read -p "Are these correct? [Y|n] " answer
  297. if [ "$answer" = "Y" ] || [ "$answer" = "y" ]
  298. then
  299. break
  300. fi
  301. file_transfer_user=
  302. trial=$(expr $trial \+ 1)
  303. if [ $trial -eq $max_trial ]
  304. then
  305. echo ""
  306. echo "Exceeded maximum attempts. Giving up."
  307. echo ""
  308. exit 1
  309. fi
  310. done
  311. fi
  312. if [ "$file_transfer_user" != "root" ]
  313. then
  314. echo $target | grep -q ${INSTALL_DIR}
  315. [ $? -eq 0 ] && run_as_sudo=1
  316. fi
  317. export password
  318. }
  319. ######################################################################
  320. #
  321. # MAIN
  322. #
  323. ######################################################################
  324. cluster_tools_init
  325. source=
  326. target=
  327. update_classpath=0
  328. OPTION=
  329. SECTION=${SECTION:-DEFAULT}
  330. classpath_do_add=
  331. reset_classpath=0
  332. delete_from_classpath=0
  333. classpath_entries=
  334. file_ransfer_user=
  335. password=
  336. run_as_sudo=0
  337. exclude_local=0
  338. hosts_list=
  339. TEMP=$(/usr/bin/getopt -o cehH:n:s:t:ru:x --long help,hosts:,classpath,delete,concurrent:,\
  340. source:,target:,reset,user:,exclude -n 'deploy-java-file' -- "$@")
  341. if [ $? != 0 ] ; then echo "Failure to parse commandline." >&2 ; end 1 ; fi
  342. eval set -- "$TEMP"
  343. while true ; do
  344. case "$1" in
  345. -c|--classpath) update_classpath=1
  346. shift ;;
  347. -e|--delete) delete_from_classpath=1
  348. shift ;;
  349. -H|--hosts) OPTION="${OPTION:+"$OPTION "}-h $2"
  350. hosts_list=$2
  351. shift 2 ;;
  352. -n|--concurrent) OPTION="${OPTION:+"$OPTION "}-n $2"
  353. shift 2 ;;
  354. -s|--source) source="$2"
  355. shift 2 ;;
  356. -t|--target) target="$2"
  357. shift 2 ;;
  358. -r|--reset) reset_classpath=1
  359. shift ;;
  360. -u|--user) file_transfer_user="$2"
  361. shift 2 ;;
  362. -x|--exclude) OPTION="${OPTION:+"$OPTION "}-x"
  363. exclude_local=1
  364. shift ;;
  365. -h|--help) usage
  366. shift ;;
  367. --) shift ; break ;;
  368. *) usage ;;
  369. esac
  370. done
  371. if [ "$(whoami)" != "root" ]; then
  372. echo ""
  373. echo "The script must run as root or sudo."
  374. echo ""
  375. exit 1
  376. fi
  377. if [ -z "$target" ]; then
  378. if [ -n "$source" ]; then
  379. target=${INSTALL_DIR}/classes
  380. elif [ $reset_classpath -eq 0 ]; then
  381. echo ""
  382. echo "Missing target"
  383. usage
  384. fi
  385. fi
  386. if [ $delete_from_classpath -eq 1 ] || [ $reset_classpath -eq 1 ]; then
  387. update_classpath=1
  388. fi
  389. if [ -z "$source" ] && [ $update_classpath -ne 1 ]; then
  390. echo ""
  391. echo "Missing source or update classpath flag"
  392. usage
  393. fi
  394. [ -n "$source" ] && setUser
  395. HPCC_CONFIG=${CONFIG_DIR}/${ENV_CONF_FILE}
  396. if [[ $target = */ ]]
  397. then
  398. target_is_directory=1
  399. [ "$target" != "/" ] && target=$(echo $target | sed 's/[\/]*$//')
  400. fi
  401. SCRIPT_FILE=~/deploy-java-files_$$
  402. createScriptFileHead
  403. EXPECT_SCRIPT_FILE=
  404. [ -n "$source" ] && addScriptDeployFiles
  405. [ ${update_classpath} -eq 1 ] && createScriptFileUpdateClasspath
  406. createScriptFileFoot
  407. expected_python_version=3.4
  408. is_python_installed ${expected_python_version}
  409. if [ $? -eq 0 ]
  410. then
  411. eval ${INSTALL_DIR}/sbin/cluster_script.py -e ${HPCC_CONFIG} -f "${SCRIPT_FILE}" -l DEBUG -s $SECTION $OPTION
  412. else
  413. echo ""
  414. echo "Cannot detect python version ${expected_python_version}+. Will run on the cluster hosts sequentially."
  415. echo ""
  416. run_cluster ${SCRIPT_FILE} ${exclude_local} ${hosts_list}
  417. fi
  418. rm -rf ${SCRIPT_FILE}