diff --git a/tripleoclient/tests/v1/overcloud_node/test_overcloud_node.py b/tripleoclient/tests/v1/overcloud_node/test_overcloud_node.py
index a8a3b1d37..76718b9db 100644
--- a/tripleoclient/tests/v1/overcloud_node/test_overcloud_node.py
+++ b/tripleoclient/tests/v1/overcloud_node/test_overcloud_node.py
@@ -25,6 +25,7 @@ import openstack
 
 from osc_lib import exceptions as oscexc
 from osc_lib.tests import utils as test_utils
+from oslo_utils import units
 import yaml
 
 from tripleoclient import exceptions
@@ -697,6 +698,14 @@ class TestImportNodeMultiArch(fakes.TestOvercloudNode):
         self._check_workflow_call(parsed_args, no_deploy_image=True)
 
 
+@mock.patch.object(openstack.baremetal.v1._proxy, 'Proxy',
+                   autospec=True, name='mock_bm')
+@mock.patch('openstack.config', autospec=True,
+            name='mock_conf')
+@mock.patch('openstack.connect', autospec=True,
+            name='mock_connect')
+@mock.patch.object(openstack.connection,
+                   'Connection', autospec=True)
 class TestConfigureNode(fakes.TestOvercloudNode):
 
     def setUp(self):
@@ -714,26 +723,62 @@ class TestConfigureNode(fakes.TestOvercloudNode):
             'root_device_minimum_size': 4,
             'overwrite_root_device_hints': False
         }
+        # Mock disks
+        self.disks = [
+            {'name': '/dev/sda', 'size': 11 * units.Gi},
+            {'name': '/dev/sdb', 'size': 2 * units.Gi},
+            {'name': '/dev/sdc', 'size': 5 * units.Gi},
+            {'name': '/dev/sdd', 'size': 21 * units.Gi},
+            {'name': '/dev/sde', 'size': 13 * units.Gi},
+        ]
 
-    def test_configure_all_manageable_nodes(self):
+        for i, disk in enumerate(self.disks):
+            disk['wwn'] = 'wwn%d' % i
+            disk['serial'] = 'serial%d' % i
+
+        self.fake_baremetal_node = fakes.make_fake_machine(
+            machine_name='node1',
+            machine_id='4e540e11-1366-4b57-85d5-319d168d98a1'
+        )
+        self.fake_baremetal_node2 = fakes.make_fake_machine(
+            machine_name='node2',
+            machine_id='9070e42d-1ad7-4bd0-b868-5418bc9c7176'
+        )
+
+    def test_configure_all_manageable_nodes(self, mock_conn,
+                                            mock_connect, mock_conf,
+                                            mock_bm):
+        mock_conn.return_value = mock_bm
+        mock_bm.baremetal = mock_bm
+        mock_bm.baremetal.nodes.side_effect = [
+            iter([self.fake_baremetal_node]),
+            iter([self.fake_baremetal_node])]
         parsed_args = self.check_parser(self.cmd,
                                         ['--all-manageable'],
                                         [('all_manageable', True)])
         self.cmd.take_action(parsed_args)
 
-    def test_configure_specified_nodes(self):
+    def test_configure_specified_nodes(self, mock_conn,
+                                       mock_connect, mock_conf,
+                                       mock_bm):
+        mock_conn.return_value = mock_bm
+        mock_bm.baremetal = mock_bm
         argslist = ['node_uuid1', 'node_uuid2']
         verifylist = [('node_uuids', ['node_uuid1', 'node_uuid2'])]
 
         parsed_args = self.check_parser(self.cmd, argslist, verifylist)
         self.cmd.take_action(parsed_args)
 
-    def test_configure_no_node_or_flag_specified(self):
+    def test_configure_no_node_or_flag_specified(self, mock_conn,
+                                                 mock_connect, mock_conf,
+                                                 mock_bm):
         self.assertRaises(test_utils.ParserException,
                           self.check_parser,
                           self.cmd, [], [])
 
