summaryrefslogtreecommitdiff
path: root/ironic_python_agent/utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'ironic_python_agent/utils.py')
-rw-r--r--ironic_python_agent/utils.py101
1 files changed, 101 insertions, 0 deletions
diff --git a/ironic_python_agent/utils.py b/ironic_python_agent/utils.py
index 195783c2..17446881 100644
--- a/ironic_python_agent/utils.py
+++ b/ironic_python_agent/utils.py
@@ -13,9 +13,12 @@
# limitations under the License.
import collections
+import glob
+import os
from oslo_concurrency import processutils
+from ironic_python_agent import errors
from ironic_python_agent.openstack.common import _i18n as gtu
from ironic_python_agent.openstack.common import log as logging
@@ -39,3 +42,101 @@ def execute(*cmd, **kwargs):
LOG.debug(gtu._('Command stdout is: "%s"') % result[0])
LOG.debug(gtu._('Command stderr is: "%s"') % result[1])
return result
+
+
+def _read_params_from_file(filepath):
+ """Extract key=value pairs from a file.
+
+ :param filepath: path to a file containing key=value pairs separated by
+ whitespace or newlines.
+ :returns: a dictionary representing the content of the file
+ """
+ with open(filepath) as f:
+ cmdline = f.read()
+
+ options = cmdline.split()
+ params = {}
+ for option in options:
+ if '=' not in option:
+ continue
+ k, v = option.split('=', 1)
+ params[k] = v
+
+ return params
+
+
+def _get_vmedia_device():
+ """Finds the device filename of the virtual media device using sysfs.
+
+ :returns: a string containing the filename of the virtual media device
+ """
+ sysfs_device_models = glob.glob("/sys/class/block/*/device/model")
+ vmedia_device_model = "virtual media"
+ for model_file in sysfs_device_models:
+ try:
+ with open(model_file) as model_file_fobj:
+ if vmedia_device_model in model_file_fobj.read().lower():
+ vmedia_device = model_file.split('/')[4]
+ return vmedia_device
+ except Exception:
+ pass
+
+
+def _get_vmedia_params():
+ """This method returns the parameters passed to the agent through virtual
+ media floppy.
+
+ :returns: a partial dict of potential agent configuration parameters
+ :raises: VirtualMediaBootError when it cannot find the virtual media device
+ """
+ vmedia_mount_point = "/vmedia_mnt"
+ parameters_file = "parameters.txt"
+
+ vmedia_device = _get_vmedia_device()
+ if not vmedia_device:
+ msg = "Unable to find virtual media device"
+ raise errors.VirtualMediaBootError(msg)
+
+ vmedia_device_file = os.path.join("/dev", vmedia_device)
+ os.mkdir(vmedia_mount_point)
+
+ try:
+ stdout, stderr = execute("mount", vmedia_device_file,
+ vmedia_mount_point)
+ except processutils.ProcessExecutionError as e:
+ msg = ("Unable to mount virtual media device %(device)s: %(error)s" %
+ {'device': vmedia_device_file, 'error': e})
+ raise errors.VirtualMediaBootError(msg)
+
+ parameters_file_path = os.path.join(vmedia_mount_point, parameters_file)
+ params = _read_params_from_file(parameters_file_path)
+
+ try:
+ stdout, stderr = execute("umount", vmedia_mount_point)
+ except processutils.ProcessExecutionError as e:
+ pass
+
+ return params
+
+
+def get_agent_params():
+ """Gets parameters passed to the agent via kernel cmdline or vmedia.
+
+ Parameters can be passed using either the kernel commandline or through
+ virtual media. If boot_method is vmedia, merge params provided via vmedia
+ with those read from the kernel command line.
+
+ Although it should never happen, if a variable is both set by vmedia and
+ kernel command line, the setting in vmedia will take precedence.
+
+ :returns: a dict of potential configuration parameters for the agent
+ """
+ params = _read_params_from_file('/proc/cmdline')
+
+ # If the node booted over virtual media, the parameters are passed
+ # in a text file within the virtual media floppy.
+ if params.get('boot_method', None) == 'vmedia':
+ vmedia_params = _get_vmedia_params()
+ params.update(vmedia_params)
+
+ return params