Repository: sodafoundation/delfin

Issue:
Add VMAX driver support for Unisphere 8.4
**Issue/Feature Description:**
Add VMAX driver support for Unisphere 8.4

**Why this issue to fixed / feature is needed(give scenarios or use cases):**

**How to reproduce, in case of a bug:**

**Other Notes /  Environment Information: (Please give the env information, log link or any useful information for this issue)**



Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/sodafoundation/delfin/pull/479?src=pr&el=h1) Report
> Merging [#479](https://codecov.io/gh/sodafoundation/delfin/pull/479?src=pr&el=desc) (8fdf642) into [master](https://codecov.io/gh/sodafoundation/delfin/commit/8023a1f2b8273ed45bd0064c3cd0044feeeb8e0c?el=desc) (8023a1f) will **decrease** coverage by `0.45%`.
> The diff coverage is `63.63%`.


```diff
@@            Coverage Diff             @@
##           master     #479      +/-   ##
==========================================
- Coverage   67.95%   67.49%   -0.46%     
==========================================
  Files         113      113              
  Lines        8217     8144      -73     
  Branches      926      922       -4     
==========================================
- Hits         5584     5497      -87     
- Misses       2321     2333      +12     
- Partials      312      314       +2     
```

| [Impacted Files](https://codecov.io/gh/sodafoundation/delfin/pull/479?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [delfin/drivers/dell\_emc/vmax/client.py](https://codecov.io/gh/sodafoundation/delfin/pull/479/diff?src=pr&el=tree#diff-ZGVsZmluL2RyaXZlcnMvZGVsbF9lbWMvdm1heC9jbGllbnQucHk=) | `69.63% <62.79%> (-3.27%)` | :arrow_down: |
| [delfin/drivers/dell\_emc/vmax/vmax.py](https://codecov.io/gh/sodafoundation/delfin/pull/479/diff?src=pr&el=tree#diff-ZGVsZmluL2RyaXZlcnMvZGVsbF9lbWMvdm1heC92bWF4LnB5) | `79.59% <100.00%> (-3.17%)` | :arrow_down: |
| [delfin/drivers/driver.py](https://codecov.io/gh/sodafoundation/delfin/pull/479/diff?src=pr&el=tree#diff-ZGVsZmluL2RyaXZlcnMvZHJpdmVyLnB5) | `61.29% <0.00%> (-10.14%)` | :arrow_down: |
| [delfin/wsgi/common.py](https://codecov.io/gh/sodafoundation/delfin/pull/479/diff?src=pr&el=tree#diff-ZGVsZmluL3dzZ2kvY29tbW9uLnB5) | `64.28% <0.00%> (-3.46%)` | :arrow_down: |
| [delfin/api/validation/validators.py](https://codecov.io/gh/sodafoundation/delfin/pull/479/diff?src=pr&el=tree#diff-ZGVsZmluL2FwaS92YWxpZGF0aW9uL3ZhbGlkYXRvcnMucHk=) | `44.35% <0.00%> (-1.74%)` | :arrow_down: |
| [delfin/manager.py](https://codecov.io/gh/sodafoundation/delfin/pull/479/diff?src=pr&el=tree#diff-ZGVsZmluL21hbmFnZXIucHk=) | `68.42% <0.00%> (-1.58%)` | :arrow_down: |
| [delfin/drivers/hpe/hpe\_3par/alert\_handler.py](https://codecov.io/gh/sodafoundation/delfin/pull/479/diff?src=pr&el=tree#diff-ZGVsZmluL2RyaXZlcnMvaHBlL2hwZV8zcGFyL2FsZXJ0X2hhbmRsZXIucHk=) | `47.10% <0.00%> (-1.50%)` | :arrow_down: |
| [delfin/cryptor.py](https://codecov.io/gh/sodafoundation/delfin/pull/479/diff?src=pr&el=tree#diff-ZGVsZmluL2NyeXB0b3IucHk=) | `90.90% <0.00%> (-1.40%)` | :arrow_down: |
| [delfin/api/v1/alerts.py](https://codecov.io/gh/sodafoundation/delfin/pull/479/diff?src=pr&el=tree#diff-ZGVsZmluL2FwaS92MS9hbGVydHMucHk=) | `74.54% <0.00%> (-1.32%)` | :arrow_down: |
| [delfin/api/v1/storages.py](https://codecov.io/gh/sodafoundation/delfin/pull/479/diff?src=pr&el=tree#diff-ZGVsZmluL2FwaS92MS9zdG9yYWdlcy5weQ==) | `70.86% <0.00%> (-0.94%)` | :arrow_down: |
| ... and [32 more](https://codecov.io/gh/sodafoundation/delfin/pull/479/diff?src=pr&el=tree-more) | |


Patch:
diff --git a/delfin/drivers/dell_emc/vmax/client.py b/delfin/drivers/dell_emc/vmax/client.py
index 62974b7..ed24ecc 100644
--- a/delfin/drivers/dell_emc/vmax/client.py
+++ b/delfin/drivers/dell_emc/vmax/client.py
@@ -112,7 +112,44 @@ class VMAXClient(object):
         try:
             storage_info = self.rest.get_system_capacity(
                 self.array_id, self.uni_version)
-            return storage_info
+
+            total_capacity = 0
+            used_capacity = 0
+            free_capacity = 0
+            raw_capacity = 0
+            subscribed_capacity = 0
+            if int(self.uni_version) < 90:
+                physical_capacity = storage_info.get('physicalCapacity')
+                total_cap = storage_info.get('total_usable_cap_gb')
+                used_cap = storage_info.get('total_allocated_cap_gb')
+                subscribed_cap = storage_info.get('total_subscribed_cap_gb')
+                total_raw = physical_capacity.get('total_capacity_gb')
+                free_cap = total_cap - used_cap
+
+                total_capacity = int(total_cap * units.Gi)
+                used_capacity = int(used_cap * units.Gi)
+                free_capacity = int(free_cap * units.Gi)
+                raw_capacity = int(total_raw * units.Gi)
+                subscribed_capacity = int(subscribed_cap * units.Gi)
+
+            else:
+                system_capacity = storage_info['system_capacity']
+                physical_capacity = storage_info.get('physicalCapacity')
+                total_cap = system_capacity.get('usable_total_tb')
+                used_cap = system_capacity.get('usable_used_tb')
+                subscribed_cap = system_capacity.get('subscribed_total_tb')
+                total_raw = physical_capacity.get('total_capacity_gb')
+                free_cap = total_cap - used_cap
+
+                total_capacity = int(total_cap * units.Ti)
+                used_capacity = int(used_cap * units.Ti)
+                free_capacity = int(free_cap * units.Ti)
+                raw_capacity = int(total_raw * units.Gi)
+                subscribed_capacity = int(subscribed_cap * units.Ti)
+
+            return total_capacity, used_capacity, free_capacity,\
+                raw_capacity, subscribed_capacity
+
         except exception.SSLCertificateFailed:
             LOG.error('SSL certificate failed when '
                       'get storage capacity for VMax')
@@ -134,10 +171,20 @@ class VMAXClient(object):
                 pool_info = self.rest.get_srp_by_name(
                     self.array_id, self.uni_version, srp=pool)
 
-                srp_cap = pool_info['srp_capacity']
-                total_cap = srp_cap['usable_total_tb'] * units.Ti
-                used_cap = srp_cap['usable_used_tb'] * units.Ti
-                subscribed_cap = srp_cap['subscribed_total_tb'] * units.Ti
+                total_cap = 0
+                used_cap = 0
+                subscribed_cap = 0
+                if int(self.uni_version) < 90:
+                    total_cap = pool_info['total_usable_cap_gb'] * units.Gi
+                    used_cap = pool_info['total_allocated_cap_gb'] * units.Gi
+                    subscribed_cap =\
+                        pool_info['total_subscribed_cap_gb'] * units.Gi
+                else:
+                    srp_cap = pool_info['srp_capacity']
+                    total_cap = srp_cap['usable_total_tb'] * units.Ti
+                    used_cap = srp_cap['usable_used_tb'] * units.Ti
+                    subscribed_cap = srp_cap['subscribed_total_tb'] * units.Ti
+
                 p = {
                     "name": pool,
                     "storage_id": storage_id,
@@ -150,6 +197,7 @@ class VMAXClient(object):
                     "free_capacity": int(total_cap - used_cap),
                     "subscribed_capacity": int(subscribed_cap),
                 }
+
                 pool_list.append(p)
 
             return pool_list
@@ -221,8 +269,9 @@ class VMAXClient(object):
                     sg = vol['storageGroupId'][0]
                     sg_info = self.rest.get_storage_group(
                         self.array_id, self.uni_version, sg)
-                    v['native_storage_pool_id'] = sg_info['srp']
-                    v['compressed'] = sg_info['compression']
+                    v['native_storage_pool_id'] =\
+                        sg_info.get('srp', default_srps[emulation_type])
+                    v['compressed'] = sg_info.get('compression', False)
                 else:
                     v['native_storage_pool_id'] = default_srps[emulation_type]
 
diff --git a/delfin/drivers/dell_emc/vmax/vmax.py b/delfin/drivers/dell_emc/vmax/vmax.py
index cd3ac40..f58e974 100644
--- a/delfin/drivers/dell_emc/vmax/vmax.py
+++ b/delfin/drivers/dell_emc/vmax/vmax.py
@@ -13,7 +13,6 @@
 # limitations under the License.
 
 from oslo_log import log
-from oslo_utils import units
 from delfin.common import constants
 from delfin.drivers.dell_emc.vmax.alert_handler import snmp_alerts
 from delfin.drivers.dell_emc.vmax.alert_handler import unisphere_alerts
@@ -43,14 +42,9 @@ class VMAXStorageDriver(driver.StorageDriver):
         display_name = array_details['display_name']
 
         # Get Storage details for capacity info
-        storg_info = self.client.get_storage_capacity()
-        system_capacity = storg_info['system_capacity']
-        physical_capacity = storg_info['physicalCapacity']
-        total_cap = system_capacity.get('usable_total_tb')
-        used_cap = system_capacity.get('usable_used_tb')
-        subscribed_cap = system_capacity.get('subscribed_total_tb')
-        total_raw = physical_capacity.get('total_capacity_gb')
-        free_cap = total_cap - used_cap
+        total_capacity, used_capacity, free_capacity,\
+            raw_capacity, subscribed_capacity = \
+            self.client.get_storage_capacity()
 
         storage = {
             # Unisphere Rest API do not provide Array name .
@@ -63,11 +57,11 @@ class VMAXStorageDriver(driver.StorageDriver):
             'status': constants.StorageStatus.NORMAL,
             'serial_number': self.client.array_id,
             'location': '',
-            'total_capacity': int(total_cap * units.Ti),
-            'used_capacity': int(used_cap * units.Ti),
-            'free_capacity': int(free_cap * units.Ti),
-            'raw_capacity': int(total_raw * units.Gi),
-            'subscribed_capacity': int(subscribed_cap * units.Ti)
+            'total_capacity': total_capacity,
+            'used_capacity': used_capacity,
+            'free_capacity': free_capacity,
+            'raw_capacity': raw_capacity,
+            'subscribed_capacity': subscribed_capacity
         }
         LOG.info("get_storage(), successfully retrieved storage details")
         return storage


Test patch:
diff --git a/delfin/tests/unit/drivers/dell_emc/vmax/test_vmax.py b/delfin/tests/unit/drivers/dell_emc/vmax/test_vmax.py
index 53c6713..0284ec8 100644
--- a/delfin/tests/unit/drivers/dell_emc/vmax/test_vmax.py
+++ b/delfin/tests/unit/drivers/dell_emc/vmax/test_vmax.py
@@ -109,6 +109,14 @@ class TestVMAXStorageDriver(TestCase):
 
             }
         }
+        system_capacity_84 = {
+            'total_usable_cap_gb': 100 * 1024,
+            'total_allocated_cap_gb': 75 * 1024,
+            'total_subscribed_cap_gb': 200 * 1024,
+            'physicalCapacity': {
+                'total_capacity_gb': 1500
+            }
+        }
         kwargs = VMAX_STORAGE_CONF
 
         mock_version.return_value = ['V9.0.2.7', '90']
@@ -128,6 +136,11 @@ class TestVMAXStorageDriver(TestCase):
         ret = driver.get_storage(context)
         self.assertDictEqual(ret, expected)
 
+        driver.client.uni_version = '84'
+        mock_capacity.return_value = system_capacity_84
+        ret = driver.get_storage(context)
+        self.assertDictEqual(ret, expected)
+
         mock_array_details.side_effect = exception.StorageBackendException
         with self.assertRaises(Exception) as exc:
             driver.get_storage(context)