Revision dd7f6776 lib/mcpu.py
b/lib/mcpu.py | ||
---|---|---|
427 | 427 |
self.callfn = callfn |
428 | 428 |
self.lu = lu |
429 | 429 |
self.op = lu.op |
430 |
self.env, node_list_pre, node_list_post = self._BuildEnv() |
|
431 |
self.node_list = { |
|
432 |
constants.HOOKS_PHASE_PRE: node_list_pre, |
|
433 |
constants.HOOKS_PHASE_POST: node_list_post, |
|
434 |
} |
|
430 |
self.pre_env = None |
|
431 |
self.pre_nodes = None |
|
435 | 432 |
|
436 |
def _BuildEnv(self): |
|
433 |
def _BuildEnv(self, phase):
|
|
437 | 434 |
"""Compute the environment and the target nodes. |
438 | 435 |
|
439 | 436 |
Based on the opcode and the current node list, this builds the |
440 | 437 |
environment for the hooks and the target node list for the run. |
441 | 438 |
|
442 | 439 |
""" |
443 |
env = { |
|
444 |
"PATH": "/sbin:/bin:/usr/sbin:/usr/bin", |
|
445 |
"GANETI_HOOKS_VERSION": constants.HOOKS_VERSION, |
|
446 |
"GANETI_OP_CODE": self.op.OP_ID, |
|
447 |
"GANETI_OBJECT_TYPE": self.lu.HTYPE, |
|
448 |
"GANETI_DATA_DIR": constants.DATA_DIR, |
|
449 |
} |
|
440 |
if phase == constants.HOOKS_PHASE_PRE: |
|
441 |
prefix = "GANETI_" |
|
442 |
elif phase == constants.HOOKS_PHASE_POST: |
|
443 |
prefix = "GANETI_POST_" |
|
444 |
else: |
|
445 |
raise AssertionError("Unknown phase '%s'" % phase) |
|
446 |
|
|
447 |
env = {} |
|
450 | 448 |
|
451 | 449 |
if self.lu.HPATH is not None: |
452 | 450 |
(lu_env, lu_nodes_pre, lu_nodes_post) = self.lu.BuildHooksEnv() |
453 | 451 |
if lu_env: |
454 |
assert not compat.any(key.upper().startswith("GANETI")
|
|
452 |
assert not compat.any(key.upper().startswith(prefix)
|
|
455 | 453 |
for key in lu_env) |
456 |
env.update(("GANETI_%s" % key, value) for (key, value) in lu_env) |
|
454 |
env.update(("%s%s" % (prefix, key), value) |
|
455 |
for (key, value) in lu_env.items()) |
|
457 | 456 |
else: |
458 | 457 |
lu_nodes_pre = lu_nodes_post = [] |
459 | 458 |
|
459 |
if phase == constants.HOOKS_PHASE_PRE: |
|
460 |
assert compat.all((key.startswith("GANETI_") and |
|
461 |
not key.startswith("GANETI_POST_")) |
|
462 |
for key in env) |
|
463 |
|
|
464 |
# Record environment for any post-phase hooks |
|
465 |
self.pre_env = env |
|
466 |
|
|
467 |
elif phase == constants.HOOKS_PHASE_POST: |
|
468 |
assert compat.all(key.startswith("GANETI_POST_") for key in env) |
|
469 |
|
|
470 |
if self.pre_env: |
|
471 |
assert not compat.any(key.startswith("GANETI_POST_") |
|
472 |
for key in self.pre_env) |
|
473 |
env.update(self.pre_env) |
|
474 |
else: |
|
475 |
raise AssertionError("Unknown phase '%s'" % phase) |
|
476 |
|
|
460 | 477 |
return env, frozenset(lu_nodes_pre), frozenset(lu_nodes_post) |
461 | 478 |
|
462 |
def _RunWrapper(self, node_list, hpath, phase): |
|
479 |
def _RunWrapper(self, node_list, hpath, phase, phase_env):
|
|
463 | 480 |
"""Simple wrapper over self.callfn. |
464 | 481 |
|
465 | 482 |
This method fixes the environment before doing the rpc call. |
466 | 483 |
|
467 | 484 |
""" |
468 |
env = self.env.copy() |
|
469 |
env["GANETI_HOOKS_PHASE"] = phase |
|
470 |
env["GANETI_HOOKS_PATH"] = hpath |
|
471 |
if self.lu.cfg is not None: |
|
472 |
env["GANETI_CLUSTER"] = self.lu.cfg.GetClusterName() |
|
473 |
env["GANETI_MASTER"] = self.lu.cfg.GetMasterNode() |
|
485 |
cfg = self.lu.cfg |
|
486 |
|
|
487 |
env = { |
|
488 |
"PATH": "/sbin:/bin:/usr/sbin:/usr/bin", |
|
489 |
"GANETI_HOOKS_VERSION": constants.HOOKS_VERSION, |
|
490 |
"GANETI_OP_CODE": self.op.OP_ID, |
|
491 |
"GANETI_OBJECT_TYPE": self.lu.HTYPE, |
|
492 |
"GANETI_DATA_DIR": constants.DATA_DIR, |
|
493 |
"GANETI_HOOKS_PHASE": phase, |
|
494 |
"GANETI_HOOKS_PATH": hpath, |
|
495 |
} |
|
496 |
|
|
497 |
if cfg is not None: |
|
498 |
env["GANETI_CLUSTER"] = cfg.GetClusterName() |
|
499 |
env["GANETI_MASTER"] = cfg.GetMasterNode() |
|
500 |
|
|
501 |
if phase_env: |
|
502 |
assert not (set(env) & set(phase_env)), "Environment variables conflict" |
|
503 |
env.update(phase_env) |
|
474 | 504 |
|
505 |
# Convert everything to strings |
|
475 | 506 |
env = dict([(str(key), str(val)) for key, val in env.iteritems()]) |
476 | 507 |
|
477 |
assert compat.all(key == key.upper() and |
|
478 |
(key == "PATH" or key.startswith("GANETI_")) |
|
508 |
assert compat.all(key == "PATH" or key.startswith("GANETI_") |
|
479 | 509 |
for key in env) |
480 | 510 |
|
481 | 511 |
return self.callfn(node_list, hpath, phase, env) |
... | ... | |
493 | 523 |
@raise errors.HooksAbort: on failure of one of the hooks |
494 | 524 |
|
495 | 525 |
""" |
526 |
(env, node_list_pre, node_list_post) = self._BuildEnv(phase) |
|
496 | 527 |
if nodes is None: |
497 |
nodes = self.node_list[phase] |
|
528 |
if phase == constants.HOOKS_PHASE_PRE: |
|
529 |
self.pre_nodes = (node_list_pre, node_list_post) |
|
530 |
nodes = node_list_pre |
|
531 |
elif phase == constants.HOOKS_PHASE_POST: |
|
532 |
post_nodes = (node_list_pre, node_list_post) |
|
533 |
assert self.pre_nodes == post_nodes, \ |
|
534 |
("Node lists returned for post-phase hook don't match pre-phase" |
|
535 |
" lists (pre %s, post %s)" % (self.pre_nodes, post_nodes)) |
|
536 |
nodes = node_list_post |
|
537 |
else: |
|
538 |
raise AssertionError("Unknown phase '%s'" % phase) |
|
498 | 539 |
|
499 | 540 |
if not nodes: |
500 | 541 |
# empty node list, we should not attempt to run this as either |
... | ... | |
502 | 543 |
# even attempt to run, or this LU doesn't do hooks at all |
503 | 544 |
return |
504 | 545 |
|
505 |
results = self._RunWrapper(nodes, self.lu.HPATH, phase) |
|
546 |
results = self._RunWrapper(nodes, self.lu.HPATH, phase, env)
|
|
506 | 547 |
if not results: |
507 | 548 |
msg = "Communication Failure" |
508 | 549 |
if phase == constants.HOOKS_PHASE_PRE: |
... | ... | |
545 | 586 |
top-level LI if the configuration has been updated. |
546 | 587 |
|
547 | 588 |
""" |
589 |
if self.pre_env is None: |
|
590 |
raise AssertionError("Pre-phase must be run before configuration update") |
|
591 |
|
|
548 | 592 |
phase = constants.HOOKS_PHASE_POST |
549 | 593 |
hpath = constants.HOOKS_NAME_CFGUPDATE |
550 | 594 |
nodes = [self.lu.cfg.GetMasterNode()] |
551 |
self._RunWrapper(nodes, hpath, phase) |
|
595 |
self._RunWrapper(nodes, hpath, phase, self.pre_env) |
Also available in: Unified diff