From 82bd5095f387ec4d2a83cf837714002910297efe Mon Sep 17 00:00:00 2001 From: luojiagen <88076879+luojiagen@users.noreply.github.com> Date: Thu, 28 Jul 2022 10:47:09 +0800 Subject: [PATCH] add ScaleIO storage Sofotware staorage\Volume\DIsk\Pool Info Collection (#904) --- delfin/drivers/dell_emc/scaleio/__init__.py | 0 .../drivers/dell_emc/scaleio/alert_consts.py | 64 + delfin/drivers/dell_emc/scaleio/consts.py | 39 + .../drivers/dell_emc/scaleio/rest_handler.py | 447 ++++++ .../drivers/dell_emc/scaleio/scaleio_stor.py | 77 + .../unit/drivers/dell_emc/scaleio/__init__.py | 0 .../drivers/dell_emc/scaleio/test_constans.py | 1329 +++++++++++++++++ .../dell_emc/scaleio/test_scaleio_stor.py | 107 ++ 8 files changed, 2063 insertions(+) create mode 100644 delfin/drivers/dell_emc/scaleio/__init__.py create mode 100644 delfin/drivers/dell_emc/scaleio/alert_consts.py create mode 100644 delfin/drivers/dell_emc/scaleio/consts.py create mode 100644 delfin/drivers/dell_emc/scaleio/rest_handler.py create mode 100644 delfin/drivers/dell_emc/scaleio/scaleio_stor.py create mode 100644 delfin/tests/unit/drivers/dell_emc/scaleio/__init__.py create mode 100644 delfin/tests/unit/drivers/dell_emc/scaleio/test_constans.py create mode 100644 delfin/tests/unit/drivers/dell_emc/scaleio/test_scaleio_stor.py diff --git a/delfin/drivers/dell_emc/scaleio/__init__.py b/delfin/drivers/dell_emc/scaleio/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/delfin/drivers/dell_emc/scaleio/alert_consts.py b/delfin/drivers/dell_emc/scaleio/alert_consts.py new file mode 100644 index 000000000..37333a085 --- /dev/null +++ b/delfin/drivers/dell_emc/scaleio/alert_consts.py @@ -0,0 +1,64 @@ +# Copyright 2022 The SODA Authors. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +ALERT_MAP = { + 'DEVICE_FAILED': 'Device failed', + 'SDC_DISCONNECTED': 'SDC disconnected', + 'MDM_NOT_CLUSTERED': 'MDM is not clustered', + 'SDS_DISCONNECTED ': 'SDS is disconnected', + 'SDS_DISCONNECTS_FREQUENTLY ': 'SDS disconnects frequently ', + 'SDS_RMCACHE_MEMORY_ALLOCATION_FAILED': + 'Memory allocation for RAM ReadCache failed on SDS', + 'STORAGE_POOL_HAS_CAPACITY_ERRORS': 'Storage Pool has capacity errors', + 'STORAGE_POOL_HAS_FAILED_CAPACITY': 'Storage Pool has failed capacity', + 'STORAGE_POOL_HAS_DEGRADED_CAPACITY': 'Storage Pool has degraded capacity', + 'STORAGE_POOL_HAS_UNREACHABLE_CAPACITY': + 'Storage Pool has decreased capacity', + 'STORAGE_POOL_HAS_UNAVAILABLE_UNUSED_CAPACITY': + 'Storage Pool has unavailable-unused capacity', + 'STORAGE_POOL_UNBALANCED': 'Storage Pool is unbalanced ', + 'CAPACITY_UTILIZATION_ABOVE_CRITICAL_THRESHOLD': + 'Capacity utilization above critical threshold', + 'CAPACITY_UTILIZATION_ABOVE_HIGH_THRESHOLD': + 'Capacity utilization above high threshold', + 'CONFIGURED_SPARE_CAPACITY_SMALLER_THAN_LARGEST_FAULT_UNIT': + 'Configured spare capacity is smaller than largest fault unit', + 'SPARE_CAPACITY_AND_FREE_CAPACITY_SMALLER_THAN_LARGEST_FAULT_UNIT': + 'Spare capacity and free capacity are smaller ' + 'than the largest fault unit', + 'SPARE_CAPACITY_BELOW_THRESHOLD ': 'Spare capacity is below threshold', + 'LICENSE_EXPIRED': 'License expired', + 'LICENSE_ABOUT_TO_EXPIRE ': 'License will expire in %d days', + 'FWD_REBUILD_STUCK ': 'Forward rebuild cannot proceed ', + 'BKWD_REBUILD_STUCK': 'Backward rebuild cannot proceed', + 'REBALANCE_STUCK ': 'Rebalance cannot proceed ', + 'MDM_FAILS_OVER_FREQUENTLY': 'MDM fails over frequently', + 'FAILURE_RECOVERY_CAPACITY_BELOW_THRESHOLD': + 'Failure recovery capacity is below the threshold', + 'DEVICE_PENDING_ACTIVATION': + 'Device test is done and device is pending activation', + 'PD_INACTIVE ': 'Inactive Protection Domain', + 'DRL_MODE_NON_VOLATILE': 'DRL mode: Hardened ', + 'NOT_ENOUGH_FAULT_UNITS_IN_SP ': + 'Storage Pool does not meet the minimum requirement of 3 fault units', + 'SDC_MAX_COUNT': 'No more SDCs can be defined on this system; ' + 'the maximum has been reached', + 'FIXED_READ_ERROR_COUNT_ABOVE_THRESHOLD': 'Device has fixed read errors ', + 'SCANNER_COMPARE_ERROR': + 'Background device scanning has found data conflicts', + 'STORAGE_POOL_EXTREMELY_UNBALANCED': + 'The Storage Pool relies too heavily(over 50%)on capacity from a ' + 'single SDS or Fault SetBalance capacity over other SDSs or Fault Sets' + +} diff --git a/delfin/drivers/dell_emc/scaleio/consts.py b/delfin/drivers/dell_emc/scaleio/consts.py new file mode 100644 index 000000000..8f9194363 --- /dev/null +++ b/delfin/drivers/dell_emc/scaleio/consts.py @@ -0,0 +1,39 @@ +# Copyright 2022 The SODA Authors. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +from delfin.common import constants + +StorageVendor = 'DELL EMC' +DEFAULT_TIMEOUT = 10 +REST_AUTH_LOGIN = '/api/login' +REST_AUTH_LOGOUT = '/api/logout' +REST_SCALEIO_SYSTEM = '/api/types/System/instances' +REST_SCALEIO_STORAGE_POOL = '/api/types/StoragePool/instances' +REST_SCALEIO_VOLUMES = '/api/types/Volume/instances' +REST_SCALEIO_DISKS = '/api/types/Device/instances' +REST_SCALIO_HOSTS = '/api/types/Sdc/instances' +REST_SCALIO_INITIIATORS = '/api/types/Sds/instances' +REST_SCALEIO_ALERT = '/api/types/Alert/instances' +DEFAULT_ALERTS_TIME_CONVERSION = 1000 +DEFAULT_VOLUME_USERD_CAPACITY = 0 +DATETIME_UTC_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ' +OID_SEVERITY = '1139.101.1.1' +OID_EVENT_TYPE = '1139.101.1.2' +OID_ERR_ID = '1139.101.1.3' +OID_EVENT_ID = '1139.101.1.4' + +TRAP_ALERT_MAP = { + '5': constants.Severity.CRITICAL, + '2': constants.Severity.WARNING, +} diff --git a/delfin/drivers/dell_emc/scaleio/rest_handler.py b/delfin/drivers/dell_emc/scaleio/rest_handler.py new file mode 100644 index 000000000..4fc13fdaf --- /dev/null +++ b/delfin/drivers/dell_emc/scaleio/rest_handler.py @@ -0,0 +1,447 @@ +# Copyright 2022 The SODA Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import hashlib +import six +import json + +import requests +import datetime +import time +from oslo_log import log +from oslo_utils import units +from delfin import exception +from delfin import cryptor +from delfin.common import alert_util +from delfin.drivers.utils.rest_client import RestClient +from delfin.drivers.dell_emc.scaleio import consts +from delfin.drivers.dell_emc.scaleio import alert_consts +from delfin.common import constants + +LOG = log.getLogger(__name__) + + +class RestHandler(RestClient): + + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.init_http_head() + self.login() + + def login(self): + try: + res = self.get_rest_info(consts.REST_AUTH_LOGIN, 'login', 'GET') + if res: + self.rest_auth_token = res + else: + LOG.error("Login error. URL: %(url)s\n" + "Reason: %(reason)s.", + {"url": consts.REST_AUTH_LOGIN, "reason": res.text}) + if 'User authentication failed' in res.text: + raise exception.InvalidUsernameOrPassword() + else: + raise exception.StorageBackendException( + six.text_type(res.text)) + except Exception as e: + LOG.error("Login error: %s", six.text_type(e)) + raise exception.InvalidResults(e) + + def logout(self): + try: + if self.session: + self.session.close() + except Exception as e: + err_msg = "Logout error: %s" % (six.text_type(e)) + LOG.error(err_msg) + raise exception.InvalidResults(e) + + def get_storage(self, storage_id): + try: + storage_json = self.get_rest_info(consts.REST_SCALEIO_SYSTEM) + for system_json in (storage_json or []): + system_id = system_json.get('id') + system_links = json.loads(json.dumps( + system_json.get('links'))) + total_capacity = 0 + used_capacity = 0 + raw_capacity = 0 + if not system_links: + continue + storage_disk_list = self.list_disks(storage_id) + for storage_disk in storage_disk_list: + raw_capacity += storage_disk.get('capacity') + mdm_cluster = json.loads(json.dumps( + system_json.get('mdmCluster'))) + version_info = json.dumps( + system_json.get('systemVersionName')) + version_detail = version_info.split(' Version: ') + version_id = version_detail[1].replace('\"', '') + model = version_detail[0].replace('\"', '') + cluster_state = mdm_cluster.get('clusterState') + status = constants.StorageStatus.OFFLINE + if 'Degraded' in cluster_state: + status = constants.StorageStatus.DEGRADED + elif 'Normal' in cluster_state: + status = constants.StorageStatus.NORMAL + for system_link in system_links: + if 'Statistics' in system_link.get('href'): + storage_detail = self.get_rest_info( + system_link.get('href')) + total_capacity = storage_detail. \ + get('maxCapacityInKb') + used_capacity = storage_detail. \ + get('capacityInUseInKb') + storage_map = { + 'name': 'ScaleIO', + 'vendor': consts.StorageVendor, + 'model': model, + 'status': status, + 'serial_number': system_id, + 'firmware_version': version_id, + 'raw_capacity': raw_capacity, + 'total_capacity': int(total_capacity) * units.Ki, + 'used_capacity': int(used_capacity) * units.Ki, + 'free_capacity': int(total_capacity + - used_capacity) * units.Ki + } + return storage_map + except exception.DelfinException as err: + err_msg = "Get Storage System error: %s" % err.msg + LOG.error(err_msg) + raise err + except Exception as e: + LOG.error("Get Storage System error: %s", six.text_type(e)) + raise exception.InvalidResults(e) + + def list_storage_pools(self, storage_id): + storage_pool_list = [] + try: + storage_pool_json = self.get_rest_info( + consts.REST_SCALEIO_STORAGE_POOL) + for pool_json in (storage_pool_json or []): + pool_name = pool_json.get('name') + native_storage_pool_id = pool_json.get('id') + pool_links = pool_json.get('links') + used_capacity = 0 + total_size = 0 + for pool_link in pool_links: + if 'Statistics' in pool_link.get('rel'): + storage_pool_statics = self.get_rest_info( + pool_link.get('href')) + json.dumps(storage_pool_statics) + used_capacity = storage_pool_statics.\ + get('capacityInUseInKb') + total_size = storage_pool_statics.\ + get('maxCapacityInKb') + pool_map = { + 'name': pool_name, + 'storage_id': storage_id, + 'native_storage_pool_id': native_storage_pool_id, + 'status': constants.StorageStatus.NORMAL, + 'storage_type': constants.StorageType.BLOCK, + 'total_capacity': int(total_size) * units.Ki, + 'used_capacity': int(used_capacity) * units.Ki, + 'free_capacity': int(total_size - + used_capacity) * units.Ki + } + storage_pool_list.append(pool_map) + return storage_pool_list + except exception.DelfinException as err: + err_msg = "Get Storage pool error: %s" % err.msg + LOG.error(err_msg) + raise err + except Exception as e: + LOG.error("Get Storage pool error: %s", six.text_type(e)) + raise exception.InvalidResults(e) + + def list_volumes(self, storage_id): + list_volumes = [] + try: + storage_volume_json = self.get_rest_info( + consts.REST_SCALEIO_VOLUMES) + for json_volume in (storage_volume_json or []): + volume_name = json_volume.get('name') + native_storage_pool_id = json_volume.get('storagePoolId') + native_volume_id = json_volume.get('id') + total_size = json_volume.get('sizeInKb') + volume_type = constants.VolumeType.THIN + if 'Thick' in json_volume.get('volumeType'): + volume_type = constants.VolumeType.THICK + volume_map = { + 'name': volume_name, + 'storage_id': storage_id, + 'description': volume_name, + 'status': 'normal', + 'native_volume_id': native_volume_id, + 'native_storage_pool_id': native_storage_pool_id, + 'wwn': native_volume_id, + 'type': volume_type, + 'total_capacity': int(total_size) * units.Ki, + 'free_capacit': consts.DEFAULT_VOLUME_USERD_CAPACITY, + 'used_capacity': consts.DEFAULT_VOLUME_USERD_CAPACITY, + 'compressed': True, + 'deduplicated': True + } + list_volumes.append(volume_map) + return list_volumes + except exception.DelfinException as err: + err_msg = "Get Storage volume error: %s" % err.msg + LOG.error(err_msg) + raise err + except Exception as e: + LOG.error("Get Storage volume error: %s", six.text_type(e)) + raise exception.InvalidResults(e) + + def list_disks(self, storage_id): + disks_list = [] + try: + storage_disks_json = self.get_rest_info(consts.REST_SCALEIO_DISKS) + for json_disk in (storage_disks_json or []): + device_status = json_disk.get('deviceState') + capacity = json_disk.get('maxCapacityInKb') + status = constants.DiskStatus.NORMAL + if device_status != 'Normal': + status = constants.DiskStatus.OFFLINE + disk_map = { + 'native_disk_id': json_disk.get('id'), + 'name': json_disk.get('name'), + 'status': status, + 'storage_id': storage_id, + 'native_disk_group_id': json_disk.get('sdsId'), + 'serial_number': json_disk.get('id'), + 'capacity': int(capacity) * units.Ki, + 'health_score': status + } + disks_list.append(disk_map) + return disks_list + except exception.DelfinException as err: + err_msg = "Get Storage disk error: %s" % err.msg + LOG.error(err_msg) + raise err + except Exception as e: + LOG.error("Get Storage disk error: %s", six.text_type(e)) + raise exception.InvalidResults(e) + + def list_alerts(self, query_para=None): + alert_list = [] + try: + storage_alert = self.get_rest_info(consts.REST_SCALEIO_ALERT) + alert_description_map = alert_consts.ALERT_MAP + for json_alert in (storage_alert or []): + match_key = json_alert.get('id') + json_alert.get('name') + occur_time = json_alert.get('startTime') + datetime_obj = datetime.datetime.strptime( + occur_time, consts.DATETIME_UTC_FORMAT) + alert_time = int(time.mktime(datetime_obj.timetuple()) * + consts.DEFAULT_ALERTS_TIME_CONVERSION + + datetime_obj.microsecond / + consts.DEFAULT_ALERTS_TIME_CONVERSION) + alert_type_desc = json_alert.get('alertType') + alert_type_desc = alert_type_desc.lower().replace('_', ' ') + if not alert_util.is_alert_in_time_range(query_para, + alert_time): + continue + alert_severity = json_alert.get('severity') + if 'LOW' in alert_severity: + alert_severity = constants.Severity.MINOR + elif 'MEDIUM' in alert_severity: + alert_severity = constants.Severity.CRITICAL + elif 'HIGH' in alert_severity: + alert_severity = constants.Severity.FATAL + alert_type = json_alert.get('alertType') + alert_model = { + 'alert_id': json_alert.get('id'), + 'alert_name': alert_type + json_alert.get('name'), + 'severity': alert_severity, + 'category': constants.Category.FAULT, + 'type': alert_type, + 'sequence_number': json_alert.get('uuid'), + 'description': alert_description_map.get( + json_alert.get('alertType'), alert_type_desc), + 'occur_time': alert_time, + 'match_key': hashlib.md5( + match_key.encode()).hexdigest() + } + alert_list.append(alert_model) + return alert_list + except exception.DelfinException as err: + err_msg = "Get Storage alerts error: %s" % err.msg + LOG.error(err_msg) + raise err + except Exception as e: + LOG.error("Get Storage alerts error: %s", six.text_type(e)) + raise exception.InvalidResults(e) + + def list_storage_host_initiators(self, storage_id): + initiators_list = [] + try: + storage_initiators = self.get_rest_info( + consts.REST_SCALIO_INITIIATORS) + list_host = self.list_storage_hosts(storage_id) + for initiators_json in (storage_initiators or []): + status = initiators_json.get('sdsState') + initiators_id = initiators_json.get('id') + initiators_type = constants.InitiatorType.UNKNOWN + if 'iscsi' in initiators_json.get('perfProfile'): + initiators_type = constants.InitiatorType.ISCSI + if 'Normal' == status: + status = constants.InitiatorStatus.ONLINE + elif 'Disconnected' == status: + status = constants.InitiatorStatus.OFFLINE + ip_list = initiators_json.get('ipList') + native_storage_host_id = None + for ip_data in ip_list: + sds_ip = ip_data.get('ip') + for host_json in list_host: + ip_address = host_json.get('ip_address') + if sds_ip == ip_address: + native_storage_host_id = \ + host_json.get('native_storage_host_id') + initiators_dict = { + "name": initiators_json.get('name'), + "storage_id": storage_id, + "native_storage_host_initiator_id": initiators_id, + "wwn": initiators_id, + "type": initiators_type, + "status": status, + "native_storage_host_id": native_storage_host_id, + } + initiators_list.append(initiators_dict) + return initiators_list + except exception.DelfinException as err: + err_msg = "Get Storage initiators error: %s" % err.msg + LOG.error(err_msg) + raise err + except Exception as e: + LOG.error("Get Storage initiators error: %s", six.text_type(e)) + raise exception.InvalidResults(e) + + def list_storage_hosts(self, storage_id): + host_list = [] + try: + storage_hosts = self.get_rest_info(consts.REST_SCALIO_HOSTS) + for host_json in (storage_hosts or []): + status = host_json.get('mdmConnectionState') + if 'Connected' == status: + status = constants.HostStatus.NORMAL + elif 'Disconnected' == status: + status = constants.HostStatus.OFFLINE + ip_address = host_json.get('sdcIp') + soft_version = host_json.get('softwareVersionInfo') + host_dict = { + "name": host_json.get('sdcGuid'), + "description": ip_address + soft_version, + "storage_id": storage_id, + "native_storage_host_id": + host_json.get('id'), + "os_type": host_json.get('osType'), + "status": status, + "ip_address": ip_address + } + host_list.append(host_dict) + return host_list + except exception.DelfinException as err: + err_msg = "Get Storage hosts error: %s" % err.msg + LOG.error(err_msg) + raise err + except Exception as e: + LOG.error("Get Storage hosts error: %s", six.text_type(e)) + raise exception.InvalidResults(e) + + def list_masking_views(self, storage_id): + list_masking_views_list = [] + try: + storage_view = self.get_rest_info(consts.REST_SCALEIO_VOLUMES) + for map_json in (storage_view or []): + view_name = map_json.get('name') + volume_id = map_json.get('id') + map_sdc_list = map_json.get('mappedSdcInfo') + if map_sdc_list: + for map_sdc in map_sdc_list: + sdc_id = map_sdc.get('sdcId') + view_map = { + "name": view_name + sdc_id + volume_id, + "description": view_name, + "storage_id": storage_id, + "native_masking_view_id": + view_name + sdc_id + volume_id, + 'native_volume_id': volume_id, + 'native_storage_host_id': sdc_id + } + list_masking_views_list.append(view_map) + return list_masking_views_list + except exception.DelfinException as err: + err_msg = "Get Storage Views Error: %s" % err.msg + LOG.error(err_msg) + raise err + except Exception as e: + LOG.error("Get Storage Views Error: %s", six.text_type(e)) + raise exception.InvalidResults(e) + + @staticmethod + def parse_alert(alert): + alert_model = dict() + try: + alert_dict = alert.split(' ') + for alert_json in alert_dict: + alert_detail = alert_json.split('=')[1] + if consts.OID_SEVERITY in alert_json: + severity = consts.TRAP_ALERT_MAP.get( + alert_detail, constants.Severity.INFORMATIONAL) + alert_model['severity'] = severity + elif consts.OID_EVENT_ID in alert_json: + alert_model['alert_name'] = alert_detail.replace('\"', '') + elif consts.OID_EVENT_TYPE in alert_json: + alert_desc = alert_detail.split('.')[2].lower().replace( + '_', ' ') + alert_model['description'] = alert_desc + alert_model['location'] = alert_desc + elif consts.OID_ERR_ID in alert_json: + alert_model['alert_id'] = str( + alert_detail.replace('\"', '')) + alert_model['category'] = constants.Category.FAULT + alert_model['type'] = constants.EventType.EQUIPMENT_ALARM + now = time.time() + alert_model['occur_time'] = \ + int(round(now * consts.DEFAULT_ALERTS_TIME_CONVERSION)) + return alert_model + except Exception as e: + LOG.error(e) + msg = "Failed to build alert model: %s." % (six.text_type(e)) + raise exception.InvalidResults(msg) + + def get_rest_info(self, url, data=None, method='GET'): + if 'login' == data: + self.session.auth = requests.auth.HTTPBasicAuth( + self.rest_username, cryptor.decode(self.rest_password)) + else: + self.login() + self.session.auth = requests.auth.HTTPBasicAuth( + self.rest_username, self.rest_auth_token) + res = self.do_call(url, data, method) + try: + if res.status_code == 200: + result_json = json.loads(res.text) + elif res.status_code == 500: + LOG.error('Connect Timeout error') + raise exception.ConnectTimeout() + elif res.status_code == 401: + LOG.error('User authentication failed') + raise exception.InvalidUsernameOrPassword + else: + raise exception.BadResponse() + except Exception as err: + LOG.exception('Get RestHandler.call failed: %(url)s.' + ' Error: %(err)s', {'url': url, 'err': err}) + raise exception.InvalidResults(err) + return result_json diff --git a/delfin/drivers/dell_emc/scaleio/scaleio_stor.py b/delfin/drivers/dell_emc/scaleio/scaleio_stor.py new file mode 100644 index 000000000..6d7351879 --- /dev/null +++ b/delfin/drivers/dell_emc/scaleio/scaleio_stor.py @@ -0,0 +1,77 @@ +# Copyright 2022 The SODA Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from oslo_log import log +from delfin.drivers import driver +from delfin.drivers.dell_emc.scaleio import rest_handler +from delfin.drivers.dell_emc.scaleio.rest_handler import RestHandler + +LOG = log.getLogger(__name__) + + +class ScaleioStorageDriver(driver.StorageDriver): + + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.rest_handler = rest_handler.RestHandler(**kwargs) + self.rest_handler.logout() + self.rest_handler.verify = kwargs.get('verify', False) + self.rest_handler.login() + + def reset_connection(self, context, **kwargs): + self.rest_handler.logout() + self.rest_handler.verify = kwargs.get('verify', False) + return self.rest_handler.login() + + def get_storage(self, context): + return self.rest_handler.get_storage(self.storage_id) + + def list_storage_pools(self, context): + return self.rest_handler.list_storage_pools(self.storage_id) + + def list_volumes(self, context): + return self.rest_handler.list_volumes(self.storage_id) + + def list_disks(self, context): + return self.rest_handler.list_disks(self.storage_id) + + def list_alerts(self, context, query_para=None): + return self.rest_handler.list_alerts(query_para) + + @staticmethod + def parse_alert(context, alert): + return RestHandler.parse_alert(alert) + + def add_trap_config(self, context, trap_config): + pass + + def clear_alert(self, context, trap_config): + pass + + def remove_trap_config(self, context, trap_config): + pass + + def list_storage_host_initiators(self, context): + return self.rest_handler.list_storage_host_initiators(self.storage_id) + + def list_storage_hosts(self, context): + return self.rest_handler.list_storage_hosts(self.storage_id) + + def list_masking_views(self, context): + return self.rest_handler.list_masking_views(self.storage_id) + + @staticmethod + def get_access_url(): + return 'https://{ip}' diff --git a/delfin/tests/unit/drivers/dell_emc/scaleio/__init__.py b/delfin/tests/unit/drivers/dell_emc/scaleio/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/delfin/tests/unit/drivers/dell_emc/scaleio/test_constans.py b/delfin/tests/unit/drivers/dell_emc/scaleio/test_constans.py new file mode 100644 index 000000000..53192c805 --- /dev/null +++ b/delfin/tests/unit/drivers/dell_emc/scaleio/test_constans.py @@ -0,0 +1,1329 @@ +# Copyright 2022 The SODA Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +SYSTEM_INFO = [ + { + "systemVersionName": "DellEMC ScaleIO Version: R2_5.0.254", + "capacityAlertHighThresholdPercent": 80, + "capacityAlertCriticalThresholdPercent": 90, + "remoteReadOnlyLimitState": False, + "upgradeState": "NoUpgrade", + "mdmManagementPort": 6611, + "sdcMdmNetworkDisconnectionsCounterParameters": { + "shortWindow": { + "threshold": 300, + "windowSizeInSec": 60 + }, + "mediumWindow": { + "threshold": 500, + "windowSizeInSec": 3600 + }, + "longWindow": { + "threshold": 700, + "windowSizeInSec": 86400 + } + }, + "sdcSdsNetworkDisconnectionsCounterParameters": { + "shortWindow": { + "threshold": 800, + "windowSizeInSec": 60 + }, + "mediumWindow": { + "threshold": 4000, + "windowSizeInSec": 3600 + }, + "longWindow": { + "threshold": 20000, + "windowSizeInSec": 86400 + } + }, + "sdcMemoryAllocationFailuresCounterParameters": { + "shortWindow": { + "threshold": 300, + "windowSizeInSec": 60 + }, + "mediumWindow": { + "threshold": 500, + "windowSizeInSec": 3600 + }, + "longWindow": { + "threshold": 700, + "windowSizeInSec": 86400 + } + }, + "sdcSocketAllocationFailuresCounterParameters": { + "shortWindow": { + "threshold": 300, + "windowSizeInSec": 60 + }, + "mediumWindow": { + "threshold": 500, + "windowSizeInSec": 3600 + }, + "longWindow": { + "threshold": 700, + "windowSizeInSec": 86400 + } + }, + "sdcLongOperationsCounterParameters": { + "shortWindow": { + "threshold": 10000, + "windowSizeInSec": 60 + }, + "mediumWindow": { + "threshold": 100000, + "windowSizeInSec": 3600 + }, + "longWindow": { + "threshold": 1000000, + "windowSizeInSec": 86400 + } + }, + "cliPasswordAllowed": True, + "managementClientSecureCommunicationEnabled": True, + "tlsVersion": "TLSv1.2", + "showGuid": True, + "authenticationMethod": "Native", + "mdmToSdsPolicy": "Authentication", + "mdmCluster": { + "clusterState": "ClusteredNormal", + "clusterMode": "ThreeNodes", + "goodNodesNum": 3, + "goodReplicasNum": 2, + "id": "8049148500852184920" + }, + "perfProfile": "Default", + "installId": "7b940dfb71191770", + "daysInstalled": 6, + "maxCapacityInGb": "Unlimited", + "capacityTimeLeftInDays": "Unlimited", + "isInitialLicense": True, + "defaultIsVolumeObfuscated": False, + "restrictedSdcModeEnabled": False, + "restrictedSdcMode": "None", + "enterpriseFeaturesEnabled": True, + "id": "6fb451ea51a99758", + "links": [ + { + "rel": "/api/System/relationship/Statistics", + "href": "/api/instances/System::6fb451ea51a99758/" + "relationships/Statistics" + } + ] + } +] + +SYSTEM_DETAIL = { + "pendingMovingOutBckRebuildJobs": 0, + "rfcachePoolWritePending": 0, + "degradedHealthyCapacityInKb": 0, + "activeMovingOutFwdRebuildJobs": 0, + "rfcachePoolWritePendingG1Sec": 0, + "bckRebuildWriteBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "primaryReadFromDevBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "BackgroundScannedInMB": 0, + "rfcacheReadsSkippedAlignedSizeTooLarge": 0, + "rfcachePoolSize": 0, + "pendingMovingInRebalanceJobs": 0, + "rfcacheWritesSkippedHeavyLoad": 0, + "rfcachePoolPagesInuse": 0, + "unusedCapacityInKb": 14107527168, + "rmcacheEntryEvictionCount": 0, + "rfcacheFdAvgWriteTime": 0, + "totalReadBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "totalWriteBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "rmPendingAllocatedInKb": 0, + "numOfVolumes": 19, + "rfcacheIosOutstanding": 0, + "rmcacheBigBlockEvictionSizeCountInKb": 0, + "capacityAvailableForVolumeAllocationInKb": 7038042112, + "numOfMappedToAllVolumes": 0, + "numOfScsiInitiators": 0, + "rebuildPerReceiveJobNetThrottlingInKbps": 0, + "rmcache32kbEntryCount": 0, + "rfcachePoolEvictions": 0, + "rfcachePoolNumCacheDevs": 0, + "activeMovingInNormRebuildJobs": 0, + "rfcacheFdWriteTimeGreater500Millis": 0, + "rmcacheSkipCountCacheAllBusy": 0, + "fixedReadErrorCount": 0, + "rfcachePoolNumSrcDevs": 0, + "numOfSdc": 3, + "rfcacheFdMonitorErrorStuckIo": 0, + "rfcacheReadsSkippedInternalError": 0, + "pendingMovingInBckRebuildJobs": 0, + "rfcachePoolWritePendingG500Micro": 0, + "activeBckRebuildCapacityInKb": 0, + "rebalanceCapacityInKb": 0, + "rfcachePoolInLowMemoryCondition": 0, + "rfcacheReadsSkippedLowResources": 0, + "thinCapacityInUseInKb": 4096, + "rfcachePoolLowResourcesInitiatedPassthroughMode": 0, + "rfcachePoolWritePendingG10Millis": 0, + "rfcacheWritesSkippedInternalError": 0, + "rfcachePoolWriteHit": 0, + "rmcache128kbEntryCount": 0, + "rfcacheWritesSkippedCacheMiss": 0, + "rfcacheFdReadTimeGreater5Sec": 0, + "numOfFaultSets": 0, + "degradedFailedCapacityInKb": 0, + "BackgroundScanCompareCount": 0, + "activeNormRebuildCapacityInKb": 0, + "snapCapacityInUseInKb": 20967424, + "rfcacheWriteMiss": 0, + "rfcacheFdIoErrors": 0, + "primaryReadFromRmcacheBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "numOfVtrees": 19, + "rfacheReadHit": 0, + "rfcachePooIosOutstanding": 0, + "pendingMovingCapacityInKb": 0, + "numOfSnapshots": 0, + "sdcIds": [ + "7bec302f00000000", + "7bec303000000001", + "7bec303100000002" + ], + "pendingFwdRebuildCapacityInKb": 0, + "rmcacheBigBlockEvictionCount": 0, + "rmcacheNoEvictionCount": 0, + "rmcacheCurrNumOf128kbEntries": 0, + "normRebuildCapacityInKb": 0, + "rfcachePoolReadPendingG1Millis": 0, + "primaryWriteBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "numOfThickBaseVolumes": 14, + "rmcacheSizeInUseInKb": 0, + "rfcachePoolReadPendingG10Millis": 0, + "activeRebalanceCapacityInKb": 0, + "rfcacheReadsSkippedLockIos": 0, + "unreachableUnusedCapacityInKb": 0, + "rfcachePoolReadPendingG500Micro": 0, + "rmcache8kbEntryCount": 0, + "numOfVolumesInDeletion": 0, + "maxCapacityInKb": 17932736512, + "pendingMovingOutFwdRebuildJobs": 0, + "rmcacheSkipCountLargeIo": 0, + "protectedCapacityInKb": 3825209343, + "secondaryWriteBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "normRebuildReadBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "thinCapacityAllocatedInKb": 2097152000, + "thinCapacityAllocatedInKm": 2097152000, + "rebalanceWriteBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "rmcacheCurrNumOf8kbEntries": 0, + "primaryVacInKb": 2961178624, + "secondaryVacInKb": 2961178624, + "numOfDevices": 10, + "rfcachePoolWriteMiss": 0, + "rfcachePoolReadPendingG1Sec": 0, + "failedCapacityInKb": 0, + "rebalanceWaitSendQLength": 0, + "rfcacheFdReadTimeGreater1Min": 0, + "rmcache4kbEntryCount": 0, + "rfcachePoolWritePendingG1Millis": 0, + "rebalancePerReceiveJobNetThrottlingInKbps": 0, + "rfcacheReadsFromCache": 0, + "activeMovingOutBckRebuildJobs": 0, + "rfcacheFdReadTimeGreater1Sec": 0, + "rmcache64kbEntryCount": 0, + "pendingMovingInNormRebuildJobs": 0, + "primaryReadBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "failedVacInKb": 0, + "pendingRebalanceCapacityInKb": 0, + "rfcacheAvgReadTime": 0, + "semiProtectedCapacityInKb": 0, + "rfcachePoolSourceIdMismatch": 0, + "rfcacheFdAvgReadTime": 0, + "fwdRebuildReadBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "rfcacheWritesReceived": 0, + "rfcachePoolSuspendedIos": 0, + "protectedVacInKb": 5922357248, + "activeMovingRebalanceJobs": 0, + "bckRebuildCapacityInKb": 0, + "activeMovingInFwdRebuildJobs": 0, + "pendingMovingRebalanceJobs": 0, + "degradedHealthyVacInKb": 0, + "rfcachePoolLockTimeGreater1Sec": 0, + "semiProtectedVacInKb": 0, + "userDataReadBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "pendingBckRebuildCapacityInKb": 0, + "rmcacheCurrNumOf4kbEntries": 0, + "capacityLimitInKb": 17932736512, + "numOfProtectionDomains": 1, + "activeMovingCapacityInKb": 0, + "rfcacheIosSkipped": 0, + "scsiInitiatorIds": [], + "rfcacheFdWriteTimeGreater5Sec": 0, + "userDataWriteBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "inMaintenanceVacInKb": 0, + "rfcacheReadsSkipped": 0, + "rfcachePoolReadHit": 0, + "rebuildWaitSendQLength": 0, + "numOfUnmappedVolumes": 17, + "rmcacheCurrNumOf64kbEntries": 0, + "rfcacheWritesSkippedMaxIoSize": 0, + "rfacheWriteHit": 0, + "atRestCapacityInKb": 3825209344, + "bckRebuildReadBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "rfcacheSourceDeviceWrites": 0, + "spareCapacityInKb": 0, + "rfcacheFdInlightReads": 0, + "normRebuildWriteBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "numOfSds": 3, + "rfcacheIoErrors": 0, + "capacityInUseInKb": 3825209344, + "rebalanceReadBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "rmcacheSkipCountUnaligned4kbIo": 0, + "rfcacheReadsSkippedMaxIoSize": 0, + "secondaryReadFromDevBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "rfcachePoolSuspendedPequestsRedundantSearchs": 0, + "secondaryReadFromRmcacheBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "rfcacheWritesSkippedStuckIo": 0, + "secondaryReadBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "numOfStoragePools": 2, + "rfcachePoolCachePages": 0, + "inMaintenanceCapacityInKb": 0, + "protectionDomainIds": [ + "4389836100000000" + ], + "inUseVacInKb": 5922357248, + "fwdRebuildCapacityInKb": 0, + "thickCapacityInUseInKb": 3825205248, + "activeMovingInRebalanceJobs": 0, + "rmcacheCurrNumOf32kbEntries": 0, + "rfcacheWritesSkippedLowResources": 0, + "rfcacheFdCacheOverloaded": 0, + "rmcache16kbEntryCount": 0, + "rmcacheEntryEvictionSizeCountInKb": 0, + "rfcacheSkippedUnlinedWrite": 0, + "rfcacheAvgWriteTime": 0, + "pendingNormRebuildCapacityInKb": 0, + "rfcacheFdReadTimeGreater500Millis": 0, + "pendingMovingOutNormrebuildJobs": 0, + "rfcacheSourceDeviceReads": 0, + "rmcacheCurrNumOf16kbEntries": 0, + "rfcacheReadsPending": 0, + "fwdRebuildWriteBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "rfcacheReadsSkippedHeavyLoad": 0, + "rfcacheFdInlightWrites": 0, + "rfcacheReadMiss": 0, + "rfcacheFdReadsReceived": 0, + "activeMovingInBckRebuildJobs": 0, + "movingCapacityInKb": 0, + "pendingMovingInFwdRebuildJobs": 0, + "rfcacheReadsReceived": 0, + "rfcachePoolReadsPending": 0, + "snapCapacityInUseOccupiedInKb": 0, + "activeFwdRebuildCapacityInKb": 0, + "rfcacheReadsSkippedStuckIo": 0, + "activeMovingOutNormRebuildJobs": 0, + "rfcacheFdWritesReceived": 0, + "rmcacheSizeInKb": 393216, + "rfcacheFdWriteTimeGreater1Min": 0, + "rfcacheWritePending": 0, + "rfcacheFdWriteTimeGreater1Sec": 0, + "numOfThinBaseVolumes": 5, + "numOfRfcacheDevices": 0, + "degradedFailedVacInKb": 0, + "rfcachePoolIoTimeGreater1Min": 0, + "rfcachePoolReadMiss": 0 +} +SYSTEM_STORAGE_POOL_INFO = [ + { + "protectionDomainId": "4389836100000000", + "sparePercentage": 0, + "rmcacheWriteHandlingMode": "Cached", + "checksumEnabled": False, + "useRfcache": False, + "rebuildEnabled": True, + "rebalanceEnabled": True, + "numOfParallelRebuildRebalanceJobsPerDevice": 2, + "capacityAlertHighThreshold": 80, + "capacityAlertCriticalThreshold": 90, + "rebalanceIoPriorityPolicy": "favorAppIos", + "rebuildIoPriorityNumOfConcurrentIosPerDevice": 1, + "rebuildIoPriorityPolicy": "limitNumOfConcurrentIos", + "rebalanceIoPriorityNumOfConcurrentIosPerDevice": 1, + "rebuildIoPriorityBwLimitPerDeviceInKbps": 10240, + "rebalanceIoPriorityBwLimitPerDeviceInKbps": 10240, + "rebuildIoPriorityAppIopsPerDeviceThreshold": None, + "rebalanceIoPriorityAppIopsPerDeviceThreshold": None, + "rebuildIoPriorityAppBwPerDeviceThresholdInKbps": None, + "rebalanceIoPriorityAppBwPerDeviceThresholdInKbps": None, + "rebuildIoPriorityQuietPeriodInMsec": None, + "rebalanceIoPriorityQuietPeriodInMsec": None, + "zeroPaddingEnabled": False, + "useRmcache": False, + "backgroundScannerMode": "Disabled", + "backgroundScannerBWLimitKBps": 0, + "name": "StoragePool", + "id": "b1566d0f00000000", + "links": [ + { + "rel": "/api/StoragePool/relationship/Statistics", + "href": "/api/instances/StoragePool::b1566d0f00000000/" + "relationships/Statistics" + } + ] + } +] + +SYSTEM_POOL_DETAIL = { + "pendingMovingOutBckRebuildJobs": 0, + "deviceIds": [ + "6afe148700000000", + "6afe3b9c00000001", + "6afe3b9d00000002", + "6afe148500010000", + "6afe3b9900010001", + "6afe3b9a00010002", + "6afe3b9b00010003", + "bbfe3b9600020000", + "bbfe3b9e00020001", + "bbfe3b9f00020002" + ], + "secondaryVacInKb": 2961178624, + "numOfDevices": 10, + "degradedHealthyCapacityInKb": 0, + "activeMovingOutFwdRebuildJobs": 0, + "bckRebuildWriteBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "failedCapacityInKb": 0, + "primaryReadFromDevBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "BackgroundScannedInMB": 0, + "volumeIds": [ + "851005a700000000", + "851005a800000001", + "851005a900000002", + "851005aa00000003", + "851005ab00000004", + "851005ac00000005", + "851005ad00000006", + "851005ae00000007", + "851005af00000008", + "851005b000000009", + "851005b10000000a", + "851005b20000000b", + "851005b30000000c", + "851005b40000000d", + "851005b50000000e", + "851005b60000000f", + "85102cb300000010", + "85102cb400000011", + "85102cb500000012" + ], + "activeMovingOutBckRebuildJobs": 0, + "rfcacheReadsFromCache": 0, + "pendingMovingInNormRebuildJobs": 0, + "rfcacheReadsSkippedAlignedSizeTooLarge": 0, + "primaryReadBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "failedVacInKb": 0, + "pendingMovingInRebalanceJobs": 0, + "pendingRebalanceCapacityInKb": 0, + "rfcacheWritesSkippedHeavyLoad": 0, + "unusedCapacityInKb": 14107527168, + "rfcacheAvgReadTime": 0, + "semiProtectedCapacityInKb": 0, + "totalReadBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "fwdRebuildReadBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "totalWriteBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "rfcacheWritesReceived": 0, + "rmPendingAllocatedInKb": 0, + "numOfVolumes": 19, + "rfcacheIosOutstanding": 0, + "protectedVacInKb": 5922357248, + "capacityAvailableForVolumeAllocationInKb": 7038042112, + "numOfMappedToAllVolumes": 0, + "bckRebuildCapacityInKb": 0, + "activeMovingInFwdRebuildJobs": 0, + "activeMovingRebalanceJobs": 0, + "pendingMovingRebalanceJobs": 0, + "degradedHealthyVacInKb": 0, + "semiProtectedVacInKb": 0, + "userDataReadBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "pendingBckRebuildCapacityInKb": 0, + "capacityLimitInKb": 17932736512, + "vtreeIds": [ + "d39b454d00000000", + "d39b454e00000001", + "d39b454f00000002", + "d39b455000000003", + "d39b455100000004", + "d39b455200000005", + "d39b455300000006", + "d39b455400000007", + "d39b455500000008", + "d39b455600000009", + "d39b45570000000a", + "d39b45580000000b", + "d39b45590000000c", + "d39b455a0000000d", + "d39b455b0000000e", + "d39b455c0000000f", + "d39b6c5700000010", + "d39b6c5800000011", + "d39b6c5900000012" + ], + "activeMovingInNormRebuildJobs": 0, + "activeMovingCapacityInKb": 0, + "rfcacheIosSkipped": 0, + "userDataWriteBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "inMaintenanceVacInKb": 0, + "rfcacheReadsSkipped": 0, + "numOfUnmappedVolumes": 17, + "rfcacheWritesSkippedMaxIoSize": 0, + "fixedReadErrorCount": 0, + "rfacheWriteHit": 0, + "atRestCapacityInKb": 3825209344, + "bckRebuildReadBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "pendingMovingInBckRebuildJobs": 0, + "rfcacheReadsSkippedInternalError": 0, + "activeBckRebuildCapacityInKb": 0, + "rfcacheSourceDeviceWrites": 0, + "spareCapacityInKb": 0, + "rebalanceCapacityInKb": 0, + "normRebuildWriteBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "rfcacheIoErrors": 0, + "capacityInUseInKb": 3825209344, + "rfcacheReadsSkippedLowResources": 0, + "rebalanceReadBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "thinCapacityInUseInKb": 4096, + "rfcacheReadsSkippedMaxIoSize": 0, + "secondaryReadFromDevBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "secondaryReadFromRmcacheBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "secondaryReadBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "rfcacheWritesSkippedStuckIo": 0, + "rfcacheWritesSkippedInternalError": 0, + "inMaintenanceCapacityInKb": 0, + "inUseVacInKb": 5922357248, + "fwdRebuildCapacityInKb": 0, + "rfcacheWritesSkippedCacheMiss": 0, + "thickCapacityInUseInKb": 3825205248, + "activeMovingInRebalanceJobs": 0, + "degradedFailedCapacityInKb": 0, + "BackgroundScanCompareCount": 0, + "activeNormRebuildCapacityInKb": 0, + "snapCapacityInUseInKb": 26210304, + "rfcacheWriteMiss": 0, + "rfcacheWritesSkippedLowResources": 0, + "primaryReadFromRmcacheBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "numOfVtrees": 19, + "rfacheReadHit": 0, + "rfcacheSkippedUnlinedWrite": 0, + "rfcacheAvgWriteTime": 0, + "pendingMovingCapacityInKb": 0, + "numOfSnapshots": 0, + "pendingNormRebuildCapacityInKb": 0, + "pendingFwdRebuildCapacityInKb": 0, + "pendingMovingOutNormrebuildJobs": 0, + "normRebuildCapacityInKb": 0, + "rfcacheSourceDeviceReads": 0, + "primaryWriteBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "numOfThickBaseVolumes": 14, + "rfcacheReadsPending": 0, + "rfcacheReadsSkippedHeavyLoad": 0, + "fwdRebuildWriteBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "rfcacheReadMiss": 0, + "activeRebalanceCapacityInKb": 0, + "activeMovingInBckRebuildJobs": 0, + "movingCapacityInKb": 0, + "rfcacheReadsSkippedLockIos": 0, + "unreachableUnusedCapacityInKb": 0, + "pendingMovingInFwdRebuildJobs": 0, + "rfcacheReadsReceived": 0, + "numOfVolumesInDeletion": 0, + "maxCapacityInKb": 17932736512, + "snapCapacityInUseOccupiedInKb": 0, + "pendingMovingOutFwdRebuildJobs": 0, + "activeFwdRebuildCapacityInKb": 0, + "rfcacheReadsSkippedStuckIo": 0, + "activeMovingOutNormRebuildJobs": 0, + "protectedCapacityInKb": 3825209343, + "secondaryWriteBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "rfcacheWritePending": 0, + "normRebuildReadBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "numOfThinBaseVolumes": 5, + "thinCapacityAllocatedInKb": 2097152000, + "degradedFailedVacInKb": 0, + "thinCapacityAllocatedInKm": 2097152000, + "rebalanceWriteBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "primaryVacInKb": 2961178624 +} + +SYSTEM_STORAGE_VOLUME_INFO = [ + { + "mappedSdcInfo": [ + { + "sdcId": "7bec302f00000000", + "sdcIp": "192.168.3.240", + "limitIops": 0, + "limitBwInMbps": 0 + }, + { + "sdcId": "7bec303100000002", + "sdcIp": "192.168.3.239", + "limitIops": 0, + "limitBwInMbps": 0 + }, + { + "sdcId": "7bec303000000001", + "sdcIp": "192.168.3.241", + "limitIops": 0, + "limitBwInMbps": 0 + } + ], + "mappingToAllSdcsEnabled": False, + "isVvol": False, + "sizeInKb": 209715200, + "vtreeId": "d39b455100000004", + "isObfuscated": False, + "volumeType": "ThinProvisioned", + "consistencyGroupId": None, + "ancestorVolumeId": None, + "useRmcache": False, + "storagePoolId": "b1566d0f00000000", + "creationTime": 1653359703, + "name": "volume023", + "id": "851005ab00000004", + "links": [ + { + "rel": "/api/Volume/relationship/Statistics", + "href": "/api/instances/Volume::851005ab00000004/" + "relationships/Statistics" + } + ] + } +] +SYSTEM_VOLUME_DETAIL = { + "descendantVolumeIds": [], + "numOfMappedScsiInitiators": 0, + "numOfChildVolumes": 0, + "numOfMappedSdcs": 3, + "userDataReadBwc": { + "numSeconds": 1, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "userDataWriteBwc": { + "numSeconds": 1, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "numOfDescendantVolumes": 0, + "childVolumeIds": [], + "mappedSdcIds": [ + "7bec302f00000000", + "7bec303100000002", + "7bec303000000001" + ] +} + +SYSTEM_STORAGE_DISK_INFO = [ + { + "sdsId": "29ab6a0a00000000", + "deviceState": "Normal", + "capacityLimitInKb": 942668800, + "maxCapacityInKb": 942668800, + "ledSetting": "Off", + "storagePoolId": "b1566d0f00000000", + "errorState": "None", + "name": "sd09", + "id": "6afe3b9d00000002" + } +] + +SYSTEM_DISK_DETAIL = { + "rfcacheReadsSkippedInternalError": 0, + "pendingMovingInBckRebuildJobs": 0, + "avgReadLatencyInMicrosec": 618, + "rfcacheSourceDeviceWrites": 0, + "pendingMovingOutBckRebuildJobs": 0, + "secondaryVacInKb": 150192128, + "normRebuildWriteBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "rfcacheIoErrors": 0, + "capacityInUseInKb": 222265344, + "rfcacheReadsSkippedLowResources": 0, + "rebalanceReadBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "thinCapacityInUseInKb": 0, + "activeMovingOutFwdRebuildJobs": 0, + "rfcacheReadsSkippedMaxIoSize": 0, + "secondaryReadFromDevBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "bckRebuildWriteBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "avgWriteLatencyInMicrosec": 0, + "secondaryReadFromRmcacheBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "secondaryReadBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "rfcacheWritesSkippedInternalError": 0, + "rfcacheWritesSkippedStuckIo": 0, + "primaryReadFromDevBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "BackgroundScannedInMB": 0, + "rfcacheReadsFromCache": 0, + "activeMovingOutBckRebuildJobs": 0, + "pendingMovingInNormRebuildJobs": 0, + "inUseVacInKb": 310329344, + "rfcacheWritesSkippedCacheMiss": 0, + "rfcacheReadsSkippedAlignedSizeTooLarge": 0, + "primaryReadBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "failedVacInKb": 0, + "pendingMovingInRebalanceJobs": 0, + "rfcacheWritesSkippedHeavyLoad": 0, + "thickCapacityInUseInKb": 222265344, + "unusedCapacityInKb": 719354880, + "rfcacheAvgReadTime": 0, + "activeMovingInRebalanceJobs": 0, + "BackgroundScanCompareCount": 0, + "totalReadBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "snapCapacityInUseInKb": 1048576, + "rfcacheWriteMiss": 0, + "rfcacheWritesSkippedLowResources": 0, + "primaryReadFromRmcacheBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "fwdRebuildReadBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "totalWriteBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "rfcacheWritesReceived": 0, + "rmPendingAllocatedInKb": 0, + "rfacheReadHit": 0, + "rfcacheIosOutstanding": 0, + "rfcacheSkippedUnlinedWrite": 0, + "protectedVacInKb": 310329344, + "activeMovingInFwdRebuildJobs": 0, + "activeMovingRebalanceJobs": 0, + "rfcacheAvgWriteTime": 0, + "pendingMovingRebalanceJobs": 0, + "pendingMovingOutNormrebuildJobs": 0, + "degradedHealthyVacInKb": 0, + "rfcacheSourceDeviceReads": 0, + "avgWriteSizeInBytes": 0, + "primaryWriteBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "rfcacheReadsPending": 0, + "rfcacheReadsSkippedHeavyLoad": 0, + "semiProtectedVacInKb": 0, + "fwdRebuildWriteBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "rfcacheReadMiss": 0, + "avgReadSizeInBytes": 1024, + "activeMovingInBckRebuildJobs": 0, + "capacityLimitInKb": 942668800, + "rfcacheReadsSkippedLockIos": 0, + "unreachableUnusedCapacityInKb": 0, + "pendingMovingInFwdRebuildJobs": 0, + "rfcacheReadsReceived": 0, + "activeMovingInNormRebuildJobs": 0, + "rfcacheIosSkipped": 0, + "inMaintenanceVacInKb": 0, + "rfcacheReadsSkipped": 0, + "snapCapacityInUseOccupiedInKb": 0, + "maxCapacityInKb": 942668800, + "pendingMovingOutFwdRebuildJobs": 0, + "rfcacheReadsSkippedStuckIo": 0, + "activeMovingOutNormRebuildJobs": 0, + "secondaryWriteBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "normRebuildReadBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "rfcacheWritePending": 0, + "rfcacheWritesSkippedMaxIoSize": 0, + "fixedReadErrorCount": 0, + "thinCapacityAllocatedInKb": 88064000, + "degradedFailedVacInKb": 0, + "thinCapacityAllocatedInKm": 88064000, + "rfacheWriteHit": 0, + "rebalanceWriteBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "bckRebuildReadBwc": { + "numSeconds": 0, + "totalWeightInKb": 0, + "numOccured": 0 + }, + "primaryVacInKb": 160137216 +} + +SYSTEM_HOST_INFO = [ + { + "sdcApproved": True, + "osType": "Linux", + "mdmConnectionState": "Connected", + "memoryAllocationFailure": None, + "socketAllocationFailure": None, + "softwareVersionInfo": "R2_5.0.0", + "sdcGuid": "ADEF3BC8-693F-4FCF-A423-6890508731C8", + "installedSoftwareVersionInfo": "R2_5.0.0", + "kernelVersion": "3.10.0", + "kernelBuildNumber": None, + "sdcIp": "192.168.3.240", + "sdcApprovedIps": None, + "versionInfo": "R2_5.0.0", + "perfProfile": "Default", + "systemId": "6fb451ea51a99758", + "name": None, + "id": "7bec302f00000000", + }, + { + "sdcApproved": True, + "osType": "Linux", + "mdmConnectionState": "Connected", + "memoryAllocationFailure": None, + "socketAllocationFailure": None, + "softwareVersionInfo": "R2_5.0.0", + "sdcGuid": "FBAD6944-6F2D-442C-9AA1-9FF0403B7235", + "installedSoftwareVersionInfo": "R2_5.0.0", + "kernelVersion": "3.10.0", + "kernelBuildNumber": None, + "sdcIp": "192.168.3.241", + "sdcApprovedIps": None, + "versionInfo": "R2_5.0.0", + "perfProfile": "Default", + "systemId": "6fb451ea51a99758", + "name": None, + "id": "7bec303000000001", + }, + { + "sdcApproved": True, + "osType": "Linux", + "mdmConnectionState": "Connected", + "memoryAllocationFailure": None, + "socketAllocationFailure": None, + "softwareVersionInfo": "R2_5.0.0", + "sdcGuid": "FFA0F6C3-E2CD-45F5-AF7E-0C1DDF570303", + "installedSoftwareVersionInfo": "R2_5.0.0", + "kernelVersion": "3.10.0", + "kernelBuildNumber": None, + "sdcIp": "192.168.3.239", + "sdcApprovedIps": None, + "versionInfo": "R2_5.0.0", + "perfProfile": "Default", + "systemId": "6fb451ea51a99758", + "name": None, + "id": "7bec303100000002", + } +] + +SYSTEM_INITIATORS_INFO = [ + { + "protectionDomainId": "4389836100000000", + "faultSetId": None, + "sdsState": "Normal", + "membershipState": "Joined", + "mdmConnectionState": "Connected", + "drlMode": "Volatile", + "rmcacheEnabled": True, + "rmcacheSizeInKb": 131072, + "rmcacheFrozen": False, + "rmcacheMemoryAllocationState": "AllocationPending", + "rfcacheEnabled": True, + "maintenanceState": "NoMaintenance", + "sdsDecoupled": None, + "sdsConfigurationFailure": None, + "sdsReceiveBufferAllocationFailures": None, + "rfcacheErrorLowResources": False, + "rfcacheErrorApiVersionMismatch": False, + "rfcacheErrorInconsistentCacheConfiguration": False, + "rfcacheErrorInconsistentSourceConfiguration": False, + "rfcacheErrorInvalidDriverPath": False, + "authenticationError": "None", + "softwareVersionInfo": "R2_5.0.0", + "rfcacheErrorDeviceDoesNotExist": False, + "numOfIoBuffers": None, + "perfProfile": "Default", + "ipList": [ + { + "ip": "192.168.3.241", + "role": "all" + } + ], + "onVmWare": True, + "name": "SDS_192.168.3.241", + "port": 7072, + "id": "29ab911800000002", + }, + { + "protectionDomainId": "4389836100000000", + "faultSetId": None, + "sdsState": "Normal", + "membershipState": "Joined", + "mdmConnectionState": "Connected", + "drlMode": "Volatile", + "rmcacheEnabled": True, + "rmcacheSizeInKb": 131072, + "rmcacheFrozen": False, + "rmcacheMemoryAllocationState": "AllocationPending", + "rfcacheEnabled": True, + "maintenanceState": "NoMaintenance", + "sdsDecoupled": None, + "sdsConfigurationFailure": None, + "sdsReceiveBufferAllocationFailures": None, + "rfcacheErrorLowResources": False, + "rfcacheErrorApiVersionMismatch": False, + "rfcacheErrorInconsistentCacheConfiguration": False, + "rfcacheErrorInconsistentSourceConfiguration": False, + "rfcacheErrorInvalidDriverPath": False, + "authenticationError": "None", + "softwareVersionInfo": "R2_5.0.0", + "rfcacheErrorDeviceDoesNotExist": False, + "numOfIoBuffers": None, + "perfProfile": "Default", + "ipList": [ + { + "ip": "192.168.3.239", + "role": "all" + } + ], + "onVmWare": True, + "name": "SDS_192.168.3.239", + "port": 7072, + "id": "29ab6a0a00000000", + }, + { + "protectionDomainId": "4389836100000000", + "faultSetId": None, + "sdsState": "Normal", + "membershipState": "Joined", + "mdmConnectionState": "Connected", + "drlMode": "Volatile", + "rmcacheEnabled": True, + "rmcacheSizeInKb": 131072, + "rmcacheFrozen": False, + "rmcacheMemoryAllocationState": "AllocationPending", + "rfcacheEnabled": True, + "maintenanceState": "NoMaintenance", + "sdsDecoupled": None, + "sdsConfigurationFailure": None, + "sdsReceiveBufferAllocationFailures": None, + "rfcacheErrorLowResources": False, + "rfcacheErrorApiVersionMismatch": False, + "rfcacheErrorInconsistentCacheConfiguration": False, + "rfcacheErrorInconsistentSourceConfiguration": False, + "rfcacheErrorInvalidDriverPath": False, + "authenticationError": "None", + "softwareVersionInfo": "R2_5.0.0", + "rfcacheErrorDeviceDoesNotExist": False, + "numOfIoBuffers": None, + "perfProfile": "Default", + "ipList": [ + { + "ip": "192.168.3.240", + "role": "all" + } + ], + "onVmWare": True, + "name": "SDS_192.168.3.240", + "port": 7072, + "id": "29ab6a0800000001", + } +] +SYSTEM_STORAGE = { + "name": "ScaleIO", + "vendor": "DELL EMC", + "model": "DellEMC ScaleIO", + "status": "normal", + "serial_number": "6fb451ea51a99758", + "firmware_version": "R2_5.0.254", + "raw_capacity": 965292851200, + "total_capacity": 18363122188288, + "used_capacity": 3917014368256, + "free_capacity": 14446107820032 +} + +SYSTEM_ALERT_INFO = [ + { + "alertType": "TRIAL_LICENSE_USED", + "severity": "ALERT_LOW", + "affectedObject": { + "type": "com.emc.ecs.api.model.gen.System", + "id": "6fb451ea51a99758", + "objectId": "6fb451ea51a99758" + }, + "alertValues": {}, + "lastObserved": "2022-05-27T03:10:52.552Z", + "uuid": "31d682d5-e696-466e-990a-57d0f9616b21", + "startTime": "2022-05-26T18:00:13.336Z", + "name": "31d682d5-e696-466e-990a-57d0f9616b21", + "id": "31d682d5-e696-466e-990a-57d0f9616b21", + } +] + +SYSTEM_TRAP_ALERT = 'system.sysUpTime.0=6132004 S:1.1.4.1.0=E:1139.101.1 ' \ + 'E:1139.101.1.1=5 ' \ + 'E:1139.101.1.2="MDM.MDM_Cluster.MDM_CONNECTION_LOST" ' \ + 'E:1139.101.1.3="hjfadsfa42524533" ' \ + 'E:1139.101.1.4="SIO02.01.0000008"' + +SYSTEM_STORAGE_POOL = [ + { + "name": "StoragePool", + "storage_id": "12345", + "native_storage_pool_id": "b1566d0f00000000", + "status": "normal", + "storage_type": "block", + "total_capacity": 18363122188288, + "used_capacity": 3917014368256, + "free_capacity": 14446107820032 + } +] + +SYSTEM_STORAGE_VOLUME = [ + { + "name": "volume023", + "storage_id": "12345", + "description": "volume023", + "status": "normal", + "native_volume_id": "851005ab00000004", + "native_storage_pool_id": "b1566d0f00000000", + "wwn": "851005ab00000004", + "type": "thin", + "total_capacity": 214748364800, + "free_capacit": 0, + "used_capacity": 0, + "compressed": True, + "deduplicated": True + } +] + +SYSTEM_STORAGE_DISK = [ + { + 'native_disk_id': '6afe3b9d00000002', + 'name': 'sd09', + 'status': 'normal', + 'storage_id': '12345', + 'native_disk_group_id': '29ab6a0a00000000', + 'serial_number': '6afe3b9d00000002', + 'capacity': 965292851200, + 'health_score': 'normal' + } +] + + +SYSTEM_ALERT = [ + { + 'alert_id': '31d682d5-e696-466e-990a-57d0f9616b21', + 'alert_name': 'TRIAL_LICENSE_USED31d682d5-e696-466e-990a-57d0f9616b21', + 'severity': 'Minor', + 'category': 'Fault', + 'type': 'TRIAL_LICENSE_USED', + 'sequence_number': '31d682d5-e696-466e-990a-57d0f9616b21', + 'description': 'trial license used', + 'occur_time': 1653588013336, + 'match_key': '10648e5e11b1d6daf4f5cf989349967d' + } +] + +SYSTEM_HOST = [ + { + "name": "ADEF3BC8-693F-4FCF-A423-6890508731C8", + "description": "192.168.3.240R2_5.0.0", + "storage_id": "12345", + "native_storage_host_id": "7bec302f00000000", + "os_type": "Linux", + "status": "normal", + "ip_address": "192.168.3.240" + }, { + "name": "FBAD6944-6F2D-442C-9AA1-9FF0403B7235", + "description": "192.168.3.241R2_5.0.0", + "storage_id": "12345", + "native_storage_host_id": "7bec303000000001", + "os_type": "Linux", + "status": "normal", + "ip_address": "192.168.3.241" + }, { + "name": "FFA0F6C3-E2CD-45F5-AF7E-0C1DDF570303", + "description": "192.168.3.239R2_5.0.0", + "storage_id": "12345", + "native_storage_host_id": "7bec303100000002", + "os_type": "Linux", + "status": "normal", + "ip_address": "192.168.3.239" + } +] + +SYSTEM_VIEW_MAPPING = [ + {'name': 'volume0237bec302f00000000851005ab00000004', + 'description': 'volume023', + 'storage_id': '12345', + 'native_masking_view_id': 'volume0237bec302f00000000851005ab00000004', + 'native_volume_id': '851005ab00000004', + 'native_storage_host_id': '7bec302f00000000' + }, { + 'name': 'volume0237bec303100000002851005ab00000004', + 'description': 'volume023', + 'storage_id': '12345', + 'native_masking_view_id': 'volume0237bec303100000002851005ab00000004', + 'native_volume_id': '851005ab00000004', + 'native_storage_host_id': '7bec303100000002' + }, { + 'name': 'volume0237bec303000000001851005ab00000004', + 'description': 'volume023', + 'storage_id': '12345', + 'native_masking_view_id': 'volume0237bec303000000001851005ab00000004', + 'native_volume_id': '851005ab00000004', + 'native_storage_host_id': '7bec303000000001' + } +] + + +SYSTEM_INITIATORS = [ + {"name": "SDS_192.168.3.241", + "storage_id": "12345", + "native_storage_host_initiator_id": "29ab911800000002", + "wwn": "29ab911800000002", + "type": "unknown", + "status": "online", + "native_storage_host_id": "7bec303000000001" + }, { + "name": "SDS_192.168.3.239", + "storage_id": "12345", + "native_storage_host_initiator_id": "29ab6a0a00000000", + "wwn": "29ab6a0a00000000", + "type": "unknown", + "status": "online", + "native_storage_host_id": "7bec303100000002" + }, { + "name": "SDS_192.168.3.240", + "storage_id": "12345", + "native_storage_host_initiator_id": "29ab6a0800000001", + "wwn": "29ab6a0800000001", + "type": "unknown", + "status": "online", + "native_storage_host_id": "7bec302f00000000" + } +] + +SYSTEM_TRAP = { + 'category': 'Fault', + 'type': 'EquipmentAlarm', + 'occur_time': 1655171867749, + 'severity': 'Critical', + 'description': 'mdm connection lost"', + 'location': 'mdm connection lost"', + 'alert_id': 'hjfadsfa42524533', + 'alert_name': 'SIO02.01.0000008' +} diff --git a/delfin/tests/unit/drivers/dell_emc/scaleio/test_scaleio_stor.py b/delfin/tests/unit/drivers/dell_emc/scaleio/test_scaleio_stor.py new file mode 100644 index 000000000..f6e1c1a19 --- /dev/null +++ b/delfin/tests/unit/drivers/dell_emc/scaleio/test_scaleio_stor.py @@ -0,0 +1,107 @@ +# Copyright 2021 The SODA Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import sys + +from delfin import context +from unittest import TestCase, mock + + +from delfin.drivers.dell_emc.scaleio.scaleio_stor import ScaleioStorageDriver +from delfin.drivers.dell_emc.scaleio.rest_handler import RestHandler +from delfin.tests.unit.drivers.dell_emc.scaleio import test_constans + + +sys.modules['delfin.cryptor'] = mock.Mock() + +ACCESS_INFO = { + "storage_id": "12345", + "vendor": "dell_emc", + "model": "scaleio", + "rest": { + "host": "8.44.162.250", + "port": 443, + "username": "admin", + "password": "Pbu4@123" + } +} + + +class TestScaleIOStorDriver(TestCase): + RestHandler.login = mock.Mock(return_value=None) + + def test_get_storage(self): + RestHandler.get_rest_info = mock.Mock(side_effect=[ + test_constans.SYSTEM_INFO, test_constans.SYSTEM_DETAIL]) + RestHandler.list_disks = mock.Mock(side_effect=[test_constans. + SYSTEM_STORAGE_DISK]) + system_storage = ScaleioStorageDriver(**ACCESS_INFO).\ + get_storage(context) + self.assertEqual(system_storage, test_constans.SYSTEM_STORAGE) + + def test_list_storage_pool(self): + RestHandler.get_rest_info = mock.Mock(side_effect=[ + test_constans.SYSTEM_STORAGE_POOL_INFO, + test_constans.SYSTEM_POOL_DETAIL]) + storage_pool = ScaleioStorageDriver(**ACCESS_INFO)\ + .list_storage_pools(context) + self.assertEqual(storage_pool, test_constans.SYSTEM_STORAGE_POOL) + + def test_list_volume(self): + RestHandler.get_rest_info = mock.Mock(side_effect=[ + test_constans.SYSTEM_STORAGE_VOLUME_INFO, + test_constans.SYSTEM_VOLUME_DETAIL]) + storage_volumes = ScaleioStorageDriver(**ACCESS_INFO)\ + .list_volumes(context) + self.assertEqual(storage_volumes, test_constans.SYSTEM_STORAGE_VOLUME) + + def test_list_alert(self): + RestHandler.get_rest_info = mock.Mock( + side_effect=[test_constans.SYSTEM_ALERT_INFO]) + storage_alert = ScaleioStorageDriver(**ACCESS_INFO).\ + list_alerts(context) + alert_result = test_constans.SYSTEM_ALERT + alert_result[0]['occur_time'] = storage_alert[0]['occur_time'] + self.assertEqual(storage_alert, alert_result) + + def test_list_storage_host_initiators(self): + RestHandler.get_rest_info = mock.Mock( + side_effect=[test_constans.SYSTEM_INITIATORS_INFO]) + RestHandler.list_storage_hosts = mock.Mock( + side_effect=[test_constans.SYSTEM_HOST]) + storage_initiators = ScaleioStorageDriver(**ACCESS_INFO). \ + list_storage_host_initiators(context) + self.assertEqual(storage_initiators, test_constans.SYSTEM_INITIATORS) + + def test_list_masking_views(self): + RestHandler.get_rest_info = mock.Mock( + side_effect=[test_constans.SYSTEM_STORAGE_VOLUME_INFO]) + storage_mapping = ScaleioStorageDriver(**ACCESS_INFO). \ + list_masking_views(context) + self.assertEqual(storage_mapping, test_constans.SYSTEM_VIEW_MAPPING) + + def test_list_hosts(self): + RestHandler.get_rest_info = mock.Mock( + side_effect=[test_constans.SYSTEM_HOST_INFO]) + storage_host = ScaleioStorageDriver(**ACCESS_INFO)\ + .list_storage_hosts(context) + self.assertEqual(storage_host, test_constans.SYSTEM_HOST) + + def test_parse_alert(self): + trap_alert = test_constans.SYSTEM_TRAP_ALERT + storage_trap_alert = ScaleioStorageDriver(**ACCESS_INFO).\ + parse_alert(context, trap_alert) + trap_alert_result = test_constans.SYSTEM_TRAP + trap_alert_result['occur_time'] = storage_trap_alert['occur_time'] + self.assertEqual(storage_trap_alert, trap_alert_result)