proxysql_galera_checker 93 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589
  1. #!/bin/bash
  2. ## inspired by Percona clustercheck.sh
  3. # https://github.com/percona/proxysql-admin-tool/blob/master/proxysql_galera_checker
  4. #-------------------------------------------------------------------------------
  5. #
  6. # Step 1 : Bash internal configuration
  7. #
  8. set -o nounset # no undefined variables
  9. #-------------------------------------------------------------------------------
  10. #
  11. # Step 2 : Global variables
  12. #
  13. #
  14. # Script parameters/constants
  15. #
  16. declare -i DEBUG=0
  17. readonly PROXYSQL_ADMIN_VERSION="1.4.14"
  18. #Timeout exists for instances where mysqld may be hung
  19. declare -i TIMEOUT=10
  20. declare RED=""
  21. declare NRED=""
  22. #
  23. # Global variables used by the script
  24. #
  25. declare ERR_FILE="/dev/stderr"
  26. declare NODE_MONITOR_LOG_FILE=""
  27. declare CONFIG_FILE="/etc/proxysql-admin.cnf"
  28. declare HOST_PRIORITY_FILE=""
  29. declare CHECKER_PIDFILE=""
  30. # Set to send output here when DEBUG is set
  31. declare DEBUG_ERR_FILE="/dev/null"
  32. declare -i HOSTGROUP_WRITER_ID=1
  33. declare -i HOSTGROUP_READER_ID=-1
  34. declare -i HOSTGROUP_SLAVEREADER_ID=-1
  35. declare -i NUMBER_WRITERS=0
  36. declare WRITER_IS_READER="ondemand"
  37. declare SLAVE_IS_WRITER="yes"
  38. declare P_MODE=""
  39. declare P_PRIORITY=""
  40. declare MYSQL_USERNAME
  41. declare MYSQL_PASSWORD
  42. declare PROXYSQL_USERNAME
  43. declare PROXYSQL_PASSWORD
  44. declare PROXYSQL_HOSTNAME
  45. declare PROXYSQL_PORT
  46. declare PROXYSQL_DATADIR='/var/lib/proxysql'
  47. # Set to 1 if slave readers are being used
  48. declare -i HAVE_SLAVEREADERS=0
  49. declare -i HAVE_SLAVEWRITERS=0
  50. # How far behind can a slave be before its put into OFFLINE_SOFT state
  51. declare SLAVE_SECONDS_BEHIND=3600
  52. # Some extra text that will be logged
  53. # (useful for debugging)
  54. declare LOG_TEXT=""
  55. # Default value for max_connections in mysql_servers
  56. declare MAX_CONNECTIONS=1000
  57. #-------------------------------------------------------------------------------
  58. #
  59. # Step 3 : Helper functions
  60. #
  61. function log() {
  62. local lineno=$1
  63. shift
  64. if [[ -n $ERR_FILE ]]; then
  65. if [[ -n $lineno && $DEBUG -ne 0 ]]; then
  66. echo -e "[$(date +%Y-%m-%d\ %H:%M:%S)] $$ (line $lineno) $*" >> $ERR_FILE
  67. else
  68. echo -e "[$(date +%Y-%m-%d\ %H:%M:%S)] $$ $*" >> $ERR_FILE
  69. fi
  70. fi
  71. }
  72. # Checks the return value of the most recent command
  73. #
  74. # Globals:
  75. # None
  76. #
  77. # Arguments:
  78. # 1: the lineno where the error occurred
  79. # 2: the error code of the most recent command
  80. # 3: the error message if the error code is non-zero
  81. #
  82. function check_cmd() {
  83. local lineno=$1
  84. local retcode=$2
  85. local errmsg=$3
  86. shift 3
  87. if [[ ${retcode} -ne 0 ]]; then
  88. error "$lineno" $errmsg
  89. if [[ -n "$*" ]]; then
  90. log "$lineno" $*
  91. fi
  92. fi
  93. return $retcode
  94. }
  95. # Checks the return value of the most recent command
  96. # Exits the program if the command fails (non-zero return codes)
  97. #
  98. # This should not be used with commands that can fail for legitimate
  99. # reasons.
  100. #
  101. # Globals:
  102. # None
  103. #
  104. # Arguments:
  105. # 1: the lineno where the error occurred
  106. # 2: the error code of the most recent command
  107. # 3: the error message if the error code is non-zero
  108. #
  109. function check_cmd_and_exit() {
  110. check_cmd "$@"
  111. local retcode=$?
  112. if [[ $retcode -ne 0 ]]; then
  113. exit 1
  114. fi
  115. return $retcode
  116. }
  117. function log_if_success() {
  118. local lineno=$1
  119. local rc=$2
  120. shift 2
  121. if [[ $rc -eq 0 ]]; then
  122. log "$lineno" "$*"
  123. fi
  124. return $rc
  125. }
  126. function error() {
  127. local lineno=$1
  128. shift
  129. log "$lineno" "proxysql_galera_checker : Error ($lineno): $*"
  130. }
  131. function warning() {
  132. local lineno=$1
  133. shift
  134. log "$lineno" "Warning: $*"
  135. }
  136. function debug() {
  137. if [[ $DEBUG -eq 0 ]]; then
  138. return
  139. fi
  140. local lineno=$1
  141. shift
  142. log "$lineno" "${RED}debug: $*${NRED}"
  143. }
  144. function usage() {
  145. local path=$0
  146. cat << EOF
  147. Usage: ${path##*/} --write-hg=10 --read-hg=11 --config-file=/etc/proxysql-admin.cnf --log=/var/lib/proxysql/pxc_test_proxysql_galera_check.log
  148. Options:
  149. -w, --write-hg=<NUMBER> Specify ProxySQL write hostgroup.
  150. -r, --read-hg=<NUMBER> Specify ProxySQL read hostgroup.
  151. -c, --config-file=PATH Specify ProxySQL-admin configuration file.
  152. -l, --log=PATH Specify proxysql_galera_checker log file.
  153. --log-text=TEXT This is text that will be written to the log file
  154. whenever this script is run (useful for debugging).
  155. --node-monitor-log=PATH Specify proxysql_node_monitor log file.
  156. -n, --writer-count=<NUMBER> Maximum number of write hostgroup_id nodes
  157. that can be marked ONLINE
  158. When 0 (default), all nodes can be marked ONLINE
  159. -p, --priority=<HOST_LIST> Can accept comma delimited list of write nodes priority
  160. -m, --mode=[loadbal|singlewrite] ProxySQL read/write configuration mode,
  161. currently supporting: 'loadbal' and 'singlewrite'
  162. --writer-is-reader=<value> Defines if the writer node also accepts writes.
  163. Possible values are 'always', 'never', and 'ondemand'.
  164. 'ondemand' means that the writer node only accepts reads
  165. if there are no other readers.
  166. (default: 'never')
  167. --use-slave-as-writer=<yes/no> If this is 'yes' then slave nodes may
  168. be added to the write hostgroup if all other
  169. cluster nodes are down.
  170. (default: 'yes')
  171. --max-connections=<NUMBER> Value for max_connections in the mysql_servers table.
  172. This is the maximum number of connections that
  173. ProxySQL will open to the backend servers.
  174. (default: 1000)
  175. --debug Enables additional debug logging.
  176. -h, --help Display script usage information
  177. -v, --version Print version info
  178. Notes about the mysql_servers in ProxySQL:
  179. - NODE STATUS * Nodes that are in status OFFLINE_HARD will not be checked
  180. nor will their status be changed
  181. * SHUNNED nodes are not to be used with Galera based systems,
  182. they will be checked and their status will be changed
  183. to either ONLINE or OFFLINE_SOFT.
  184. When no nodes were found to be in wsrep_local_state=4 (SYNCED) for either
  185. read or write nodes, then the script will try 5 times for each node to try
  186. to find nodes wsrep_local_state=4 (SYNCED) or wsrep_local_state=2 (DONOR/DESYNC)
  187. EOF
  188. }
  189. # Check the permissions for a file or directory
  190. #
  191. # Globals:
  192. # None
  193. #
  194. # Arguments:
  195. # 1: the bash test to be applied to the file
  196. # 2: the lineno where this call is invoked (used for errors)
  197. # 3: the path to the file
  198. # 4: (optional) description of the path (mostly used for existence checks)
  199. #
  200. # Exits the script if the permissions test fails.
  201. #
  202. function check_permission() {
  203. local permission=$1
  204. local lineno=$2
  205. local path_to_check=$3
  206. local description=""
  207. if [[ $# -gt 3 ]]; then
  208. description="$4"
  209. fi
  210. if [ ! $permission "$path_to_check" ] ; then
  211. if [[ $permission == "-r" ]]; then
  212. error $lineno "You do not have READ permission for: $path_to_check"
  213. elif [[ $permission == "-w" ]]; then
  214. error $lineno "You do not have WRITE permission for: $path_to_check"
  215. elif [[ $permission == "-x" ]]; then
  216. error $lineno "You do not have EXECUTE permission for: $path_to_check"
  217. elif [[ $permission == "-e" ]]; then
  218. if [[ -n $description ]]; then
  219. error $lineno "Could not find the $description: $path_to_check"
  220. else
  221. error $lineno "Could not find: $path_to_check"
  222. fi
  223. elif [[ $permission == "-d" ]]; then
  224. if [[ -n $description ]]; then
  225. error $lineno "Could not find the $description: $path_to_check"
  226. else
  227. error $lineno "Could not find the directory: $path_to_check"
  228. fi
  229. elif [[ $permission == "-f" ]]; then
  230. if [[ -n $description ]]; then
  231. error $lineno "Could not find the $description: $path_to_check"
  232. else
  233. error $lineno "Could not find the file: $path_to_check"
  234. fi
  235. else
  236. error $lineno "You do not have the correct permissions for: $path_to_check"
  237. fi
  238. exit 1
  239. fi
  240. }
  241. # Executes a SQL query with the (fully) specified server
  242. #
  243. # Globals:
  244. # None
  245. #
  246. # Arguments:
  247. # 1: lineno
  248. # 2: the name of the user
  249. # 3: the user's password
  250. # 4: the hostname of the server
  251. # 5: the port used to connect to the server
  252. # 6: the query to be run
  253. # 7: arguments to the mysql client
  254. # 8: timeout in secs
  255. # 9: additional options, space separated
  256. # Available options:
  257. # "hide_output"
  258. # This will not show the output of the query when DEBUG is set.
  259. # Used to stop the display of sensitve information (such as passwords)
  260. # from being displayed when debugging.
  261. #
  262. function exec_sql() {
  263. local lineno=$1
  264. local user=$2
  265. local password=$3
  266. local hostname=$4
  267. local port=$5
  268. local query=$6
  269. local args=$7
  270. local timeout_secs=$8
  271. local more_options=$9
  272. local retvalue
  273. local retoutput
  274. debug "$lineno" "exec_sql : $user@$hostname:$port ($args) ==> $query"
  275. retoutput=$(printf "[client]\nuser=${user}\npassword=\"${password}\"\nhost=${hostname}\nport=${port}" \
  276. | timeout ${timeout_secs} mysql --defaults-file=/dev/stdin --protocol=tcp \
  277. ${args} -e "$query")
  278. retvalue=$?
  279. if [[ $DEBUG -eq 1 ]]; then
  280. local number_of_newlines=0
  281. local dbgoutput=$retoutput
  282. if [[ " $more_options " =~ [[:space:]]hide_output[[:space:]] ]]; then
  283. dbgoutput="**** data hidden ****"
  284. fi
  285. if [[ -n $dbgoutput ]]; then
  286. number_of_newlines=$(printf "%s" "${dbgoutput}" | wc -l)
  287. fi
  288. if [[ $retvalue -ne 0 ]]; then
  289. debug "" "--> query failed $retvalue"
  290. elif [[ -z $dbgoutput ]]; then
  291. debug "" "--> query returned $retvalue : <query returned no data>"
  292. elif [[ ${number_of_newlines} -eq 0 ]]; then
  293. debug "" "--> query returned $retvalue : ${dbgoutput}"
  294. else
  295. debug "" "--> query returned $retvalue : <data follows>"
  296. printf "${dbgoutput//%/%%}\n" | while IFS= read -r line; do
  297. debug "" "----> $line"
  298. done
  299. fi
  300. fi
  301. printf "${retoutput//%/%%}"
  302. return $retvalue
  303. }
  304. # Executes a SQL query on proxysql (with a timeout of $TIMEOUT seconds)
  305. #
  306. # Globals:
  307. # PROXYSQL_USERNAME
  308. # PROXYSQL_PASSWORD
  309. # PROXYSQL_HOSTNAME
  310. # PROXYSQL_PORT
  311. #
  312. # Arguments:
  313. # 1: lineno (used for debugging/output, may be blank)
  314. # 2: Additional arguments to the mysql client for the query
  315. # 3: The SQL query
  316. # 4: (optional) see the additional options for exec_sql
  317. #
  318. function proxysql_exec() {
  319. local lineno=$1
  320. local args=$2
  321. local query="$3"
  322. local more_options=""
  323. local retoutput
  324. if [[ $# -ge 4 ]]; then
  325. more_options=$4
  326. fi
  327. exec_sql "$lineno" "$PROXYSQL_USERNAME" "$PROXYSQL_PASSWORD" \
  328. "$PROXYSQL_HOSTNAME" "$PROXYSQL_PORT" \
  329. "$query" "$args" "$TIMEOUT" "$more_options"
  330. retoutput=$?
  331. if [[ $retoutput -eq 124 ]]; then
  332. error $lineno "TIMEOUT: SQL query ($PROXYSQL_HOSTNAME:$PROXYSQL_PORT) : $query"
  333. fi
  334. return $retoutput
  335. }
  336. # Executes a SQL query on mysql (with a timeout of $TIMEOUT secs)
  337. #
  338. # Globals:
  339. # MYSQL_USERNAME
  340. # MYSQL_PASSWORD
  341. #
  342. # Arguments:
  343. # 1: lineno (used for debugging/output, may be blank)
  344. # 2: the hostname of the server
  345. # 3: the port used to connect to the server
  346. # 4: arguments to the mysql client
  347. # 5: the query to be run
  348. # 6: (optional) more options see exec_sql
  349. #
  350. function mysql_exec() {
  351. local lineno=$1
  352. local hostname=$2
  353. local port=$3
  354. local args=$4
  355. local query=$5
  356. local more_options=""
  357. local retoutput
  358. if [[ $# -ge 6 ]]; then
  359. more_options=$6
  360. fi
  361. exec_sql "$lineno" "$MYSQL_USERNAME" "$MYSQL_PASSWORD" \
  362. "$hostname" "$port" \
  363. "$query" "$args" "$TIMEOUT" "$more_options"
  364. retoutput=$?
  365. if [[ $retoutput -eq 124 ]]; then
  366. error $lineno "TIMEOUT: SQL query ($hostname:$$port) : $query"
  367. fi
  368. return $retoutput
  369. }
  370. # Separates the IP address from the port in a network address
  371. # Works for IPv4 and IPv6
  372. #
  373. # Globals:
  374. # None
  375. #
  376. # Params:
  377. # 1. The network address to be parsed
  378. #
  379. # Outputs:
  380. # A string with a space separating the IP address from the port
  381. #
  382. function separate_ip_port_from_address()
  383. {
  384. #
  385. # Break address string into host:port/path parts
  386. #
  387. local address=$1
  388. # Has to have at least one ':' to separate the port from the ip address
  389. if [[ $address =~ : ]]; then
  390. ip_addr=${address%:*}
  391. port=${address##*:}
  392. else
  393. ip_addr=$address
  394. port=""
  395. fi
  396. # Remove any braces that surround the ip address portion
  397. ip_addr=${ip_addr#\[}
  398. ip_addr=${ip_addr%\]}
  399. echo "${ip_addr} ${port}"
  400. }
  401. # Combines the IP address and port into a network address
  402. # Works for IPv4 and IPv6
  403. # (If the IP address is IPv6, the IP portion will have brackets)
  404. #
  405. # Globals:
  406. # None
  407. #
  408. # Params:
  409. # 1: The IP address portion
  410. # 2: The port
  411. #
  412. # Outputs:
  413. # A string containing the full network address
  414. #
  415. function combine_ip_port_into_address()
  416. {
  417. local ip_addr=$1
  418. local port=$2
  419. local addr
  420. if [[ ! $ip_addr =~ \[.*\] && $ip_addr =~ .*:.* ]] ; then
  421. # If there are no brackets and it does have a ':', then add the brackets
  422. # because this is an unbracketed IPv6 address
  423. addr="[${ip_addr}]:${port}"
  424. else
  425. addr="${ip_addr}:${port}"
  426. fi
  427. echo $addr
  428. }
  429. # upgrade scheduler from old layout to new layout
  430. #
  431. # Globals:
  432. # PROXYSQL_DATADIR
  433. # TIMEOUT
  434. # HOST_PRIORITY_FILE
  435. #
  436. # Arguments:
  437. # None
  438. function upgrade_scheduler(){
  439. log $LINENO "**** Scheduler upgrade started ****"
  440. if [[ -f /etc/proxysql-admin.cnf ]]; then
  441. source /etc/proxysql-admin.cnf
  442. else
  443. error $LINENO "Assert! proxysql-admin configuration file : /etc/proxysql-admin.cnf does not exist, Terminating!"
  444. exit 1
  445. fi
  446. # For this function, use a shorter timeout than normal
  447. TIMEOUT=2
  448. local scheduler_rows
  449. local -i rows_found=0
  450. local -i rows_modified=0
  451. scheduler_rows=$(proxysql_exec $LINENO "-Ns" "SELECT * FROM scheduler")
  452. check_cmd_and_exit $LINENO $? "Could not retreive rows from scheduler (query failed). Exiting"
  453. while read i; do
  454. if [[ -z $i ]]; then continue; fi
  455. rows_found+=1
  456. # Extract fields from the line
  457. local id=$(echo "$i" | awk '{print $1}')
  458. local s_write_hg=$(echo "$i" | awk '{print $5}')
  459. local s_read_hg=$(echo "$i" | awk '{print $6}')
  460. local s_number_of_writes=$(echo "$i" | awk '{print $7}')
  461. local s_log=$(echo "$i" | awk '{print $9}')
  462. local s_cluster_name=$(echo "$i" | awk '{print $10}')
  463. local s_mode=""
  464. log $LINENO "Modifying the scheduler for write hostgroup: $s_write_hg"
  465. # Get the mode for this cluster
  466. local proxysql_mode_file
  467. if [[ -z $s_cluster_name ]]; then
  468. proxysql_mode_file="${PROXYSQL_DATADIR}/mode"
  469. else
  470. proxysql_mode_file="${PROXYSQL_DATADIR}/${s_cluster_name}_mode"
  471. fi
  472. if [[ -f ${proxysql_mode_file} && -r ${proxysql_mode_file} ]] ; then
  473. s_mode=$(cat ${proxysql_mode_file})
  474. else
  475. log $LINENO ".. Cannot find the ${proxysql_mode_file} file"
  476. if [[ $s_read_hg == "-1" ]]; then
  477. log $LINENO ".. Assuming mode='loadbal'"
  478. s_mode="loadbal"
  479. else
  480. log $LINENO ".. Assuming mode='singlewrite'"
  481. s_mode="singlewrite"
  482. fi
  483. fi
  484. # TODO: kennt
  485. # This will fail in the multi-cluster case, but may be a non-issue
  486. # since those nodes should appear in one cluster (may cause extra work
  487. # for the othre clusters though).
  488. # Get the host priority file
  489. local s_host_priority=''
  490. if [[ -n $HOST_PRIORITY_FILE && -f $HOST_PRIORITY_FILE ]]; then
  491. debug $LINENO "Found a host priority file: $HOST_PRIORITY_FILE"
  492. local p_priority_hosts=""
  493. # Get the list of hosts from the host_priority file ignoring blanks
  494. # and any lines that start with '#'
  495. p_priority_hosts=$(cat $HOST_PRIORITY_FILE | grep '^[^#]' | sed ':a;N;$!ba;s/\n/,/g')
  496. if [[ ! -z $p_priority_hosts ]] ; then
  497. s_host_priority="--priority=$p_priority_hosts"
  498. fi
  499. fi
  500. # Make the changes
  501. if [[ ! -z $s_write_hg ]] && [[ ! -z $s_read_hg ]] && [[ ! -z $s_number_of_writes ]] && [[ ! -z $s_log ]]; then
  502. proxysql_exec $LINENO -Ns "UPDATE scheduler SET arg1='--config-file=/etc/proxysql-admin.cnf --writer-is-reader=ondemand --write-hg=$s_write_hg --read-hg=$s_read_hg --writer-count=$s_number_of_writes $s_host_priority --mode=$s_mode --log=$s_log', arg2=NULL, arg3=NULL, arg4=NULL, arg5=NULL WHERE id=$id"
  503. check_cmd_and_exit $LINENO $? "Could not update the scheduler (query failed). Exiting."
  504. rows_modified+=1
  505. fi
  506. done< <(printf "${scheduler_rows}\n")
  507. if [[ $rows_modified -gt 0 ]]; then
  508. proxysql_exec $LINENO -Ns "LOAD SCHEDULER TO RUNTIME; SAVE SCHEDULER TO DISK;"
  509. check_cmd_and_exit $LINENO $? "Could not save scheduler changes to runtime or disk (query failed). Exiting."
  510. log_if_success $LINENO $? "Scheduler changes saved to runtime and disk"
  511. fi
  512. log $LINENO "$rows_modified row(s) modified / $rows_found row(s) found"
  513. log $LINENO "**** Scheduler upgrade finished ****"
  514. }
  515. # Upgrade the status of a node
  516. # This may also perform an INSERT (depending on the reader_status)
  517. #
  518. # Globals:
  519. # TIMEOUT
  520. #
  521. # Arguments:
  522. # 1: lineno
  523. # 2: hostgroup
  524. # 3: server address
  525. # 4: port
  526. # 5: new status
  527. # 6: reader_status
  528. # 7: comment
  529. #
  530. function change_server_status() {
  531. local lineno=$1
  532. local hostgroup=$2
  533. local server=$3
  534. local port=$4
  535. local status=$5
  536. local reader_status=$6
  537. local comment=$7
  538. local address
  539. address=$(combine_ip_port_into_address "$server" "$port")
  540. # If we have a PRIORITY_NODE, then we don't have a WRITER entry
  541. # to upgrade, but we do have a READER entry, so upgrade that
  542. if [[ $reader_status == "PRIORITY_NODE" ]]; then
  543. proxysql_exec $lineno -Ns "INSERT INTO mysql_servers
  544. (hostname,hostgroup_id,port,weight,status,comment,max_connections)
  545. VALUES ('$server',$hostgroup,$port,1000000,'$status','WRITE',$MAX_CONNECTIONS);"
  546. check_cmd_and_exit $LINENO $? "Could not create new mysql_servers row (query failed). Exiting."
  547. log "$lineno" "Adding server $hostgroup:$address with status $status. Reason: $comment"
  548. else
  549. proxysql_exec $lineno -Ns "UPDATE mysql_servers
  550. set status = '$status' WHERE hostgroup_id = $hostgroup AND hostname = '$server' AND port = $port;" 2>>${ERR_FILE}
  551. check_cmd_and_exit $LINENO $? "Could not update new mysql_servers row (query failed). Exiting."
  552. log "$lineno" "Changing server $hostgroup:$address to status $status. Reason: $comment"
  553. fi
  554. }
  555. # Arguments:
  556. # The arguments to the script.
  557. #
  558. function parse_args() {
  559. local go_out=""
  560. # TODO: kennt, what happens if we don't have a functional getopt()?
  561. # Check if we have a functional getopt(1)
  562. if ! getopt --test; then
  563. go_out="$(getopt --options=w:r:c:l:n:m:p:vh --longoptions=write-hg:,read-hg:,config-file:,log:,node-monitor-log:,writer-count:,mode:,priority:,writer-is-reader:,use-slave-as-writer:,log-text:,max-connections:,version,debug,help \
  564. --name="$(basename "$0")" -- "$@")"
  565. if [[ $? -ne 0 ]]; then
  566. # no place to send output
  567. echo "proxysql_galera_checker : Script error: getopt() failed" >&2
  568. exit 1
  569. fi
  570. eval set -- "$go_out"
  571. fi
  572. if [[ $go_out == " --" ]];then
  573. usage
  574. exit 1
  575. fi
  576. #
  577. # We iterate through the command-line options twice
  578. # (1) to handle options that don't need permissions (such as --help)
  579. # (2) to handle options that need to be done before other
  580. # options, such as loading the config file
  581. #
  582. for arg
  583. do
  584. case "$arg" in
  585. -- ) shift; break;;
  586. --config-file )
  587. CONFIG_FILE="$2"
  588. check_permission -e $LINENO "$CONFIG_FILE" "proxysql-admin configuration file"
  589. debug $LINENO "--config-file specified, using : $CONFIG_FILE"
  590. shift 2
  591. ;;
  592. --help)
  593. usage
  594. exit 0
  595. ;;
  596. -v | --version)
  597. echo "proxysql_galera_checker version $PROXYSQL_ADMIN_VERSION"
  598. exit 0
  599. ;;
  600. --debug)
  601. DEBUG=1
  602. shift
  603. ;;
  604. *)
  605. shift
  606. ;;
  607. esac
  608. done
  609. #
  610. # Load the config file before reading in the command-line options
  611. #
  612. readonly CONFIG_FILE
  613. if [ ! -e "$CONFIG_FILE" ]; then
  614. warning "" "Could not locate the configuration file: $CONFIG_FILE"
  615. else
  616. check_permission -r $LINENO "$CONFIG_FILE"
  617. debug $LINENO "Loading $CONFIG_FILE"
  618. source "$CONFIG_FILE"
  619. fi
  620. if [[ $DEBUG -ne 0 ]]; then
  621. # For now
  622. if [[ -t 1 ]]; then
  623. ERR_FILE=/dev/stderr
  624. fi
  625. fi
  626. # Reset the command line for the next invocation
  627. eval set -- "$go_out"
  628. for arg
  629. do
  630. case "$arg" in
  631. -- ) shift; break;;
  632. -w | --write-hg )
  633. HOSTGROUP_WRITER_ID=$2
  634. shift 2
  635. ;;
  636. -r | --read-hg )
  637. HOSTGROUP_READER_ID=$2
  638. shift 2
  639. ;;
  640. --config-file )
  641. # Do no processing of config-file here, it is processed
  642. # before this loop (see above)
  643. shift 2
  644. ;;
  645. -l | --log )
  646. ERR_FILE="$2"
  647. shift 2
  648. # Test if stderr is open to a terminal
  649. # We cannot use stdout as the log output, since it is used
  650. # to return values.
  651. if [[ $ERR_FILE == "/dev/stderr" ]]; then
  652. RED=$(tput setaf 1)
  653. NRED=$(tput sgr0)
  654. else
  655. RED=""
  656. NRED=""
  657. fi
  658. ;;
  659. --node-monitor-log )
  660. NODE_MONITOR_LOG_FILE="$2"
  661. shift 2
  662. ;;
  663. -n | --writer-count )
  664. NUMBER_WRITERS="$2"
  665. shift 2
  666. ;;
  667. -p | --priority )
  668. P_PRIORITY="$2"
  669. shift 2
  670. ;;
  671. -m | --mode )
  672. P_MODE="$2"
  673. shift 2
  674. if [ "$P_MODE" != "loadbal" ] && [ "$P_MODE" != "singlewrite" ]; then
  675. echo "ERROR: Invalid --mode passed:"
  676. echo " Please choose one of these modes: loadbal, singlewrite"
  677. exit 1
  678. fi
  679. ;;
  680. --writer-is-reader )
  681. WRITER_IS_READER="$2"
  682. shift 2
  683. ;;
  684. --use-slave-as-writer )
  685. SLAVE_IS_WRITER="$2"
  686. shift 2
  687. ;;
  688. --max-connections )
  689. MAX_CONNECTIONS="$2"
  690. shift 2
  691. ;;
  692. --debug )
  693. # Not handled here, see above
  694. shift
  695. ;;
  696. --log-text )
  697. LOG_TEXT="$2"
  698. shift 2
  699. ;;
  700. -v | --version )
  701. # Not handled here, see above
  702. shift
  703. ;;
  704. -h | --help )
  705. # Not handled here, see above
  706. shift
  707. ;;
  708. esac
  709. done
  710. if [[ $DEBUG -eq 1 ]]; then
  711. DEBUG_ERR_FILE=$ERR_FILE
  712. fi
  713. #
  714. # Argument validation
  715. #
  716. test $HOSTGROUP_WRITER_ID -ge 0 &>/dev/null
  717. if [[ $? -ne 0 ]]; then
  718. echo "ERROR: writer hostgroup_id is not an integer"
  719. usage
  720. exit 1
  721. fi
  722. test $HOSTGROUP_READER_ID -ge -1 &>/dev/null
  723. if [[ $? -ne 0 ]]; then
  724. echo "ERROR: reader hostgroup_id is not an integer"
  725. usage
  726. exit 1
  727. fi
  728. HOSTGROUP_SLAVEREADER_ID=$HOSTGROUP_READER_ID
  729. if [ $HOSTGROUP_SLAVEREADER_ID -eq $HOSTGROUP_WRITER_ID ];then
  730. let HOSTGROUP_SLAVEREADER_ID+=1
  731. fi
  732. if [[ $NUMBER_WRITERS -lt 0 ]]; then
  733. echo "ERROR: The number of writers should either be 0 to enable all possible nodes ONLINE"
  734. echo " or be larger than 0 to limit the number of writers"
  735. usage
  736. exit 1
  737. fi
  738. if [[ ! $WRITER_IS_READER =~ ^(always|never|ondemand)$ ]]; then
  739. error "" "Invalid --writer-is-reader option: '$WRITER_IS_READER'"
  740. echo "Please choose one of these values: always, never, or ondemand"
  741. exit 1
  742. fi
  743. if [[ ! $SLAVE_IS_WRITER =~ ^(yes|YES|no|NO)$ ]]; then
  744. error "" "Invalid --use-slave-as-writer option: '$SLAVE_IS_WRITER'"
  745. echo "Please choose either yes or no"
  746. exit 1
  747. fi
  748. if [[ $SLAVE_IS_WRITER =~ ^(yes|YES)$ ]]; then
  749. SLAVE_IS_WRITER="yes"
  750. else
  751. SLAVE_IS_WRITER="no"
  752. fi
  753. # These may get set in the config file, but they are not used
  754. # by this script. So to avoid confusion and problems, remove
  755. # these variables explicitly.
  756. unset WRITE_HOSTGROUP_ID
  757. unset READ_HOSTGROUP_ID
  758. unset SLAVEREAD_HOSTGROUP_ID
  759. # Verify that we have an integer
  760. if [[ -n $MAX_CONNECTIONS ]]; then
  761. if ! [ "$MAX_CONNECTIONS" -eq "$MAX_CONNECTIONS" ] 2>/dev/null
  762. then
  763. error "" "option '--max-connections' parameter (must be a number) : $MAX_CONNECTIONS"
  764. exit 1
  765. fi
  766. fi
  767. readonly ERR_FILE
  768. readonly CONFIG_FILE
  769. readonly DEBUG_ERR_FILE
  770. readonly HOSTGROUP_WRITER_ID
  771. readonly HOSTGROUP_READER_ID
  772. readonly HOSTGROUP_SLAVEREADER_ID
  773. readonly NUMBER_WRITERS
  774. readonly WRITER_IS_READER
  775. readonly SLAVE_IS_WRITER
  776. readonly P_PRIORITY
  777. readonly P_MODE
  778. readonly MAX_CONNECTIONS
  779. }
  780. # Checks to see if another instance of the script is running.
  781. # We want only one instance of this script to be running at a time.
  782. #
  783. # Globals:
  784. # PROXYSQL_DATADIR
  785. # ERR_FILE
  786. #
  787. # Arguments:
  788. # 1: the cluster name
  789. #
  790. # This function will exit if another instance of the script is running.
  791. #
  792. # With thanks, http://bencane.com/2015/09/22/preventing-duplicate-cron-job-executions/
  793. #
  794. function check_is_galera_checker_running() {
  795. local cluster_name=$1
  796. if [[ -z $cluster_name ]]; then
  797. CHECKER_PIDFILE=${PROXYSQL_DATADIR}/galera_checker.pid
  798. else
  799. CHECKER_PIDFILE=${PROXYSQL_DATADIR}/${cluster_name}_galera_checker.pid
  800. fi
  801. if [[ -f $CHECKER_PIDFILE && -r $CHECKER_PIDFILE ]] ; then
  802. local GPID
  803. GPID=$(cat "$CHECKER_PIDFILE")
  804. if ps -p $GPID -o args=ARGS | grep $ERR_FILE | grep -o proxysql_galera_check >/dev/null 2>&1 ; then
  805. ps -p $GPID > /dev/null 2>&1
  806. if [[ $? -eq 0 ]]; then
  807. log "$LINENO" "ProxySQL galera checker process already running. (pid:$GPID this pid:$$)"
  808. # We don't want to remove this file on cleanup
  809. CHECKER_PIDFILE=""
  810. exit 1
  811. else
  812. echo $$ > $CHECKER_PIDFILE
  813. if [[ $? -ne 0 ]] ; then
  814. warning "$LINENO" "Could not create galera checker PID file"
  815. exit 1
  816. fi
  817. debug "$LINENO" "Created PID file at $CHECKER_PIDFILE"
  818. fi
  819. else
  820. warning "$LINENO" "Existing PID($GPID) belongs to some other process. Creating new PID file."
  821. echo $$ > $CHECKER_PIDFILE
  822. if [[ $? -ne 0 ]] ; then
  823. warning "$LINENO" "Could not create galera checker PID file"
  824. exit 1
  825. fi
  826. debug "$LINENO" "Created PID file at $CHECKER_PIDFILE"
  827. fi
  828. else
  829. echo "$$" > "$CHECKER_PIDFILE"
  830. if [[ $? -ne 0 ]]; then
  831. warning "$LINENO" "Could not create galera checker PID file"
  832. exit 1
  833. fi
  834. debug "$LINENO" "Created PID file at $CHECKER_PIDFILE"
  835. fi
  836. }
  837. function cleanup_handler() {
  838. if [[ -n $CHECKER_PIDFILE ]]; then
  839. rm -f $CHECKER_PIDFILE
  840. fi
  841. }
  842. # Checks to see that the READ hostgroup entries have been created/deleted
  843. # This function has no meaning if mode="loadbal".
  844. #
  845. # Globals:
  846. # HOSTGROUP_READER_ID
  847. # HOSTGROUP_WRITER_ID
  848. # WRITER_IS_READER
  849. # MODE
  850. #
  851. # Arguments:
  852. # 1: the name of the reload_check_file
  853. # 2: the number of online-readers
  854. #
  855. function writer_is_reader_check() {
  856. local reload_check_file=$1
  857. local number_readers_online=$2
  858. local servers
  859. if [[ $MODE == "loadbal" ]]; then
  860. return
  861. fi
  862. servers=$(proxysql_exec $LINENO -Ns "SELECT hostgroup_id, hostname, port, status
  863. FROM mysql_servers
  864. WHERE hostgroup_id IN ($HOSTGROUP_READER_ID,$HOSTGROUP_WRITER_ID) AND
  865. status <> 'OFFLINE_HARD'
  866. AND comment <> 'SLAVEREAD'
  867. ORDER BY hostname, port, hostgroup_id")
  868. check_cmd_and_exit $LINENO $? "Could not retreive data from mysql_servers (query failed). Exiting."
  869. debug $LINENO "writer_is_reader_check : number_readers_online:$number_readers_online"
  870. # The extra test at the end is to ensure that the very last line read in
  871. # is also handled (the read may be returning EOF)
  872. printf "${servers}" | while read hostgroup server port stat || [ -n "$stat" ]
  873. do
  874. debug $LINENO "Examining $hostgroup:$server:$port"
  875. # Only look at writer nodes, so skip non-writers
  876. if [[ $hostgroup -ne $HOSTGROUP_WRITER_ID ]]; then
  877. continue
  878. fi
  879. local regex="(^|[[:space:]])${HOSTGROUP_READER_ID}[[:blank:]]${server}[[:blank:]]${port}[[:blank:]]"
  880. local address
  881. address=$(combine_ip_port_into_address "$server" "$port")
  882. if [[ $WRITER_IS_READER == "always" || $WRITER_IS_READER == "ondemand" ]]; then
  883. #
  884. # Ensure that there is a corresponding entry in mysql_servers
  885. #
  886. local reader_row=$(echo "$servers" | grep -E "$regex")
  887. if [[ -z $reader_row ]]; then
  888. # We did not find a matching row, insert the corresponding READER entry
  889. # If we are to always have a reader, or if there are no other
  890. # readers, add it as an ONLINE reader
  891. local comment
  892. if [[ $WRITER_IS_READER == "always" || $number_readers_online -eq 0 ]]; then
  893. comment="ONLINE"
  894. else
  895. comment="OFFLINE_SOFT"
  896. fi
  897. proxysql_exec $LINENO -Ns "INSERT INTO mysql_servers (hostname,hostgroup_id,port,weight,status,comment,max_connections) VALUES ('$server',$HOSTGROUP_READER_ID,$port,1000,'$comment','READ',$MAX_CONNECTIONS);"
  898. check_cmd_and_exit $LINENO $? "writer-is-reader($WRITER_IS_READER): Failed to add $HOSTGROUP_READER_ID:$address (query failed). Exiting."
  899. log_if_success $LINENO $? "writer-is-reader($WRITER_IS_READER): Adding reader $HOSTGROUP_READER_ID:$address with status OFFLINE_SOFT"
  900. echo "1" > ${reload_check_file}
  901. elif [[ $WRITER_IS_READER == "ondemand" && $stat == "ONLINE" && $number_readers_online -gt 1 ]]; then
  902. # If the reader node is ONLINE and there is another reader
  903. # Then we can deactivate this reader node (if ondemand)
  904. # This should only do this if there is a corresponding READ entry that is NOT "OFFLINE_SOFT"
  905. # Search through the $servers for an entry corresponding to the READ data
  906. local reader_status=$(echo -e "$reader_row" | cut -f4)
  907. if [[ $reader_status != "OFFLINE_SOFT" ]]; then
  908. proxysql_exec $LINENO -Ns "UPDATE mysql_servers SET status='OFFLINE_SOFT' WHERE hostgroup_id=$HOSTGROUP_READER_ID AND hostname='$server' AND port=$port"
  909. check_cmd_and_exit $LINENO $? "Could not update mysql_servers (query failed). Exiting."
  910. log_if_success $LINENO $? "Updating $hostgroup:$address to OFFLINE_SOFT because writers prefer to not be readers (writer-is-reader:ondemand)"
  911. echo "1" > ${reload_check_file}
  912. fi
  913. fi
  914. elif [[ $WRITER_IS_READER == "never" ]]; then
  915. #
  916. # Ensure that there is NO corresponding entry in mysql_servers
  917. #
  918. if [[ $servers =~ $regex ]]; then
  919. # Delete the corresponding READER entry
  920. proxysql_exec $LINENO -Ns "DELETE FROM mysql_servers WHERE hostgroup_id=$HOSTGROUP_READER_ID and hostname='$server' and port=$port"
  921. check_cmd_and_exit $LINENO $? "writer-is-reader(never): Failed to remove $HOSTGROUP_READER_ID:$address (query failed). Exiting."
  922. log_if_success $LINENO $? "writer-is-reader(never): Removing reader $HOSTGROUP_READER_ID:$address"
  923. echo "1" > ${reload_check_file}
  924. fi
  925. fi
  926. done
  927. }
  928. # Returns the address of an available (online) cluster host
  929. #
  930. # Globals:
  931. # None
  932. #
  933. # Arguments:
  934. # None
  935. #
  936. # Returns:
  937. # 0 : if the function succeeds (this means that no errors occurred in the SQL queries)
  938. # The function can return nothing and still return success
  939. # 1 : if an error occurs
  940. #
  941. function find_online_cluster_host() {
  942. # Query the proxysql database for hosts,ports in use
  943. # Then just go through the list until we reach one that responds
  944. local hosts
  945. hosts=$(proxysql_exec $LINENO -Ns "SELECT hostname,port FROM mysql_servers where hostgroup_id in ($HOSTGROUP_WRITER_ID, $HOSTGROUP_READER_ID) and comment <> 'SLAVEREAD' and status='ONLINE'")
  946. if [[ $? -ne 0 ]]; then
  947. return 1
  948. fi
  949. printf "$hosts" | while read server port || [[ -n $port ]]
  950. do
  951. debug $LINENO "Trying to contact $server:$port..."
  952. mysql_exec "$LINENO" "$server" "$port" -Bs "select @@port" 1>/dev/null 2>>${DEBUG_ERR_FILE}
  953. if [[ $? -eq 0 ]]; then
  954. printf "$server $port"
  955. return 0
  956. fi
  957. done
  958. # No cluster host available (cannot contact any)
  959. return 0
  960. }
  961. # Checks the number of online writers and promotes a reader to a writer
  962. # if needed
  963. #
  964. # Globals:
  965. # HOSTGROUP_WRITER_ID
  966. # CHECK_STATUS
  967. #
  968. # Arguments:
  969. # 1: The path to the reload_check_file
  970. #
  971. function ensure_one_writer_node() {
  972. local reload_check_file=$1
  973. log $LINENO "No ONLINE writers found, looking for readers to promote"
  974. # We are trying to find a reader node that can be promoted to
  975. # a writer.
  976. # So what we do is we ORDER BY writer.status ASC because
  977. # by accident ONLINE is last in the line
  978. local reader_proxysql_query="SELECT
  979. reader.hostname,
  980. reader.port,
  981. writer.status
  982. FROM mysql_servers as reader
  983. LEFT JOIN mysql_servers as writer
  984. ON writer.hostgroup_id = $HOSTGROUP_WRITER_ID
  985. AND writer.hostname = reader.hostname
  986. AND writer.port = reader.port
  987. WHERE reader.hostgroup_id = $HOSTGROUP_READER_ID
  988. AND reader.status = 'ONLINE'
  989. AND reader.comment = 'READ'
  990. ORDER BY writer.status ASC,
  991. reader.weight DESC,
  992. reader.hostname,
  993. reader.port"
  994. local possible_hosts
  995. possible_hosts=$(proxysql_exec $LINENO -Ns "$reader_proxysql_query")
  996. check_cmd_and_exit $LINENO $? "Could not get data from mysql_servers (query failed). Exiting."
  997. if [[ -z $possible_hosts ]]; then
  998. log $LINENO "Cannot find a reader that can be promoted to a writer"
  999. return
  1000. fi
  1001. while read line; do
  1002. if [[ -z $line ]]; then
  1003. continue
  1004. fi
  1005. local host=$(echo $line | awk '{ print $1 }')
  1006. local port=$(echo $line | awk '{ print $2 }')
  1007. # Have to check that we can actually access the node
  1008. local wsrep_status
  1009. local pxc_main_mode
  1010. local result
  1011. local address
  1012. address=$(combine_ip_port_into_address "$host" "$port")
  1013. result=$(mysql_exec $LINENO "$host" "$port" -Nns "SHOW STATUS LIKE 'wsrep_local_state'; SHOW VARIABLES LIKE 'pxc_maint_mode';" 2>>${DEBUG_ERR_FILE})
  1014. wsrep_status=$(echo "$result" | grep "wsrep_local_state" | awk '{ print $2 }')
  1015. pxc_main_mode=$(echo "$result" | grep "pxc_maint_mode" | awk '{ print $2 }')
  1016. if [[ -z $pxc_main_mode ]]; then
  1017. pxc_main_mode="DISABLED"
  1018. fi
  1019. if [[ $wsrep_status -ne 4 || $pxc_main_mode != "DISABLED" ]]; then
  1020. continue
  1021. fi
  1022. local write_stat=$(echo "$line" | awk '{print $3}')
  1023. debug $LINENO "Looking at $address write_status:$write_stat"
  1024. log $LINENO "Promoting $address as writer node..."
  1025. # We have an ONLINE reader node
  1026. # if ondemand or always keep the reader node (may need to move it to OFFLINE_SOFT)
  1027. # if we have a writer, move to ONLINE
  1028. # if no writer, create it
  1029. if [[ $WRITER_IS_READER == "ondemand" || $WRITER_IS_READER == "always" ]]; then
  1030. if [[ -z $write_stat || $write_stat == "NULL" ]]; then
  1031. # Writer does not exist, add an ONLINE writer
  1032. proxysql_exec $LINENO -Ns \
  1033. "INSERT INTO mysql_servers (hostname,hostgroup_id,port,weight,status,comment,max_connections)
  1034. VALUES ('$host',$HOSTGROUP_WRITER_ID,$port,1000000,'ONLINE','WRITE',$MAX_CONNECTIONS);"
  1035. check_cmd_and_exit $LINENO $? "Cannot add a PXC writer node to ProxySQL (query failed). Exiting."
  1036. log_if_success $LINENO $? "Added $HOSTGROUP_WRITER_ID:$address as a writer."
  1037. else
  1038. # Writer exists, move writer to ONLINE
  1039. proxysql_exec $LINENO -Ns "UPDATE mysql_servers SET status='ONLINE',comment='WRITE',weight=1000000 WHERE hostgroup_id=$HOSTGROUP_WRITER_ID AND hostname='$host' AND port=$port"
  1040. check_cmd_and_exit $LINENO $? "Cannot update the PXC node $HOSTGROUP_WRITER_ID:$address (query failed). Exiting."
  1041. log_if_success $LINENO $? "Updated ${HOSTGROUP_WRITER_ID}:${host}:${port} node in ProxySQL."
  1042. fi
  1043. else
  1044. if [[ -z $write_stat || $write_stat == "NULL" ]]; then
  1045. # Writer does not exist, move reader to writer
  1046. proxysql_exec $$LINENO -Ns\
  1047. "UPDATE mysql_servers set status='ONLINE',hostgroup_id=$HOSTGROUP_WRITER_ID, comment='WRITE', weight=1000000 WHERE hostgroup_id=$HOSTGROUP_READER_ID and hostname='$host' and port=$port"
  1048. check_cmd_and_exit $LINENO $? "Cannot update PXC writer in ProxySQL (query failed). Exiting."
  1049. log_if_success $LINENO $? "Added $HOSTGROUP_WRITER_ID:$address as a writer node."
  1050. else
  1051. # Writer exists, move writer to ONLINE, remove reader
  1052. proxysql_exec $LINENO -Ns "UPDATE mysql_servers SET status='ONLINE',comment='WRITE',weight=1000000 WHERE hostgroup_id=$HOSTGROUP_WRITER_ID AND hostname='$host' AND port=$port"
  1053. check_cmd_and_exit $LINENO $? "Cannot update the PXC node $HOSTGROUP_WRITER_ID:$address (query failed). Exiting."
  1054. log_if_success $LINENO $? "Updated ${HOSTGROUP_WRITER_ID}:${host}:${port} node in ProxySQL."
  1055. proxysql_exec $LINENO -Ns "DELETE FROM mysql_servers WHERE hostgroup_id=$HOSTGROUP_READER_ID and hostname='$host' and port=$port"
  1056. check_cmd_and_exit $LINENO $? "writer-is-reader(never): Failed to remove $HOSTGROUP_READER_ID:$server:$port (query failed). Exiting."
  1057. log_if_success $LINENO $? "writer-is-reader(never): Removing reader $HOSTGROUP_READER_ID:$server:$port"
  1058. fi
  1059. fi
  1060. echo '1' > ${reload_check_file}
  1061. break
  1062. done< <(printf "${possible_hosts}\n")
  1063. }
  1064. # Returns the host priority list defined by the user
  1065. #
  1066. # Globals:
  1067. # HOST_PRIORITY_FILE
  1068. # P_PRIORITY
  1069. # PROXYSQL_DATADIR
  1070. # CLUSTER_NAME
  1071. #
  1072. # Arguments:
  1073. # 1: cluster name
  1074. #
  1075. function get_host_priority_list() {
  1076. local cluster_name=$1
  1077. local priority_hosts=""
  1078. if [[ -z $HOST_PRIORITY_FILE || ! -f $HOST_PRIORITY_FILE ]]; then
  1079. HOST_PRIORITY_FILE=${PROXYSQL_DATADIR}/${cluster_name}_host_priority
  1080. fi
  1081. if [[ ! -z "$P_PRIORITY" ]] ; then
  1082. IFS=',' read -r -a priority_hosts <<< "$P_PRIORITY"
  1083. debug $LINENO "host_priority = ${priority_hosts[@]}"
  1084. elif [[ -f $HOST_PRIORITY_FILE ]];then
  1085. # Get the list of hosts from the host_priority file ignoring blanks and
  1086. # any lines that start with '#'
  1087. debug $LINENO "Found a host priority file: $HOST_PRIORITY_FILE"
  1088. priority_hosts=$(cat "$HOST_PRIORITY_FILE" | grep '^[^#]')
  1089. if [[ -n $priority_hosts ]]; then
  1090. priority_hosts=($(echo $priority_hosts))
  1091. fi
  1092. fi
  1093. # File sample:
  1094. # 10.11.12.21:3306
  1095. # 10.21.12.21:3306
  1096. # 10.31.12.21:3306
  1097. #
  1098. echo "${priority_hosts[@]}"
  1099. }
  1100. # Builds the proxysql host list and merges it with the priority list.
  1101. # The entries from the priority list are put at the top in order.
  1102. #
  1103. # If they have an entry in the proxysql_list, the data is copied over.
  1104. # If it does not exist in the proxysql_list, then it is added
  1105. # with status=OFFLINE_SOFT.
  1106. #
  1107. # This ensures that the entry will not be added as
  1108. # a writer if the node is really offline.
  1109. #
  1110. # Globals:
  1111. # None
  1112. #
  1113. # Argument:
  1114. # 1: field separator
  1115. # 2: the proxysql list (array of nodes from proxysql)
  1116. # 3: the priority list
  1117. #
  1118. function build_proxysql_list_with_priority() {
  1119. local sep=$1
  1120. local proxysql_list=$(echo "$2" | tr ' ' '\n')
  1121. local priority_list=($3)
  1122. local new_proxysql_list=()
  1123. local reader_list=""
  1124. local reader_query=0
  1125. for prio in "${priority_list[@]}"; do
  1126. local psql_entry
  1127. local prio_entry
  1128. local prio_ip
  1129. local prio_port
  1130. prio_entry=$(separate_ip_port_from_address "$prio")
  1131. prio_ip=$(echo "$prio_entry" | cut -d' ' -f1)
  1132. prio_port=$(echo "$prio_entry" | cut -d' ' -f2)
  1133. prio_entry="$prio_ip$sep$prio_port"
  1134. # properly escape the characters for grep
  1135. prio_entry_re="$(printf '%s' "$prio_entry" | sed 's/[.[\*^$]/\\&/g')"
  1136. psql_entry=$(echo "$proxysql_list" | grep "^${prio_entry_re}[^[[:space:]]]*")
  1137. if [[ $? -eq 0 && -n ${psql_entry} ]]; then
  1138. # Add entries that are in the priority list and in the proxysql list
  1139. new_proxysql_list+=($psql_entry)
  1140. else
  1141. # Add entries that are in the priority list but not in proxysql
  1142. # (but only if there is a reader entry for the address)
  1143. if [[ $reader_query -eq 0 ]]; then
  1144. reader_list=$(proxysql_exec $LINENO -Ns "SELECT hostname, port
  1145. FROM mysql_servers
  1146. WHERE hostgroup_id IN ($HOSTGROUP_READER_ID)
  1147. AND status <> 'OFFLINE_HARD'
  1148. AND comment <> 'SLAVEREAD'
  1149. ORDER BY status DESC, hostgroup_id, weight DESC, hostname, port")
  1150. check_cmd_and_exit $LINENO $? "Unable to obtain list of nodes from ProxySQL (query failed). Exiting."
  1151. reader_list=$(echo "$reader_list" | tr '\t' "$sep" | tr '\n' ' ')
  1152. reader_query=1
  1153. fi
  1154. if [[ -n $reader_list ]]; then
  1155. if echo $reader_list | grep -E -q "(^|[[:space:]])${prio_entry_re}($|[[:space:]])*"; then
  1156. # If this address is a reader, add a fake writer entry
  1157. # If detected to be online, the writer check algorithm
  1158. # will insert an entry
  1159. new_proxysql_list+=("${prio_entry}${sep}${HOSTGROUP_WRITER_ID}${sep}OFFLINE_SOFT${sep}WRITE${sep}PRIORITY_NODE")
  1160. fi
  1161. fi
  1162. fi
  1163. done
  1164. # Add the rest of the entries (not in the priority list but in proxysql)
  1165. # For this magic, see:
  1166. # https://stackoverflow.com/questions/7577052/bash-empty-array-expansion-with-set-u
  1167. if [[ -n ${priority_list[@]+"${priority_list[@]}"} ]]; then
  1168. local priority_string="${priority_list[@]}"
  1169. for row in ${proxysql_list}; do
  1170. local host=$(echo $row | cut -d "$sep" -f 1)
  1171. local port=$(echo $row | cut -d "$sep" -f 2)
  1172. local addr=$(combine_ip_port_into_address "$host" "$port")
  1173. # properly escape the characters for grep -E
  1174. addr_re="$(printf '%s' "$addr" | sed 's/[.[\*^$()+?{|]/\\&/g')"
  1175. if ! echo $priority_string | grep -E -q "(^|[[:space:]])${addr_re}($|[[:space:]])"; then
  1176. new_proxysql_list+=($row)
  1177. fi
  1178. done
  1179. fi
  1180. if [[ -n ${new_proxysql_list[@]+"${new_proxysql_list[@]}"} ]]; then
  1181. debug $LINENO "new priority list = ${new_proxysql_list[@]}"
  1182. echo "${new_proxysql_list[@]}"
  1183. fi
  1184. }
  1185. function update_writers() {
  1186. local reload_check_file=$1
  1187. local proxysql_list=""
  1188. local priority_list=""
  1189. # Nodes are orderd by status DESC first, this allows ONLINE nodes to always
  1190. # be processed first.
  1191. writer_proxysql_query="SELECT
  1192. writer.hostname,
  1193. writer.port,
  1194. writer.hostgroup_id,
  1195. writer.status,
  1196. writer.comment,
  1197. reader.status
  1198. FROM mysql_servers as writer
  1199. LEFT JOIN mysql_servers as reader
  1200. ON reader.hostgroup_id = $HOSTGROUP_READER_ID
  1201. AND reader.hostname = writer.hostname
  1202. AND reader.port = writer.port
  1203. WHERE writer.hostgroup_id = $HOSTGROUP_WRITER_ID
  1204. AND writer.status <> 'OFFLINE_HARD'
  1205. ORDER BY writer.status DESC"
  1206. proxysql_list=$(proxysql_exec $LINENO -Ns "$writer_proxysql_query")
  1207. check_cmd_and_exit $LINENO $? "Unable to obtain list of nodes from ProxySQL (query failed). Exiting."
  1208. if [[ $proxysql_list =~ [[:space:]]ONLINE[[:space:]]SLAVEREAD[[:space:]] ]]; then
  1209. HAVE_SLAVEWRITERS=1
  1210. fi
  1211. # Now that we have the proxysql list, order it by the priority list
  1212. # (with unprioritized nodes at the end)
  1213. # Using the priority list only makes sense for non-load balancing
  1214. if [[ $MODE != "loadbal" ]]; then
  1215. priority_list=$(get_host_priority_list "$cluster_name")
  1216. fi
  1217. if [[ -n $priority_list ]]; then
  1218. #
  1219. # Need to do some processing of the lists so that we can pass them down
  1220. # Assume that the fields cannot contain the ';' character'
  1221. # Can't use "local -n" becaus of Centos6 (needs newer bash version)
  1222. #
  1223. local prio_list=${priority_list}
  1224. local pxsql_list=$(echo "${proxysql_list[@]}" | tr '\t' ';' | tr '\n' ' ')
  1225. proxysql_list=$(build_proxysql_list_with_priority ";" "$pxsql_list" "$prio_list")
  1226. proxysql_list=$(echo "${proxysql_list}" | tr ' ' '\n' | tr ';' '\t')
  1227. fi
  1228. if [[ -z ${proxysql_list[@]+"${proxysql_list[@]}"} ]]; then
  1229. log $LINENO "No writers found."
  1230. return
  1231. fi
  1232. # Go through the list
  1233. #
  1234. while read line; do
  1235. if [[ -z $line ]]; then
  1236. continue
  1237. fi
  1238. server=$(echo -e "$line" | cut -f1)
  1239. port=$(echo -e "$line" | cut -f2)
  1240. hostgroup=$(echo -e "$line" | cut -f3)
  1241. stat=$(echo -e "$line" | cut -f4)
  1242. comment=$(echo -e "$line" | cut -f5)
  1243. rdstat=$(echo -e "$line" | cut -f6)
  1244. if [[ $comment == "SLAVEREAD" ]]; then
  1245. set_slave_status "${reload_check_file}" $hostgroup $server $port $stat
  1246. continue
  1247. fi
  1248. local wsrep_status
  1249. local pxc_main_mode
  1250. local result
  1251. local address
  1252. address=$(combine_ip_port_into_address "$server" "$port")
  1253. result=$(mysql_exec $LINENO "$server" "$port" -Nns "SHOW STATUS LIKE 'wsrep_local_state'; SHOW VARIABLES LIKE 'pxc_maint_mode';" 2>>${DEBUG_ERR_FILE})
  1254. wsrep_status=$(echo "$result" | grep "wsrep_local_state" | awk '{ print $2 }')
  1255. pxc_main_mode=$(echo "$result" | grep "pxc_maint_mode" | awk '{ print $2 }')
  1256. if [[ -z $wsrep_status ]]; then
  1257. wsrep_status="<unknown:query failed>"
  1258. fi
  1259. # For PXC 5.6 there is no pxc_maint_mode, so assume DISABLED
  1260. if [[ -z $pxc_main_mode ]]; then
  1261. pxc_main_mode="DISABLED"
  1262. fi
  1263. # If this node was added because of the priority list and the
  1264. # node is not reporting SYNCED, then just skip it
  1265. if [[ $rdstat == "PRIORITY_NODE" && $wsrep_status != "4" ]]; then
  1266. continue
  1267. fi
  1268. log "" "--> Checking WRITE server $hostgroup:$address, current status $stat, wsrep_local_state $wsrep_status"
  1269. # we have to limit amount of writers, WSREP status OK, AND node is marked ONLINE
  1270. # PXC and ProxySQL agreee on the status
  1271. # wsrep:ok pxc:-- status:online
  1272. if [ $NUMBER_WRITERS -gt 0 -a "${wsrep_status}" = "4" -a "$stat" == "ONLINE" -a "${pxc_main_mode}" == "DISABLED" ] ; then
  1273. if [[ $number_writers_online -lt $NUMBER_WRITERS ]]; then
  1274. number_writers_online=$(( $number_writers_online + 1 ))
  1275. log "" "server $hostgroup:$address is already ONLINE: ${number_writers_online} of ${NUMBER_WRITERS} write nodes"
  1276. else
  1277. number_writers_online=$(( $number_writers_online + 1 ))
  1278. change_server_status $LINENO $HOSTGROUP_WRITER_ID "$server" "$port" "OFFLINE_SOFT" "$rdstat" \
  1279. "max write nodes reached (${NUMBER_WRITERS})"
  1280. echo "1" > ${reload_check_file}
  1281. fi
  1282. fi
  1283. # WSREP status OK, but node is not marked ONLINE
  1284. # Make the node ONLINE if possible
  1285. # wsrep:ok pxc:ok status:not online
  1286. if [ "${wsrep_status}" = "4" -a "$stat" != "ONLINE" -a "${pxc_main_mode}" == "DISABLED" ] ; then
  1287. # we have to limit amount of writers
  1288. if [[ $NUMBER_WRITERS -gt 0 ]] ; then
  1289. if [[ $number_writers_online -lt $NUMBER_WRITERS ]]; then
  1290. number_writers_online=$(( $number_writers_online + 1 ))
  1291. change_server_status $LINENO $HOSTGROUP_WRITER_ID "$server" "$port" "ONLINE" "$rdstat" \
  1292. "${number_writers_online} of ${NUMBER_WRITERS} write nodes"
  1293. echo "1" > ${reload_check_file}
  1294. else
  1295. number_writers_online=$(( $number_writers_online + 1 ))
  1296. if [ "$stat" != "OFFLINE_SOFT" ]; then
  1297. change_server_status $LINENO $HOSTGROUP_WRITER_ID "$server" "$port" "OFFLINE_SOFT" "" \
  1298. "max write nodes reached (${NUMBER_WRITERS})"
  1299. echo "1" > ${reload_check_file}
  1300. elif [[ $rdstat != "PRIORITY_NODE" ]]; then
  1301. log $LINENO "server $hostgroup:$address is already OFFLINE_SOFT, max write nodes reached (${NUMBER_WRITERS})"
  1302. fi
  1303. fi
  1304. # we do not have to limit
  1305. elif [[ $NUMBER_WRITERS -eq 0 ]] ; then
  1306. # TODO: kennt, What if node is SHUNNED?
  1307. change_server_status $LINENO $HOSTGROUP_WRITER_ID "$server" "$port" "ONLINE" "$rdstat"\
  1308. "Changed state, marking write node ONLINE"
  1309. echo "1" > ${reload_check_file}
  1310. fi
  1311. fi
  1312. # WSREP status is not ok, but the node is marked online, we should put it offline
  1313. # wsrep:not ok pxc:-- status:online
  1314. if [ "${wsrep_status}" != "4" -a "$stat" = "ONLINE" ]; then
  1315. change_server_status $LINENO $HOSTGROUP_WRITER_ID "$server" "$port" "OFFLINE_SOFT" "" \
  1316. "WSREP status is ${wsrep_status} which is not ok"
  1317. echo "1" > ${reload_check_file}
  1318. # wsrep:-- pxc:not ok status:online
  1319. elif [ "${pxc_main_mode}" != "DISABLED" -a "$stat" = "ONLINE" ]; then
  1320. change_server_status $LINENO $HOSTGROUP_WRITER_ID "$server" "$port" "OFFLINE_SOFT" "" \
  1321. "pxc_maint_mode is $pxc_main_mode" 2>>${ERR_FILE}
  1322. echo "1" > ${reload_check_file}
  1323. # wsrep:not ok pxc:-- status:offline soft
  1324. elif [ "${wsrep_status}" != "4" -a "$stat" = "OFFLINE_SOFT" -a "$rdstat" != "PRIORITY_NODE" ]; then
  1325. log "" "server $hostgroup:$address is already OFFLINE_SOFT, WSREP status is ${wsrep_status} which is not ok"
  1326. # wsrep:-- pxc:not ok status:offline soft
  1327. elif [ "${pxc_main_mode}" != "DISABLED" -a "$stat" = "OFFLINE_SOFT" -a "$rdstat" != "PRIORITY_NODE" ]; then
  1328. log "" "server $hostgroup:$address is already OFFLINE_SOFT, pxc_maint_mode is ${pxc_main_mode} which is not ok"
  1329. fi
  1330. done< <(printf "${proxysql_list[@]}\n")
  1331. }
  1332. #
  1333. # This function checks the status of slave machines and sets their status field
  1334. #
  1335. # Globals:
  1336. # PROXSQL_DATADIR
  1337. # SLAVE_SECONDS_BEHIND
  1338. # HOSTGROUP_SLAVEREADER_ID
  1339. #
  1340. # Arguments:
  1341. # 1: Path to the reload_check_file
  1342. # 2: Slave hostgroup
  1343. # 3: Slave IP address
  1344. # 4: Slave port
  1345. # 5: Slave status in ProxySQL
  1346. #
  1347. function set_slave_status() {
  1348. debug $LINENO "START set_slave_status"
  1349. local reload_check_file=$1
  1350. local ws_hg_id=$2
  1351. local ws_ip=$3
  1352. local ws_port=$4
  1353. local ws_status=$5
  1354. local ws_address
  1355. ws_address=$(combine_ip_port_into_address "$ws_ip" "$ws_port")
  1356. local node_id="${ws_hg_id}:${ws_address}"
  1357. # This function will get and return a status of a slave node, 4=GOOD, 2=BEHIND, 0=OTHER
  1358. local slave_status
  1359. log $LINENO "--> Checking SLAVE server ${node_id}"
  1360. slave_status=$(mysql_exec $LINENO "$ws_ip" "$ws_port" -nsE "SHOW SLAVE STATUS")
  1361. check_cmd $LINENO $? "Cannot get status from the slave $ws_address, Please check cluster login credentials"
  1362. slave_status=$(echo "$slave_status" | sed 's/ //g')
  1363. echo "$slave_status" | grep "^Master_Host:" >/dev/null
  1364. if [ $? -ne 0 ];then
  1365. #
  1366. # No status was found, this is not replicating
  1367. # Only changing the status here as another node might be in the writer hostgroup
  1368. #
  1369. proxysql_exec $LINENO -Ns "UPDATE mysql_servers SET status = 'OFFLINE_HARD' WHERE hostname='$ws_ip' and port=$ws_port;"
  1370. check_cmd_and_exit $LINENO $? "Cannot update Galera Cluster node $ws_address to ProxySQL database (query failed). Exiting"
  1371. log_if_success $LINENO $? "slave server ${ws_address} set to OFFLINE_HARD status in ProxySQL (cannot determine slave status)."
  1372. echo "1" > ${reload_check_file}
  1373. else
  1374. local slave_master_host slave_io_running slave_sql_running seconds_behind
  1375. slave_master_host=$(echo "$slave_status" | grep "^Master_Host:" | cut -d: -f2)
  1376. slave_io_running=$(echo "$slave_status" | grep "^Slave_IO_Running:" | cut -d: -f2)
  1377. slave_sql_running=$(echo "$slave_status" | grep "^Slave_SQL_Running:" | cut -d: -f2)
  1378. seconds_behind=$(echo "$slave_status" | grep "^Seconds_Behind_Master:" | cut -d: -f2)
  1379. if [ "$seconds_behind" == "NULL" ];then
  1380. #
  1381. # When slave_io is not working, the seconds behind value will read 'NULL',
  1382. # convert this to a number higher than the max
  1383. #
  1384. let seconds_behind=SLAVE_SECONDS_BEHIND+1
  1385. fi
  1386. if [ "$slave_sql_running" != "Yes" ];then
  1387. #
  1388. # Slave is not replicating, so set to OFFLINE_HARD
  1389. #
  1390. if [ "$ws_status" != "OFFLINE_HARD" ];then
  1391. proxysql_exec $LINENO -Ns "UPDATE mysql_servers SET status = 'OFFLINE_HARD' WHERE hostname='$ws_ip' and port=$ws_port;"
  1392. check_cmd_and_exit $LINENO $? "Cannot update Galera Cluster node $ws_address to ProxySQL database (query failed). Exiting."
  1393. log_if_success $LINENO $? "slave server ${ws_address} set to OFFLINE_HARD status in ProxySQL (io:$slave_io_running sql:$slave_sql_running)."
  1394. echo "1" > ${reload_check_file}
  1395. else
  1396. log $LINENO "slave server (${ws_hg_id}:${ws_address}) current status '$ws_status' in ProxySQL. (io:$slave_io_running sql:$slave_sql_running)"
  1397. fi
  1398. elif [[ $slave_io_running == "Yes" ]]; then
  1399. #
  1400. # The slave is replicating (and the cluster is up)
  1401. # So set the status accordingly
  1402. #
  1403. if [ $seconds_behind -gt $SLAVE_SECONDS_BEHIND ];then
  1404. # Slave is more than the set number of seconds behind, return status 2
  1405. if [ "$ws_status" != "OFFLINE_SOFT" ];then
  1406. proxysql_exec $LINENO -Ns "UPDATE mysql_servers SET status = 'OFFLINE_SOFT' WHERE hostname='$ws_ip' and port=$ws_port;"
  1407. check_cmd_and_exit $LINENO $? "Cannot update Galera Cluster node $ws_address to ProxySQL database (query failed). Exiting."
  1408. log_if_success $LINENO $? "slave server ${ws_address} set to OFFLINE_SOFT status in ProxySQL (slave is too far behind:$seconds_behind). (io:$slave_io_running sql:$slave_sql_running)"
  1409. echo "1" > ${reload_check_file}
  1410. else
  1411. log $LINENO "slave server (${node_id}) current status '$ws_status' in ProxySQL. (io:$slave_io_running sql:$slave_sql_running)"
  1412. fi
  1413. else
  1414. #
  1415. # The slave is replicating and is caught up (relatively)
  1416. # So it is ok for READs
  1417. #
  1418. if [ "$ws_status" != "ONLINE" ];then
  1419. proxysql_exec $LINENO -Ns "UPDATE mysql_servers SET status = 'ONLINE' WHERE hostgroup_id=$HOSTGROUP_SLAVEREADER_ID AND hostname='$ws_ip' and port=$ws_port;"
  1420. check_cmd_and_exit $LINENO $? "Cannot update Galera Cluster node $ws_address in ProxySQL (query failed). Exiting."
  1421. log_if_success $LINENO $? "slave server $HOSTGROUP_SLAVEREADER_ID:${ws_address} set to ONLINE status in ProxySQL. (io:$slave_io_running sql:$slave_sql_running)"
  1422. if [[ $ws_hg_id -ne $HOSTGROUP_SLAVEREADER_ID ]]; then
  1423. log $LINENO "slave server (${node_id}) current status '$ws_status' in ProxySQL. (io:$slave_io_running sql:$slave_sql_running)"
  1424. fi
  1425. echo "1" > ${reload_check_file}
  1426. else
  1427. log $LINENO "slave server (${node_id}) current status '$ws_status' in ProxySQL. (io:$slave_io_running sql:$slave_sql_running)"
  1428. fi
  1429. fi
  1430. else
  1431. #
  1432. # Note: if slave_sql_running is YES and slave_io_running is NO
  1433. # This may indicate that the cluster is down, so we may move a
  1434. # slave to the WRITE hostgroup (but that is not done here).
  1435. # So leave it ONLINE in this state.
  1436. #
  1437. if [[ $ws_status == "ONLINE" ]]; then
  1438. log $LINENO "slave server ${ws_address} status:'${ws_status}' maintained in case the cluster is down. (io:$slave_io_running sql:$slave_sql_running)"
  1439. else
  1440. proxysql_exec $LINENO -Ns "UPDATE mysql_servers SET status = 'OFFLINE_SOFT' WHERE hostname='$ws_ip' and port=$ws_port;"
  1441. check_cmd_and_exit $LINENO $? "Unable to update mysql_servers (query failed). Exiting."
  1442. log $LINENO "slave server ${ws_address} status:'OFFLINE_SOFT'. (io:$slave_io_running sql:$slave_sql_running)"
  1443. echo "1" > ${reload_check_file}
  1444. fi
  1445. fi
  1446. fi
  1447. debug $LINENO "END set_slave_status"
  1448. }
  1449. function update_readers() {
  1450. local reload_check_file=$1
  1451. if [[ $WRITER_IS_READER != "ondemand" ]]; then
  1452. reader_proxysql_query="SELECT hostgroup_id,
  1453. hostname,
  1454. port,
  1455. status,
  1456. comment,
  1457. 'NULL'
  1458. FROM mysql_servers
  1459. WHERE hostgroup_id IN ($HOSTGROUP_READER_ID)
  1460. AND status <> 'OFFLINE_HARD'
  1461. ORDER BY weight DESC, hostname, port"
  1462. elif [[ $WRITER_IS_READER == "ondemand" ]]; then
  1463. # We will not try to change reader state of nodes that are writer ONLINE,
  1464. # so what we do is we ORDER BY writer.status ASC because by accident ONLINE
  1465. # is last in the line
  1466. reader_proxysql_query="SELECT reader.hostgroup_id,
  1467. reader.hostname,
  1468. reader.port,
  1469. reader.status,
  1470. reader.comment,
  1471. writer.status
  1472. FROM mysql_servers as reader
  1473. LEFT JOIN mysql_servers as writer
  1474. ON writer.hostgroup_id = $HOSTGROUP_WRITER_ID
  1475. AND writer.hostname = reader.hostname
  1476. AND writer.port = reader.port
  1477. WHERE reader.hostgroup_id = $HOSTGROUP_READER_ID
  1478. ORDER BY writer.status ASC,
  1479. reader.weight DESC,
  1480. reader.hostname,
  1481. reader.port"
  1482. fi
  1483. # This is the count of nodes that have readers with ONLINE status
  1484. # and writers that are not ONLINE (either no entry or !ONLINE)
  1485. local online_readonly_nodes_found=0
  1486. local query_result
  1487. query_result=$(proxysql_exec $LINENO -Ns "$reader_proxysql_query")
  1488. check_cmd_and_exit $LINENO $? "Unable to obtain list of nodes from ProxySQL (query failed). Exiting."
  1489. if [[ $query_result =~ [[:space:]]SLAVEREAD[[:space:]] ]]; then
  1490. HAVE_SLAVEREADERS=1
  1491. fi
  1492. while read line; do
  1493. if [[ -z $line ]]; then
  1494. continue
  1495. fi
  1496. hostgroup=$(echo "$line" | cut -f1)
  1497. server=$(echo "$line" | cut -f2)
  1498. port=$(echo "$line" | cut -f3)
  1499. stat=$(echo "$line" | cut -f4)
  1500. comment=$(echo "$line" | cut -f5)
  1501. writer_stat=$(echo "$line" | cut -f6)
  1502. if [[ $comment == "SLAVEREAD" ]]; then
  1503. set_slave_status "${reload_check_file}" $hostgroup $server $port $stat
  1504. continue
  1505. fi
  1506. if [[ $stat == "OFFLINE_HARD" ]]; then
  1507. continue
  1508. fi
  1509. local wsrep_status
  1510. local pxc_main_mode
  1511. local result
  1512. local address
  1513. address=$(combine_ip_port_into_address "$server" "$port")
  1514. result=$(mysql_exec $LINENO "$server" "$port" -Nns "SHOW STATUS LIKE 'wsrep_local_state'; SHOW VARIABLES LIKE 'pxc_maint_mode';" 2>>${DEBUG_ERR_FILE})
  1515. wsrep_status=$(echo "$result" | grep "wsrep_local_state" | awk '{ print $2 }')
  1516. pxc_main_mode=$(echo "$result" | grep "pxc_maint_mode" | awk '{ print $2 }')
  1517. if [[ -z $wsrep_status ]]; then
  1518. wsrep_status="<unknown:query failed>"
  1519. fi
  1520. # For PXC 5.6 there is no pxc_maint_mode, so assume DISABLED
  1521. if [[ -z $pxc_main_mode ]]; then
  1522. pxc_main_mode="DISABLED"
  1523. fi
  1524. log "" "--> Checking READ server $hostgroup:$address, current status $stat, wsrep_local_state $wsrep_status"
  1525. if [[ $WRITER_IS_READER == "ondemand" && $writer_stat == "ONLINE" ]] ; then
  1526. if [ $online_readonly_nodes_found -eq 0 ] ; then
  1527. # WSREP:ok PXC:ok STATUS:online
  1528. if [ "${wsrep_status}" = "4" -a "$stat" == "ONLINE" -a "${pxc_main_mode}" == "DISABLED" ] ; then
  1529. log "" "server $hostgroup:$address is already ONLINE, is also write node in ONLINE state, not enough non-ONLINE readers found"
  1530. fi
  1531. # WSREP:ok PXC:ok STATUS:not online
  1532. if [ "${wsrep_status}" = "4" -a "$stat" != "ONLINE" -a "${pxc_main_mode}" == "DISABLED" ] ; then
  1533. #
  1534. # Enable the first one found as ONLINE
  1535. # (when writer-is-reader=ondemand)
  1536. #
  1537. change_server_status $LINENO $HOSTGROUP_READER_ID "$server" "$port" "ONLINE" ""\
  1538. "marking ONLINE write node as read ONLINE state, not enough non-ONLINE readers found"
  1539. echo "1" > ${reload_check_file}
  1540. fi
  1541. else
  1542. # WSREP:ok PXC:ok STATUS:online
  1543. if [ "${wsrep_status}" = "4" -a "$stat" == "ONLINE" -a "${pxc_main_mode}" == "DISABLED" ] ; then
  1544. # Else disable the other READ nodes
  1545. change_server_status $LINENO $HOSTGROUP_READER_ID "$server" "$port" "OFFLINE_SOFT" ""\
  1546. "making ONLINE writer node as read OFFLINE_SOFT as well because writers should not be readers"
  1547. echo "1" > ${reload_check_file}
  1548. fi
  1549. # WSREP:ok PXC:ok STATUS:not online
  1550. if [ "${wsrep_status}" = "4" -a "$stat" != "ONLINE" -a "${pxc_main_mode}" == "DISABLED" ] ; then
  1551. log "" "server $hostgroup:$address is $stat, keeping node as $stat,as it is an ONLINE writer and we prefer not to have writers as readers (writer-is-reader:ondemand)"
  1552. fi
  1553. fi
  1554. else
  1555. # WSREP:ok PXC:ok STATUS:online
  1556. if [ "${wsrep_status}" = "4" -a "$stat" == "ONLINE" -a "${pxc_main_mode}" == "DISABLED" ] ; then
  1557. log "" "server $hostgroup:$address is already ONLINE"
  1558. online_readonly_nodes_found=$(( $online_readonly_nodes_found + 1 ))
  1559. # WSREP:ok PXC:not ok STATUS:not online
  1560. elif [ "${wsrep_status}" = "4" -a "$stat" != "ONLINE" -a "${pxc_main_mode}" != "DISABLED" ] ; then
  1561. log "" "server $hostgroup:$address is $stat"
  1562. fi
  1563. # WSREP status OK, but node is not marked ONLINE
  1564. # WSREP:ok PXC:ok STATUS:not online
  1565. if [ "${wsrep_status}" = "4" -a "$stat" != "ONLINE" -a "${pxc_main_mode}" == "DISABLED" ] ; then
  1566. change_server_status $LINENO $HOSTGROUP_READER_ID "$server" "$port" "ONLINE" ""\
  1567. "changed state"
  1568. echo "1" > ${reload_check_file}
  1569. online_readonly_nodes_found=$(( $online_readonly_nodes_found + 1 ))
  1570. fi
  1571. fi
  1572. # WSREP status is not ok, but the node is marked online, we should put it offline
  1573. # WSREP:not ok STATUS:online
  1574. if [ "${wsrep_status}" != "4" -a "$stat" = "ONLINE" ]; then
  1575. change_server_status $LINENO $HOSTGROUP_READER_ID "$server" "$port" "OFFLINE_SOFT" ""\
  1576. "WSREP status is ${wsrep_status} which is not ok"
  1577. echo "1" > ${reload_check_file}
  1578. # PXC:not ok STATUS:online
  1579. elif [ "${pxc_main_mode}" != "DISABLED" -a "$stat" = "ONLINE" ];then
  1580. change_server_status $LINENO $HOSTGROUP_READER_ID "$server" "$port" "OFFLINE_SOFT" ""\
  1581. "pxc_maint_mode is $pxc_main_mode" 2>>${ERR_FILE}
  1582. echo "1" > ${reload_check_file}
  1583. # WSREP:not ok STATUS:offline soft
  1584. elif [ "${wsrep_status}" != "4" -a "$stat" = "OFFLINE_SOFT" ]; then
  1585. log "" "server $hostgroup:$address is already OFFLINE_SOFT, WSREP status is ${wsrep_status} which is not ok"
  1586. fi
  1587. done< <(printf "$query_result\n")
  1588. }
  1589. # Looks specifically for nodes that are in the DONOR/DESYNCED(2) state
  1590. #
  1591. # Globals:
  1592. # NUMBER_WRITERS
  1593. # HOSTGROUP_WRITER_ID
  1594. #
  1595. # Arguments:
  1596. # None
  1597. #
  1598. function search_for_desynced_writers() {
  1599. local reload_check_file=$1
  1600. local cnt=0
  1601. local sort_order="ASC"
  1602. # We want the writers to come before the readers
  1603. if [[ $HOSTGROUP_WRITER_ID -gt $HOSTGROUP_READER_ID ]]; then
  1604. sort_order="DESC"
  1605. fi
  1606. local writer_query="SELECT hostgroup_id, hostname, port, status
  1607. FROM mysql_servers
  1608. WHERE hostgroup_id IN ($HOSTGROUP_WRITER_ID,$HOSTGROUP_READER_ID)
  1609. AND status <> 'OFFLINE_HARD'
  1610. AND comment <> 'SLAVEREAD'
  1611. ORDER BY hostgroup_id ${sort_order}"
  1612. query_result=$(proxysql_exec $LINENO -Ns "$writer_query")
  1613. check_cmd_and_exit $LINENO $? "Could not get the list of nodes (query failed). Exiting."
  1614. while read line; do
  1615. if [[ -z $line ]]; then
  1616. continue
  1617. fi
  1618. hostgroup=$(echo "$line" | cut -f1)
  1619. server=$(echo "$line" | cut -f2)
  1620. port=$(echo "$line" | cut -f3)
  1621. stat=$(echo "$line" | cut -f4)
  1622. safety_cnt=0
  1623. while [ ${cnt} -lt $NUMBER_WRITERS -a ${safety_cnt} -lt 5 ]
  1624. do
  1625. local wsrep_status
  1626. local pxc_main_mode
  1627. local result
  1628. local address
  1629. address=$(combine_ip_port_into_address "$server" "$port")
  1630. result=$(mysql_exec $LINENO "$server" "$port" -Nns "SHOW STATUS LIKE 'wsrep_local_state'; SHOW VARIABLES LIKE 'pxc_maint_mode';" 2>>${DEBUG_ERR_FILE})
  1631. wsrep_status=$(echo "$result" | grep "wsrep_local_state" | awk '{ print $2 }')
  1632. pxc_main_mode=$(echo "$result" | grep "pxc_maint_mode" | awk '{ print $2 }')
  1633. if [[ -z $wsrep_status ]]; then
  1634. wsrep_status="<unknown:query failed>"
  1635. fi
  1636. # PXC 5.6 does not have this, so default to DISABLED
  1637. if [[ -z $pxc_main_mode ]]; then
  1638. pxc_main_mode="DISABLED"
  1639. fi
  1640. # Nodes in maintenance are not allowed
  1641. if [[ $pxc_main_mode != "DISABLED" ]]; then
  1642. log "" "Skipping $hostgroup:$address node is in pxc_maint_mode:$pxc_main_mode"
  1643. break
  1644. fi
  1645. log "" "Checking $hostgroup:$address for node in DONOR state, status $stat , wsrep_local_state $wsrep_status"
  1646. if [ "${wsrep_status}" = "2" -a "$stat" != "ONLINE" ]; then
  1647. # if we are on Donor/Desync and not online in mysql_servers -> proceed
  1648. # If we do not have a writer row, we have to add it
  1649. local writer_count=$(proxysql_exec $LINENO -Ns "SELECT count(*) FROM mysql_servers WHERE hostgroup_id=$HOSTGROUP_WRITER_ID AND hostname='$server' AND port=$port")
  1650. check_cmd_and_exit $LINENO $? "Could not get writer count (query failed). Exiting."
  1651. if [[ $writer_count -eq 0 ]]; then
  1652. proxysql_exec $LINENO -Ns \
  1653. "INSERT INTO mysql_servers (hostname,hostgroup_id,port,weight,comment,max_connections)
  1654. VALUES ('$server',$HOSTGROUP_WRITER_ID,$port,1000000,'WRITE',$MAX_CONNECTIONS);"
  1655. check_cmd_and_exit $LINENO $? "Could not add writer node (query failed). Exiting."
  1656. log $LINENO "Adding server $HOSTGROUP_WRITER_ID:$address with status ONLINE. Reason: WSREP status is DESYNC/DONOR, as this is the only node we will put this one online"
  1657. else
  1658. change_server_status $LINENO $HOSTGROUP_WRITER_ID "$server" "$port" "ONLINE" ""\
  1659. "WSREP status is DESYNC/DONOR, as this is the only node we will put this one online"
  1660. fi
  1661. cnt=$(( $cnt + 1 ))
  1662. local proxy_runtime_status
  1663. proxy_runtime_status=$(proxysql_exec $LINENO -Ns "SELECT status FROM runtime_mysql_servers WHERE hostname='${server}' AND port='${port}' AND hostgroup_id='${hostgroup}'")
  1664. check_cmd_and_exit $LINENO $? "Could not get writer node status (query failed). Exiting."
  1665. if [ "${proxy_runtime_status}" != "ONLINE" ]; then
  1666. # if we are not online in runtime_mysql_servers, proceed to change
  1667. # the server status and reload mysql_servers
  1668. echo "1" > ${reload_check_file}
  1669. fi
  1670. # TODO: kennt, this doesn't work. We will go through the upper
  1671. # loop and move the writer to OFFLINE_SOFT (since it's desynced).
  1672. # We would have to detect that state (then we could move it to 0).
  1673. # Or we could only force the update if the tables are the same.
  1674. # (But only for the descyned node case).
  1675. # Maybe we can compare the table to itself, no updates needed if it
  1676. # hasn't changed.
  1677. # Note: If the node in the runtime is already ONLINE, then we don't
  1678. # need to change the reload_check_file to 1
  1679. # So if there was no change to the state, we will skip uploading
  1680. # the in-memory tables and nothing will change. (This only makes
  1681. # sense if all the nodes are already down). If any of the nodes are
  1682. # up, this node will be moved to OFFLINE_SOFT since it is not in
  1683. # the SYNCED(4) state.
  1684. fi
  1685. safety_cnt=$(( $safety_cnt + 1 ))
  1686. done
  1687. done< <(printf "$query_result\n")
  1688. }
  1689. #
  1690. #
  1691. # Globals:
  1692. # HOSTGROUP_READER_ID
  1693. #
  1694. # Arguments:
  1695. # None
  1696. #
  1697. function search_for_desynced_readers() {
  1698. local reload_check_file=$1
  1699. local cnt=0
  1700. query_result=$(proxysql_exec $LINENO -Ns "SELECT hostgroup_id, hostname, port, status FROM mysql_servers WHERE hostgroup_id IN ($HOSTGROUP_READER_ID) AND status <> 'OFFLINE_HARD' AND comment <> 'SLAVEREAD'")
  1701. check_cmd_and_exit $LINENO $? "Could not get the list of nodes (query failed). Exiting."
  1702. while read line; do
  1703. if [[ -z $line ]]; then
  1704. continue
  1705. fi
  1706. hostgroup=$(echo "$line" | cut -f1)
  1707. server=$(echo "$line" | cut -f2)
  1708. port=$(echo "$line" | cut -f3)
  1709. stat=$(echo "$line" | cut -f4)
  1710. local safety_cnt=0
  1711. while [[ ${cnt} -eq 0 && ${safety_cnt} -lt 5 ]]
  1712. do
  1713. local wsrep_status
  1714. local pxc_main_mode
  1715. local result
  1716. local address
  1717. address=$(combine_ip_port_into_address "$server" "$port")
  1718. result=$(mysql_exec $LINENO "$server" "$port" -Nns "SHOW STATUS LIKE 'wsrep_local_state'; SHOW VARIABLES LIKE 'pxc_maint_mode';" 2>>${DEBUG_ERR_FILE})
  1719. wsrep_status=$(echo "$result" | grep "wsrep_local_state" | awk '{ print $2 }')
  1720. pxc_main_mode=$(echo "$result" | grep "pxc_maint_mode" | awk '{ print $2 }')
  1721. if [[ -z $wsrep_status ]]; then
  1722. wsrep_status="<unknown:query failed>"
  1723. fi
  1724. # PXC 5.6 does not have this, so default to DISABLED
  1725. if [[ -z $pxc_main_mode ]]; then
  1726. pxc_main_mode="DISABLED"
  1727. fi
  1728. # Nodes in maintenance are not allowed
  1729. if [[ $pxc_main_mode != "DISABLED" ]]; then
  1730. log "" "Skipping $hostgroup:$address node is in pxc_maint_mode:$pxc_main_mode"
  1731. break
  1732. fi
  1733. log "" "Checking $hostgroup:$address for node in DONOR state, status $stat , wsrep_local_state $wsrep_status"
  1734. if [ "${wsrep_status}" = "2" -a "$stat" != "ONLINE" ];then
  1735. # if we are on Donor/Desync an not online in mysql_servers -> proceed
  1736. change_server_status $LINENO $HOSTGROUP_READER_ID "$server" "$port" "ONLINE" ""\
  1737. "WSREP status is DESYNC/DONOR, as this is the only node we will put this one online"
  1738. cnt=$(( $cnt + 1 ))
  1739. local proxy_runtime_status
  1740. proxy_runtime_status=$(proxysql_exec $LINENO -Ns "SELECT status FROM runtime_mysql_servers WHERE hostname='${server}' AND port='${port}' AND hostgroup_id='${hostgroup}'")
  1741. check_cmd_and_exit $LINENO $? "Could not get the runtime server status (query failed). Exiting."
  1742. if [ "${proxy_runtime_status}" != "ONLINE" ]; then
  1743. # if we are not online in runtime_mysql_servers,
  1744. # proceed to change the server status and reload mysql_servers
  1745. echo "1" > ${reload_check_file}
  1746. fi
  1747. # Note: If the node in the runtime is already ONLINE, then we don't
  1748. # need to change the reload_check_file to 1
  1749. # So if there was no change to the state, we will skip uploading
  1750. # the in-memory tables and nothing will change. (This only makes
  1751. # sense if all the nodes are already down). If any of the nodes are
  1752. # up, this node will be moved to OFFLINE_SOFT since it is not in
  1753. # the SYNCED(4) state.
  1754. break 2
  1755. fi
  1756. safety_cnt=$(( $safety_cnt + 1 ))
  1757. done
  1758. done< <(printf "$query_result\n")
  1759. }
  1760. # Saves the reload_check_file value and resets it to 0
  1761. #
  1762. # Globals:
  1763. # None
  1764. #
  1765. # Arguments:
  1766. # 1: path to the reload_check_file
  1767. #
  1768. function save_reload_check() {
  1769. local reload_check_file=$1
  1770. local save_state
  1771. save_state=$(cat "${reload_check_file}")
  1772. echo 0 > "${reload_check_file}"
  1773. echo "${save_state}"
  1774. }
  1775. # Resets the restore_reload_check value if needed
  1776. # If nothing has changed, restores the value
  1777. #
  1778. # Globals:
  1779. # None
  1780. #
  1781. # Arguments:
  1782. # 1: Path to the reload_check_file
  1783. # 2: The saved (previous) value
  1784. #
  1785. # Returns:
  1786. # Returns 0 (success) if something changed
  1787. # Else returns 1
  1788. #
  1789. function restore_reload_check() {
  1790. local reload_check_file=$1
  1791. local save_state=$2
  1792. # Default return value is failure (non-zero)
  1793. local rc=1
  1794. if [[ $(cat ${reload_check_file}) -ne 0 ]] ; then
  1795. save_state=1
  1796. # A success means that something changed
  1797. rc=0
  1798. fi
  1799. echo "${save_state}" > "${reload_check_file}"
  1800. return $rc
  1801. }
  1802. # Adds slaves to the write hostgroup if needed
  1803. #
  1804. # Globals:
  1805. # HOSTGROUP_WRITER_ID
  1806. # HOSTGROUP_SLAVEREADER_ID
  1807. #
  1808. # Arguments:
  1809. # None
  1810. #
  1811. function add_slave_to_write_hostgroup() {
  1812. # General outline:
  1813. # Delete all non-ONLINE slaves to the read hostgroup
  1814. # Check for an ONLINE slave in the write hostgroup
  1815. # If there is none, add a random slave to the write hostgroup
  1816. # If cannot find an ONLINE, look for OFFLINE_SOFT (emergency only)
  1817. local reload_check_file=$1
  1818. local -i online_count=0
  1819. local -i offline_count=0
  1820. local query_result=""
  1821. query_result=$(proxysql_exec $LINENO -Ns "SELECT status FROM mysql_servers
  1822. WHERE hostgroup_id=$HOSTGROUP_WRITER_ID
  1823. AND comment = 'SLAVEREAD'")
  1824. check_cmd_and_exit $LINENO $? "Could not get the list of slave writers (query failed). Exiting."
  1825. # Count # of online vs offline slave nodes
  1826. local status
  1827. while read line; do
  1828. if [[ -z $line ]]; then
  1829. continue
  1830. fi
  1831. status=$(echo $line | awk '{ print $1 }')
  1832. if [[ $status = 'ONLINE' ]]; then
  1833. online_count+=1
  1834. else
  1835. offline_count+=1
  1836. fi
  1837. done< <(printf "$query_result\n")
  1838. # Remove any nodes that have been moved OFFLINE
  1839. if [[ $offline_count -gt 0 ]]; then
  1840. proxysql_exec $LINENO -Ns "DELETE FROM mysql_servers
  1841. WHERE hostgroup_id=$HOSTGROUP_WRITER_ID
  1842. AND status != 'ONLINE'
  1843. AND comment = 'SLAVEREAD'"
  1844. check_cmd_and_exit $LINENO $? "Failed to remove all non-ONLINE slaves acting as writers (query failed). Exiting."
  1845. log_if_success $LINENO $? "Removed all non-ONLINE slaves acting as writers"
  1846. echo 1 > "${reload_check_file}"
  1847. fi
  1848. # If there is an active slave writer node, no need to add another node
  1849. if [[ $online_count -eq 1 ]]; then
  1850. log $LINENO "Async-slave already ONLINE"
  1851. return
  1852. fi
  1853. if [[ $online_count -eq 0 ]]; then
  1854. # There are no ONLINE slaves, so add a random one from the
  1855. # list of ONLINE reader slaves
  1856. local next_host host port
  1857. next_host=$(proxysql_exec $LINENO -Ns "select hostname,port FROM mysql_servers
  1858. WHERE status='ONLINE'
  1859. AND comment = 'SLAVEREAD'
  1860. AND hostgroup_id='$HOSTGROUP_SLAVEREADER_ID'
  1861. ORDER BY random() LIMIT 1")
  1862. check_cmd_and_exit $LINENO $? "Could not get info for a slave node (query failed). Exiting."
  1863. # Emergency situation, if there are no ONLINE hosts,
  1864. # look for OFFLINE_SOFT hosts
  1865. if [[ -z $next_host ]]; then
  1866. next_host=$(proxysql_exec $LINENO -Ns "select hostname,port FROM mysql_servers
  1867. WHERE status='OFFLINE_SOFT'
  1868. AND comment = 'SLAVEREAD'
  1869. AND hostgroup_id='$HOSTGROUP_SLAVEREADER_ID'
  1870. ORDER BY random() LIMIT 1")
  1871. check_cmd_and_exit $LINENO $? "Could not get info for a slave node (query failed). Exiting."
  1872. if [[ -n $next_host ]]; then
  1873. local host=$(echo "$next_host" | awk '{ print $1 }')
  1874. local port=$(echo "$next_host" | awk '{ print $2 }')
  1875. local address=$(combine_ip_port_into_address "$host" "$port")
  1876. # Found a node, update the READER to ONLINE
  1877. proxysql_exec $LINENO -Ns "UPDATE mysql_servers
  1878. SET status='ONLINE'
  1879. WHERE hostgroup_id=$HOSTGROUP_SLAVEREADER_ID
  1880. AND hostname='$host'
  1881. AND port=$port"
  1882. check_cmd_and_exit $LINENO $? "Could not update the info for a slave node (query failed). Exiting."
  1883. log_if_success $LINENO $? "slave server ${HOSTGROUP_SLAVEREADER_ID}:$address set to ONLINE status in ProxySQL."
  1884. echo 1 > "${reload_check_file}"
  1885. fi
  1886. fi
  1887. if [[ -n $next_host ]]; then
  1888. local host=$(echo "$next_host" | awk '{ print $1 }')
  1889. local port=$(echo "$next_host" | awk '{ print $2 }')
  1890. local address=$(combine_ip_port_into_address "$host" "$port")
  1891. proxysql_exec $LINENO -Ns "INSERT INTO mysql_servers
  1892. (hostname,hostgroup_id,port,weight,status,comment,max_connections)
  1893. VALUES ('$host',$HOSTGROUP_WRITER_ID,$port,1000000,'ONLINE','SLAVEREAD',$MAX_CONNECTIONS);"
  1894. check_cmd_and_exit $LINENO $? "Cannot add Galera Cluster node $address to ProxySQL (query failed). Exiting."
  1895. log_if_success $LINENO $? "slave server ${HOSTGROUP_WRITER_ID}:$address set to ONLINE status in ProxySQL."
  1896. echo 1 > "${reload_check_file}"
  1897. else
  1898. log $LINENO "Could not find any slave readers to promote to a writer"
  1899. fi
  1900. fi
  1901. }
  1902. # Removes slaves from the write hostgroup
  1903. # (Actually moves the writers to OFFLINE_SOFT)
  1904. #
  1905. # Globals:
  1906. # HOSTGROUP_WRITER_ID
  1907. #
  1908. # Arguments:
  1909. # None
  1910. #
  1911. function remove_slave_from_write_hostgroup() {
  1912. local reload_check_file=$1
  1913. log $LINENO "Removing async-slaves from the writegroup"
  1914. # Move all writer slaves to OFFLINE_SOFT
  1915. proxysql_exec $LINENO -Ns "UPDATE mysql_servers
  1916. SET status = 'OFFLINE_SOFT'
  1917. WHERE hostgroup_id = $HOSTGROUP_WRITER_ID
  1918. AND comment = 'SLAVEREAD'"
  1919. check_cmd_and_exit $LINENO $? "Failed to move slave writers to OFFLINE_SOFT (query failed). Exiting."
  1920. log_if_success $LINENO $? "Moved slave writers to OFFLINE_SOFT"
  1921. echo 1 > "${reload_check_file}"
  1922. }
  1923. #
  1924. # Globals:
  1925. # TIMEOUT
  1926. # MYSQL_USERNAME MYSQL_PASSWORD MYSQL_HOSTNAME MYSQL_PORT
  1927. # PROXYSQL_DATADIR
  1928. # HOSTGROUP_READER_ID HOSTGROUP_WRITER_ID
  1929. # CONFIG_FILE
  1930. # NUMBER_WRITERS
  1931. #
  1932. function main() {
  1933. local cluster_name=""
  1934. local mysql_credentials
  1935. local scheduler_id
  1936. # If this call fails, exit out. We can't do anything without the monitor
  1937. # credentials. (Or if we can't connect to proxysql).
  1938. mysql_credentials=$(proxysql_exec $LINENO -Ns "SELECT variable_value FROM global_variables WHERE variable_name IN ('mysql-monitor_username','mysql-monitor_password') ORDER BY variable_name DESC" "hide_output")
  1939. check_cmd_and_exit $LINENO $? "Unable to obtain MySQL credentials from ProxySQL (query failed). Exiting."
  1940. MYSQL_USERNAME=$(echo $mysql_credentials | awk '{print $1}')
  1941. MYSQL_PASSWORD=$(echo $mysql_credentials | awk '{print $2}')
  1942. # Search for the scheduler id that corresponds to our write hostgroup
  1943. scheduler_id=$(proxysql_exec $LINENO -Ns "SELECT id FROM scheduler where arg1 LIKE '%--write-hg=$HOSTGROUP_WRITER_ID %' OR arg1 LIKE '%-w $HOSTGROUP_WRITER_ID %'")
  1944. check_cmd_and_exit $LINENO $? "Could not retreive scheduler row (query failed). Exiting."
  1945. if [[ -z $scheduler_id ]]; then
  1946. error $LINENO "Cannot find the scheduler row with write hostgroup : $HOSTGROUP_WRITER_ID"
  1947. else
  1948. cluster_name=$(proxysql_exec $LINENO -Ns "SELECT comment FROM scheduler WHERE id=${scheduler_id}" 2>>$ERR_FILE)
  1949. check_cmd_and_exit $LINENO $? "Cannot get the cluster name from ProxySQL (query failed). Exiting."
  1950. fi
  1951. if [[ -z $cluster_name ]]; then
  1952. #
  1953. # Could not find the cluster name from the scheduler,
  1954. # contact the cluster directly
  1955. #
  1956. local available_host=""
  1957. local server port
  1958. # Find a PXC host that's we can connect to
  1959. available_host=$(find_online_cluster_host)
  1960. check_cmd_and_exit $LINENO $? "Cannot get the list of nodes in the cluster from ProxySQL (query failed). Exiting"
  1961. if [[ -z $available_host ]]; then
  1962. error $LINENO "Cannot contact a PXC host in hostgroups($HOSTGROUP_WRITER_ID, $HOSTGROUP_READER_ID)"
  1963. else
  1964. server=$(echo $available_host | awk '{print $1}')
  1965. port=$(echo $available_host | awk '{print $2}')
  1966. cluster_name=$(mysql_exec $LINENO "$server" "$port" -Nn \
  1967. "SELECT @@wsrep_cluster_name" 2>>${ERR_FILE} | tail -1)
  1968. fi
  1969. if [[ ! -z $cluster_name ]]; then
  1970. #
  1971. # We've found the cluster name so update the scheduler args
  1972. #
  1973. if [[ -z $scheduler_id ]]; then
  1974. warning "$LINENO" "Cannot update scheduler due to missing scheduler_id"
  1975. else
  1976. local arg1 my_path
  1977. log "$LINENO" "Updating scheduler for cluster:${cluster_name} write_hg:$HOSTGROUP_WRITER_ID"
  1978. arg1=$(proxysql_exec $LINENO -Ns "SELECT arg1 from scheduler where id=${scheduler_id}")
  1979. check_cmd_and_exit $LINENO $? "Could not get arg1 from scheduler from (query failed)" "Please check ProxySQL credentials and status."
  1980. if [[ -z $arg1 ]]; then
  1981. warning $LINENO "Cannot update scheduler due to missing arguments (arg1 is empty)"
  1982. else
  1983. my_path=$(echo ${PROXYSQL_DATADIR}/${cluster_name}_proxysql_galera_check.log | sed 's#\/#\\\/#g')
  1984. arg1=$(echo $arg1 | sed "s/--log=.*/--log=$my_path/g")
  1985. proxysql_exec $LINENO -Ns "UPDATE scheduler set comment='$cluster_name',arg1='$arg1' where id=${scheduler_id};load scheduler to runtime;save scheduler to disk"
  1986. check_cmd_and_exit $LINENO $? "Could not update scheduler from (query failed). Exiting."
  1987. fi
  1988. fi
  1989. fi
  1990. fi
  1991. # Check to see if there are other proxysql_galera_checkers running
  1992. # Before we can check, we need the cluster name
  1993. check_is_galera_checker_running "$cluster_name"
  1994. local mode=$MODE
  1995. if [[ ! -z $P_MODE ]] ; then
  1996. mode=$P_MODE
  1997. else
  1998. local proxysql_mode_file
  1999. if [[ -z $cluster_name ]]; then
  2000. proxysql_mode_file="${PROXYSQL_DATADIR}/mode"
  2001. else
  2002. proxysql_mode_file="${PROXYSQL_DATADIR}/${cluster_name}_mode"
  2003. fi
  2004. if [[ ! -f ${proxysql_mode_file} ]]; then
  2005. local mode_check
  2006. mode_check=$(proxysql_exec $LINENO -Ns "SELECT comment from mysql_servers where comment='WRITE' and hostgroup_id in ($HOSTGROUP_WRITER_ID, $HOSTGROUP_READER_ID)")
  2007. if [[ "$mode_check" == "WRITE" ]]; then
  2008. echo "singlewrite" > ${proxysql_mode_file}
  2009. else
  2010. echo "loadbal" > ${proxysql_mode_file}
  2011. fi
  2012. fi
  2013. if [[ -r $proxysql_mode_file ]]; then
  2014. mode=$(cat ${proxysql_mode_file})
  2015. fi
  2016. fi
  2017. MODE=$mode
  2018. # Running proxysql_node_monitor script.
  2019. # First try the same directory as this script
  2020. local monitor_dir
  2021. monitor_dir=$(cd $(dirname $0) && pwd)
  2022. if [[ ! -f $monitor_dir/proxysql_node_monitor ]]; then
  2023. # Cannot find it in same directory, try default location
  2024. monitor_dir="/usr/bin"
  2025. if [[ ! -f $monitor_dir/proxysql_node_monitor ]]; then
  2026. log "" "ERROR! Could not find proxysql_node_monitor. Terminating"
  2027. exit 1
  2028. fi
  2029. fi
  2030. # If the reload_check_file contains 1, then there was a change
  2031. # made to the state and we need to upload the MYSQL SERVERS to runtime.
  2032. # This is used because changes are made to the MYSQL SERVERS table
  2033. # in other scripts/subshells.
  2034. local reload_check_file
  2035. if [[ -z $cluster_name ]]; then
  2036. reload_check_file="${PROXYSQL_DATADIR}/reload"
  2037. else
  2038. reload_check_file="${PROXYSQL_DATADIR}/${cluster_name}_reload"
  2039. fi
  2040. echo "0" > ${reload_check_file}
  2041. # Run the monitor script
  2042. local proxysql_monitor_log
  2043. if [[ -n $NODE_MONITOR_LOG_FILE ]]; then
  2044. proxysql_monitor_log=$NODE_MONITOR_LOG_FILE
  2045. else
  2046. if [[ -z $cluster_name ]]; then
  2047. proxysql_monitor_log="${PROXYSQL_DATADIR}/proxysql_node_monitor.log"
  2048. else
  2049. proxysql_monitor_log="${PROXYSQL_DATADIR}/${cluster_name}_proxysql_node_monitor.log"
  2050. fi
  2051. fi
  2052. local more_monitor_options=""
  2053. if [[ $DEBUG -ne 0 ]]; then
  2054. more_monitor_options+=" --debug "
  2055. fi
  2056. # TODO: kennt, do we need to check the return code? do we care?
  2057. $monitor_dir/proxysql_node_monitor --config-file=$CONFIG_FILE \
  2058. --write-hg=$HOSTGROUP_WRITER_ID \
  2059. --read-hg=$HOSTGROUP_READER_ID \
  2060. --mode=$mode \
  2061. --reload-check-file="$reload_check_file" \
  2062. --log-text="$LOG_TEXT" \
  2063. --max-connections="$MAX_CONNECTIONS" \
  2064. --log="$proxysql_monitor_log" $more_monitor_options
  2065. # print information prior to a run if ${ERR_FILE} is defined
  2066. log "" "###### proxysql_galera_checker.sh SUMMARY ######"
  2067. log "" "Hostgroup writers $HOSTGROUP_WRITER_ID"
  2068. log "" "Hostgroup readers $HOSTGROUP_READER_ID"
  2069. log "" "Number of writers $NUMBER_WRITERS"
  2070. log "" "Writers are readers $WRITER_IS_READER"
  2071. log "" "Log file $ERR_FILE"
  2072. log "" "Mode $MODE"
  2073. if [[ -n $P_PRIORITY ]]; then
  2074. log "" "Priority $P_PRIORITY"
  2075. fi
  2076. if [[ -n $LOG_TEXT ]]; then
  2077. log "" "Extra notes $LOG_TEXT"
  2078. fi
  2079. local number_readers_online=0
  2080. local number_writers_online=0
  2081. local save_reload_state=0
  2082. log "" "###### HANDLE WRITER NODES ######"
  2083. update_writers "${reload_check_file}"
  2084. number_writers_online=$(proxysql_exec $LINENO -Ns "SELECT count(*) FROM mysql_servers WHERE hostgroup_id=$HOSTGROUP_WRITER_ID AND status = 'ONLINE' AND comment <> 'SLAVEREAD'" 2>>${ERR_FILE})
  2085. check_cmd_and_exit $LINENO $? "Could not get node count (query failed). Exiting."
  2086. # Check to see if we need to add readers for any writer nodes
  2087. # (depends on the writer-is-reader setting)
  2088. number_readers_online=$(proxysql_exec $LINENO -Ns "SELECT count(*) FROM mysql_servers WHERE hostgroup_id IN ($HOSTGROUP_READER_ID) AND status = 'ONLINE' AND comment <> 'SLAVEREAD'")
  2089. check_cmd_and_exit $LINENO $? "Could not get node count (query failed). Exiting."
  2090. save_reload_state=$(save_reload_check "${reload_check_file}")
  2091. writer_is_reader_check "$reload_check_file" "$number_readers_online"
  2092. # Something changed
  2093. if restore_reload_check "${reload_check_file}" $save_reload_state; then
  2094. number_readers_online=$(proxysql_exec $LINENO -Ns "SELECT count(*) FROM mysql_servers WHERE hostgroup_id IN ($HOSTGROUP_READER_ID) AND status = 'ONLINE' AND comment <> 'SLAVEREAD'")
  2095. check_cmd_and_exit $LINENO $? "Could not get node count (query failed). Exiting."
  2096. fi
  2097. if [ ${HOSTGROUP_READER_ID} -ne -1 ]; then
  2098. log "" "###### HANDLE READER NODES ######"
  2099. save_reload_state=$(save_reload_check "${reload_check_file}")
  2100. update_readers "${reload_check_file}"
  2101. # Something changed
  2102. if restore_reload_check "${reload_check_file}" $save_reload_state; then
  2103. number_readers_online=$(proxysql_exec $LINENO -Ns "SELECT count(*) FROM mysql_servers WHERE hostgroup_id IN ($HOSTGROUP_READER_ID) AND status = 'ONLINE' AND comment <> 'SLAVEREAD'")
  2104. check_cmd_and_exit $LINENO $? "Could not get node count (query failed). Exiting."
  2105. fi
  2106. fi
  2107. if [[ $MODE != "loadbal" ]]; then
  2108. # If we have no writers, check if we can create one (just one)
  2109. if [[ $number_writers_online -eq 0 ]]; then
  2110. save_reload_state=$(save_reload_check "${reload_check_file}")
  2111. ensure_one_writer_node "${reload_check_file}"
  2112. # Something changed
  2113. if restore_reload_check "${reload_check_file}" $save_reload_state; then
  2114. # Check to see if we need to add readers for any writer nodes
  2115. # (depends on the writer-is-reader setting)
  2116. writer_is_reader_check "$reload_check_file" "$number_readers_online"
  2117. echo 1 > "${reload_check_file}"
  2118. number_readers_online=$(proxysql_exec $LINENO -Ns "SELECT count(*) FROM mysql_servers WHERE hostgroup_id IN ($HOSTGROUP_READER_ID) AND status = 'ONLINE' AND comment <> 'SLAVEREAD'")
  2119. check_cmd_and_exit $LINENO $? "Could not get node count (query failed). Exiting."
  2120. number_writers_online=$(proxysql_exec $LINENO -Ns "SELECT count(*) FROM mysql_servers WHERE hostgroup_id=$HOSTGROUP_WRITER_ID AND status = 'ONLINE' AND comment <> 'SLAVEREAD'" 2>>${ERR_FILE})
  2121. check_cmd_and_exit $LINENO $? "Could not get node count (query failed). Exiting."
  2122. fi
  2123. else
  2124. debug $LINENO "writer nodes found: $number_writers_online, no need to add more"
  2125. fi
  2126. fi
  2127. log "" "###### SUMMARY ######"
  2128. log "" "--> Number of writers that are 'ONLINE': ${number_writers_online} : hostgroup: ${HOSTGROUP_WRITER_ID}"
  2129. [[ ${HOSTGROUP_READER_ID} -ne -1 ]] && log "" "--> Number of readers that are 'ONLINE': ${number_readers_online} : hostgroup: ${HOSTGROUP_READER_ID}"
  2130. # We don't have any writers... alert, try to bring some online!
  2131. # This includes bringing a DONOR online
  2132. if [[ ${number_writers_online} -eq 0 ]]; then
  2133. log "" "###### TRYING TO FIX MISSING WRITERS ######"
  2134. log "" "No writers found, Trying to enable last available node of the cluster (in Donor/Desync state)"
  2135. save_reload_state=$(save_reload_check "${reload_check_file}")
  2136. search_for_desynced_writers "${reload_check_file}"
  2137. # Something changed
  2138. if restore_reload_check "${reload_check_file}" $save_reload_state; then
  2139. number_writers_online=$(proxysql_exec $LINENO -Ns "SELECT count(*) FROM mysql_servers WHERE hostgroup_id=$HOSTGROUP_WRITER_ID AND status = 'ONLINE' AND comment <> 'SLAVEREAD'" 2>>${ERR_FILE})
  2140. check_cmd_and_exit $LINENO $? "Could not get node count (query failed). Exiting."
  2141. fi
  2142. fi
  2143. # We don't have any readers... alert, try to bring some online!
  2144. if [[ ${HOSTGROUP_READER_ID} -ne -1 && ${number_readers_online} -eq 0 ]]; then
  2145. log "" "###### TRYING TO FIX MISSING READERS ######"
  2146. log "" "--> No readers found, Trying to enable last available node of the cluster (in Donor/Desync state) or pick the master"
  2147. save_reload_state=$(save_reload_check "${reload_check_file}")
  2148. search_for_desynced_readers "${reload_check_file}"
  2149. # Something changed
  2150. if restore_reload_check "${reload_check_file}" $save_reload_state; then
  2151. number_readers_online=$(proxysql_exec $LINENO -Ns "SELECT count(*) FROM mysql_servers WHERE hostgroup_id IN ($HOSTGROUP_READER_ID) AND status = 'ONLINE' AND comment <> 'SLAVEREAD'")
  2152. check_cmd_and_exit $LINENO $? "Could not get node count (query failed). Exiting."
  2153. fi
  2154. fi
  2155. # Check to see if we need to enable the slaves as readers/writers
  2156. if [[ $HAVE_SLAVEREADERS -eq 1 ]]; then
  2157. save_reload_state=$(save_reload_check "${reload_check_file}")
  2158. log $LINENO "###### ASYNC-SLAVE ACTIVITY ######"
  2159. # If use-slave-as-writer is set, then we do not allow slaves to
  2160. # be added, however we still call the remove slave writers
  2161. # in case the option was just changed.
  2162. if [[ $SLAVE_IS_WRITER == "yes" && $number_readers_online -eq 0 && $number_writers_online -eq 0 ]]; then
  2163. # No cluster nodes active, add a slave to the writer hostgroup
  2164. debug $LINENO "Nothing in the cluster, checking slavereaders"
  2165. add_slave_to_write_hostgroup "${reload_check_file}"
  2166. elif [[ $HAVE_SLAVEWRITERS -eq 1 ]]; then
  2167. # Active cluster nodes discovered, remove all write nodes
  2168. debug $LINENO "Found a cluster, removing slavereaders (acting as writers)"
  2169. remove_slave_from_write_hostgroup "${reload_check_file}"
  2170. fi
  2171. local query_result
  2172. local -i num_slave_writers=0
  2173. local -i num_slave_readers=0
  2174. query_result=$(proxysql_exec $LINENO -Ns "SELECT hostgroup_id FROM mysql_servers
  2175. WHERE hostgroup_id IN ($HOSTGROUP_WRITER_ID, $HOSTGROUP_READER_ID, $HOSTGROUP_SLAVEREADER_ID)
  2176. AND comment = 'SLAVEREAD'
  2177. AND status = 'ONLINE'")
  2178. check_cmd_and_exit $LINENO $? "Could not get the list of slave nodes (query failed). Exiting."
  2179. while read line; do
  2180. if [[ -z $line ]]; then
  2181. continue
  2182. fi
  2183. if [[ $line = "$HOSTGROUP_WRITER_ID" ]]; then
  2184. num_slave_writers+=1
  2185. elif [[ $line = "$HOSTGROUP_READER_ID" ]]; then
  2186. num_slave_readers+=1
  2187. fi
  2188. done< <(printf "$query_result\n")
  2189. log "" "--> Number of slave writers that are 'ONLINE': ${num_slave_writers} : hostgroup: ${HOSTGROUP_WRITER_ID}"
  2190. [[ ${HOSTGROUP_READER_ID} -ne -1 ]] && log "" "--> Number of slave readers that are 'ONLINE': ${num_slave_readers} : hostgroup: ${HOSTGROUP_READER_ID}"
  2191. restore_reload_check "${reload_check_file}" $save_reload_state
  2192. fi
  2193. if [[ $(cat ${reload_check_file}) -ne 0 ]] ; then
  2194. log "" "###### Loading mysql_servers config into runtime ######"
  2195. proxysql_exec $LINENO -Ns "LOAD MYSQL SERVERS TO RUNTIME;" 2>>${ERR_FILE}
  2196. check_cmd_and_exit $LINENO $? "Could not update the mysql_servers table in ProxySQL. Exiting."
  2197. else
  2198. log "" "###### Not loading mysql_servers, no change needed ######"
  2199. fi
  2200. }
  2201. #-------------------------------------------------------------------------------
  2202. #
  2203. # Step 4 : Begin script execution
  2204. #
  2205. #
  2206. # In the initial version, ProxySQL has 5 slots for command-line arguments
  2207. # and would send them separately (each enclosed in double quotes,
  2208. # such as "arg1" "arg2" etc..).
  2209. #
  2210. # We now configure all parameters in the arg1 field (since we need more
  2211. # than 5 arguments). This means that we now receive all the arguments
  2212. # in one parameter "arg1 arg2 arg3 arg4 arg5"
  2213. #
  2214. # This means that anytime this script is called with > 1 argument, we
  2215. # assume that the old method is in use and we need to upgrade the script
  2216. # to the new method (in upgrade_scheduler).
  2217. #
  2218. if [ "$#" -eq 1 ]; then
  2219. # Below set will reshuffle parameters.
  2220. # example arg1=" --one=1 --two=2" will result in:
  2221. # $1 = --one=1
  2222. # $2 = --two=2
  2223. #
  2224. # The eval is needed here to preserve whitespace in the arguments
  2225. eval set -- $1
  2226. else
  2227. # Parse the arguments
  2228. declare param value
  2229. # We don't need all the options here, just the log/debug options
  2230. while [[ $# -gt 0 && "$1" != "" ]]; do
  2231. param=`echo $1 | awk -F= '{print $1}'`
  2232. value=`echo $1 | awk -F= '{print $2}'`
  2233. # Assume that all options start with a '-'
  2234. # otherwise treat as a positional parameter
  2235. if [[ ! $param =~ ^- ]]; then
  2236. continue
  2237. fi
  2238. case $param in
  2239. -h | --help)
  2240. usage
  2241. exit 0
  2242. ;;
  2243. --debug)
  2244. DEBUG=1
  2245. ;;
  2246. -v | --version)
  2247. echo "proxysql_galera_checker version $PROXYSQL_ADMIN_VERSION"
  2248. exit 0
  2249. ;;
  2250. --log)
  2251. if [[ -n $value ]]; then
  2252. ERR_FILE=$value
  2253. fi
  2254. ;;
  2255. esac
  2256. shift
  2257. done
  2258. echo "Old config detected...trying to upgrade More than one parameter"
  2259. if [[ $DEBUG -eq 1 ]]; then
  2260. # For now
  2261. if [[ -z $ERR_FILE && -t 1 ]]; then
  2262. ERR_FILE=/dev/stderr
  2263. fi
  2264. fi
  2265. upgrade_scheduler
  2266. exit 1
  2267. fi
  2268. trap cleanup_handler EXIT
  2269. parse_args "$@"
  2270. main
  2271. exit 0