/usr/lib/python2.7/dist-packages/provisioningserver/power/poweraction.py is in python-maas-provisioningserver 1.5.4+bzr2294-0ubuntu1.2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | # Copyright 2012-2014 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Actions for power-related operations."""
from __future__ import (
absolute_import,
print_function,
unicode_literals,
)
str = None
__metaclass__ = type
__all__ = [
"PowerAction",
"PowerActionFail",
"UnknownPowerType",
]
import os
import subprocess
from celery.app import app_or_default
from provisioningserver.utils import (
locate_config,
ShellTemplate,
)
class UnknownPowerType(Exception):
"""Raised when trying to process an unknown power type."""
class PowerActionFail(Exception):
"""Raised when there's a problem executing a power script."""
def __init__(self, power_action, err):
self.power_action = power_action
self.err = err
def __str__(self):
message = "%s failed: %s" % (self.power_action.power_type, self.err)
is_process_error = isinstance(self.err, subprocess.CalledProcessError)
if is_process_error and self.err.output:
# Add error output to the message.
message += ":\n" + self.err.output.strip()
return message
def get_power_templates_dir():
"""Get the power-templates directory from the config."""
return app_or_default().conf.POWER_TEMPLATES_DIR
def get_power_config_dir():
"""Get the power-config directory from the config."""
return app_or_default().conf.POWER_CONFIG_DIR
class PowerAction:
"""Actions for power-related operations.
:param power_type: A power-type name, e.g. `ipmi`.
The class is intended to be used in two phases:
1. Instantiation, passing the power_type.
2. .execute(), passing any template parameters required by the template.
"""
def __init__(self, power_type):
self.path = os.path.join(
self.template_basedir, power_type + ".template")
if not os.path.exists(self.path):
raise UnknownPowerType(power_type)
self.power_type = power_type
@property
def template_basedir(self):
"""Directory where power templates are stored."""
return get_power_templates_dir() or locate_config('templates/power')
@property
def config_basedir(self):
"""Directory where power config are stored."""
# By default, power config lives in the same directory as power
# templates. This makes it easy to customize them together.
return get_power_config_dir() or locate_config('templates/power')
def get_template(self):
with open(self.path, "rb") as f:
return ShellTemplate(f.read(), name=self.path)
def get_extra_context(self):
"""Extra context used when rending the power templates."""
return {
'config_dir': self.config_basedir,
}
def render_template(self, template, **kwargs):
try:
kwargs.update(self.get_extra_context())
return template.substitute(kwargs)
except NameError as error:
raise PowerActionFail(self, error)
def run_shell(self, commands):
"""Execute raw shell script (as rendered from a template).
:param commands: String containing shell script.
:raises: :class:`PowerActionFail`
"""
# This might need retrying but it could be better to leave that
# to the individual scripts.
try:
output = subprocess.check_output(
commands, shell=True, stderr=subprocess.STDOUT, close_fds=True)
except subprocess.CalledProcessError as e:
raise PowerActionFail(self, e)
# This output is only examined in tests, execute just ignores it
return output
def execute(self, **kwargs):
"""Execute the template.
Any supplied parameters will be passed to the template as substitution
values.
"""
template = self.get_template()
rendered = self.render_template(template, **kwargs)
self.run_shell(rendered)
|