Merge "PXE: Pass root device hints via kernel cmdline"
This commit is contained in:
@@ -3,7 +3,7 @@ default=deploy
|
||||
image={{pxe_options.deployment_aki_path}}
|
||||
label=deploy
|
||||
initrd={{pxe_options.deployment_ari_path}}
|
||||
append="rootfstype=ramfs selinux=0 disk={{ pxe_options.disk }} iscsi_target_iqn={{ pxe_options.iscsi_target_iqn }} deployment_id={{ pxe_options.deployment_id }} deployment_key={{ pxe_options.deployment_key }} ironic_api_url={{ pxe_options.ironic_api_url }} troubleshoot=0 text {{ pxe_options.pxe_append_params|default("", true) }} ip=%I:{{pxe_options.tftp_server}}:%G:%M:%H::on"
|
||||
append="rootfstype=ramfs selinux=0 disk={{ pxe_options.disk }} iscsi_target_iqn={{ pxe_options.iscsi_target_iqn }} deployment_id={{ pxe_options.deployment_id }} deployment_key={{ pxe_options.deployment_key }} ironic_api_url={{ pxe_options.ironic_api_url }} troubleshoot=0 text {{ pxe_options.pxe_append_params|default("", true) }} ip=%I:{{pxe_options.tftp_server}}:%G:%M:%H::on" {% if pxe_options.root_device %}root_device={{ pxe_options.root_device }}{% endif %}
|
||||
|
||||
image={{pxe_options.aki_path}}
|
||||
label=boot
|
||||
|
||||
@@ -5,7 +5,7 @@ dhcp
|
||||
goto deploy
|
||||
|
||||
:deploy
|
||||
kernel {{ pxe_options.deployment_aki_path }} selinux=0 disk={{ pxe_options.disk }} iscsi_target_iqn={{ pxe_options.iscsi_target_iqn }} deployment_id={{ pxe_options.deployment_id }} deployment_key={{ pxe_options.deployment_key }} ironic_api_url={{ pxe_options.ironic_api_url }} troubleshoot=0 text {{ pxe_options.pxe_append_params|default("", true) }} ip=${ip}:${next-server}:${gateway}:${netmask} BOOTIF=${mac}
|
||||
kernel {{ pxe_options.deployment_aki_path }} selinux=0 disk={{ pxe_options.disk }} iscsi_target_iqn={{ pxe_options.iscsi_target_iqn }} deployment_id={{ pxe_options.deployment_id }} deployment_key={{ pxe_options.deployment_key }} ironic_api_url={{ pxe_options.ironic_api_url }} troubleshoot=0 text {{ pxe_options.pxe_append_params|default("", true) }} ip=${ip}:${next-server}:${gateway}:${netmask} BOOTIF=${mac} {% if pxe_options.root_device %}root_device={{ pxe_options.root_device }}{% endif %}
|
||||
initrd {{ pxe_options.deployment_ari_path }}
|
||||
boot
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ import os
|
||||
|
||||
from oslo.config import cfg
|
||||
from oslo.utils import strutils
|
||||
import six
|
||||
from six.moves.urllib import parse
|
||||
|
||||
from ironic.common import exception
|
||||
from ironic.common.i18n import _
|
||||
@@ -284,6 +286,36 @@ def continue_deploy(task, **kwargs):
|
||||
return root_uuid
|
||||
|
||||
|
||||
def parse_root_device_hints(node):
|
||||
"""Parse the root_device property of a node.
|
||||
|
||||
Parse the root_device property of a node and make it a flat string
|
||||
to be passed via the PXE config.
|
||||
|
||||
:param node: a single Node.
|
||||
:returns: A flat string with the following format
|
||||
opt1=value1,opt2=value2. Or None if the
|
||||
Node contains no hints.
|
||||
|
||||
"""
|
||||
root_device = node.properties.get('root_device')
|
||||
if not root_device:
|
||||
return
|
||||
|
||||
hints = []
|
||||
for key, value in root_device.items():
|
||||
# NOTE(lucasagomes): We can't have spaces in the PXE config
|
||||
# file, so we are going to url/percent encode the value here
|
||||
# and decode on the other end.
|
||||
if isinstance(value, six.string_types):
|
||||
value = value.strip()
|
||||
value = parse.quote(value)
|
||||
|
||||
hints.append("%s=%s" % (key, value))
|
||||
|
||||
return ','.join(hints)
|
||||
|
||||
|
||||
def build_deploy_ramdisk_options(node):
|
||||
"""Build the ramdisk config options for a node
|
||||
|
||||
@@ -312,6 +344,11 @@ def build_deploy_ramdisk_options(node):
|
||||
'ironic_api_url': ironic_api,
|
||||
'disk': CONF.pxe.disk_devices,
|
||||
}
|
||||
|
||||
root_device = parse_root_device_hints(node)
|
||||
if root_device:
|
||||
deploy_options['root_device'] = root_device
|
||||
|
||||
return deploy_options
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ default deploy
|
||||
|
||||
label deploy
|
||||
kernel {{ pxe_options.deployment_aki_path }}
|
||||
append initrd={{ pxe_options.deployment_ari_path }} rootfstype=ramfs selinux=0 disk={{ pxe_options.disk }} iscsi_target_iqn={{ pxe_options.iscsi_target_iqn }} deployment_id={{ pxe_options.deployment_id }} deployment_key={{ pxe_options.deployment_key }} ironic_api_url={{ pxe_options.ironic_api_url }} troubleshoot=0 text {{ pxe_options.pxe_append_params|default("", true) }}
|
||||
append initrd={{ pxe_options.deployment_ari_path }} rootfstype=ramfs selinux=0 disk={{ pxe_options.disk }} iscsi_target_iqn={{ pxe_options.iscsi_target_iqn }} deployment_id={{ pxe_options.deployment_id }} deployment_key={{ pxe_options.deployment_key }} ironic_api_url={{ pxe_options.ironic_api_url }} troubleshoot=0 text {{ pxe_options.pxe_append_params|default("", true) }} {% if pxe_options.root_device %}root_device={{ pxe_options.root_device }}{% endif %}
|
||||
ipappend 3
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ default deploy
|
||||
|
||||
label deploy
|
||||
kernel /tftpboot/1be26c0b-03f2-4d2e-ae87-c02d7f33c123/deploy_kernel
|
||||
append initrd=/tftpboot/1be26c0b-03f2-4d2e-ae87-c02d7f33c123/deploy_ramdisk rootfstype=ramfs selinux=0 disk=cciss/c0d0,sda,hda,vda iscsi_target_iqn=iqn-1be26c0b-03f2-4d2e-ae87-c02d7f33c123 deployment_id=1be26c0b-03f2-4d2e-ae87-c02d7f33c123 deployment_key=0123456789ABCDEFGHIJKLMNOPQRSTUV ironic_api_url=http://192.168.122.184:6385 troubleshoot=0 text test_param
|
||||
append initrd=/tftpboot/1be26c0b-03f2-4d2e-ae87-c02d7f33c123/deploy_ramdisk rootfstype=ramfs selinux=0 disk=cciss/c0d0,sda,hda,vda iscsi_target_iqn=iqn-1be26c0b-03f2-4d2e-ae87-c02d7f33c123 deployment_id=1be26c0b-03f2-4d2e-ae87-c02d7f33c123 deployment_key=0123456789ABCDEFGHIJKLMNOPQRSTUV ironic_api_url=http://192.168.122.184:6385 troubleshoot=0 text test_param root_device=vendor=fake,size=123
|
||||
ipappend 3
|
||||
|
||||
|
||||
|
||||
@@ -205,7 +205,8 @@ class IscsiDeployMethodsTestCase(db_base.DbTestCase):
|
||||
mock_unlink.assert_called_once_with('/path/uuid/disk')
|
||||
mock_rmtree.assert_called_once_with('/path/uuid')
|
||||
|
||||
def _test_build_deploy_ramdisk_options(self, mock_alnum, api_url):
|
||||
def _test_build_deploy_ramdisk_options(self, mock_alnum, api_url,
|
||||
expected_root_device=None):
|
||||
fake_key = '0123456789ABCDEFGHIJKLMNOPQRSTUV'
|
||||
fake_disk = 'fake-disk'
|
||||
|
||||
@@ -219,6 +220,9 @@ class IscsiDeployMethodsTestCase(db_base.DbTestCase):
|
||||
'disk': fake_disk,
|
||||
'ironic_api_url': api_url}
|
||||
|
||||
if expected_root_device:
|
||||
expected_opts['root_device'] = expected_root_device
|
||||
|
||||
opts = iscsi_deploy.build_deploy_ramdisk_options(self.node)
|
||||
|
||||
self.assertEqual(expected_opts, opts)
|
||||
@@ -248,3 +252,31 @@ class IscsiDeployMethodsTestCase(db_base.DbTestCase):
|
||||
# As the Ironic api url is not specified in the config file
|
||||
# assert we are getting it from keystone
|
||||
mock_get_url.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(keystone, 'get_service_url')
|
||||
@mock.patch.object(utils, 'random_alnum')
|
||||
def test_build_deploy_ramdisk_options_root_device(self, mock_alnum,
|
||||
mock_get_url):
|
||||
self.node.properties['root_device'] = {'wwn': 123456}
|
||||
expected = 'wwn=123456'
|
||||
fake_api_url = 'http://127.0.0.1:6385'
|
||||
self.config(api_url=fake_api_url, group='conductor')
|
||||
self._test_build_deploy_ramdisk_options(mock_alnum, fake_api_url,
|
||||
expected_root_device=expected)
|
||||
|
||||
def test_parse_root_device_hints(self):
|
||||
self.node.properties['root_device'] = {'wwn': 123456}
|
||||
expected = 'wwn=123456'
|
||||
result = iscsi_deploy.parse_root_device_hints(self.node)
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
def test_parse_root_device_hints_string_space(self):
|
||||
self.node.properties['root_device'] = {'model': 'fake model'}
|
||||
expected = 'model=fake%20model'
|
||||
result = iscsi_deploy.parse_root_device_hints(self.node)
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
def test_parse_root_device_hints_no_hints(self):
|
||||
self.node.properties = {}
|
||||
result = iscsi_deploy.parse_root_device_hints(self.node)
|
||||
self.assertIsNone(result)
|
||||
|
||||
@@ -48,7 +48,8 @@ class TestPXEUtils(db_base.DbTestCase):
|
||||
'ironic_api_url': 'http://192.168.122.184:6385',
|
||||
'deployment_aki_path': u'/tftpboot/1be26c0b-03f2-4d2e-ae87-'
|
||||
u'c02d7f33c123/deploy_kernel',
|
||||
'disk': 'cciss/c0d0,sda,hda,vda'
|
||||
'disk': 'cciss/c0d0,sda,hda,vda',
|
||||
'root_device': 'vendor=fake,size=123'
|
||||
}
|
||||
self.agent_pxe_options = {
|
||||
'deployment_ari_path': u'/tftpboot/1be26c0b-03f2-4d2e-ae87-c02d7'
|
||||
|
||||
Reference in New Issue
Block a user