summaryrefslogtreecommitdiff
path: root/ironic/common
diff options
context:
space:
mode:
Diffstat (limited to 'ironic/common')
-rw-r--r--ironic/common/neutron.py4
-rw-r--r--ironic/common/pxe_utils.py167
-rw-r--r--ironic/common/tftp.py140
3 files changed, 168 insertions, 143 deletions
diff --git a/ironic/common/neutron.py b/ironic/common/neutron.py
index 897f60610..034a177bd 100644
--- a/ironic/common/neutron.py
+++ b/ironic/common/neutron.py
@@ -23,7 +23,6 @@ from oslo.config import cfg
from ironic.api import acl
from ironic.common import exception
from ironic.common import keystone
-from ironic.common import tftp
from ironic.drivers.modules import ssh
from ironic.openstack.common import log as logging
@@ -144,9 +143,8 @@ def get_node_vif_ids(task):
return port_vifs
-def update_neutron(task, pxe_bootfile_name):
+def update_neutron(task, options):
"""Send or update the DHCP BOOT options to Neutron for this node."""
- options = tftp.dhcp_options_for_instance(pxe_bootfile_name)
vifs = get_node_vif_ids(task)
if not vifs:
LOG.warning(_("No VIFs found for node %(node)s when attempting to "
diff --git a/ironic/common/pxe_utils.py b/ironic/common/pxe_utils.py
new file mode 100644
index 000000000..19685b8f0
--- /dev/null
+++ b/ironic/common/pxe_utils.py
@@ -0,0 +1,167 @@
+#
+# Copyright 2014 Rackspace, Inc
+# All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import os
+
+import jinja2
+from oslo.config import cfg
+
+from ironic.common import utils
+from ironic.drivers import utils as driver_utils
+from ironic.openstack.common import fileutils
+from ironic.openstack.common import log as logging
+
+CONF = cfg.CONF
+
+LOG = logging.getLogger(__name__)
+
+PXE_CFG_DIR_NAME = 'pxelinux.cfg'
+
+
+def _ensure_config_dirs_exist(node_uuid):
+ """Ensure that the node's and PXE configuration directories exist.
+
+ :param node_uuid: the UUID of the node.
+
+ """
+ tftp_root = CONF.pxe.tftp_root
+ fileutils.ensure_tree(os.path.join(tftp_root, node_uuid))
+ fileutils.ensure_tree(os.path.join(tftp_root, PXE_CFG_DIR_NAME))
+
+
+def _build_pxe_config(pxe_options, template):
+ """Build the PXE boot configuration file.
+
+ This method builds the PXE boot configuration file by rendering the
+ template with the given parameters.
+
+ :param pxe_options: A dict of values to set on the configuration file.
+ :param template: The PXE configuration template.
+ :returns: A formatted string with the file content.
+
+ """
+ tmpl_path, tmpl_file = os.path.split(template)
+ env = jinja2.Environment(loader=jinja2.FileSystemLoader(tmpl_path))
+ template = env.get_template(tmpl_file)
+ return template.render({'pxe_options': pxe_options,
+ 'ROOT': '{{ ROOT }}'})
+
+
+def _link_mac_pxe_configs(task):
+ """Link each MAC address with the PXE configuration file.
+
+ :param task: A TaskManager instance.
+
+ """
+ pxe_config_file_path = get_pxe_config_file_path(task.node.uuid)
+ for mac in driver_utils.get_node_mac_addresses(task):
+ mac_path = _get_pxe_mac_path(mac)
+ utils.unlink_without_raise(mac_path)
+ utils.create_link_without_raise(pxe_config_file_path, mac_path)
+
+
+def _get_pxe_mac_path(mac):
+ """Convert a MAC address into a PXE config file name.
+
+ :param mac: A MAC address string in the format xx:xx:xx:xx:xx:xx.
+ :returns: the path to the config file.
+
+ """
+ return os.path.join(
+ CONF.pxe.tftp_root,
+ PXE_CFG_DIR_NAME,
+ "01-" + mac.replace(":", "-").lower()
+ )
+
+
+def get_deploy_kr_info(node_uuid, driver_info):
+ """Get uuid and tftp path for deploy kernel and ramdisk.
+
+ Note: driver_info should be validated outside of this method.
+ """
+ image_info = {}
+ for label in ('deploy_kernel', 'deploy_ramdisk'):
+ # the values for these keys will look like "glance://image-uuid"
+ image_info[label] = (
+ str(driver_info[label]).split('/')[-1],
+ os.path.join(CONF.pxe.tftp_root, node_uuid, label)
+ )
+ return image_info
+
+
+def get_pxe_config_file_path(node_uuid):
+ """Generate the path for the node's PXE configuration file.
+
+ :param node_uuid: the UUID of the node.
+ :returns: The path to the node's PXE configuration file.
+
+ """
+ return os.path.join(CONF.pxe.tftp_root, node_uuid, 'config')
+
+
+def create_pxe_config(task, pxe_options, template=None):
+ """Generate PXE configuration file and MAC address links for it.
+
+ This method will generate the PXE configuration file for the task's
+ node under a directory named with the UUID of that node. For each
+ MAC address (port) of that node, a symlink for the configuration file
+ will be created under the PXE configuration directory, so regardless
+ of which port boots first they'll get the same PXE configuration.
+
+ :param task: A TaskManager instance.
+ :param pxe_options: A dictionary with the PXE configuration
+ parameters.
+ :param template: The PXE configuration template. If no template is
+ given the CONF.pxe.pxe_config_template will be used.
+
+ """
+ LOG.debug("Building PXE config for node %s", task.node.uuid)
+
+ if template is None:
+ template = CONF.pxe.pxe_config_template
+
+ _ensure_config_dirs_exist(task.node.uuid)
+
+ pxe_config_file_path = get_pxe_config_file_path(task.node.uuid)
+ pxe_config = _build_pxe_config(pxe_options, template)
+ utils.write_to_file(pxe_config_file_path, pxe_config)
+ _link_mac_pxe_configs(task)
+
+
+def clean_up_pxe_config(task):
+ """Clean up the TFTP environment for the task's node.
+
+ :param task: A TaskManager instance.
+
+ """
+ LOG.debug("Cleaning up PXE config for node %s", task.node.uuid)
+
+ for mac in driver_utils.get_node_mac_addresses(task):
+ utils.unlink_without_raise(_get_pxe_mac_path(mac))
+
+ utils.rmtree_without_raise(os.path.join(CONF.pxe.tftp_root,
+ task.node.uuid))
+
+
+def dhcp_options_for_instance():
+ """Retrieves the DHCP PXE boot options."""
+ return [{'opt_name': 'bootfile-name',
+ 'opt_value': CONF.pxe.pxe_bootfile_name},
+ {'opt_name': 'server-ip-address',
+ 'opt_value': CONF.pxe.tftp_server},
+ {'opt_name': 'tftp-server',
+ 'opt_value': CONF.pxe.tftp_server}
+ ]
diff --git a/ironic/common/tftp.py b/ironic/common/tftp.py
deleted file mode 100644
index 88399e0da..000000000
--- a/ironic/common/tftp.py
+++ /dev/null
@@ -1,140 +0,0 @@
-#
-# Copyright 2014 Rackspace, Inc
-# All Rights Reserved
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import os
-
-import jinja2
-from oslo.config import cfg
-
-from ironic.common import utils
-from ironic.drivers import utils as driver_utils
-from ironic.openstack.common import fileutils
-from ironic.openstack.common import log as logging
-
-
-tftp_opts = [
- cfg.StrOpt('tftp_server',
- default='$my_ip',
- help='IP address of Ironic compute node\'s tftp server.',
- deprecated_group='pxe'),
- cfg.StrOpt('tftp_root',
- default='/tftpboot',
- help='Ironic compute node\'s tftp root path.',
- deprecated_group='pxe')
- ]
-
-CONF = cfg.CONF
-CONF.register_opts(tftp_opts, group='tftp')
-
-LOG = logging.getLogger(__name__)
-
-
-def get_deploy_kr_info(node_uuid, driver_info):
- """Get uuid and tftp path for deploy kernel and ramdisk.
-
- Note: driver_info should be validated outside of this method.
- """
- image_info = {}
- for label in ('deploy_kernel', 'deploy_ramdisk'):
- # the values for these keys will look like "glance://image-uuid"
- image_info[label] = (
- str(driver_info[label]).split('/')[-1],
- os.path.join(CONF.tftp.tftp_root, node_uuid, label)
- )
- return image_info
-
-
-def create_pxe_config(task, pxe_options, pxe_config_template):
- """Generate PXE configuration file and MAC symlinks for it."""
- node = task.node
- fileutils.ensure_tree(os.path.join(CONF.tftp.tftp_root,
- node.uuid))
- fileutils.ensure_tree(os.path.join(CONF.tftp.tftp_root,
- 'pxelinux.cfg'))
-
- pxe_config_file_path = get_pxe_config_file_path(node.uuid)
- pxe_config = build_pxe_config(node, pxe_options, pxe_config_template)
- utils.write_to_file(pxe_config_file_path, pxe_config)
- _write_mac_pxe_configs(task)
-
-
-def clean_up_pxe_config(task):
- """Clean up the TFTP environment for the task's node."""
- node = task.node
-
- utils.unlink_without_raise(get_pxe_config_file_path(node.uuid))
- for port in driver_utils.get_node_mac_addresses(task):
- utils.unlink_without_raise(get_pxe_mac_path(port))
-
- utils.rmtree_without_raise(os.path.join(CONF.tftp.tftp_root, node.uuid))
-
-
-def _write_mac_pxe_configs(task):
- """Create a file in the PXE config directory for each MAC so regardless
- of which port boots first, they'll get the same PXE config.
- """
- pxe_config_file_path = get_pxe_config_file_path(task.node.uuid)
- for port in driver_utils.get_node_mac_addresses(task):
- mac_path = get_pxe_mac_path(port)
- utils.unlink_without_raise(mac_path)
- utils.create_link_without_raise(pxe_config_file_path, mac_path)
-
-
-def build_pxe_config(node, pxe_options, pxe_config_template):
- """Build the PXE config file for a node
-
- This method builds the PXE boot configuration file for a node,
- given all the required parameters.
-
- :param pxe_options: A dict of values to set on the configuration file
- :returns: A formatted string with the file content.
- """
- LOG.debug("Building PXE config for deployment %s."), node['id']
-
- tmpl_path, tmpl_file = os.path.split(pxe_config_template)
- env = jinja2.Environment(loader=jinja2.FileSystemLoader(tmpl_path))
- template = env.get_template(tmpl_file)
- return template.render({'pxe_options': pxe_options,
- 'ROOT': '{{ ROOT }}'})
-
-
-def get_pxe_mac_path(mac):
- """Convert a MAC address into a PXE config file name.
-
- :param mac: A mac address string in the format xx:xx:xx:xx:xx:xx.
- :returns: the path to the config file.
- """
- return os.path.join(
- CONF.tftp.tftp_root,
- 'pxelinux.cfg',
- "01-" + mac.replace(":", "-").lower()
- )
-
-
-def get_pxe_config_file_path(node_uuid):
- """Generate the path for an instances PXE config file."""
- return os.path.join(CONF.tftp.tftp_root, node_uuid, 'config')
-
-
-def dhcp_options_for_instance(pxe_bootfile_name):
- """Retrives the DHCP PXE boot options."""
- return [{'opt_name': 'bootfile-name',
- 'opt_value': pxe_bootfile_name},
- {'opt_name': 'server-ip-address',
- 'opt_value': CONF.tftp.tftp_server},
- {'opt_name': 'tftp-server',
- 'opt_value': CONF.tftp.tftp_server}
- ]