HMCDBAccessor.php 116 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412
  1. <?php
  2. /*
  3. *
  4. * Licensed to the Apache Software Foundation (ASF) under one
  5. * or more contributor license agreements. See the NOTICE file
  6. * distributed with this work for additional information
  7. * regarding copyright ownership. The ASF licenses this file
  8. * to you under the Apache License, Version 2.0 (the
  9. * "License"); you may not use this file except in compliance
  10. * with the License. You may obtain a copy of the License at
  11. *
  12. * http://www.apache.org/licenses/LICENSE-2.0
  13. *
  14. * Unless required by applicable law or agreed to in writing,
  15. * software distributed under the License is distributed on an
  16. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  17. * KIND, either express or implied. See the License for the
  18. * specific language governing permissions and limitations
  19. * under the License.
  20. *
  21. */
  22. class HMCDBAccessor {
  23. private $dbHandle;
  24. private $dbPath;
  25. private $logger;
  26. function __construct($db) {
  27. $this->dbPath = $db;
  28. $this->logger = new HMCLogger("HMCDBAccessor");
  29. $dsn = "sqlite:".$db;
  30. if (!file_exists($db)) {
  31. $this->logger->log_error("Sqlite db file does not exist, db=$db");
  32. throw new Exception("Could not find sqlite db file, db=$db");
  33. }
  34. $this->dbHandle = new PDO($dsn);
  35. if ($this->dbHandle === FALSE) {
  36. $this->logger->log_error("Could not open sqlite db, db=$db");
  37. throw new Exception("Could not open sqlite db, db=$db");
  38. }
  39. }
  40. private function getLastDBErrorAsString() {
  41. $error = "";
  42. $pdoError = $this->dbHandle->errorInfo();
  43. if (isset($pdoError) && is_array($pdoError)) {
  44. if (isset($pdoError[0])) {
  45. $error = "sqlStateErrorCode=".$pdoError[0];
  46. if (isset($pdoError[1])) {
  47. $error .= ", driverErrCode=".$pdoError[1];
  48. }
  49. if (isset($pdoError[1])) {
  50. $error .= ", driverErrMsg=".$pdoError[2];
  51. }
  52. }
  53. }
  54. else {
  55. $error = "Unknown DB error";
  56. }
  57. return $error;
  58. }
  59. /**
  60. * Create a new cluster
  61. * @param string $clusterName Cluster Name
  62. * @param string $version Version
  63. * @param string $state Current state
  64. * @return mixed
  65. * array (
  66. * "clusterName" => $clusterName,
  67. * "result" => 0,
  68. * "error" => "");
  69. */
  70. public function createCluster($clusterName, $version, $state) {
  71. LockAcquire();
  72. $query = "INSERT INTO Clusters "
  73. . " ( cluster_name, version, state ) "
  74. . " VALUES ( "
  75. . $this->dbHandle->quote($clusterName) . " , "
  76. . $this->dbHandle->quote($version) . " , "
  77. . $this->dbHandle->quote($state) . " )";
  78. $response = array ( "clusterName" => $clusterName,
  79. "result" => 0, "error" => "");
  80. $this->logger->log_trace("Running query: $query");
  81. $ret = $this->dbHandle->exec($query);
  82. if (FALSE === $ret) {
  83. $error = $this->getLastDBErrorAsString();
  84. $this->logger->log_error("Error when executing query"
  85. . ", query=".$query
  86. . ", error=".$error);
  87. $response["result"] = 1;
  88. $response["error"] = $error;
  89. LockRelease(); return $response;
  90. }
  91. LockRelease(); return $response;
  92. }
  93. /**
  94. * Update cluster state for a given clusterName
  95. * @param string $clusterName Cluster Name
  96. * @param string $state New state of cluster
  97. * @return mixed
  98. * array ( "state" => $clusterState,
  99. * "result" => 0,
  100. * "error" => "");
  101. */
  102. public function getClusterState ($clusterName) {
  103. LockAcquire();
  104. $query = "SELECT state FROM Clusters WHERE cluster_name = "
  105. . $this->dbHandle->quote($clusterName);
  106. $response = array ( "result" => 0, "error" => "");
  107. $this->logger->log_trace("Running query: $query");
  108. $pdoStmt = $this->dbHandle->query($query);
  109. if ($pdoStmt === FALSE) {
  110. $error = $this->getLastDBErrorAsString();
  111. $this->logger->log_error("Error when executing query"
  112. . ", query=".$query
  113. . ", error=".$error);
  114. $response["result"] = 1;
  115. $response["error"] = $error;
  116. LockRelease(); return $response;
  117. }
  118. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  119. if (isset($result) && is_array($result) && count($result) == 1) {
  120. $response["state"] = $result[0]["state"];
  121. LockRelease(); return $response;
  122. }
  123. LockRelease(); return $response;
  124. }
  125. /**
  126. * Update cluster state for a given clusterName
  127. * @param string $clusterName Cluster Name
  128. * @param string $state New state of cluster
  129. * @return mixed
  130. * array ( "clusterName" => $clusterName,
  131. * "clusterState" => $clusterState,
  132. * "oldClusterState" => $oldClusterState,
  133. * "result" => 0,
  134. * "error" => "");
  135. */
  136. public function setClusterState($clusterName, $state) {
  137. LockAcquire();
  138. $response = array ( "clusterName" => $clusterName,
  139. "result" => 0, "error" => "");
  140. $ret = $this->dbHandle->beginTransaction();
  141. if (!$ret) {
  142. $error = $this->getLastDBErrorAsString();
  143. $response["result"] = 1;
  144. $response["error"] = "Failed to start DB transaction, error=".$error;
  145. LockRelease(); return $response;
  146. }
  147. $query = "SELECT state FROM Clusters WHERE cluster_name = "
  148. . $this->dbHandle->quote($clusterName);
  149. $this->logger->log_trace("Running query: $query");
  150. $pdoStmt = $this->dbHandle->query($query);
  151. if ($pdoStmt === FALSE) {
  152. $error = $this->getLastDBErrorAsString();
  153. $this->dbHandle->rollBack();
  154. $this->logger->log_error("Error when executing query"
  155. . ", query=".$query
  156. . ", error=".$error);
  157. $response["result"] = 1;
  158. $response["error"] = $error;
  159. LockRelease(); return $response;
  160. }
  161. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  162. if (isset($result) && is_array($result) && count($result) == 1) {
  163. $response["oldClusterState"] = $result[0]["state"];
  164. $query = "UPDATE Clusters SET state = " . $this->dbHandle->quote($state)
  165. . " WHERE cluster_name = " . $this->dbHandle->quote($clusterName);
  166. $this->logger->log_trace("Running query: $query");
  167. $ret = $this->dbHandle->exec($query);
  168. if (FALSE === $ret) {
  169. $error = $this->getLastDBErrorAsString();
  170. $this->dbHandle->rollBack();
  171. $this->logger->log_error("Error when executing query"
  172. . ", query=".$query
  173. . ", error=".$error);
  174. $response["result"] = 1;
  175. $response["error"] = $error;
  176. LockRelease(); return $response;
  177. }
  178. $ret = $this->dbHandle->commit();
  179. if (!$ret) {
  180. $error = $this->getLastDBErrorAsString();
  181. $response["result"] = 1;
  182. $response["error"] = "Failed to commit DB transaction, error=".$error;
  183. LockRelease(); return $response;
  184. }
  185. $response["clusterState"] = $state;
  186. LockRelease();
  187. return $response;
  188. }
  189. $this->dbHandle->rollBack();
  190. $response["result"] = 1;
  191. $response["error"] = "Could not find cluster name".$clusterName." in DB";
  192. LockRelease(); return $response;
  193. }
  194. /**
  195. * Get info on all clusters
  196. * @return mixed
  197. * array (
  198. * "result" => 0,
  199. * "error" => "",
  200. * "clusters" => array (
  201. * "$clusterName" => array (
  202. * "clusterName" => $clusterName,
  203. * "version" => $version,
  204. * "state" => $state
  205. * ),
  206. * ...
  207. * )
  208. * );
  209. */
  210. public function getAllClusters() {
  211. LockAcquire();
  212. $query = "SELECT cluster_name, version, state FROM Clusters";
  213. $response = array ( "result" => 0, "error" => "");
  214. $this->logger->log_trace("Running query: $query");
  215. $pdoStmt = $this->dbHandle->query($query);
  216. if ($pdoStmt === FALSE) {
  217. $error = $this->getLastDBErrorAsString();
  218. $this->logger->log_error("Error when executing query"
  219. . ", query=".$query
  220. . ", error=".$error);
  221. $response["result"] = 1;
  222. $response["error"] = $error;
  223. LockRelease(); return $response;
  224. }
  225. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  226. $response["clusters"] = array();
  227. foreach ($result as $entry) {
  228. $cluster = array();
  229. $cluster["clusterName"] = $entry["cluster_name"];
  230. $cluster["state"] = $entry["state"];
  231. $cluster["version"] = $entry["version"];
  232. $response["clusters"][$cluster["clusterName"]] = $cluster;
  233. }
  234. LockRelease(); return $response;
  235. }
  236. /////////////////////////////////////////// Services related APIs ////////////////////////////////////////////
  237. /**
  238. * Get the list of all possible services supported by the hadoop statck
  239. * @return mixed
  240. * array (
  241. * "result" => 0,
  242. * "error" => "",
  243. * "services" => array (
  244. * "$serviceName" => array (
  245. * "serviceName" => $serviceName,
  246. * "displayName" => $displayName,
  247. * "description" => $desc,
  248. * "attributes" => array( "isMaster" => boolean, "isClient" => boolean )
  249. * ),
  250. * ...
  251. * )
  252. * );
  253. */
  254. public function getAllServicesList() {
  255. LockAcquire();
  256. $response = array ( "result" => 0, "error" => "");
  257. $query = "SELECT service_name, description, display_name, attributes FROM Services";
  258. $this->logger->log_trace("Running query: $query");
  259. $pdoStmt = $this->dbHandle->query($query);
  260. if ($pdoStmt === FALSE) {
  261. $error = $this->getLastDBErrorAsString();
  262. $this->logger->log_error("Error when executing query"
  263. . ", query=".$query
  264. . ", error=".$error);
  265. $response["result"] = 1;
  266. $response["error"] = $error;
  267. LockRelease(); return $response;
  268. }
  269. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  270. $response["services"] = array();
  271. foreach ($result as $entry) {
  272. $svcInfo = array();
  273. $svcInfo["serviceName"] = $entry["service_name"];
  274. $svcInfo["displayName"] = $entry["display_name"];
  275. $svcInfo["description"] = $entry["description"];
  276. $svcInfo["attributes"] = json_decode($entry["attributes"], true);
  277. $response["services"][$svcInfo["serviceName"]] = $svcInfo;
  278. }
  279. LockRelease(); return $response;
  280. }
  281. /**
  282. * Get all components for all services that are supported.
  283. * @return
  284. * array (
  285. * "result" => 0,
  286. * "error" => "",
  287. * "services" => array (
  288. * "$serviceName" => array (
  289. * "serviceName" => $serviceName,
  290. * "components" => array (
  291. * "$componentName" => array (
  292. * "componentName" =>
  293. * "isMaster" =>
  294. * "isClient" =>
  295. * "displayName" =>
  296. * "description" =>
  297. * )
  298. * )
  299. * )
  300. * )
  301. * )
  302. */
  303. public function getAllServiceComponentsList() {
  304. LockAcquire();
  305. $response = array ( "result" => 0, "error" => "");
  306. $query = "SELECT service_name, component_name, display_name"
  307. . ", attributes, description FROM ServiceComponents";
  308. $this->logger->log_trace("Running query: $query");
  309. $pdoStmt = $this->dbHandle->query($query);
  310. if ($pdoStmt === FALSE) {
  311. $error = $this->getLastDBErrorAsString();
  312. $this->logger->log_error("Error when executing query"
  313. . ", query=".$query
  314. . ", error=".$error);
  315. $response["result"] = 1;
  316. $response["error"] = $error;
  317. LockRelease(); return $response;
  318. }
  319. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  320. $response["services"] = array();
  321. foreach ($result as $entry) {
  322. $serviceName = $entry["service_name"];
  323. if (!isset($response["services"]["$serviceName"])) {
  324. $response["services"][$serviceName] = array();
  325. $response["services"][$serviceName]["serviceName"] = $serviceName;
  326. $response["services"][$serviceName]["components"] = array();
  327. }
  328. $comp = array();
  329. $comp["serviceName"] = $serviceName;
  330. $comp["componentName"] = $entry["component_name"];
  331. $comp["displayName"] = $entry["display_name"];
  332. $comp["attributes"] = json_decode($entry["attributes"], true);
  333. /* $comp["isMaster"] and $comp["isClient"] are populated only for
  334. * backward compatibility (with when is_master and is_client were
  335. * fields in this table) and should be removed once all the code
  336. * that uses this method is fixed to look at
  337. * $comp["attributes"]["isMaster"] directly.
  338. */
  339. $comp["isMaster"] = FALSE;
  340. if (isset($comp["attributes"]["isMaster"])) {
  341. $comp["isMaster"] = $comp["attributes"]["isMaster"];
  342. }
  343. $comp["isClient"] = FALSE;
  344. if (isset($comp["attributes"]["isClient"])) {
  345. $comp["isClient"] = $comp["attributes"]["isClient"];
  346. }
  347. $response["services"][$serviceName]["components"]
  348. [$comp["componentName"]] = $comp;
  349. }
  350. LockRelease(); return $response;
  351. }
  352. /**
  353. * Get the list of all services that are available for the given clusterName
  354. * @return mixed
  355. * array (
  356. * "result" => 0,
  357. * "error" => "",
  358. * "clusterName" => $clusterName,
  359. * "services" => array (
  360. * "$serviceName" => array (
  361. * "serviceName" => $serviceName,
  362. * "state" => $state,
  363. * "desiredState" => $desiredState,
  364. * "isEnabled" => $isEnabled
  365. * ),
  366. * ...
  367. * )
  368. * );
  369. */
  370. public function getAllServicesInfo($clusterName) {
  371. LockAcquire();
  372. $query = "SELECT ServiceInfo.service_name as service_name"
  373. . ", ServiceInfo.state as state"
  374. . ", ServiceInfo.desired_state as desired_state"
  375. . ", ServiceInfo.is_enabled as is_enabled FROM ServiceInfo "
  376. . " LEFT JOIN Services ON ServiceInfo.service_name = Services.service_name "
  377. . " WHERE ServiceInfo.cluster_name = " . $this->dbHandle->quote($clusterName)
  378. . " ORDER BY Services.id ";
  379. $response = array ( "result" => 0, "error" => "");
  380. $this->logger->log_trace("Running query: $query");
  381. $pdoStmt = $this->dbHandle->query($query);
  382. if ($pdoStmt === FALSE) {
  383. $error = $this->getLastDBErrorAsString();
  384. $this->logger->log_error("Error when executing query"
  385. . ", query=".$query
  386. . ", error=".$error);
  387. $response["result"] = 1;
  388. $response["error"] = $error;
  389. LockRelease(); return $response;
  390. }
  391. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  392. $response["clusterName"] = $clusterName;
  393. $response["services"] = array();
  394. foreach ($result as $entry) {
  395. $svcInfo = array();
  396. $svcInfo["serviceName"] = $entry["service_name"];
  397. $svcInfo["state"] = $entry["state"];
  398. $svcInfo["desiredState"] = $entry["desired_state"];
  399. $svcInfo["isEnabled"] = $entry["is_enabled"];
  400. $response["services"][$svcInfo["serviceName"]] = $svcInfo;
  401. }
  402. LockRelease(); return $response;
  403. }
  404. /**
  405. * Get information related to a service
  406. * @param string $clusterName
  407. * @param string $serviceName
  408. * @return mixed
  409. * array (
  410. * "result" => 0,
  411. * "error" => "",
  412. * "clusterName" => $clusterName,
  413. * "serviceName" => $serviceName,
  414. * "isEnabled" => $isEnabled,
  415. * "state" => $state,
  416. * "desiredState" => $desiredState
  417. * )
  418. */
  419. public function getServiceInfo($clusterName, $serviceName) {
  420. LockAcquire();
  421. $error = "";
  422. $query = "SELECT is_enabled, state, desired_state FROM ServiceInfo "
  423. . " WHERE cluster_name = " . $this->dbHandle->quote($clusterName)
  424. . " AND service_name = " . $this->dbHandle->quote($serviceName);
  425. $response = array ( "result" => 0, "error" => "");
  426. $response["clusterName"] = $clusterName;
  427. $response["serviceName"] = $serviceName;
  428. $this->logger->log_trace("Running query: $query");
  429. $pdoStmt = $this->dbHandle->query($query);
  430. if ($pdoStmt === FALSE) {
  431. $error = $this->getLastDBErrorAsString();
  432. $this->logger->log_error("Error when executing query"
  433. . ", query=".$query
  434. . ", error=".$error);
  435. $response["result"] = 1;
  436. $response["error"] = $error;
  437. LockRelease(); return $response;
  438. }
  439. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  440. if (isset($result) && is_array($result) && count($result) == 1) {
  441. $response["isEnabled"] = $result[0]["is_enabled"];
  442. $response["state"] = $result[0]["state"];
  443. $response["desiredState"] = $result[0]["desired_state"];
  444. LockRelease(); return $response;
  445. }
  446. $response["result"] = 1;
  447. $response["error"] = "Could not find service in DB";
  448. LockRelease(); return $response;
  449. }
  450. /**
  451. * Set Service Desired State
  452. * @param clusterName Cluster Name
  453. * @param serviceName Service Name
  454. * @param desiredState New Desired State
  455. * @return mixed
  456. * array (
  457. * "result" => 0,
  458. * "error" => "",
  459. * "desiredState" => $desiredState,
  460. * "oldDesiredState" => $oldDesiredState,
  461. * "clusterName" =>
  462. * "serviceName" =>
  463. * )
  464. */
  465. public function setServiceDesiredState($clusterName, $serviceName, $desiredState) {
  466. LockAcquire();
  467. $response = array ( "result" => 0, "error" => "",
  468. "clusterName" => $clusterName, "serviceName" => $serviceName);
  469. $error = "";
  470. $ret = $this->dbHandle->beginTransaction();
  471. if (!$ret) {
  472. $error = $this->getLastDBErrorAsString();
  473. $response["result"] = 1;
  474. $response["error"] = "Failed to start DB transaction, error=".$error;
  475. LockRelease(); return $response;
  476. }
  477. $query = "SELECT desired_state FROM ServiceInfo"
  478. . " WHERE cluster_name = " . $this->dbHandle->quote($clusterName)
  479. . " AND service_name = " . $this->dbHandle->quote($serviceName);
  480. $this->logger->log_trace("Running query: $query");
  481. $pdoStmt = $this->dbHandle->query($query);
  482. if ($pdoStmt === FALSE) {
  483. $error = $this->getLastDBErrorAsString();
  484. $this->dbHandle->rollBack();
  485. $this->logger->log_error("Error when executing query"
  486. . ", query=".$query
  487. . ", error=".$error);
  488. $response["result"] = 1;
  489. $response["error"] = $error;
  490. LockRelease(); return $response;
  491. }
  492. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  493. if (isset($result) && is_array($result) && count($result) == 1) {
  494. $response["oldDesiredState"] = $result[0]["desired_state"];
  495. $query = "UPDATE ServiceInfo SET desired_state = "
  496. . $this->dbHandle->quote($desiredState)
  497. . " WHERE cluster_name = " . $this->dbHandle->quote($clusterName)
  498. . " AND service_name = " . $this->dbHandle->quote($serviceName);
  499. $this->logger->log_trace("Running query: $query");
  500. $ret = $this->dbHandle->exec($query);
  501. if (FALSE === $ret) {
  502. $error = $this->getLastDBErrorAsString();
  503. $this->dbHandle->rollBack();
  504. $this->logger->log_error("Error when executing query"
  505. . ", query=".$query
  506. . ", error=".$error);
  507. $response["result"] = 1;
  508. $response["error"] = $error;
  509. LockRelease(); return $response;
  510. }
  511. $ret = $this->dbHandle->commit();
  512. if (!$ret) {
  513. $error = $this->getLastDBErrorAsString();
  514. $response["result"] = 1;
  515. $response["error"] = "Failed to commit DB transaction, error=".$error;
  516. LockRelease(); return $response;
  517. }
  518. $response["desiredState"] = $desiredState;
  519. LockRelease(); return $response;
  520. }
  521. $this->dbHandle->rollBack();
  522. $response["result"] = 1;
  523. $response["error"] = "Could not find service in DB";
  524. LockRelease(); return $response;
  525. }
  526. /**
  527. * Set Service State
  528. * @param clusterName Cluster Name
  529. * @param serviceName Service Name
  530. * @param desiredState New Desired State
  531. * @return mixed
  532. * array (
  533. * "result" => 0,
  534. * "error" => "",
  535. * "state" => $state,
  536. * "oldState" => $oldState,
  537. * "clusterName" =>
  538. * "serviceName" =>
  539. * )
  540. */
  541. public function setServiceState($clusterName, $serviceName, $state) {
  542. LockAcquire();
  543. $response = array ( "result" => 0, "error" => "",
  544. "clusterName" => $clusterName, "serviceName" => $serviceName);
  545. $error = "";
  546. $ret = $this->dbHandle->beginTransaction();
  547. if (!$ret) {
  548. $error = $this->getLastDBErrorAsString();
  549. $response["result"] = 1;
  550. $response["error"] = "Failed to start DB transaction, error=".$error;
  551. LockRelease(); return $response;
  552. }
  553. $query = "SELECT state FROM ServiceInfo"
  554. . " WHERE cluster_name = " . $this->dbHandle->quote($clusterName)
  555. . " AND service_name = " . $this->dbHandle->quote($serviceName);
  556. $this->logger->log_trace("Running query: $query");
  557. $pdoStmt = $this->dbHandle->query($query);
  558. if ($pdoStmt === FALSE) {
  559. $error = $this->getLastDBErrorAsString();
  560. $this->dbHandle->rollBack();
  561. $this->logger->log_error("Error when executing query"
  562. . ", query=".$query
  563. . ", error=".$error);
  564. $response["result"] = 1;
  565. $response["error"] = $error;
  566. LockRelease(); return $response;
  567. }
  568. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  569. if (isset($result) && is_array($result) && count($result) == 1) {
  570. $response["oldState"] = $result[0]["state"];
  571. $query = "UPDATE ServiceInfo SET state = "
  572. . $this->dbHandle->quote($state)
  573. . " WHERE cluster_name = " . $this->dbHandle->quote($clusterName)
  574. . " AND service_name = " . $this->dbHandle->quote($serviceName);
  575. $this->logger->log_trace("Running query: $query");
  576. $ret = $this->dbHandle->exec($query);
  577. if (FALSE === $ret) {
  578. $error = $this->getLastDBErrorAsString();
  579. $this->dbHandle->rollBack();
  580. $this->logger->log_error("Error when executing query"
  581. . ", query=".$query
  582. . ", error=".$error);
  583. $response["result"] = 1;
  584. $response["error"] = $error;
  585. LockRelease(); return $response;
  586. }
  587. $ret = $this->dbHandle->commit();
  588. if (!$ret) {
  589. $error = $this->getLastDBErrorAsString();
  590. $response["result"] = 1;
  591. $response["error"] = "Failed to commit DB transaction, error=".$error;
  592. LockRelease(); return $response;
  593. }
  594. $response["state"] = $state;
  595. LockRelease(); return $response;
  596. }
  597. $this->dbHandle->rollBack();
  598. $response["result"] = 1;
  599. $response["error"] = "Could not find service in DB";
  600. LockRelease(); return $response;
  601. }
  602. /**
  603. * Add list of services for cluster
  604. * @param string $clusterName
  605. * @param mixed $services
  606. * array (
  607. * array (
  608. * "serviceName" => ,
  609. * "state" =>
  610. * "desiredState" =>
  611. * "isEnabled" =>
  612. * )
  613. * )
  614. * @return mixed
  615. * array (
  616. * "result" => 0,
  617. * "error" => ""
  618. * )
  619. */
  620. public function addServicesToCluster($clusterName, $services) {
  621. $response = array ( "result" => 0, "error" => "",
  622. "clusterName" => $clusterName);
  623. $error = "";
  624. $supportedServices = $this->getAllServicesList();
  625. if ($supportedServices === FALSE
  626. || $supportedServices["result"] != 0) {
  627. return $supportedServices;
  628. }
  629. LockAcquire();
  630. // sanitize input
  631. $sanitizedSvcs = array();
  632. foreach ($services as $service) {
  633. if (!isset($service["serviceName"])
  634. || $service["serviceName"] == "") {
  635. $response["error"] = "Invalid arguments";
  636. $response["result"] = 1;
  637. LockRelease(); return $response;
  638. }
  639. if (!isset($supportedServices["services"][$service["serviceName"]])) {
  640. $response["error"] = "Invalid service - not supported, svc="
  641. . $service["serviceName"];
  642. $response["result"] = 1;
  643. LockRelease(); return $response;
  644. }
  645. if (!isset($service["state"])) {
  646. $service["state"] = "";
  647. }
  648. if (!isset($service["desiredState"])) {
  649. $service["desiredState"] = "";
  650. }
  651. if (!isset($service["isEnabled"])) {
  652. $service["isEnabled"] = 0;
  653. }
  654. else {
  655. if ($service["isEnabled"]) {
  656. $service["isEnabled"] = 1;
  657. }
  658. else {
  659. $service["isEnabled"] = 0;
  660. }
  661. }
  662. $sanitizedSvcs[$service["serviceName"]] = $service;
  663. }
  664. $ret = $this->dbHandle->beginTransaction();
  665. if (!$ret) {
  666. $error = $this->getLastDBErrorAsString();
  667. $response["result"] = 1;
  668. $response["error"] = "Failed to start DB transaction, error=".$error;
  669. LockRelease(); return $response;
  670. }
  671. foreach ($sanitizedSvcs as $service) {
  672. $query = "INSERT INTO ServiceInfo "
  673. . " ( cluster_name, service_name, state, desired_state, is_enabled ) "
  674. . " VALUES "
  675. . " ("
  676. . $this->dbHandle->quote($clusterName) . " , "
  677. . $this->dbHandle->quote($service["serviceName"]) . " , "
  678. . $this->dbHandle->quote($service["state"]) . " , "
  679. . $this->dbHandle->quote($service["desiredState"]) . " , "
  680. . $service["isEnabled"]
  681. . " )";
  682. $this->logger->log_trace("Running query: $query");
  683. $ret = $this->dbHandle->exec($query);
  684. if (FALSE === $ret) {
  685. $error = $this->getLastDBErrorAsString();
  686. $this->dbHandle->rollBack();
  687. $this->logger->log_error("Error when executing query"
  688. . ", query=".$query
  689. . ", error=".$error);
  690. $response["result"] = 1;
  691. $response["error"] = $error;
  692. LockRelease(); return $response;
  693. }
  694. }
  695. $ret = $this->dbHandle->commit();
  696. if (!$ret) {
  697. $error = $this->getLastDBErrorAsString();
  698. $response["result"] = 1;
  699. $response["error"] = "Failed to commit DB transaction, error=".$error;
  700. LockRelease(); return $response;
  701. }
  702. LockRelease(); return $response;
  703. }
  704. /////////////////////////////////////////// End of services related APIs ////////////////////////////////////////////
  705. /////////////////////////////////////////// Hosts related APIs ////////////////////////////////////////////
  706. /**
  707. * Add new hosts to Hosts table for a given cluster.
  708. * Replaces existing hosts if needed
  709. * @param string $clusterName ClusterName
  710. * @param mixed $hostsInfo Mixed array containing host info
  711. * array (
  712. * array (
  713. * "hostName" =>
  714. * "ip" =>
  715. * "totalMem" =>
  716. * "cpuCount" =>
  717. * "osArch" =>
  718. * "osType" =>
  719. * "os" =>
  720. * "disksInfo" =>
  721. * "discoveryStatus" =>
  722. * "badHealthReason" =>
  723. * "attributes" => array ( ... )
  724. * ),
  725. * )
  726. * @return mixed
  727. * array ( "clusterName" => $clusterName,
  728. * "hosts" => array ($hostName1, $hostName2 ...),
  729. * "result" => 0,
  730. * "error" => ""
  731. * );
  732. */
  733. public function addHostsToCluster($clusterName, $hostsInfo) {
  734. LockAcquire();
  735. $response = array( "result" => 0, "error" => "");
  736. if (empty($hostsInfo)) {
  737. LockRelease(); return $response;
  738. }
  739. $hosts = array();
  740. if (empty($hostsInfo)) {
  741. return $response;
  742. }
  743. foreach ($hostsInfo as $hostInfo) {
  744. if (!isset($hostInfo["hostName"])
  745. || $hostInfo["hostName"] == ""
  746. || !isset($hostInfo["discoveryStatus"])) {
  747. $response["result"] = 1;
  748. $response["error"] = "Invalid arguments";
  749. LockRelease(); return $response;
  750. }
  751. // sanitize input
  752. if (!isset($hostInfo["totalMem"])) {
  753. $hostInfo["totalMem"] = 0;
  754. }
  755. if (!isset($hostInfo["cpuCount"])) {
  756. $hostInfo["cpuCount"] = 0;
  757. }
  758. if (!isset($hostInfo["osArch"])) {
  759. $hostInfo["os_arch"] = "";
  760. }
  761. if (!isset($hostInfo["osType"])) {
  762. $hostInfo["osType"] = "";
  763. }
  764. if (!isset($hostInfo["os"])) {
  765. $hostInfo["os"] = "";
  766. }
  767. if (!isset($hostInfo["disksInfo"])) {
  768. $hostInfo["disksInfo"] = "";
  769. }
  770. if (!isset($hostInfo["badHealthReason"])) {
  771. $hostInfo["badHealthReason"] = "";
  772. }
  773. if (!isset($hostInfo["attributes"])) {
  774. $hostInfo["attributes"] = array();
  775. }
  776. $hostInfo["attributes"] = json_encode($hostInfo["attributes"]);
  777. array_push($hosts, $hostInfo);
  778. }
  779. $response["clusterName"] = $clusterName;
  780. $ret = $this->dbHandle->beginTransaction();
  781. if (!$ret) {
  782. $error = $this->getLastDBErrorAsString();
  783. $response["result"] = 1;
  784. $response["error"] = "Failed to start DB transaction, error=".$error;
  785. LockRelease(); return $response;
  786. }
  787. foreach ($hosts as $hostInfo) {
  788. $this->logger->log_debug(json_encode(($hostInfo)));
  789. $query = " INSERT OR REPLACE INTO Hosts "
  790. . " ( cluster_name, host_name, ip, total_mem, cpu_count, "
  791. . " os_arch, os_type, os, disks_info, discovery_status, "
  792. . " bad_health_reason, attributes ) "
  793. . " VALUES "
  794. . " ("
  795. . $this->dbHandle->quote($clusterName) . " , "
  796. . $this->dbHandle->quote($hostInfo["hostName"]) . " , "
  797. . $this->dbHandle->quote($hostInfo["ip"]) . " , "
  798. . $this->dbHandle->quote($hostInfo["totalMem"]) . " , "
  799. . $this->dbHandle->quote($hostInfo["cpuCount"]) . " , "
  800. . $this->dbHandle->quote($hostInfo["osArch"]) . " , "
  801. . $this->dbHandle->quote($hostInfo["osType"]) . " , "
  802. . $this->dbHandle->quote($hostInfo["os"]) . " , "
  803. . $this->dbHandle->quote($hostInfo["disksInfo"]) . " , "
  804. . $this->dbHandle->quote($hostInfo["discoveryStatus"]) . " , "
  805. . $this->dbHandle->quote($hostInfo["badHealthReason"]) . " , "
  806. . $this->dbHandle->quote($hostInfo["attributes"])
  807. . " ) ";
  808. $this->logger->log_trace("Running query: $query");
  809. $ret = $this->dbHandle->exec($query);
  810. if (FALSE === $ret) {
  811. $error = $this->getLastDBErrorAsString();
  812. $this->dbHandle->rollBack();
  813. $this->logger->log_error("Error when executing query"
  814. . ", query=".$query
  815. . ", error=".$error);
  816. $response["result"] = 1;
  817. $response["error"] = $error;
  818. LockRelease(); return $response;
  819. }
  820. }
  821. $ret = $this->dbHandle->commit();
  822. if (!$ret) {
  823. $error = $this->getLastDBErrorAsString();
  824. $this->logger->log_error("Failed to commit DB transaction, error=".$error);
  825. $response["result"] = 1;
  826. $response["error"] = "Failed to commit DB transaction, error=".$error;
  827. LockRelease(); return $response;
  828. }
  829. $error = "";
  830. $query = "SELECT host_name FROM Hosts WHERE "
  831. . " ( cluster_name = " . $this->dbHandle->quote($clusterName) . " ) AND ( ";
  832. $index = 0;
  833. foreach ($hostsInfo as $hostInfo) {
  834. if ($index != 0) {
  835. $query .= " OR ";
  836. }
  837. $index++;
  838. $query .= " host_name = " . $this->dbHandle->quote($hostInfo["hostName"]);
  839. }
  840. $query .= " ) ";
  841. $this->logger->log_trace("Running query: $query");
  842. $pdoStmt = $this->dbHandle->query($query);
  843. if ($pdoStmt === FALSE) {
  844. $error = $this->getLastDBErrorAsString();
  845. $this->logger->log_error("Error when executing query"
  846. . ", query=".$query
  847. . ", error=".$error);
  848. $response["result"] = 1;
  849. $response["error"] = $error;
  850. LockRelease(); return $response;
  851. }
  852. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  853. $response["hosts"] = array();
  854. if (isset($result) && is_array($result) && count($result) > 0) {
  855. foreach ($result as $entry) {
  856. $host["hostName"] = $entry["host_name"];
  857. array_push($response["hosts"], $entry["host_name"]);
  858. }
  859. LockRelease(); return $response;
  860. }
  861. $response["result"] = 1;
  862. $response["error"] = "Invalid result set returned from DB";
  863. LockRelease(); return $response;
  864. }
  865. /**
  866. * Add new hosts to Hosts table for a given cluster.
  867. * Replaces existing hosts if needed
  868. * @param string $clusterName ClusterName
  869. * @param mixed $hostsInfo Mixed array containing host info
  870. * array (
  871. * "$hostName" => array (
  872. * "discoveryStatus" =>
  873. * "badHealthReason" =>
  874. * ),
  875. * )
  876. * @return mixed
  877. * array (
  878. * "result" => 0,
  879. * "error" => "",
  880. * "sql" => array ( "rowsChanged" => 1 )
  881. * )
  882. */
  883. public function updateHostDiscoveryStatus($clusterName, $hostsInfo) {
  884. LockAcquire();
  885. $response = array( "result" => 0, "error" => "");
  886. $hosts = array();
  887. foreach ($hostsInfo as $hostName => $hostInfo) {
  888. if (!isset($hostInfo["discoveryStatus"])) {
  889. $response["result"] = 1;
  890. $response["error"] = "Invalid arguments";
  891. LockRelease(); return $response;
  892. }
  893. if (!isset($hostInfo["badHealthReason"])) {
  894. $hostInfo["badHealthReason"] = "";
  895. }
  896. $hosts[$hostName] = $hostInfo;
  897. }
  898. $ret = $this->dbHandle->beginTransaction();
  899. if (!$ret) {
  900. $error = $this->getLastDBErrorAsString();
  901. $response["result"] = 1;
  902. $response["error"] = "Failed to start DB transaction, error=".$error;
  903. LockRelease(); return $response;
  904. }
  905. $rowsChanged = 0;
  906. foreach ($hosts as $hostName => $hostInfo) {
  907. $this->logger->log_debug(json_encode(($hostInfo)));
  908. $query = " UPDATE Hosts SET "
  909. . " discovery_status = "
  910. . $this->dbHandle->quote($hostInfo["discoveryStatus"])
  911. . ", bad_health_reason = "
  912. . $this->dbHandle->quote($hostInfo["badHealthReason"])
  913. . " WHERE cluster_name = " . $this->dbHandle->quote($clusterName)
  914. . " AND host_name = " . $this->dbHandle->quote($hostName);
  915. $this->logger->log_trace("Running query: $query");
  916. $ret = $this->dbHandle->exec($query);
  917. if (FALSE === $ret) {
  918. $error = $this->getLastDBErrorAsString();
  919. $this->dbHandle->rollBack();
  920. $this->logger->log_error("Error when executing query"
  921. . ", query=".$query
  922. . ", error=".$error);
  923. $response["result"] = 1;
  924. $response["error"] = $error;
  925. LockRelease(); return $response;
  926. }
  927. $rowsChanged += $ret;
  928. }
  929. $ret = $this->dbHandle->commit();
  930. if (!$ret) {
  931. $error = $this->getLastDBErrorAsString();
  932. $this->logger->log_error("Failed to commit DB transaction, error=".$error);
  933. $response["result"] = 1;
  934. $response["error"] = "Failed to commit DB transaction, error=".$error;
  935. LockRelease(); return $response;
  936. }
  937. $response["sql"] = array ( "rowsChanged" => $rowsChanged);
  938. LockRelease(); return $response;
  939. }
  940. /**
  941. * Get information on all hosts
  942. * @param string $clusterName
  943. * @param mixed $filter
  944. * - only supports equal operand
  945. * - only supports discoveryStatus filter
  946. * - array (
  947. * "=" => array ( "discoveryStatus" => "SUCCESS" )
  948. * )
  949. * - format
  950. * "$operand" => array ( "$column1" => "$value1", ... )
  951. * @param mixed $order order by particular column
  952. * - only supports hostName, ip, totalMem, cpuCount, osArch, osType
  953. * array (
  954. * "sortColumn" => "totalMem",
  955. * "sortOrder" => "ASC/DESC"
  956. * )
  957. * - optionally, an array of [ "sortColumn" => $sortColumn, "sortOrder" => $sortOrder]
  958. * can be used
  959. *
  960. * @return mixed
  961. * array (
  962. * "result" => 0,
  963. * "error" => "",
  964. * "clusterName" => $clusterName,
  965. * "hosts" => array (
  966. * array (
  967. * "hostName" =>
  968. * "ip" =>
  969. * "totalMem" =>
  970. * "cpuCount" =>
  971. * "osArch" =>
  972. * "osType" =>
  973. * "os" =>
  974. * "disksInfo" =>
  975. * "discoveryStatus" =>
  976. * "badHealthReason" =>
  977. * "attributes" => array ( ... )
  978. * ),
  979. * ...
  980. * )
  981. * )
  982. */
  983. public function getAllHostsInfo($clusterName, $filter = array(),
  984. $order = array()) {
  985. LockAcquire();
  986. $error = "";
  987. $query = "SELECT "
  988. . " cluster_name, host_name, ip, total_mem, "
  989. . " cpu_count, os_arch, os_type, os, disks_info, "
  990. . " discovery_status, bad_health_reason, attributes "
  991. . " FROM Hosts WHERE host_name != ''";
  992. if ($clusterName != "") {
  993. $query .= " AND cluster_name = "
  994. . $this->dbHandle->quote($clusterName);
  995. }
  996. if (is_array($filter) && !empty($filter)) {
  997. foreach ($filter as $operand => $cols) {
  998. if ($operand == "=" || $operand == "!=") {
  999. foreach ($cols as $columnName => $value) {
  1000. if ($columnName == "discoveryStatus") {
  1001. $query .= " AND discovery_status " . $operand . " "
  1002. . $this->dbHandle->quote($value);
  1003. }
  1004. }
  1005. }
  1006. }
  1007. }
  1008. $using_sort = FALSE;
  1009. if (isset($order) && is_array($order)) {
  1010. if (sizeof($order) > 0) {
  1011. $query .= " ORDER BY ";
  1012. $using_sort = TRUE;
  1013. }
  1014. while (sizeof($order) > 0) {
  1015. // is it an array of arrays, for an array of sortColumn and sortOrder?
  1016. if (isset($order[0]) && is_array($order[0])) {
  1017. $this->logger->log_debug('Order is array of arrays');
  1018. $orderItem = array_shift($order);
  1019. } else {
  1020. $orderItem["sortColumn"] = array_shift($order);
  1021. $orderItem["sortOrder"] = array_shift($order);
  1022. }
  1023. if (isset($orderItem["sortColumn"])) {
  1024. if ($orderItem["sortColumn"] == "hostName") {
  1025. $query .= "host_name";
  1026. }
  1027. else if ($orderItem["sortColumn"] == "ip") {
  1028. $query .= "ip";
  1029. }
  1030. else if ($orderItem["sortColumn"] == "totalMem") {
  1031. $query .= "total_mem";
  1032. }
  1033. else if ($orderItem["sortColumn"] == "cpuCount") {
  1034. $query .= "cpu_count";
  1035. }
  1036. else if ($orderItem["sortColumn"] == "osArch") {
  1037. $query .= "os_arch";
  1038. }
  1039. else if ($orderItem["sortColumn"] == "osType") {
  1040. $query .= "os_type";
  1041. }
  1042. if (isset($orderItem["sortOrder"])) {
  1043. $query .= " ".$orderItem["sortOrder"];
  1044. if (sizeof($order) > 0) {
  1045. $query .= ',';
  1046. }
  1047. }
  1048. }
  1049. }
  1050. }
  1051. $response = array ( "result" => 0, "error" => "");
  1052. $this->logger->log_trace("Running query: $query");
  1053. $pdoStmt = $this->dbHandle->query($query);
  1054. if ($pdoStmt === FALSE) {
  1055. $error = $this->getLastDBErrorAsString();
  1056. $this->logger->log_error("Error when executing query"
  1057. . ", query=".$query
  1058. . ", error=".$error);
  1059. $response["result"] = 1;
  1060. $response["error"] = $error;
  1061. LockRelease(); return $response;
  1062. }
  1063. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  1064. $response["hosts"] = array();
  1065. $response["clusterName"] = $clusterName;
  1066. foreach ($result as $entry) {
  1067. $host = array();
  1068. $host["hostName"] = $entry["host_name"];
  1069. $host["ip"] = $entry["ip"];
  1070. $host["totalMem"] = $entry["total_mem"];
  1071. $host["cpuCount"] = $entry["cpu_count"];
  1072. $host["osArch"] = $entry["os_arch"];
  1073. $host["osType"] = $entry["os_type"];
  1074. $host["os"] = $entry["os"];
  1075. $host["disksInfo"] = $entry["disks_info"];
  1076. $host["discoveryStatus"] = $entry["discovery_status"];
  1077. $host["badHealthReason"] = $entry["bad_health_reason"];
  1078. $host["attributes"] = json_decode($entry["attributes"], true);
  1079. $host["clusterName"] = $entry["cluster_name"];
  1080. array_push($response["hosts"], $host);
  1081. }
  1082. LockRelease(); return $response;
  1083. }
  1084. /**
  1085. * Get information on a specified host
  1086. * @param string $clusterName
  1087. * @param string $hostName
  1088. * @return mixed
  1089. * array (
  1090. * "result" => 0,
  1091. * "error" => "",
  1092. * "clusterName" => $clusterName,
  1093. * "hostName" =>
  1094. * "ip" =>
  1095. * "totalMem" =>
  1096. * "cpuCount" =>
  1097. * "osArch" =>
  1098. * "osType" =>
  1099. * "os" =>
  1100. * "disksInfo" =>
  1101. * "discoveryStatus" =>
  1102. * "badHealthReason" =>
  1103. * "attributes" => array ( ... )
  1104. * )
  1105. */
  1106. public function getHostInfo($clusterName, $hostName) {
  1107. LockAcquire();
  1108. $error = "";
  1109. $query = "SELECT "
  1110. . " host_name, ip, total_mem, "
  1111. . " cpu_count, os_arch, os_type, os, disks_info, "
  1112. . " discovery_status, bad_health_reason, attributes "
  1113. . " FROM Hosts WHERE cluster_name = " . $this->dbHandle->quote($clusterName)
  1114. . " AND host_name = " . $this->dbHandle->quote($hostName);
  1115. $response = array ( "result" => 0, "error" => "");
  1116. $this->logger->log_trace("Running query: $query");
  1117. $pdoStmt = $this->dbHandle->query($query);
  1118. if ($pdoStmt === FALSE) {
  1119. $error = $this->getLastDBErrorAsString();
  1120. $this->logger->log_error("Error when executing query"
  1121. . ", query=".$query
  1122. . ", error=".$error);
  1123. $response["result"] = 1;
  1124. $response["error"] = $error;
  1125. LockRelease(); return $response;
  1126. }
  1127. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  1128. if ($clusterName != "") {
  1129. $response["clusterName"] = $clusterName;
  1130. }
  1131. if (isset($result) && is_array($result) && count($result) == 1) {
  1132. $entry = $result[0];
  1133. $response["clusterName"] = $entry["cluster_name"];
  1134. $response["hostName"] = $entry["host_name"];
  1135. $response["ip"] = $entry["ip"];
  1136. $response["totalMem"] = $entry["total_mem"];
  1137. $response["cpuCount"] = $entry["cpu_count"];
  1138. $response["osArch"] = $entry["os_arch"];
  1139. $response["osType"] = $entry["os_type"];
  1140. $response["os"] = $entry["os"];
  1141. $response["disksInfo"] = $entry["disks_info"];
  1142. $response["discoveryStatus"] = $entry["discovery_status"];
  1143. $response["badHealthReason"] = $entry["bad_health_reason"];
  1144. $response["attributes"] = json_decode($entry["attributes"], true);
  1145. LockRelease(); return $response;
  1146. }
  1147. $response["result"] = 1;
  1148. $response["error"] = "Could not find host in DB";
  1149. LockRelease(); return $response;
  1150. }
  1151. /////////////////////////////////////////// End of hosts related APIs ////////////////////////////////////////////
  1152. /////////////////////////////////////////// Configuration related APIs ////////////////////////////////////////////
  1153. /**
  1154. * Get meta info about all config properties
  1155. * @return mixed
  1156. * array (
  1157. * "result" => 0,
  1158. * "error" => "",
  1159. * "configs" => array(
  1160. * "key" => array (
  1161. * "key" => $key,
  1162. * "displayName" => $displayName,
  1163. * "serviceName" => $serviceName
  1164. * "description" => $description,
  1165. * "displayType" => $displayType,
  1166. * "displayAttributes" => array ( ... )
  1167. * "value" => $default_value
  1168. * )
  1169. * .....
  1170. * );
  1171. */
  1172. public function getConfigPropertiesMetaInfo() {
  1173. LockAcquire();
  1174. $error = "";
  1175. $query = "SELECT "
  1176. . " key, display_name, service_name, description, default_value"
  1177. . ", display_type, display_attributes "
  1178. . " FROM ConfigProperties";
  1179. $response = array ( "result" => 0, "error" => "", "configs" => array());
  1180. $this->logger->log_trace("Running query: $query");
  1181. $pdoStmt = $this->dbHandle->query($query);
  1182. if ($pdoStmt === FALSE) {
  1183. $error = $this->getLastDBErrorAsString();
  1184. $this->logger->log_error("Error when executing query"
  1185. . ", query=".$query
  1186. . ", error=".$error);
  1187. $response["result"] = 1;
  1188. $response["error"] = $error;
  1189. LockRelease(); return $response;
  1190. }
  1191. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  1192. foreach ($result as $entry) {
  1193. $prop = array();
  1194. $prop["key"] = $entry["key"];
  1195. $prop["displayName"] = $entry["display_name"];
  1196. $prop["serviceName"] = $entry["service_name"];
  1197. $prop["description"] = $entry["description"];
  1198. $prop["displayType"] = $entry["display_type"];
  1199. $prop["displayAttributes"] = json_decode($entry["display_attributes"], true);
  1200. $prop["value"] = $entry["default_value"];
  1201. $response["configs"][$prop["key"]] = $prop;
  1202. }
  1203. LockRelease(); return $response;
  1204. }
  1205. /**
  1206. * Get all configuration properties for a given cluster
  1207. * @param string $clusterName
  1208. * @return mixed
  1209. * array (
  1210. * "result" => 0,
  1211. * "error" => "",
  1212. * "clusterName" => $clusterName,
  1213. * "properties" => array (
  1214. * "key1" => "val1",
  1215. * "key2" => "val2",
  1216. * ...
  1217. * )
  1218. * )
  1219. */
  1220. public function getServiceConfig($clusterName) {
  1221. LockAcquire();
  1222. $error = "";
  1223. $query = "SELECT key, value FROM ServiceConfig "
  1224. . " WHERE cluster_name = " . $this->dbHandle->quote($clusterName);
  1225. $response = array ( "result" => 0, "error" => "");
  1226. $this->logger->log_trace("Running query: $query");
  1227. $pdoStmt = $this->dbHandle->query($query);
  1228. if ($pdoStmt === FALSE) {
  1229. $error = $this->getLastDBErrorAsString();
  1230. $this->logger->log_error("Error when executing query"
  1231. . ", query=".$query
  1232. . ", error=".$error);
  1233. $response["result"] = 1;
  1234. $response["error"] = $error;
  1235. LockRelease(); return $response;
  1236. }
  1237. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  1238. $response["properties"] = array();
  1239. $response["clusterName"] = $clusterName;
  1240. foreach ($result as $entry) {
  1241. $response["properties"][$entry["key"]] = $entry["value"];
  1242. }
  1243. LockRelease(); return $response;
  1244. }
  1245. /**
  1246. * Update config properties for a given cluster
  1247. * Updates prop key if it exists or inserts a new entry if not found.
  1248. * @param string $clusterName
  1249. * @param mixed $config
  1250. * array of properties as key-val pairs
  1251. * $config = array ( "prop_key1" => "prop_val1", ... );
  1252. * @return mixed
  1253. * array (
  1254. * "result" => 0,
  1255. * "error" => "",
  1256. * "sql" => array ( "rowsChanged" => 1 )
  1257. * )
  1258. */
  1259. public function updateServiceConfigs($clusterName, $config) {
  1260. LockAcquire();
  1261. $response = array ( "result" => 0, "error" => "");
  1262. if (count($config) == 0) {
  1263. // no-op
  1264. LockRelease(); return $response;
  1265. }
  1266. $error = "";
  1267. $rowsChanged = 0;
  1268. $ret = $this->dbHandle->beginTransaction();
  1269. if (!$ret) {
  1270. $error = $this->getLastDBErrorAsString();
  1271. $response["result"] = 1;
  1272. $response["error"] = "Failed to start DB transaction, error=".$error;
  1273. LockRelease(); return $response;
  1274. }
  1275. foreach ($config as $key=>$val) {
  1276. $query = " INSERT OR REPLACE INTO ServiceConfig "
  1277. . " ( cluster_name, key, value ) "
  1278. . " VALUES "
  1279. . " ( " . $this->dbHandle->quote($clusterName) . ", "
  1280. . $this->dbHandle->quote($key) . ", "
  1281. . $this->dbHandle->quote($val) . " ) ";
  1282. $this->logger->log_trace("Running query: $query");
  1283. $ret = $this->dbHandle->exec($query);
  1284. if (FALSE === $ret) {
  1285. $error = $this->getLastDBErrorAsString();
  1286. $ret = $this->dbHandle->rollBack();
  1287. $this->logger->log_error("Error when executing query"
  1288. . ", query=".$query
  1289. . ", error=".$error);
  1290. $response["result"] = 1;
  1291. $response["error"] = $error;
  1292. LockRelease(); return $response;
  1293. }
  1294. $rowsChanged += $ret;
  1295. }
  1296. $ret = $this->dbHandle->commit();
  1297. if (!$ret) {
  1298. $error = $this->getLastDBErrorAsString();
  1299. $this->logger->log_error("Failed to commit DB transaction, error=".$error);
  1300. $response["result"] = 1;
  1301. $response["error"] = "Failed to commit DB transaction, error=". $error;
  1302. LockRelease(); return $response;
  1303. }
  1304. $response["sql"] = array ( "rowsChanged" => $rowsChanged);
  1305. LockRelease(); return $response;
  1306. }
  1307. /**
  1308. * Update config properties for a given cluster
  1309. * Updates prop key if it exists or inserts a new entry if not found.
  1310. * @param string $clusterName
  1311. * @param mixed $config
  1312. * array of properties as key-val pairs
  1313. * $config =
  1314. * array (
  1315. * "component" => array (
  1316. * "hostname" =>
  1317. * array ( "prop_key1" => "prop_val1", ... )
  1318. * )
  1319. * )
  1320. * @return mixed
  1321. * array (
  1322. * "result" => 0,
  1323. * "error" => "",
  1324. * "sql" => array ( "rowsChanged" => 1 )
  1325. * )
  1326. */
  1327. public function updateHostRoleConfigs($clusterName, $config) {
  1328. LockAcquire();
  1329. $response = array ( "result" => 0, "error" => "");
  1330. if (count($config) == 0) {
  1331. // no-op
  1332. LockRelease(); return $response;
  1333. }
  1334. $error = "";
  1335. $rowsChanged = 0;
  1336. $ret = $this->dbHandle->beginTransaction();
  1337. if (!$ret) {
  1338. $error = $this->getLastDBErrorAsString();
  1339. $response["result"] = 1;
  1340. $response["error"] = "Failed to start DB transaction, error=".$error;
  1341. LockRelease(); return $response;
  1342. }
  1343. foreach ($config as $compName => $hostsInfo) {
  1344. foreach ($hostsInfo as $hostName => $configProps) {
  1345. foreach ($configProps as $key => $val) {
  1346. $query = " INSERT OR REPLACE INTO HostRoleConfig "
  1347. . " ( cluster_name, component_name, host_name"
  1348. . ", key, value ) "
  1349. . " VALUES "
  1350. . " ( " . $this->dbHandle->quote($clusterName) . ", "
  1351. . $this->dbHandle->quote($compName) . ", "
  1352. . $this->dbHandle->quote($hostName) . ", "
  1353. . $this->dbHandle->quote($key) . ", "
  1354. . $this->dbHandle->quote($val) . " ) ";
  1355. $this->logger->log_trace("Running query: $query");
  1356. $ret = $this->dbHandle->exec($query);
  1357. if (FALSE === $ret) {
  1358. $error = $this->getLastDBErrorAsString();
  1359. $ret = $this->dbHandle->rollBack();
  1360. $this->logger->log_error("Error when executing query"
  1361. . ", query=".$query
  1362. . ", error=".$error);
  1363. $response["result"] = 1;
  1364. $response["error"] = $error;
  1365. LockRelease(); return $response;
  1366. }
  1367. $rowsChanged += $ret;
  1368. }
  1369. }
  1370. }
  1371. $ret = $this->dbHandle->commit();
  1372. if (!$ret) {
  1373. $error = $this->getLastDBErrorAsString();
  1374. $this->logger->log_error("Failed to commit DB transaction, error=".$error);
  1375. $response["result"] = 1;
  1376. $response["error"] = "Failed to commit DB transaction, error=". $error;
  1377. LockRelease(); return $response;
  1378. }
  1379. $response["sql"] = array ( "rowsChanged" => $rowsChanged);
  1380. LockRelease(); return $response;
  1381. }
  1382. /**
  1383. * Get host role configs
  1384. * @param string $clusterName
  1385. * @param string $componentName ( optional )
  1386. */
  1387. public function getHostRoleConfigs($clusterName, $componentName = "") {
  1388. LockAcquire();
  1389. $error = "";
  1390. $query = "SELECT component_name, host_name, key, value FROM HostRoleConfig "
  1391. . " WHERE cluster_name = " . $this->dbHandle->quote($clusterName);
  1392. if ($componentName != "") {
  1393. $query .= " AND component_name = "
  1394. . $this->dbHandle->quote($componentName);
  1395. }
  1396. $response = array ( "result" => 0, "error" => "");
  1397. $this->logger->log_trace("Running query: $query");
  1398. $pdoStmt = $this->dbHandle->query($query);
  1399. if ($pdoStmt === FALSE) {
  1400. $error = $this->getLastDBErrorAsString();
  1401. $this->logger->log_error("Error when executing query"
  1402. . ", query=".$query
  1403. . ", error=".$error);
  1404. $response["result"] = 1;
  1405. $response["error"] = $error;
  1406. LockRelease(); return $response;
  1407. }
  1408. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  1409. $response["clusterName"] = $clusterName;
  1410. $response["properties"] = array();
  1411. foreach ($result as $entry) {
  1412. $compName = $entry["component_name"];
  1413. $hostName = $entry["host_name"];
  1414. $key = $entry["key"];
  1415. $val = $entry["value"];
  1416. if (!isset($response["properties"][$compName])) {
  1417. $response["properties"][$compName] = array();
  1418. }
  1419. if (!isset($response["properties"][$compName][$hostName])) {
  1420. $response["properties"][$compName][$hostName] = array();
  1421. }
  1422. $response["properties"][$compName][$hostName][$key] = $val;
  1423. }
  1424. LockRelease(); return $response;
  1425. }
  1426. /////////////////////////////////////////// Configuration related APIs ////////////////////////////////////////////
  1427. /////////////////////////////////////////// Component related APIs ////////////////////////////////////////////
  1428. /**
  1429. * Get all components for a given service.
  1430. * @param string $serviceName
  1431. * @return mixed
  1432. * array (
  1433. * "result" => 0,
  1434. * "error" => "",
  1435. * "serviceName" => $serviceName,
  1436. * "components" => array (
  1437. * "$componentName" => array (
  1438. * "componentName" =>
  1439. * "displayName" =>
  1440. * "isMaster" =>
  1441. * "isClient" =>
  1442. * "description" =>
  1443. * )
  1444. * )
  1445. * )
  1446. */
  1447. public function getAllServiceComponents($serviceName) {
  1448. LockAcquire();
  1449. $response = array ( "result" => 0, "error" => "");
  1450. $query = "SELECT component_name, display_name, attributes, description"
  1451. . " FROM ServiceComponents WHERE service_name = "
  1452. . $this->dbHandle->quote($serviceName);
  1453. $this->logger->log_trace("Running query: $query");
  1454. $pdoStmt = $this->dbHandle->query($query);
  1455. if ($pdoStmt === FALSE) {
  1456. $error = $this->getLastDBErrorAsString();
  1457. $this->logger->log_error("Error when executing query"
  1458. . ", query=".$query
  1459. . ", error=".$error);
  1460. $response["result"] = 1;
  1461. $response["error"] = $error;
  1462. LockRelease(); return $response;
  1463. }
  1464. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  1465. $response["serviceName"] = $serviceName;
  1466. $response["components"] = array();
  1467. foreach ($result as $entry) {
  1468. $comp = array();
  1469. $comp["componentName"] = $entry["component_name"];
  1470. $comp["displayName"] = $entry["display_name"];
  1471. $comp["description"] = $entry["description"];
  1472. $attributes = json_decode($entry["attributes"], true);
  1473. $comp["isMaster"] = FALSE;
  1474. $comp["isClient"] = FALSE;
  1475. if (isset($attributes["isMaster"])) {
  1476. $comp["isMaster"] = $attributes["isMaster"];
  1477. }
  1478. if (isset($attributes["isClient"])) {
  1479. $comp["isClient"] = $attributes["isClient"];
  1480. }
  1481. $response["components"][$comp["componentName"]] = $comp;
  1482. }
  1483. LockRelease(); return $response;
  1484. }
  1485. /**
  1486. * Add host-role mappings for given hostnames to the specified component
  1487. * @param string $clusterName
  1488. * @param string $componentName
  1489. * @param array $hosts Array of hostnames
  1490. * @param string $state
  1491. * @param string $desiredState
  1492. * @return mixed
  1493. * array (
  1494. * "result" => 0,
  1495. * "error" => ""
  1496. * )
  1497. */
  1498. public function addHostsToComponent($clusterName, $componentName,
  1499. $hosts, $state, $desiredState) {
  1500. LockAcquire();
  1501. $response = array ( "result" => 0, "error" => "");
  1502. if ($hosts == NULL || empty($hosts)) {
  1503. LockRelease(); return $response;
  1504. } else {
  1505. $noOp = TRUE;
  1506. foreach ($hosts as $host) {
  1507. if (isset($host)) {
  1508. $h = trim($host);
  1509. if ($h != "") {
  1510. $noOp = FALSE;
  1511. break;
  1512. }
  1513. }
  1514. }
  1515. if ($noOp) {
  1516. $this->logger->log_warn("Invalid hosts array passed in to function"
  1517. . ", hosts=" . implode(",", $hosts));
  1518. LockRelease(); return $response;
  1519. }
  1520. }
  1521. $error = "";
  1522. $ret = $this->dbHandle->beginTransaction();
  1523. if (!$ret) {
  1524. $error = $this->getLastDBErrorAsString();
  1525. $response["result"] = 1;
  1526. $response["error"] = "Failed to start DB transaction, error=".$error;
  1527. LockRelease(); return $response;
  1528. }
  1529. foreach ($hosts as $host) {
  1530. $query = " INSERT OR REPLACE INTO HostRoles "
  1531. . " ( cluster_name, component_name"
  1532. . ", host_name, state, desired_state ) "
  1533. . " VALUES "
  1534. . " ( " . $this->dbHandle->quote($clusterName) . ", "
  1535. . $this->dbHandle->quote($componentName) . ", "
  1536. . $this->dbHandle->quote($host) . ", "
  1537. . $this->dbHandle->quote($state) . ", "
  1538. . $this->dbHandle->quote($desiredState) . " ) ";
  1539. $this->logger->log_trace("Running query: $query");
  1540. $ret = $this->dbHandle->exec($query);
  1541. if (FALSE === $ret) {
  1542. $error = $this->getLastDBErrorAsString();
  1543. $ret = $this->dbHandle->rollBack();
  1544. $this->logger->log_error("Error when executing query"
  1545. . ", query=".$query
  1546. . ", error=".$error);
  1547. $response["result"] = 1;
  1548. $response["error"] = $error;
  1549. LockRelease(); return $response;
  1550. }
  1551. }
  1552. $ret = $this->dbHandle->commit();
  1553. if (!$ret) {
  1554. $error = $this->getLastDBErrorAsString();
  1555. $this->logger->log_error("Failed to commit DB transaction, error=".$error);
  1556. $response["result"] = 1;
  1557. $response["error"] = "Failed to commit DB transaction, error=". $error;
  1558. LockRelease(); return $response;
  1559. }
  1560. LockRelease(); return $response;
  1561. }
  1562. /**
  1563. * Get all hosts mapped to any component
  1564. * @param string $clusterName
  1565. * @return mixed
  1566. * array (
  1567. * "result" => 0,
  1568. * "error" => "",
  1569. * "clusterName" => $clusterName,
  1570. * "components" => array (
  1571. * "$componentName" = array (
  1572. * "componentName" => $componentName,
  1573. * "hosts" => array (
  1574. * "$hostName" => array (
  1575. * "hostName" =>
  1576. * "state" =>
  1577. * "desiredState" =>
  1578. * )
  1579. * )
  1580. * )
  1581. * )
  1582. * )
  1583. */
  1584. public function getAllHostsByComponent($clusterName) {
  1585. LockAcquire();
  1586. $response = array ( "result" => 0, "error" => "");
  1587. $error = "";
  1588. $query = "SELECT role_id, component_name, host_name, state, desired_state"
  1589. . " FROM HostRoles"
  1590. . " WHERE cluster_name = " . $this->dbHandle->quote($clusterName);
  1591. $this->logger->log_trace("Running query: $query");
  1592. $pdoStmt = $this->dbHandle->query($query);
  1593. if ($pdoStmt === FALSE) {
  1594. $error = $this->getLastDBErrorAsString();
  1595. $this->logger->log_error("Error when executing query"
  1596. . ", query=".$query
  1597. . ", error=".$error);
  1598. $response["result"] = 1;
  1599. $response["error"] = $error;
  1600. LockRelease(); return $response;
  1601. }
  1602. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  1603. $response["clusterName"] = $clusterName;
  1604. $response["components"] = array();
  1605. foreach ($result as $entry) {
  1606. $componentName = $entry["component_name"];
  1607. if (!isset($response["components"][$componentName])) {
  1608. $response["components"][$componentName] = array();
  1609. $response["components"][$componentName]["componentName"] =
  1610. $componentName;
  1611. $response["components"][$componentName]["hosts"] = array();
  1612. }
  1613. $hostInfo = array();
  1614. $hostInfo["hostName"] = $entry["host_name"];
  1615. $hostInfo["roleId"] = $entry["role_id"];
  1616. $hostInfo["state"] = $entry["state"];
  1617. $hostInfo["desiredState"] = $entry["desired_state"];
  1618. $response["components"][$componentName]["hosts"]
  1619. [$hostInfo["hostName"]] = $hostInfo;
  1620. }
  1621. LockRelease(); return $response;
  1622. }
  1623. /**
  1624. * Get all hosts mapped to all the components
  1625. * @param string $clusterName
  1626. * @return mixed
  1627. * array (
  1628. * "result" => 0,
  1629. * "error" => "",
  1630. * "clusterName" => $clusterName,
  1631. * "hosts" => array (
  1632. * "hostName" =>
  1633. * "components" = array (
  1634. * "componentName", .....
  1635. * )
  1636. * )
  1637. * )
  1638. */
  1639. public function getAllHostsToComponentMap($clusterName) {
  1640. LockAcquire();
  1641. $response = array ( "result" => 0, "error" => "");
  1642. $error = "";
  1643. $query = "SELECT component_name, host_name, state, desired_state "
  1644. . " FROM HostRoles"
  1645. . " WHERE cluster_name = " . $this->dbHandle->quote($clusterName);
  1646. $this->logger->log_trace("Running query: $query");
  1647. $pdoStmt = $this->dbHandle->query($query);
  1648. if ($pdoStmt === FALSE) {
  1649. $error = $this->getLastDBErrorAsString();
  1650. $this->logger->log_error("Error when executing query"
  1651. . ", query=".$query
  1652. . ", error=".$error);
  1653. $response["result"] = 1;
  1654. $response["error"] = $error;
  1655. LockRelease(); return $response;
  1656. }
  1657. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  1658. $response["clusterName"] = $clusterName;
  1659. $response["hosts"] = array();
  1660. foreach ($result as $entry) {
  1661. $hostName = $entry["host_name"];
  1662. if (!isset($response["hosts"][$hostName])) {
  1663. $response["hosts"][$hostName] = array();
  1664. $initComponents = array();
  1665. array_push($initComponents, $entry["component_name"]);
  1666. $response["hosts"][$hostName]["components"] =
  1667. $initComponents;
  1668. } else {
  1669. $components = $response["hosts"][$hostName]["components"];
  1670. array_push($components, $entry["component_name"]);
  1671. $response["hosts"][$hostName]["components"] = $components;
  1672. }
  1673. }
  1674. LockRelease(); return $response;
  1675. }
  1676. /**
  1677. * Get hosts mapped to a given component
  1678. * @param string $clusterName
  1679. * @param string $componentName
  1680. * @return mixed
  1681. * array (
  1682. * "result" => 0,
  1683. * "error" => "",
  1684. * "clusterName" => $clusterName,
  1685. * "componentName" => $componentName,
  1686. * "hosts" => array (
  1687. * "$hostName" => array (
  1688. * "hostName" =>
  1689. * "state" =>
  1690. * "desiredState" =>
  1691. * )
  1692. * )
  1693. * )
  1694. */
  1695. public function getHostsForComponent($clusterName, $componentName) {
  1696. LockAcquire();
  1697. $response = array ( "result" => 0, "error" => "");
  1698. $error = "";
  1699. $query = "SELECT host_name, state, desired_state FROM HostRoles"
  1700. . " WHERE cluster_name = " . $this->dbHandle->quote($clusterName)
  1701. . " AND component_name = " . $this->dbHandle->quote($componentName);
  1702. $this->logger->log_trace("Running query: $query");
  1703. $pdoStmt = $this->dbHandle->query($query);
  1704. if ($pdoStmt === FALSE) {
  1705. $error = $this->getLastDBErrorAsString();
  1706. $this->logger->log_error("Error when executing query"
  1707. . ", query=".$query
  1708. . ", error=".$error);
  1709. $response["result"] = 1;
  1710. $response["error"] = $error;
  1711. LockRelease(); return $response;
  1712. }
  1713. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  1714. $response["hosts"] = array();
  1715. $response["clusterName"] = $clusterName;
  1716. $response["componentName"] = $componentName;
  1717. foreach ($result as $entry) {
  1718. $hostInfo = array();
  1719. $hostInfo["hostName"] = $entry["host_name"];
  1720. $hostInfo["state"] = $entry["state"];
  1721. $hostInfo["desiredState"] = $entry["desired_state"];
  1722. $response["hosts"][$hostInfo["hostName"]] = $hostInfo;
  1723. }
  1724. LockRelease(); return $response;
  1725. }
  1726. /**
  1727. * Set the state for specified hosts mapped to given component/role
  1728. * @param string $clusterName
  1729. * @param string $componentName
  1730. * @param array $hosts
  1731. * @param string $state
  1732. * @return mixed
  1733. * array (
  1734. * "result" => 0,
  1735. * "error" => ""
  1736. * "sql" => array ( "rowsChanged" => 1 )
  1737. * )
  1738. */
  1739. public function setHostsStateForComponent($clusterName, $componentName,
  1740. $hosts, $state) {
  1741. LockAcquire();
  1742. $response = array ( "result" => 0, "error" => "");
  1743. if (count($hosts) == 0) {
  1744. LockRelease(); return $response;
  1745. }
  1746. $query = " UPDATE HostRoles SET state = " . $this->dbHandle->quote($state)
  1747. . " WHERE cluster_name = " . $this->dbHandle->quote($clusterName)
  1748. . " AND component_name = " . $this->dbHandle->quote($componentName)
  1749. . " AND ( ";
  1750. $index = 0;
  1751. foreach ($hosts as $host) {
  1752. if ($index != 0) {
  1753. $query .= " OR ";
  1754. }
  1755. $index++;
  1756. $query .= " host_name = " . $this->dbHandle->quote($host);
  1757. }
  1758. $query .= " ) ";
  1759. $this->logger->log_trace("Running query: $query");
  1760. $ret = $this->dbHandle->exec($query);
  1761. if (FALSE === $ret) {
  1762. $error = $this->getLastDBErrorAsString();
  1763. $this->logger->log_error("Error when executing query"
  1764. . ", query=".$query
  1765. . ", error=".$error);
  1766. $response["result"] = 1;
  1767. $response["error"] = $error;
  1768. LockRelease(); return $response;
  1769. }
  1770. $rowsChanged = $ret;
  1771. $response["sql"] = array ( "rowsChanged" => $rowsChanged);
  1772. LockRelease(); return $response;
  1773. }
  1774. /**
  1775. * Set the state for specified hosts mapped to given component/role
  1776. * @param string $clusterName
  1777. * @param string $componentName
  1778. * @param array $hosts
  1779. * @param string $desiredState
  1780. * @return mixed
  1781. * array (
  1782. * "result" => 0,
  1783. * "error" => ""
  1784. * "sql" => array ( "rowsChanged" => 1 )
  1785. * )
  1786. */
  1787. public function setHostsDesiredStateForComponent($clusterName, $componentName,
  1788. $hosts, $desiredState) {
  1789. LockAcquire();
  1790. $response = array ( "result" => 0, "error" => "");
  1791. if (count($hosts) == 0) {
  1792. LockRelease(); return $response;
  1793. }
  1794. $query = " UPDATE HostRoles SET desired_state = " . $this->dbHandle->quote($desiredState)
  1795. . " WHERE cluster_name = " . $this->dbHandle->quote($clusterName)
  1796. . " AND component_name = " . $this->dbHandle->quote($componentName)
  1797. . " AND ( ";
  1798. $index = 0;
  1799. foreach ($hosts as $host) {
  1800. if ($index != 0) {
  1801. $query .= " OR ";
  1802. }
  1803. $index++;
  1804. $query .= " host_name = " . $this->dbHandle->quote($host);
  1805. }
  1806. $query .= " ) ";
  1807. $this->logger->log_trace("Running query: $query");
  1808. $ret = $this->dbHandle->exec($query);
  1809. if (FALSE === $ret) {
  1810. $error = $this->getLastDBErrorAsString();
  1811. $this->logger->log_error("Error when executing query"
  1812. . ", query=".$query
  1813. . ", error=".$error);
  1814. $response["result"] = 1;
  1815. $response["error"] = $error;
  1816. LockRelease(); return $response;
  1817. }
  1818. $rowsChanged = $ret;
  1819. $response["sql"] = array ( "rowsChanged" => $rowsChanged);
  1820. LockRelease(); return $response;
  1821. }
  1822. /**
  1823. * Get services that the given service depends upon
  1824. * @param string $serviceName
  1825. * @return mixed
  1826. * array (
  1827. * "result" => 0,
  1828. * "error" => "",
  1829. * "serviceName" =>
  1830. * "serviceDependencies" = array ( "svc1", "svc2", ... )
  1831. * )
  1832. */
  1833. public function getServiceDependencies($serviceName) {
  1834. LockAcquire();
  1835. $response = array ( "result" => 0, "error" => "");
  1836. $query = "SELECT to_service_name FROM ServiceDependencies WHERE "
  1837. . " from_service_name = " . $this->dbHandle->quote($serviceName);
  1838. $this->logger->log_trace("Running query: $query");
  1839. $pdoStmt = $this->dbHandle->query($query);
  1840. if ($pdoStmt === FALSE) {
  1841. $error = $this->getLastDBErrorAsString();
  1842. $this->logger->log_error("Error when executing query"
  1843. . ", query=".$query
  1844. . ", error=".$error);
  1845. $response["result"] = 1;
  1846. $response["error"] = $error;
  1847. LockRelease(); return $response;
  1848. }
  1849. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  1850. $response["serviceName"] = $serviceName;
  1851. $response["serviceDependencies"] = array();
  1852. foreach ($result as $entry) {
  1853. array_push($response["serviceDependencies"], $entry["to_service_name"]);
  1854. }
  1855. LockRelease(); return $response;
  1856. }
  1857. /**
  1858. * Get services which depend on the given service.
  1859. * @param string $serviceName
  1860. * @return mixed
  1861. * array (
  1862. * "result" => 0,
  1863. * "error" => "",
  1864. * "serviceName" =>
  1865. * "serviceDependents" = array ( "svc1", "svc2", ... )
  1866. * )
  1867. */
  1868. public function getServiceDependents($serviceName) {
  1869. LockAcquire();
  1870. $response = array ( "result" => 0, "error" => "");
  1871. $query = "SELECT from_service_name FROM ServiceDependencies WHERE "
  1872. . " to_service_name = " . $this->dbHandle->quote($serviceName);
  1873. $this->logger->log_trace("Running query: $query");
  1874. $pdoStmt = $this->dbHandle->query($query);
  1875. if ($pdoStmt === FALSE) {
  1876. $error = $this->getLastDBErrorAsString();
  1877. $this->logger->log_error("Error when executing query"
  1878. . ", query=".$query
  1879. . ", error=".$error);
  1880. $response["result"] = 1;
  1881. $response["error"] = $error;
  1882. LockRelease(); return $response;
  1883. }
  1884. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  1885. $response["serviceName"] = $serviceName;
  1886. $response["serviceDependents"] = array();
  1887. foreach ($result as $entry) {
  1888. array_push($response["serviceDependents"], $entry["from_service_name"]);
  1889. }
  1890. LockRelease(); return $response;
  1891. }
  1892. /**
  1893. * Get components that the given component depends upon
  1894. * @param string $componentName
  1895. * @return mixed
  1896. * array (
  1897. * "result" => 0,
  1898. * "error" => "",
  1899. * "componentName" =>
  1900. * "componentDependencies" = array ( "comp1", "comp2", ... )
  1901. * )
  1902. */
  1903. public function getServiceComponentDependencies($componentName) {
  1904. LockAcquire();
  1905. $response = array ( "result" => 0, "error" => "");
  1906. $query = "SELECT to_component_name "
  1907. . " FROM ServiceComponentDependencies WHERE "
  1908. . " from_component_name = "
  1909. . $this->dbHandle->quote($componentName);
  1910. $this->logger->log_trace("Running query: $query");
  1911. $pdoStmt = $this->dbHandle->query($query);
  1912. if ($pdoStmt === FALSE) {
  1913. $error = $this->getLastDBErrorAsString();
  1914. $this->logger->log_error("Error when executing query"
  1915. . ", query=".$query
  1916. . ", error=".$error);
  1917. $response["result"] = 1;
  1918. $response["error"] = $error;
  1919. LockRelease(); return $response;
  1920. }
  1921. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  1922. $response["componentName"] = $componentName;
  1923. $response["componentDependencies"] = array();
  1924. foreach ($result as $entry) {
  1925. array_push($response["componentDependencies"],
  1926. $entry["to_component_name"]);
  1927. }
  1928. LockRelease(); return $response;
  1929. }
  1930. /**
  1931. * Get components that the given component depends upon
  1932. * @param string $componentName
  1933. * @return mixed
  1934. * array (
  1935. * "result" => 0,
  1936. * "error" => "",
  1937. * "serviceName" =>
  1938. * "componentName" =>
  1939. * "componentDependents" = array ( "comp1", "comp2", ... )
  1940. * )
  1941. */
  1942. public function getServiceComponentDependents($componentName) {
  1943. LockAcquire();
  1944. $response = array ( "result" => 0, "error" => "");
  1945. $query = "SELECT from_component_name "
  1946. . " FROM ServiceComponentDependencies WHERE "
  1947. . " to_component_name = "
  1948. . $this->dbHandle->quote($componentName);
  1949. $this->logger->log_trace("Running query: $query");
  1950. $pdoStmt = $this->dbHandle->query($query);
  1951. if ($pdoStmt === FALSE) {
  1952. $error = $this->getLastDBErrorAsString();
  1953. $this->logger->log_error("Error when executing query"
  1954. . ", query=".$query
  1955. . ", error=".$error);
  1956. $response["result"] = 1;
  1957. $response["error"] = $error;
  1958. LockRelease(); return $response;
  1959. }
  1960. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  1961. $response["componentName"] = $componentName;
  1962. $response["componentDependents"] = array();
  1963. foreach ($result as $entry) {
  1964. array_push($response["componentDependents"],
  1965. $entry["from_component_name"]);
  1966. }
  1967. LockRelease(); return $response;
  1968. }
  1969. /**
  1970. * Add Service Components to a given cluster
  1971. * @param string $clusterName
  1972. * @param mixed $components
  1973. * array (
  1974. * "$serviceName" => array (
  1975. * "$componentName" =>
  1976. * "state" =>
  1977. * "desiredState" =>
  1978. * )
  1979. * )
  1980. * )
  1981. */
  1982. public function addServiceComponentsToCluster($clusterName, $components) {
  1983. LockAcquire();
  1984. $response = array ( "result" => 0, "error" => "",
  1985. "clusterName" => $clusterName);
  1986. $error = "";
  1987. $supportedComps = $this->getAllServiceComponentsList();
  1988. if ($supportedComps === FALSE
  1989. || $supportedComps["result"] != 0) {
  1990. LockRelease(); return $supportedComps;
  1991. }
  1992. // sanitize input
  1993. $sanitizedComps = array();
  1994. foreach ($components as $svc=>$comps) {
  1995. if (!isset($comps)
  1996. || !is_array($comps)
  1997. || count($comps) == 0) {
  1998. $this->logger->log_warn("Invalid args to addServiceComponentsToCluster"
  1999. . ", svc=" . $svc
  2000. . ", comps either null or empty");
  2001. continue;
  2002. }
  2003. if (!isset($supportedComps["services"][$svc])
  2004. || !is_array($supportedComps["services"][$svc])
  2005. || !isset($supportedComps["services"][$svc]["components"])
  2006. || !is_array($supportedComps["services"][$svc]["components"])) {
  2007. $response["error"] = "Invalid service - not supported, svc="
  2008. . $svc;
  2009. $response["result"] = 1;
  2010. LockRelease(); return $response;
  2011. }
  2012. foreach ($comps as $compName=>$comp) {
  2013. if (!isset($supportedComps["services"][$svc]["components"][$compName])
  2014. || !is_array($supportedComps["services"]
  2015. [$svc]["components"][$compName])) {
  2016. $response["error"] = "Invalid component - not supported, svc="
  2017. . $svc . ", component=" . $compName;
  2018. $response["result"] = 1;
  2019. LockRelease(); return $response;
  2020. }
  2021. $saneComp = array(); // yes - it really is sane as in not insane
  2022. $saneComp["serviceName"] = $svc;
  2023. $saneComp["componentName"] = $compName;
  2024. $saneComp["state"] = "";
  2025. $saneComp["desiredState"] = "";
  2026. if (isset($comp["state"])) {
  2027. $saneComp["state"] = $comp["state"];
  2028. }
  2029. if (isset($comp["desiredState"])) {
  2030. $saneComp["desiredState"] = $comp["desiredState"];
  2031. }
  2032. array_push($sanitizedComps, $saneComp);
  2033. }
  2034. }
  2035. $ret = $this->dbHandle->beginTransaction();
  2036. if (!$ret) {
  2037. $error = $this->getLastDBErrorAsString();
  2038. $response["result"] = 1;
  2039. $response["error"] = "Failed to start DB transaction, error=".$error;
  2040. LockRelease(); return $response;
  2041. }
  2042. foreach ($sanitizedComps as $comp) {
  2043. $query = "INSERT INTO ServiceComponentInfo "
  2044. . " ( cluster_name, service_name, component_name"
  2045. . ", state, desired_state ) "
  2046. . " VALUES "
  2047. . " ("
  2048. . $this->dbHandle->quote($clusterName) . " , "
  2049. . $this->dbHandle->quote($comp["serviceName"]) . " , "
  2050. . $this->dbHandle->quote($comp["componentName"]) . " , "
  2051. . $this->dbHandle->quote($comp["state"]) . " , "
  2052. . $this->dbHandle->quote($comp["desiredState"])
  2053. . " )";
  2054. $this->logger->log_trace("Running query: $query");
  2055. $ret = $this->dbHandle->exec($query);
  2056. if (FALSE === $ret) {
  2057. $error = $this->getLastDBErrorAsString();
  2058. $this->dbHandle->rollBack();
  2059. $this->logger->log_error("Error when executing query"
  2060. . ", query=".$query
  2061. . ", error=".$error);
  2062. $response["result"] = 1;
  2063. $response["error"] = $error;
  2064. LockRelease(); return $response;
  2065. }
  2066. }
  2067. $ret = $this->dbHandle->commit();
  2068. if (!$ret) {
  2069. $error = $this->getLastDBErrorAsString();
  2070. $response["result"] = 1;
  2071. $response["error"] = "Failed to commit DB transaction, error=".$error;
  2072. LockRelease(); return $response;
  2073. }
  2074. LockRelease(); return $response;
  2075. }
  2076. /**
  2077. * Get all components for all services within the cluster
  2078. * @param string $clusterName
  2079. * @return mixed
  2080. * array (
  2081. * "result" => 0,
  2082. * "error" => "",
  2083. * "services" => array (
  2084. * "$serviceName" => array (
  2085. * "serviceName" => $serviceName,
  2086. * "components" => array (
  2087. * "$componentName" => array (
  2088. * "componentName" =>
  2089. * "state" =>
  2090. * "desiredState" =>
  2091. * )
  2092. * )
  2093. * )
  2094. * )
  2095. */
  2096. public function getAllServiceComponentsInfo($clusterName) {
  2097. LockAcquire();
  2098. $response = array ( "result" => 0, "error" => "");
  2099. $query = "SELECT service_name, component_name, state, desired_state "
  2100. . " FROM ServiceComponentInfo WHERE "
  2101. . " cluster_name = " . $this->dbHandle->quote($clusterName);
  2102. $this->logger->log_trace("Running query: $query");
  2103. $pdoStmt = $this->dbHandle->query($query);
  2104. if ($pdoStmt === FALSE) {
  2105. $error = $this->getLastDBErrorAsString();
  2106. $this->logger->log_error("Error when executing query"
  2107. . ", query=".$query
  2108. . ", error=".$error);
  2109. $response["result"] = 1;
  2110. $response["error"] = $error;
  2111. LockRelease(); return $response;
  2112. }
  2113. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  2114. $response["services"] = array();
  2115. foreach ($result as $entry) {
  2116. $serviceName = $entry["service_name"];
  2117. if (!isset($response["services"]["$serviceName"])) {
  2118. $response["services"][$serviceName] = array();
  2119. $response["services"][$serviceName]["serviceName"] = $serviceName;
  2120. $response["services"][$serviceName]["components"] = array();
  2121. }
  2122. $comp = array();
  2123. $comp["serviceName"] = $serviceName;
  2124. $comp["componentName"] = $entry["component_name"];
  2125. $comp["state"] = $entry["state"];
  2126. $comp["desiredState"] = $entry["desired_state"];
  2127. $response["services"][$serviceName]["components"]
  2128. [$comp["componentName"]] = $comp;
  2129. }
  2130. LockRelease(); return $response;
  2131. }
  2132. /*
  2133. public function getServiceComponentInfo($clusterName, $componentName) {
  2134. LockAcquire();
  2135. // TODO
  2136. // use getAllServiceComponentsInfo for now
  2137. }
  2138. */
  2139. private function genericSetServiceComponentState($clusterName, $componentName,
  2140. $state, $updateAllMappedHosts, $updateDesired) {
  2141. LockAcquire();
  2142. $columnName = "state";
  2143. if ($updateDesired) {
  2144. $columnName = "desired_state";
  2145. }
  2146. $response = array ( "result" => 0, "error" => "");
  2147. $ret = $this->dbHandle->beginTransaction();
  2148. if (!$ret) {
  2149. $error = $this->getLastDBErrorAsString();
  2150. $response["result"] = 1;
  2151. $response["error"] = "Failed to start DB transaction, error=".$error;
  2152. LockRelease(); return $response;
  2153. }
  2154. $query = "UPDATE ServiceComponentInfo SET " . $columnName . " = "
  2155. . $this->dbHandle->quote($state)
  2156. . " WHERE cluster_name = " . $this->dbHandle->quote($clusterName)
  2157. . " AND component_name = " . $this->dbHandle->quote($componentName);
  2158. $this->logger->log_trace("Running query: $query");
  2159. $ret = $this->dbHandle->exec($query);
  2160. if (FALSE === $ret) {
  2161. $error = $this->getLastDBErrorAsString();
  2162. $this->dbHandle->rollBack();
  2163. $this->logger->log_error("Error when executing query"
  2164. . ", query=".$query
  2165. . ", error=".$error);
  2166. $response["result"] = 1;
  2167. $response["error"] = $error;
  2168. LockRelease(); return $response;
  2169. }
  2170. if ($updateAllMappedHosts) {
  2171. $query = "UPDATE HostRoles SET " . $columnName . " = "
  2172. . $this->dbHandle->quote($state)
  2173. . " WHERE cluster_name = " . $this->dbHandle->quote($clusterName)
  2174. . " AND component_name = " . $this->dbHandle->quote($componentName);
  2175. $this->logger->log_trace("Running query: $query");
  2176. $ret = $this->dbHandle->exec($query);
  2177. if (FALSE === $ret) {
  2178. $error = $this->getLastDBErrorAsString();
  2179. $this->dbHandle->rollBack();
  2180. $this->logger->log_error("Error when executing query"
  2181. . ", query=".$query
  2182. . ", error=".$error);
  2183. $response["result"] = 1;
  2184. $response["error"] = $error;
  2185. LockRelease(); return $response;
  2186. }
  2187. }
  2188. $ret = $this->dbHandle->commit();
  2189. if (!$ret) {
  2190. $error = $this->getLastDBErrorAsString();
  2191. $response["result"] = 1;
  2192. $response["error"] = "Failed to commit DB transaction, error=".$error;
  2193. LockRelease(); return $response;
  2194. }
  2195. LockRelease(); return $response;
  2196. }
  2197. /**
  2198. * Update the state for a specified component. Based on update hosts flag,
  2199. * set the state for all the hosts mapped to that component too.
  2200. * @param string $clusterName
  2201. * @param string $componentName
  2202. * @param string $state
  2203. * @param bool $updateAllMappedHosts
  2204. * @return mixed
  2205. * array (
  2206. * "result" => 0,
  2207. * "error" => ""
  2208. * )
  2209. */
  2210. public function setServiceComponentState($clusterName, $componentName,
  2211. $state, $updateAllMappedHosts) {
  2212. return $this->genericSetServiceComponentState($clusterName, $componentName,
  2213. $state, $updateAllMappedHosts, FALSE);
  2214. }
  2215. /**
  2216. * Update the desired state for a specified component. Based on update hosts
  2217. * flag, set the desired state for all the hosts mapped to that component too.
  2218. * @param string $clusterName
  2219. * @param string $componentName
  2220. * @param string $desiredState
  2221. * @param bool $updateAllMappedHosts
  2222. * @return mixed
  2223. * array (
  2224. * "result" => 0,
  2225. * "error" => ""
  2226. * )
  2227. */
  2228. public function setServiceComponentDesiredState($clusterName, $componentName,
  2229. $desiredState, $updateAllMappedHosts) {
  2230. return $this->genericSetServiceComponentState($clusterName, $componentName,
  2231. $desiredState, $updateAllMappedHosts, TRUE);
  2232. }
  2233. // TODO add apis for config history
  2234. // TODO add apis for txn status table
  2235. /**
  2236. * Create a new transaction
  2237. * @param string $statusInfo Status blob to attach to txn in DB
  2238. * @param string $pidInfo Pid Info to attach to txn
  2239. * @return mixed
  2240. * array (
  2241. * "result" => 0,
  2242. * "error" => "",
  2243. * "txnId" => $txn_id
  2244. * )
  2245. */
  2246. public function createNewTransaction($clusterName, $statusInfo, $pidInfo) {
  2247. LockAcquire();
  2248. $response = array ( "result" => 0, "error" => "");
  2249. $ret = $this->dbHandle->beginTransaction();
  2250. if (!$ret) {
  2251. $error = $this->getLastDBErrorAsString();
  2252. $response["result"] = 1;
  2253. $response["error"] = "Failed to start DB transaction, error=".$error;
  2254. LockRelease(); return $response;
  2255. }
  2256. $query = "INSERT INTO TransactionStatus ( cluster_name, create_time"
  2257. . ", status_info, pid_info ) VALUES ( "
  2258. . $this->dbHandle->quote($clusterName) . " , "
  2259. . $this->dbHandle->quote(time()) . " , "
  2260. . $this->dbHandle->quote($statusInfo) . " , "
  2261. . $this->dbHandle->quote($pidInfo) . " ) ";
  2262. $this->logger->log_trace("Running query: $query");
  2263. $ret = $this->dbHandle->exec($query);
  2264. if (FALSE === $ret) {
  2265. $error = $this->getLastDBErrorAsString();
  2266. $this->dbHandle->rollBack();
  2267. $this->logger->log_error("Error when executing query"
  2268. . ", query=".$query
  2269. . ", error=".$error);
  2270. $response["result"] = 1;
  2271. $response["error"] = $error;
  2272. LockRelease(); return $response;
  2273. }
  2274. $lastInsertId = intval($this->dbHandle->lastInsertId());
  2275. if ($lastInsertId == 0) {
  2276. $this->dbHandle->rollBack();
  2277. $error = "Obtained invalid last insert id from DB";
  2278. $this->logger->log_error($error);
  2279. $response["result"] = 1;
  2280. $response["error"] = $error;
  2281. LockRelease(); return $response;
  2282. }
  2283. $ret = $this->dbHandle->commit();
  2284. if (!$ret) {
  2285. $error = $this->getLastDBErrorAsString();
  2286. $response["result"] = 1;
  2287. $response["error"] = "Failed to commit DB transaction, error=".$error;
  2288. LockRelease(); return $response;
  2289. }
  2290. $response["txnId"] = $lastInsertId;
  2291. LockRelease(); return $response;
  2292. }
  2293. /**
  2294. * Get transaction Info
  2295. * @param string $clusterName
  2296. * @param int $txnId
  2297. * @return mixed
  2298. * array (
  2299. * "result" => 0,
  2300. * "error" => "",
  2301. * "clusterName" => $clusterName,
  2302. * "txnId" => $txn_id,
  2303. * "statusInfo" => $statusInfo,
  2304. * "pidInfo" => $pidInfo,
  2305. * "createTime" => $createTime
  2306. * )
  2307. */
  2308. public function getTransactionStatusInfo($clusterName, $txnId) {
  2309. LockAcquire();
  2310. $response = array ( "result" => 0, "error" => "");
  2311. $query = "SELECT create_time, status_info, pid_info "
  2312. . " FROM TransactionStatus WHERE "
  2313. . " cluster_name = " . $this->dbHandle->quote($clusterName)
  2314. . " AND txn_id = " . $this->dbHandle->quote($txnId);
  2315. $response = array ( "result" => 0, "error" => "");
  2316. $this->logger->log_trace("Running query: $query");
  2317. $pdoStmt = $this->dbHandle->query($query);
  2318. if ($pdoStmt === FALSE) {
  2319. $error = $this->getLastDBErrorAsString();
  2320. $this->logger->log_error("Error when executing query"
  2321. . ", query=".$query
  2322. . ", error=".$error);
  2323. $response["result"] = 1;
  2324. $response["error"] = $error;
  2325. LockRelease(); return $response;
  2326. }
  2327. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  2328. $response["clusterName"] = $clusterName;
  2329. $response["txnId"] = $txnId;
  2330. if (isset($result) && is_array($result) && count($result) == 1) {
  2331. $entry = $result[0];
  2332. $response["createTime"] = $entry["create_time"];
  2333. $response["statusInfo"] = $entry["status_info"];
  2334. $response["pidInfo"] = $entry["pid_info"];
  2335. LockRelease(); return $response;
  2336. }
  2337. $response["result"] = 1;
  2338. $response["error"] = "Could not find txn in DB";
  2339. LockRelease(); return $response;
  2340. }
  2341. /**
  2342. * Update pid info for a given transaction
  2343. * @param string $clusterName
  2344. * @param string $txnId
  2345. * @param string $pidInfo
  2346. * @return mixed
  2347. * array (
  2348. * "result" => 0,
  2349. * "error" => ""
  2350. * )
  2351. */
  2352. public function updateTransactionPidInfo($clusterName, $txnId, $pidInfo) {
  2353. LockAcquire();
  2354. $response = array ( "result" => 0, "error" => "");
  2355. $query = "UPDATE TransactionStatus SET pid_info = "
  2356. . $this->dbHandle->quote($pidInfo)
  2357. . " WHERE cluster_name = " . $this->dbHandle->quote($clusterName)
  2358. . " AND txn_id = " . $this->dbHandle->quote($txnId);
  2359. $this->logger->log_trace("Running query: $query");
  2360. $ret = $this->dbHandle->exec($query);
  2361. if (FALSE === $ret) {
  2362. $error = $this->getLastDBErrorAsString();
  2363. $this->logger->log_error("Error when executing query"
  2364. . ", query=".$query
  2365. . ", error=".$error);
  2366. $response["result"] = 1;
  2367. $response["error"] = $error;
  2368. LockRelease(); return $response;
  2369. }
  2370. $rowsChanged = intval($ret);
  2371. $response["sql"] = array ( "rowsChanged" => $rowsChanged);
  2372. LockRelease(); return $response;
  2373. }
  2374. /**
  2375. * Update status info for a given transaction
  2376. * @param string $clusterName
  2377. * @param string $txnId
  2378. * @param string $statusInfo
  2379. * @return mixed
  2380. * array (
  2381. * "result" => 0,
  2382. * "error" => ""
  2383. * )
  2384. */
  2385. public function updateTransactionStatusInfo($clusterName, $txnId, $statusInfo) {
  2386. LockAcquire();
  2387. $response = array ( "result" => 0, "error" => "");
  2388. $query = "UPDATE TransactionStatus SET status_info = "
  2389. . $this->dbHandle->quote($statusInfo)
  2390. . " WHERE cluster_name = " . $this->dbHandle->quote($clusterName)
  2391. . " AND txn_id = " . $this->dbHandle->quote($txnId);
  2392. $this->logger->log_trace("Running query: $query");
  2393. $ret = $this->dbHandle->exec($query);
  2394. if (FALSE === $ret) {
  2395. $error = $this->getLastDBErrorAsString();
  2396. $this->logger->log_error("Error when executing query"
  2397. . ", query=".$query
  2398. . ", error=".$error);
  2399. $response["result"] = 1;
  2400. $response["error"] = $error;
  2401. LockRelease(); return $response;
  2402. }
  2403. $rowsChanged = intval($ret);
  2404. $response["sql"] = array ( "rowsChanged" => $rowsChanged);
  2405. LockRelease(); return $response;
  2406. }
  2407. /**
  2408. * Add a new sub-txn
  2409. * @param string $clusterName
  2410. * @param int $txnId
  2411. * @param int $subTxnId
  2412. * @param int $parentSubTxnId
  2413. * @param string $state
  2414. * @param string $description
  2415. * @param string $progress
  2416. * @param string $subTxnType
  2417. * @return mixed
  2418. * array (
  2419. * "result" => 0,
  2420. * "error" => ""
  2421. * )
  2422. */
  2423. public function insertOrUpdateSubTransaction($clusterName, $txnId, $subTxnId,
  2424. $parentSubTxnId, $state, $description, $progress, $subTxnType) {
  2425. LockAcquire();
  2426. $response = array ( "result" => 0, "error" => "");
  2427. $query = "SELECT cluster_name, txn_id, sub_txn_id, op_status "
  2428. . " FROM SubTransactionStatus "
  2429. . " WHERE cluster_name = " . $this->dbHandle->quote($clusterName)
  2430. . " AND txn_id = " . $this->dbHandle->quote($txnId)
  2431. . " AND sub_txn_id = " . $this->dbHandle->quote($subTxnId);
  2432. $this->logger->log_trace("Running query: $query");
  2433. $pdoStmt = $this->dbHandle->query($query);
  2434. if ($pdoStmt === FALSE) {
  2435. $error = $this->getLastDBErrorAsString();
  2436. $this->logger->log_error("Error when executing query"
  2437. . ", query=".$query
  2438. . ", error=".$error);
  2439. $response["result"] = 1;
  2440. $response["error"] = $error;
  2441. LockRelease(); return $response;
  2442. }
  2443. $opStatus = json_encode(array());
  2444. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  2445. if (is_array($result) && count($result) == 1) {
  2446. $opStatus = $result[0]["op_status"];
  2447. }
  2448. $query = "INSERT OR REPLACE INTO SubTransactionStatus "
  2449. . " ( cluster_name, txn_id, sub_txn_id, parent_sub_txn_id"
  2450. . ", state, description, progress, sub_txn_type, op_status ) VALUES ( "
  2451. . $this->dbHandle->quote($clusterName) . " , "
  2452. . $this->dbHandle->quote($txnId) . " , "
  2453. . $this->dbHandle->quote($subTxnId) . " , "
  2454. . $this->dbHandle->quote($parentSubTxnId) . " , "
  2455. . $this->dbHandle->quote($state) . " , "
  2456. . $this->dbHandle->quote($description) . " , "
  2457. . $this->dbHandle->quote($progress) . " , "
  2458. . $this->dbHandle->quote($subTxnType) . " , "
  2459. . $this->dbHandle->quote($opStatus) . " ) ";
  2460. $this->logger->log_trace("Running query: $query");
  2461. $ret = $this->dbHandle->exec($query);
  2462. if (FALSE === $ret) {
  2463. $error = $this->getLastDBErrorAsString();
  2464. $this->logger->log_error("Error when executing query"
  2465. . ", query=".$query
  2466. . ", error=".$error);
  2467. $response["result"] = 1;
  2468. $response["error"] = $error;
  2469. LockRelease(); return $response;
  2470. }
  2471. $rowsChanged = intval($ret);
  2472. $response["sql"] = array ( "rowsChanged" => $rowsChanged);
  2473. LockRelease(); return $response;
  2474. }
  2475. /**
  2476. * Get all sub transactions
  2477. * Enter description here ...
  2478. * @param string $clusterName
  2479. * @param int $txnId
  2480. * @return mixed
  2481. * array (
  2482. * "result" => 0,
  2483. * "error" => "",
  2484. * "clusterName" =>
  2485. * "txnId" =>
  2486. * "subTxns" => array (
  2487. * $subTxnId => array (
  2488. * "subTxnId" =>
  2489. * "parentSubTxnId" =>
  2490. * "state" =>
  2491. * "description" =>
  2492. * "progress" =>
  2493. * "subTxnType" =>
  2494. * "opStatus" =>
  2495. * )
  2496. * )
  2497. * )
  2498. */
  2499. public function getAllSubTransactionsInfo($clusterName, $txnId) {
  2500. LockAcquire();
  2501. $response = array ( "result" => 0, "error" => "");
  2502. $query = "SELECT sub_txn_id, parent_sub_txn_id, state, description"
  2503. . ", progress, sub_txn_type, op_status FROM SubTransactionStatus "
  2504. . " WHERE cluster_name = " . $this->dbHandle->quote($clusterName)
  2505. . " AND txn_id = " . $this->dbHandle->quote($txnId);
  2506. $this->logger->log_trace("Running query: $query");
  2507. $pdoStmt = $this->dbHandle->query($query);
  2508. if ($pdoStmt === FALSE) {
  2509. $error = $this->getLastDBErrorAsString();
  2510. $this->logger->log_error("Error when executing query"
  2511. . ", query=".$query
  2512. . ", error=".$error);
  2513. $response["result"] = 1;
  2514. $response["error"] = $error;
  2515. LockRelease(); return $response;
  2516. }
  2517. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  2518. $response["clusterName"] = $clusterName;
  2519. $response["txnId"] = $txnId;
  2520. $response["subTxns"] = array();
  2521. foreach ($result as $entry) {
  2522. $subTxn = array();
  2523. $subTxn["subTxnId"] = $entry["sub_txn_id"];
  2524. $subTxn["parentSubTxnId"] = $entry["parent_sub_txn_id"];
  2525. $subTxn["state"] = $entry["state"];
  2526. $subTxn["description"] = $entry["description"];
  2527. $subTxn["progress"] = $entry["progress"];
  2528. $subTxn["subTxnType"] = $entry["sub_txn_type"];
  2529. $subTxn["opStatus"] = $entry["op_status"];
  2530. $response["subTxns"][$entry["sub_txn_id"]] = $subTxn;
  2531. }
  2532. LockRelease(); return $response;
  2533. }
  2534. /**
  2535. * Update op status for sub txn
  2536. * @param string $clusterName
  2537. * @param int $txnId
  2538. * @param int $subTxnId
  2539. * @param string $progress
  2540. * @return mixed
  2541. * array (
  2542. * "result" => 0,
  2543. * "error" => ""
  2544. * )
  2545. */
  2546. public function updateSubTransactionProgress($clusterName, $txnId,
  2547. $subTxnId, $progress) {
  2548. LockAcquire();
  2549. $response = array ( "result" => 0, "error" => "");
  2550. $query = "UPDATE SubTransactionStatus SET progress = "
  2551. . $this->dbHandle->quote($progress)
  2552. . " WHERE cluster_name = " . $this->dbHandle->quote($clusterName)
  2553. . " AND txn_id = " . $this->dbHandle->quote($txnId)
  2554. . " AND sub_txn_id = " . $this->dbHandle->quote($subTxnId);
  2555. $this->logger->log_trace("Running query: $query");
  2556. $ret = $this->dbHandle->exec($query);
  2557. if (FALSE === $ret) {
  2558. $error = $this->getLastDBErrorAsString();
  2559. $this->logger->log_error("Error when executing query"
  2560. . ", query=".$query
  2561. . ", error=".$error);
  2562. $response["result"] = 1;
  2563. $response["error"] = $error;
  2564. LockRelease(); return $response;
  2565. }
  2566. $rowsChanged = intval($ret);
  2567. $response["sql"] = array ( "rowsChanged" => $rowsChanged);
  2568. LockRelease(); return $response;
  2569. }
  2570. /**
  2571. * Update op status for sub txn
  2572. * @param string $clusterName
  2573. * @param int $txnId
  2574. * @param int $subTxnId
  2575. * @param string $opStatus
  2576. * @return mixed
  2577. * array (
  2578. * "result" => 0,
  2579. * "error" => ""
  2580. * )
  2581. */
  2582. public function updateSubTransactionOpStatus($clusterName, $txnId,
  2583. $subTxnId, $opStatus) {
  2584. LockAcquire();
  2585. $response = array ( "result" => 0, "error" => "");
  2586. $query = "UPDATE SubTransactionStatus SET op_status = "
  2587. . $this->dbHandle->quote($opStatus)
  2588. . " WHERE cluster_name = " . $this->dbHandle->quote($clusterName)
  2589. . " AND txn_id = " . $this->dbHandle->quote($txnId)
  2590. . " AND sub_txn_id = " . $this->dbHandle->quote($subTxnId);
  2591. $this->logger->log_trace("Running query: $query");
  2592. $ret = $this->dbHandle->exec($query);
  2593. if (FALSE === $ret) {
  2594. $error = $this->getLastDBErrorAsString();
  2595. $this->logger->log_error("Error when executing query"
  2596. . ", query=".$query
  2597. . ", error=".$error);
  2598. $response["result"] = 1;
  2599. $response["error"] = $error;
  2600. LockRelease(); return $response;
  2601. }
  2602. $rowsChanged = intval($ret);
  2603. $response["sql"] = array ( "rowsChanged" => $rowsChanged);
  2604. LockRelease(); return $response;
  2605. }
  2606. /**
  2607. * Get roles which host belongs to
  2608. * @param string $clusterName
  2609. * @param string $hostName
  2610. * @return mixed
  2611. * array (
  2612. * "result" => 0,
  2613. * "error" => "",
  2614. * "clusterName" =>
  2615. * "hosts" => array (
  2616. * "$hostName" => array (
  2617. * "services" => array (
  2618. * "$serviceName" => array (
  2619. * "components" => array (
  2620. * "$compName1" => array (
  2621. * "state" =>
  2622. * "desiredState" =>
  2623. * ),
  2624. * "$compName2" =>
  2625. * ...
  2626. * )
  2627. * )
  2628. * )
  2629. * )
  2630. * )
  2631. * )
  2632. */
  2633. public function getRolesForHosts($clusterName, $hostNames) {
  2634. LockAcquire();
  2635. $response = array ( "result" => 0, "error" => "");
  2636. if (count($hostNames) == 0) {
  2637. LockRelease(); return $response;
  2638. }
  2639. $query = "SELECT HostRoles.host_name as host_name"
  2640. . ", HostRoles.component_name as component_name"
  2641. . ", ServiceComponentInfo.service_name as service_name"
  2642. . ", ServiceComponentInfo.state as component_state"
  2643. . ", ServiceComponentInfo.desired_state as component_desired_state"
  2644. . " FROM HostRoles LEFT JOIN ServiceComponentInfo "
  2645. . " ON HostRoles.cluster_name = ServiceComponentInfo.cluster_name "
  2646. . " AND HostRoles.component_name = ServiceComponentInfo.component_name "
  2647. . " WHERE HostRoles.cluster_name = " . $this->dbHandle->quote($clusterName)
  2648. . " AND ( ";
  2649. $index = 0;
  2650. foreach ($hostNames as $hostName) {
  2651. if ($index != 0) {
  2652. $query .= " OR ";
  2653. }
  2654. ++$index;
  2655. $query .= " HostRoles.host_name = " . $this->dbHandle->quote($hostName);
  2656. }
  2657. $query .= " ) ";
  2658. $this->logger->log_trace("Running query: $query");
  2659. $pdoStmt = $this->dbHandle->query($query);
  2660. if ($pdoStmt === FALSE) {
  2661. $error = $this->getLastDBErrorAsString();
  2662. $this->logger->log_error("Error when executing query"
  2663. . ", query=".$query
  2664. . ", error=".$error);
  2665. $response["result"] = 1;
  2666. $response["error"] = $error;
  2667. LockRelease(); return $response;
  2668. }
  2669. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  2670. $response["clusterName"] = $clusterName;
  2671. $response["hosts"] = array();
  2672. foreach ($result as $entry) {
  2673. if (!isset($response["hosts"][$entry["host_name"]])) {
  2674. $response["hosts"][$entry["host_name"]] = array("services" => array());
  2675. }
  2676. if (!isset($entry["service_name"])
  2677. || $entry["service_name"] == "") {
  2678. $this->logger->log_warn("Invalid entry in host roles table, "
  2679. . print_r($entry, true));
  2680. continue;
  2681. }
  2682. if (!isset($response["hosts"][$entry["host_name"]]["services"][$entry["service_name"]])) {
  2683. $response["hosts"][$entry["host_name"]]["services"][$entry["service_name"]] =
  2684. array( "components" => array());
  2685. }
  2686. $compInfo = array();
  2687. $compInfo["componentName"] = $entry["component_name"];
  2688. $compInfo["state"] = $entry["component_state"];
  2689. $compInfo["desiredState"] = $entry["component_desired_state"];
  2690. $response["hosts"][$entry["host_name"]]["services"][$entry["service_name"]]
  2691. ["components"][$entry["component_name"]] = $compInfo;
  2692. }
  2693. LockRelease(); return $response;
  2694. }
  2695. /**
  2696. * Dump out the contents of the ServiceDependencies table
  2697. * @return mixed
  2698. * array (
  2699. * "result" =>
  2700. * "error" =>
  2701. * "serviceDependencies" => array (
  2702. * "svcName" => array (
  2703. * "svcDep1",
  2704. * ...
  2705. * ),
  2706. * ...
  2707. * )
  2708. * )
  2709. */
  2710. public function getAllServiceDependencies() {
  2711. LockAcquire();
  2712. $response = array ( "result" => 0, "error" => "");
  2713. $query = "SELECT from_service_name, to_service_name "
  2714. . " FROM ServiceDependencies";
  2715. $this->logger->log_trace("Running query: $query");
  2716. $pdoStmt = $this->dbHandle->query($query);
  2717. if ($pdoStmt === FALSE) {
  2718. $error = $this->getLastDBErrorAsString();
  2719. $this->logger->log_error("Error when executing query"
  2720. . ", query=".$query
  2721. . ", error=".$error);
  2722. $response["result"] = 1;
  2723. $response["error"] = $error;
  2724. LockRelease(); return $response;
  2725. }
  2726. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  2727. $svcDeps = array();
  2728. foreach ($result as $entry) {
  2729. if (!isset($svcDeps[$entry["from_service_name"]])) {
  2730. $svcDeps[$entry["from_service_name"]] = array();
  2731. }
  2732. array_push($svcDeps[$entry["from_service_name"]],
  2733. $entry["to_service_name"]);
  2734. }
  2735. $response["serviceDependencies"] = $svcDeps;
  2736. LockRelease(); return $response;
  2737. }
  2738. /**
  2739. * Get recursive dependencies for a given service.
  2740. * @param mixed $serviceDependencies Full Service Dependencies list as
  2741. * obtained from getAllServiceDependencies()
  2742. * @param string $serviceName Service name to get the dependencies for.
  2743. * @return array of service dependencies.
  2744. */
  2745. public function getRecursiveServiceDependency($serviceDependencies,
  2746. $serviceName) {
  2747. if (!isset($serviceDependencies[$serviceName])) {
  2748. return array();
  2749. }
  2750. $svcDeps = array();
  2751. $bfsQ = array ( $serviceName );
  2752. $seen = array();
  2753. while (count($bfsQ) > 0) {
  2754. $svc = array_shift($bfsQ);
  2755. if (isset($seen[$svc])) {
  2756. continue;
  2757. }
  2758. if ($svc != $serviceName) {
  2759. array_push($svcDeps, $svc);
  2760. }
  2761. $seen[$svc] = TRUE;
  2762. if (!isset($serviceDependencies[$svc])) {
  2763. continue;
  2764. }
  2765. $bfsQ = array_merge($bfsQ, $serviceDependencies[$svc]);
  2766. }
  2767. return $svcDeps;
  2768. }
  2769. /**
  2770. * Get recursive dependents for a given service.
  2771. * @param mixed $serviceDependencies Full Service Dependencies list as
  2772. * obtained from getAllServiceDependencies()
  2773. * @param string $serviceName Service name to get the dependents for.
  2774. * @return array of service dependents.
  2775. */
  2776. public function getRecursiveServiceDependents($serviceDependencies,
  2777. $serviceName) {
  2778. $serviceDependents = array();
  2779. foreach ($serviceDependencies as $fromSvc => $toSvcs) {
  2780. foreach ($toSvcs as $toSvc) {
  2781. if (!isset($serviceDependents[$toSvc])) {
  2782. $serviceDependents[$toSvc] = array();
  2783. }
  2784. array_push($serviceDependents[$toSvc], $fromSvc);
  2785. }
  2786. }
  2787. if (!isset($serviceDependents[$serviceName])) {
  2788. return array();
  2789. }
  2790. $svcDeps = array();
  2791. $bfsQ = array ( $serviceName );
  2792. $seen = array();
  2793. while (count($bfsQ) > 0) {
  2794. $svc = array_shift($bfsQ);
  2795. if (isset($seen[$svc])) {
  2796. continue;
  2797. }
  2798. if ($svc != $serviceName) {
  2799. array_push($svcDeps, $svc);
  2800. }
  2801. $seen[$svc] = TRUE;
  2802. if (!isset($serviceDependents[$svc])) {
  2803. continue;
  2804. }
  2805. $bfsQ = array_merge($bfsQ, $serviceDependents[$svc]);
  2806. }
  2807. return $svcDeps;
  2808. }
  2809. /**
  2810. * Set host state
  2811. * @param string $clusterName
  2812. * @param mixed $hostsToUpdate
  2813. * array (
  2814. * "$svc" => array (
  2815. * "$compName" => array (
  2816. * "host1", "host2" ...
  2817. * )
  2818. * )
  2819. * )
  2820. * @param string $state
  2821. * @param boolean $updateDesired
  2822. * @return mixed
  2823. * array (
  2824. * "result" => 0,
  2825. * "error" => "",
  2826. * "sql" => array ( "rowsChanged" => 1 )
  2827. * )
  2828. */
  2829. private function setGenericHostsState($clusterName, $hostsToUpdate,
  2830. $state, $updateDesired) {
  2831. LockAcquire();
  2832. $columnName = "state";
  2833. if ($updateDesired) {
  2834. $columnName = "desired_state";
  2835. }
  2836. $response = array ( "result" => 0, "error" => "");
  2837. $ret = $this->dbHandle->beginTransaction();
  2838. if (!$ret) {
  2839. $error = $this->getLastDBErrorAsString();
  2840. $response["result"] = 1;
  2841. $response["error"] = "Failed to start DB transaction, error=".$error;
  2842. LockRelease(); return $response;
  2843. }
  2844. $rowsChanged = 0;
  2845. foreach ($hostsToUpdate as $svcName => $compList) {
  2846. foreach ($compList as $compName => $hostList) {
  2847. if (count($hostList) == 0) {
  2848. continue;
  2849. }
  2850. $query = "UPDATE HostRoles SET " . $columnName . " = "
  2851. . $this->dbHandle->quote($state) . " WHERE "
  2852. . " cluster_name = " . $this->dbHandle->quote($clusterName)
  2853. . " AND component_name = " . $this->dbHandle->quote($compName)
  2854. . " AND ( ";
  2855. $index = 0;
  2856. foreach ($hostList as $host) {
  2857. if ($index != 0) {
  2858. $query .= " OR ";
  2859. }
  2860. ++$index;
  2861. $query .= " host_name = " . $this->dbHandle->quote($host);
  2862. }
  2863. $query .= " ) ";
  2864. $this->logger->log_trace("Running query: $query");
  2865. $ret = $this->dbHandle->exec($query);
  2866. if (FALSE === $ret) {
  2867. $error = $this->getLastDBErrorAsString();
  2868. $this->dbHandle->rollBack();
  2869. $this->logger->log_error("Error when executing query"
  2870. . ", query=".$query
  2871. . ", error=".$error);
  2872. $response["result"] = 1;
  2873. $response["error"] = $error;
  2874. LockRelease(); return $response;
  2875. }
  2876. $rowsChanged += $ret;
  2877. }
  2878. }
  2879. $ret = $this->dbHandle->commit();
  2880. if (!$ret) {
  2881. $error = $this->getLastDBErrorAsString();
  2882. $response["result"] = 1;
  2883. $response["error"] = "Failed to commit DB transaction, error=".$error;
  2884. LockRelease(); return $response;
  2885. }
  2886. $response["sql"] = array ( "rowsChanged" => $rowsChanged);
  2887. LockRelease(); return $response;
  2888. }
  2889. /**
  2890. * Set host state
  2891. * @param string $clusterName
  2892. * @param mixed $hostsToUpdate
  2893. * array (
  2894. * "$svc" => array (
  2895. * "$compName" => array (
  2896. * "host1", "host2" ...
  2897. * )
  2898. * )
  2899. * )
  2900. * @param string $state
  2901. * @return mixed
  2902. * array (
  2903. * "result" => 0,
  2904. * "error" => "",
  2905. * "sql" => array ( "rowsChanged" => 1 )
  2906. * )
  2907. */
  2908. public function setHostsState($clusterName, $hostsToUpdate, $state) {
  2909. return $this->setGenericHostsState($clusterName, $hostsToUpdate, $state,
  2910. FALSE);
  2911. }
  2912. /**
  2913. * Set host state
  2914. * @param string $clusterName
  2915. * @param mixed $hostsToUpdate
  2916. * array (
  2917. * "$svc" => array (
  2918. * "$compName" => array (
  2919. * "host1", "host2" ...
  2920. * )
  2921. * )
  2922. * )
  2923. * @param string $state Desired State
  2924. * @return mixed
  2925. * array (
  2926. * "result" => 0,
  2927. * "error" => "",
  2928. * "sql" => array ( "rowsChanged" => 1 )
  2929. * )
  2930. */
  2931. public function setHostsDesiredState($clusterName, $hostsToUpdate, $state) {
  2932. return $this->setGenericHostsState($clusterName, $hostsToUpdate, $state,
  2933. TRUE);
  2934. }
  2935. /**
  2936. * Set host role state to match components to which it belongs to
  2937. * @param mixed $hosts
  2938. * array (
  2939. * "$svc" => array (
  2940. * "$compName" => array (
  2941. * "host1", "host2" ...
  2942. * )
  2943. * )
  2944. * )
  2945. * @return mixed
  2946. * array (
  2947. * "result" => 0,
  2948. * "error" => "",
  2949. * "sql" => array ( "rowsChanged" => 1 )
  2950. * )
  2951. */
  2952. private function genericMatchHostStateToComponent($clusterName, $hosts,
  2953. $updateDesired) {
  2954. $response = array ("result" => 0, "error" => "");
  2955. if (count($hosts) == 0) {
  2956. return $response;
  2957. }
  2958. $columnName = "state";
  2959. if ($updateDesired) {
  2960. $columnName = "desired_state";
  2961. }
  2962. $compList = array();
  2963. foreach ($hosts as $svc => $compInfo) {
  2964. foreach ($compInfo as $compName => $hostList)
  2965. $compList[$compName] = $hostList;
  2966. }
  2967. if (count($compList) == 0) {
  2968. return $response;
  2969. }
  2970. LockAcquire();
  2971. $query = "SELECT component_name, ". $columnName . " FROM "
  2972. . " ServiceComponentInfo WHERE "
  2973. . " cluster_name = " . $this->dbHandle->quote($clusterName)
  2974. . " AND ( " ;
  2975. $index = 0;
  2976. foreach ($compList as $compName => $foo) {
  2977. if ($index != 0) {
  2978. $query .= " OR ";
  2979. }
  2980. ++$index;
  2981. $query .= " component_name = " . $this->dbHandle->quote($compName);
  2982. }
  2983. $query .= " ) ";
  2984. $this->logger->log_trace("Running query: $query");
  2985. $pdoStmt = $this->dbHandle->query($query);
  2986. if ($pdoStmt === FALSE) {
  2987. $error = $this->getLastDBErrorAsString();
  2988. $this->logger->log_error("Error when executing query"
  2989. . ", query=".$query
  2990. . ", error=".$error);
  2991. $response["result"] = 1;
  2992. $response["error"] = $error;
  2993. LockRelease(); return $response;
  2994. }
  2995. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  2996. $compState = array();
  2997. foreach ($result as $entry) {
  2998. $compState[$entry["component_name"]] = $entry[$columnName];
  2999. }
  3000. $rowsChanged = 0;
  3001. $ret = $this->dbHandle->beginTransaction();
  3002. if (!$ret) {
  3003. $error = $this->getLastDBErrorAsString();
  3004. $response["result"] = 1;
  3005. $response["error"] = "Failed to start DB transaction, error=".$error;
  3006. LockRelease(); return $response;
  3007. }
  3008. foreach ($compList as $compName => $hostList) {
  3009. if (count($hostList) == 0) {
  3010. continue;
  3011. }
  3012. if (!isset($compState[$compName])) {
  3013. continue;
  3014. }
  3015. $query = " UPDATE HostRoles SET " . $columnName . " = "
  3016. . $this->dbHandle->quote($compState[$compName])
  3017. . " WHERE cluster_name = " . $this->dbHandle->quote($clusterName)
  3018. . " AND component_name = " . $this->dbHandle->quote($compName)
  3019. . " AND ( ";
  3020. $index = 0;
  3021. foreach ($hostList as $host) {
  3022. if ($index != 0) {
  3023. $query .= " OR ";
  3024. }
  3025. ++$index;
  3026. $query .= " host_name = " . $this->dbHandle->quote($host);
  3027. }
  3028. $query .= " ) ";
  3029. $this->logger->log_trace("Running query: $query");
  3030. $ret = $this->dbHandle->exec($query);
  3031. if (FALSE === $ret) {
  3032. $error = $this->getLastDBErrorAsString();
  3033. $this->dbHandle->rollBack();
  3034. $this->logger->log_error("Error when executing query"
  3035. . ", query=".$query
  3036. . ", error=".$error);
  3037. $response["result"] = 1;
  3038. $response["error"] = $error;
  3039. LockRelease(); return $response;
  3040. }
  3041. $rowsChanged += $ret;
  3042. }
  3043. $ret = $this->dbHandle->commit();
  3044. if (!$ret) {
  3045. $error = $this->getLastDBErrorAsString();
  3046. $response["result"] = 1;
  3047. $response["error"] = "Failed to commit DB transaction, error=".$error;
  3048. LockRelease(); return $response;
  3049. }
  3050. $response["sql"] = array ( "rowsChanged" => $rowsChanged);
  3051. LockRelease(); return $response;
  3052. }
  3053. public function matchHostStateToComponent($clusterName, $hosts) {
  3054. return $this->genericMatchHostStateToComponent($clusterName, $hosts, FALSE);
  3055. }
  3056. public function matchHostDesiredStateToComponent($clusterName, $hosts) {
  3057. return $this->genericMatchHostStateToComponent($clusterName, $hosts, TRUE);
  3058. }
  3059. /**
  3060. * Use the current set of configs in ServiceConfig to create a snapshot
  3061. * in the ConfigHistory table
  3062. * @param string $clusterName
  3063. * @param string $changeLogMsg
  3064. * @return mixed
  3065. * array (
  3066. * "result" => 0,
  3067. * "error" => "",
  3068. * "configSnapshotId" => $snapshotId
  3069. * )
  3070. */
  3071. public function createServiceConfigSnapshot($clusterName, $changeLogMsg) {
  3072. $response = array ("result" => 0, "error" => "");
  3073. $result = $this->getServiceConfig($clusterName);
  3074. if ($result["result"] != 0) {
  3075. return $result;
  3076. }
  3077. $configs = $result["properties"];
  3078. $configBlob = json_encode(
  3079. array ( "clusterName" => $clusterName,
  3080. "properties" => $configs ) );
  3081. $curTime = time();
  3082. LockAcquire();
  3083. $ret = $this->dbHandle->beginTransaction();
  3084. if (!$ret) {
  3085. $error = $this->getLastDBErrorAsString();
  3086. $response["result"] = 1;
  3087. $response["error"] = "Failed to start DB transaction, error=".$error;
  3088. LockRelease(); return $response;
  3089. }
  3090. $query = "INSERT INTO ConfigHistory ( cluster_name, config, change_log, "
  3091. . " update_time ) VALUES ( " . $this->dbHandle->quote($clusterName)
  3092. . ", " . $this->dbHandle->quote($configBlob)
  3093. . ", " . $this->dbHandle->quote($changeLogMsg)
  3094. . ", " . $this->dbHandle->quote($curTime) . " ) ";
  3095. $this->logger->log_trace("Running query: $query");
  3096. $ret = $this->dbHandle->exec($query);
  3097. if (FALSE === $ret) {
  3098. $error = $this->getLastDBErrorAsString();
  3099. $this->dbHandle->rollBack();
  3100. $this->logger->log_error("Error when executing query"
  3101. . ", query=".$query
  3102. . ", error=".$error);
  3103. $response["result"] = 1;
  3104. $response["error"] = $error;
  3105. LockRelease(); return $response;
  3106. }
  3107. $lastInsertId = intval($this->dbHandle->lastInsertId());
  3108. if ($lastInsertId == 0) {
  3109. $this->dbHandle->rollBack();
  3110. $error = "Obtained invalid last insert id from DB";
  3111. $this->logger->log_error($error);
  3112. $response["result"] = 1;
  3113. $response["error"] = $error;
  3114. LockRelease(); return $response;
  3115. }
  3116. $ret = $this->dbHandle->commit();
  3117. if (!$ret) {
  3118. $error = $this->getLastDBErrorAsString();
  3119. $response["result"] = 1;
  3120. $response["error"] = "Failed to commit DB transaction, error=".$error;
  3121. LockRelease(); return $response;
  3122. }
  3123. $response["configSnapshotId"] = $lastInsertId;
  3124. LockRelease(); return $response;
  3125. }
  3126. public function getConfigSnapshot($clusterName, $snapshotId) {
  3127. LockAcquire();
  3128. $response = array ("result" => 0, "error" => "");
  3129. $query = "SELECT config, change_log, update_time FROM ConfigHistory"
  3130. . " WHERE cluster_name = " . $this->dbHandle->quote($clusterName)
  3131. . " AND version = " . $this->dbHandle->quote($snapshotId);
  3132. $this->logger->log_trace("Running query: $query");
  3133. $pdoStmt = $this->dbHandle->query($query);
  3134. if ($pdoStmt === FALSE) {
  3135. $error = $this->getLastDBErrorAsString();
  3136. $this->logger->log_error("Error when executing query"
  3137. . ", query=".$query
  3138. . ", error=".$error);
  3139. $response["result"] = 1;
  3140. $response["error"] = $error;
  3141. LockRelease(); return $response;
  3142. }
  3143. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  3144. $response["clusterName"] = $clusterName;
  3145. $response["configSnapshotId"] = $snapshotId;
  3146. if (isset($result) && is_array($result) && count($result) == 1) {
  3147. $response["changeLog"] = $result[0]["change_log"];
  3148. $response["config"] = json_decode($result[0]["config"], true);
  3149. $response["updateTime"] = $result[0]["update_time"];
  3150. LockRelease(); return $response;
  3151. }
  3152. $response["result"] = 1;
  3153. $response["error"] = "Could not find config snapshot in DB";
  3154. LockRelease(); return $response;
  3155. }
  3156. private function deleteClusterTable ($clusterName, $table) {
  3157. LockAcquire();
  3158. $response = array ("result" => 0, "error" => "");
  3159. $query = "DELETE from " . $table . " WHERE cluster_name = "
  3160. . $this->dbHandle->quote($clusterName);
  3161. $this->logger->log_trace("Running query: $query");
  3162. $pdoStmt = $this->dbHandle->query($query);
  3163. if ($pdoStmt == FALSE) {
  3164. $error = $this->getLastDBErrorAsString();
  3165. $this->logger->log_error("Error when executing query"
  3166. . ", query=".$query
  3167. . ", error=".$error);
  3168. $response["result"] = 1;
  3169. $response["error"] = $error;
  3170. LockRelease(); return $response;
  3171. }
  3172. LockRelease(); return $response;
  3173. }
  3174. private function deleteAllInTable ($table) {
  3175. LockAcquire();
  3176. $response = array ("result" => 0, "error" => "");
  3177. $query = "DELETE from " . $table;
  3178. $this->logger->log_trace("Running query: $query");
  3179. $pdoStmt = $this->dbHandle->query($query);
  3180. if ($pdoStmt == FALSE) {
  3181. $error = $this->getLastDBErrorAsString();
  3182. $this->logger->log_error("Error when executing query"
  3183. . ", query=".$query
  3184. . ", error=".$error);
  3185. $response["result"] = 1;
  3186. $response["error"] = $error;
  3187. LockRelease(); return $response;
  3188. }
  3189. LockRelease(); return $response;
  3190. }
  3191. public function cleanupServices($clusterName) {
  3192. $this->deleteClusterTable($clusterName, "ServiceConfig");
  3193. $this->deleteClusterTable($clusterName, "ServiceInfo");
  3194. }
  3195. public function cleanupHosts ($clusterName) {
  3196. $this->deleteClusterTable($clusterName, "Hosts");
  3197. $this->deleteClusterTable($clusterName, "HostRoles");
  3198. $this->cleanupServices($clusterName);
  3199. }
  3200. public function cleanupCluster ($clusterName) {
  3201. // $this->deleteAllInTable("Clusters");
  3202. $this->deleteClusterTable($clusterName, "ServiceComponentInfo");
  3203. $this->cleanupHosts($clusterName);
  3204. }
  3205. public function wipeOutClusters () {
  3206. $this->deleteAllInTable("Clusters");
  3207. $this->deleteAllInTable("ServiceComponentInfo");
  3208. $this->deleteAllInTable("Hosts");
  3209. $this->deleteAllInTable("HostRoles");
  3210. $this->deleteAllInTable("ServiceConfig");
  3211. $this->deleteAllInTable("ServiceInfo");
  3212. }
  3213. /**
  3214. * Returns all nodes that were successfully discovered but have no
  3215. * components/roles assigned to them within the given cluster
  3216. * Enter description here ...
  3217. * @param unknown_type $clusterName
  3218. */
  3219. public function getAllUnassignedHosts($clusterName) {
  3220. LockAcquire();
  3221. $error = "";
  3222. $query = "SELECT "
  3223. . " Hosts.host_name, Hosts.ip, Hosts.total_mem, "
  3224. . " Hosts.cpu_count, Hosts.os_arch, Hosts.os_type, Hosts.os, Hosts.disks_info, "
  3225. . " Hosts.discovery_status, Hosts.bad_health_reason, Hosts.attributes "
  3226. . " FROM Hosts LEFT JOIN HostRoles ON "
  3227. . " Hosts.cluster_name = HostRoles.cluster_name "
  3228. . " AND Hosts.host_name = HostRoles.host_name "
  3229. . " WHERE Hosts.cluster_name = "
  3230. . $this->dbHandle->quote($clusterName)
  3231. . " AND Hosts.discovery_status = 'SUCCESS'"
  3232. . " AND HostRoles.component_name ISNULL";
  3233. $response = array ( "result" => 0, "error" => "");
  3234. $this->logger->log_trace("Running query: $query");
  3235. $pdoStmt = $this->dbHandle->query($query);
  3236. if ($pdoStmt === FALSE) {
  3237. $error = $this->getLastDBErrorAsString();
  3238. $this->logger->log_error("Error when executing query"
  3239. . ", query=".$query
  3240. . ", error=".$error);
  3241. $response["result"] = 1;
  3242. $response["error"] = $error;
  3243. LockRelease(); return $response;
  3244. }
  3245. $result = $pdoStmt->fetchAll(PDO::FETCH_BOTH);
  3246. $response["hosts"] = array();
  3247. $response["clusterName"] = $clusterName;
  3248. foreach ($result as $entry) {
  3249. $host = array();
  3250. $host["hostName"] = $entry["host_name"];
  3251. $host["ip"] = $entry["ip"];
  3252. $host["totalMem"] = $entry["total_mem"];
  3253. $host["cpuCount"] = $entry["cpu_count"];
  3254. $host["osArch"] = $entry["os_arch"];
  3255. $host["osType"] = $entry["os_type"];
  3256. $host["os"] = $entry["os"];
  3257. $host["disksInfo"] = $entry["disks_info"];
  3258. $host["discoveryStatus"] = $entry["discovery_status"];
  3259. $host["badHealthReason"] = $entry["bad_health_reason"];
  3260. $host["attributes"] = json_decode($entry["attributes"], true);
  3261. array_push($response["hosts"][$host["hostName"]], $host);
  3262. }
  3263. LockRelease(); return $response;
  3264. }
  3265. }
  3266. ?>