From 78902bfd0c56ba08642cd1ec0b21408c19ab2839 Mon Sep 17 00:00:00 2001
From: Kaifeng Wang <kaifeng.w@gmail.com>
Date: Tue, 27 Mar 2018 15:52:19 +0800
Subject: [PATCH] Power fault recovery: client support

This patch adds codes to support the fault field exposed from ironic API.
Querying nodes with specified fault is also supported as well.

Story: #1596107
Task: #10469
Partial-Bug: #1596107

Depends-On: https://review.openstack.org/556015/

Change-Id: I429df0ab5ea39140a2b988d5dfdacb24a67b955e
---
 ironicclient/common/http.py                   |  2 +-
 ironicclient/osc/v1/baremetal_node.py         |  7 ++++
 .../tests/unit/osc/v1/test_baremetal_node.py  | 41 +++++++++++++++----
 ironicclient/tests/unit/v1/test_node_shell.py |  1 +
 ironicclient/v1/node.py                       |  7 +++-
 ironicclient/v1/resource_fields.py            |  2 +
 .../notes/node-fault-adbe74fd600063ee.yaml    |  5 +++
 7 files changed, 56 insertions(+), 9 deletions(-)
 create mode 100644 releasenotes/notes/node-fault-adbe74fd600063ee.yaml

diff --git a/ironicclient/common/http.py b/ironicclient/common/http.py
index e8c24f1ea..edf423207 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 = 38
+LAST_KNOWN_API_VERSION = 42
 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 e8d801905..244bca1f8 100755
--- a/ironicclient/osc/v1/baremetal_node.py
+++ b/ironicclient/osc/v1/baremetal_node.py
@@ -555,6 +555,11 @@ class ListBaremetalNode(command.Lister):
             default=None,
             help=_("Limit list to nodes not in maintenance mode"),
         )
+        parser.add_argument(
+            '--fault',
+            dest='fault',
+            metavar='<fault>',
+            help=_("List nodes in specified fault."))
         associated_group = parser.add_mutually_exclusive_group()
         associated_group.add_argument(
             '--associated',
@@ -625,6 +630,8 @@ class ListBaremetalNode(command.Lister):
             params['associated'] = False
         if parsed_args.maintenance is not None:
             params['maintenance'] = parsed_args.maintenance
+        if parsed_args.fault is not None:
+            params['fault'] = parsed_args.fault
         if parsed_args.provision_state:
             params['provision_state'] = parsed_args.provision_state
         if parsed_args.driver:
diff --git a/ironicclient/tests/unit/osc/v1/test_baremetal_node.py b/ironicclient/tests/unit/osc/v1/test_baremetal_node.py
index 33e017e12..6495e5897 100644
--- a/ironicclient/tests/unit/osc/v1/test_baremetal_node.py
+++ b/ironicclient/tests/unit/osc/v1/test_baremetal_node.py
@@ -592,13 +592,12 @@ class TestBaremetalList(TestBaremetal):
                    'Console Enabled', 'Driver', 'Driver Info',
                    'Driver Internal Info', 'Extra', 'Instance Info',
                    'Instance UUID', 'Last Error', 'Maintenance',
-                   'Maintenance Reason', 'Power State', 'Properties',
-                   'Provisioning State', 'Provision Updated At',
-                   'Current RAID configuration', 'Reservation',
-                   'Resource Class',
-                   'Target Power State', 'Target Provision State',
-                   'Target RAID configuration', 'Traits',
-                   'Updated At', 'Inspection Finished At',
+                   'Maintenance Reason', 'Fault',
+                   'Power State', 'Properties', 'Provisioning State',
+                   'Provision Updated At', 'Current RAID configuration',
+                   'Reservation', 'Resource Class', 'Target Power State',
+                   'Target Provision State', 'Target RAID configuration',
+                   'Traits', 'Updated At', 'Inspection Finished At',
                    'Inspection Started At', 'UUID', 'Name',
                    'Boot Interface', 'Console Interface',
                    'Deploy Interface', 'Inspect Interface',
@@ -621,6 +620,7 @@ class TestBaremetalList(TestBaremetal):
             '',
             baremetal_fakes.baremetal_maintenance,
             '',
+            '',
             baremetal_fakes.baremetal_power_state,
             '',
             baremetal_fakes.baremetal_provision_state,
@@ -713,6 +713,33 @@ class TestBaremetalList(TestBaremetal):
                           self.check_parser,
                           self.cmd, arglist, verifylist)
 
