From cdab37f6990f9c5aea68b82f723137bd0611cbb8 Mon Sep 17 00:00:00 2001
From: Nisha Agarwal <agarwalnisha1980@gmail.com>
Date: Thu, 19 Jan 2017 22:24:17 +0000
Subject: [PATCH] Add the new capabilities to the iLO InspectInterface

This patch adds the new capabilities to iLO InspectInterface
as listed in the specification. It requires proliantutils
version >=2.4.0 for these new capabilities.

This patch also removes three capabilities keys from
iLO InspectInterface - ``max_raid_level``, ``BootMode``, and
``sr_iov_devices``.
max_raid_level - It cannot be discovered out-of-band using
proliantutils. The capability is set during RAID configuration
as ``raid_level`` instead.
sr_iov_devices - It cannot be discovered out-of-band. Required
Inband mechanism to discover this.
BootMode - This capability required Nova to change as the value
was supposed to be a list of supported boot modes on the system.
Nova asked to implement the Boolean capabilities instead.

Partial-Bug: 1599425

Change-Id: I64c3e471d55c2020204cf7a20e50c399e43eccf7
---
 doc/source/admin/drivers/ilo.rst              | 35 +++++++++++++++++++
 ironic/drivers/modules/ilo/inspect.py         | 18 ++++++++--
 .../unit/drivers/modules/ilo/test_inspect.py  | 31 ++++++++++++----
 .../new_capabilities-5241619c4b46a460.yaml    | 28 +++++++++++++++
 4 files changed, 103 insertions(+), 9 deletions(-)
 create mode 100644 releasenotes/notes/new_capabilities-5241619c4b46a460.yaml

diff --git a/doc/source/admin/drivers/ilo.rst b/doc/source/admin/drivers/ilo.rst
index 93669fded1..6983920a43 100644
--- a/doc/source/admin/drivers/ilo.rst
+++ b/doc/source/admin/drivers/ilo.rst
@@ -1054,6 +1054,7 @@ The following iLO drivers support hardware inspection:
 * ``pxe_ilo``
 * ``iscsi_ilo``
 * ``agent_ilo``
+* ``ilo`` hardware type
 
 .. note::
 
@@ -1113,6 +1114,38 @@ Inspection can also discover the following extra capabilities for iLO drivers:
 
 * ``nic_capacity``: the max speed of the embedded NIC adapter.
 
+* ``sriov_enabled``: true, if server has the SRIOV supporting NIC.
+
+* ``has_rotational``: true, if server has HDD disk.
+
+* ``has_ssd``: true, if server has SSD disk.
+
+* ``has_nvme_ssd``: true, if server has NVME SSD disk.
+
+* ``cpu_vt``: true, if server supports cpu virtualization.
+
+* ``hardware_supports_raid``: true, if RAID can be configured on the server using
+  RAID controller.
+
+* ``nvdimm_n``: true, if server has NVDIMM_N type of persistent memory.
+
+* ``persistent_memory``: true, if server has persistent memory.
+
+* ``logical_nvdimm_n``: true, if server has logical NVDIMM_N configured.
+
+* ``rotational_drive_<speed>_rpm``: The capabilities
+  ``rotational_drive_4800_rpm``, ``rotational_drive_5400_rpm``,
+  ``rotational_drive_7200_rpm``, ``rotational_drive_10000_rpm`` and
+  ``rotational_drive_15000_rpm`` are set to true if the server has HDD
+  drives with speed of 4800, 5400, 7200, 10000 and 15000 rpm respectively.
+
+* ``logical_raid_level_<raid_level>``: The capabilities
+  ``logical_raid_level_0``, ``logical_raid_level_1``, ``logical_raid_level_2``,
+  ``logical_raid_level_5``, ``logical_raid_level_6``, ``logical_raid_level_10``,
+  ``logical_raid_level_50`` and ``logical_raid_level_60`` are set to true if any
+  of the raid levels among 0, 1, 2, 5, 6, 10, 50 and 60 are configured on
+  the system.
+
   .. note::
 
      * The capability ``nic_capacity`` can only be discovered if ipmitool
@@ -1130,6 +1163,8 @@ for scheduling::
 
   nova flavor-key my-baremetal-flavor set capabilities:ilo_firmware_version="<in> 2.10"
 
+  nova flavor-key my-baremetal-flavor set capabilities:has_ssd="true"
+
 See :ref:`capabilities-discovery` for more details and examples.
 
 Swiftless deploy for intermediate images
diff --git a/ironic/drivers/modules/ilo/inspect.py b/ironic/drivers/modules/ilo/inspect.py
index 825e5c1ed3..6884a675e5 100644
--- a/ironic/drivers/modules/ilo/inspect.py
+++ b/ironic/drivers/modules/ilo/inspect.py
@@ -31,9 +31,21 @@ LOG = logging.getLogger(__name__)
 
 METRICS = metrics_utils.get_metrics_logger(__name__)
 
