Setting static ip= for baremetal PXE boot.
This patch adds a new option "pxe_network_config" to baremetal PXE driver, if set it tells the driver to append the network configuration to the kernel cmdline. Initramfs built with network support could then benefit from this option and avoid the injection of network configuration files into the image. DocImpact Change-Id: I61dc946f42f8a86eaad0e73b033a0d8da4a74e40
This commit is contained in:
parent
ed6099d77e
commit
68e9b487bf
@ -116,6 +116,7 @@ class PXEClassMethodsTestCase(BareMetalPXETestCase):
|
||||
'deployment_ari_path': 'eee',
|
||||
'aki_path': 'fff',
|
||||
'ari_path': 'ggg',
|
||||
'network_info': self.test_network_info,
|
||||
}
|
||||
config = pxe.build_pxe_config(**args)
|
||||
self.assertThat(config, matchers.StartsWith('default deploy'))
|
||||
@ -140,6 +141,21 @@ class PXEClassMethodsTestCase(BareMetalPXETestCase):
|
||||
matchers.Not(matchers.Contains('kernel ddd')),
|
||||
))
|
||||
|
||||
def test_build_pxe_network_config(self):
|
||||
self.flags(
|
||||
pxe_network_config=True,
|
||||
group='baremetal',
|
||||
)
|
||||
net = utils.get_test_network_info(1)
|
||||
config = pxe.build_pxe_network_config(net)
|
||||
self.assertIn('eth0:off', config)
|
||||
self.assertNotIn('eth1', config)
|
||||
|
||||
net = utils.get_test_network_info(2)
|
||||
config = pxe.build_pxe_network_config(net)
|
||||
self.assertIn('eth0:off', config)
|
||||
self.assertIn('eth1:off', config)
|
||||
|
||||
def test_build_network_config(self):
|
||||
net = utils.get_test_network_info(1)
|
||||
config = pxe.build_network_config(net)
|
||||
@ -458,7 +474,8 @@ class PXEPublicMethodsTestCase(BareMetalPXETestCase):
|
||||
bm_utils.random_alnum(32).AndReturn('alnum')
|
||||
pxe.build_pxe_config(
|
||||
self.node['id'], 'alnum', iqn,
|
||||
'aaaa', 'bbbb', 'cccc', 'dddd').AndReturn(pxe_config)
|
||||
'aaaa', 'bbbb', 'cccc', 'dddd',
|
||||
self.test_network_info).AndReturn(pxe_config)
|
||||
bm_utils.write_to_file(pxe_path, pxe_config)
|
||||
for mac in macs:
|
||||
bm_utils.create_link_without_raise(
|
||||
@ -466,7 +483,8 @@ class PXEPublicMethodsTestCase(BareMetalPXETestCase):
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
self.driver.activate_bootloader(self.context, self.node, self.instance)
|
||||
self.driver.activate_bootloader(self.context, self.node, self.instance,
|
||||
network_info=self.test_network_info)
|
||||
|
||||
self.mox.VerifyAll()
|
||||
|
||||
@ -515,8 +533,8 @@ class PXEPublicMethodsTestCase(BareMetalPXETestCase):
|
||||
row = db.bm_node_get(self.context, 1)
|
||||
self.assertTrue(row['deploy_key'] is None)
|
||||
|
||||
self.driver.activate_bootloader(self.context, self.node,
|
||||
self.instance)
|
||||
self.driver.activate_bootloader(self.context, self.node, self.instance,
|
||||
network_info=self.test_network_info)
|
||||
row = db.bm_node_get(self.context, 1)
|
||||
self.assertTrue(row['deploy_key'] is not None)
|
||||
|
||||
|
@ -317,7 +317,8 @@ class TileraPublicMethodsTestCase(BareMetalTileraTestCase):
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
self.driver.activate_bootloader(self.context, self.node, self.instance)
|
||||
self.driver.activate_bootloader(self.context, self.node, self.instance,
|
||||
network_info=self.test_network_info)
|
||||
|
||||
self.mox.VerifyAll()
|
||||
|
||||
@ -334,8 +335,8 @@ class TileraPublicMethodsTestCase(BareMetalTileraTestCase):
|
||||
row = db.bm_node_get(self.context, 1)
|
||||
self.assertTrue(row['deploy_key'] is None)
|
||||
|
||||
self.driver.activate_bootloader(self.context, self.node,
|
||||
self.instance)
|
||||
self.driver.activate_bootloader(self.context, self.node, self.instance,
|
||||
network_info=self.test_network_info)
|
||||
row = db.bm_node_get(self.context, 1)
|
||||
self.assertTrue(row['deploy_key'] is not None)
|
||||
|
||||
|
@ -30,7 +30,7 @@ class NodeDriver(object):
|
||||
def destroy_images(self, context, node, instance):
|
||||
raise NotImplementedError()
|
||||
|
||||
def activate_bootloader(self, context, node, instance):
|
||||
def activate_bootloader(self, context, node, instance, **kwargs):
|
||||
raise NotImplementedError()
|
||||
|
||||
def deactivate_bootloader(self, context, node, instance):
|
||||
|
@ -248,7 +248,8 @@ class BareMetalDriver(driver.ComputeDriver):
|
||||
injected_files=injected_files,
|
||||
network_info=network_info,
|
||||
)
|
||||
self.driver.activate_bootloader(context, node, instance)
|
||||
self.driver.activate_bootloader(context, node, instance,
|
||||
network_info=network_info)
|
||||
self.power_on(instance, node)
|
||||
self.driver.activate_node(context, node, instance)
|
||||
_update_state(context, node, instance, baremetal_states.ACTIVE)
|
||||
|
@ -28,7 +28,7 @@ class FakeDriver(base.NodeDriver):
|
||||
def destroy_images(self, context, node, instance):
|
||||
pass
|
||||
|
||||
def activate_bootloader(self, context, node, instance):
|
||||
def activate_bootloader(self, context, node, instance, **kwargs):
|
||||
pass
|
||||
|
||||
def deactivate_bootloader(self, context, node, instance):
|
||||
|
@ -54,6 +54,10 @@ pxe_opts = [
|
||||
cfg.IntOpt('pxe_deploy_timeout',
|
||||
help='Timeout for PXE deployments. Default: 0 (unlimited)',
|
||||
default=0),
|
||||
cfg.BoolOpt('pxe_network_config',
|
||||
help='If set, pass the network configuration details to the '
|
||||
'initramfs via cmdline.',
|
||||
default=False),
|
||||
]
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -77,9 +81,22 @@ def _get_cheetah():
|
||||
return CHEETAH
|
||||
|
||||
|
||||
def build_pxe_network_config(network_info):
|
||||
interfaces = bm_utils.map_network_interfaces(network_info, CONF.use_ipv6)
|
||||
template = None
|
||||
if not CONF.use_ipv6:
|
||||
template = "ip=%(address)s::%(gateway)s:%(netmask)s::%(name)s:off"
|
||||
else:
|
||||
template = ("ip=[%(address_v6)s]::[%(gateway_v6)s]:"
|
||||
"[%(netmask_v6)s]::%(name)s:off")
|
||||
|
||||
net_config = [template % iface for iface in interfaces]
|
||||
return ' '.join(net_config)
|
||||
|
||||
|
||||
def build_pxe_config(deployment_id, deployment_key, deployment_iscsi_iqn,
|
||||
deployment_aki_path, deployment_ari_path,
|
||||
aki_path, ari_path):
|
||||
aki_path, ari_path, network_info):
|
||||
"""Build the PXE config file for a node
|
||||
|
||||
This method builds the PXE boot configuration file for a node,
|
||||
@ -90,6 +107,11 @@ def build_pxe_config(deployment_id, deployment_key, deployment_iscsi_iqn,
|
||||
|
||||
"""
|
||||
LOG.debug(_("Building PXE config for deployment %s.") % deployment_id)
|
||||
|
||||
network_config = None
|
||||
if network_info and CONF.baremetal.pxe_network_config:
|
||||
network_config = build_pxe_network_config(network_info)
|
||||
|
||||
pxe_options = {
|
||||
'deployment_id': deployment_id,
|
||||
'deployment_key': deployment_key,
|
||||
@ -99,6 +121,7 @@ def build_pxe_config(deployment_id, deployment_key, deployment_iscsi_iqn,
|
||||
'aki_path': aki_path,
|
||||
'ari_path': ari_path,
|
||||
'pxe_append_params': CONF.baremetal.pxe_append_params,
|
||||
'pxe_network_config': network_config,
|
||||
}
|
||||
cheetah = _get_cheetah()
|
||||
pxe_config = str(cheetah(
|
||||
@ -110,33 +133,7 @@ def build_pxe_config(deployment_id, deployment_key, deployment_iscsi_iqn,
|
||||
|
||||
|
||||
def build_network_config(network_info):
|
||||
# TODO(deva): fix assumption that device names begin with "eth"
|
||||
# and fix assumption about ordering
|
||||
try:
|
||||
assert isinstance(network_info, list)
|
||||
except AssertionError:
|
||||
network_info = [network_info]
|
||||
interfaces = []
|
||||
for id, (network, mapping) in enumerate(network_info):
|
||||
address_v6 = None
|
||||
gateway_v6 = None
|
||||
netmask_v6 = None
|
||||
if CONF.use_ipv6:
|
||||
address_v6 = mapping['ip6s'][0]['ip']
|
||||
netmask_v6 = mapping['ip6s'][0]['netmask']
|
||||
gateway_v6 = mapping['gateway_v6']
|
||||
interface = {
|
||||
'name': 'eth%d' % id,
|
||||
'address': mapping['ips'][0]['ip'],
|
||||
'gateway': mapping['gateway'],
|
||||
'netmask': mapping['ips'][0]['netmask'],
|
||||
'dns': ' '.join(mapping['dns']),
|
||||
'address_v6': address_v6,
|
||||
'gateway_v6': gateway_v6,
|
||||
'netmask_v6': netmask_v6,
|
||||
}
|
||||
interfaces.append(interface)
|
||||
|
||||
interfaces = bm_utils.map_network_interfaces(network_info, CONF.use_ipv6)
|
||||
cheetah = _get_cheetah()
|
||||
network_config = str(cheetah(
|
||||
open(CONF.baremetal.net_config_template).read(),
|
||||
@ -354,7 +351,7 @@ class PXE(base.NodeDriver):
|
||||
bm_utils.unlink_without_raise(get_image_file_path(instance))
|
||||
bm_utils.rmtree_without_raise(get_image_dir_path(instance))
|
||||
|
||||
def activate_bootloader(self, context, node, instance):
|
||||
def activate_bootloader(self, context, node, instance, network_info):
|
||||
"""Configure PXE boot loader for an instance
|
||||
|
||||
Kernel and ramdisk images are downloaded by cache_tftp_images,
|
||||
@ -398,6 +395,7 @@ class PXE(base.NodeDriver):
|
||||
image_info['deploy_ramdisk'][1],
|
||||
image_info['kernel'][1],
|
||||
image_info['ramdisk'][1],
|
||||
network_info,
|
||||
)
|
||||
bm_utils.write_to_file(pxe_config_file_path, pxe_config)
|
||||
|
||||
|
@ -8,4 +8,4 @@ ipappend 3
|
||||
|
||||
label boot
|
||||
kernel ${pxe_options.aki_path}
|
||||
append initrd=${pxe_options.ari_path} root=${ROOT} ro ${pxe_options.pxe_append_params}
|
||||
append initrd=${pxe_options.ari_path} root=${ROOT} ro ${pxe_options.pxe_append_params} ${pxe_options.pxe_network_config}
|
||||
|
@ -64,31 +64,7 @@ def _get_cheetah():
|
||||
|
||||
|
||||
def build_network_config(network_info):
|
||||
try:
|
||||
assert isinstance(network_info, list)
|
||||
except AssertionError:
|
||||
network_info = [network_info]
|
||||
interfaces = []
|
||||
for id, (network, mapping) in enumerate(network_info):
|
||||
address_v6 = None
|
||||
gateway_v6 = None
|
||||
netmask_v6 = None
|
||||
if CONF.use_ipv6:
|
||||
address_v6 = mapping['ip6s'][0]['ip']
|
||||
netmask_v6 = mapping['ip6s'][0]['netmask']
|
||||
gateway_v6 = mapping['gateway_v6']
|
||||
interface = {
|
||||
'name': 'eth%d' % id,
|
||||
'address': mapping['ips'][0]['ip'],
|
||||
'gateway': mapping['gateway'],
|
||||
'netmask': mapping['ips'][0]['netmask'],
|
||||
'dns': ' '.join(mapping['dns']),
|
||||
'address_v6': address_v6,
|
||||
'gateway_v6': gateway_v6,
|
||||
'netmask_v6': netmask_v6,
|
||||
}
|
||||
interfaces.append(interface)
|
||||
|
||||
interfaces = bm_utils.map_network_interfaces(network_info, CONF.use_ipv6)
|
||||
cheetah = _get_cheetah()
|
||||
network_config = str(cheetah(
|
||||
open(CONF.baremetal.net_config_template).read(),
|
||||
@ -271,7 +247,7 @@ class Tilera(base.NodeDriver):
|
||||
bm_utils.unlink_without_raise(get_image_file_path(instance))
|
||||
bm_utils.rmtree_without_raise(get_image_dir_path(instance))
|
||||
|
||||
def activate_bootloader(self, context, node, instance):
|
||||
def activate_bootloader(self, context, node, instance, network_info):
|
||||
"""Configure Tilera boot loader for an instance
|
||||
|
||||
Kernel and ramdisk images are downloaded by cache_tftp_images,
|
||||
|
@ -81,3 +81,32 @@ def random_alnum(count):
|
||||
import string
|
||||
chars = string.ascii_uppercase + string.digits
|
||||
return "".join(random.choice(chars) for _ in range(count))
|
||||
|
||||
|
||||
def map_network_interfaces(network_info, use_ipv6=False):
|
||||
# TODO(deva): fix assumption that device names begin with "eth"
|
||||
# and fix assumption about ordering
|
||||
if not isinstance(network_info, list):
|
||||
network_info = [network_info]
|
||||
|
||||
interfaces = []
|
||||
for id, (network, mapping) in enumerate(network_info):
|
||||
address_v6 = None
|
||||
gateway_v6 = None
|
||||
netmask_v6 = None
|
||||
if use_ipv6:
|
||||
address_v6 = mapping['ip6s'][0]['ip']
|
||||
netmask_v6 = mapping['ip6s'][0]['netmask']
|
||||
gateway_v6 = mapping['gateway_v6']
|
||||
interface = {
|
||||
'name': 'eth%d' % id,
|
||||
'address': mapping['ips'][0]['ip'],
|
||||
'gateway': mapping['gateway'],
|
||||
'netmask': mapping['ips'][0]['netmask'],
|
||||
'dns': ' '.join(mapping['dns']),
|
||||
'address_v6': address_v6,
|
||||
'gateway_v6': gateway_v6,
|
||||
'netmask_v6': netmask_v6,
|
||||
}
|
||||
interfaces.append(interface)
|
||||
return interfaces
|
||||
|
Loading…
Reference in New Issue
Block a user