+    def test_baremetal_list_fault(self):
+        arglist = [
+            '--maintenance',
+            '--fault', 'power failure',
+        ]
+        verifylist = [
+            ('maintenance', True),
+            ('fault', 'power failure'),
+        ]
+
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+        # DisplayCommandBase.take_action() returns two tuples
+        self.cmd.take_action(parsed_args)
+
+        # Set expected values
+        kwargs = {
+            'marker': None,
+            'limit': None,
+            'maintenance': True,
+            'fault': 'power failure'
+        }
+
+        self.baremetal_mock.node.list.assert_called_with(
+            **kwargs
+        )
+
     def test_baremetal_list_associated(self):
         arglist = [
             '--associated',
diff --git a/ironicclient/tests/unit/v1/test_node_shell.py b/ironicclient/tests/unit/v1/test_node_shell.py
index a8152142e..be0074798 100644
--- a/ironicclient/tests/unit/v1/test_node_shell.py
+++ b/ironicclient/tests/unit/v1/test_node_shell.py
@@ -46,6 +46,7 @@ class NodeShellTest(utils.BaseTestCase):
                'last_error',
                'maintenance',
                'maintenance_reason',
+               'fault',
                'name',
                'boot_interface',
                'console_interface',
diff --git a/ironicclient/v1/node.py b/ironicclient/v1/node.py
index 9fb59c842..292c5cf78 100644
--- a/ironicclient/v1/node.py
+++ b/ironicclient/v1/node.py
@@ -58,7 +58,7 @@ class NodeManager(base.CreateManager):
     def list(self, associated=None, maintenance=None, marker=None, limit=None,
              detail=False, sort_key=None, sort_dir=None, fields=None,
              provision_state=None, driver=None, resource_class=None,
-             chassis=None):
+             chassis=None, fault=None):
         """Retrieve a list of nodes.
 
         :param associated: Optional. Either a Boolean or a string
@@ -105,6 +105,9 @@ class NodeManager(base.CreateManager):
         :param chassis: Optional, the UUID of a chassis. Used to get only
                         nodes of this chassis.
 
+        :param fault: Optional. String value to get only nodes with
+                      specified fault.
+
         :returns: A list of nodes.
 
         """
@@ -121,6 +124,8 @@ class NodeManager(base.CreateManager):
             filters.append('associated=%s' % associated)
         if maintenance is not None:
             filters.append('maintenance=%s' % maintenance)
+        if fault is not None:
+            filters.append('fault=%s' % fault)
         if provision_state is not None:
             filters.append('provision_state=%s' % provision_state)
         if driver is not None:
diff --git a/ironicclient/v1/resource_fields.py b/ironicclient/v1/resource_fields.py
index a67383dfe..0b87feda6 100644
--- a/ironicclient/v1/resource_fields.py
+++ b/ironicclient/v1/resource_fields.py
@@ -76,6 +76,7 @@ class Resource(object):
         'last_error': 'Last Error',
         'maintenance': 'Maintenance',
         'maintenance_reason': 'Maintenance Reason',
+        'fault': 'Fault',
         'mode': 'Mode',
         'name': 'Name',
         'node_uuid': 'Node UUID',
@@ -204,6 +205,7 @@ NODE_DETAILED_RESOURCE = Resource(
      'last_error',
      'maintenance',
      'maintenance_reason',
+     'fault',
      'power_state',
      'properties',
      'provision_state',
diff --git a/releasenotes/notes/node-fault-adbe74fd600063ee.yaml b/releasenotes/notes/node-fault-adbe74fd600063ee.yaml
new file mode 100644
index 000000000..66f4df6c1
--- /dev/null
+++ b/releasenotes/notes/node-fault-adbe74fd600063ee.yaml
@@ -0,0 +1,5 @@
+---
+features:
+  - |
+    Supports the node's ``fault`` field, introduced in the Bare Metal API
+    version 1.42, including displaying or querying nodes by this field.