-CAPABILITIES_KEYS = {'BootMode', 'secure_boot', 'rom_firmware_version',
-                     'ilo_firmware_version', 'server_model', 'max_raid_level',
-                     'pci_gpu_devices', 'sr_iov_devices', 'nic_capacity'}
+CAPABILITIES_KEYS = {'secure_boot', 'rom_firmware_version',
+                     'ilo_firmware_version', 'server_model',
+                     'pci_gpu_devices', 'sriov_enabled', 'nic_capacity',
+                     'has_ssd', 'has_rotational',
+                     'rotational_drive_4800_rpm',
+                     'rotational_drive_5400_rpm',
+                     'rotational_drive_7200_rpm',
+                     'rotational_drive_10000_rpm',
+                     'rotational_drive_15000_rpm',
+                     'logical_raid_level_0', 'logical_raid_level_1',
+                     'logical_raid_level_2', 'logical_raid_level_10',
+                     'logical_raid_level_5', 'logical_raid_level_6',
+                     'logical_raid_level_50', 'logical_raid_level_60',
+                     'cpu_vt', 'hardware_supports_raid', 'has_nvme_ssd',
+                     'nvdimm_n', 'logical_nvdimm_n', 'persistent_memory'}
 
 
 def _create_ports_if_not_exist(task, macs):
diff --git a/ironic/tests/unit/drivers/modules/ilo/test_inspect.py b/ironic/tests/unit/drivers/modules/ilo/test_inspect.py
index 7276b3ddaf..242751ee4f 100644
--- a/ironic/tests/unit/drivers/modules/ilo/test_inspect.py
+++ b/ironic/tests/unit/drivers/modules/ilo/test_inspect.py
@@ -199,8 +199,8 @@ class IloInspectTestCase(db_base.DbTestCase):
         properties = {'memory_mb': '512', 'local_gb': '10',
                       'cpus': '1', 'cpu_arch': 'x86_64'}
         macs = {'Port 1': 'aa:aa:aa:aa:aa:aa', 'Port 2': 'bb:bb:bb:bb:bb:bb'}
-        capability_str = 'BootMode:uefi'
-        capabilities = {'BootMode': 'uefi'}
+        capability_str = 'sriov_enabled:true'
+        capabilities = {'sriov_enabled': 'true'}
         result = {'properties': properties, 'macs': macs}
         get_essential_mock.return_value = result
         get_capabilities_mock.return_value = capabilities
@@ -240,15 +240,15 @@ class IloInspectTestCase(db_base.DbTestCase):
                       'somekey': 'somevalue'}
         macs = {'Port 1': 'aa:aa:aa:aa:aa:aa', 'Port 2': 'bb:bb:bb:bb:bb:bb'}
         result = {'properties': properties, 'macs': macs}
-        capabilities = {'BootMode': 'uefi'}
+        capabilities = {'sriov_enabled': 'true'}
         get_essential_mock.return_value = result
         get_capabilities_mock.return_value = capabilities
         power_mock.return_value = states.POWER_ON
         with task_manager.acquire(self.context, self.node.uuid,
                                   shared=False) as task:
-            task.node.properties = {'capabilities': 'foo:bar'}
-            expected_capabilities = ('BootMode:uefi,'
-                                     'foo:bar')
+            task.node.properties = {'capabilities': 'boot_mode:uefi'}
+            expected_capabilities = ('sriov_enabled:true,'
+                                     'boot_mode:uefi')
             set1 = set(expected_capabilities.split(','))
             task.driver.inspect.inspect_hardware(task)
             end_capabilities = task.node.properties['capabilities']
@@ -414,3 +414,22 @@ class TestInspectPrivateMethods(db_base.DbTestCase):
         data = {'properties': properties, 'macs': macs}
         self.assertRaises(exception.HardwareInspectionFailure,
                           ilo_inspect._validate, self.node, data)
+
+    def test___create_supported_capabilities_dict(self):
+        capabilities = {}
+        expected = {}
+        for key in ilo_inspect.CAPABILITIES_KEYS:
+            capabilities.update({key: 'true'})
+            expected.update({key: 'true'})
+        capabilities.update({'unknown_property': 'true'})
+        cap = ilo_inspect._create_supported_capabilities_dict(capabilities)
+        self.assertEqual(expected, cap)
+
+    def test___create_supported_capabilities_dict_excluded_capability(self):
+        capabilities = {}
+        expected = {}
+        for key in ilo_inspect.CAPABILITIES_KEYS - {'has_ssd'}:
+            capabilities.update({key: 'true'})
+            expected.update({key: 'true'})
+        cap = ilo_inspect._create_supported_capabilities_dict(capabilities)
+        self.assertEqual(expected, cap)
diff --git a/releasenotes/notes/new_capabilities-5241619c4b46a460.yaml b/releasenotes/notes/new_capabilities-5241619c4b46a460.yaml
new file mode 100644
index 0000000000..4649beb388
--- /dev/null
+++ b/releasenotes/notes/new_capabilities-5241619c4b46a460.yaml
@@ -0,0 +1,28 @@
+---
+features:
+  - |
+    Adds support for the following Boolean capabilities keys to
+    ``ilo`` inspect interface:
+
+    * ``sriov_enabled``
+    * ``has_ssd``
+    * ``has_rotational``
+    * ``rotational_drive_4800_rpm``
+    * ``rotational_drive_5400_rpm``
+    * ``rotational_drive_7200_rpm``
+    * ``rotational_drive_10000_rpm``
+    * ``rotational_drive_15000_rpm``
+    * ``logical_raid_level_0``
+    * ``logical_raid_level_1``
+    * ``logical_raid_level_2``
+    * ``logical_raid_level_10``
+    * ``logical_raid_level_5``
+    * ``logical_raid_level_6``
+    * ``logical_raid_level_50``
+    * ``logical_raid_level_60``
+    * ``cpu_vt``
+    * ``hardware_supports_raid``
+    * ``has_nvme_ssd``
+    * ``nvdimm_n``
+    * ``logical_nvdimm_n``
+    * ``persistent_memory``