1""" 2Control Modjk via the Apache Tomcat "Status" worker 3(http://tomcat.apache.org/connectors-doc/reference/status.html) 4 5Below is an example of the configuration needed for this module. This 6configuration data can be placed either in :ref:`grains 7<targeting-grains>` or :ref:`pillar <salt-pillars>`. 8 9If using grains, this can be accomplished :ref:`statically 10<static-custom-grains>` or via a :ref:`grain module <writing-grains>`. 11 12If using pillar, the yaml configuration can be placed directly into a pillar 13SLS file, making this both the easier and more dynamic method of configuring 14this module. 15 16.. code-block:: yaml 17 18 modjk: 19 default: 20 url: http://localhost/jkstatus 21 user: modjk 22 pass: secret 23 realm: authentication realm for digest passwords 24 timeout: 5 25 otherVhost: 26 url: http://otherVhost/jkstatus 27 user: modjk 28 pass: secret2 29 realm: authentication realm2 for digest passwords 30 timeout: 600 31""" 32import urllib.parse 33import urllib.request 34 35 36def __virtual__(): 37 """ 38 Always load 39 """ 40 return True 41 42 43def _auth(url, user, passwd, realm): 44 """ 45 returns a authentication handler. 46 """ 47 48 basic = urllib.request.HTTPBasicAuthHandler() 49 basic.add_password(realm=realm, uri=url, user=user, passwd=passwd) 50 digest = urllib.request.HTTPDigestAuthHandler() 51 digest.add_password(realm=realm, uri=url, user=user, passwd=passwd) 52 return urllib.request.build_opener(basic, digest) 53 54 55def _do_http(opts, profile="default"): 56 """ 57 Make the http request and return the data 58 """ 59 60 ret = {} 61 62 url = __salt__["config.get"]("modjk:{}:url".format(profile), "") 63 user = __salt__["config.get"]("modjk:{}:user".format(profile), "") 64 passwd = __salt__["config.get"]("modjk:{}:pass".format(profile), "") 65 realm = __salt__["config.get"]("modjk:{}:realm".format(profile), "") 66 timeout = __salt__["config.get"]("modjk:{}:timeout".format(profile), "") 67 68 if not url: 69 raise Exception("missing url in profile {}".format(profile)) 70 71 if user and passwd: 72 auth = _auth(url=url, realm=realm, user=user, passwd=passwd) 73 urllib.request.install_opener(auth) 74 75 url += "?{}".format(urllib.parse.urlencode(opts)) 76 77 for line in urllib.request.urlopen(url, timeout=timeout).read().splitlines(): 78 splt = line.split("=", 1) 79 if splt[0] in ret: 80 ret[splt[0]] += ",{}".format(splt[1]) 81 else: 82 ret[splt[0]] = splt[1] 83 84 return ret 85 86 87def _worker_ctl(worker, lbn, vwa, profile="default"): 88 """ 89 enable/disable/stop a worker 90 """ 91 92 cmd = { 93 "cmd": "update", 94 "mime": "prop", 95 "w": lbn, 96 "sw": worker, 97 "vwa": vwa, 98 } 99 return _do_http(cmd, profile)["worker.result.type"] == "OK" 100 101 102def version(profile="default"): 103 """ 104 Return the modjk version 105 106 CLI Examples: 107 108 .. code-block:: bash 109 110 salt '*' modjk.version 111 salt '*' modjk.version other-profile 112 """ 113 114 cmd = { 115 "cmd": "version", 116 "mime": "prop", 117 } 118 return _do_http(cmd, profile)["worker.jk_version"].split("/")[-1] 119 120 121def get_running(profile="default"): 122 """ 123 Get the current running config (not from disk) 124 125 CLI Examples: 126 127 .. code-block:: bash 128 129 salt '*' modjk.get_running 130 salt '*' modjk.get_running other-profile 131 """ 132 133 cmd = { 134 "cmd": "list", 135 "mime": "prop", 136 } 137 return _do_http(cmd, profile) 138 139 140def dump_config(profile="default"): 141 """ 142 Dump the original configuration that was loaded from disk 143 144 CLI Examples: 145 146 .. code-block:: bash 147 148 salt '*' modjk.dump_config 149 salt '*' modjk.dump_config other-profile 150 """ 151 152 cmd = { 153 "cmd": "dump", 154 "mime": "prop", 155 } 156 return _do_http(cmd, profile) 157 158 159def list_configured_members(lbn, profile="default"): 160 """ 161 Return a list of member workers from the configuration files 162 163 CLI Examples: 164 165 .. code-block:: bash 166 167 salt '*' modjk.list_configured_members loadbalancer1 168 salt '*' modjk.list_configured_members loadbalancer1 other-profile 169 """ 170 171 config = dump_config(profile) 172 173 try: 174 ret = config["worker.{}.balance_workers".format(lbn)] 175 except KeyError: 176 return [] 177 178 return [_f for _f in ret.strip().split(",") if _f] 179 180 181def workers(profile="default"): 182 """ 183 Return a list of member workers and their status 184 185 CLI Examples: 186 187 .. code-block:: bash 188 189 salt '*' modjk.workers 190 salt '*' modjk.workers other-profile 191 """ 192 193 config = get_running(profile) 194 lbn = config["worker.list"].split(",") 195 worker_list = [] 196 ret = {} 197 198 for lb in lbn: 199 try: 200 worker_list.extend( 201 config["worker.{}.balance_workers".format(lb)].split(",") 202 ) 203 except KeyError: 204 pass 205 206 worker_list = list(set(worker_list)) 207 208 for worker in worker_list: 209 ret[worker] = { 210 "activation": config["worker.{}.activation".format(worker)], 211 "state": config["worker.{}.state".format(worker)], 212 } 213 214 return ret 215 216 217def recover_all(lbn, profile="default"): 218 """ 219 Set the all the workers in lbn to recover and activate them if they are not 220 221 CLI Examples: 222 223 .. code-block:: bash 224 225 salt '*' modjk.recover_all loadbalancer1 226 salt '*' modjk.recover_all loadbalancer1 other-profile 227 """ 228 229 ret = {} 230 config = get_running(profile) 231 try: 232 workers_ = config["worker.{}.balance_workers".format(lbn)].split(",") 233 except KeyError: 234 return ret 235 236 for worker in workers_: 237 curr_state = worker_status(worker, profile) 238 if curr_state["activation"] != "ACT": 239 worker_activate(worker, lbn, profile) 240 if not curr_state["state"].startswith("OK"): 241 worker_recover(worker, lbn, profile) 242 ret[worker] = worker_status(worker, profile) 243 244 return ret 245 246 247def reset_stats(lbn, profile="default"): 248 """ 249 Reset all runtime statistics for the load balancer 250 251 CLI Examples: 252 253 .. code-block:: bash 254 255 salt '*' modjk.reset_stats loadbalancer1 256 salt '*' modjk.reset_stats loadbalancer1 other-profile 257 """ 258 259 cmd = { 260 "cmd": "reset", 261 "mime": "prop", 262 "w": lbn, 263 } 264 return _do_http(cmd, profile)["worker.result.type"] == "OK" 265 266 267def lb_edit(lbn, settings, profile="default"): 268 """ 269 Edit the loadbalancer settings 270 271 Note: http://tomcat.apache.org/connectors-doc/reference/status.html 272 Data Parameters for the standard Update Action 273 274 CLI Examples: 275 276 .. code-block:: bash 277 278 salt '*' modjk.lb_edit loadbalancer1 "{'vlr': 1, 'vlt': 60}" 279 salt '*' modjk.lb_edit loadbalancer1 "{'vlr': 1, 'vlt': 60}" other-profile 280 """ 281 282 settings["cmd"] = "update" 283 settings["mime"] = "prop" 284 settings["w"] = lbn 285 286 return _do_http(settings, profile)["worker.result.type"] == "OK" 287 288 289def bulk_stop(workers, lbn, profile="default"): 290 """ 291 Stop all the given workers in the specific load balancer 292 293 CLI Examples: 294 295 .. code-block:: bash 296 297 salt '*' modjk.bulk_stop node1,node2,node3 loadbalancer1 298 salt '*' modjk.bulk_stop node1,node2,node3 loadbalancer1 other-profile 299 300 salt '*' modjk.bulk_stop ["node1","node2","node3"] loadbalancer1 301 salt '*' modjk.bulk_stop ["node1","node2","node3"] loadbalancer1 other-profile 302 """ 303 304 ret = {} 305 306 if isinstance(workers, str): 307 workers = workers.split(",") 308 309 for worker in workers: 310 try: 311 ret[worker] = worker_stop(worker, lbn, profile) 312 except Exception: # pylint: disable=broad-except 313 ret[worker] = False 314 315 return ret 316 317 318def bulk_activate(workers, lbn, profile="default"): 319 """ 320 Activate all the given workers in the specific load balancer 321 322 CLI Examples: 323 324 .. code-block:: bash 325 326 salt '*' modjk.bulk_activate node1,node2,node3 loadbalancer1 327 salt '*' modjk.bulk_activate node1,node2,node3 loadbalancer1 other-profile 328 329 salt '*' modjk.bulk_activate ["node1","node2","node3"] loadbalancer1 330 salt '*' modjk.bulk_activate ["node1","node2","node3"] loadbalancer1 other-profile 331 """ 332 333 ret = {} 334 335 if isinstance(workers, str): 336 workers = workers.split(",") 337 338 for worker in workers: 339 try: 340 ret[worker] = worker_activate(worker, lbn, profile) 341 except Exception: # pylint: disable=broad-except 342 ret[worker] = False 343 344 return ret 345 346 347def bulk_disable(workers, lbn, profile="default"): 348 """ 349 Disable all the given workers in the specific load balancer 350 351 CLI Examples: 352 353 .. code-block:: bash 354 355 salt '*' modjk.bulk_disable node1,node2,node3 loadbalancer1 356 salt '*' modjk.bulk_disable node1,node2,node3 loadbalancer1 other-profile 357 358 salt '*' modjk.bulk_disable ["node1","node2","node3"] loadbalancer1 359 salt '*' modjk.bulk_disable ["node1","node2","node3"] loadbalancer1 other-profile 360 """ 361 362 ret = {} 363 364 if isinstance(workers, str): 365 workers = workers.split(",") 366 367 for worker in workers: 368 try: 369 ret[worker] = worker_disable(worker, lbn, profile) 370 except Exception: # pylint: disable=broad-except 371 ret[worker] = False 372 373 return ret 374 375 376def bulk_recover(workers, lbn, profile="default"): 377 """ 378 Recover all the given workers in the specific load balancer 379 380 CLI Examples: 381 382 .. code-block:: bash 383 384 salt '*' modjk.bulk_recover node1,node2,node3 loadbalancer1 385 salt '*' modjk.bulk_recover node1,node2,node3 loadbalancer1 other-profile 386 387 salt '*' modjk.bulk_recover ["node1","node2","node3"] loadbalancer1 388 salt '*' modjk.bulk_recover ["node1","node2","node3"] loadbalancer1 other-profile 389 """ 390 391 ret = {} 392 393 if isinstance(workers, str): 394 workers = workers.split(",") 395 396 for worker in workers: 397 try: 398 ret[worker] = worker_recover(worker, lbn, profile) 399 except Exception: # pylint: disable=broad-except 400 ret[worker] = False 401 402 return ret 403 404 405def worker_status(worker, profile="default"): 406 """ 407 Return the state of the worker 408 409 CLI Examples: 410 411 .. code-block:: bash 412 413 salt '*' modjk.worker_status node1 414 salt '*' modjk.worker_status node1 other-profile 415 """ 416 417 config = get_running(profile) 418 try: 419 return { 420 "activation": config["worker.{}.activation".format(worker)], 421 "state": config["worker.{}.state".format(worker)], 422 } 423 except KeyError: 424 return False 425 426 427def worker_recover(worker, lbn, profile="default"): 428 """ 429 Set the worker to recover 430 this module will fail if it is in OK state 431 432 CLI Examples: 433 434 .. code-block:: bash 435 436 salt '*' modjk.worker_recover node1 loadbalancer1 437 salt '*' modjk.worker_recover node1 loadbalancer1 other-profile 438 """ 439 440 cmd = { 441 "cmd": "recover", 442 "mime": "prop", 443 "w": lbn, 444 "sw": worker, 445 } 446 return _do_http(cmd, profile) 447 448 449def worker_disable(worker, lbn, profile="default"): 450 """ 451 Set the worker to disable state in the lbn load balancer 452 453 CLI Examples: 454 455 .. code-block:: bash 456 457 salt '*' modjk.worker_disable node1 loadbalancer1 458 salt '*' modjk.worker_disable node1 loadbalancer1 other-profile 459 """ 460 461 return _worker_ctl(worker, lbn, "d", profile) 462 463 464def worker_activate(worker, lbn, profile="default"): 465 """ 466 Set the worker to activate state in the lbn load balancer 467 468 CLI Examples: 469 470 .. code-block:: bash 471 472 salt '*' modjk.worker_activate node1 loadbalancer1 473 salt '*' modjk.worker_activate node1 loadbalancer1 other-profile 474 """ 475 476 return _worker_ctl(worker, lbn, "a", profile) 477 478 479def worker_stop(worker, lbn, profile="default"): 480 """ 481 Set the worker to stopped state in the lbn load balancer 482 483 CLI Examples: 484 485 .. code-block:: bash 486 487 salt '*' modjk.worker_activate node1 loadbalancer1 488 salt '*' modjk.worker_activate node1 loadbalancer1 other-profile 489 """ 490 491 return _worker_ctl(worker, lbn, "s", profile) 492 493 494def worker_edit(worker, lbn, settings, profile="default"): 495 """ 496 Edit the worker settings 497 498 Note: http://tomcat.apache.org/connectors-doc/reference/status.html 499 Data Parameters for the standard Update Action 500 501 CLI Examples: 502 503 .. code-block:: bash 504 505 salt '*' modjk.worker_edit node1 loadbalancer1 "{'vwf': 500, 'vwd': 60}" 506 salt '*' modjk.worker_edit node1 loadbalancer1 "{'vwf': 500, 'vwd': 60}" other-profile 507 """ 508 509 settings["cmd"] = "update" 510 settings["mime"] = "prop" 511 settings["w"] = lbn 512 settings["sw"] = worker 513 514 return _do_http(settings, profile)["worker.result.type"] == "OK" 515