diff options
author | Zuul <zuul@review.openstack.org> | 2019-03-07 03:30:54 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2019-03-07 03:30:54 +0000 |
commit | 7ed696e5ded4776093c7e50316a13d6481c7e71b (patch) | |
tree | b2d87cf2bef75639e94523cca77f0b83a5e4a1db | |
parent | aa2c7fc9ac0b9c094db0f09bb3b75a09fa92063f (diff) | |
parent | 595db83ddcbed667c6d1abdb1e697e3397df3a3b (diff) | |
download | python-ironicclient-7ed696e5ded4776093c7e50316a13d6481c7e71b.tar.gz |
Merge "Support passing a dictionary for configdrive"
-rw-r--r-- | ironicclient/common/http.py | 2 | ||||
-rwxr-xr-x | ironicclient/osc/v1/baremetal_node.py | 16 | ||||
-rw-r--r-- | ironicclient/tests/unit/osc/v1/test_baremetal_node.py | 19 | ||||
-rw-r--r-- | ironicclient/tests/unit/v1/test_node.py | 10 | ||||
-rw-r--r-- | ironicclient/v1/node.py | 19 | ||||
-rw-r--r-- | releasenotes/notes/configdrive-7bd2b67830691b2e.yaml | 5 |
6 files changed, 60 insertions, 11 deletions
diff --git a/ironicclient/common/http.py b/ironicclient/common/http.py index f930e21..0144e98 100644 --- a/ironicclient/common/http.py +++ b/ironicclient/common/http.py @@ -43,7 +43,7 @@ from ironicclient import exc # http://specs.openstack.org/openstack/ironic-specs/specs/kilo/api-microversions.html # noqa # for full details. DEFAULT_VER = '1.9' -LAST_KNOWN_API_VERSION = 55 +LAST_KNOWN_API_VERSION = 56 LATEST_VERSION = '1.{}'.format(LAST_KNOWN_API_VERSION) LOG = logging.getLogger(__name__) diff --git a/ironicclient/osc/v1/baremetal_node.py b/ironicclient/osc/v1/baremetal_node.py index 718e12a..e940731 100755 --- a/ironicclient/osc/v1/baremetal_node.py +++ b/ironicclient/osc/v1/baremetal_node.py @@ -16,6 +16,7 @@ import argparse import itertools +import json import logging from osc_lib.command import command @@ -30,8 +31,10 @@ from ironicclient.v1 import utils as v1_utils CONFIG_DRIVE_ARG_HELP = _( "A gzipped, base64-encoded configuration drive string OR " "the path to the configuration drive file OR the path to a " - "directory containing the config drive files. In case it's " - "a directory, a config drive will be generated from it.") + "directory containing the config drive files OR a JSON object to build " + "config drive from. In case it's a directory, a config drive will be " + "generated from it. In case it's a JSON object, a config drive will " + "be generated on the server side.") SUPPORTED_INTERFACES = ['bios', 'boot', 'console', 'deploy', 'inspect', @@ -69,6 +72,15 @@ class ProvisionStateBaremetalNode(command.Command): clean_steps = utils.handle_json_arg(clean_steps, 'clean steps') config_drive = getattr(parsed_args, 'config_drive', None) + if config_drive: + try: + config_drive_dict = json.loads(config_drive) + except (ValueError, TypeError): + pass + else: + if isinstance(config_drive_dict, dict): + config_drive = config_drive_dict + rescue_password = getattr(parsed_args, 'rescue_password', None) baremetal_client.node.set_provision_state( diff --git a/ironicclient/tests/unit/osc/v1/test_baremetal_node.py b/ironicclient/tests/unit/osc/v1/test_baremetal_node.py index ad45fac..887e763 100644 --- a/ironicclient/tests/unit/osc/v1/test_baremetal_node.py +++ b/ironicclient/tests/unit/osc/v1/test_baremetal_node.py @@ -1390,6 +1390,25 @@ class TestDeployBaremetalProvisionState(TestBaremetal): 'node_uuid', 'active', cleansteps=None, configdrive='path/to/drive', rescue_password=None) + def test_deploy_baremetal_provision_state_active_and_configdrive_dict( + self): + arglist = ['node_uuid', + '--config-drive', '{"meta_data": {}}'] + verifylist = [ + ('node', 'node_uuid'), + ('provision_state', 'active'), + ('config_drive', '{"meta_data": {}}'), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.cmd.take_action(parsed_args) + + self.baremetal_mock.node.set_provision_state.assert_called_once_with( + 'node_uuid', 'active', + cleansteps=None, configdrive={'meta_data': {}}, + rescue_password=None) + def test_deploy_no_wait(self): arglist = ['node_uuid'] verifylist = [ diff --git a/ironicclient/tests/unit/v1/test_node.py b/ironicclient/tests/unit/v1/test_node.py index 6afe1e2..baba5ea 100644 --- a/ironicclient/tests/unit/v1/test_node.py +++ b/ironicclient/tests/unit/v1/test_node.py @@ -1388,6 +1388,16 @@ class NodeManagerTest(testtools.TestCase): ] self.assertEqual(expect, self.api.calls) + def test_node_set_provision_state_with_configdrive_as_dict(self): + target_state = 'active' + self.mgr.set_provision_state(NODE1['uuid'], target_state, + configdrive={'user_data': ''}) + body = {'target': target_state, 'configdrive': {'user_data': ''}} + expect = [ + ('PUT', '/v1/nodes/%s/states/provision' % NODE1['uuid'], {}, body), + ] + self.assertEqual(expect, self.api.calls) + def test_node_set_provision_state_with_configdrive_file(self): target_state = 'active' file_content = b'foo bar cat meow dog bark' diff --git a/ironicclient/v1/node.py b/ironicclient/v1/node.py index 8e5747b..d525eed 100644 --- a/ironicclient/v1/node.py +++ b/ironicclient/v1/node.py @@ -515,9 +515,11 @@ class NodeManager(base.CreateManager): 'rescue', 'unrescue'. :param configdrive: A gzipped, base64-encoded configuration drive string OR the path to the configuration drive file OR the path to - a directory containing the config drive files. In case it's a - directory, a config drive will be generated from it. This is only - valid when setting state to 'active'. + a directory containing the config drive files OR a dictionary to + build config drive from. In case it's a directory, a config drive + will be generated from it. In case it's a dictionary, a config + drive will be generated on the server side (requires API version + 1.56). This is only valid when setting state to 'active'. :param cleansteps: The clean steps as a list of clean-step dictionaries; each dictionary should have keys 'interface' and 'step', and optional key 'args'. This must be specified (and is @@ -534,11 +536,12 @@ class NodeManager(base.CreateManager): path = "%s/states/provision" % node_uuid body = {'target': state} if configdrive: - if os.path.isfile(configdrive): - with open(configdrive, 'rb') as f: - configdrive = f.read() - if os.path.isdir(configdrive): - configdrive = utils.make_configdrive(configdrive) + if not isinstance(configdrive, dict): + if os.path.isfile(configdrive): + with open(configdrive, 'rb') as f: + configdrive = f.read() + if os.path.isdir(configdrive): + configdrive = utils.make_configdrive(configdrive) body['configdrive'] = configdrive elif cleansteps: diff --git a/releasenotes/notes/configdrive-7bd2b67830691b2e.yaml b/releasenotes/notes/configdrive-7bd2b67830691b2e.yaml new file mode 100644 index 0000000..b7dbed3 --- /dev/null +++ b/releasenotes/notes/configdrive-7bd2b67830691b2e.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + Supports passing a JSON object to ``--config-drive`` to build the config + drive on the server side (requires API version 1.56). |