summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.opendev.org>2020-09-03 13:43:40 +0000
committerGerrit Code Review <review@openstack.org>2020-09-03 13:43:40 +0000
commitc15bc2a7a1dbf3b4e0ca3ef0517eb77fb2de6f46 (patch)
tree094b5e724da921d0edd99b56da598d2bfea96515
parentd69e46b18b8ad0fa9e2b266d4106b94c87bc73a1 (diff)
parent9ac5c0277022a28f3332a43c9572a56b56a51589 (diff)
downloadironic-c15bc2a7a1dbf3b4e0ca3ef0517eb77fb2de6f46.tar.gz
Merge "Support caching http:// images locally in the direct deploy"
-rw-r--r--doc/source/admin/interfaces/deploy.rst8
-rw-r--r--ironic/conf/agent.py9
-rw-r--r--ironic/drivers/modules/agent.py1
-rw-r--r--ironic/drivers/modules/deploy_utils.py3
-rw-r--r--ironic/tests/unit/drivers/modules/test_agent.py11
-rw-r--r--ironic/tests/unit/drivers/modules/test_deploy_utils.py33
-rw-r--r--releasenotes/notes/http-local-4e8f32c6d5309f12.yaml7
7 files changed, 67 insertions, 5 deletions
diff --git a/doc/source/admin/interfaces/deploy.rst b/doc/source/admin/interfaces/deploy.rst
index 5b86adf4c..74e50dd46 100644
--- a/doc/source/admin/interfaces/deploy.rst
+++ b/doc/source/admin/interfaces/deploy.rst
@@ -63,6 +63,14 @@ To use this deploy interface with a custom HTTP server, set
image_download_source = http
...
+This configuration affects *glance* and ``file://`` images. If you want
+``http(s)://`` images to also be cached and served locally, use instead:
+
+.. code-block:: ini
+
+ [agent]
+ image_download_source = local
+
You need to set up a workable HTTP server at each conductor node which with
``direct`` deploy interface enabled, and check http related options in the
ironic configuration file to match the HTTP server configurations.
diff --git a/ironic/conf/agent.py b/ironic/conf/agent.py
index 8572a25bd..85b0fc4e0 100644
--- a/ironic/conf/agent.py
+++ b/ironic/conf/agent.py
@@ -101,15 +101,16 @@ opts = [
'from the Object Storage service.')),
('http', _('IPA ramdisk retrieves instance image '
'from HTTP service served at conductor '
- 'nodes.'))],
+ 'nodes.')),
+ ('local', _('Same as "http", but HTTP images '
+ 'are also cached locally, converted '
+ 'and served from the conductor'))],
default='swift',
mutable=True,
help=_('Specifies whether direct deploy interface should try '
'to use the image source directly or if ironic should '
'cache the image on the conductor and serve it from '
- 'ironic\'s own http server. This option takes effect '
- 'only when instance image is provided from the Image '
- 'service.')),
+ 'ironic\'s own http server.')),
cfg.IntOpt('command_timeout',
default=60,
mutable=True,
diff --git a/ironic/drivers/modules/agent.py b/ironic/drivers/modules/agent.py
index 73f0c72d5..558052466 100644
--- a/ironic/drivers/modules/agent.py
+++ b/ironic/drivers/modules/agent.py
@@ -172,6 +172,7 @@ def validate_http_provisioning_configuration(node):
# 1. Glance images with image_download_source == http
# 2. File images (since we need to serve them to IPA)
if (not image_source.startswith('file://')
+ and CONF.agent.image_download_source != 'local'
and (not service_utils.is_glance_image(image_source)
or CONF.agent.image_download_source == 'swift')):
return
diff --git a/ironic/drivers/modules/deploy_utils.py b/ironic/drivers/modules/deploy_utils.py
index 3b68f8571..662460a1f 100644
--- a/ironic/drivers/modules/deploy_utils.py
+++ b/ironic/drivers/modules/deploy_utils.py
@@ -1085,7 +1085,8 @@ def build_instance_info_for_deploy(task):
if not iwdi:
instance_info['kernel'] = image_info['properties']['kernel_id']
instance_info['ramdisk'] = image_info['properties']['ramdisk_id']
- elif image_source.startswith('file://'):
+ elif (image_source.startswith('file://')
+ or CONF.agent.image_download_source == 'local'):
_cache_and_convert_image(task, instance_info)
else:
_validate_image_url(node, image_source)
diff --git a/ironic/tests/unit/drivers/modules/test_agent.py b/ironic/tests/unit/drivers/modules/test_agent.py
index 39baa2bda..51c6dccca 100644
--- a/ironic/tests/unit/drivers/modules/test_agent.py
+++ b/ironic/tests/unit/drivers/modules/test_agent.py
@@ -202,6 +202,17 @@ class TestAgentMethods(db_base.DbTestCase):
agent.validate_http_provisioning_configuration,
self.node)
+ def test_validate_http_provisioning_missing_args_local_http(self):
+ CONF.set_override('image_download_source', 'local', group='agent')
+ CONF.set_override('http_url', None, group='deploy')
+ i_info = self.node.instance_info
+ i_info['image_source'] = 'http://image-ref'
+ self.node.instance_info = i_info
+ self.assertRaisesRegex(exception.MissingParameterValue,
+ 'failed to validate http provisoning',
+ agent.validate_http_provisioning_configuration,
+ self.node)
+
class TestAgentDeploy(db_base.DbTestCase):
def setUp(self):
diff --git a/ironic/tests/unit/drivers/modules/test_deploy_utils.py b/ironic/tests/unit/drivers/modules/test_deploy_utils.py
index e8b3088e2..549727e6c 100644
--- a/ironic/tests/unit/drivers/modules/test_deploy_utils.py
+++ b/ironic/tests/unit/drivers/modules/test_deploy_utils.py
@@ -2073,6 +2073,39 @@ class TestBuildInstanceInfoForHttpProvisioning(db_base.DbTestCase):
validate_href_mock.assert_called_once_with(
mock.ANY, expected_url, False)
+ @mock.patch.object(image_service.HttpImageService, 'validate_href',
+ autospec=True)
+ def test_build_instance_info_local_image(self, validate_href_mock):
+ cfg.CONF.set_override('image_download_source', 'local', group='agent')
+ i_info = self.node.instance_info
+ driver_internal_info = self.node.driver_internal_info
+ i_info['image_source'] = 'http://image-ref'
+ i_info['image_checksum'] = 'aa'
+ i_info['root_gb'] = 10
+ i_info['image_checksum'] = 'aa'
+ driver_internal_info['is_whole_disk_image'] = True
+ self.node.instance_info = i_info
+ self.node.driver_internal_info = driver_internal_info
+ self.node.save()
+
+ expected_url = (
+ 'http://172.172.24.10:8080/agent_images/%s' % self.node.uuid)
+
+ with task_manager.acquire(
+ self.context, self.node.uuid, shared=False) as task:
+
+ info = utils.build_instance_info_for_deploy(task)
+
+ self.assertEqual(expected_url, info['image_url'])
+ self.assertEqual('sha256', info['image_os_hash_algo'])
+ self.assertEqual('fake-checksum', info['image_os_hash_value'])
+ self.cache_image_mock.assert_called_once_with(
+ task.context, task.node, force_raw=True)
+ self.checksum_mock.assert_called_once_with(
+ self.fake_path, algorithm='sha256')
+ validate_href_mock.assert_called_once_with(
+ mock.ANY, expected_url, False)
+
class TestStorageInterfaceUtils(db_base.DbTestCase):
def setUp(self):
diff --git a/releasenotes/notes/http-local-4e8f32c6d5309f12.yaml b/releasenotes/notes/http-local-4e8f32c6d5309f12.yaml
new file mode 100644
index 000000000..5260ddb43
--- /dev/null
+++ b/releasenotes/notes/http-local-4e8f32c6d5309f12.yaml
@@ -0,0 +1,7 @@
+---
+features:
+ - |
+ Adds a new possible value for ``image_download_source``: ``local``.
+ When used, even ``http://`` images are downloaded, converted to RAW if
+ needed and served from the conductor's HTTP server. This feature targets
+ primarily nodes with low RAM.