ambari-server.py 155 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487
  1. #!/usr/bin/env python
  2. '''
  3. Licensed to the Apache Software Foundation (ASF) under one
  4. or more contributor license agreements. See the NOTICE file
  5. distributed with this work for additional information
  6. regarding copyright ownership. The ASF licenses this file
  7. to you under the Apache License, Version 2.0 (the
  8. "License"); you may not use this file except in compliance
  9. with the License. You may obtain a copy of the License at
  10. http://www.apache.org/licenses/LICENSE-2.0
  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. import optparse
  18. import shlex
  19. import sys
  20. import os
  21. import signal
  22. import subprocess
  23. import re
  24. import string
  25. import glob
  26. import platform
  27. import shutil
  28. import stat
  29. import fileinput
  30. import urllib2
  31. import time
  32. import getpass
  33. import socket
  34. import datetime
  35. import tempfile
  36. import random
  37. import pwd
  38. from ambari_server.resourceFilesKeeper import ResourceFilesKeeper, KeeperException
  39. import json
  40. from common_functions import OSCheck, OSConst
  41. from ambari_server import utils
  42. # debug settings
  43. VERBOSE = False
  44. SILENT = False
  45. SERVER_START_DEBUG = False
  46. # OS info
  47. OS_VERSION = OSCheck().get_os_major_version()
  48. OS_TYPE = OSCheck.get_os_type()
  49. OS_FAMILY = OSCheck.get_os_family()
  50. # action commands
  51. SETUP_ACTION = "setup"
  52. START_ACTION = "start"
  53. STOP_ACTION = "stop"
  54. RESET_ACTION = "reset"
  55. UPGRADE_ACTION = "upgrade"
  56. UPGRADE_STACK_ACTION = "upgradestack"
  57. STATUS_ACTION = "status"
  58. SETUP_HTTPS_ACTION = "setup-https"
  59. LDAP_SETUP_ACTION = "setup-ldap"
  60. SETUP_GANGLIA_HTTPS_ACTION = "setup-ganglia-https"
  61. SETUP_NAGIOS_HTTPS_ACTION = "setup-nagios-https"
  62. ENCRYPT_PASSWORDS_ACTION = "encrypt-passwords"
  63. SETUP_SECURITY_ACTION = "setup-security"
  64. ACTION_REQUIRE_RESTART = [RESET_ACTION, UPGRADE_ACTION, UPGRADE_STACK_ACTION,
  65. SETUP_SECURITY_ACTION, LDAP_SETUP_ACTION]
  66. # selinux commands
  67. GET_SE_LINUX_ST_CMD = utils.locate_file('sestatus', '/usr/sbin')
  68. SE_SETENFORCE_CMD = "setenforce 0"
  69. SE_STATUS_DISABLED = "disabled"
  70. SE_STATUS_ENABLED = "enabled"
  71. SE_MODE_ENFORCING = "enforcing"
  72. SE_MODE_PERMISSIVE = "permissive"
  73. # server commands
  74. ambari_provider_module_option = ""
  75. ambari_provider_module = os.environ.get('AMBARI_PROVIDER_MODULE')
  76. # Non-root user setup commands
  77. NR_USER_PROPERTY = "ambari-server.user"
  78. NR_USER_COMMENT = "Ambari user"
  79. NR_GET_OWNER_CMD = 'stat -c "%U" {0}'
  80. NR_USERADD_CMD = 'useradd -M --comment "{1}" ' \
  81. '--shell %s -d /var/lib/ambari-server/keys/ {0}' % utils.locate_file('nologin', '/sbin')
  82. NR_SET_USER_COMMENT_CMD = 'usermod -c "{0}" {1}'
  83. NR_CHMOD_CMD = 'chmod {0} {1} {2}'
  84. NR_CHOWN_CMD = 'chown {0} {1} {2}'
  85. RECURSIVE_RM_CMD = 'rm -rf {0}'
  86. SSL_PASSWORD_FILE = "pass.txt"
  87. SSL_PASSIN_FILE = "passin.txt"
  88. # openssl command
  89. VALIDATE_KEYSTORE_CMD = "openssl pkcs12 -info -in '{0}' -password file:'{1}' -passout file:'{2}'"
  90. EXPRT_KSTR_CMD = "openssl pkcs12 -export -in '{0}' -inkey '{1}' -certfile '{0}' -out '{4}' -password file:'{2}' -passin file:'{3}'"
  91. CHANGE_KEY_PWD_CND = 'openssl rsa -in {0} -des3 -out {0}.secured -passout pass:{1}'
  92. GET_CRT_INFO_CMD = 'openssl x509 -dates -subject -in {0}'
  93. #keytool commands
  94. KEYTOOL_IMPORT_CERT_CMD = "{0}" + os.sep + "bin" + os.sep + "keytool -import -alias '{1}' -storetype '{2}' -file '{3}' -storepass '{4}' -noprompt"
  95. KEYTOOL_DELETE_CERT_CMD = "{0}" + os.sep + "bin" + os.sep + "keytool -delete -alias '{1}' -storepass '{2}' -noprompt"
  96. KEYTOOL_KEYSTORE = " -keystore '{0}'"
  97. # constants
  98. STACK_NAME_VER_SEP = "-"
  99. JAVA_SHARE_PATH = "/usr/share/java"
  100. SERVER_OUT_FILE = "/var/log/ambari-server/ambari-server.out"
  101. SERVER_LOG_FILE = "/var/log/ambari-server/ambari-server.log"
  102. BLIND_PASSWORD = "*****"
  103. # terminal styles
  104. BOLD_ON = '\033[1m'
  105. BOLD_OFF = '\033[0m'
  106. #Common messages
  107. PRESS_ENTER_MSG = "Press <enter> to continue."
  108. #Common setup or upgrade message
  109. SETUP_OR_UPGRADE_MSG = "- If this is a new setup, then run the \"ambari-server setup\" command to create the user\n" \
  110. "- If this is an upgrade of an existing setup, run the \"ambari-server upgrade\" command.\n" \
  111. "Refer to the Ambari documentation for more information on setup and upgrade."
  112. AMBARI_SERVER_DIE_MSG = "Ambari Server java process died with exitcode {0}. Check {1} for more information."
  113. #SSL certificate metainfo
  114. COMMON_NAME_ATTR = 'CN'
  115. NOT_BEFORE_ATTR = 'notBefore'
  116. NOT_AFTER_ATTR = 'notAfter'
  117. if ambari_provider_module is not None:
  118. ambari_provider_module_option = "-Dprovider.module.class=" +\
  119. ambari_provider_module + " "
  120. SERVER_START_CMD = "{0}" + os.sep + "bin" + os.sep +\
  121. "java -server -XX:NewRatio=3 "\
  122. "-XX:+UseConcMarkSweepGC " +\
  123. "-XX:-UseGCOverheadLimit -XX:CMSInitiatingOccupancyFraction=60 " +\
  124. ambari_provider_module_option +\
  125. os.getenv('AMBARI_JVM_ARGS', '-Xms512m -Xmx2048m') +\
  126. " -cp {1}" + os.pathsep + "{2}" +\
  127. " org.apache.ambari.server.controller.AmbariServer "\
  128. ">" + SERVER_OUT_FILE + " 2>&1 || echo $? > {3} &"
  129. SERVER_START_CMD_DEBUG = "{0}" + os.sep + "bin" + os.sep +\
  130. "java -server -XX:NewRatio=2 -XX:+UseConcMarkSweepGC " +\
  131. ambari_provider_module_option +\
  132. os.getenv('AMBARI_JVM_ARGS', '-Xms512m -Xmx2048m') +\
  133. " -Xdebug -Xrunjdwp:transport=dt_socket,address=5005,"\
  134. "server=y,suspend=n -cp {1}" + os.pathsep + "{2}" +\
  135. " org.apache.ambari.server.controller.AmbariServer"
  136. SERVER_SEARCH_PATTERN = "org.apache.ambari.server.controller.AmbariServer"
  137. SECURITY_PROVIDER_GET_CMD = "{0}" + os.sep + "bin" + os.sep + "java -cp {1}" +\
  138. os.pathsep + "{2} " +\
  139. "org.apache.ambari.server.security.encryption" +\
  140. ".CredentialProvider GET {3} {4} {5} " +\
  141. "> " + SERVER_OUT_FILE + " 2>&1"
  142. SECURITY_PROVIDER_PUT_CMD = "{0}" + os.sep + "bin" + os.sep + "java -cp {1}" +\
  143. os.pathsep + "{2} " +\
  144. "org.apache.ambari.server.security.encryption" +\
  145. ".CredentialProvider PUT {3} {4} {5} " +\
  146. "> " + SERVER_OUT_FILE + " 2>&1"
  147. SECURITY_PROVIDER_KEY_CMD = "{0}" + os.sep + "bin" + os.sep + "java -cp {1}" +\
  148. os.pathsep + "{2} " +\
  149. "org.apache.ambari.server.security.encryption" +\
  150. ".MasterKeyServiceImpl {3} {4} {5} " +\
  151. "> " + SERVER_OUT_FILE + " 2>&1"
  152. SCHEMA_UPGRADE_HELPER_CMD = "{0}" + os.sep + "bin" + os.sep + "java -cp {1}" +\
  153. os.pathsep + "{2} " +\
  154. "org.apache.ambari.server.upgrade.SchemaUpgradeHelper" +\
  155. " > " + SERVER_OUT_FILE + " 2>&1"
  156. STACK_UPGRADE_HELPER_CMD = "{0}" + os.sep + "bin" + os.sep + "java -cp {1}" +\
  157. os.pathsep + "{2} " +\
  158. "org.apache.ambari.server.upgrade.StackUpgradeHelper" +\
  159. " {3} {4} > " + SERVER_OUT_FILE + " 2>&1"
  160. ULIMIT_CMD = "ulimit -n"
  161. SERVER_INIT_TIMEOUT = 5
  162. SERVER_START_TIMEOUT = 10
  163. SECURITY_KEYS_DIR = "security.server.keys_dir"
  164. SECURITY_MASTER_KEY_LOCATION = "security.master.key.location"
  165. SECURITY_KEY_IS_PERSISTED = "security.master.key.ispersisted"
  166. SECURITY_KEY_ENV_VAR_NAME = "AMBARI_SECURITY_MASTER_KEY"
  167. SECURITY_MASTER_KEY_FILENAME = "master"
  168. SECURITY_IS_ENCRYPTION_ENABLED = "security.passwords.encryption.enabled"
  169. SECURITY_KERBEROS_JASS_FILENAME = "krb5JAASLogin.conf"
  170. SSL_KEY_DIR = 'security.server.keys_dir'
  171. SSL_API_PORT = 'client.api.ssl.port'
  172. SSL_API = 'api.ssl'
  173. SSL_SERVER_CERT_NAME = 'client.api.ssl.cert_name'
  174. SSL_SERVER_KEY_NAME = 'client.api.ssl.key_name'
  175. SSL_CERT_FILE_NAME = "https.crt"
  176. SSL_KEY_FILE_NAME = "https.key"
  177. SSL_KEYSTORE_FILE_NAME = "https.keystore.p12"
  178. SSL_KEY_PASSWORD_FILE_NAME = "https.pass.txt"
  179. SSL_KEY_PASSWORD_LENGTH = 50
  180. DEFAULT_SSL_API_PORT = 8443
  181. SSL_DATE_FORMAT = '%b %d %H:%M:%S %Y GMT'
  182. GANGLIA_HTTPS = 'ganglia.https'
  183. NAGIOS_HTTPS = 'nagios.https'
  184. JDBC_RCA_PASSWORD_ALIAS = "ambari.db.password"
  185. CLIENT_SECURITY_KEY = "client.security"
  186. LDAP_MGR_PASSWORD_ALIAS = "ambari.ldap.manager.password"
  187. LDAP_MGR_PASSWORD_PROPERTY = "authentication.ldap.managerPassword"
  188. LDAP_MGR_USERNAME_PROPERTY = "authentication.ldap.managerDn"
  189. SSL_TRUSTSTORE_PASSWORD_ALIAS = "ambari.ssl.trustStore.password"
  190. SSL_TRUSTSTORE_PATH_PROPERTY = "ssl.trustStore.path"
  191. SSL_TRUSTSTORE_PASSWORD_PROPERTY = "ssl.trustStore.password"
  192. SSL_TRUSTSTORE_TYPE_PROPERTY = "ssl.trustStore.type"
  193. AMBARI_CONF_VAR = "AMBARI_CONF_DIR"
  194. AMBARI_SERVER_LIB = "AMBARI_SERVER_LIB"
  195. JAVA_HOME = "JAVA_HOME"
  196. PID_DIR = "/var/run/ambari-server"
  197. BOOTSTRAP_DIR_PROPERTY = "bootstrap.dir"
  198. PID_NAME = "ambari-server.pid"
  199. EXITCODE_NAME = "ambari-server.exitcode"
  200. AMBARI_PROPERTIES_FILE = "ambari.properties"
  201. AMBARI_PROPERTIES_RPMSAVE_FILE = "ambari.properties.rpmsave"
  202. RESOURCES_DIR_PROPERTY = "resources.dir"
  203. SETUP_DB_CONNECT_TIMEOUT = 5
  204. SETUP_DB_CONNECT_ATTEMPTS = 3
  205. SETUP_DB_CMD = ['su', '-', 'postgres',
  206. '--command=psql -f {0} -v username=\'"{1}"\' -v password="\'{2}\'" -v dbname="{3}"']
  207. UPGRADE_STACK_CMD = ['su', 'postgres',
  208. '--command=psql -f {0} -v stack_name="\'{1}\'" -v stack_version="\'{2}\'" -v dbname="{3}"']
  209. CHANGE_OWNER_COMMAND = ['su', '-', 'postgres',
  210. '--command=/var/lib/ambari-server/resources/scripts/change_owner.sh -d {0} -s {1} -o {2}']
  211. PG_ERROR_BLOCKED = "is being accessed by other users"
  212. PG_STATUS_RUNNING = utils.get_postgre_running_status(OS_TYPE)
  213. PG_DEFAULT_PASSWORD = "bigdata"
  214. SERVICE_CMD = "/usr/bin/env service"
  215. PG_SERVICE_NAME = "postgresql"
  216. PG_HBA_DIR = utils.get_postgre_hba_dir(OS_TYPE)
  217. PG_ST_CMD = "%s %s status" % (SERVICE_CMD, PG_SERVICE_NAME)
  218. if os.path.isfile("/usr/bin/postgresql-setup"):
  219. PG_INITDB_CMD = "/usr/bin/postgresql-setup initdb"
  220. else:
  221. PG_INITDB_CMD = "%s %s initdb" % (SERVICE_CMD, PG_SERVICE_NAME)
  222. PG_START_CMD = "%s %s start" % (SERVICE_CMD, PG_SERVICE_NAME)
  223. PG_RESTART_CMD = "%s %s restart" % (SERVICE_CMD, PG_SERVICE_NAME)
  224. PG_HBA_RELOAD_CMD = "%s %s reload" % (SERVICE_CMD, PG_SERVICE_NAME)
  225. PG_HBA_CONF_FILE = os.path.join(PG_HBA_DIR, "pg_hba.conf")
  226. PG_HBA_CONF_FILE_BACKUP = os.path.join(PG_HBA_DIR, "pg_hba_bak.conf.old")
  227. POSTGRESQL_CONF_FILE = os.path.join(PG_HBA_DIR, "postgresql.conf")
  228. SERVER_VERSION_FILE_PATH = "server.version.file"
  229. #TODO property used incorrectly in local case, it was meant to be dbms name, not postgres database name,
  230. # has workaround for now, as we don't need dbms name if persistence_type=local
  231. JDBC_DATABASE_PROPERTY = "server.jdbc.database"
  232. JDBC_HOSTNAME_PROPERTY = "server.jdbc.hostname"
  233. JDBC_PORT_PROPERTY = "server.jdbc.port"
  234. JDBC_SCHEMA_PROPERTY = "server.jdbc.schema"
  235. JDBC_USER_NAME_PROPERTY = "server.jdbc.user.name"
  236. JDBC_PASSWORD_PROPERTY = "server.jdbc.user.passwd"
  237. JDBC_PASSWORD_FILENAME = "password.dat"
  238. JDBC_RCA_PASSWORD_FILENAME = "rca_password.dat"
  239. CLIENT_API_PORT_PROPERTY = "client.api.port"
  240. CLIENT_API_PORT = "8080"
  241. SRVR_TWO_WAY_SSL_PORT_PROPERTY = "security.server.two_way_ssl.port"
  242. SRVR_TWO_WAY_SSL_PORT = "8441"
  243. SRVR_ONE_WAY_SSL_PORT_PROPERTY = "security.server.one_way_ssl.port"
  244. SRVR_ONE_WAY_SSL_PORT = "8440"
  245. PERSISTENCE_TYPE_PROPERTY = "server.persistence.type"
  246. JDBC_DRIVER_PROPERTY = "server.jdbc.driver"
  247. JDBC_URL_PROPERTY = "server.jdbc.url"
  248. JDBC_RCA_DATABASE_PROPERTY = "server.jdbc.database"
  249. JDBC_RCA_HOSTNAME_PROPERTY = "server.jdbc.hostname"
  250. JDBC_RCA_PORT_PROPERTY = "server.jdbc.port"
  251. JDBC_RCA_SCHEMA_PROPERTY = "server.jdbc.schema"
  252. JDBC_RCA_DRIVER_PROPERTY = "server.jdbc.rca.driver"
  253. JDBC_RCA_URL_PROPERTY = "server.jdbc.rca.url"
  254. JDBC_RCA_USER_NAME_PROPERTY = "server.jdbc.rca.user.name"
  255. JDBC_RCA_PASSWORD_FILE_PROPERTY = "server.jdbc.rca.user.passwd"
  256. CHECK_COMMAND_EXIST_CMD = "type {0}"
  257. DATABASE_INDEX = 0
  258. PROMPT_DATABASE_OPTIONS = False
  259. USERNAME_PATTERN = "^[a-zA-Z_][a-zA-Z0-9_\-]*$"
  260. PASSWORD_PATTERN = "^[a-zA-Z0-9_-]*$"
  261. DATABASE_NAMES = ["postgres", "oracle", "mysql"]
  262. DATABASE_STORAGE_NAMES = ["Database", "Service", "Database"]
  263. DATABASE_PORTS = ["5432", "1521", "3306"]
  264. DATABASE_DRIVER_NAMES = ["org.postgresql.Driver", "oracle.jdbc.driver.OracleDriver", "com.mysql.jdbc.Driver"]
  265. DATABASE_CONNECTION_STRINGS = [
  266. "jdbc:postgresql://{0}:{1}/{2}",
  267. "jdbc:oracle:thin:@{0}:{1}/{2}",
  268. "jdbc:mysql://{0}:{1}/{2}"]
  269. DATABASE_CONNECTION_STRINGS_ALT = [
  270. "jdbc:postgresql://{0}:{1}/{2}",
  271. "jdbc:oracle:thin:@{0}:{1}:{2}",
  272. "jdbc:mysql://{0}:{1}/{2}"]
  273. ORACLE_SID_PATTERN = "jdbc:oracle:thin:@.+:.+/.+"
  274. ORACLE_SNAME_PATTERN = "jdbc:oracle:thin:@.+:.+:.+"
  275. DATABASE_CLI_TOOLS = [["psql"], ["sqlplus", "sqlplus64"], ["mysql"]]
  276. DATABASE_CLI_TOOLS_DESC = ["psql", "sqlplus", "mysql"]
  277. DATABASE_CLI_TOOLS_USAGE = ['su -postgres --command=psql -f {0} -v username=\'"{1}"\' -v password="\'{2}\'"',
  278. 'sqlplus {1}/{2} < {0} ',
  279. 'mysql --user={1} --password={2} {3}<{0}']
  280. MYSQL_INIT_SCRIPT = '/var/lib/ambari-server/resources/Ambari-DDL-MySQL-CREATE.sql'
  281. DATABASE_INIT_SCRIPTS = ['/var/lib/ambari-server/resources/Ambari-DDL-Postgres-CREATE.sql',
  282. '/var/lib/ambari-server/resources/Ambari-DDL-Oracle-CREATE.sql',
  283. MYSQL_INIT_SCRIPT]
  284. DATABASE_DROP_SCRIPTS = ['/var/lib/ambari-server/resources/Ambari-DDL-Postgres-DROP.sql',
  285. '/var/lib/ambari-server/resources/Ambari-DDL-Oracle-DROP.sql',
  286. '/var/lib/ambari-server/resources/Ambari-DDL-MySQL-DROP.sql']
  287. JDBC_PROPERTIES_PREFIX = "server.jdbc.properties."
  288. DATABASE_JDBC_PROPERTIES = [
  289. [ ],
  290. [
  291. ["oracle.net.CONNECT_TIMEOUT", "2000"], # socket level timeout
  292. ["oracle.net.READ_TIMEOUT", "2000"], # socket level timeout
  293. ["oracle.jdbc.ReadTimeout", "8000"] # query fetch timeout
  294. ],
  295. [ ]
  296. ]
  297. REGEX_IP_ADDRESS = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"
  298. REGEX_HOSTNAME = "^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$"
  299. REGEX_HOSTNAME_PORT = "^(.*:[0-9]{1,5}$)"
  300. REGEX_TRUE_FALSE = "^(true|false)?$"
  301. REGEX_ANYTHING = ".*"
  302. POSTGRES_EXEC_ARGS = "-h {0} -p {1} -d {2} -U {3} -f {4} -v username='{3}'"
  303. ORACLE_EXEC_ARGS = "-S -L '{0}/{1}@(description=(address=(protocol=TCP)(host={2})(port={3}))(connect_data=({6}={4})))' @{5} {0}"
  304. MYSQL_EXEC_ARGS_WITH_USER_VARS = "--host={0} --port={1} --user={2} --password={3} {4} " \
  305. "-e\"set @schema=\'{4}\'; set @username=\'{2}\'; source {5};\""
  306. MYSQL_EXEC_ARGS_WO_USER_VARS = "--force --host={0} --port={1} --user={2} --password={3} --database={4} < {5} 2> /dev/null"
  307. MYSQL_UPGRADE_STACK_ARGS = "--host={0} --port={1} --user={2} --password={3} --database={4} " \
  308. "-e\"set @stackName=\'{6}\'; set @stackVersion=\'{7}\'; source {5};\""
  309. ORACLE_UPGRADE_STACK_ARGS = "-S -L '{0}/{1}@(description=(address=(protocol=TCP)(host={2})(port={3}))(connect_data=({6}={4})))' @{5} {7} {8}"
  310. JDBC_PATTERNS = {"oracle": "*ojdbc*.jar", "mysql": "*mysql*.jar"}
  311. DATABASE_FULL_NAMES = {"oracle": "Oracle", "mysql": "MySQL", "postgres": "PostgreSQL"}
  312. JDBC_DB_OPTION_VALUES = ["postgresql", "mysql", "oracle"]
  313. JDBC_DB_DEFAULT_DRIVER = {"postgresql" : "postgresql-jdbc.jar", "mysql" : "mysql-connector-java.jar", "oracle" : "ojdbc6.jar"}
  314. ORACLE_DB_ID_TYPES = ["Service Name", "SID"]
  315. # jdk commands
  316. JDK_NAMES = ["jdk-7u45-linux-x64.tar.gz", "jdk-6u31-linux-x64.bin"]
  317. JDK_URL_PROPERTIES = ["jdk1.7.url", "jdk1.6.url"]
  318. JCE_URL_PROPERTIES = ["jce_policy1.7.url", "jce_policy1.6.url"]
  319. DEFAULT_JDK16_LOCATION = "/usr/jdk64/jdk1.6.0_31"
  320. JDK_INDEX = 0
  321. JDK_VERSION_REs = ["(jdk.*)/jre", "Creating (jdk.*)/jre"]
  322. CUSTOM_JDK_NUMBER = "3"
  323. JDK_MIN_FILESIZE = 5000
  324. JDK_INSTALL_DIR = "/usr/jdk64"
  325. CREATE_JDK_DIR_CMD = "/bin/mkdir -p " + JDK_INSTALL_DIR
  326. MAKE_FILE_EXECUTABLE_CMD = "chmod a+x {0}"
  327. JAVA_HOME_PROPERTY = "java.home"
  328. JDK_NAME_PROPERTY = "jdk.name"
  329. JCE_NAME_PROPERTY = "jce.name"
  330. OS_TYPE_PROPERTY = "server.os_type"
  331. GET_FQDN_SERVICE_URL = "server.fqdn.service.url"
  332. JDK_DOWNLOAD_CMD = "curl --create-dirs -o {0} {1}"
  333. JDK_DOWNLOAD_SIZE_CMD = "curl -I {0}"
  334. UNTAR_JDK_ARVHIVE = "tar -xvf {0}"
  335. #JCE Policy files
  336. JCE_POLICY_FILENAMES = ["UnlimitedJCEPolicyJDK7.zip", "jce_policy-6.zip"]
  337. JCE_DOWNLOAD_CMD = "curl -o {0} {1}"
  338. JCE_MIN_FILESIZE = 5000
  339. DEFAULT_DB_NAME = "ambari"
  340. # stack repo upgrade
  341. STACK_LOCATION_KEY = 'metadata.path'
  342. STACK_LOCATION_DEFAULT = '/var/lib/ambari-server/resources/stacks'
  343. # linux open-file limit
  344. ULIMIT_OPEN_FILES_KEY = 'ulimit.open.files'
  345. ULIMIT_OPEN_FILES_DEFAULT = 10000
  346. #Apache License Header
  347. ASF_LICENSE_HEADER = '''
  348. # Copyright 2011 The Apache Software Foundation
  349. #
  350. # Licensed to the Apache Software Foundation (ASF) under one
  351. # or more contributor license agreements. See the NOTICE file
  352. # distributed with this work for additional information
  353. # regarding copyright ownership. The ASF licenses this file
  354. # to you under the Apache License, Version 2.0 (the
  355. # "License"); you may not use this file except in compliance
  356. # with the License. You may obtain a copy of the License at
  357. #
  358. # http://www.apache.org/licenses/LICENSE-2.0
  359. #
  360. # Unless required by applicable law or agreed to in writing, software
  361. # distributed under the License is distributed on an "AS IS" BASIS,
  362. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  363. # See the License for the specific language governing permissions and
  364. # limitations under the License.
  365. '''
  366. class FirewallChecks(object):
  367. def __init__(self):
  368. self.FIREWALL_SERVICE_NAME = "iptables"
  369. self.SERVICE_CMD = SERVICE_CMD
  370. self.SERVICE_SUBCMD = "status"
  371. def get_command(self):
  372. return "%s %s %s" % (self.SERVICE_CMD, self.FIREWALL_SERVICE_NAME, self.SERVICE_SUBCMD)
  373. def check_result(self, retcode, out, err):
  374. return retcode == 0
  375. def check_iptables(self):
  376. retcode, out, err = run_os_command(self.get_command())
  377. if err and len(err) > 0:
  378. print err
  379. if self.check_result(retcode, out, err):
  380. print_warning_msg("%s is running. Confirm the necessary Ambari ports are accessible. " %
  381. self.FIREWALL_SERVICE_NAME +
  382. "Refer to the Ambari documentation for more details on ports.")
  383. ok = get_YN_input("OK to continue [y/n] (y)? ", True)
  384. if not ok:
  385. raise FatalException(1, None)
  386. def get_running_result(self):
  387. # To support test code. Expected ouput from run_os_command.
  388. return (0, "", "")
  389. def get_stopped_result(self):
  390. # To support test code. Expected output from run_os_command.
  391. return (3, "", "")
  392. class UbuntuFirewallChecks(FirewallChecks):
  393. def __init__(self):
  394. super(UbuntuFirewallChecks, self).__init__()
  395. self.FIREWALL_SERVICE_NAME = "ufw"
  396. self.SERVICE_CMD = utils.locate_file('service', '/usr/sbin')
  397. def check_result(self, retcode, out, err):
  398. # On ubuntu, the status command returns 0 whether running or not
  399. return out and len(out) > 0 and out.strip() != "ufw stop/waiting"
  400. def get_running_result(self):
  401. # To support test code. Expected ouput from run_os_command.
  402. return (0, "ufw start/running", "")
  403. def get_stopped_result(self):
  404. # To support test code. Expected output from run_os_command.
  405. return (0, "ufw stop/waiting", "")
  406. class Fedora18FirewallChecks(FirewallChecks):
  407. def __init__(self):
  408. self.FIREWALL_SERVICE_NAME = "firewalld.service"
  409. def get_command(self):
  410. return "systemctl is-active firewalld.service"
  411. class OpenSuseFirewallChecks(FirewallChecks):
  412. def __init__(self):
  413. self.FIREWALL_SERVICE_NAME = "SuSEfirewall2"
  414. def get_command(self):
  415. return "/sbin/SuSEfirewall2 status"
  416. def get_firewall_object():
  417. if OS_TYPE == OSConst.OS_UBUNTU:
  418. return UbuntuFirewallChecks()
  419. elif OS_TYPE == OSConst.OS_FEDORA and int(OS_VERSION) >= 18:
  420. return Fedora18FirewallChecks()
  421. elif OS_TYPE == OSConst.OS_OPENSUSE:
  422. return OpenSuseFirewallChecks()
  423. else:
  424. return FirewallChecks()
  425. def get_firewall_object_types():
  426. # To support test code, so tests can loop through the types
  427. return (FirewallChecks,
  428. UbuntuFirewallChecks,
  429. Fedora18FirewallChecks,
  430. OpenSuseFirewallChecks)
  431. def check_iptables():
  432. return get_firewall_object().check_iptables()
  433. def get_conf_dir():
  434. try:
  435. conf_dir = os.environ[AMBARI_CONF_VAR]
  436. return conf_dir
  437. except KeyError:
  438. default_conf_dir = "/etc/ambari-server/conf"
  439. print AMBARI_CONF_VAR + " is not set, using default " + default_conf_dir
  440. return default_conf_dir
  441. def find_properties_file():
  442. conf_file = search_file(AMBARI_PROPERTIES_FILE, get_conf_dir())
  443. if conf_file is None:
  444. err = 'File %s not found in search path $%s: %s' % (AMBARI_PROPERTIES_FILE,
  445. AMBARI_CONF_VAR, get_conf_dir())
  446. print err
  447. raise FatalException(1, err)
  448. else:
  449. print_info_msg('Loading properties from ' + conf_file)
  450. return conf_file
  451. def update_ambari_properties():
  452. prev_conf_file = search_file(AMBARI_PROPERTIES_RPMSAVE_FILE, get_conf_dir())
  453. conf_file = search_file(AMBARI_PROPERTIES_FILE, get_conf_dir())
  454. # Previous config file does not exist
  455. if (not prev_conf_file) or (prev_conf_file is None):
  456. print_warning_msg("Can not find ambari.properties.rpmsave file from previous version, skipping import of settings")
  457. return 0
  458. try:
  459. old_properties = Properties()
  460. old_properties.load(open(prev_conf_file))
  461. except Exception, e:
  462. print 'Could not read "%s": %s' % (prev_conf_file, e)
  463. return -1
  464. try:
  465. new_properties = Properties()
  466. new_properties.load(open(conf_file))
  467. for prop_key, prop_value in old_properties.getPropertyDict().items():
  468. if ("agent.fqdn.service.url" == prop_key):
  469. #BUG-7179 what is agent.fqdn property in ambari.props?
  470. new_properties.process_pair(GET_FQDN_SERVICE_URL, prop_value)
  471. elif ("server.os_type" == prop_key):
  472. new_properties.process_pair(OS_TYPE_PROPERTY, OS_FAMILY + OS_VERSION)
  473. else:
  474. new_properties.process_pair(prop_key, prop_value)
  475. # Adding custom user name property if it is absent
  476. # In previous versions without custom user support server was started as
  477. # "root" anyway so it's a reasonable default
  478. if not NR_USER_PROPERTY in new_properties.keys():
  479. new_properties.process_pair(NR_USER_PROPERTY, "root")
  480. isJDK16Installed = new_properties.get_property(JAVA_HOME_PROPERTY) == DEFAULT_JDK16_LOCATION
  481. if not JDK_NAME_PROPERTY in new_properties.keys() and isJDK16Installed:
  482. new_properties.process_pair(JDK_NAME_PROPERTY, JDK_NAMES[1])
  483. if not JCE_NAME_PROPERTY in new_properties.keys() and isJDK16Installed:
  484. new_properties.process_pair(JCE_NAME_PROPERTY, JCE_POLICY_FILENAMES[1])
  485. new_properties.store(open(conf_file, 'w'))
  486. except Exception, e:
  487. print 'Could not write "%s": %s' % (conf_file, e)
  488. return -1
  489. timestamp = datetime.datetime.now()
  490. format = '%Y%m%d%H%M%S'
  491. os.rename(prev_conf_file, prev_conf_file + '.' + timestamp.strftime(format))
  492. return 0
  493. NR_CONF_DIR = get_conf_dir()
  494. # ownership/permissions mapping
  495. # path - permissions - user - group - recursive
  496. # Rules are executed in the same order as they are listed
  497. # {0} in user/group will be replaced by customized ambari-server username
  498. NR_ADJUST_OWNERSHIP_LIST = [
  499. ("/var/log/ambari-server", "644", "{0}", True),
  500. ("/var/log/ambari-server", "755", "{0}", False),
  501. ("/var/run/ambari-server", "644", "{0}", True),
  502. ("/var/run/ambari-server", "755", "{0}", False),
  503. ("/var/run/ambari-server/bootstrap", "755", "{0}", False),
  504. ("/var/lib/ambari-server/ambari-env.sh", "700", "{0}", False),
  505. ("/var/lib/ambari-server/keys", "600", "{0}", True),
  506. ("/var/lib/ambari-server/keys", "700", "{0}", False),
  507. ("/var/lib/ambari-server/keys/db", "700", "{0}", False),
  508. ("/var/lib/ambari-server/keys/db/newcerts", "700", "{0}", False),
  509. ("/var/lib/ambari-server/keys/.ssh", "700", "{0}", False),
  510. ("/var/lib/ambari-server/resources/stacks/", "755", "{0}", True),
  511. ("/var/lib/ambari-server/resources/custom_actions/", "755", "{0}", True),
  512. ("/etc/ambari-server/conf", "644", "{0}", True),
  513. ("/etc/ambari-server/conf", "755", "{0}", False),
  514. ("/etc/ambari-server/conf/password.dat", "640", "{0}", False),
  515. # Also, /etc/ambari-server/conf/password.dat
  516. # is generated later at store_password_file
  517. ]
  518. ### System interaction ###
  519. class FatalException(Exception):
  520. def __init__(self, code, reason):
  521. self.code = code
  522. self.reason = reason
  523. def __str__(self):
  524. return repr("Fatal exception: %s, exit code %s" % (self.reason, self.code))
  525. def _get_message(self):
  526. return str(self)
  527. class NonFatalException(Exception):
  528. def __init__(self, reason):
  529. self.reason = reason
  530. def __str__(self):
  531. return repr("NonFatal exception: %s" % self.reason)
  532. def _get_message(self):
  533. return str(self)
  534. def is_root():
  535. '''
  536. Checks effective UUID
  537. Returns True if a program is running under root-level privileges.
  538. '''
  539. return os.geteuid() == 0
  540. def get_exec_path(cmd):
  541. cmd = 'which {0}'.format(cmd)
  542. ret, out, err = run_in_shell(cmd)
  543. if ret == 0:
  544. return out.strip()
  545. else:
  546. return None
  547. def run_in_shell(cmd):
  548. print_info_msg('about to run command: ' + str(cmd))
  549. process = subprocess.Popen(cmd,
  550. stdout=subprocess.PIPE,
  551. stdin=subprocess.PIPE,
  552. stderr=subprocess.PIPE,
  553. shell=True
  554. )
  555. (stdoutdata, stderrdata) = process.communicate()
  556. return process.returncode, stdoutdata, stderrdata
  557. def run_os_command(cmd):
  558. print_info_msg('about to run command: ' + str(cmd))
  559. if type(cmd) == str:
  560. cmd = shlex.split(cmd)
  561. process = subprocess.Popen(cmd,
  562. stdout=subprocess.PIPE,
  563. stdin=subprocess.PIPE,
  564. stderr=subprocess.PIPE
  565. )
  566. (stdoutdata, stderrdata) = process.communicate()
  567. return process.returncode, stdoutdata, stderrdata
  568. #
  569. # Checks SELinux
  570. #
  571. def check_selinux():
  572. try:
  573. retcode, out, err = run_os_command(GET_SE_LINUX_ST_CMD)
  574. se_status = re.search('(disabled|enabled)', out).group(0)
  575. print "SELinux status is '" + se_status + "'"
  576. if se_status == SE_STATUS_DISABLED:
  577. return 0
  578. else:
  579. try:
  580. se_mode = re.search('(enforcing|permissive)', out).group(0)
  581. except AttributeError:
  582. err = "Error determining SELinux mode. Exiting."
  583. raise FatalException(1, err)
  584. print "SELinux mode is '" + se_mode + "'"
  585. if se_mode == SE_MODE_ENFORCING:
  586. print "Temporarily disabling SELinux"
  587. run_os_command(SE_SETENFORCE_CMD)
  588. print_warning_msg(
  589. "SELinux is set to 'permissive' mode and temporarily disabled.")
  590. ok = get_YN_input("OK to continue [y/n] (y)? ", True)
  591. if not ok:
  592. raise FatalException(1, None)
  593. return 0
  594. except OSError:
  595. print_warning_msg("Could not run {0}: OK".format(GET_SE_LINUX_ST_CMD))
  596. return 0
  597. def read_ambari_user():
  598. '''
  599. Reads ambari user from properties file
  600. '''
  601. conf_file = find_properties_file()
  602. try:
  603. properties = Properties()
  604. properties.load(open(conf_file))
  605. user = properties[NR_USER_PROPERTY]
  606. if user:
  607. return user
  608. else:
  609. return None
  610. except Exception, e:
  611. print_error_msg('Could not read "%s": %s' % (conf_file, e))
  612. return None
  613. def adjust_directory_permissions(ambari_user):
  614. properties = get_ambari_properties()
  615. bootstrap_dir = get_value_from_properties(properties, BOOTSTRAP_DIR_PROPERTY)
  616. print_info_msg("Cleaning bootstrap directory ({0}) contents...".format(bootstrap_dir))
  617. cmd = RECURSIVE_RM_CMD.format(bootstrap_dir)
  618. run_os_command(cmd)
  619. os.makedirs(bootstrap_dir)
  620. # Add master key and credential store if exists
  621. keyLocation = get_master_key_location(properties)
  622. masterKeyFile = search_file(SECURITY_MASTER_KEY_FILENAME, keyLocation)
  623. if masterKeyFile:
  624. NR_ADJUST_OWNERSHIP_LIST.append((masterKeyFile, "600", "{0}", "{0}", False))
  625. credStoreFile = get_credential_store_location(properties)
  626. if os.path.exists(credStoreFile):
  627. NR_ADJUST_OWNERSHIP_LIST.append((credStoreFile, "600", "{0}", "{0}", False))
  628. trust_store_location = properties[SSL_TRUSTSTORE_PATH_PROPERTY]
  629. if trust_store_location:
  630. NR_ADJUST_OWNERSHIP_LIST.append((trust_store_location, "600", "{0}", "{0}", False))
  631. print "Adjusting ambari-server permissions and ownership..."
  632. for pack in NR_ADJUST_OWNERSHIP_LIST:
  633. file = pack[0]
  634. mod = pack[1]
  635. user = pack[2].format(ambari_user)
  636. recursive = pack[3]
  637. set_file_permissions(file, mod, user, recursive)
  638. def set_file_permissions(file, mod, user, recursive):
  639. WARN_MSG = "Command {0} returned exit code {1} with message: {2}"
  640. if recursive:
  641. params = " -R "
  642. else:
  643. params = ""
  644. if os.path.exists(file):
  645. command = NR_CHMOD_CMD.format(params, mod, file)
  646. retcode, out, err = run_os_command(command)
  647. if retcode != 0:
  648. print_warning_msg(WARN_MSG.format(command, file, err))
  649. command = NR_CHOWN_CMD.format(params, user, file)
  650. retcode, out, err = run_os_command(command)
  651. if retcode != 0:
  652. print_warning_msg(WARN_MSG.format(command, file, err))
  653. else:
  654. print_info_msg("File %s does not exist" % file)
  655. def create_custom_user():
  656. user = get_validated_string_input(
  657. "Enter user account for ambari-server daemon (root):",
  658. "root",
  659. "^[a-z_][a-z0-9_-]{1,31}$",
  660. "Invalid username.",
  661. False
  662. )
  663. print_info_msg("Trying to create user {0}".format(user))
  664. command = NR_USERADD_CMD.format(user, NR_USER_COMMENT)
  665. retcode, out, err = run_os_command(command)
  666. if retcode == 9: # 9 = username already in use
  667. print_info_msg("User {0} already exists, "
  668. "skipping user creation".format(user))
  669. elif retcode != 0: # fail
  670. print_warning_msg("Can't create user {0}. Command {1} "
  671. "finished with {2}: \n{3}".format(user, command, retcode, err))
  672. return retcode, None
  673. print_info_msg("User configuration is done.")
  674. return 0, user
  675. def check_reverse_lookup():
  676. """
  677. Check if host fqdn resolves to current host ip
  678. """
  679. try:
  680. host_name = socket.gethostname()
  681. host_ip = socket.gethostbyname(host_name)
  682. host_fqdn = socket.getfqdn()
  683. fqdn_ip = socket.gethostbyname(host_fqdn)
  684. return host_ip == fqdn_ip
  685. except socket.herror:
  686. pass
  687. return False
  688. def check_ambari_user():
  689. try:
  690. user = read_ambari_user()
  691. create_user = False
  692. update_user_setting = False
  693. if user is not None:
  694. create_user = get_YN_input("Ambari-server daemon is configured to run under user '{0}'."
  695. " Change this setting [y/n] (n)? ".format(user), False)
  696. update_user_setting = create_user # Only if we will create another user
  697. else: # user is not configured yet
  698. update_user_setting = True # Write configuration anyway
  699. create_user = get_YN_input("Customize user account for ambari-server "
  700. "daemon [y/n] (n)? ", False)
  701. if not create_user:
  702. user = "root"
  703. if create_user:
  704. (retcode, user) = create_custom_user()
  705. if retcode != 0:
  706. return retcode
  707. if update_user_setting:
  708. write_property(NR_USER_PROPERTY, user)
  709. adjust_directory_permissions(user)
  710. except OSError as e:
  711. print_error_msg("Failed: %s" % e.strerror)
  712. return 4
  713. except Exception as e:
  714. print_error_msg("Unexpected error %s" % e.message)
  715. return 1
  716. return 0
  717. ### Postgres ###
  718. def configure_pg_hba_ambaridb_users():
  719. args = optparse.Values()
  720. configure_database_username_password(args)
  721. with open(PG_HBA_CONF_FILE, "a") as pgHbaConf:
  722. pgHbaConf.write("\n")
  723. pgHbaConf.write("local all " + args.database_username +
  724. ",mapred md5")
  725. pgHbaConf.write("\n")
  726. pgHbaConf.write("host all " + args.database_username +
  727. ",mapred 0.0.0.0/0 md5")
  728. pgHbaConf.write("\n")
  729. pgHbaConf.write("host all " + args.database_username +
  730. ",mapred ::/0 md5")
  731. pgHbaConf.write("\n")
  732. retcode, out, err = run_os_command(PG_HBA_RELOAD_CMD)
  733. if not retcode == 0:
  734. raise FatalException(retcode, err)
  735. def configure_pg_hba_postgres_user():
  736. postgresString = "all postgres"
  737. for line in fileinput.input(PG_HBA_CONF_FILE, inplace=1):
  738. print re.sub('all\s*all', postgresString, line),
  739. os.chmod(PG_HBA_CONF_FILE, 0644)
  740. def configure_postgresql_conf():
  741. listenAddress = "listen_addresses = '*' #"
  742. for line in fileinput.input(POSTGRESQL_CONF_FILE, inplace=1):
  743. print re.sub('#+listen_addresses.*?(#|$)', listenAddress, line),
  744. os.chmod(POSTGRESQL_CONF_FILE, 0644)
  745. def configure_postgres():
  746. if os.path.isfile(PG_HBA_CONF_FILE):
  747. if not os.path.isfile(PG_HBA_CONF_FILE_BACKUP):
  748. shutil.copyfile(PG_HBA_CONF_FILE, PG_HBA_CONF_FILE_BACKUP)
  749. else:
  750. #Postgres has been configured before, must not override backup
  751. print "Backup for pg_hba found, reconfiguration not required"
  752. return 0
  753. configure_pg_hba_postgres_user()
  754. configure_pg_hba_ambaridb_users()
  755. os.chmod(PG_HBA_CONF_FILE, 0644)
  756. configure_postgresql_conf()
  757. #restart postgresql if already running
  758. pg_status = get_postgre_status()
  759. if pg_status == PG_STATUS_RUNNING:
  760. retcode = restart_postgres()
  761. return retcode
  762. return 0
  763. def restart_postgres():
  764. print "Restarting PostgreSQL"
  765. process = subprocess.Popen(PG_RESTART_CMD.split(' '),
  766. stdout=subprocess.PIPE,
  767. stdin=subprocess.PIPE,
  768. stderr=subprocess.PIPE
  769. )
  770. time.sleep(5)
  771. result = process.poll()
  772. if result is None:
  773. print_info_msg("Killing restart PostgresSQL process")
  774. process.kill()
  775. pg_status = get_postgre_status()
  776. # SUSE linux set status of stopped postgresql proc to unused
  777. if pg_status == "unused" or pg_status == "stopped":
  778. print_info_msg("PostgreSQL is stopped. Restarting ...")
  779. retcode, out, err = run_os_command(PG_START_CMD)
  780. return retcode
  781. return 0
  782. # todo: check if the scheme is already exist
  783. def write_property(key, value):
  784. conf_file = find_properties_file()
  785. properties = Properties()
  786. try:
  787. properties.load(open(conf_file))
  788. except Exception, e:
  789. print_error_msg('Could not read ambari config file "%s": %s' % (conf_file, e))
  790. return -1
  791. properties.process_pair(key, value)
  792. try:
  793. properties.store(open(conf_file, "w"))
  794. except Exception, e:
  795. print_error_msg('Could not write ambari config file "%s": %s' % (conf_file, e))
  796. return -1
  797. return 0
  798. def remove_property(key):
  799. conf_file = find_properties_file()
  800. properties = Properties()
  801. try:
  802. properties.load(open(conf_file))
  803. except Exception, e:
  804. print_error_msg('Could not read ambari config file "%s": %s' % (conf_file, e))
  805. return -1
  806. properties.removeOldProp(key)
  807. try:
  808. properties.store(open(conf_file, "w"))
  809. except Exception, e:
  810. print_error_msg('Could not write ambari config file "%s": %s' % (conf_file, e))
  811. return -1
  812. return 0
  813. def setup_db(args):
  814. #password access to ambari-server and mapred
  815. configure_database_username_password(args)
  816. dbname = args.database_name
  817. scriptFile = args.init_script_file
  818. username = args.database_username
  819. password = args.database_password
  820. #setup DB
  821. command = SETUP_DB_CMD[:]
  822. command[-1] = command[-1].format(scriptFile, username, password, dbname)
  823. for i in range(SETUP_DB_CONNECT_ATTEMPTS):
  824. sys.stdout.write('Connecting to local database...')
  825. retcode, outdata, errdata = run_os_command(command)
  826. if retcode == 0:
  827. print 'done.'
  828. return retcode, outdata, errdata
  829. timeOutMsg = 'connection timed out'
  830. if (i+1) < SETUP_DB_CONNECT_ATTEMPTS:
  831. timeOutMsg += '...retrying (%d)' % (i+1)
  832. print timeOutMsg
  833. time.sleep(SETUP_DB_CONNECT_TIMEOUT)
  834. print 'unable to connect to database'
  835. print_error_msg(errdata)
  836. return retcode, outdata, errdata
  837. def store_password_file(password, filename):
  838. conf_file = find_properties_file()
  839. passFilePath = os.path.join(os.path.dirname(conf_file),
  840. filename)
  841. with open(passFilePath, 'w+') as passFile:
  842. passFile.write(password)
  843. print_info_msg("Adjusting filesystem permissions")
  844. ambari_user = read_ambari_user()
  845. set_file_permissions(passFilePath, "660", ambari_user, False)
  846. return passFilePath
  847. def remove_password_file(filename):
  848. conf_file = find_properties_file()
  849. passFilePath = os.path.join(os.path.dirname(conf_file),
  850. filename)
  851. if os.path.exists(passFilePath):
  852. try:
  853. os.remove(passFilePath)
  854. except Exception, e:
  855. print_warning_msg('Unable to remove password file: ' + str(e))
  856. return 1
  857. pass
  858. return 0
  859. def execute_db_script(args, file):
  860. #password access to ambari-server and mapred
  861. configure_database_username_password(args)
  862. dbname = args.database_name
  863. username = args.database_username
  864. password = args.database_password
  865. command = SETUP_DB_CMD[:]
  866. command[-1] = command[-1].format(file, username, password, dbname)
  867. retcode, outdata, errdata = run_os_command(command)
  868. if not retcode == 0:
  869. print errdata
  870. return retcode
  871. def check_db_consistency(args, file):
  872. #password access to ambari-server and mapred
  873. configure_database_username_password(args)
  874. dbname = args.database_name
  875. username = args.database_username
  876. password = args.database_password
  877. command = SETUP_DB_CMD[:]
  878. command[-1] = command[-1].format(file, username, password, dbname)
  879. retcode, outdata, errdata = run_os_command(command)
  880. if not retcode == 0:
  881. print errdata
  882. return retcode
  883. else:
  884. # Assumes that the output is of the form ...\n<count>
  885. print_info_msg("Parsing output: " + outdata)
  886. lines = outdata.splitlines()
  887. if (lines[-1] == '3' or lines[-1] == '0'):
  888. return 0
  889. return -1
  890. def get_postgre_status():
  891. retcode, out, err = run_os_command(PG_ST_CMD)
  892. try:
  893. pg_status = re.search('(stopped|running)', out, re.IGNORECASE).group(0).lower()
  894. except AttributeError:
  895. pg_status = None
  896. return pg_status
  897. def check_postgre_up():
  898. pg_status = get_postgre_status()
  899. if pg_status == PG_STATUS_RUNNING:
  900. print_info_msg("PostgreSQL is running")
  901. return 0
  902. else:
  903. # run initdb only on non ubuntu systems as ubuntu does not have initdb cmd.
  904. if OS_TYPE != OSConst.OS_UBUNTU:
  905. print "Running initdb: This may take upto a minute."
  906. retcode, out, err = run_os_command(PG_INITDB_CMD)
  907. if retcode == 0:
  908. print out
  909. print "About to start PostgreSQL"
  910. try:
  911. process = subprocess.Popen(PG_START_CMD.split(' '),
  912. stdout=subprocess.PIPE,
  913. stdin=subprocess.PIPE,
  914. stderr=subprocess.PIPE
  915. )
  916. if OS_TYPE == OSConst.OS_SUSE:
  917. time.sleep(20)
  918. result = process.poll()
  919. print_info_msg("Result of postgres start cmd: " + str(result))
  920. if result is None:
  921. process.kill()
  922. pg_status = get_postgre_status()
  923. else:
  924. retcode = result
  925. else:
  926. out, err = process.communicate()
  927. retcode = process.returncode
  928. if pg_status == PG_STATUS_RUNNING:
  929. print_info_msg("Postgres process is running. Returning...")
  930. return 0
  931. except (Exception), e:
  932. pg_status = get_postgre_status()
  933. if pg_status == PG_STATUS_RUNNING:
  934. return 0
  935. else:
  936. print_error_msg("Postgres start failed. " + str(e))
  937. return 1
  938. return retcode
  939. def get_validated_db_name(database_name):
  940. return get_validated_string_input(
  941. DATABASE_STORAGE_NAMES[DATABASE_INDEX] + " Name ("
  942. + database_name + "): ",
  943. database_name,
  944. ".*",
  945. "Invalid " + DATABASE_STORAGE_NAMES[DATABASE_INDEX] + " name.",
  946. False
  947. )
  948. def get_validated_service_name(service_name, index):
  949. return get_validated_string_input(
  950. ORACLE_DB_ID_TYPES[index] + " (" + service_name + "): ",
  951. service_name,
  952. ".*",
  953. "Invalid " + ORACLE_DB_ID_TYPES[index] + ".",
  954. False
  955. )
  956. def read_password(passwordDefault=PG_DEFAULT_PASSWORD,
  957. passwordPattern=PASSWORD_PATTERN,
  958. passwordPrompt=None,
  959. passwordDescr=None):
  960. # setup password
  961. if passwordPrompt is None:
  962. passwordPrompt = 'Password (' + passwordDefault + '): '
  963. if passwordDescr is None:
  964. passwordDescr = "Invalid characters in password. Use only alphanumeric or " \
  965. "_ or - characters"
  966. password = get_validated_string_input(passwordPrompt, passwordDefault,
  967. passwordPattern, passwordDescr, True)
  968. if not password:
  969. print 'Password cannot be blank.'
  970. return read_password(passwordDefault, passwordPattern, passwordPrompt,
  971. passwordDescr)
  972. if password != passwordDefault:
  973. password1 = get_validated_string_input("Re-enter password: ",
  974. passwordDefault, passwordPattern, passwordDescr, True)
  975. if password != password1:
  976. print "Passwords do not match"
  977. return read_password(passwordDefault, passwordPattern, passwordPrompt,
  978. passwordDescr)
  979. return password
  980. def get_pass_file_path(conf_file):
  981. return os.path.join(os.path.dirname(conf_file),
  982. JDBC_PASSWORD_FILENAME)
  983. # Set database properties to default values
  984. def load_default_db_properties(args):
  985. args.persistence_type = 'local'
  986. args.dbms = DATABASE_NAMES[DATABASE_INDEX]
  987. args.database_host = "localhost"
  988. args.database_port = DATABASE_PORTS[DATABASE_INDEX]
  989. args.database_name = DEFAULT_DB_NAME
  990. args.database_username = "ambari"
  991. args.database_password = "bigdata"
  992. args.sid_or_sname = "sname"
  993. pass
  994. # Ask user for database conenction properties
  995. def prompt_db_properties(args):
  996. global DATABASE_INDEX
  997. if PROMPT_DATABASE_OPTIONS:
  998. load_default_db_properties(args)
  999. ok = get_YN_input("Enter advanced database configuration [y/n] (n)? ", False)
  1000. if ok:
  1001. print "=============================================================================="
  1002. print "Choose one of the following options:"
  1003. database_num = str(DATABASE_INDEX + 1)
  1004. database_num = get_validated_string_input(
  1005. "[1] - PostgreSQL (Embedded)\n[2] - Oracle\n[3] - MySQL\n[4] - PostgreSQL\n"
  1006. "==============================================================================\n"
  1007. "Enter choice (" + database_num + "): ",
  1008. database_num,
  1009. "^[1234]$",
  1010. "Invalid number.",
  1011. False
  1012. )
  1013. if int(database_num) == 1:
  1014. args.persistence_type = 'local'
  1015. args.database_index = 0
  1016. else:
  1017. args.persistence_type = 'remote'
  1018. selected_db_option = int(database_num)
  1019. if selected_db_option == 2:
  1020. args.database_index = 1
  1021. elif selected_db_option == 3:
  1022. args.database_index = 2
  1023. elif selected_db_option == 4:
  1024. args.database_index = 0
  1025. else:
  1026. print_info_msg('Unknown db option, default to embbeded postgres.')
  1027. args.database_index = 0
  1028. pass
  1029. pass
  1030. DATABASE_INDEX = args.database_index
  1031. args.dbms = DATABASE_NAMES[args.database_index]
  1032. if args.persistence_type != 'local':
  1033. args.database_host = get_validated_string_input(
  1034. "Hostname (" + args.database_host + "): ",
  1035. args.database_host,
  1036. "^[a-zA-Z0-9.\-]*$",
  1037. "Invalid hostname.",
  1038. False
  1039. )
  1040. args.database_port = DATABASE_PORTS[DATABASE_INDEX]
  1041. args.database_port = get_validated_string_input(
  1042. "Port (" + args.database_port + "): ",
  1043. args.database_port,
  1044. "^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$",
  1045. "Invalid port.",
  1046. False
  1047. )
  1048. if args.dbms == "oracle":
  1049. # Oracle uses service name or service id
  1050. idType = "1"
  1051. idType = get_validated_string_input(
  1052. "Select Oracle identifier type:\n1 - " + ORACLE_DB_ID_TYPES[0] +
  1053. "\n2 - " + ORACLE_DB_ID_TYPES[1] + "\n(" + idType + "): ",
  1054. idType,
  1055. "^[12]$",
  1056. "Invalid number.",
  1057. False
  1058. )
  1059. if idType == "2":
  1060. args.sid_or_sname = "sid"
  1061. IDTYPE_INDEX = int(idType) - 1
  1062. args.database_name = get_validated_service_name(args.database_name,
  1063. IDTYPE_INDEX)
  1064. elif args.dbms in ["mysql", "postgres"]:
  1065. args.database_name = get_validated_db_name(args.database_name)
  1066. else:
  1067. # other DB types
  1068. pass
  1069. pass
  1070. else:
  1071. args.database_host = "localhost"
  1072. args.database_port = DATABASE_PORTS[DATABASE_INDEX]
  1073. args.database_name = get_validated_db_name(args.database_name)
  1074. pass
  1075. # Username is common for Oracle/MySQL/Postgres
  1076. args.database_username = get_validated_string_input(
  1077. 'Username (' + args.database_username + '): ',
  1078. args.database_username,
  1079. USERNAME_PATTERN,
  1080. "Invalid characters in username. Start with _ or alpha "
  1081. "followed by alphanumeric or _ or - characters",
  1082. False
  1083. )
  1084. args.database_password = configure_database_password(True)
  1085. print_info_msg('Using database options: {database},{host},{port},{schema},{user},{password}'.format(
  1086. database=args.dbms,
  1087. host=args.database_host,
  1088. port=args.database_port,
  1089. schema=args.database_name,
  1090. user=args.database_username,
  1091. password=args.database_password
  1092. ))
  1093. # Store set of properties for remote database connection
  1094. def store_remote_properties(args):
  1095. properties = get_ambari_properties()
  1096. if properties == -1:
  1097. print_error_msg("Error getting ambari properties")
  1098. return -1
  1099. isSecure = get_is_secure(properties)
  1100. properties.process_pair(PERSISTENCE_TYPE_PROPERTY, "remote")
  1101. properties.process_pair(JDBC_DATABASE_PROPERTY, args.dbms)
  1102. properties.process_pair(JDBC_HOSTNAME_PROPERTY, args.database_host)
  1103. properties.process_pair(JDBC_PORT_PROPERTY, args.database_port)
  1104. properties.process_pair(JDBC_SCHEMA_PROPERTY, args.database_name)
  1105. properties.process_pair(JDBC_DRIVER_PROPERTY, DATABASE_DRIVER_NAMES[DATABASE_INDEX])
  1106. # fully qualify the hostname to make sure all the other hosts can connect
  1107. # to the jdbc hostname since its passed onto the agents for RCA
  1108. jdbc_hostname = args.database_host
  1109. if (args.database_host == "localhost"):
  1110. jdbc_hostname = socket.getfqdn()
  1111. connectionStringFormat = DATABASE_CONNECTION_STRINGS
  1112. if args.sid_or_sname == "sid":
  1113. connectionStringFormat = DATABASE_CONNECTION_STRINGS_ALT
  1114. properties.process_pair(JDBC_URL_PROPERTY, connectionStringFormat[DATABASE_INDEX].format(jdbc_hostname, args.database_port, args.database_name))
  1115. properties.process_pair(JDBC_USER_NAME_PROPERTY, args.database_username)
  1116. properties.process_pair(JDBC_PASSWORD_PROPERTY,
  1117. store_password_file(args.database_password, JDBC_PASSWORD_FILENAME))
  1118. # save any other defined properties to pass to JDBC
  1119. if DATABASE_INDEX < len(DATABASE_JDBC_PROPERTIES):
  1120. for pair in DATABASE_JDBC_PROPERTIES[DATABASE_INDEX]:
  1121. properties.process_pair(JDBC_PROPERTIES_PREFIX + pair[0], pair[1])
  1122. if isSecure:
  1123. encrypted_password = encrypt_password(JDBC_RCA_PASSWORD_ALIAS, args.database_password)
  1124. if encrypted_password != args.database_password:
  1125. properties.process_pair(JDBC_PASSWORD_PROPERTY, encrypted_password)
  1126. pass
  1127. properties.process_pair(JDBC_RCA_DRIVER_PROPERTY, DATABASE_DRIVER_NAMES[DATABASE_INDEX])
  1128. properties.process_pair(JDBC_RCA_URL_PROPERTY, connectionStringFormat[DATABASE_INDEX].format(jdbc_hostname, args.database_port, args.database_name))
  1129. properties.process_pair(JDBC_RCA_USER_NAME_PROPERTY, args.database_username)
  1130. properties.process_pair(JDBC_RCA_PASSWORD_FILE_PROPERTY,
  1131. store_password_file(args.database_password, JDBC_PASSWORD_FILENAME))
  1132. if isSecure:
  1133. encrypted_password = encrypt_password(JDBC_RCA_PASSWORD_ALIAS, args.database_password)
  1134. if encrypted_password != args.database_password:
  1135. properties.process_pair(JDBC_RCA_PASSWORD_FILE_PROPERTY, encrypted_password)
  1136. pass
  1137. conf_file = properties.fileName
  1138. try:
  1139. properties.store(open(conf_file, "w"))
  1140. except Exception, e:
  1141. print 'Could not write ambari config file "%s": %s' % (conf_file, e)
  1142. return -1
  1143. return 0
  1144. # Initialize remote database schema
  1145. def setup_remote_db(args):
  1146. setup_msg = "Before starting Ambari Server, you must run the following DDL " \
  1147. "against the database to create the schema: {0}".format(DATABASE_INIT_SCRIPTS[DATABASE_INDEX])
  1148. print_warning_msg(setup_msg)
  1149. proceed = get_YN_input("Proceed with configuring remote database connection properties [y/n] (y)? ", True)
  1150. retCode = 0 if proceed else -1
  1151. return retCode
  1152. # Get database client executable path
  1153. def get_db_cli_tool(args):
  1154. for tool in DATABASE_CLI_TOOLS[DATABASE_INDEX]:
  1155. cmd = CHECK_COMMAND_EXIST_CMD.format(tool)
  1156. ret, out, err = run_in_shell(cmd)
  1157. if ret == 0:
  1158. return get_exec_path(tool)
  1159. return None
  1160. #execute SQL script on remote database: Deprecated
  1161. def execute_remote_script(args, scriptPath):
  1162. print_warning_msg("Deprecated method called.")
  1163. tool = get_db_cli_tool(args)
  1164. if not tool:
  1165. # args.warnings.append('{0} not found. Please, run DDL script manually'.format(DATABASE_CLI_TOOLS[DATABASE_INDEX]))
  1166. if VERBOSE:
  1167. print_warning_msg('{0} not found'.format(DATABASE_CLI_TOOLS[DATABASE_INDEX]))
  1168. return -1, "Client wasn't found", "Client wasn't found"
  1169. if args.dbms == "postgres":
  1170. os.environ["PGPASSWORD"] = args.database_password
  1171. retcode, out, err = run_in_shell('{0} {1}'.format(tool, POSTGRES_EXEC_ARGS.format(
  1172. args.database_host,
  1173. args.database_port,
  1174. args.database_name,
  1175. args.database_username,
  1176. scriptPath
  1177. )))
  1178. return retcode, out, err
  1179. elif args.dbms == "oracle":
  1180. sid_or_sname = "sid"
  1181. if (hasattr(args, 'sid_or_sname') and args.sid_or_sname == "sname") or \
  1182. (hasattr(args, 'jdbc_url') and args.jdbc_url and re.match(ORACLE_SNAME_PATTERN, args.jdbc_url)):
  1183. print_info_msg("using SERVICE_NAME instead of SID for Oracle")
  1184. sid_or_sname = "service_name"
  1185. retcode, out, err = run_in_shell('{0} {1}'.format(tool, ORACLE_EXEC_ARGS.format(
  1186. args.database_username,
  1187. args.database_password,
  1188. args.database_host,
  1189. args.database_port,
  1190. args.database_name,
  1191. scriptPath,
  1192. sid_or_sname
  1193. )))
  1194. return retcode, out, err
  1195. elif args.dbms == "mysql":
  1196. MYSQL_EXEC_ARGS = MYSQL_EXEC_ARGS_WO_USER_VARS if MYSQL_INIT_SCRIPT == scriptPath else MYSQL_EXEC_ARGS_WITH_USER_VARS
  1197. retcode, out, err = run_in_shell('{0} {1}'.format(tool, MYSQL_EXEC_ARGS.format(
  1198. args.database_host,
  1199. args.database_port,
  1200. args.database_username,
  1201. args.database_password,
  1202. args.database_name,
  1203. scriptPath
  1204. )))
  1205. return retcode, out, err
  1206. return -2, "Wrong database", "Wrong database"
  1207. def configure_database_password(showDefault=True):
  1208. passwordDefault = PG_DEFAULT_PASSWORD
  1209. if showDefault:
  1210. passwordPrompt = 'Enter Database Password (' + passwordDefault + '): '
  1211. else:
  1212. passwordPrompt = 'Enter Database Password: '
  1213. passwordPattern = "^[a-zA-Z0-9_-]*$"
  1214. passwordDescr = "Invalid characters in password. Use only alphanumeric or "\
  1215. "_ or - characters"
  1216. password = read_password(passwordDefault, passwordPattern, passwordPrompt,
  1217. passwordDescr)
  1218. return password
  1219. def check_database_name_property():
  1220. properties = get_ambari_properties()
  1221. if properties == -1:
  1222. print_error_msg("Error getting ambari properties")
  1223. return -1
  1224. dbname = properties[JDBC_DATABASE_PROPERTY]
  1225. if dbname is None or dbname == "":
  1226. err = "DB Name property not set in config file.\n" + SETUP_OR_UPGRADE_MSG
  1227. raise FatalException(-1, err)
  1228. def configure_database_username_password(args):
  1229. properties = get_ambari_properties()
  1230. if properties == -1:
  1231. print_error_msg("Error getting ambari properties")
  1232. return -1
  1233. username = properties[JDBC_USER_NAME_PROPERTY]
  1234. passwordProp = properties[JDBC_PASSWORD_PROPERTY]
  1235. dbname = properties[JDBC_DATABASE_PROPERTY]
  1236. if username and passwordProp and dbname:
  1237. print_info_msg("Database username + password already configured")
  1238. args.database_username = username
  1239. args.database_name = dbname
  1240. if is_alias_string(passwordProp):
  1241. args.database_password = decrypt_password_for_alias(JDBC_RCA_PASSWORD_ALIAS)
  1242. else:
  1243. if os.path.exists(passwordProp):
  1244. with open(passwordProp, 'r') as file:
  1245. args.database_password = file.read()
  1246. return 1
  1247. else:
  1248. print_error_msg("Connection properties not set in config file.")
  1249. # Check if jdbc user is changed
  1250. def is_jdbc_user_changed(args):
  1251. properties = get_ambari_properties()
  1252. if properties == -1:
  1253. print_error_msg("Error getting ambari properties")
  1254. return None
  1255. previos_user = properties[JDBC_USER_NAME_PROPERTY]
  1256. new_user = args.database_username
  1257. if previos_user and new_user:
  1258. if previos_user != new_user:
  1259. return True
  1260. else:
  1261. return False
  1262. return None
  1263. # Store local database connection properties
  1264. def store_local_properties(args):
  1265. properties = get_ambari_properties()
  1266. if properties == -1:
  1267. print_error_msg("Error getting ambari properties")
  1268. return -1
  1269. isSecure = get_is_secure(properties)
  1270. properties.removeOldProp(JDBC_SCHEMA_PROPERTY)
  1271. properties.removeOldProp(JDBC_HOSTNAME_PROPERTY)
  1272. properties.removeOldProp(JDBC_RCA_DRIVER_PROPERTY)
  1273. properties.removeOldProp(JDBC_RCA_URL_PROPERTY)
  1274. properties.removeOldProp(JDBC_PORT_PROPERTY)
  1275. properties.removeOldProp(JDBC_DRIVER_PROPERTY)
  1276. properties.removeOldProp(JDBC_URL_PROPERTY)
  1277. properties.process_pair(PERSISTENCE_TYPE_PROPERTY, "local")
  1278. properties.process_pair(JDBC_DATABASE_PROPERTY, args.database_name)
  1279. properties.process_pair(JDBC_USER_NAME_PROPERTY, args.database_username)
  1280. properties.process_pair(JDBC_PASSWORD_PROPERTY,
  1281. store_password_file(args.database_password, JDBC_PASSWORD_FILENAME))
  1282. if isSecure:
  1283. encrypted_password = encrypt_password(JDBC_RCA_PASSWORD_ALIAS, args.database_password)
  1284. if args.database_password != encrypted_password:
  1285. properties.process_pair(JDBC_PASSWORD_PROPERTY, encrypted_password)
  1286. pass
  1287. pass
  1288. conf_file = properties.fileName
  1289. try:
  1290. properties.store(open(conf_file, "w"))
  1291. except Exception, e:
  1292. print 'Unable to write ambari.properties configuration file "%s": %s' % (conf_file, e)
  1293. return -1
  1294. return 0
  1295. # Load ambari properties and return dict with values
  1296. def get_ambari_properties():
  1297. conf_file = find_properties_file()
  1298. properties = None
  1299. try:
  1300. properties = Properties()
  1301. properties.load(open(conf_file))
  1302. except (Exception), e:
  1303. print 'Could not read "%s": %s' % (conf_file, e)
  1304. return -1
  1305. return properties
  1306. # Load database connection properties from conf file
  1307. def parse_properties_file(args):
  1308. properties = get_ambari_properties()
  1309. if properties == -1:
  1310. print_error_msg("Error getting ambari properties")
  1311. return -1
  1312. args.server_version_file_path = properties[SERVER_VERSION_FILE_PATH]
  1313. args.persistence_type = properties[PERSISTENCE_TYPE_PROPERTY]
  1314. args.jdbc_url = properties[JDBC_URL_PROPERTY]
  1315. if not args.persistence_type:
  1316. args.persistence_type = "local"
  1317. if args.persistence_type == 'remote':
  1318. args.dbms = properties[JDBC_DATABASE_PROPERTY]
  1319. args.database_host = properties[JDBC_HOSTNAME_PROPERTY]
  1320. args.database_port = properties[JDBC_PORT_PROPERTY]
  1321. args.database_name = properties[JDBC_SCHEMA_PROPERTY]
  1322. global DATABASE_INDEX
  1323. try:
  1324. DATABASE_INDEX = DATABASE_NAMES.index(args.dbms)
  1325. except ValueError:
  1326. pass
  1327. else:
  1328. #TODO incorrect property used!! leads to bunch of troubles. Workaround for now
  1329. args.database_name = properties[JDBC_DATABASE_PROPERTY]
  1330. args.database_username = properties[JDBC_USER_NAME_PROPERTY]
  1331. args.database_password_file = properties[JDBC_PASSWORD_PROPERTY]
  1332. if args.database_password_file:
  1333. if not is_alias_string(args.database_password_file):
  1334. args.database_password = open(properties[JDBC_PASSWORD_PROPERTY]).read()
  1335. else:
  1336. args.database_password = args.database_password_file
  1337. return 0
  1338. ### JDK ###
  1339. def get_ambari_jars():
  1340. try:
  1341. conf_dir = os.environ[AMBARI_SERVER_LIB]
  1342. return conf_dir
  1343. except KeyError:
  1344. default_jar_location = "/usr/lib/ambari-server"
  1345. print_info_msg(AMBARI_SERVER_LIB + " is not set, using default "
  1346. + default_jar_location)
  1347. return default_jar_location
  1348. def get_share_jars():
  1349. share_jars = ""
  1350. file_list = []
  1351. file_list.extend(glob.glob(JAVA_SHARE_PATH + os.sep + "*mysql*"))
  1352. file_list.extend(glob.glob(JAVA_SHARE_PATH + os.sep + "*ojdbc*"))
  1353. if len(file_list) > 0:
  1354. share_jars = string.join(file_list, os.pathsep)
  1355. return share_jars
  1356. def get_ambari_classpath():
  1357. ambari_cp = get_ambari_jars() + os.sep + "*"
  1358. share_cp = get_share_jars()
  1359. if len(share_cp) > 0:
  1360. ambari_cp = ambari_cp + os.pathsep + share_cp
  1361. return ambari_cp
  1362. def search_file(filename, search_path, pathsep=os.pathsep):
  1363. """ Given a search path, find file with requested name """
  1364. for path in string.split(search_path, pathsep):
  1365. candidate = os.path.join(path, filename)
  1366. if os.path.exists(candidate):
  1367. return os.path.abspath(candidate)
  1368. return None
  1369. def dlprogress(base_name, count, blockSize, totalSize):
  1370. percent = int(count * blockSize * 100 / totalSize)
  1371. if (totalSize < blockSize):
  1372. sys.stdout.write("\r" + base_name + "... %d%%" % (100))
  1373. else:
  1374. sys.stdout.write("\r" + base_name + "... %d%% (%.1f MB of %.1f MB)" % (
  1375. percent, count * blockSize / 1024 / 1024.0, totalSize / 1024 / 1024.0))
  1376. if (percent == 100 or totalSize < blockSize):
  1377. sys.stdout.write("\n")
  1378. sys.stdout.flush()
  1379. def track_jdk(base_name, url, local_name):
  1380. u = urllib2.urlopen(url)
  1381. h = u.info()
  1382. totalSize = int(h["Content-Length"])
  1383. fp = open(local_name, "wb")
  1384. blockSize = 8192
  1385. count = 0
  1386. while True:
  1387. chunk = u.read(blockSize)
  1388. if not chunk:
  1389. break
  1390. fp.write(chunk)
  1391. count += 1
  1392. dlprogress(base_name, count, blockSize, totalSize)
  1393. fp.flush()
  1394. fp.close()
  1395. def install_jce_manualy(args):
  1396. properties = get_ambari_properties()
  1397. if properties == -1:
  1398. err = "Error getting ambari properties"
  1399. raise FatalException(-1, err)
  1400. if args.jce_policy:
  1401. if os.path.exists(args.jce_policy):
  1402. if os.path.isdir(args.jce_policy):
  1403. err = "JCE Policy path is a directory: " + args.jce_policy
  1404. raise FatalException(-1, err)
  1405. jce_destination = os.path.join(properties[RESOURCES_DIR_PROPERTY], JCE_POLICY_FILENAMES[JDK_INDEX])
  1406. try:
  1407. shutil.copy(args.jce_policy, jce_destination)
  1408. except Exception, e:
  1409. err = "Can not copy file {0} to {1} due to: {2}. Please check file " \
  1410. "permissions and free disk space.".format(args.jce_policy, jce_destination, e.message)
  1411. raise FatalException(-1, err)
  1412. print "JCE policy copied from " + args.jce_policy + " to " + jce_destination
  1413. return 0
  1414. else:
  1415. err = "JCE Policy path " + args.jce_policy + " doesn't exists."
  1416. raise FatalException(-1, err)
  1417. else:
  1418. return 1
  1419. #
  1420. # Downloads the JDK
  1421. #
  1422. def download_jdk(args):
  1423. global JDK_INDEX
  1424. ambari_setup_with_jdk_location = False
  1425. properties = get_ambari_properties()
  1426. if properties == -1:
  1427. err = "Error getting ambari properties"
  1428. raise FatalException(-1, err)
  1429. conf_file = properties.fileName
  1430. ok = False
  1431. jcePolicyWarn = "JCE Policy files are required for configuring Kerberos security. If you plan to use Kerberos," \
  1432. "please make sure JCE Unlimited Strength Jurisdiction Policy Files are valid on all hosts."
  1433. if args.java_home:
  1434. if not os.path.exists(args.java_home) or not os.path.isfile(os.path.join(args.java_home, "bin", "java")):
  1435. err = "Path to java home " + args.java_home + " or java binary file does not exists"
  1436. raise FatalException(1, err)
  1437. print_warning_msg("JAVA_HOME " + args.java_home + " must be valid on ALL hosts")
  1438. print_warning_msg(jcePolicyWarn)
  1439. write_property(JAVA_HOME_PROPERTY, args.java_home)
  1440. remove_property(JDK_NAME_PROPERTY)
  1441. remove_property(JCE_NAME_PROPERTY)
  1442. return 0
  1443. else:
  1444. if get_JAVA_HOME() and not args.jdk_location:
  1445. change_jdk = get_YN_input("Do you want to change Oracle JDK [y/n] (n)? ", False)
  1446. if not change_jdk:
  1447. return 0
  1448. try:
  1449. resources_dir = properties[RESOURCES_DIR_PROPERTY]
  1450. except (KeyError), e:
  1451. err = 'Property ' + str(e) + ' is not defined at ' + conf_file
  1452. raise FatalException(1, err)
  1453. ##JDK location was set by user with --jdk-location key
  1454. if args.jdk_location:
  1455. if not os.path.exists(args.jdk_location):
  1456. err = "Path to jdk " + args.jdk_location + " does not exists"
  1457. raise FatalException(1, err)
  1458. path, custom_jdk_name = os.path.split(args.jdk_location)
  1459. dest_file = resources_dir + os.sep + custom_jdk_name
  1460. print_warning_msg("JDK must be installed on all agent hosts and JAVA_HOME must be valid on all agent hosts.")
  1461. print_warning_msg(jcePolicyWarn)
  1462. print "Copying local JDK file {0} to {1}".format(args.jdk_location, dest_file)
  1463. try:
  1464. shutil.copyfile(args.jdk_location, dest_file)
  1465. except Exception, e:
  1466. err = "Can not copy file {0} to {1} due to: {2} . Please check file " \
  1467. "permissions and free disk space.".format(args.jdk_location, dest_file, e.message)
  1468. raise FatalException(1, err)
  1469. ambari_setup_with_jdk_location = True
  1470. remove_property(JDK_NAME_PROPERTY)
  1471. remove_property(JCE_NAME_PROPERTY)
  1472. else:
  1473. jdk_num = str(JDK_INDEX + 1)
  1474. jdk_num = get_validated_string_input(
  1475. "[1] - Oracle JDK 1.7\n[2] - Oracle JDK 1.6\n[3] - Custom JDK\n==============================================================================\nEnter choice (" + jdk_num + "): ",
  1476. jdk_num,
  1477. "^[123]$",
  1478. "Invalid number.",
  1479. False
  1480. )
  1481. if jdk_num == CUSTOM_JDK_NUMBER:
  1482. print_warning_msg("JDK must be installed on all hosts and JAVA_HOME must be valid on all hosts.")
  1483. print_warning_msg(jcePolicyWarn)
  1484. args.java_home = get_validated_string_input("Path to JAVA_HOME: ", None, None, None, False, False)
  1485. if not os.path.exists(args.java_home) or not os.path.isfile(os.path.join(args.java_home, "bin", "java")):
  1486. err = "Java home path or java binary file is unavailable. Please put correct path to java home."
  1487. raise FatalException(1, err)
  1488. print "Validating JDK on Ambari Server...done."
  1489. write_property(JAVA_HOME_PROPERTY, args.java_home)
  1490. remove_property(JDK_NAME_PROPERTY)
  1491. remove_property(JCE_NAME_PROPERTY)
  1492. return 0
  1493. JDK_INDEX = int(jdk_num) - 1
  1494. JDK_FILENAME = JDK_NAMES[JDK_INDEX]
  1495. JDK_URL_PROPERTY = JDK_URL_PROPERTIES[JDK_INDEX]
  1496. try:
  1497. jdk_url = properties[JDK_URL_PROPERTY]
  1498. except (KeyError), e:
  1499. err = 'Property ' + str(e) + ' is not defined at ' + conf_file
  1500. raise FatalException(1, err)
  1501. dest_file = resources_dir + os.sep + JDK_FILENAME
  1502. if os.path.exists(dest_file):
  1503. print "JDK already exists, using " + dest_file
  1504. else:
  1505. ok = get_YN_input("To download the Oracle JDK you must accept the "
  1506. "license terms found at "
  1507. "http://www.oracle.com/technetwork/java/javase/"
  1508. "terms/license/index.html and not accepting will "
  1509. "cancel the Ambari Server setup.\nDo you accept the "
  1510. "Oracle Binary Code License Agreement [y/n] (y)? ", True)
  1511. if not ok:
  1512. print 'Exiting...'
  1513. sys.exit(1)
  1514. print 'Downloading JDK from ' + jdk_url + ' to ' + dest_file
  1515. jdk_download_fail_msg = " Failed to download JDK: {0}. Please check that Oracle " \
  1516. "JDK is available at {1}. Also you may specify JDK file " \
  1517. "location in local filesystem using --jdk-location command " \
  1518. "line argument.".format("{0}", jdk_url)
  1519. try:
  1520. size_command = JDK_DOWNLOAD_SIZE_CMD.format(jdk_url)
  1521. #Get Header from url,to get file size then
  1522. retcode, out, err = run_os_command(size_command)
  1523. if out.find("Content-Length") == -1:
  1524. err = jdk_download_fail_msg.format("Request header doesn't contain Content-Length")
  1525. raise FatalException(1, err)
  1526. start_with = int(out.find("Content-Length") + len("Content-Length") + 2)
  1527. end_with = out.find("\r\n", start_with)
  1528. src_size = int(out[start_with:end_with])
  1529. print 'JDK distribution size is ' + str(src_size) + ' bytes'
  1530. file_exists = os.path.isfile(dest_file)
  1531. file_size = -1
  1532. if file_exists:
  1533. file_size = os.stat(dest_file).st_size
  1534. if file_exists and file_size == src_size:
  1535. print_info_msg("File already exists")
  1536. else:
  1537. track_jdk(JDK_FILENAME, jdk_url, dest_file)
  1538. print 'Successfully downloaded JDK distribution to ' + dest_file
  1539. except FatalException:
  1540. raise
  1541. except Exception, e:
  1542. err = jdk_download_fail_msg.format(str(e))
  1543. raise FatalException(1, err)
  1544. downloaded_size = os.stat(dest_file).st_size
  1545. if downloaded_size != src_size or downloaded_size < JDK_MIN_FILESIZE:
  1546. err = 'Size of downloaded JDK distribution file is ' \
  1547. + str(downloaded_size) + ' bytes, it is probably \
  1548. damaged or incomplete'
  1549. raise FatalException(1, err)
  1550. try:
  1551. out = install_jdk(dest_file)
  1552. jdk_version = re.search(JDK_VERSION_REs[JDK_INDEX], out).group(1)
  1553. if not ambari_setup_with_jdk_location:
  1554. write_property(JDK_NAME_PROPERTY, JDK_FILENAME)
  1555. except Exception, e:
  1556. print "Installation of JDK has failed: %s\n" % e.message
  1557. file_exists = os.path.isfile(dest_file)
  1558. if file_exists:
  1559. ok = get_YN_input("JDK found at "+dest_file+". "
  1560. "Would you like to re-download the JDK [y/n] (y)? ", True)
  1561. if not ok:
  1562. err = "Unable to install JDK. Please remove JDK file found at " + \
  1563. dest_file + " and re-run Ambari Server setup"
  1564. raise FatalException(1, err)
  1565. else:
  1566. track_jdk(JDK_FILENAME, jdk_url, dest_file)
  1567. print 'Successfully re-downloaded JDK distribution to ' + dest_file
  1568. try:
  1569. out = install_jdk(dest_file)
  1570. jdk_version = re.search(JDK_VERSION_REs[JDK_INDEX], out).group(1)
  1571. if not ambari_setup_with_jdk_location:
  1572. write_property(JDK_NAME_PROPERTY, JDK_FILENAME)
  1573. except Exception, e:
  1574. print "Installation of JDK was failed: %s\n" % e.message
  1575. err = "Unable to install JDK. Please remove JDK, file found at " + \
  1576. dest_file + " and re-run Ambari Server setup"
  1577. raise FatalException(1, err)
  1578. else:
  1579. err = "Unable to install JDK. File " + dest_file + " does not exist, " \
  1580. "please re-run Ambari Server setup"
  1581. raise FatalException(1, err)
  1582. print "Successfully installed JDK to {0}/{1}".\
  1583. format(JDK_INSTALL_DIR, jdk_version)
  1584. write_property(JAVA_HOME_PROPERTY, "{0}/{1}".
  1585. format(JDK_INSTALL_DIR, jdk_version))
  1586. try:
  1587. if not ambari_setup_with_jdk_location:
  1588. download_jce_policy(properties, ok)
  1589. except FatalException as e:
  1590. print "JCE Policy files are required for secure HDP setup. Please ensure " \
  1591. " all hosts have the JCE unlimited strength policy 6, files."
  1592. print_error_msg("Failed to download JCE policy files:")
  1593. if e.reason is not None:
  1594. print_error_msg("\nREASON: {0}".format(e.reason))
  1595. # TODO: We don't fail installation if download_jce_policy fails. Is it OK?
  1596. return 0
  1597. def download_jce_policy(properties, accpeted_bcl):
  1598. JCE_URL_PROPERTY = JCE_URL_PROPERTIES[JDK_INDEX]
  1599. JCE_POLICY_FILENAME = JCE_POLICY_FILENAMES[JDK_INDEX]
  1600. try:
  1601. jce_url = properties[JCE_URL_PROPERTY]
  1602. resources_dir = properties[RESOURCES_DIR_PROPERTY]
  1603. except KeyError, e:
  1604. err = 'Property ' + str(e) + ' is not defined in properties file'
  1605. raise FatalException(1, err)
  1606. dest_file = resources_dir + os.sep + JCE_POLICY_FILENAME
  1607. if not os.path.exists(dest_file):
  1608. print 'Downloading JCE Policy archive from ' + jce_url + ' to ' + dest_file
  1609. jce_download_fail_msg = " Failed to download JCE Policy archive : {0}. " \
  1610. "Please check that JCE Policy archive is available at {1} . "
  1611. try:
  1612. size_command = JDK_DOWNLOAD_SIZE_CMD.format(jce_url)
  1613. #Get Header from url,to get file size then
  1614. retcode, out, err = run_os_command(size_command)
  1615. if out.find("Content-Length") == -1:
  1616. err = jce_download_fail_msg.format(
  1617. "Request header doesn't contain Content-Length")
  1618. raise FatalException(1, err)
  1619. start_with = int(out.find("Content-Length") + len("Content-Length") + 2)
  1620. end_with = out.find("\r\n", start_with)
  1621. src_size = int(out[start_with:end_with])
  1622. print_info_msg('JCE zip distribution size is ' + str(src_size) + ' bytes')
  1623. file_exists = os.path.isfile(dest_file)
  1624. file_size = -1
  1625. if file_exists:
  1626. file_size = os.stat(dest_file).st_size
  1627. if file_exists and file_size == src_size:
  1628. print_info_msg("File already exists")
  1629. else:
  1630. #BCL license before download
  1631. jce_download_cmd = JCE_DOWNLOAD_CMD.format(dest_file, jce_url)
  1632. print_info_msg("JCE download cmd: " + jce_download_cmd)
  1633. if accpeted_bcl:
  1634. retcode, out, err = run_os_command(jce_download_cmd)
  1635. if retcode == 0:
  1636. write_property(JCE_NAME_PROPERTY, JCE_POLICY_FILENAME)
  1637. print 'Successfully downloaded JCE Policy archive to ' + dest_file
  1638. else:
  1639. raise FatalException(1, err)
  1640. else:
  1641. ok = get_YN_input("To download the JCE Policy files you must "
  1642. "accept the license terms found at "
  1643. "http://www.oracle.com/technetwork/java/javase"
  1644. "/terms/license/index.html"
  1645. "Not accepting will result in errors when "
  1646. "configuring Kerberos security. \nDo you accept the "
  1647. "Oracle Binary Code License Agreement [y/n] (y)? ", True)
  1648. if ok:
  1649. retcode, out, err = run_os_command(jce_download_cmd)
  1650. if retcode == 0:
  1651. write_property(JCE_NAME_PROPERTY, JCE_POLICY_FILENAME)
  1652. print 'Successfully downloaded JCE Policy archive to ' + dest_file
  1653. else:
  1654. raise FatalException(1, None)
  1655. except FatalException:
  1656. raise
  1657. except Exception, e:
  1658. err = 'Failed to download JCE Policy archive: ' + str(e)
  1659. raise FatalException(1, err)
  1660. downloaded_size = os.stat(dest_file).st_size
  1661. if downloaded_size != src_size or downloaded_size < JCE_MIN_FILESIZE:
  1662. err = 'Size of downloaded JCE Policy archive is ' \
  1663. + str(downloaded_size) + ' bytes, it is probably \
  1664. damaged or incomplete'
  1665. raise FatalException(1, err)
  1666. else:
  1667. write_property(JCE_NAME_PROPERTY, JCE_POLICY_FILENAME)
  1668. print "JCE Policy archive already exists, using " + dest_file
  1669. class RetCodeException(Exception):
  1670. pass
  1671. def install_jdk(dest_file):
  1672. print "Installing JDK to {0}".format(JDK_INSTALL_DIR)
  1673. retcode, out, err = run_os_command(CREATE_JDK_DIR_CMD)
  1674. savedPath = os.getcwd()
  1675. os.chdir(JDK_INSTALL_DIR)
  1676. if dest_file.endswith(".bin"):
  1677. retcode, out, err = run_os_command(MAKE_FILE_EXECUTABLE_CMD.format(dest_file))
  1678. retcode, out, err = run_os_command(dest_file + ' -noregister')
  1679. elif dest_file.endswith(".gz"):
  1680. retcode, out, err = run_os_command(UNTAR_JDK_ARVHIVE.format(dest_file))
  1681. else:
  1682. err = "JDK installation failed.Unknown file mask."
  1683. raise FatalException(1, err)
  1684. os.chdir(savedPath)
  1685. if retcode != 0:
  1686. err = "Installation of JDK returned exit code %s" % retcode
  1687. raise FatalException(retcode, err)
  1688. return out
  1689. #
  1690. # Configures the OS settings in ambari properties.
  1691. #
  1692. def configure_os_settings():
  1693. properties = get_ambari_properties()
  1694. if properties == -1:
  1695. print_error_msg("Error getting ambari properties")
  1696. return -1
  1697. try:
  1698. conf_os_type = properties[OS_TYPE_PROPERTY]
  1699. if conf_os_type != '':
  1700. print_info_msg("os_type already setting in properties file")
  1701. return 0
  1702. except (KeyError):
  1703. print_error_msg("os_type is not set in properties file")
  1704. os_system = platform.system()
  1705. if os_system != 'Linux':
  1706. print_error_msg("Non-Linux systems are not supported")
  1707. return -1
  1708. master_os_type = OS_FAMILY + OS_VERSION
  1709. write_property(OS_TYPE_PROPERTY, master_os_type)
  1710. return 0
  1711. def get_JAVA_HOME():
  1712. properties = get_ambari_properties()
  1713. if properties == -1:
  1714. print_error_msg("Error getting ambari properties")
  1715. return None
  1716. java_home = properties[JAVA_HOME_PROPERTY]
  1717. if (not 0 == len(java_home)) and (os.path.exists(java_home)):
  1718. return java_home
  1719. return None
  1720. #
  1721. # Checks jdk path for correctness
  1722. #
  1723. def validate_jdk(jdk_path):
  1724. if jdk_path:
  1725. return os.path.exists(jdk_path) and os.path.exists(
  1726. jdk_path + os.sep + 'bin' + os.sep + 'java')
  1727. else:
  1728. return False
  1729. #
  1730. # Finds the available JDKs.
  1731. #
  1732. def find_jdk():
  1733. jdkPath = get_JAVA_HOME()
  1734. if jdkPath:
  1735. if validate_jdk(jdkPath):
  1736. return jdkPath
  1737. print "Looking for available JDKs at " + JDK_INSTALL_DIR
  1738. jdks = glob.glob(JDK_INSTALL_DIR + os.sep + "jdk*")
  1739. jdks.sort()
  1740. print "Found: " + str(jdks)
  1741. if len(jdks) == 0:
  1742. return
  1743. for jdkPath in jdks:
  1744. print "Trying to use JDK {0}".format(jdkPath)
  1745. if validate_jdk(jdkPath):
  1746. print "Selected JDK {0}".format(jdkPath)
  1747. return jdkPath
  1748. else:
  1749. print "JDK {0} is invalid".format(jdkPath)
  1750. return
  1751. #
  1752. # Checks if options determine local DB configuration
  1753. #
  1754. def is_local_database(args):
  1755. return hasattr(args, 'persistence_type') and args.persistence_type == 'local'
  1756. #Check if required jdbc drivers present
  1757. def find_jdbc_driver(args):
  1758. if args.dbms in JDBC_PATTERNS.keys():
  1759. drivers = []
  1760. drivers.extend(glob.glob(JAVA_SHARE_PATH + os.sep + JDBC_PATTERNS[args.dbms]))
  1761. if drivers:
  1762. return drivers
  1763. return -1
  1764. return 0
  1765. def copy_file(src, dest_file):
  1766. try:
  1767. shutil.copyfile(src, dest_file)
  1768. except Exception, e:
  1769. err = "Can not copy file {0} to {1} due to: {2} . Please check file " \
  1770. "permissions and free disk space.".format(src, dest_file, e.message)
  1771. raise FatalException(1, err)
  1772. def remove_file(filePath):
  1773. if os.path.exists(filePath):
  1774. try:
  1775. os.remove(filePath)
  1776. except Exception, e:
  1777. print_warning_msg('Unable to remove file: ' + str(e))
  1778. return 1
  1779. pass
  1780. return 0
  1781. def copy_files(files, dest_dir):
  1782. if os.path.isdir(dest_dir):
  1783. for filepath in files:
  1784. shutil.copy(filepath, dest_dir)
  1785. return 0
  1786. else:
  1787. return -1
  1788. #
  1789. # Wait for Popen process and returns exit code if process was finished in
  1790. # timeout seconds, otherwise returns None
  1791. #
  1792. def wait_popen(popen, timeout=0):
  1793. begin = time.time()
  1794. while popen.poll() is None and not time.time() - begin > timeout:
  1795. time.sleep(1)
  1796. return popen.poll()
  1797. def check_jdbc_drivers(args):
  1798. properties = get_ambari_properties()
  1799. if properties == -1:
  1800. print_error_msg("Error getting ambari properties")
  1801. return -1
  1802. result = find_jdbc_driver(args)
  1803. msg = 'Before starting Ambari Server, ' \
  1804. 'you must copy the {0} JDBC driver JAR file to {1}.'.format(
  1805. DATABASE_FULL_NAMES[args.dbms],
  1806. JAVA_SHARE_PATH)
  1807. if result == -1:
  1808. if SILENT:
  1809. print_error_msg(msg)
  1810. raise FatalException(-1, msg)
  1811. else:
  1812. print_warning_msg(msg)
  1813. raw_input(PRESS_ENTER_MSG)
  1814. result = find_jdbc_driver(args)
  1815. if result == -1:
  1816. print_error_msg(msg)
  1817. raise FatalException(-1, msg)
  1818. # Check if selected RDBMS requires drivers to copy
  1819. if type(result) is not int:
  1820. print 'Copying JDBC drivers to server resources...'
  1821. try:
  1822. resources_dir = properties[RESOURCES_DIR_PROPERTY]
  1823. except KeyError:
  1824. print_error_msg("There is no value for " + RESOURCES_DIR_PROPERTY + "in " + AMBARI_PROPERTIES_FILE)
  1825. return -1
  1826. db_name = DATABASE_FULL_NAMES[args.dbms].lower()
  1827. jdbc_symlink = os.path.join(resources_dir, db_name + "-jdbc-driver.jar")
  1828. db_default_driver_path = os.path.join(JAVA_SHARE_PATH, JDBC_DB_DEFAULT_DRIVER[db_name])
  1829. if os.path.lexists(jdbc_symlink):
  1830. os.remove(jdbc_symlink)
  1831. copy_status = copy_files(result, resources_dir)
  1832. if not copy_status == 0:
  1833. raise FatalException(-1, "Failed to copy JDBC drivers to server resources")
  1834. if db_default_driver_path in result:
  1835. os.symlink(os.path.join(resources_dir, JDBC_DB_DEFAULT_DRIVER[db_name]), jdbc_symlink)
  1836. return 0
  1837. def verify_setup_allowed():
  1838. properties = get_ambari_properties()
  1839. if properties == -1:
  1840. print_error_msg("Error getting ambari properties")
  1841. return -1
  1842. isSecure = get_is_secure(properties)
  1843. (isPersisted, masterKeyFile) = get_is_persisted(properties)
  1844. if isSecure and not isPersisted and SILENT:
  1845. print "ERROR: Cannot run silent 'setup' with password encryption enabled " \
  1846. "and Master Key not persisted."
  1847. print "Ambari Server 'setup' exiting."
  1848. return 1
  1849. return 0
  1850. #
  1851. # Setup the Ambari Server.
  1852. #
  1853. def setup(args):
  1854. retcode = verify_setup_allowed()
  1855. if not retcode == 0:
  1856. raise FatalException(1, None)
  1857. if not is_root():
  1858. err = 'Ambari-server setup should be run with '\
  1859. 'root-level privileges'
  1860. raise FatalException(4, err)
  1861. # proceed jdbc properties if they were set
  1862. if args.jdbc_driver is not None and args.jdbc_db is not None:
  1863. proceedJDBCProperties(args)
  1864. status, pid = is_server_runing()
  1865. if status:
  1866. return
  1867. print 'Checking SELinux...'
  1868. retcode = check_selinux()
  1869. if not retcode == 0:
  1870. err = 'Failed to disable SELinux. Exiting.'
  1871. raise FatalException(retcode, err)
  1872. # Create ambari user, if needed
  1873. retcode = check_ambari_user()
  1874. if not retcode == 0:
  1875. err = 'Failed to create user. Exiting.'
  1876. raise FatalException(retcode, err)
  1877. print 'Checking iptables...'
  1878. check_iptables()
  1879. # proceed jdbc properties if they were set
  1880. if args.jdbc_driver is not None and args.jdbc_db is not None:
  1881. proceedJDBCProperties(args)
  1882. print 'Checking JDK...'
  1883. try:
  1884. download_jdk(args)
  1885. except FatalException as e:
  1886. err = 'Downloading or installing JDK failed: {0}. Exiting.'.format(e)
  1887. raise FatalException(e.code, err)
  1888. print 'Completing setup...'
  1889. retcode = configure_os_settings()
  1890. if not retcode == 0:
  1891. err = 'Configure of OS settings in ambari.properties failed. Exiting.'
  1892. raise FatalException(retcode, err)
  1893. print 'Configuring database...'
  1894. prompt_db_properties(args)
  1895. #DB setup should be done last after doing any setup.
  1896. if is_local_database(args):
  1897. #check if jdbc user is changed
  1898. is_user_changed = is_jdbc_user_changed(args)
  1899. print 'Default properties detected. Using built-in database.'
  1900. store_local_properties(args)
  1901. print 'Checking PostgreSQL...'
  1902. retcode = check_postgre_up()
  1903. if not retcode == 0:
  1904. err = 'Unable to start PostgreSQL server. Exiting'
  1905. raise FatalException(retcode, err)
  1906. print 'Configuring local database...'
  1907. retcode, outdata, errdata = setup_db(args)
  1908. if not retcode == 0:
  1909. err = 'Running database init script was failed. Exiting.'
  1910. raise FatalException(retcode, err)
  1911. if is_user_changed:
  1912. #remove backup for pg_hba in order to reconfigure postgres
  1913. remove_file(PG_HBA_CONF_FILE_BACKUP)
  1914. print 'Configuring PostgreSQL...'
  1915. retcode = configure_postgres()
  1916. if not retcode == 0:
  1917. err = 'Unable to configure PostgreSQL server. Exiting'
  1918. raise FatalException(retcode, err)
  1919. else:
  1920. retcode = store_remote_properties(args)
  1921. if retcode != 0:
  1922. err = 'Unable to save config file'
  1923. raise FatalException(retcode, err)
  1924. check_jdbc_drivers(args)
  1925. print 'Configuring remote database connection properties...'
  1926. retcode = setup_remote_db(args)
  1927. if retcode == -1:
  1928. err = "Remote database setup aborted."
  1929. raise NonFatalException(err)
  1930. if not retcode == 0:
  1931. err = 'Error while configuring connection properties. Exiting'
  1932. raise FatalException(retcode, err)
  1933. check_jdbc_drivers(args)
  1934. def proceedJDBCProperties(args):
  1935. if not os.path.isfile(args.jdbc_driver):
  1936. err = "File {0} does not exist!".format(args.jdbc_driver)
  1937. raise FatalException(1, err)
  1938. if args.jdbc_db not in JDBC_DB_OPTION_VALUES:
  1939. err = "Unsupported database name {0}. Please see help for more information.".format(args.jdbc_db)
  1940. raise FatalException(1, err)
  1941. properties = get_ambari_properties()
  1942. if properties == -1:
  1943. err = "Error getting ambari properties"
  1944. raise FatalException(-1, err)
  1945. conf_file = properties.fileName
  1946. try:
  1947. resources_dir = properties[RESOURCES_DIR_PROPERTY]
  1948. except (KeyError), e:
  1949. err = 'Property ' + str(e) + ' is not defined at ' + conf_file
  1950. raise FatalException(1, err)
  1951. symlink_name = args.jdbc_db + "-jdbc-driver.jar"
  1952. jdbc_symlink = os.path.join(resources_dir, symlink_name)
  1953. path, jdbc_name = os.path.split(args.jdbc_driver)
  1954. if os.path.lexists(jdbc_symlink):
  1955. os.remove(jdbc_symlink)
  1956. if not os.path.isfile(os.path.join(resources_dir, jdbc_name)):
  1957. try:
  1958. shutil.copy(args.jdbc_driver, resources_dir)
  1959. except Exception, e:
  1960. err = "Can not copy file {0} to {1} due to: {2} . Please check file " \
  1961. "permissions and free disk space.".format(args.jdbc_driver, resources_dir, e.message)
  1962. raise FatalException(1, err)
  1963. os.symlink(os.path.join(resources_dir,jdbc_name), jdbc_symlink)
  1964. print "JDBC driver was successfully initialized ."
  1965. #
  1966. # Resets the Ambari Server.
  1967. #
  1968. def reset(args):
  1969. #force reset if silent option provided
  1970. global SILENT
  1971. if SILENT:
  1972. default = "yes"
  1973. else:
  1974. default = "no"
  1975. if not is_root():
  1976. err = 'Ambari-server reset should be run with ' \
  1977. 'root-level privileges'
  1978. raise FatalException(4, err)
  1979. status, pid = is_server_runing()
  1980. if status:
  1981. err = 'Ambari-server must be stopped to reset'
  1982. raise FatalException(1, err)
  1983. choice = get_YN_input("**** WARNING **** You are about to reset and clear the "
  1984. "Ambari Server database. This will remove all cluster "
  1985. "host and configuration information from the database. "
  1986. "You will be required to re-configure the Ambari server "
  1987. "and re-run the cluster wizard. \n"
  1988. "Are you SURE you want to perform the reset "
  1989. "[yes/no] ({0})? ".format(default), SILENT)
  1990. okToRun = choice
  1991. if not okToRun:
  1992. err = "Ambari Server 'reset' cancelled"
  1993. raise FatalException(1, err)
  1994. check_database_name_property()
  1995. parse_properties_file(args)
  1996. if args.persistence_type == "remote":
  1997. client_usage_cmd_drop = DATABASE_CLI_TOOLS_USAGE[DATABASE_INDEX].format(DATABASE_DROP_SCRIPTS[DATABASE_INDEX], args.database_username,
  1998. BLIND_PASSWORD, args.database_name)
  1999. client_usage_cmd_init = DATABASE_CLI_TOOLS_USAGE[DATABASE_INDEX].format(DATABASE_INIT_SCRIPTS[DATABASE_INDEX], args.database_username,
  2000. BLIND_PASSWORD, args.database_name)
  2001. print_warning_msg('To reset Ambari Server schema ' +
  2002. 'you must run the following DDL against the database to '
  2003. + 'drop the schema:' + os.linesep + client_usage_cmd_drop
  2004. + os.linesep + 'Then you must run the following DDL ' +
  2005. 'against the database to create the schema: ' + os.linesep +
  2006. client_usage_cmd_init + os.linesep)
  2007. else:
  2008. # Run automatic reset only for embedded DB
  2009. okToRun = get_YN_input("Confirm server reset [yes/no]({0})? ".format(default), SILENT)
  2010. if not okToRun:
  2011. err = "Ambari Server 'reset' cancelled"
  2012. raise FatalException(1, err)
  2013. print "Resetting the Server database..."
  2014. dbname = args.database_name
  2015. filename = args.drop_script_file
  2016. username = args.database_username
  2017. password = args.database_password
  2018. command = SETUP_DB_CMD[:]
  2019. command[-1] = command[-1].format(filename, username, password, dbname)
  2020. drop_retcode, drop_outdata, drop_errdata = run_os_command(command)
  2021. if not drop_retcode == 0:
  2022. raise FatalException(1, drop_errdata)
  2023. if drop_errdata and PG_ERROR_BLOCKED in drop_errdata:
  2024. raise FatalException(1, "Database is in use. Please, make sure all connections to the database are closed")
  2025. if drop_errdata and VERBOSE:
  2026. print_warning_msg(drop_errdata)
  2027. print_info_msg("About to run database setup")
  2028. retcode, outdata, errdata = setup_db(args)
  2029. if errdata and VERBOSE:
  2030. print_warning_msg(errdata)
  2031. if (errdata and 'ERROR' in errdata.upper()) or (drop_errdata and 'ERROR' in drop_errdata.upper()):
  2032. if not VERBOSE:
  2033. raise NonFatalException("Non critical error in DDL, use --verbose for more information")
  2034. else:
  2035. raise NonFatalException("Non critical error in DDL")
  2036. pass
  2037. pass
  2038. #
  2039. # Starts the Ambari Server.
  2040. #
  2041. def start(args):
  2042. if not check_reverse_lookup():
  2043. print_warning_msg("The hostname was not found in the reverse DNS lookup. "
  2044. "This may result in incorrect behavior. "
  2045. "Please check the DNS setup and fix the issue.")
  2046. current_user = getpass.getuser()
  2047. ambari_user = read_ambari_user()
  2048. if ambari_user is None:
  2049. err = "Unable to detect a system user for Ambari Server.\n" + SETUP_OR_UPGRADE_MSG
  2050. raise FatalException(1, err)
  2051. if current_user != ambari_user and not is_root():
  2052. err = "Unable to start Ambari Server as user {0}. Please either run \"ambari-server start\" " \
  2053. "command as root, as sudo or as user \"{1}\"".format(current_user, ambari_user)
  2054. raise FatalException(1, err)
  2055. check_database_name_property()
  2056. parse_properties_file(args)
  2057. status, pid = is_server_runing()
  2058. if status:
  2059. err = "Ambari Server is already running."
  2060. raise FatalException(1, err)
  2061. print_info_msg("Ambari Server is not running...")
  2062. conf_dir = get_conf_dir()
  2063. jdk_path = find_jdk()
  2064. if jdk_path is None:
  2065. err = "No JDK found, please run the \"ambari-server setup\" " \
  2066. "command to install a JDK automatically or install any " \
  2067. "JDK manually to " + JDK_INSTALL_DIR
  2068. raise FatalException(1, err)
  2069. if args.persistence_type == 'remote':
  2070. result = find_jdbc_driver(args)
  2071. msg = 'Before starting Ambari Server, ' \
  2072. 'you must copy the {0} JDBC driver JAR file to {1}.'.format(
  2073. DATABASE_FULL_NAMES[args.dbms],
  2074. JAVA_SHARE_PATH)
  2075. if result == -1:
  2076. raise FatalException(-1, msg)
  2077. # Preparations
  2078. if is_root():
  2079. print "Ambari Server running with 'root' privileges."
  2080. if args.persistence_type == "local":
  2081. retcode = check_postgre_up()
  2082. if not retcode == 0:
  2083. err = "Unable to start PostgreSQL server. Exiting"
  2084. raise FatalException(retcode, err)
  2085. else: # Skipping actions that require root permissions
  2086. print "Unable to check iptables status when starting "\
  2087. "without root privileges."
  2088. print "Please do not forget to disable or adjust iptables if needed"
  2089. if args.persistence_type == "local":
  2090. print "Unable to check PostgreSQL server status when starting " \
  2091. "without root privileges."
  2092. print "Please do not forget to start PostgreSQL server."
  2093. properties = get_ambari_properties()
  2094. stack_location = get_stack_location(properties)
  2095. # Hack: we determine resource dir as a parent dir for stack_location
  2096. resources_location = os.path.dirname(stack_location)
  2097. resource_files_keeper = ResourceFilesKeeper(resources_location)
  2098. try:
  2099. print "Organizing resource files at {0}...".format(resources_location,
  2100. verbose=VERBOSE)
  2101. resource_files_keeper.perform_housekeeping()
  2102. except KeeperException, ex:
  2103. msg = "Can not organize resource files at {0}: {1}".format(
  2104. resources_location, str(ex))
  2105. raise FatalException(-1, msg)
  2106. isSecure = get_is_secure(properties)
  2107. (isPersisted, masterKeyFile) = get_is_persisted(properties)
  2108. environ = os.environ.copy()
  2109. # Need to handle master key not persisted scenario
  2110. if isSecure and not masterKeyFile:
  2111. prompt = False
  2112. masterKey = environ.get(SECURITY_KEY_ENV_VAR_NAME)
  2113. if masterKey is not None and masterKey != "":
  2114. pass
  2115. else:
  2116. keyLocation = environ.get(SECURITY_MASTER_KEY_LOCATION)
  2117. if keyLocation is not None:
  2118. try:
  2119. # Verify master key can be read by the java process
  2120. with open(keyLocation, 'r'):
  2121. pass
  2122. except IOError:
  2123. print_warning_msg("Cannot read Master key from path specified in "
  2124. "environemnt.")
  2125. prompt = True
  2126. else:
  2127. # Key not provided in the environment
  2128. prompt = True
  2129. if prompt:
  2130. masterKey = get_original_master_key(properties)
  2131. tempDir = tempfile.gettempdir()
  2132. tempFilePath = tempDir + os.sep + "masterkey"
  2133. save_master_key(masterKey, tempFilePath, True)
  2134. if ambari_user != current_user:
  2135. uid = pwd.getpwnam(ambari_user).pw_uid
  2136. gid = pwd.getpwnam(ambari_user).pw_gid
  2137. os.chown(tempFilePath, uid, gid)
  2138. else:
  2139. os.chmod(tempFilePath, stat.S_IREAD | stat.S_IWRITE)
  2140. if tempFilePath is not None:
  2141. environ[SECURITY_MASTER_KEY_LOCATION] = tempFilePath
  2142. pidfile = PID_DIR + os.sep + PID_NAME
  2143. command_base = SERVER_START_CMD_DEBUG if (SERVER_DEBUG_MODE or SERVER_START_DEBUG) else SERVER_START_CMD
  2144. command = "%s %s; %s" % (ULIMIT_CMD, str(get_ulimit_open_files()),
  2145. command_base.format(jdk_path,
  2146. conf_dir,
  2147. get_ambari_classpath(),
  2148. pidfile,
  2149. os.path.join(PID_DIR, EXITCODE_NAME))
  2150. )
  2151. if not os.path.exists(PID_DIR):
  2152. os.makedirs(PID_DIR, 0755)
  2153. #For properly daemonization server should be started using shell as parent
  2154. if is_root() and ambari_user != "root":
  2155. # To inherit exported environment variables (especially AMBARI_PASSPHRASE),
  2156. # from subprocess, we have to skip --login option of su command. That's why
  2157. # we change dir to / (otherwise subprocess can face with 'permission denied'
  2158. # errors while trying to list current directory
  2159. os.chdir("/")
  2160. param_list = [utils.locate_file('su', '/bin'), ambari_user, "-s", utils.locate_file('sh', '/bin'), "-c", command]
  2161. else:
  2162. param_list = [utils.locate_file('sh', '/bin'), "-c", command]
  2163. print_info_msg("Running server: " + str(param_list))
  2164. subprocess.Popen(param_list, env=environ)
  2165. #wait for server process for SERVER_START_TIMEOUT seconds
  2166. print "Waiting for server start..."
  2167. pids = utils.looking_for_pid(SERVER_SEARCH_PATTERN, SERVER_INIT_TIMEOUT)
  2168. if utils.wait_for_pid(pids, SERVER_START_TIMEOUT) <= 0:
  2169. exitcode = utils.check_exitcode(os.path.join(PID_DIR, EXITCODE_NAME))
  2170. raise FatalException(-1, AMBARI_SERVER_DIE_MSG.format(exitcode, SERVER_OUT_FILE))
  2171. else:
  2172. utils.save_main_pid_ex(pids, pidfile, [utils.locate_file('sh', '/bin'),
  2173. utils.locate_file('bash', '/bin')], True)
  2174. print "Server PID at: "+pidfile
  2175. print "Server out at: "+SERVER_OUT_FILE
  2176. print "Server log at: "+SERVER_LOG_FILE
  2177. #
  2178. # Stops the Ambari Server.
  2179. #
  2180. def stop(args):
  2181. if (args != None):
  2182. args.exit_message = None
  2183. status, pid = is_server_runing()
  2184. if status:
  2185. try:
  2186. os.killpg(os.getpgid(pid), signal.SIGKILL)
  2187. except OSError, e:
  2188. print_info_msg("Unable to stop Ambari Server - " + str(e))
  2189. return
  2190. pid_file_path = PID_DIR + os.sep + PID_NAME
  2191. os.remove(pid_file_path)
  2192. print "Ambari Server stopped"
  2193. else:
  2194. print "Ambari Server is not running"
  2195. ### Stack upgrade ###
  2196. def upgrade_stack(args, stack_id, repo_url=None, repo_url_os=None):
  2197. if not is_root():
  2198. err = 'Ambari-server upgradestack should be run with ' \
  2199. 'root-level privileges'
  2200. raise FatalException(4, err)
  2201. check_database_name_property()
  2202. local_repo_check_commamd = ""
  2203. if OS_FAMILY == OSConst.DEBIAN_FAMILY:
  2204. raise FatalException(3, '"upgradestack" command not supported yet for Debian OS\'es family.')
  2205. elif OS_FAMILY == OSConst.REDHAT_FAMILY:
  2206. local_repo_check_commamd = 'yum repolist | grep "{0} "'
  2207. elif OS_FAMILY == OSConst.SUSE_FAMILY:
  2208. local_repo_check_commamd = 'zypper repos | grep "{0} "'
  2209. command = local_repo_check_commamd.format(stack_id)
  2210. (retcode, stdout, stderr) = run_in_shell(command)
  2211. if not retcode == 0 and repo_url is None:
  2212. raise FatalException(retcode, 'Repository for ' + stack_id + " is not existed")
  2213. stack_name, stack_version = stack_id.split(STACK_NAME_VER_SEP)
  2214. retcode, stdout, stderr = run_stack_upgrade(stack_name, stack_version, repo_url, repo_url_os)
  2215. if not retcode == 0:
  2216. raise FatalException(retcode, 'Error executing stack upgrade. ' + stderr)
  2217. def load_stack_values(version, filename):
  2218. import xml.etree.ElementTree as ET
  2219. values = {}
  2220. root = ET.parse(filename).getroot()
  2221. for ostag in root:
  2222. ostype = ostag.attrib['type']
  2223. for repotag in ostag:
  2224. reponametag = repotag.find('reponame')
  2225. repoidtag = repotag.find('repoid')
  2226. baseurltag = repotag.find('baseurl')
  2227. if reponametag is not None and repoidtag is not None and baseurltag is not None:
  2228. key = "repo:/" + reponametag.text
  2229. key += "/" + version
  2230. key += "/" + ostype
  2231. key += "/" + repoidtag.text
  2232. key += ":baseurl"
  2233. values[key] = baseurltag.text
  2234. return values
  2235. def get_stack_location(properties):
  2236. stack_location = properties[STACK_LOCATION_KEY]
  2237. if stack_location is None:
  2238. stack_location = STACK_LOCATION_DEFAULT
  2239. return stack_location
  2240. def upgrade_local_repo(args):
  2241. properties = get_ambari_properties()
  2242. if properties == -1:
  2243. print_error_msg("Error getting ambari properties")
  2244. return -1
  2245. stack_location = get_stack_location(properties)
  2246. stack_root_local = os.path.join(stack_location, "HDPLocal")
  2247. if not os.path.exists(stack_root_local):
  2248. print_info_msg("HDPLocal stack directory does not exist, skipping")
  2249. return
  2250. stack_root = os.path.join(stack_location, "HDP")
  2251. if not os.path.exists(stack_root):
  2252. print_info_msg("HDP stack directory does not exist, skipping")
  2253. return
  2254. for stack_version_local in os.listdir(stack_root_local):
  2255. repo_file_local = os.path.join(stack_root_local, stack_version_local, "repos", "repoinfo.xml.rpmsave")
  2256. if not os.path.exists(repo_file_local):
  2257. repo_file_local = os.path.join(stack_root_local, stack_version_local, "repos", "repoinfo.xml")
  2258. repo_file = os.path.join(stack_root, stack_version_local, "repos", "repoinfo.xml")
  2259. print_info_msg("Local repo file: " + repo_file_local)
  2260. print_info_msg("Repo file: " + repo_file_local)
  2261. metainfo_update_items = {}
  2262. if os.path.exists(repo_file_local) and os.path.exists(repo_file):
  2263. local_values = load_stack_values(stack_version_local, repo_file_local)
  2264. repo_values = load_stack_values(stack_version_local, repo_file)
  2265. for k, v in local_values.iteritems():
  2266. if repo_values.has_key(k):
  2267. local_url = local_values[k]
  2268. repo_url = repo_values[k]
  2269. if repo_url != local_url:
  2270. metainfo_update_items[k] = local_url
  2271. run_metainfo_upgrade(metainfo_update_items)
  2272. def change_objects_owner(args):
  2273. print 'Fixing database objects owner'
  2274. database_name = args.database_name
  2275. new_owner = args.database_username
  2276. if '"' not in new_owner:
  2277. #wrap to allow old username "ambari-server", postgres only
  2278. new_owner = '\'"{0}"\''.format(new_owner)
  2279. pass
  2280. command = CHANGE_OWNER_COMMAND[:]
  2281. command[-1] = command[-1].format(database_name, 'ambari', new_owner)
  2282. return run_os_command(command)
  2283. def compare_versions(version1, version2):
  2284. def normalize(v):
  2285. return [int(x) for x in re.sub(r'(\.0+)*$', '', v).split(".")]
  2286. return cmp(normalize(version1), normalize(version2))
  2287. pass
  2288. def run_schema_upgrade():
  2289. jdk_path = find_jdk()
  2290. if jdk_path is None:
  2291. print_error_msg("No JDK found, please run the \"setup\" "
  2292. "command to install a JDK automatically or install any "
  2293. "JDK manually to " + JDK_INSTALL_DIR)
  2294. return 1
  2295. command = SCHEMA_UPGRADE_HELPER_CMD.format(jdk_path, get_conf_dir(), get_ambari_classpath())
  2296. (retcode, stdout, stderr) = run_os_command(command)
  2297. print_info_msg("Return code from schema upgrade command, retcode = " + str(retcode))
  2298. if retcode > 0:
  2299. print_error_msg("Error executing schema upgrade, please check the server logs.")
  2300. return retcode
  2301. def run_stack_upgrade(stackName, stackVersion, repo_url, repo_url_os):
  2302. jdk_path = find_jdk()
  2303. if jdk_path is None:
  2304. return 1, "", "No JDK found, please run the \"setup\" \
  2305. command to install a JDK automatically or install any \
  2306. JDK manually to " + JDK_INSTALL_DIR
  2307. stackId = {}
  2308. stackId[stackName] = stackVersion
  2309. if repo_url is not None:
  2310. stackId['repo_url'] = repo_url
  2311. if repo_url_os is not None:
  2312. stackId['repo_url_os'] = repo_url_os
  2313. command = STACK_UPGRADE_HELPER_CMD.format(jdk_path, get_conf_dir(), get_ambari_classpath(),
  2314. "updateStackId",
  2315. "'" + json.dumps(stackId) + "'")
  2316. return run_os_command(command)
  2317. def run_metainfo_upgrade(keyValueMap=None):
  2318. jdk_path = find_jdk()
  2319. if jdk_path is None:
  2320. print_error_msg("No JDK found, please run the \"setup\" "
  2321. "command to install a JDK automatically or install any "
  2322. "JDK manually to " + JDK_INSTALL_DIR)
  2323. retcode = 1
  2324. if keyValueMap:
  2325. command = STACK_UPGRADE_HELPER_CMD.format(jdk_path, get_conf_dir(), get_ambari_classpath(),
  2326. 'updateMetaInfo',
  2327. "'" + json.dumps(keyValueMap) + "'")
  2328. (retcode, stdout, stderr) = run_os_command(command)
  2329. print_info_msg("Return code from stack upgrade command, retcode = " + str(retcode))
  2330. if retcode > 0:
  2331. print_error_msg("Error executing metainfo upgrade, please check the "
  2332. "server logs.")
  2333. return retcode
  2334. #
  2335. # Upgrades the Ambari Server.
  2336. #
  2337. def upgrade(args):
  2338. if not is_root():
  2339. err = 'Ambari-server upgrade should be run with ' \
  2340. 'root-level privileges'
  2341. raise FatalException(4, err)
  2342. print 'Updating properties in ' + AMBARI_PROPERTIES_FILE + ' ...'
  2343. retcode = update_ambari_properties()
  2344. if not retcode == 0:
  2345. err = AMBARI_PROPERTIES_FILE + ' file can\'t be updated. Exiting'
  2346. raise FatalException(retcode, err)
  2347. try:
  2348. check_database_name_property()
  2349. except FatalException:
  2350. properties = get_ambari_properties()
  2351. if properties == -1:
  2352. print_error_msg("Error getting ambari properties")
  2353. return -1
  2354. print_warning_msg(JDBC_DATABASE_PROPERTY + " property isn't set in " +
  2355. AMBARI_PROPERTIES_FILE + ". Setting it to default value - " + DEFAULT_DB_NAME)
  2356. properties.process_pair(JDBC_DATABASE_PROPERTY, DEFAULT_DB_NAME)
  2357. conf_file = find_properties_file()
  2358. try:
  2359. properties.store(open(conf_file, "w"))
  2360. except Exception, e:
  2361. print_error_msg('Could not write ambari config file "%s": %s' % (conf_file, e))
  2362. return -1
  2363. parse_properties_file(args)
  2364. #TODO check database version
  2365. if args.persistence_type == 'local':
  2366. retcode, stdout, stderr = change_objects_owner(args)
  2367. if not retcode == 0:
  2368. raise FatalException(20, 'Unable to change owner of database objects')
  2369. retcode = run_schema_upgrade()
  2370. if not retcode == 0:
  2371. print_error_msg("Ambari server upgrade failed. Please look at /var/log/ambari-server/ambari-server.log, for more details.")
  2372. raise FatalException(11, 'Schema upgrade failed.')
  2373. user = read_ambari_user()
  2374. if user is None:
  2375. warn = "Can not determine custom ambari user.\n" + SETUP_OR_UPGRADE_MSG
  2376. print_warning_msg(warn)
  2377. else:
  2378. adjust_directory_permissions(user)
  2379. # local repo
  2380. upgrade_local_repo(args)
  2381. # create jdbc symlinks if jdbc drivers are available in resources
  2382. properties = get_ambari_properties()
  2383. if properties == -1:
  2384. err = "Error getting ambari properties"
  2385. print_error_msg(err)
  2386. raise FatalException(-1, err)
  2387. conf_file = properties.fileName
  2388. try:
  2389. resources_dir = properties[RESOURCES_DIR_PROPERTY]
  2390. except (KeyError), e:
  2391. err = 'Property ' + str(e) + ' is not defined at ' + conf_file
  2392. raise FatalException(1, err)
  2393. for db_name in list(JDBC_DB_DEFAULT_DRIVER):
  2394. if os.path.isfile(os.path.join(resources_dir, JDBC_DB_DEFAULT_DRIVER[db_name])):
  2395. symlink_name = db_name + "-jdbc-driver.jar"
  2396. jdbc_symlink = os.path.join(resources_dir, symlink_name)
  2397. if os.path.lexists(jdbc_symlink):
  2398. os.remove(jdbc_symlink)
  2399. os.symlink(os.path.join(resources_dir,JDBC_DB_DEFAULT_DRIVER[db_name]), jdbc_symlink)
  2400. #
  2401. # The Ambari Server status.
  2402. #
  2403. def status(args):
  2404. args.exit_message = None
  2405. status, pid = is_server_runing()
  2406. if status:
  2407. print "Ambari Server running"
  2408. print "Found Ambari Server PID: '" + str(pid) + " at: " + PID_DIR + os.sep + PID_NAME
  2409. else:
  2410. print "Ambari Server not running. Stale PID File at: " + PID_DIR + os.sep + PID_NAME
  2411. #
  2412. # Prints an "info" messsage.
  2413. #
  2414. def print_info_msg(msg):
  2415. if VERBOSE:
  2416. print("INFO: " + msg)
  2417. #
  2418. # Prints an "error" messsage.
  2419. #
  2420. def print_error_msg(msg):
  2421. print("ERROR: " + msg)
  2422. #
  2423. # Prints a "warning" messsage.
  2424. #
  2425. def print_warning_msg(msg, bold=False):
  2426. if bold:
  2427. print(BOLD_ON + "WARNING: " + msg + BOLD_OFF)
  2428. else:
  2429. print("WARNING: " + msg)
  2430. #
  2431. # Gets the y/n input.
  2432. #
  2433. # return True if 'y' or False if 'n'
  2434. #
  2435. def get_YN_input(prompt, default):
  2436. yes = set(['yes', 'ye', 'y'])
  2437. no = set(['no', 'n'])
  2438. return get_choice_string_input(prompt, default, yes, no)
  2439. def get_choice_string_input(prompt, default, firstChoice, secondChoice):
  2440. if SILENT:
  2441. print(prompt)
  2442. return default
  2443. choice = raw_input(prompt).lower()
  2444. if choice in firstChoice:
  2445. return True
  2446. elif choice in secondChoice:
  2447. return False
  2448. elif choice is "": # Just enter pressed
  2449. return default
  2450. else:
  2451. print "input not recognized, please try again: "
  2452. return get_choice_string_input(prompt, default, firstChoice, secondChoice)
  2453. def get_validated_string_input(prompt, default, pattern, description,
  2454. is_pass, allowEmpty=True, validatorFunction=None):
  2455. input = ""
  2456. while not input:
  2457. if SILENT:
  2458. print (prompt)
  2459. input = default
  2460. elif is_pass:
  2461. input = getpass.getpass(prompt)
  2462. else:
  2463. input = raw_input(prompt)
  2464. if not input.strip():
  2465. # Empty input - if default available use default
  2466. if not allowEmpty and not default:
  2467. print 'Property cannot be blank.'
  2468. input = ""
  2469. continue
  2470. else:
  2471. input = default
  2472. if validatorFunction:
  2473. if not validatorFunction(input):
  2474. input = ""
  2475. continue
  2476. break # done here and picking up default
  2477. else:
  2478. if not pattern == None and not re.search(pattern, input.strip()):
  2479. print description
  2480. input = ""
  2481. if validatorFunction:
  2482. if not validatorFunction(input):
  2483. input = ""
  2484. continue
  2485. return input
  2486. def get_value_from_properties(properties, key, default=""):
  2487. try:
  2488. value = properties.get_property(key)
  2489. if not value:
  2490. value = default
  2491. except:
  2492. return default
  2493. return value
  2494. def get_prompt_default(defaultStr=None):
  2495. if not defaultStr or defaultStr == "":
  2496. return ""
  2497. else:
  2498. return '(' + defaultStr + ')'
  2499. def setup_ldap():
  2500. if not is_root():
  2501. err = 'Ambari-server setup-ldap should be run with ' \
  2502. 'root-level privileges'
  2503. raise FatalException(4, err)
  2504. properties = get_ambari_properties()
  2505. isSecure = get_is_secure(properties)
  2506. # python2.x dict is not ordered
  2507. ldap_property_list_reqd = ["authentication.ldap.primaryUrl",
  2508. "authentication.ldap.secondaryUrl",
  2509. "authentication.ldap.useSSL",
  2510. "authentication.ldap.usernameAttribute",
  2511. "authentication.ldap.baseDn",
  2512. "authentication.ldap.bindAnonymously"]
  2513. ldap_property_list_opt = ["authentication.ldap.managerDn",
  2514. LDAP_MGR_PASSWORD_PROPERTY,
  2515. SSL_TRUSTSTORE_TYPE_PROPERTY,
  2516. SSL_TRUSTSTORE_PATH_PROPERTY,
  2517. SSL_TRUSTSTORE_PASSWORD_PROPERTY]
  2518. ldap_property_list_truststore=[SSL_TRUSTSTORE_TYPE_PROPERTY,
  2519. SSL_TRUSTSTORE_PATH_PROPERTY,
  2520. SSL_TRUSTSTORE_PASSWORD_PROPERTY]
  2521. ldap_property_list_passwords=[LDAP_MGR_PASSWORD_PROPERTY,
  2522. SSL_TRUSTSTORE_PASSWORD_PROPERTY]
  2523. LDAP_PRIMARY_URL_DEFAULT = get_value_from_properties(properties, ldap_property_list_reqd[0])
  2524. LDAP_SECONDARY_URL_DEFAULT = get_value_from_properties(properties, ldap_property_list_reqd[1])
  2525. LDAP_USE_SSL_DEFAULT = get_value_from_properties(properties, ldap_property_list_reqd[2], "false")
  2526. LDAP_USER_ATT_DEFAULT = get_value_from_properties(properties, ldap_property_list_reqd[3], "uid")
  2527. LDAP_BASE_DN_DEFAULT = get_value_from_properties(properties, ldap_property_list_reqd[4])
  2528. LDAP_BIND_DEFAULT = get_value_from_properties(properties, ldap_property_list_reqd[5], "false")
  2529. LDAP_MGR_DN_DEFAULT = get_value_from_properties(properties, ldap_property_list_opt[0])
  2530. SSL_TRUSTSTORE_TYPE_DEFAULT = get_value_from_properties(properties, SSL_TRUSTSTORE_TYPE_PROPERTY, "jks")
  2531. SSL_TRUSTSTORE_PATH_DEFAULT = get_value_from_properties(properties, SSL_TRUSTSTORE_PATH_PROPERTY)
  2532. ldap_properties_map_reqd =\
  2533. {
  2534. ldap_property_list_reqd[0]:(LDAP_PRIMARY_URL_DEFAULT, "Primary URL* {{host:port}} {0}: ".format(get_prompt_default(LDAP_PRIMARY_URL_DEFAULT)), False),\
  2535. ldap_property_list_reqd[1]:(LDAP_SECONDARY_URL_DEFAULT, "Secondary URL {{host:port}} {0}: ".format(get_prompt_default(LDAP_SECONDARY_URL_DEFAULT)), True),\
  2536. ldap_property_list_reqd[2]:(LDAP_USE_SSL_DEFAULT, "Use SSL* [true/false] {0}: ".format(get_prompt_default(LDAP_USE_SSL_DEFAULT)), False),\
  2537. ldap_property_list_reqd[3]:(LDAP_USER_ATT_DEFAULT, "User name attribute* {0}: ".format(get_prompt_default(LDAP_USER_ATT_DEFAULT)), False),\
  2538. ldap_property_list_reqd[4]:(LDAP_BASE_DN_DEFAULT, "Base DN* {0}: ".format(get_prompt_default(LDAP_BASE_DN_DEFAULT)), False),\
  2539. ldap_property_list_reqd[5]:(LDAP_BIND_DEFAULT, "Bind anonymously* [true/false] {0}: ".format(get_prompt_default(LDAP_BIND_DEFAULT)), False)\
  2540. }
  2541. ldap_property_value_map = {}
  2542. for idx, key in enumerate(ldap_property_list_reqd):
  2543. if idx in [0, 1]:
  2544. pattern = REGEX_HOSTNAME_PORT
  2545. elif idx in [2, 5]:
  2546. pattern = REGEX_TRUE_FALSE
  2547. else:
  2548. pattern = REGEX_ANYTHING
  2549. input = get_validated_string_input(ldap_properties_map_reqd[key][1],
  2550. ldap_properties_map_reqd[key][0], pattern,
  2551. "Invalid characters in the input!", False, ldap_properties_map_reqd[key][2])
  2552. if input is not None and input != "":
  2553. ldap_property_value_map[key] = input
  2554. bindAnonymously = ldap_property_value_map["authentication.ldap.bindAnonymously"]
  2555. anonymous = (bindAnonymously and bindAnonymously.lower() == 'true')
  2556. mgr_password = None
  2557. # Ask for manager credentials only if bindAnonymously is false
  2558. if not anonymous:
  2559. username = get_validated_string_input("Manager DN* {0}: ".format(
  2560. get_prompt_default(LDAP_MGR_DN_DEFAULT)), LDAP_MGR_DN_DEFAULT, ".*",
  2561. "Invalid characters in the input!", False, False)
  2562. ldap_property_value_map[LDAP_MGR_USERNAME_PROPERTY] = username
  2563. mgr_password = configure_ldap_password()
  2564. ldap_property_value_map[LDAP_MGR_PASSWORD_PROPERTY] = mgr_password
  2565. useSSL = ldap_property_value_map["authentication.ldap.useSSL"]
  2566. ldaps = (useSSL and useSSL.lower() == 'true')
  2567. ts_password = None
  2568. if ldaps:
  2569. truststore_default = "n"
  2570. truststore_set = bool(SSL_TRUSTSTORE_PATH_DEFAULT)
  2571. if truststore_set:
  2572. truststore_default = "y"
  2573. custom_trust_store = get_YN_input("Do you want to provide custom TrustStore for Ambari [y/n] ({0})?".
  2574. format(truststore_default),
  2575. truststore_set)
  2576. if custom_trust_store:
  2577. ts_type = get_validated_string_input(
  2578. "TrustStore type [jks/jceks/pkcs12] {0}:".format(get_prompt_default(SSL_TRUSTSTORE_TYPE_DEFAULT)),
  2579. SSL_TRUSTSTORE_TYPE_DEFAULT,
  2580. "^(jks|jceks|pkcs12)?$", "Wrong type", False)
  2581. ts_path = None
  2582. while True:
  2583. ts_path = get_validated_string_input(
  2584. "Path to TrustStore file {0}:".format(get_prompt_default(SSL_TRUSTSTORE_PATH_DEFAULT)),
  2585. SSL_TRUSTSTORE_PATH_DEFAULT,
  2586. ".*", False, False)
  2587. if os.path.exists(ts_path):
  2588. break
  2589. else:
  2590. print 'File not found.'
  2591. ts_password = read_password("", ".*", "Password for TrustStore:", "Invalid characters in password")
  2592. ldap_property_value_map[SSL_TRUSTSTORE_TYPE_PROPERTY] = ts_type
  2593. ldap_property_value_map[SSL_TRUSTSTORE_PATH_PROPERTY] = ts_path
  2594. ldap_property_value_map[SSL_TRUSTSTORE_PASSWORD_PROPERTY] = ts_password
  2595. pass
  2596. else:
  2597. properties.removeOldProp(SSL_TRUSTSTORE_TYPE_PROPERTY)
  2598. properties.removeOldProp(SSL_TRUSTSTORE_PATH_PROPERTY)
  2599. properties.removeOldProp(SSL_TRUSTSTORE_PASSWORD_PROPERTY)
  2600. pass
  2601. pass
  2602. print '=' * 20
  2603. print 'Review Settings'
  2604. print '=' * 20
  2605. for property in ldap_property_list_reqd:
  2606. if property in ldap_property_value_map:
  2607. print("%s: %s" % (property, ldap_property_value_map[property]))
  2608. for property in ldap_property_list_opt:
  2609. if ldap_property_value_map.has_key(property):
  2610. if property not in ldap_property_list_passwords:
  2611. print("%s: %s" % (property, ldap_property_value_map[property]))
  2612. else:
  2613. print("%s: %s" % (property, BLIND_PASSWORD))
  2614. save_settings = get_YN_input("Save settings [y/n] (y)? ", True)
  2615. if save_settings:
  2616. ldap_property_value_map[CLIENT_SECURITY_KEY] = 'ldap'
  2617. if isSecure:
  2618. if mgr_password:
  2619. encrypted_passwd = encrypt_password(LDAP_MGR_PASSWORD_ALIAS, mgr_password)
  2620. if mgr_password != encrypted_passwd:
  2621. ldap_property_value_map[LDAP_MGR_PASSWORD_PROPERTY] = encrypted_passwd
  2622. pass
  2623. if ts_password:
  2624. encrypted_passwd = encrypt_password(SSL_TRUSTSTORE_PASSWORD_ALIAS, ts_password)
  2625. if ts_password != encrypted_passwd:
  2626. ldap_property_value_map[SSL_TRUSTSTORE_PASSWORD_PROPERTY] = encrypted_passwd
  2627. pass
  2628. pass
  2629. # Persisting values
  2630. update_properties(properties, ldap_property_value_map)
  2631. print 'Saving...done'
  2632. return 0
  2633. def read_master_key(isReset=False):
  2634. passwordPattern = ".*"
  2635. passwordPrompt = "Please provide master key for locking the credential store: "
  2636. passwordDescr = "Invalid characters in password. Use only alphanumeric or "\
  2637. "_ or - characters"
  2638. passwordDefault = ""
  2639. if isReset:
  2640. passwordPrompt = "Enter new Master Key: "
  2641. masterKey = get_validated_string_input(passwordPrompt, passwordDefault,
  2642. passwordPattern, passwordDescr, True, True)
  2643. if not masterKey:
  2644. print "Master Key cannot be empty!"
  2645. return read_master_key()
  2646. masterKey2 = get_validated_string_input("Re-enter master key: ",
  2647. passwordDefault, passwordPattern, passwordDescr, True, True)
  2648. if masterKey != masterKey2:
  2649. print "Master key did not match!"
  2650. return read_master_key()
  2651. return masterKey
  2652. def encrypt_password(alias, password):
  2653. properties = get_ambari_properties()
  2654. if properties == -1:
  2655. raise FatalException(1, None)
  2656. return get_encrypted_password(alias, password, properties)
  2657. def get_encrypted_password(alias, password, properties):
  2658. isSecure = get_is_secure(properties)
  2659. (isPersisted, masterKeyFile) = get_is_persisted(properties)
  2660. if isSecure:
  2661. masterKey = None
  2662. if not masterKeyFile:
  2663. # Encryption enabled but no master key file found
  2664. masterKey = get_original_master_key(properties)
  2665. retCode = save_passwd_for_alias(alias, password, masterKey)
  2666. if retCode != 0:
  2667. print 'Failed to save secure password!'
  2668. return password
  2669. else:
  2670. return get_alias_string(alias)
  2671. return password
  2672. def decrypt_password_for_alias(alias):
  2673. properties = get_ambari_properties()
  2674. if properties == -1:
  2675. raise FatalException(1, None)
  2676. isSecure = get_is_secure(properties)
  2677. (isPersisted, masterKeyFile) = get_is_persisted(properties)
  2678. if isSecure:
  2679. masterKey = None
  2680. if not masterKeyFile:
  2681. # Encryption enabled but no master key file found
  2682. masterKey = get_original_master_key(properties)
  2683. return read_passwd_for_alias(alias, masterKey)
  2684. else:
  2685. return alias
  2686. def get_original_master_key(properties):
  2687. try:
  2688. masterKey = get_validated_string_input('Enter current Master Key: ',
  2689. "", ".*", "", True, False)
  2690. except KeyboardInterrupt:
  2691. print 'Exiting...'
  2692. sys.exit(1)
  2693. # Find an alias that exists
  2694. alias = None
  2695. property = properties.get_property(JDBC_PASSWORD_PROPERTY)
  2696. if property and is_alias_string(property):
  2697. alias = JDBC_RCA_PASSWORD_ALIAS
  2698. if not alias:
  2699. property = properties.get_property(LDAP_MGR_PASSWORD_PROPERTY)
  2700. if property and is_alias_string(property):
  2701. alias = LDAP_MGR_PASSWORD_ALIAS
  2702. if not alias:
  2703. property = properties.get_property(SSL_TRUSTSTORE_PASSWORD_PROPERTY)
  2704. if property and is_alias_string(property):
  2705. alias = SSL_TRUSTSTORE_PASSWORD_ALIAS
  2706. # Decrypt alias with master to validate it, if no master return
  2707. if alias and masterKey:
  2708. password = read_passwd_for_alias(alias, masterKey)
  2709. if not password:
  2710. print "ERROR: Master key does not match."
  2711. return get_original_master_key(properties)
  2712. return masterKey
  2713. def get_is_secure(properties):
  2714. isSecure = properties.get_property(SECURITY_IS_ENCRYPTION_ENABLED)
  2715. isSecure = True if isSecure and isSecure.lower() == 'true' else False
  2716. return isSecure
  2717. def get_is_persisted(properties):
  2718. keyLocation = get_master_key_location(properties)
  2719. masterKeyFile = search_file(SECURITY_MASTER_KEY_FILENAME, keyLocation)
  2720. isPersisted = True if masterKeyFile else False
  2721. return (isPersisted, masterKeyFile)
  2722. def setup_master_key():
  2723. if not is_root():
  2724. err = 'Ambari-server setup should be run with '\
  2725. 'root-level privileges'
  2726. raise FatalException(4, err)
  2727. properties = get_ambari_properties()
  2728. if properties == -1:
  2729. raise FatalException(1, "Failed to read properties file.")
  2730. db_password = properties.get_property(JDBC_PASSWORD_PROPERTY)
  2731. # Encrypt passwords cannot be called before setup
  2732. if not db_password:
  2733. print 'Please call "setup" before "encrypt-passwords". Exiting...'
  2734. return 1
  2735. # Check configuration for location of master key
  2736. isSecure = get_is_secure(properties)
  2737. (isPersisted, masterKeyFile) = get_is_persisted(properties)
  2738. # Read clear text password from file
  2739. if not is_alias_string(db_password) and os.path.isfile(db_password):
  2740. with open(db_password, 'r') as passwdfile:
  2741. db_password = passwdfile.read()
  2742. ldap_password = properties.get_property(LDAP_MGR_PASSWORD_PROPERTY)
  2743. ts_password = properties.get_property(SSL_TRUSTSTORE_PASSWORD_PROPERTY)
  2744. resetKey = False
  2745. masterKey = None
  2746. if isSecure:
  2747. print "Password encryption is enabled."
  2748. resetKey = get_YN_input("Do you want to reset Master Key? [y/n] (n): ", False)
  2749. # For encrypting of only unencrypted passwords without resetting the key ask
  2750. # for master key if not persisted.
  2751. if isSecure and not isPersisted and not resetKey:
  2752. print "Master Key not persisted."
  2753. masterKey = get_original_master_key(properties)
  2754. pass
  2755. # Make sure both passwords are clear-text if master key is lost
  2756. if resetKey:
  2757. if not isPersisted:
  2758. print "Master Key not persisted."
  2759. masterKey = get_original_master_key(properties)
  2760. # Unable get the right master key or skipped question <enter>
  2761. if not masterKey:
  2762. print "To disable encryption, do the following:"
  2763. print "- Edit " + find_properties_file() + \
  2764. " and set " + SECURITY_IS_ENCRYPTION_ENABLED + " = " + "false."
  2765. err = "{0} is already encrypted. Please call {1} to store unencrypted" \
  2766. " password and call 'encrypt-passwords' again."
  2767. if db_password and is_alias_string(db_password):
  2768. print err.format('- Database password', "'" + SETUP_ACTION + "'")
  2769. if ldap_password and is_alias_string(ldap_password):
  2770. print err.format('- LDAP manager password', "'" + LDAP_SETUP_ACTION + "'")
  2771. if ts_password and is_alias_string(ts_password):
  2772. print err.format('TrustStore password', "'" + LDAP_SETUP_ACTION + "'")
  2773. return 1
  2774. pass
  2775. pass
  2776. pass
  2777. # Read back any encrypted passwords
  2778. if db_password and is_alias_string(db_password):
  2779. db_password = read_passwd_for_alias(JDBC_RCA_PASSWORD_ALIAS, masterKey)
  2780. if ldap_password and is_alias_string(ldap_password):
  2781. ldap_password = read_passwd_for_alias(LDAP_MGR_PASSWORD_ALIAS, masterKey)
  2782. if ts_password and is_alias_string(ts_password):
  2783. ts_password = read_passwd_for_alias(SSL_TRUSTSTORE_PASSWORD_ALIAS, masterKey)
  2784. # Read master key, if non-secure or reset is true
  2785. if resetKey or not isSecure:
  2786. masterKey = read_master_key(resetKey)
  2787. persist = get_YN_input("Do you want to persist master key. If you choose "\
  2788. "not to persist, you need to provide the Master "\
  2789. "Key while starting the ambari server as an env "\
  2790. "variable named " + SECURITY_KEY_ENV_VAR_NAME +\
  2791. " or the start will prompt for the master key."
  2792. " Persist [y/n] (y)? ", True)
  2793. if persist:
  2794. save_master_key(masterKey, get_master_key_location(properties) + os.sep +
  2795. SECURITY_MASTER_KEY_FILENAME, persist)
  2796. elif not persist and masterKeyFile:
  2797. try:
  2798. os.remove(masterKeyFile)
  2799. print_info_msg("Deleting master key file at location: " + str(
  2800. masterKeyFile))
  2801. except Exception, e:
  2802. print 'ERROR: Could not remove master key file. %s' % e
  2803. # Blow up the credential store made with previous key, if any
  2804. store_file = get_credential_store_location(properties)
  2805. if os.path.exists(store_file):
  2806. try:
  2807. os.remove(store_file)
  2808. except:
  2809. print_warning_msg("Failed to remove credential store file.")
  2810. pass
  2811. pass
  2812. pass
  2813. propertyMap = {SECURITY_IS_ENCRYPTION_ENABLED: 'true'}
  2814. # Encrypt only un-encrypted passwords
  2815. if db_password and not is_alias_string(db_password):
  2816. retCode = save_passwd_for_alias(JDBC_RCA_PASSWORD_ALIAS, db_password, masterKey)
  2817. if retCode != 0:
  2818. print 'Failed to save secure database password.'
  2819. else:
  2820. propertyMap[JDBC_PASSWORD_PROPERTY] = get_alias_string(JDBC_RCA_PASSWORD_ALIAS)
  2821. remove_password_file(JDBC_PASSWORD_FILENAME)
  2822. if properties.get_property(JDBC_RCA_PASSWORD_FILE_PROPERTY):
  2823. propertyMap[JDBC_RCA_PASSWORD_FILE_PROPERTY] = get_alias_string(JDBC_RCA_PASSWORD_ALIAS)
  2824. pass
  2825. if ldap_password and not is_alias_string(ldap_password):
  2826. retCode = save_passwd_for_alias(LDAP_MGR_PASSWORD_ALIAS, ldap_password, masterKey)
  2827. if retCode != 0:
  2828. print 'Failed to save secure LDAP password.'
  2829. else:
  2830. propertyMap[LDAP_MGR_PASSWORD_PROPERTY] = get_alias_string(LDAP_MGR_PASSWORD_ALIAS)
  2831. pass
  2832. if ts_password and not is_alias_string(ts_password):
  2833. retCode = save_passwd_for_alias(SSL_TRUSTSTORE_PASSWORD_ALIAS, ts_password, masterKey)
  2834. if retCode != 0:
  2835. print 'Failed to save secure TrustStore password.'
  2836. else:
  2837. propertyMap[SSL_TRUSTSTORE_PASSWORD_PROPERTY] = get_alias_string(SSL_TRUSTSTORE_PASSWORD_ALIAS)
  2838. pass
  2839. update_properties(properties, propertyMap)
  2840. # Since files for store and master are created we need to ensure correct
  2841. # permissions
  2842. ambari_user = read_ambari_user()
  2843. if ambari_user:
  2844. adjust_directory_permissions(ambari_user)
  2845. return 0
  2846. def get_credential_store_location(properties):
  2847. store_loc = properties[SECURITY_KEYS_DIR]
  2848. if store_loc is None or store_loc == "":
  2849. store_loc = "/var/lib/ambari-server/keys/credentials.jceks"
  2850. else:
  2851. store_loc += os.sep + "credentials.jceks"
  2852. return store_loc
  2853. def get_master_key_location(properties):
  2854. keyLocation = properties[SECURITY_MASTER_KEY_LOCATION]
  2855. if keyLocation is None or keyLocation == "":
  2856. keyLocation = properties[SECURITY_KEYS_DIR]
  2857. return keyLocation
  2858. def is_alias_string(passwdStr):
  2859. regex = re.compile("\$\{alias=[\w\.]+\}")
  2860. # Match implies string at beginning of word
  2861. r = regex.match(passwdStr)
  2862. if r is not None:
  2863. return True
  2864. else:
  2865. return False
  2866. def get_alias_string(alias):
  2867. return "${alias=" + alias + "}"
  2868. def get_alias_from_alias_string(aliasStr):
  2869. return aliasStr[8:-1]
  2870. def read_passwd_for_alias(alias, masterKey=""):
  2871. if alias:
  2872. jdk_path = find_jdk()
  2873. if jdk_path is None:
  2874. print_error_msg("No JDK found, please run the \"setup\" "
  2875. "command to install a JDK automatically or install any "
  2876. "JDK manually to " + JDK_INSTALL_DIR)
  2877. return 1
  2878. tempFileName = "ambari.passwd"
  2879. passwd = ""
  2880. tempDir = tempfile.gettempdir()
  2881. #create temporary file for writing
  2882. tempFilePath = tempDir + os.sep + tempFileName
  2883. file = open(tempFilePath, 'w+')
  2884. os.chmod(tempFilePath, stat.S_IREAD | stat.S_IWRITE)
  2885. file.close()
  2886. if masterKey is None or masterKey == "":
  2887. masterKey = "None"
  2888. command = SECURITY_PROVIDER_GET_CMD.format(jdk_path,
  2889. get_conf_dir(), get_ambari_classpath(), alias, tempFilePath, masterKey)
  2890. (retcode, stdout, stderr) = run_os_command(command)
  2891. print_info_msg("Return code from credential provider get passwd: " +
  2892. str(retcode))
  2893. if retcode != 0:
  2894. print 'ERROR: Unable to read password from store. alias = ' + alias
  2895. else:
  2896. passwd = open(tempFilePath, 'r').read()
  2897. # Remove temporary file
  2898. os.remove(tempFilePath)
  2899. return passwd
  2900. else:
  2901. print_error_msg("Alias is unreadable.")
  2902. def save_passwd_for_alias(alias, passwd, masterKey=""):
  2903. if alias and passwd:
  2904. jdk_path = find_jdk()
  2905. if jdk_path is None:
  2906. print_error_msg("No JDK found, please run the \"setup\" "
  2907. "command to install a JDK automatically or install any "
  2908. "JDK manually to " + JDK_INSTALL_DIR)
  2909. return 1
  2910. if masterKey is None or masterKey == "":
  2911. masterKey = "None"
  2912. command = SECURITY_PROVIDER_PUT_CMD.format(jdk_path, get_conf_dir(),
  2913. get_ambari_classpath(), alias, passwd, masterKey)
  2914. (retcode, stdout, stderr) = run_os_command(command)
  2915. print_info_msg("Return code from credential provider save passwd: " +
  2916. str(retcode))
  2917. return retcode
  2918. else:
  2919. print_error_msg("Alias or password is unreadable.")
  2920. def save_master_key(master_key, key_location, persist=True):
  2921. if master_key:
  2922. jdk_path = find_jdk()
  2923. if jdk_path is None:
  2924. print_error_msg("No JDK found, please run the \"setup\" "
  2925. "command to install a JDK automatically or install any "
  2926. "JDK manually to " + JDK_INSTALL_DIR)
  2927. return 1
  2928. command = SECURITY_PROVIDER_KEY_CMD.format(jdk_path,
  2929. get_ambari_classpath(), get_conf_dir(), master_key, key_location, persist)
  2930. (retcode, stdout, stderr) = run_os_command(command)
  2931. print_info_msg("Return code from credential provider save KEY: " +
  2932. str(retcode))
  2933. else:
  2934. print_error_msg("Master key cannot be None.")
  2935. def configure_ldap_password():
  2936. passwordDefault = ""
  2937. passwordPrompt = 'Enter Manager Password* : '
  2938. passwordPattern = ".*"
  2939. passwordDescr = "Invalid characters in password."
  2940. password = read_password(passwordDefault, passwordPattern, passwordPrompt,
  2941. passwordDescr)
  2942. return password
  2943. # Copy file to /tmp and save with file.# (largest # is latest file)
  2944. def backup_file_in_temp(filePath):
  2945. if filePath is not None:
  2946. tmpDir = tempfile.gettempdir()
  2947. back_up_file_count = len(glob.glob1(tmpDir, AMBARI_PROPERTIES_FILE + "*"))
  2948. try:
  2949. shutil.copyfile(filePath, tmpDir + os.sep +
  2950. AMBARI_PROPERTIES_FILE + "." + str(back_up_file_count + 1))
  2951. except (Exception), e:
  2952. print_error_msg('Could not backup file in temp "%s": %s' % (str(
  2953. back_up_file_count, e)))
  2954. return 0
  2955. # update properties in a section-less properties file
  2956. # Cannot use ConfigParser due to bugs in version 2.6
  2957. def update_properties(propertyMap):
  2958. conf_file = search_file(AMBARI_PROPERTIES_FILE, get_conf_dir())
  2959. backup_file_in_temp(conf_file)
  2960. if propertyMap is not None and conf_file is not None:
  2961. properties = Properties()
  2962. try:
  2963. with open(conf_file, 'r') as file:
  2964. properties.load(file)
  2965. except (Exception), e:
  2966. print_error_msg('Could not read "%s": %s' % (conf_file, e))
  2967. return -1
  2968. #for key in propertyMap.keys():
  2969. #properties[key] = propertyMap[key]
  2970. for key in propertyMap.keys():
  2971. properties.removeOldProp(key)
  2972. properties.process_pair(key, str(propertyMap[key]))
  2973. with open(conf_file, 'w') as file:
  2974. properties.store(file)
  2975. return 0
  2976. def update_properties(properties, propertyMap):
  2977. conf_file = search_file(AMBARI_PROPERTIES_FILE, get_conf_dir())
  2978. backup_file_in_temp(conf_file)
  2979. if conf_file is not None:
  2980. if propertyMap is not None:
  2981. for key in propertyMap.keys():
  2982. properties.removeOldProp(key)
  2983. properties.process_pair(key, str(propertyMap[key]))
  2984. pass
  2985. with open(conf_file, 'w') as file:
  2986. properties.store(file)
  2987. pass
  2988. pass
  2989. def setup_https(args):
  2990. if not is_root():
  2991. err = 'ambari-server setup-https should be run with ' \
  2992. 'root-level privileges'
  2993. raise FatalException(4, err)
  2994. args.exit_message = None
  2995. if not SILENT:
  2996. properties = get_ambari_properties()
  2997. try:
  2998. security_server_keys_dir = properties.get_property(SSL_KEY_DIR)
  2999. client_api_ssl_port = DEFAULT_SSL_API_PORT if properties.get_property(SSL_API_PORT) in ("")\
  3000. else properties.get_property(SSL_API_PORT)
  3001. api_ssl = properties.get_property(SSL_API) in ['true']
  3002. cert_was_imported = False
  3003. cert_must_import = True
  3004. if api_ssl:
  3005. if get_YN_input("Do you want to disable HTTPS [y/n] (n)? ", False):
  3006. properties.process_pair(SSL_API, "false")
  3007. cert_must_import=False
  3008. else:
  3009. properties.process_pair(SSL_API_PORT, \
  3010. get_validated_string_input(\
  3011. "SSL port ["+str(client_api_ssl_port)+"] ? ",\
  3012. str(client_api_ssl_port),\
  3013. "^[0-9]{1,5}$", "Invalid port.", False, validatorFunction = is_valid_https_port))
  3014. cert_was_imported = import_cert_and_key_action(security_server_keys_dir, properties)
  3015. else:
  3016. if get_YN_input("Do you want to configure HTTPS [y/n] (y)? ", True):
  3017. properties.process_pair(SSL_API_PORT,\
  3018. get_validated_string_input("SSL port ["+str(client_api_ssl_port)+"] ? ",\
  3019. str(client_api_ssl_port), "^[0-9]{1,5}$", "Invalid port.", False, validatorFunction = is_valid_https_port))
  3020. cert_was_imported = import_cert_and_key_action(security_server_keys_dir, properties)
  3021. else:
  3022. return False
  3023. if cert_must_import and not cert_was_imported:
  3024. print 'Setup of HTTPS failed. Exiting.'
  3025. return False
  3026. conf_file = find_properties_file()
  3027. f = open(conf_file, 'w')
  3028. properties.store(f, "Changed by 'ambari-server setup-https' command")
  3029. ambari_user = read_ambari_user()
  3030. if ambari_user:
  3031. adjust_directory_permissions(ambari_user)
  3032. return True
  3033. except (KeyError), e:
  3034. err = 'Property ' + str(e) + ' is not defined'
  3035. raise FatalException(1, err)
  3036. else:
  3037. warning = "setup-https is not enabled in silent mode."
  3038. raise NonFatalException(warning)
  3039. def is_server_runing():
  3040. pid_file_path = PID_DIR + os.sep + PID_NAME
  3041. if os.path.exists(pid_file_path):
  3042. try:
  3043. f = open(pid_file_path, "r")
  3044. except IOError, ex:
  3045. raise FatalException(1, str(ex))
  3046. pid = f.readline().strip()
  3047. if not pid.isdigit():
  3048. err = "%s is corrupt. Removing" % (pid_file_path)
  3049. f.close()
  3050. run_os_command("rm -f " + pid_file_path)
  3051. raise NonFatalException(err)
  3052. f.close()
  3053. retcode, out, err = run_os_command("ps -p " + pid)
  3054. if retcode == 0:
  3055. return True, int(pid)
  3056. else:
  3057. return False, None
  3058. else:
  3059. return False, None
  3060. def setup_component_https(component, command, property, alias):
  3061. if not SILENT:
  3062. jdk_path = find_jdk()
  3063. if jdk_path is None:
  3064. err = "No JDK found, please run the \"ambari-server setup\" " \
  3065. "command to install a JDK automatically or install any " \
  3066. "JDK manually to " + JDK_INSTALL_DIR
  3067. raise FatalException(1, err)
  3068. properties = get_ambari_properties()
  3069. use_https = properties.get_property(property) in ['true']
  3070. if use_https:
  3071. if get_YN_input("Do you want to disable HTTPS for " + component + " [y/n] (n)? ", False):
  3072. truststore_path = get_truststore_path(properties)
  3073. truststore_password = get_truststore_password(properties)
  3074. run_component_https_cmd(get_delete_cert_command(jdk_path, alias, truststore_path, truststore_password))
  3075. properties.process_pair(property, "false")
  3076. else:
  3077. return
  3078. else:
  3079. if get_YN_input("Do you want to configure HTTPS for " + component + " [y/n] (y)? ", True):
  3080. truststore_type = get_truststore_type(properties)
  3081. truststore_path = get_truststore_path(properties)
  3082. truststore_password = get_truststore_password(properties)
  3083. run_os_command(get_delete_cert_command(jdk_path, alias, truststore_path, truststore_password))
  3084. import_cert_path = get_validated_filepath_input(\
  3085. "Enter path to " + component + " Certificate: ",\
  3086. "Certificate not found")
  3087. run_component_https_cmd(get_import_cert_command(jdk_path, alias, truststore_type, import_cert_path, truststore_path, truststore_password))
  3088. properties.process_pair(property, "true")
  3089. else:
  3090. return
  3091. conf_file = find_properties_file()
  3092. f = open(conf_file, 'w')
  3093. properties.store(f, "Changed by 'ambari-server " + command + "' command")
  3094. else:
  3095. print command + " is not enabled in silent mode."
  3096. def get_truststore_type(properties):
  3097. truststore_type = properties.get_property(SSL_TRUSTSTORE_TYPE_PROPERTY)
  3098. if not truststore_type:
  3099. SSL_TRUSTSTORE_TYPE_DEFAULT = get_value_from_properties(properties, SSL_TRUSTSTORE_TYPE_PROPERTY, "jks")
  3100. truststore_type = get_validated_string_input(
  3101. "TrustStore type [jks/jceks/pkcs12] {0}:".format(get_prompt_default(SSL_TRUSTSTORE_TYPE_DEFAULT)),
  3102. SSL_TRUSTSTORE_TYPE_DEFAULT,
  3103. "^(jks|jceks|pkcs12)?$", "Wrong type", False)
  3104. if truststore_type:
  3105. properties.process_pair(SSL_TRUSTSTORE_TYPE_PROPERTY, truststore_type)
  3106. return truststore_type
  3107. def get_truststore_path(properties):
  3108. truststore_path = properties.get_property(SSL_TRUSTSTORE_PATH_PROPERTY)
  3109. if not truststore_path:
  3110. SSL_TRUSTSTORE_PATH_DEFAULT = get_value_from_properties(properties, SSL_TRUSTSTORE_PATH_PROPERTY)
  3111. while not truststore_path:
  3112. truststore_path = get_validated_string_input(
  3113. "Path to TrustStore file {0}:".format(get_prompt_default(SSL_TRUSTSTORE_PATH_DEFAULT)),
  3114. SSL_TRUSTSTORE_PATH_DEFAULT,
  3115. ".*", False, False)
  3116. if truststore_path:
  3117. properties.process_pair(SSL_TRUSTSTORE_PATH_PROPERTY, truststore_path)
  3118. return truststore_path
  3119. def get_truststore_password(properties):
  3120. truststore_password = properties.get_property(SSL_TRUSTSTORE_PASSWORD_PROPERTY)
  3121. isSecure = get_is_secure(properties)
  3122. if truststore_password:
  3123. if isSecure:
  3124. truststore_password = decrypt_password_for_alias(SSL_TRUSTSTORE_PASSWORD_ALIAS)
  3125. else:
  3126. truststore_password = read_password("", ".*", "Password for TrustStore:", "Invalid characters in password")
  3127. if truststore_password:
  3128. encrypted_password = get_encrypted_password(SSL_TRUSTSTORE_PASSWORD_ALIAS, truststore_password, properties)
  3129. properties.process_pair(SSL_TRUSTSTORE_PASSWORD_PROPERTY, encrypted_password)
  3130. return truststore_password
  3131. def run_component_https_cmd(cmd):
  3132. retcode, out, err = run_os_command(cmd)
  3133. if not retcode == 0:
  3134. err = 'Error occured during truststore setup ! :' + out + " : " + err
  3135. raise FatalException(1, err)
  3136. def get_delete_cert_command(jdk_path, alias, truststore_path, truststore_password):
  3137. cmd = KEYTOOL_DELETE_CERT_CMD.format(jdk_path, alias, truststore_password)
  3138. if truststore_path:
  3139. cmd += KEYTOOL_KEYSTORE.format(truststore_path)
  3140. return cmd
  3141. def get_import_cert_command(jdk_path, alias, truststore_type, import_cert_path, truststore_path, truststore_password):
  3142. cmd = KEYTOOL_IMPORT_CERT_CMD.format(jdk_path, alias, truststore_type, import_cert_path, truststore_password)
  3143. if truststore_path:
  3144. cmd += KEYTOOL_KEYSTORE.format(truststore_path)
  3145. return cmd
  3146. def import_cert_and_key_action(security_server_keys_dir, properties):
  3147. if import_cert_and_key(security_server_keys_dir):
  3148. properties.process_pair(SSL_SERVER_CERT_NAME, SSL_CERT_FILE_NAME)
  3149. properties.process_pair(SSL_SERVER_KEY_NAME, SSL_KEY_FILE_NAME)
  3150. properties.process_pair(SSL_API, "true")
  3151. return True
  3152. else:
  3153. return False
  3154. def import_cert_and_key(security_server_keys_dir):
  3155. import_cert_path = get_validated_filepath_input(\
  3156. "Enter path to Certificate: ",\
  3157. "Certificate not found")
  3158. import_key_path = get_validated_filepath_input(\
  3159. "Enter path to Private Key: ", "Private Key not found")
  3160. pem_password = get_validated_string_input("Please enter password for Private Key: ", "", None, None, True)
  3161. certInfoDict = get_cert_info(import_cert_path)
  3162. if not certInfoDict:
  3163. print_warning_msg('Unable to get Certificate information')
  3164. else:
  3165. #Validate common name of certificate
  3166. if not is_valid_cert_host(certInfoDict):
  3167. print_warning_msg('Unable to validate Certificate hostname')
  3168. #Validate issue and expirations dates of certificate
  3169. if not is_valid_cert_exp(certInfoDict):
  3170. print_warning_msg('Unable to validate Certificate issue and expiration dates')
  3171. #jetty requires private key files with non-empty key passwords
  3172. retcode = 0
  3173. err = ''
  3174. if not pem_password:
  3175. print 'Generating random password for HTTPS keystore...done.'
  3176. pem_password = generate_random_string()
  3177. retcode, out, err = run_os_command(CHANGE_KEY_PWD_CND.format(
  3178. import_key_path, pem_password))
  3179. import_key_path += '.secured'
  3180. if retcode == 0:
  3181. keystoreFilePath = os.path.join(security_server_keys_dir,\
  3182. SSL_KEYSTORE_FILE_NAME)
  3183. keystoreFilePathTmp = os.path.join(tempfile.gettempdir(),\
  3184. SSL_KEYSTORE_FILE_NAME)
  3185. passFilePath = os.path.join(security_server_keys_dir,\
  3186. SSL_KEY_PASSWORD_FILE_NAME)
  3187. passFilePathTmp = os.path.join(tempfile.gettempdir(),\
  3188. SSL_KEY_PASSWORD_FILE_NAME)
  3189. passinFilePath = os.path.join(tempfile.gettempdir(),\
  3190. SSL_PASSIN_FILE)
  3191. passwordFilePath = os.path.join(tempfile.gettempdir(),\
  3192. SSL_PASSWORD_FILE)
  3193. with open(passFilePathTmp, 'w+') as passFile:
  3194. passFile.write(pem_password)
  3195. passFile.close
  3196. pass
  3197. set_file_permissions(passFilePath, "660", read_ambari_user(), False)
  3198. copy_file(passFilePathTmp, passinFilePath)
  3199. copy_file(passFilePathTmp, passwordFilePath)
  3200. retcode, out, err = run_os_command(EXPRT_KSTR_CMD.format(import_cert_path,\
  3201. import_key_path, passwordFilePath, passinFilePath, keystoreFilePathTmp))
  3202. if retcode == 0:
  3203. print 'Importing and saving Certificate...done.'
  3204. import_file_to_keystore(keystoreFilePathTmp, keystoreFilePath)
  3205. import_file_to_keystore(passFilePathTmp, passFilePath)
  3206. import_file_to_keystore(import_cert_path, os.path.join(\
  3207. security_server_keys_dir, SSL_CERT_FILE_NAME))
  3208. import_file_to_keystore(import_key_path, os.path.join(\
  3209. security_server_keys_dir, SSL_KEY_FILE_NAME))
  3210. #Validate keystore
  3211. retcode, out, err = run_os_command(VALIDATE_KEYSTORE_CMD.format(keystoreFilePath,\
  3212. passwordFilePath, passinFilePath))
  3213. remove_file(passinFilePath)
  3214. remove_file(passwordFilePath)
  3215. if not retcode == 0:
  3216. print 'Error during keystore validation occured!:'
  3217. print err
  3218. return False
  3219. return True
  3220. else:
  3221. print_error_msg('Could not import Certificate and Private Key.')
  3222. print 'SSL error on exporting keystore: ' + err.rstrip() + \
  3223. '.\nPlease ensure that provided Private Key password is correct and ' +\
  3224. 're-import Certificate.'
  3225. return False
  3226. def import_file_to_keystore(source, destination):
  3227. shutil.copy(source, destination)
  3228. set_file_permissions(destination, "660", read_ambari_user(), False)
  3229. def generate_random_string(length=SSL_KEY_PASSWORD_LENGTH):
  3230. chars = string.digits + string.ascii_letters
  3231. return ''.join(random.choice(chars) for x in range(length))
  3232. def get_validated_filepath_input(prompt, description, default=None):
  3233. input = False
  3234. while not input:
  3235. if SILENT:
  3236. print (prompt)
  3237. return default
  3238. else:
  3239. input = raw_input(prompt)
  3240. if not input == None:
  3241. input = input.strip()
  3242. if not input == None and not "" == input and os.path.isfile(input):
  3243. return input
  3244. else:
  3245. print description
  3246. input = False
  3247. def get_cert_info(path):
  3248. retcode, out, err = run_os_command(GET_CRT_INFO_CMD.format(path))
  3249. if retcode != 0:
  3250. print 'Error getting Certificate info'
  3251. print err
  3252. return None
  3253. if out:
  3254. certInfolist = out.split(os.linesep)
  3255. else:
  3256. print 'Empty Certificate info'
  3257. return None
  3258. notBefore = None
  3259. notAfter = None
  3260. subject = None
  3261. for item in range(len(certInfolist)):
  3262. if certInfolist[item].startswith('notAfter='):
  3263. notAfter = certInfolist[item].split('=')[1]
  3264. if certInfolist[item].startswith('notBefore='):
  3265. notBefore = certInfolist[item].split('=')[1]
  3266. if certInfolist[item].startswith('subject='):
  3267. subject = certInfolist[item].split('=', 1)[1]
  3268. #Convert subj to dict
  3269. pattern = re.compile(r"[A-Z]{1,2}=[\w.-]{1,}")
  3270. if subject:
  3271. subjList = pattern.findall(subject)
  3272. keys = [item.split('=')[0] for item in subjList]
  3273. values = [item.split('=')[1] for item in subjList]
  3274. subjDict = dict(zip(keys, values))
  3275. result = subjDict
  3276. result['notBefore'] = notBefore
  3277. result['notAfter'] = notAfter
  3278. result['subject'] = subject
  3279. return result
  3280. else:
  3281. return {}
  3282. def is_valid_cert_exp(certInfoDict):
  3283. if certInfoDict.has_key(NOT_BEFORE_ATTR):
  3284. notBefore = certInfoDict[NOT_BEFORE_ATTR]
  3285. else:
  3286. print_warning_msg('There is no Not Before value in Certificate')
  3287. return False
  3288. if certInfoDict.has_key(NOT_AFTER_ATTR):
  3289. notAfter = certInfoDict['notAfter']
  3290. else:
  3291. print_warning_msg('There is no Not After value in Certificate')
  3292. return False
  3293. notBeforeDate = datetime.datetime.strptime(notBefore, SSL_DATE_FORMAT)
  3294. notAfterDate = datetime.datetime.strptime(notAfter, SSL_DATE_FORMAT)
  3295. currentDate = datetime.datetime.now()
  3296. if currentDate > notAfterDate:
  3297. print_warning_msg('Certificate expired on: ' + str(notAfterDate))
  3298. return False
  3299. if currentDate < notBeforeDate:
  3300. print_warning_msg('Certificate will be active from: ' + str(notBeforeDate))
  3301. return False
  3302. return True
  3303. def is_valid_cert_host(certInfoDict):
  3304. if certInfoDict.has_key(COMMON_NAME_ATTR):
  3305. commonName = certInfoDict[COMMON_NAME_ATTR]
  3306. else:
  3307. print_warning_msg('There is no Common Name in Certificate')
  3308. return False
  3309. fqdn = get_fqdn()
  3310. if not fqdn:
  3311. print_warning_msg('Failed to get server FQDN')
  3312. return False
  3313. if commonName != fqdn:
  3314. print_warning_msg('Common Name in Certificate: ' + commonName + ' does not match the server FQDN: ' + fqdn)
  3315. return False
  3316. return True
  3317. def is_valid_https_port(port):
  3318. properties = get_ambari_properties()
  3319. if properties == -1:
  3320. print "Error getting ambari properties"
  3321. return False
  3322. one_way_port = properties[SRVR_ONE_WAY_SSL_PORT_PROPERTY]
  3323. if not one_way_port:
  3324. one_way_port = SRVR_ONE_WAY_SSL_PORT
  3325. two_way_port = properties[SRVR_TWO_WAY_SSL_PORT_PROPERTY]
  3326. if not two_way_port:
  3327. two_way_port = SRVR_TWO_WAY_SSL_PORT
  3328. if port.strip() == one_way_port.strip():
  3329. print "Port for https can't match the port for one way authentication port(" + one_way_port + ")"
  3330. return False
  3331. if port.strip() == two_way_port.strip():
  3332. print "Port for https can't match the port for two way authentication port(" + two_way_port + ")"
  3333. return False
  3334. return True
  3335. def get_fqdn():
  3336. properties = get_ambari_properties()
  3337. if properties == -1:
  3338. print "Error reading ambari properties"
  3339. return None
  3340. get_fqdn_service_url = properties[GET_FQDN_SERVICE_URL]
  3341. try:
  3342. handle = urllib2.urlopen(get_fqdn_service_url, '', 2)
  3343. str = handle.read()
  3344. handle.close()
  3345. return str
  3346. except Exception:
  3347. return socket.getfqdn()
  3348. def get_ulimit_open_files():
  3349. properties = get_ambari_properties()
  3350. if properties == -1:
  3351. print "Error reading ambari properties"
  3352. return None
  3353. open_files = int(properties[ULIMIT_OPEN_FILES_KEY])
  3354. if open_files > 0:
  3355. return open_files
  3356. else:
  3357. return ULIMIT_OPEN_FILES_DEFAULT
  3358. def is_valid_filepath(filepath):
  3359. if not filepath or not os.path.exists(filepath) or os.path.isdir(filepath):
  3360. print 'Invalid path, please provide the absolute file path.'
  3361. return False
  3362. else:
  3363. return True
  3364. def setup_ambari_krb5_jaas():
  3365. jaas_conf_file = search_file(SECURITY_KERBEROS_JASS_FILENAME, get_conf_dir())
  3366. if os.path.exists(jaas_conf_file):
  3367. print 'Setting up Ambari kerberos JAAS configuration to access ' +\
  3368. 'secured Hadoop daemons...'
  3369. principal = get_validated_string_input('Enter ambari server\'s kerberos '
  3370. 'principal name (ambari@EXAMPLE.COM): ', 'ambari@EXAMPLE.COM', '.*', '', False,
  3371. False)
  3372. keytab = get_validated_string_input('Enter keytab path for ambari '
  3373. 'server\'s kerberos principal: ',
  3374. '/etc/security/keytabs/ambari.keytab', '.*', False, False,
  3375. validatorFunction=is_valid_filepath)
  3376. for line in fileinput.FileInput(jaas_conf_file, inplace=1):
  3377. line = re.sub('keyTab=.*$', 'keyTab="' + keytab + '"', line)
  3378. line = re.sub('principal=.*$', 'principal="' + principal + '"', line)
  3379. print line,
  3380. else:
  3381. raise NonFatalException('No jaas config file found at location: ' +
  3382. jaas_conf_file)
  3383. def setup_security(args):
  3384. need_restart = True
  3385. #Print menu options
  3386. print '=' * 75
  3387. print 'Choose one of the following options: '
  3388. print ' [1] Enable HTTPS for Ambari server.'
  3389. print ' [2] Enable HTTPS for Ganglia service.'
  3390. print ' [3] Enable HTTPS for Nagios service.'
  3391. print ' [4] Encrypt passwords stored in ambari.properties file.'
  3392. print ' [5] Setup Ambari kerberos JAAS configuration.'
  3393. print '=' * 75
  3394. choice = get_validated_string_input('Enter choice, (1-5): ', '0', '[1-5]',
  3395. 'Invalid choice', False, False)
  3396. if choice == '1':
  3397. need_restart = setup_https(args)
  3398. elif choice == '2':
  3399. setup_component_https("Ganglia", "setup-ganglia-https", GANGLIA_HTTPS,
  3400. "ganglia_cert")
  3401. elif choice == '3':
  3402. setup_component_https("Nagios", "setup-nagios-https", NAGIOS_HTTPS,
  3403. "nagios_cert")
  3404. elif choice == '4':
  3405. setup_master_key()
  3406. elif choice == '5':
  3407. setup_ambari_krb5_jaas()
  3408. else:
  3409. raise FatalException('Unknown option for setup-security command.')
  3410. return need_restart
  3411. #
  3412. # Main.
  3413. #
  3414. def main():
  3415. parser = optparse.OptionParser(usage="usage: %prog [options] action [stack_id os]",)
  3416. parser.add_option('-f', '--init-script-file',
  3417. default='/var/lib/ambari-server/'
  3418. 'resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql',
  3419. help="File with setup script")
  3420. parser.add_option('-r', '--drop-script-file', default="/var/lib/"
  3421. "ambari-server/resources/"
  3422. "Ambari-DDL-Postgres-EMBEDDED-DROP.sql",
  3423. help="File with drop script")
  3424. parser.add_option('-u', '--upgrade-script-file', default="/var/lib/"
  3425. "ambari-server/resources/upgrade/ddl/"
  3426. "Ambari-DDL-Postgres-UPGRADE-1.3.0.sql",
  3427. help="File with upgrade script")
  3428. parser.add_option('-t', '--upgrade-stack-script-file', default="/var/lib/"
  3429. "ambari-server/resources/upgrade/dml/"
  3430. "Ambari-DML-Postgres-UPGRADE_STACK.sql",
  3431. help="File with stack upgrade script")
  3432. parser.add_option('-j', '--java-home', default=None,
  3433. help="Use specified java_home. Must be valid on all hosts")
  3434. parser.add_option('-i', '--jdk-location', dest="jdk_location", default=None,
  3435. help="Use specified JDK file in local filesystem instead of downloading")
  3436. parser.add_option("-v", "--verbose",
  3437. action="store_true", dest="verbose", default=False,
  3438. help="Print verbose status messages")
  3439. parser.add_option("-s", "--silent",
  3440. action="store_true", dest="silent", default=False,
  3441. help="Silently accepts default prompt values")
  3442. parser.add_option('-g', '--debug', action="store_true", dest='debug', default=False,
  3443. help="Start ambari-server in debug mode")
  3444. parser.add_option('--database', default=None, help="Database to use embedded|oracle|mysql|postgres", dest="dbms")
  3445. parser.add_option('--databasehost', default=None, help="Hostname of database server", dest="database_host")
  3446. parser.add_option('--databaseport', default=None, help="Database port", dest="database_port")
  3447. parser.add_option('--databasename', default=None, help="Database/Schema/Service name or ServiceID",
  3448. dest="database_name")
  3449. parser.add_option('--databaseusername', default=None, help="Database user login", dest="database_username")
  3450. parser.add_option('--databasepassword', default=None, help="Database user password", dest="database_password")
  3451. parser.add_option('--sidorsname', default="sname", help="Oracle database identifier type, Service ID/Service "
  3452. "Name sid|sname", dest="sid_or_sname")
  3453. parser.add_option('--jdbc-driver', default=None, help="Path to jdbc driver. Used only in pair with --jdbc-db ",
  3454. dest="jdbc_driver")
  3455. parser.add_option('--jdbc-db', default=None, help="Database name [postgresql/mysql/oracle]. Used only in pair with " \
  3456. "--jdbc-driver", dest="jdbc_db")
  3457. (options, args) = parser.parse_args()
  3458. # set verbose
  3459. global VERBOSE
  3460. VERBOSE = options.verbose
  3461. # set silent
  3462. global SILENT
  3463. SILENT = options.silent
  3464. # debug mode
  3465. global SERVER_DEBUG_MODE
  3466. SERVER_DEBUG_MODE = options.debug
  3467. global DATABASE_INDEX
  3468. global PROMPT_DATABASE_OPTIONS
  3469. #perform checks
  3470. options.warnings = []
  3471. if options.dbms is None \
  3472. and options.database_host is None \
  3473. and options.database_port is None \
  3474. and options.database_name is None \
  3475. and options.database_username is None \
  3476. and options.database_password is None:
  3477. PROMPT_DATABASE_OPTIONS = True
  3478. elif not (options.dbms is not None
  3479. and options.database_host is not None
  3480. and options.database_port is not None
  3481. and options.database_name is not None
  3482. and options.database_username is not None
  3483. and options.database_password is not None):
  3484. parser.error('All database options should be set. Please see help for the options.')
  3485. #correct database
  3486. if options.dbms == 'embedded':
  3487. print "WARNING: HostName for postgres server " + options.database_host + \
  3488. " will be ignored: using localhost."
  3489. options.database_host = "localhost"
  3490. options.dbms = 'postgres'
  3491. options.persistence_type = 'local'
  3492. options.database_index = 0
  3493. DATABASE_INDEX = 0
  3494. pass
  3495. elif options.dbms is not None and options.dbms not in DATABASE_NAMES:
  3496. parser.print_help()
  3497. parser.error("Unsupported Database " + options.dbms)
  3498. elif options.dbms is not None:
  3499. options.dbms = options.dbms.lower()
  3500. DATABASE_INDEX = DATABASE_NAMES.index(options.dbms)
  3501. #correct port
  3502. if options.database_port is not None:
  3503. correct = False
  3504. try:
  3505. port = int(options.database_port)
  3506. if 65536 > port > 0:
  3507. correct = True
  3508. except ValueError:
  3509. pass
  3510. if not correct:
  3511. parser.print_help()
  3512. parser.error("Incorrect database port " + options.database_port)
  3513. # jdbc driver and db options validation
  3514. if options.jdbc_driver is None and options.jdbc_db is not None:
  3515. parser.error("Option --jdbc-db is used only in pair with --jdbc-driver")
  3516. elif options.jdbc_driver is not None and options.jdbc_db is None:
  3517. parser.error("Option --jdbc-driver is used only in pair with --jdbc-db")
  3518. if options.sid_or_sname.lower() not in ["sid", "sname"]:
  3519. print "WARNING: Valid values for sid_or_sname are 'sid' or 'sname'. Use 'sid' if the db identifier type is " \
  3520. "Service ID. Use 'sname' if the db identifier type is Service Name"
  3521. parser.print_help()
  3522. exit(-1)
  3523. else:
  3524. options.sid_or_sname = options.sid_or_sname.lower()
  3525. if len(args) == 0:
  3526. print parser.print_help()
  3527. parser.error("No action entered")
  3528. action = args[0]
  3529. if action == UPGRADE_STACK_ACTION:
  3530. possible_args_numbers = [2,4] # OR
  3531. else:
  3532. possible_args_numbers = [1]
  3533. matches = 0
  3534. for args_number_required in possible_args_numbers:
  3535. matches += int(len(args) == args_number_required)
  3536. if matches == 0:
  3537. print parser.print_help()
  3538. possible_args = ' or '.join(str(x) for x in possible_args_numbers)
  3539. parser.error("Invalid number of arguments. Entered: " + str(len(args)) + ", required: " + possible_args)
  3540. options.exit_message = "Ambari Server '%s' completed successfully." % action
  3541. need_restart = True
  3542. try:
  3543. if action == SETUP_ACTION:
  3544. setup(options)
  3545. elif action == START_ACTION:
  3546. start(options)
  3547. elif action == STOP_ACTION:
  3548. stop(options)
  3549. elif action == RESET_ACTION:
  3550. reset(options)
  3551. elif action == STATUS_ACTION:
  3552. status(options)
  3553. elif action == UPGRADE_ACTION:
  3554. upgrade(options)
  3555. elif action == UPGRADE_STACK_ACTION:
  3556. stack_id = args[1]
  3557. repo_url = None
  3558. repo_url_os = None
  3559. if len(args) > 2:
  3560. repo_url = args[2]
  3561. if len(args) > 3:
  3562. repo_url_os = args[3]
  3563. upgrade_stack(options, stack_id, repo_url, repo_url_os)
  3564. elif action == LDAP_SETUP_ACTION:
  3565. setup_ldap()
  3566. elif action == SETUP_SECURITY_ACTION:
  3567. need_restart = setup_security(options)
  3568. else:
  3569. parser.error("Invalid action")
  3570. if action in ACTION_REQUIRE_RESTART and need_restart:
  3571. pstatus, pid = is_server_runing()
  3572. if pstatus:
  3573. print 'NOTE: Restart Ambari Server to apply changes' + \
  3574. ' ("ambari-server restart|stop|start")'
  3575. if options.warnings:
  3576. for warning in options.warnings:
  3577. print_warning_msg(warning)
  3578. pass
  3579. options.exit_message = "Ambari Server '%s' completed with warnings." % action
  3580. pass
  3581. except FatalException as e:
  3582. if e.reason is not None:
  3583. print_error_msg("Exiting with exit code {0}. \nREASON: {1}".format(e.code, e.reason))
  3584. sys.exit(e.code)
  3585. except NonFatalException as e:
  3586. options.exit_message = "Ambari Server '%s' completed with warnings." % action
  3587. if e.reason is not None:
  3588. print_warning_msg(e.reason)
  3589. if options.exit_message is not None:
  3590. print options.exit_message
  3591. # A Python replacement for java.util.Properties
  3592. # Based on http://code.activestate.com/recipes
  3593. # /496795-a-python-replacement-for-javautilproperties/
  3594. class Properties(object):
  3595. def __init__(self, props=None):
  3596. self._props = {}
  3597. self._origprops = {}
  3598. self._keymap = {}
  3599. self.othercharre = re.compile(r'(?<!\\)(\s*\=)|(?<!\\)(\s*\:)')
  3600. self.othercharre2 = re.compile(r'(\s*\=)|(\s*\:)')
  3601. self.bspacere = re.compile(r'\\(?!\s$)')
  3602. def __parse(self, lines):
  3603. lineno = 0
  3604. i = iter(lines)
  3605. for line in i:
  3606. lineno += 1
  3607. line = line.strip()
  3608. if not line:
  3609. continue
  3610. if line[0] == '#':
  3611. continue
  3612. escaped = False
  3613. sepidx = -1
  3614. flag = 0
  3615. m = self.othercharre.search(line)
  3616. if m:
  3617. first, last = m.span()
  3618. start, end = 0, first
  3619. flag = 1
  3620. wspacere = re.compile(r'(?<![\\\=\:])(\s)')
  3621. else:
  3622. if self.othercharre2.search(line):
  3623. wspacere = re.compile(r'(?<![\\])(\s)')
  3624. start, end = 0, len(line)
  3625. m2 = wspacere.search(line, start, end)
  3626. if m2:
  3627. first, last = m2.span()
  3628. sepidx = first
  3629. elif m:
  3630. first, last = m.span()
  3631. sepidx = last - 1
  3632. while line[-1] == '\\':
  3633. nextline = i.next()
  3634. nextline = nextline.strip()
  3635. lineno += 1
  3636. line = line[:-1] + nextline
  3637. if sepidx != -1:
  3638. key, value = line[:sepidx], line[sepidx + 1:]
  3639. else:
  3640. key, value = line, ''
  3641. self.process_pair(key, value)
  3642. def process_pair(self, key, value):
  3643. oldkey = key
  3644. oldvalue = value
  3645. keyparts = self.bspacere.split(key)
  3646. strippable = False
  3647. lastpart = keyparts[-1]
  3648. if lastpart.find('\\ ') != -1:
  3649. keyparts[-1] = lastpart.replace('\\', '')
  3650. elif lastpart and lastpart[-1] == ' ':
  3651. strippable = True
  3652. key = ''.join(keyparts)
  3653. if strippable:
  3654. key = key.strip()
  3655. oldkey = oldkey.strip()
  3656. oldvalue = self.unescape(oldvalue)
  3657. value = self.unescape(value)
  3658. self._props[key] = None if value is None else value.strip()
  3659. if self._keymap.has_key(key):
  3660. oldkey = self._keymap.get(key)
  3661. self._origprops[oldkey] = None if oldvalue is None else oldvalue.strip()
  3662. else:
  3663. self._origprops[oldkey] = None if oldvalue is None else oldvalue.strip()
  3664. self._keymap[key] = oldkey
  3665. def unescape(self, value):
  3666. newvalue = value
  3667. if not value is None:
  3668. newvalue = value.replace('\:', ':')
  3669. newvalue = newvalue.replace('\=', '=')
  3670. return newvalue
  3671. def removeOldProp(self, key):
  3672. if self._origprops.has_key(key):
  3673. del self._origprops[key]
  3674. pass
  3675. def load(self, stream):
  3676. if type(stream) is not file:
  3677. raise TypeError, 'Argument should be a file object!'
  3678. if stream.mode != 'r':
  3679. raise ValueError, 'Stream should be opened in read-only mode!'
  3680. try:
  3681. self.fileName = os.path.abspath(stream.name)
  3682. lines = stream.readlines()
  3683. self.__parse(lines)
  3684. except IOError:
  3685. raise
  3686. def get_property(self, key):
  3687. return self._props.get(key, '')
  3688. def propertyNames(self):
  3689. return self._props.keys()
  3690. def getPropertyDict(self):
  3691. return self._props
  3692. def __getitem__(self, name):
  3693. return self.get_property(name)
  3694. def __getattr__(self, name):
  3695. try:
  3696. return self.__dict__[name]
  3697. except KeyError:
  3698. if hasattr(self._props, name):
  3699. return getattr(self._props, name)
  3700. def store(self, out, header=""):
  3701. """ Write the properties list to the stream 'out' along
  3702. with the optional 'header' """
  3703. if out.mode[0] != 'w':
  3704. raise ValueError, 'Steam should be opened in write mode!'
  3705. try:
  3706. out.write(''.join(('#', ASF_LICENSE_HEADER, '\n')))
  3707. out.write(''.join(('#', header, '\n')))
  3708. # Write timestamp
  3709. tstamp = time.strftime('%a %b %d %H:%M:%S %Z %Y', time.localtime())
  3710. out.write(''.join(('#', tstamp, '\n')))
  3711. # Write properties from the pristine dictionary
  3712. for prop, val in self._origprops.items():
  3713. if val is not None:
  3714. out.write(''.join((prop, '=', val, '\n')))
  3715. out.close()
  3716. except IOError:
  3717. raise
  3718. if __name__ == "__main__":
  3719. try:
  3720. main()
  3721. except (KeyboardInterrupt, EOFError):
  3722. print("\nAborting ... Keyboard Interrupt.")
  3723. sys.exit(1)