-    def test_configure_uuids_and_all_both_specified(self):
+    def test_configure_uuids_and_all_both_specified(self, mock_conn,
+                                                    mock_connect, mock_conf,
+                                                    mock_bm):
         argslist = ['node_id1', 'node_id2', '--all-manageable']
         verifylist = [('node_uuids', ['node_id1', 'node_id2']),
                       ('all_manageable', True)]
@@ -741,7 +786,23 @@ class TestConfigureNode(fakes.TestOvercloudNode):
                           self.check_parser,
                           self.cmd, argslist, verifylist)
 
-    def test_configure_kernel_and_ram(self):
+    def test_configure_kernel_and_ram(self, mock_conn,
+                                      mock_connect, mock_conf,
+                                      mock_bm):
+        mock_conn.return_value = mock_bm
+        mock_bm.baremetal = mock_bm
+        mock_bm.baremetal_introspection = mock_bm
+
+        introspector_client = mock_bm.baremetal_introspection
+        introspector_client.get_introspection_data = mock_bm
+        introspector_client.get_introspection_data.return_value = {
+            'inventory': {'disks': self.disks}
+        }
+
+        mock_bm.baremetal.nodes.side_effect = [
+            iter([self.fake_baremetal_node]),
+            iter([self.fake_baremetal_node])]
+
         argslist = ['--all-manageable', '--deploy-ramdisk', 'test_ramdisk',
                     '--deploy-kernel', 'test_kernel']
         verifylist = [('deploy_kernel', 'test_kernel'),
@@ -750,14 +811,35 @@ class TestConfigureNode(fakes.TestOvercloudNode):
         parsed_args = self.check_parser(self.cmd, argslist, verifylist)
         self.cmd.take_action(parsed_args)
 
-    def test_configure_instance_boot_option(self):
+    def test_configure_instance_boot_option(self, mock_conn,
+                                            mock_connect, mock_conf,
+                                            mock_bm):
+        mock_conn.return_value = mock_bm
+        mock_bm.baremetal = mock_bm
+        mock_bm.baremetal.nodes.side_effect = [
+            iter([self.fake_baremetal_node]),
+            iter([self.fake_baremetal_node])]
         argslist = ['--all-manageable', '--instance-boot-option', 'netboot']
         verifylist = [('instance_boot_option', 'netboot')]
 
         parsed_args = self.check_parser(self.cmd, argslist, verifylist)
         self.cmd.take_action(parsed_args)
 
-    def test_configure_root_device(self):
+    def test_configure_root_device(self, mock_conn,
+                                   mock_connect, mock_conf,
+                                   mock_bm):
+        mock_conn.return_value = mock_bm
+        mock_bm.baremetal = mock_bm
+        mock_bm.baremetal_introspection = mock_bm
+
+        introspector_client = mock_bm.baremetal_introspection
+        introspector_client.get_introspection_data = mock_bm
+        introspector_client.get_introspection_data.return_value = {
+            'inventory': {'disks': self.disks}
+        }
+        mock_bm.baremetal.nodes.side_effect = [
+            iter([self.fake_baremetal_node]),
+            iter([self.fake_baremetal_node])]
         argslist = ['--all-manageable',
                     '--root-device', 'smallest',
                     '--root-device-minimum-size', '2',
@@ -772,7 +854,23 @@ class TestConfigureNode(fakes.TestOvercloudNode):
     @mock.patch('tripleoclient.workflows.baremetal.'
                 '_apply_root_device_strategy')
     def test_configure_specified_node_with_all_arguments(
-            self, mock_root_device):
+            self, mock_root_device, mock_conn,
+            mock_connect, mock_conf,
+            mock_bm):
+        mock_conn.return_value = mock_bm
+        mock_bm.baremetal = mock_bm
+        mock_bm.baremetal_introspection = mock_bm
+
+        introspector_client = mock_bm.baremetal_introspection
+        introspector_client.get_introspection_data = mock_bm
+        introspector_client.get_introspection_data.return_value = {
+            'inventory': {'disks': self.disks}
+        }
+
+        mock_bm.baremetal.nodes.side_effect = [
+            iter([self.fake_baremetal_node]),
+            iter([self.fake_baremetal_node])]
+
         argslist = ['node_id',
                     '--deploy-kernel', 'test_kernel',
                     '--deploy-ramdisk', 'test_ramdisk',
diff --git a/tripleoclient/tests/workflows/test_baremetal.py b/tripleoclient/tests/workflows/test_baremetal.py
index 31b38c164..9e858ab12 100644
--- a/tripleoclient/tests/workflows/test_baremetal.py
+++ b/tripleoclient/tests/workflows/test_baremetal.py
@@ -108,12 +108,6 @@ class TestBaremetalWorkflows(fakes.FakePlaybookExecution):
             node_timeout=1200, max_retries=1, retry_timeout=120,
         )
 
-    def test_configure_success(self):
-        baremetal.configure(self.app.client_manager, node_uuids=[])
-
-    def test_configure_manageable_nodes_success(self):
-        baremetal.configure_manageable_nodes(self.app.client_manager)
-
     def test_run_instance_boot_option(self):
         result = baremetal._configure_boot(
             self.app.client_manager,
diff --git a/tripleoclient/v1/overcloud_node.py b/tripleoclient/v1/overcloud_node.py
index b797d8793..f34536378 100644
--- a/tripleoclient/v1/overcloud_node.py
+++ b/tripleoclient/v1/overcloud_node.py
@@ -333,36 +333,31 @@ class ConfigureNode(command.Command):
                             action='store_true',
                             help=_('Whether to overwrite existing root device '
                                    'hints when --root-device is used.'))
+        parser.add_argument("--verbosity",
+                            type=int,
+                            default=1,
+                            help=_("Print debug output during execution"))
         return parser
 
     def take_action(self, parsed_args):
         self.log.debug("take_action(%s)" % parsed_args)
 
+        conf = tb.TripleoConfigure(
+                kernel_name=parsed_args.deploy_kernel,
+                ramdisk_name=parsed_args.deploy_ramdisk,
+                instance_boot_option=parsed_args.instance_boot_option,
+                boot_mode=parsed_args.boot_mode,
+                root_device=parsed_args.root_device,
+                root_device_minimum_size=parsed_args.root_device_minimum_size,
+                overwrite_root_device_hints=(
+                    parsed_args.overwrite_root_device_hints)
+                )
+
         if parsed_args.node_uuids:
-            baremetal.configure(
-                self.app.client_manager,
-                node_uuids=parsed_args.node_uuids,
-                kernel_name=parsed_args.deploy_kernel,
-                ramdisk_name=parsed_args.deploy_ramdisk,
-                instance_boot_option=parsed_args.instance_boot_option,
-                boot_mode=parsed_args.boot_mode,
-                root_device=parsed_args.root_device,
-                root_device_minimum_size=parsed_args.root_device_minimum_size,
-                overwrite_root_device_hints=(
-                    parsed_args.overwrite_root_device_hints)
-            )
+            conf.configure(
+                node_uuids=parsed_args.node_uuids)
         else:
-            baremetal.configure_manageable_nodes(
-                self.app.client_manager,
-                kernel_name=parsed_args.deploy_kernel,
-                ramdisk_name=parsed_args.deploy_ramdisk,
-                instance_boot_option=parsed_args.instance_boot_option,
-                boot_mode=parsed_args.boot_mode,
-                root_device=parsed_args.root_device,
-                root_device_minimum_size=parsed_args.root_device_minimum_size,
-                overwrite_root_device_hints=(
-                    parsed_args.overwrite_root_device_hints)
-            )
+            conf.configure_manageable_nodes()
 
 
 class DiscoverNode(command.Command):
diff --git a/tripleoclient/workflows/baremetal.py b/tripleoclient/workflows/baremetal.py
index 022f1f3ff..cf18c8773 100644
--- a/tripleoclient/workflows/baremetal.py
+++ b/tripleoclient/workflows/baremetal.py
@@ -351,105 +351,6 @@ def _apply_root_device_strategy(clients, node_uuid, strategy,
              {'node': node.uuid, 'dev': root_device, 'local_gb': new_size})
 
 
-def configure(clients, node_uuids, kernel_name=None,
-              ramdisk_name=None, instance_boot_option=None,
-              boot_mode=None, root_device=None, root_device_minimum_size=4,
-              overwrite_root_device_hints=False):
-    """Configure Node boot options.
-
-    :param node_uuids: List of instance UUID(s).
-    :type node_uuids: List
-
-    :param kernel_name: Kernel to use
-    :type kernel_name: String
-
-    :param ramdisk_name: RAMDISK to use
-    :type ramdisk_name: String
-
-    :param instance_boot_option: Boot options to use
-    :type instance_boot_option: String
-
-    :param boot_mode: Boot mode to use
-    :type instance_boot_option: String
-
-    :param root_device: Path (name) of the root device.
-    :type root_device: String
-
-    :param root_device_minimum_size: Size of the given root device.
-    :type root_device_minimum_size: Integer
-
-    :param overwrite_root_device_hints: Whether to overwrite existing root
-                                        device hints when `root_device` is
-                                        used.
-    :type overwrite_root_device_hints: Boolean
-    """
-
-    for node_uuid in node_uuids:
-        _configure_boot(clients, node_uuid, kernel_name,
-                        ramdisk_name, instance_boot_option, boot_mode)
-        if root_device:
-            _apply_root_device_strategy(
-                clients, node_uuid,
-                strategy=root_device,
-                minimum_size=root_device_minimum_size,
-                overwrite=overwrite_root_device_hints)
-    print('Successfully configured the nodes.')
-
-
-def configure_manageable_nodes(clients, kernel_name='bm-deploy-kernel',
-                               ramdisk_name='bm-deploy-ramdisk',
-                               instance_boot_option=None, boot_mode=None,
-                               root_device=None, root_device_minimum_size=4,
-                               overwrite_root_device_hints=False):
-    """Configure all manageable Nodes.
-
-    kernel_name=parsed_args.deploy_kernel,
-    ramdisk_name=parsed_args.deploy_ramdisk,
-    instance_boot_option=parsed_args.instance_boot_option,
-    root_device=parsed_args.root_device,
-    root_device_minimum_size=parsed_args.root_device_minimum_size,
-    overwrite_root_device_hints=(parsed_args.overwrite_root_device_hints)
-
-    :param kernel_name: Kernel to use
-    :type kernel_name: String
-
-    :param ramdisk_name: RAMDISK to use
-    :type ramdisk_name: String
-
-    :param instance_boot_option: Boot options to use
-    :type instance_boot_option: String
-
-    :param boot_mode: Boot mode to use
-    :type instance_boot_option: String
-
-    :param root_device: Path (name) of the root device.
-    :type root_device: String
-
-    :param root_device_minimum_size: Size of the given root device.
-    :type root_device_minimum_size: Integer
-
-    :param overwrite_root_device_hints: Whether to overwrite existing root
-                                        device hints when `root_device` is
-                                        used.
-    :type overwrite_root_device_hints: Boolean
-    """
-
-    configure(
-        clients=clients,
-        node_uuids=[
-            i.uuid for i in clients.baremetal.node.list()
-            if i.provision_state == "manageable" and not i.maintenance
-        ],
-        kernel_name=kernel_name,
-        ramdisk_name=ramdisk_name,
-        instance_boot_option=instance_boot_option,
-        boot_mode=boot_mode,
-        root_device=root_device,
-        root_device_minimum_size=root_device_minimum_size,
-        overwrite_root_device_hints=overwrite_root_device_hints
-    )
-
-
 def create_raid_configuration(clients, node_uuids, configuration,
                               verbosity=0):
     """Create RAID configuration on nodes.
diff --git a/tripleoclient/workflows/tripleo_baremetal.py b/tripleoclient/workflows/tripleo_baremetal.py
index 313ff92b7..d85f686dc 100644
--- a/tripleoclient/workflows/tripleo_baremetal.py
+++ b/tripleoclient/workflows/tripleo_baremetal.py
@@ -19,7 +19,9 @@ from concurrent import futures
 from openstack import connect as sdkclient
 from openstack import exceptions
 from openstack.utils import iterate_timeout
+from oslo_utils import units
 from tripleoclient import exceptions as ooo_exceptions
+from tripleo_common.utils import nodes as node_utils
 
 
 class TripleoBaremetal(object):
@@ -309,3 +311,216 @@ class TripleoClean(TripleoBaremetal):
                     self.log.info(msg)
             except exceptions.OpenStackCloudException as err:
                 self.log.error(str(err))
+
+
+class TripleoConfigure(TripleoBaremetal):
+
+    """TripleoConfigure handles properties for the ironic nodes.
+
+    We use this class to set the properties for each node such as the
+    kernel, ramdisk, boot device, root_device.
+
+    :param kernel_name: The name of the kernel image we will deploy
+    :type kernel_name: String
+
+    :param ramdisk_name: The name of the ramdisk image we will deploy
+    :type ramdisk_name: String
+
+    :param instance_boot: Should the node boot from local disks or something
+                          else
+    :type instance_boot: String
+
+    :param boot_mode: Is this node using BIOS or UEFI
+    :type boot_mode: String
+
+    :param: root_device: What is the root device for this node. eg /dev/sda
+    :type root_device: String
+
+    :param root_device_minimum_size: What is the smallest disk we should
+                                     consider acceptable for deployment
+    :type root_device: Integer
+
+    :param overwrite_root_device_hints: Should we overwrite existing root
+                                        device hints when root_device is used.
+    :type overwrite_root_device_hints: Boolean
+    """
+
+    log = logging.getLogger(__name__)
+
+    def __init__(self, kernel_name: str = None, ramdisk_name: str = None,
+                 instance_boot_option: str = None, boot_mode: str = None,
+                 root_device: str = None, verbosity: int = 0,
+                 root_device_minimum_size: int = 4,
+                 overwrite_root_device_hints: bool = False):
+
+        super().__init__(verbosity=verbosity)
+        self.kernel_name = kernel_name
+        self.ramdisk_name = ramdisk_name
+        self.instance_boot_option = instance_boot_option
+        self.boot_mode = boot_mode
+        self.root_device = root_device
+        self.root_device_minimum_size = root_device_minimum_size
+        self.overwrite_root_device_hints = overwrite_root_device_hints
+
+    def _apply_root_device_strategy(self, node_uuid: List,
+                                    strategy: str, minimum_size: int = 4,
+                                    overwrite: bool = False):
+        clients = self.conn
+        node = clients.baremetal.find_node(node_uuid)
+
+        if node.properties.get('root_device') and not overwrite:
+            # This is a correct situation, we still want to allow people to
+            # fine-tune the root device setting for a subset of nodes.
+            # However, issue a warning, so that they know which nodes were not
+            # updated during this run.
+            self.log.warning('Root device hints are already set for node '
+                             '{} and overwriting is not requested,'
+                             ' skipping'.format(node.id))
+            self.log.warning('You may unset them by running $ ironic '
+                             'node-update {} remove '
+                             'properties/root_device'.format(node.id))
+            return
+
+        inspector_client = self.conn.baremetal_introspection
+        baremetal_client = self.conn.baremetal
+
+        try:
+            data = inspector_client.get_introspection_data(node.id)
+        except Exception:
+            raise exceptions.RootDeviceDetectionError(
+                f'No introspection data found for node {node.id}, '
+                'root device cannot be detected')
+        try:
+            disks = data['inventory']['disks']
+        except KeyError:
+            raise exceptions.RootDeviceDetectionError(
+                f'Malformed introspection data for node {node.id}: '
+                'disks list is missing')
+
+        minimum_size *= units.Gi
+        disks = [d for d in disks if d.get('size', 0) >= minimum_size]
+
+        if not disks:
+            raise exceptions.RootDeviceDetectionError(
+                f'No suitable disks found for node {node.id}')
+
+        if strategy == 'smallest':
+            disks.sort(key=lambda d: d['size'])
+            root_device = disks[0]
+        elif strategy == 'largest':
+            disks.sort(key=lambda d: d['size'], reverse=True)
+            root_device = disks[0]
+        else:
+            disk_names = [x.strip() for x in strategy.split(',')]
+            disks = {d['name']: d for d in disks}
+            for candidate in disk_names:
+                try:
+                    root_device = disks['/dev/%s' % candidate]
+                except KeyError:
+                    continue
+                else:
+                    break
+            else:
+                raise exceptions.RootDeviceDetectionError(
+                    f'Cannot find a disk with any of names {strategy} '
+                    f'for node {node.id}')
+
+        hint = None
+
+        for hint_name in ('wwn_with_extension', 'wwn', 'serial'):
+            if root_device.get(hint_name):
+                hint = {hint_name: root_device[hint_name]}
+                break
+
+        if hint is None:
+            # I don't think it might actually happen, but just in case
+            raise exceptions.RootDeviceDetectionError(
+                f"Neither WWN nor serial number are known for device "
+                f"{root_device['name']} "
+                f"on node {node.id}; root device hints cannot be used")
+
+        # During the introspection process we got local_gb assigned according
+        # to the default strategy. Now we need to update it.
+        new_size = root_device['size'] / units.Gi
+        # This -1 is what we always do to account for partitioning
+        new_size -= 1
+
+        baremetal_client.update_node(
+            node.id,
+            [{'op': 'add', 'path': '/properties/root_device', 'value': hint},
+             {'op': 'add', 'path': '/properties/local_gb', 'value': new_size}])
+        self.log.info('Updated root device for node %s, new device '
+                      'is %s, new local_gb is %s',
+                      node.id, root_device, new_size
+                      )
+
+    def _configure_boot(self, node_uuid: List,
+                        kernel_name: str = None,
+                        ramdisk_name: str = None,
+                        instance_boot_option: str = None,
+                        boot_mode: str = None):
+
+        baremetal_client = self.conn.baremetal
+
+        image_ids = {'kernel': kernel_name, 'ramdisk': ramdisk_name}
+        node = baremetal_client.find_node(node_uuid)
+        capabilities = node.properties.get('capabilities', {})
+        capabilities = node_utils.capabilities_to_dict(capabilities)
+
+        if instance_boot_option is not None:
+            capabilities['boot_option'] = instance_boot_option
+        if boot_mode is not None:
+            capabilities['boot_mode'] = boot_mode
+
+        capabilities = node_utils.dict_to_capabilities(capabilities)
+        baremetal_client.update_node(node.id, [
+            {
+                'op': 'add',
+                'path': '/properties/capabilities',
+                'value': capabilities,
+            },
+            {
+                'op': 'add',
+                'path': '/driver_info/deploy_ramdisk',
+                'value': image_ids['ramdisk'],
+            },
+            {
+                'op': 'add',
+                'path': '/driver_info/deploy_kernel',
+                'value': image_ids['kernel'],
+            },
+            {
+                'op': 'add',
+                'path': '/driver_info/rescue_ramdisk',
+                'value': image_ids['ramdisk'],
+            },
+            {
+                'op': 'add',
+                'path': '/driver_info/rescue_kernel',
+                'value': image_ids['kernel'],
+            },
+        ])
+
+    def configure(self, node_uuids: List):
+
+        """Configure Node boot options.
+
+        :param node_uuids: List of instance UUID(s).
+        :type node_uuids: List
+
+        """
+        for node_uuid in node_uuids:
+            self._configure_boot(node_uuid, self.kernel_name,
+                                 self.ramdisk_name, self.instance_boot_option,
+                                 self.boot_mode)
+            if self.root_device:
+                self._apply_root_device_strategy(
+                    node_uuid,
+                    strategy=self.root_device,
+                    minimum_size=self.root_device_minimum_size,
+                    overwrite=self.overwrite_root_device_hints)
+
+        self.log.info('Successfully configured the nodes.')
+
+    def configure_manageable_nodes(self):
+        self.configure(node_uuids=self.all_manageable_nodes())