nova-less-deploy: stop using glance for ironic-python-agent images
Ironic can use HTTP links or local files, and we already put the images to a location accessible inside of ironic containers (for introspection). This change switches to using file images for IPA. The existing Glance images are not deleted since some nodes may be using them. Multi-arch layout of [[PLATFORM-]ARCH/]agent.EXT is reused from the unit tests of the `image upload` command, assuming that's what people are using. Change-Id: Ie6fa04112e3348f429dc42b28442f8996ab03f29 Implements: blueprint nova-less-deploy Depends-On: https://review.opendev.org/#/c/663897/
This commit is contained in:
parent
aa62e89e88
commit
7ad1b812fc
|
@ -1341,36 +1341,36 @@ class TestDeployNameScenarios(TestWithScenarios):
|
|||
scenarios = [
|
||||
('kernel_default',
|
||||
dict(func=utils.deploy_kernel,
|
||||
expected=('bm-deploy-kernel', '.kernel'))),
|
||||
expected='agent.kernel')),
|
||||
('kernel_arch',
|
||||
dict(func=utils.deploy_kernel,
|
||||
arch='x86_64',
|
||||
expected=('x86_64-bm-deploy-kernel', '.kernel'))),
|
||||
expected='x86_64/agent.kernel')),
|
||||
('kernel_arch_platform',
|
||||
dict(func=utils.deploy_kernel,
|
||||
arch='x86_64',
|
||||
platform='SNB',
|
||||
expected=('SNB-x86_64-bm-deploy-kernel', '.kernel'))),
|
||||
expected='SNB-x86_64/agent.kernel')),
|
||||
('kernel_platform',
|
||||
dict(func=utils.deploy_kernel,
|
||||
platform='SNB',
|
||||
expected=('bm-deploy-kernel', '.kernel'))),
|
||||
expected='agent.kernel')),
|
||||
('ramdisk_default',
|
||||
dict(func=utils.deploy_ramdisk,
|
||||
expected=('bm-deploy-ramdisk', '.initramfs'))),
|
||||
expected='agent.ramdisk')),
|
||||
('ramdisk_arch',
|
||||
dict(func=utils.deploy_ramdisk,
|
||||
arch='x86_64',
|
||||
expected=('x86_64-bm-deploy-ramdisk', '.initramfs'))),
|
||||
expected='x86_64/agent.ramdisk')),
|
||||
('ramdisk_arch_platform',
|
||||
dict(func=utils.deploy_ramdisk,
|
||||
arch='x86_64',
|
||||
platform='SNB',
|
||||
expected=('SNB-x86_64-bm-deploy-ramdisk', '.initramfs'))),
|
||||
expected='SNB-x86_64/agent.ramdisk')),
|
||||
('ramdisk_platform',
|
||||
dict(func=utils.deploy_ramdisk,
|
||||
platform='SNB',
|
||||
expected=('bm-deploy-ramdisk', '.initramfs'))),
|
||||
expected='agent.ramdisk')),
|
||||
]
|
||||
|
||||
def test_deploy_params(self):
|
||||
|
|
|
@ -234,7 +234,7 @@ class TestUploadOvercloudImage(TestPluginV1):
|
|||
self.app.client_manager.image.images.delete.call_count
|
||||
)
|
||||
self.assertEqual(
|
||||
5,
|
||||
3,
|
||||
self.app.client_manager.image.images.create.call_count
|
||||
)
|
||||
self.app.client_manager.image.images.create.assert_has_calls([
|
||||
|
@ -250,14 +250,6 @@ class TestUploadOvercloudImage(TestPluginV1):
|
|||
disk_format='qcow2',
|
||||
container_format='bare',
|
||||
visibility='public'),
|
||||
mock.call(name='bm-deploy-kernel',
|
||||
disk_format='aki',
|
||||
container_format='bare',
|
||||
visibility='public'),
|
||||
mock.call(name='bm-deploy-ramdisk',
|
||||
disk_format='ari',
|
||||
container_format='bare',
|
||||
visibility='public')
|
||||
])
|
||||
|
||||
self.assertEqual(mock_subprocess_call.call_count, 2)
|
||||
|
@ -285,7 +277,7 @@ class TestUploadOvercloudImage(TestPluginV1):
|
|||
self.app.client_manager.image.images.delete.call_count
|
||||
)
|
||||
self.assertEqual(
|
||||
5,
|
||||
3,
|
||||
self.app.client_manager.image.images.create.call_count
|
||||
)
|
||||
self.app.client_manager.image.images.create.assert_has_calls([
|
||||
|
@ -306,16 +298,6 @@ class TestUploadOvercloudImage(TestPluginV1):
|
|||
container_format='bare',
|
||||
disk_format='qcow2',
|
||||
is_public=True),
|
||||
mock.call(properties={'hw_architecture': self._arch},
|
||||
data=b'IMGDATA',
|
||||
name='bm-deploy-kernel',
|
||||
disk_format='aki',
|
||||
is_public=True),
|
||||
mock.call(properties={'hw_architecture': self._arch},
|
||||
data=b'IMGDATA',
|
||||
name='bm-deploy-ramdisk',
|
||||
disk_format='ari',
|
||||
is_public=True)
|
||||
])
|
||||
|
||||
@mock.patch('os.path.isfile', autospec=True)
|
||||
|
@ -335,7 +317,7 @@ class TestUploadOvercloudImage(TestPluginV1):
|
|||
self.app.client_manager.image.images.delete.call_count
|
||||
)
|
||||
self.assertEqual(
|
||||
5,
|
||||
3,
|
||||
self.app.client_manager.image.images.create.call_count
|
||||
)
|
||||
self.app.client_manager.image.images.create.assert_has_calls([
|
||||
|
@ -356,16 +338,6 @@ class TestUploadOvercloudImage(TestPluginV1):
|
|||
container_format='bare',
|
||||
disk_format='qcow2',
|
||||
is_public=True),
|
||||
mock.call(properties={'hw_architecture': 'x86_64'},
|
||||
data=b'IMGDATA',
|
||||
name='x86_64-bm-deploy-kernel',
|
||||
disk_format='aki',
|
||||
is_public=True),
|
||||
mock.call(properties={'hw_architecture': 'x86_64'},
|
||||
data=b'IMGDATA',
|
||||
name='x86_64-bm-deploy-ramdisk',
|
||||
disk_format='ari',
|
||||
is_public=True)
|
||||
])
|
||||
|
||||
self.assertEqual(mock_subprocess_call.call_count, 2)
|
||||
|
@ -395,11 +367,12 @@ class TestUploadOvercloudImage(TestPluginV1):
|
|||
mock.ANY),
|
||||
mock.call('overcloud-full', '/foo/overcloud-full.qcow2',
|
||||
mock.ANY),
|
||||
mock.call('bm-deploy-kernel', '/foo/ironic-python-agent.kernel',
|
||||
mock.ANY),
|
||||
mock.call('bm-deploy-ramdisk',
|
||||
'/foo/ironic-python-agent.initramfs',
|
||||
mock.ANY),
|
||||
])
|
||||
mock_subprocess_call.assert_has_calls([
|
||||
mock.call('sudo cp -f "/foo/ironic-python-agent.kernel" '
|
||||
'"/var/lib/ironic/httpboot/agent.kernel"', shell=True),
|
||||
mock.call('sudo cp -f "/foo/ironic-python-agent.initramfs" '
|
||||
'"/var/lib/ironic/httpboot/agent.ramdisk"', shell=True)
|
||||
])
|
||||
|
||||
@mock.patch('os.path.isfile', autospec=True)
|
||||
|
@ -455,11 +428,11 @@ class TestUploadOvercloudImage(TestPluginV1):
|
|||
self.app.client_manager.image.images.delete.call_count
|
||||
)
|
||||
self.assertEqual(
|
||||
5,
|
||||
3,
|
||||
self.app.client_manager.image.images.create.call_count
|
||||
)
|
||||
self.assertEqual(
|
||||
10, # 5 for new uploads, 5 updating the existsing
|
||||
6, # 3 for new uploads, 3 updating the existsing
|
||||
self.app.client_manager.image.images.update.call_count
|
||||
)
|
||||
self.assertEqual(mock_subprocess_call.call_count, 2)
|
||||
|
@ -498,7 +471,7 @@ class TestUploadOvercloudImageFull(TestPluginV1):
|
|||
self.app.client_manager.image.images.delete.call_count
|
||||
)
|
||||
self.assertEqual(
|
||||
3,
|
||||
1,
|
||||
self.app.client_manager.image.images.create.call_count
|
||||
)
|
||||
|
||||
|
@ -507,20 +480,10 @@ class TestUploadOvercloudImageFull(TestPluginV1):
|
|||
disk_format='qcow2',
|
||||
container_format='bare',
|
||||
visibility='public'),
|
||||
mock.call(name='bm-deploy-kernel',
|
||||
disk_format='aki',
|
||||
container_format='bare',
|
||||
visibility='public'),
|
||||
mock.call(name='bm-deploy-ramdisk',
|
||||
disk_format='ari',
|
||||
container_format='bare',
|
||||
visibility='public')
|
||||
])
|
||||
# properties are set by updating the image
|
||||
self.app.client_manager.image.images.update.assert_has_calls([
|
||||
mock.call(mock.ANY, hw_architecture=self._arch),
|
||||
mock.call(mock.ANY, hw_architecture=self._arch),
|
||||
mock.call(mock.ANY, hw_architecture=self._arch),
|
||||
])
|
||||
|
||||
self.assertEqual(mock_subprocess_call.call_count, 2)
|
||||
|
@ -549,7 +512,7 @@ class TestUploadOvercloudImageFull(TestPluginV1):
|
|||
self.app.client_manager.image.images.delete.call_count
|
||||
)
|
||||
self.assertEqual(
|
||||
3,
|
||||
1,
|
||||
self.app.client_manager.image.images.create.call_count
|
||||
)
|
||||
|
||||
|
@ -558,20 +521,10 @@ class TestUploadOvercloudImageFull(TestPluginV1):
|
|||
disk_format='qcow2',
|
||||
container_format='bare',
|
||||
visibility='public'),
|
||||
mock.call(name='x86_64-bm-deploy-kernel',
|
||||
disk_format='aki',
|
||||
container_format='bare',
|
||||
visibility='public'),
|
||||
mock.call(name='x86_64-bm-deploy-ramdisk',
|
||||
disk_format='ari',
|
||||
container_format='bare',
|
||||
visibility='public')
|
||||
])
|
||||
|
||||
self.app.client_manager.image.images.update.assert_has_calls([
|
||||
mock.call(mock.ANY, hw_architecture='x86_64'),
|
||||
mock.call(mock.ANY, hw_architecture='x86_64'),
|
||||
mock.call(mock.ANY, hw_architecture='x86_64'),
|
||||
])
|
||||
self.assertEqual(mock_subprocess_call.call_count, 2)
|
||||
mock_subprocess_call.assert_has_calls([
|
||||
|
@ -632,11 +585,11 @@ class TestUploadOvercloudImageFull(TestPluginV1):
|
|||
self.app.client_manager.image.images.delete.call_count
|
||||
)
|
||||
self.assertEqual(
|
||||
3,
|
||||
1,
|
||||
self.app.client_manager.image.images.create.call_count
|
||||
)
|
||||
self.assertEqual(
|
||||
6, # update 3 images *and* add properties to 3 images
|
||||
2, # update 1 image *and* add properties to 1 image
|
||||
self.app.client_manager.image.images.update.call_count
|
||||
)
|
||||
self.assertEqual(mock_subprocess_call.call_count, 2)
|
||||
|
@ -698,7 +651,7 @@ class TestUploadOvercloudImageFullMultiArch(TestPluginV1):
|
|||
self.app.client_manager.image.images.delete.call_count
|
||||
)
|
||||
self.assertEqual(
|
||||
6,
|
||||
2,
|
||||
self.app.client_manager.image.images.create.call_count
|
||||
)
|
||||
|
||||
|
@ -707,32 +660,15 @@ class TestUploadOvercloudImageFullMultiArch(TestPluginV1):
|
|||
disk_format='qcow2',
|
||||
container_format='bare',
|
||||
visibility='public'),
|
||||
mock.call(name='bm-deploy-kernel',
|
||||
disk_format='aki',
|
||||
container_format='bare',
|
||||
visibility='public'),
|
||||
mock.call(name='bm-deploy-ramdisk',
|
||||
disk_format='ari',
|
||||
container_format='bare',
|
||||
visibility='public'),
|
||||
mock.call(name='ppc64le-overcloud-full',
|
||||
disk_format='qcow2',
|
||||
container_format='bare',
|
||||
visibility='public'),
|
||||
mock.call(name='ppc64le-bm-deploy-kernel',
|
||||
disk_format='aki',
|
||||
container_format='bare',
|
||||
visibility='public'),
|
||||
mock.call(name='ppc64le-bm-deploy-ramdisk',
|
||||
disk_format='ari',
|
||||
container_format='bare',
|
||||
visibility='public')
|
||||
])
|
||||
|
||||
self.app.client_manager.image.images.update.assert_has_calls([
|
||||
mock.call(13, hw_architecture='ppc64le'),
|
||||
mock.call(14, hw_architecture='ppc64le'),
|
||||
mock.call(15, hw_architecture='ppc64le'),
|
||||
mock.call(10, hw_architecture='x86_64'),
|
||||
mock.call(11, hw_architecture='ppc64le'),
|
||||
])
|
||||
self.assertEqual(mock_subprocess_call.call_count, 4)
|
||||
mock_subprocess_call.assert_has_calls([
|
||||
|
@ -779,7 +715,7 @@ class TestUploadOvercloudImageFullMultiArch(TestPluginV1):
|
|||
self.app.client_manager.image.images.delete.call_count
|
||||
)
|
||||
self.assertEqual(
|
||||
9,
|
||||
3,
|
||||
self.app.client_manager.image.images.create.call_count
|
||||
)
|
||||
|
||||
|
@ -788,47 +724,20 @@ class TestUploadOvercloudImageFullMultiArch(TestPluginV1):
|
|||
disk_format='qcow2',
|
||||
container_format='bare',
|
||||
visibility='public'),
|
||||
mock.call(name='bm-deploy-kernel',
|
||||
disk_format='aki',
|
||||
container_format='bare',
|
||||
visibility='public'),
|
||||
mock.call(name='bm-deploy-ramdisk',
|
||||
disk_format='ari',
|
||||
container_format='bare',
|
||||
visibility='public'),
|
||||
mock.call(name='ppc64le-overcloud-full',
|
||||
disk_format='qcow2',
|
||||
container_format='bare',
|
||||
visibility='public'),
|
||||
mock.call(name='ppc64le-bm-deploy-kernel',
|
||||
disk_format='aki',
|
||||
container_format='bare',
|
||||
visibility='public'),
|
||||
mock.call(name='ppc64le-bm-deploy-ramdisk',
|
||||
disk_format='ari',
|
||||
container_format='bare',
|
||||
visibility='public'),
|
||||
mock.call(name='p9-ppc64le-overcloud-full',
|
||||
disk_format='qcow2',
|
||||
container_format='bare',
|
||||
visibility='public'),
|
||||
mock.call(name='p9-ppc64le-bm-deploy-kernel',
|
||||
disk_format='aki',
|
||||
container_format='bare',
|
||||
visibility='public'),
|
||||
mock.call(name='p9-ppc64le-bm-deploy-ramdisk',
|
||||
disk_format='ari',
|
||||
container_format='bare',
|
||||
visibility='public')
|
||||
])
|
||||
|
||||
self.app.client_manager.image.images.update.assert_has_calls([
|
||||
mock.call(13, hw_architecture='ppc64le'),
|
||||
mock.call(14, hw_architecture='ppc64le'),
|
||||
mock.call(15, hw_architecture='ppc64le'),
|
||||
mock.call(16, hw_architecture='ppc64le', tripleo_platform='p9'),
|
||||
mock.call(17, hw_architecture='ppc64le', tripleo_platform='p9'),
|
||||
mock.call(18, hw_architecture='ppc64le', tripleo_platform='p9'),
|
||||
mock.call(10, hw_architecture='x86_64'),
|
||||
mock.call(11, hw_architecture='ppc64le'),
|
||||
mock.call(12, hw_architecture='ppc64le', tripleo_platform='p9'),
|
||||
])
|
||||
self.assertEqual(mock_subprocess.call_count, 6)
|
||||
mock_subprocess.assert_has_calls([
|
||||
|
@ -880,12 +789,7 @@ class TestUploadOnlyExisting(TestPluginV1):
|
|||
[mock.call('./ironic-python-agent.initramfs'),
|
||||
mock.call('./ironic-python-agent.kernel')])
|
||||
|
||||
# ensure try_update has been called just with ipa
|
||||
files = []
|
||||
for item in self.cmd._image_try_update.call_args_list:
|
||||
files.append(item[0][1])
|
||||
self.assertEqual(files, ['./ironic-python-agent.kernel',
|
||||
'./ironic-python-agent.initramfs'])
|
||||
self.assertFalse(self.cmd._image_try_update.called)
|
||||
|
||||
@mock.patch('subprocess.check_call', autospec=True)
|
||||
@mock.patch('os.path.isfile', autospec=True)
|
||||
|
@ -930,12 +834,7 @@ class TestUploadOnlyExisting(TestPluginV1):
|
|||
[mock.call('./ironic-python-agent.initramfs'),
|
||||
mock.call('./ironic-python-agent.kernel')])
|
||||
|
||||
# ensure try_update has been called just with ipa
|
||||
files = []
|
||||
for item in self.cmd._image_try_update.call_args_list:
|
||||
files.append(item[0][1])
|
||||
self.assertEqual(files, ['./ironic-python-agent.kernel',
|
||||
'./ironic-python-agent.initramfs'])
|
||||
self.assertFalse(self.cmd._image_try_update.called)
|
||||
|
||||
@mock.patch('subprocess.check_call', autospec=True)
|
||||
@mock.patch('os.path.isfile', autospec=True)
|
||||
|
|
|
@ -20,6 +20,7 @@ import mock
|
|||
import os
|
||||
import tempfile
|
||||
|
||||
import fixtures
|
||||
from osc_lib import exceptions as oscexc
|
||||
from osc_lib.tests import utils as test_utils
|
||||
import yaml
|
||||
|
@ -486,11 +487,17 @@ class TestImportNode(fakes.TestOvercloudNode):
|
|||
image = collections.namedtuple('image', ['id', 'name'])
|
||||
self.app.client_manager.image = mock.Mock()
|
||||
self.app.client_manager.image.images.list.return_value = [
|
||||
image(id=1, name='bm-deploy-kernel'),
|
||||
image(id=2, name='bm-deploy-ramdisk'),
|
||||
image(id=3, name='overcloud-full'),
|
||||
]
|
||||
|
||||
self.http_boot = '/var/lib/ironic/httpboot'
|
||||
|
||||
self.useFixture(fixtures.MockPatch(
|
||||
'os.path.exists', autospec=True,
|
||||
side_effect=lambda path: path in [os.path.join(self.http_boot, i)
|
||||
for i in ('agent.kernel',
|
||||
'agent.ramdisk')]))
|
||||
|
||||
def _check_workflow_call(self, parsed_args, introspect=False,
|
||||
provide=False, local=None, no_deploy_image=False):
|
||||
self.websocket.wait_for_messages.return_value = [{
|
||||
|
@ -505,14 +512,17 @@ class TestImportNode(fakes.TestOvercloudNode):
|
|||
self.cmd.take_action(parsed_args)
|
||||
|
||||
nodes_list = copy.deepcopy(self.nodes_list)
|
||||
if not no_deploy_image:
|
||||
for node in nodes_list:
|
||||
node.update({
|
||||
'kernel_id': 'file://%s/agent.kernel' % self.http_boot,
|
||||
'ramdisk_id': 'file://%s/agent.ramdisk' % self.http_boot,
|
||||
})
|
||||
|
||||
call_count = 1
|
||||
call_list = [mock.call(
|
||||
'tripleo.baremetal.v1.register_or_update', workflow_input={
|
||||
'nodes_json': nodes_list,
|
||||
'kernel_name': None if no_deploy_image else 'bm-deploy-kernel',
|
||||
'ramdisk_name': (None
|
||||
if no_deploy_image else 'bm-deploy-ramdisk'),
|
||||
'instance_boot_option': ('local' if local is True else
|
||||
'netboot' if local is False else None)
|
||||
}
|
||||
|
@ -637,17 +647,21 @@ class TestImportNodeMultiArch(fakes.TestOvercloudNode):
|
|||
image = collections.namedtuple('image', ['id', 'name'])
|
||||
self.app.client_manager.image = mock.Mock()
|
||||
self.app.client_manager.image.images.list.return_value = [
|
||||
image(id=1, name='bm-deploy-kernel'),
|
||||
image(id=2, name='bm-deploy-ramdisk'),
|
||||
image(id=3, name='overcloud-full'),
|
||||
image(id=4, name='x86_64-bm-deploy-kernel'),
|
||||
image(id=5, name='x86_64-bm-deploy-ramdisk'),
|
||||
image(id=6, name='x86_64-overcloud-full'),
|
||||
image(id=7, name='SNB-x86_64-bm-deploy-kernel'),
|
||||
image(id=8, name='SNB-x86_64-bm-deploy-ramdisk'),
|
||||
image(id=9, name='SNB-x86_64-overcloud-full'),
|
||||
]
|
||||
|
||||
self.http_boot = '/var/lib/ironic/httpboot'
|
||||
|
||||
existing = ['agent', 'x86_64/agent', 'SNB-x86_64/agent']
|
||||
existing = {os.path.join(self.http_boot, name + ext)
|
||||
for name in existing for ext in ('.kernel', '.ramdisk')}
|
||||
|
||||
self.useFixture(fixtures.MockPatch(
|
||||
'os.path.exists', autospec=True,
|
||||
side_effect=lambda path: path in existing))
|
||||
|
||||
def _check_workflow_call(self, parsed_args, introspect=False,
|
||||
provide=False, local=None, no_deploy_image=False):
|
||||
self.websocket.wait_for_messages.return_value = [{
|
||||
|
@ -662,20 +676,24 @@ class TestImportNodeMultiArch(fakes.TestOvercloudNode):
|
|||
self.cmd.take_action(parsed_args)
|
||||
|
||||
nodes_list = copy.deepcopy(self.nodes_list)
|
||||
# We expect update_nodes_deploy_data() to set these values for the
|
||||
# nodes with an 'arch' field
|
||||
nodes_list[1]['kernel_id'] = 4
|
||||
nodes_list[1]['ramdisk_id'] = 5
|
||||
nodes_list[2]['kernel_id'] = 7
|
||||
nodes_list[2]['ramdisk_id'] = 8
|
||||
if not no_deploy_image:
|
||||
nodes_list[0]['kernel_id'] = (
|
||||
'file://%s/agent.kernel' % self.http_boot)
|
||||
nodes_list[0]['ramdisk_id'] = (
|
||||
'file://%s/agent.ramdisk' % self.http_boot)
|
||||
nodes_list[1]['kernel_id'] = (
|
||||
'file://%s/x86_64/agent.kernel' % self.http_boot)
|
||||
nodes_list[1]['ramdisk_id'] = (
|
||||
'file://%s/x86_64/agent.ramdisk' % self.http_boot)
|
||||
nodes_list[2]['kernel_id'] = (
|
||||
'file://%s/SNB-x86_64/agent.kernel' % self.http_boot)
|
||||
nodes_list[2]['ramdisk_id'] = (
|
||||
'file://%s/SNB-x86_64/agent.ramdisk' % self.http_boot)
|
||||
|
||||
call_count = 1
|
||||
call_list = [mock.call(
|
||||
'tripleo.baremetal.v1.register_or_update', workflow_input={
|
||||
'nodes_json': nodes_list,
|
||||
'kernel_name': None if no_deploy_image else 'bm-deploy-kernel',
|
||||
'ramdisk_name': (None
|
||||
if no_deploy_image else 'bm-deploy-ramdisk'),
|
||||
'instance_boot_option': ('local' if local is True else
|
||||
'netboot' if local is False else None)
|
||||
}
|
||||
|
@ -768,12 +786,14 @@ class TestConfigureNode(fakes.TestOvercloudNode):
|
|||
# Get the command object to test
|
||||
self.cmd = overcloud_node.ConfigureNode(self.app, None)
|
||||
|
||||
self.workflow_input = {'kernel_name': 'bm-deploy-kernel',
|
||||
'ramdisk_name': 'bm-deploy-ramdisk',
|
||||
'instance_boot_option': None,
|
||||
'root_device': None,
|
||||
'root_device_minimum_size': 4,
|
||||
'overwrite_root_device_hints': False}
|
||||
self.workflow_input = {
|
||||
'kernel_name': 'file:///var/lib/ironic/httpboot/agent.kernel',
|
||||
'ramdisk_name': 'file:///var/lib/ironic/httpboot/agent.ramdisk',
|
||||
'instance_boot_option': None,
|
||||
'root_device': None,
|
||||
'root_device_minimum_size': 4,
|
||||
'overwrite_root_device_hints': False
|
||||
}
|
||||
|
||||
def test_configure_all_manageable_nodes(self):
|
||||
parsed_args = self.check_parser(self.cmd,
|
||||
|
|
|
@ -1456,14 +1456,19 @@ def configure_logging(log, level, log_file):
|
|||
log.addHandler(fhandler)
|
||||
|
||||
|
||||
def _name_helper(basename, arch=None, platform=None):
|
||||
def _name_helper(basename, arch=None, platform=None, use_subdir=False):
|
||||
# NOTE(tonyb): We don't accept a platform with an arch. This caught when
|
||||
# import the nodes / process args, but lets be a little cautious here
|
||||
# anyway.
|
||||
if use_subdir:
|
||||
delim = '/'
|
||||
else:
|
||||
delim = '-'
|
||||
|
||||
if arch and platform:
|
||||
basename = platform + '-' + arch + '-' + basename
|
||||
basename = platform + '-' + arch + delim + basename
|
||||
elif arch:
|
||||
basename = arch + '-' + basename
|
||||
basename = arch + delim + basename
|
||||
return basename
|
||||
|
||||
|
||||
|
@ -1485,48 +1490,71 @@ def overcloud_image(basename, arch=None, platform=None):
|
|||
|
||||
|
||||
def deploy_kernel(arch=None, platform=None):
|
||||
return (_name_helper('bm-deploy-kernel', arch=arch, platform=platform),
|
||||
'.kernel')
|
||||
return _name_helper('agent', arch=arch, platform=platform,
|
||||
use_subdir=True) + '.kernel'
|
||||
|
||||
|
||||
def deploy_ramdisk(arch=None, platform=None):
|
||||
return (_name_helper('bm-deploy-ramdisk', arch=arch, platform=platform),
|
||||
'.initramfs')
|
||||
return _name_helper('agent', arch=arch, platform=platform,
|
||||
use_subdir=True) + '.ramdisk'
|
||||
|
||||
|
||||
def update_nodes_deploy_data(imageclient, nodes):
|
||||
def _candidate_files(node, call):
|
||||
arch = node.get('arch')
|
||||
platform = node.get('platform')
|
||||
|
||||
if arch:
|
||||
if platform:
|
||||
yield call(arch=arch, platform=platform)
|
||||
yield call(arch=arch)
|
||||
|
||||
yield call()
|
||||
|
||||
|
||||
def update_nodes_deploy_data(nodes,
|
||||
http_boot=constants.IRONIC_HTTP_BOOT_BIND_MOUNT):
|
||||
"""Add specific kernel and ramdisk IDs to a node.
|
||||
|
||||
Look at all images and update node data with the most specific
|
||||
deploy_kernel and deploy_ramdisk for the architecture/platform comination
|
||||
platform.
|
||||
"""
|
||||
img_map = {}
|
||||
for image in imageclient.images.list():
|
||||
name = image.name
|
||||
# NOTE(tonyb): We don't want to include the default kernel or ramdisk
|
||||
# in the map as that will short-circuit logic elesewhere.
|
||||
if name != deploy_kernel()[0] and name != deploy_ramdisk()[0]:
|
||||
img_map[image.name] = image.id
|
||||
|
||||
for node in nodes:
|
||||
arch = node.get('arch')
|
||||
platform = node.get('platform')
|
||||
|
||||
# NOTE(tonyb): Check to see if we have a specific kernel for this node
|
||||
# and use that.
|
||||
for kernel in [deploy_kernel(arch=arch, platform=platform)[0],
|
||||
deploy_kernel(arch=arch)[0]]:
|
||||
if 'kernel_id' not in node and kernel in img_map:
|
||||
node['kernel_id'] = img_map[kernel]
|
||||
break
|
||||
# and use that. Fall back to the generic image.
|
||||
if 'kernel_id' not in node:
|
||||
kernel_locations = list(_candidate_files(node, deploy_kernel))
|
||||
|
||||
for kernel in kernel_locations:
|
||||
path = os.path.join(http_boot, kernel)
|
||||
if os.path.exists(path):
|
||||
# NOTE(dtantsur): we don't use http_boot here since we
|
||||
# assume that the path in containers is fixed
|
||||
node['kernel_id'] = 'file://%s/%s' % (
|
||||
constants.IRONIC_HTTP_BOOT_BIND_MOUNT,
|
||||
kernel)
|
||||
break
|
||||
else:
|
||||
raise RuntimeError('No kernel image provided and none of %s '
|
||||
'found in %s' % (kernel_locations,
|
||||
http_boot))
|
||||
|
||||
# NOTE(tonyb): As above except for ramdisks
|
||||
for ramdisk in [deploy_ramdisk(arch=arch, platform=platform)[0],
|
||||
deploy_ramdisk(arch=arch)[0]]:
|
||||
if 'ramdisk_id' not in node and ramdisk in img_map:
|
||||
node['ramdisk_id'] = img_map[ramdisk]
|
||||
break
|
||||
if 'ramdisk_id' not in node:
|
||||
ramdisk_locations = list(_candidate_files(node, deploy_ramdisk))
|
||||
|
||||
for ramdisk in ramdisk_locations:
|
||||
path = os.path.join(http_boot, ramdisk)
|
||||
if os.path.exists(path):
|
||||
node['ramdisk_id'] = 'file://%s/%s' % (
|
||||
constants.IRONIC_HTTP_BOOT_BIND_MOUNT,
|
||||
ramdisk)
|
||||
break
|
||||
else:
|
||||
raise RuntimeError('No ramdisk image provided and none of %s '
|
||||
'found in %s' % (ramdisk_locations,
|
||||
http_boot))
|
||||
|
||||
|
||||
def get_deployment_python_interpreter(parsed_args):
|
||||
|
|
|
@ -270,7 +270,7 @@ class UploadOvercloudImage(command.Command):
|
|||
default=self._get_environment_var(
|
||||
'HTTP_BOOT',
|
||||
constants.IRONIC_HTTP_BOOT_BIND_MOUNT),
|
||||
help=_("Root directory for the introspection image")
|
||||
help=_("Root directory for the ironic-python-agent image")
|
||||
)
|
||||
parser.add_argument(
|
||||
"--update-existing",
|
||||
|
@ -458,44 +458,8 @@ class UploadOvercloudImage(command.Command):
|
|||
|
||||
if parsed_args.image_type is None or \
|
||||
parsed_args.image_type == 'ironic-python-agent':
|
||||
(deploy_kernel_name,
|
||||
deploy_kernel_extension) = plugin_utils.deploy_kernel(
|
||||
arch=arch, platform=platform)
|
||||
deploy_kernel_file = os.path.join(parsed_args.image_path,
|
||||
parsed_args.ipa_name +
|
||||
deploy_kernel_extension)
|
||||
self._image_try_update(deploy_kernel_name, deploy_kernel_file,
|
||||
parsed_args) or \
|
||||
glance_client_adaptor.upload_image(
|
||||
name=deploy_kernel_name,
|
||||
is_public=True,
|
||||
disk_format='aki',
|
||||
properties=properties,
|
||||
data=self._read_image_file_pointer(
|
||||
parsed_args.image_path,
|
||||
deploy_kernel_file))
|
||||
|
||||
(deploy_ramdisk_name,
|
||||
deploy_ramdisk_extension) = plugin_utils.deploy_ramdisk(
|
||||
arch=arch, platform=platform)
|
||||
deploy_ramdisk_file = os.path.join(parsed_args.image_path,
|
||||
parsed_args.ipa_name +
|
||||
deploy_ramdisk_extension)
|
||||
self._image_try_update(deploy_ramdisk_name, deploy_ramdisk_file,
|
||||
parsed_args) or \
|
||||
glance_client_adaptor.upload_image(
|
||||
name=deploy_ramdisk_name,
|
||||
is_public=True,
|
||||
disk_format='ari',
|
||||
properties=properties,
|
||||
data=self._read_image_file_pointer(parsed_args.image_path,
|
||||
deploy_ramdisk_file))
|
||||
|
||||
self.log.debug("copy agent images to HTTP BOOT dir")
|
||||
|
||||
# TODO(tonyb) Decide how to handle platform specific httpboot
|
||||
# files/names
|
||||
|
||||
self._file_create_or_update(
|
||||
os.path.join(parsed_args.image_path,
|
||||
'%s.kernel' % parsed_args.ipa_name),
|
||||
|
|
|
@ -269,6 +269,12 @@ class ImportNode(command.Command):
|
|||
help=_('Whether to set instances for booting from '
|
||||
'local hard drive (local) or network '
|
||||
'(netboot).'))
|
||||
parser.add_argument("--http-boot",
|
||||
default=os.environ.get(
|
||||
'HTTP_BOOT',
|
||||
constants.IRONIC_HTTP_BOOT_BIND_MOUNT),
|
||||
help=_("Root directory for the ironic-python-agent"
|
||||
" image"))
|
||||
parser.add_argument('env_file', type=argparse.FileType('r'))
|
||||
return parser
|
||||
|
||||
|
@ -281,22 +287,14 @@ class ImportNode(command.Command):
|
|||
return baremetal.validate_nodes(self.app.client_manager,
|
||||
nodes_json=nodes_config)
|
||||
|
||||
if parsed_args.no_deploy_image:
|
||||
deploy_kernel = None
|
||||
deploy_ramdisk = None
|
||||
else:
|
||||
deploy_kernel = oooutils.deploy_kernel()[0]
|
||||
deploy_ramdisk = oooutils.deploy_ramdisk()[0]
|
||||
|
||||
# Look for *specific* deploy images and update the node data if
|
||||
# one is found.
|
||||
oooutils.update_nodes_deploy_data(self.app.client_manager.image,
|
||||
nodes_config)
|
||||
if not parsed_args.no_deploy_image:
|
||||
oooutils.update_nodes_deploy_data(nodes_config,
|
||||
http_boot=parsed_args.http_boot)
|
||||
nodes = baremetal.register_or_update(
|
||||
self.app.client_manager,
|
||||
nodes_json=nodes_config,
|
||||
kernel_name=deploy_kernel,
|
||||
ramdisk_name=deploy_ramdisk,
|
||||
instance_boot_option=parsed_args.instance_boot_option
|
||||
)
|
||||
|
||||
|
@ -332,12 +330,16 @@ class ConfigureNode(command.Command):
|
|||
action='store_true',
|
||||
help=_("Configure all nodes currently in "
|
||||
"'manageable' state"))
|
||||
parser.add_argument('--deploy-kernel',
|
||||
default='bm-deploy-kernel',
|
||||
help=_('Image with deploy kernel.'))
|
||||
parser.add_argument('--deploy-ramdisk',
|
||||
default='bm-deploy-ramdisk',
|
||||
help=_('Image with deploy ramdisk.'))
|
||||
parser.add_argument(
|
||||
'--deploy-kernel',
|
||||
default='file://%s/agent.kernel' %
|
||||
constants.IRONIC_HTTP_BOOT_BIND_MOUNT,
|
||||
help=_('Image with deploy kernel.'))
|
||||
parser.add_argument(
|
||||
'--deploy-ramdisk',
|
||||
default='file://%s/agent.ramdisk' %
|
||||
constants.IRONIC_HTTP_BOOT_BIND_MOUNT,
|
||||
help=_('Image with deploy ramdisk.'))
|
||||
parser.add_argument('--instance-boot-option',
|
||||
choices=['local', 'netboot'],
|
||||
help=_('Whether to set instances for booting from '
|
||||
|
|
Loading…
Reference in New Issue