summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.opendev.org>2020-06-20 00:00:10 +0000
committerGerrit Code Review <review@openstack.org>2020-06-20 00:00:10 +0000
commit46bf7e0ef4c9c3d17effdcc67accfac09f916cf1 (patch)
tree196d5687a859aa26a6de249ac70fdb18c642e3ef
parente8836e5359834915a4dc460921a2636ea6cce46b (diff)
parent9d4cf5532ff3cc4725c247aa0e0aca2caa30e640 (diff)
downloadironic-python-agent-46bf7e0ef4c9c3d17effdcc67accfac09f916cf1.tar.gz
Merge "Add a deploy step for writing an image"
-rw-r--r--ironic_python_agent/agent.py8
-rw-r--r--ironic_python_agent/extensions/base.py23
-rw-r--r--ironic_python_agent/hardware.py29
-rw-r--r--ironic_python_agent/tests/unit/base.py3
4 files changed, 56 insertions, 7 deletions
diff --git a/ironic_python_agent/agent.py b/ironic_python_agent/agent.py
index 5eb1e28d..b2e2e38e 100644
--- a/ironic_python_agent/agent.py
+++ b/ironic_python_agent/agent.py
@@ -29,7 +29,6 @@ from oslo_concurrency import processutils
from oslo_config import cfg
from oslo_log import log
import pkg_resources
-from stevedore import extension
from ironic_python_agent.api import app
from ironic_python_agent import config
@@ -171,12 +170,7 @@ class IronicPythonAgent(base.ExecuteCommandMixin):
if bool(cfg.CONF.keyfile) != bool(cfg.CONF.certfile):
LOG.warning("Only one of 'keyfile' and 'certfile' options is "
"defined in config file. Its value will be ignored.")
- self.ext_mgr = extension.ExtensionManager(
- namespace='ironic_python_agent.extensions',
- invoke_on_load=True,
- propagate_map_exceptions=True,
- invoke_kwds={'agent': self},
- )
+ self.ext_mgr = base.init_ext_manager(self)
self.api_url = api_url
if not self.api_url or self.api_url == 'mdns':
try:
diff --git a/ironic_python_agent/extensions/base.py b/ironic_python_agent/extensions/base.py
index a4314098..d2ea4337 100644
--- a/ironic_python_agent/extensions/base.py
+++ b/ironic_python_agent/extensions/base.py
@@ -19,6 +19,7 @@ import threading
from oslo_log import log
from oslo_utils import uuidutils
+from stevedore import extension
from ironic_python_agent import encoding
from ironic_python_agent import errors
@@ -331,3 +332,25 @@ def sync_command(command_name, validator=None):
return wrapper
return sync_decorator
+
+
+_EXT_MANAGER = None
+
+
+def init_ext_manager(agent):
+ global _EXT_MANAGER
+ _EXT_MANAGER = extension.ExtensionManager(
+ namespace='ironic_python_agent.extensions',
+ invoke_on_load=True,
+ propagate_map_exceptions=True,
+ invoke_kwds={'agent': agent},
+ )
+ return _EXT_MANAGER
+
+
+def get_extension(name):
+ if _EXT_MANAGER is None:
+ raise errors.ExtensionError('Extension manager is not initialized')
+ ext = _EXT_MANAGER[name].obj
+ ext.ext_mgr = _EXT_MANAGER
+ return ext
diff --git a/ironic_python_agent/hardware.py b/ironic_python_agent/hardware.py
index a5b31c73..fb1a2102 100644
--- a/ironic_python_agent/hardware.py
+++ b/ironic_python_agent/hardware.py
@@ -37,6 +37,7 @@ import yaml
from ironic_python_agent import encoding
from ironic_python_agent import errors
+from ironic_python_agent.extensions import base as ext_base
from ironic_python_agent import netutils
from ironic_python_agent import raid_utils
from ironic_python_agent import utils
@@ -1566,6 +1567,15 @@ class GenericHardwareManager(HardwareManager):
'reboot_requested': False,
'argsinfo': RAID_APPLY_CONFIGURATION_ARGSINFO,
},
+ {
+ 'step': 'write_image',
+ # NOTE(dtantsur): this step has to be proxied via an
+ # out-of-band step with the same name, hence the priority here
+ # doesn't really matter.
+ 'priority': 0,
+ 'interface': 'deploy',
+ 'reboot_requested': False,
+ },
]
def apply_configuration(self, node, ports, raid_config,
@@ -1980,6 +1990,25 @@ class GenericHardwareManager(HardwareManager):
'errors': '; '.join(raid_errors)}
raise errors.SoftwareRAIDError(error)
+ def write_image(self, node, ports, image_info, configdrive=None):
+ """A deploy step to write an image.
+
+ Downloads and writes an image to disk if necessary. Also writes a
+ configdrive to disk if the configdrive parameter is specified.
+
+ :param node: A dictionary of the node object
+ :param ports: A list of dictionaries containing information
+ of ports for the node
+ :param image_info: Image information dictionary.
+ :param configdrive: A string containing the location of the config
+ drive as a URL OR the contents (as gzip/base64)
+ of the configdrive. Optional, defaults to None.
+ """
+ ext = ext_base.get_extension('standby')
+ cmd = ext.prepare_image(image_info=image_info, configdrive=configdrive)
+ # The result is asynchronous, wait here.
+ cmd.join()
+
def _compare_extensions(ext1, ext2):
mgr1 = ext1.obj
diff --git a/ironic_python_agent/tests/unit/base.py b/ironic_python_agent/tests/unit/base.py
index 033c39cb..94196985 100644
--- a/ironic_python_agent/tests/unit/base.py
+++ b/ironic_python_agent/tests/unit/base.py
@@ -23,6 +23,7 @@ from oslo_config import cfg
from oslo_config import fixture as config_fixture
from oslotest import base as test_base
+from ironic_python_agent.extensions import base as ext_base
from ironic_python_agent import utils
CONF = cfg.CONF
@@ -58,6 +59,8 @@ class IronicAgentTest(test_base.BaseTestCase):
self.patch(subprocess, 'check_output', do_not_call)
self.patch(utils, 'execute', do_not_call)
+ ext_base._EXT_MANAGER = None
+
def _set_config(self):
self.cfg_fixture = self.useFixture(config_fixture.Config(CONF))