diff --git a/delfin/drivers/hpe/hpe_msa/__init__.py b/delfin/drivers/hpe/hpe_msa/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/delfin/drivers/hpe/hpe_msa/hpe_msastor.py b/delfin/drivers/hpe/hpe_msa/hpe_msastor.py new file mode 100644 index 000000000..345c3b306 --- /dev/null +++ b/delfin/drivers/hpe/hpe_msa/hpe_msastor.py @@ -0,0 +1,43 @@ +from delfin.drivers import driver +from delfin.drivers.hpe.hpe_msa import ssh_handler + + +class HpeMsaStorDriver(driver.StorageDriver): + + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.ssh_hanlder = ssh_handler.SSHHandler(**kwargs) + + def reset_connection(self, context, **kwargs): + self.ssh_hanlder.login() + + def get_storage(self, context): + return self.ssh_hanlder.get_storage(self.storage_id) + + def list_storage_pools(self, context): + return self.ssh_hanlder.list_storage_pools(self.storage_id) + + def list_volumes(self, context): + return self.ssh_hanlder.list_storage_volume(self.storage_id) + + def list_controllers(self, context): + return self.ssh_hanlder.\ + list_storage_controller(self.storage_id) + + def list_ports(self, context): + return self.ssh_hanlder.list_storage_ports(self.storage_id) + + def list_disks(self, context): + return self.ssh_hanlder.list_storage_disks(self.storage_id) + + def list_alerts(self, context, query_para=None): + return self.ssh_hanlder.list_storage_error(query_para) + + def add_trap_config(self, context, trap_config): + pass + + def remove_trap_config(self, context, trap_config): + pass + + def clear_alert(self): + pass diff --git a/delfin/drivers/hpe/hpe_msa/ssh_handler.py b/delfin/drivers/hpe/hpe_msa/ssh_handler.py new file mode 100644 index 000000000..845bcd4d4 --- /dev/null +++ b/delfin/drivers/hpe/hpe_msa/ssh_handler.py @@ -0,0 +1,370 @@ +import six + +from oslo_log import log as logging +from delfin import exception +from delfin.common import constants, alert_util +from delfin.drivers.utils.ssh_client import SSHPool +from delfin.drivers.utils.tools import Tools + +try: + import xml.etree.cElementTree as ET +except ImportError: + import xml.etree.cElementTree as ET + +LOG = logging.getLogger(__name__) + + +class SSHHandler(): + + SECONDS_TO_MS = 1000 + + DISK_PHYSICAL_TYPE = { + 'fc': constants.DiskPhysicalType.FC, + 'SAS': constants.DiskPhysicalType.SAS + } + + def __init__(self, **kwargs): + self.ssh_pool = SSHPool(**kwargs) + + def login(self): + try: + result = self.ssh_pool.do_exec('show pools') + if 'is not a recognized command' in result: + raise exception.InvalidIpOrPort() + except Exception as e: + LOG.error("Failed to login msa storwize_svc %s" % + (six.text_type(e))) + raise e + + def get_storage(self, storage_id): + try: + result = self.ssh_pool.do_exec('show system') + list = self.analysisDataToList(result, 'system') + version_result = self.ssh_pool.do_exec('show version') + version_list = self.analysisDataToList(version_result, + 'versions') + if list: + pool_list = self.list_storage_pools(storage_id) + total_capacity = 0 + for pool in pool_list: + total_capacity += int(pool['total_capacity']) + disk_list = self.list_storage_disks(storage_id) + disk_all = 0 + for disk in disk_list: + disk_all += int(disk['capacity']) + volume_list = self.list_storage_volume(storage_id) + volume_all = 0 + for volume in volume_list: + volume_all += int(volume['total_capacity']) + health = list[0]['health'] + status = constants.StoragePoolStatus.OFFLINE + if health == 'OK': + status = constants.StoragePoolStatus.NORMAL + dataMap = { + 'name': list[0]['system-name'], + 'vendor': list[0]['vendor-name'], + 'model': list[0]['product-id'], + 'status': status, + 'serial_number': list[0]['midplane-serial-number'], + 'firmware_version': version_list[0]['bundle-version'], + 'location': list[0]['system-location'], + 'raw_capacity': int(disk_all), + 'total_capacity': int(total_capacity), + 'used_capacity': int(volume_all), + 'free_capacity': int(total_capacity - volume_all) + } + return dataMap + except Exception as e: + err_msg = "Failed to get storage : %s" % (six.text_type(e)) + LOG.error(err_msg) + raise e + + def list_storage_disks(self, storage_id): + try: + result = self.ssh_pool.do_exec('show disks') + list = self.analysisDataToList(result, 'drives') + list_disks = [] + if list: + for data in list: + health = data['health'] + status = constants.StoragePoolStatus.OFFLINE + if health == 'OK': + status = constants.StoragePoolStatus.NORMAL + size = self.parse_string(data['size']) + physical_type = SSHHandler.DISK_PHYSICAL_TYPE.\ + get(data.get('description'), + constants.DiskPhysicalType.UNKNOWN) + data_map = { + 'native_disk_id': data['location'], + 'name': data['location'], + 'physical_type': physical_type, + 'status': status, + 'storage_id': storage_id, + 'native_disk_group_id': data['disk-group'], + 'serial_number': data['serial-number'], + 'manufacturer': data['vendor'], + 'model': data['model'], + 'speed': data['rpm'], + 'capacity': int(size), + 'health_score': status + } + list_disks.append(data_map) + return list_disks + except Exception as e: + err_msg = "Failed to get storage disk: %s" % (six.text_type(e)) + LOG.error(err_msg) + raise e + + def list_storage_ports(self, storage_id): + try: + result = self.ssh_pool.do_exec('show ports') + result_info = result.split('\n') + result_list = result_info[1:len(result_info) - 1] + result_xml = ''.join(result_list) + root_elem = ET.fromstring(result_xml) + list_port_detail = [] + for ch in root_elem.iter("OBJECT"): + propertyName = ch.get('basetype') + if propertyName != 'status': + msg = {} + for child in ch.iter("PROPERTY"): + msg[child.get('name')] = child.text + list_port_detail.append(msg) + list_all_ports = [] + for i in range(0, len(list_port_detail) - 1, 2): + aa = list_port_detail[i].copy() + aa.update(list_port_detail[i + 1]) + list_all_ports.append(aa) + list_ports = [] + if list_all_ports: + for data in list_all_ports: + status = constants.PortHealthStatus.NORMAL + conn_status = constants.PortConnectionStatus.CONNECTED + if data.get('health') != 'OK': + status = constants.PortHealthStatus.ABNORMAL + conn_status = constants.PortConnectionStatus.\ + DISCONNECTED + location = '%s_%s' % (data.get('port'), + data.get('durable-id')) + port_type = constants.PortType.FC + if data.get('port-type') == 'iSCSI': + port_type = constants.PortType.ETH + speed = data.get('configured-speed', None) + max_speed = 0 + if speed != 'Auto' and speed is not None: + max_speed = self.parse_string(speed) + speed = data.get('configured-speed') + dataMap = { + 'native_port_id': data.get('durable-id', ''), + 'name': data.get('port', ''), + 'type': port_type, + 'connection_status': conn_status, + 'health_status': status, + 'location': location, + 'storage_id': storage_id, + 'speed': max_speed, + 'max_speed': max_speed, + 'wwn': '', + 'mac_address': data.get('mac-address', ''), + 'ipv4': data.get('ip-address', '') + } + list_ports.append(dataMap) + return list_ports + except Exception as e: + err_msg = "Failed to get storage ports: %s" % (six.text_type(e)) + LOG.error(err_msg) + raise e + + def list_storage_controller(self, storage_id): + try: + result = self.ssh_pool.do_exec('show controllers') + list = self.analysisDataToList(result, 'controllers') + list_controllers = [] + if list: + for data in list: + health = data.get('health', '') + status = constants.StoragePoolStatus.OFFLINE + if health == 'OK': + status = constants.StoragePoolStatus.NORMAL + cpu_info = str(data['sc-cpu-type']) + memory_size = data['system-memory-size'] + "MB" + system_memory_size = self.parse_string( + memory_size) + data_map = { + 'native_controller_id': data['controller-id'], + 'name': data['durable-id'], + 'storage_id': storage_id, + 'status': status, + 'location': data['position'], + 'soft_version': data['sc-fw'], + 'cpu_info': cpu_info, + 'memory_size': int(system_memory_size) + } + list_controllers.append(data_map) + return list_controllers + except Exception as e: + err_msg = "Failed to get storage controllers: %s"\ + % (six.text_type(e)) + LOG.error(err_msg) + raise e + + def list_storage_volume(self, storage_id): + try: + result = self.ssh_pool.do_exec('show volumes') + list = self.analysisDataToList(result, 'volumes') + result_pools = self.ssh_pool.do_exec('show pools') + list_pools = self.analysisDataToList(result_pools, 'pools') + list_volumes = [] + if list: + for data in list: + health = data.get('health', '') + status = constants.StoragePoolStatus.OFFLINE + if health == 'OK': + status = constants.StoragePoolStatus.NORMAL + total_size = self.parse_string(data['total-size']) + total_avail = self.parse_string(data['allocated-size']) + native_storage_pool_id = list_pools[0].\ + get("serial-number") + for pools in list_pools: + if data.get("virtual-disk-name") == pools.\ + get("name"): + native_storage_pool_id = pools.\ + get("serial-number") + dataMap = { + 'name': data['volume-name'], + 'storage_id': storage_id, + 'description': data['volume-name'], + 'status': status, + 'native_volume_id': str(data['durable-id']), + 'native_storage_pool_id': native_storage_pool_id, + 'wwn': str(data['wwn']), + 'type': data['volume-type'], + 'total_capacity': int(total_size), + 'free_capacit': int(total_avail), + 'used_capacity': int(total_size - total_avail), + 'blocks': int(data.get("blocks")), + 'compressed': True, + 'deduplicated': True + } + list_volumes.append(dataMap) + return list_volumes + except Exception as e: + err_msg = "Failed to get storage volume: %s" % (six.text_type(e)) + LOG.error(err_msg) + raise e + + def list_storage_pools(self, storage_id): + try: + result = self.ssh_pool.do_exec('show pools') + list = self.analysisDataToList(result, 'pools') + volume_list = self.list_storage_volume(storage_id) + pools_list = [] + if list: + for data in list: + volume_size = 0 + blocks = 0 + for volume in volume_list: + if volume.get("native_storage_pool_id") == data.\ + get("serial-number"): + volume_size += volume.get("total_capacity") + blocks += volume.get("blocks") + health = data.get('health', '') + status = constants.StoragePoolStatus.OFFLINE + if health == 'OK': + status = constants.StoragePoolStatus.NORMAL + total_size = self.parse_string(data['total-size']) + dataMap = { + 'name': data['name'], + 'storage_id': storage_id, + 'native_storage_pool_id': data['serial-number'], + 'description': '', + 'status': status, + 'storage_type': constants.StorageType.BLOCK, + 'total_capacity': int(total_size), + 'subscribed_capacity': int(blocks), + 'used_capacity': volume_size, + 'free_capacity': int(total_size - volume_size) + } + pools_list.append(dataMap) + return pools_list + except Exception as e: + err_msg = "Failed to get storage pool: %s" % (six.text_type(e)) + LOG.error(err_msg) + raise e + + def parse_string(self, value): + capacity = 0 + if value: + if value.isdigit(): + capacity = float(value) + else: + if value == '0B': + capacity = 0 + else: + unit = value[-2:] + capacity = float(value[:-2]) * int( + Tools.change_capacity_to_bytes(unit)) + return capacity + + def analysisDataToList(self, result, dataName): + list_xml = [] + result_info = result.split('\n') + result_list = result_info[1:len(result_info) - 1] + result_xml = ''.join(result_list) + root_elem = ET.fromstring(result_xml) + for ch in root_elem.iter("OBJECT"): + propertyName = ch.get('basetype') + if dataName == propertyName: + msg = {} + for child in ch.iter("PROPERTY"): + msg[child.get('name')] = child.text + list_xml.append(msg) + return list_xml + + def list_storage_error(self, query_para): + alert_list = [] + try: + result = self.ssh_pool.do_exec('show events error') + list = self.analysisDataToList(result, 'events') + if list: + for alert_map in list: + time_stamp = alert_map.get('time-stamp-numeric') + occur_time = int(time_stamp) * self.SECONDS_TO_MS + if not alert_util.is_alert_in_time_range(query_para, + occur_time): + continue + alert_name = alert_map.get('message', '') + event_id = alert_map.get('event-id') + location = alert_map.get('serial-number', '') + resource_type = alert_map.get('event-code', '') + severity = alert_map.get('severity') + if severity == 'Informational' or severity is None: + continue + alert_model = { + 'alert_id': event_id, + 'alert_name': alert_name, + 'severity': severity, + 'category': constants.Category.FAULT, + 'type': 'EquipmentAlarm', + 'sequence_number': alert_map.get('event-code'), + 'occur_time': occur_time, + 'description': alert_name, + 'resource_type': resource_type, + 'location': location + } + alert_list.append(alert_model) + return self.distinct2(alert_list) + except Exception as e: + err_msg = "Failed to get storage error: %s" % (six.text_type(e)) + LOG.error(err_msg) + raise e + + def distinct2(self, result_list): + exist_questions = set() + result = [] + for item in result_list: + question = item['resource_type'] + if question not in exist_questions: + exist_questions.add(question) + result.append(item) + return result diff --git a/delfin/tests/unit/drivers/hpe/hpe_msa/__init__.py b/delfin/tests/unit/drivers/hpe/hpe_msa/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/delfin/tests/unit/drivers/hpe/hpe_msa/test_constans.py b/delfin/tests/unit/drivers/hpe/hpe_msa/test_constans.py new file mode 100644 index 000000000..b8843d8fd --- /dev/null +++ b/delfin/tests/unit/drivers/hpe/hpe_msa/test_constans.py @@ -0,0 +1,543 @@ +LIST_CONTROLLERS = """ + + + + + controller_a + A + 7CE539M591 + 4096 + 6144 + GLS210R04-01 + Gladden + OK + Top + + + + controller_b + B + 7CE539M591 + 4096 + 6144 + GLS210R04-01 + Gladden + OK + Bottom + + +""" + +LIST_SYSTEM = """ + + + + + msa2040 + 00C0FF26DCB0 + Uninitialized Location + HP + MSA 2040 SAN + MSA Storage + OK + + +""" + +LIST_VISION = """ + + + + + GL210R004 + + +""" + +LIST_PORTS = """ + + + + + hostport_A1 + A1 + 8Gb + FC + N/A + + + + 4G,8G + + + + hostport_A2 + A2 + FC + 8Gb + N/A + + + + 4G,8G + + + + hostport_A3 + A3 + iSCSI + N/A + + + + 0.0.0.0 + 00:C0:FF:35:BD:64 + + + + hostport_A4 + A4 + iSCSI + Auto + N/A + + + + 0.0.0.0 + 00:C0:FF:35:BD:65 + + + + hostport_B1 + B1 + FC + 8Gb + N/A + + + + 4G,8G + + + + hostport_B2 + B2 + FC + 8Gb + N/A + + + + 4G,8G + + + + hostport_B3 + B3 + iSCSI + Auto + N/A + + + + 0.0.0.0 + 00:C0:FF:35:BA:BC + + + + hostport_B4 + B4 + iSCSI + Auto + N/A + + + + 0.0.0.0 + 00:C0:FF:35:BA:BD + + +""" + +LIST_POOLS = """ + + + + + A + 00c0ff26c4ea0000d980546101000000 + 1196.8GB + 1196.8GB + OK + + +""" + +LIST_VOLUMES = """ + + + + + V1 + Vol0001 + 99.9GB + 0B + 99.9GB + 195305472 + OK + 600C0FF00026C4EAFA80546101000000 + base + + + + V2 + Vol0002 + 0B + 99.9GB + 195305472 + OK + 600C0FF00026C4EA0A81546101000000 + base + + +""" + +LIST_DISKS = """ + + + + + disk_01.01 + 1.1 + 0 + 6SL9CD560000N51404EF + SEAGATE + ST3600057SS + SAS + SAS + 15 + 600.1GB + OK + dgA01 + + + + disk_01.02 + 1.2 + 6SL7X4RE0000B42601SF + SEAGATE + ST3600057SS + SAS + SAS + 15 + 600.1GB + OK + dgA01 + + + + disk_01.03 + 1.3 + 6SL9QR5T0000N52120SK + SEAGATE + SAS + ST3600057SS + 15 + 600.1GB + OK + dgA01 + + + + disk_01.04 + 0 + 1.4 + SAS + 3SL0WT7G00009051YBTF + SEAGATE + ST3600057SS + 15 + 600.1GB + OK + dgA01 + + +""" +LIST_ERROR = """ + + + + + 1630305906 + 557 + A35 + 00C0FF26C236 + ERROR + ERROE_INFOMATION + + +""" + +error_result = [ + { + 'alert_id': 'A35', + 'alert_name': 'ERROE_INFOMATION', + 'severity': 'ERROR', + 'category': 'Fault', + 'type': 'EquipmentAlarm', + 'sequence_number': '557', + 'occur_time': 1630305906000, + 'description': 'ERROE_INFOMATION', + 'resource_type': '557', + 'location': '00C0FF26C236' + } +] + + +volume_result = [ + { + 'name': 'Vol0001', + 'storage_id': 'kkk', + 'description': 'Vol0001', + 'status': 'normal', + 'native_volume_id': 'V1', + 'native_storage_pool_id': '00c0ff26c4ea0000d980546101000000', + 'wwn': '600C0FF00026C4EAFA80546101000000', + 'type': 'base', + 'total_capacity': 107266808217, + 'free_capacit': 0, + 'used_capacity': 107266808217, + 'blocks': 195305472, + 'compressed': True, + 'deduplicated': True + }, { + 'name': 'Vol0002', + 'storage_id': 'kkk', + 'description': 'Vol0002', + 'status': 'normal', + 'native_volume_id': 'V2', + 'native_storage_pool_id': '00c0ff26c4ea0000d980546101000000', + 'wwn': '600C0FF00026C4EA0A81546101000000', + 'type': 'base', + 'total_capacity': 107266808217, + 'free_capacit': 0, + 'used_capacity': 107266808217, + 'blocks': 195305472, + 'compressed': True, + 'deduplicated': True + } +] + +pools_result = [ + { + 'name': 'A', + 'storage_id': 'kkk', + 'native_storage_pool_id': '00c0ff26c4ea0000d980546101000000', + 'description': '', + 'status': 'normal', + 'storage_type': 'block', + 'total_capacity': 1285054214963, + 'subscribed_capacity': 390610944, + 'used_capacity': 214533616434, + 'free_capacity': 1070520598529 + } +] + +ports_result = [ + {'native_port_id': 'hostport_A1', + 'name': 'A1', + 'type': 'fc', + 'connection_status': 'disconnected', + 'health_status': 'abnormal', + 'location': 'A1_hostport_A1', + 'storage_id': 'kkk', + 'speed': 8589934592.0, + 'max_speed': 8589934592.0, + 'wwn': '', + 'mac_address': '', + 'ipv4': '' + }, { + 'native_port_id': 'hostport_A2', + 'name': 'A2', + 'type': 'fc', + 'connection_status': 'disconnected', + 'health_status': 'abnormal', + 'location': 'A2_hostport_A2', + 'storage_id': 'kkk', + 'speed': 8589934592.0, + 'max_speed': 8589934592.0, + 'wwn': '', + 'mac_address': '', + 'ipv4': '' + }, { + 'native_port_id': 'hostport_A3', + 'name': 'A3', + 'type': 'eth', + 'connection_status': 'disconnected', + 'health_status': 'abnormal', + 'location': 'A3_hostport_A3', + 'storage_id': 'kkk', + 'speed': 0, + 'max_speed': 0, + 'wwn': '', + 'mac_address': '00:C0:FF:35:BD:64', + 'ipv4': '0.0.0.0' + }, { + 'native_port_id': 'hostport_A4', + 'name': 'A4', + 'type': 'eth', + 'connection_status': 'disconnected', + 'health_status': 'abnormal', + 'location': 'A4_hostport_A4', + 'storage_id': 'kkk', + 'speed': 0, + 'max_speed': 0, + 'wwn': '', + 'mac_address': '00:C0:FF:35:BD:65', + 'ipv4': '0.0.0.0' + }, { + 'native_port_id': 'hostport_B1', + 'name': 'B1', + 'type': 'fc', + 'connection_status': 'disconnected', + 'health_status': 'abnormal', + 'location': 'B1_hostport_B1', + 'storage_id': 'kkk', + 'speed': 8589934592.0, + 'max_speed': 8589934592.0, + 'wwn': '', + 'mac_address': '', + 'ipv4': '' + }, { + 'native_port_id': 'hostport_B2', + 'name': 'B2', + 'type': 'fc', + 'connection_status': 'disconnected', + 'health_status': 'abnormal', + 'location': 'B2_hostport_B2', + 'storage_id': 'kkk', + 'speed': 8589934592.0, + 'max_speed': 8589934592.0, + 'wwn': '', + 'mac_address': '', + 'ipv4': '' + }, { + 'native_port_id': 'hostport_B3', + 'name': 'B3', + 'type': 'eth', + 'connection_status': 'disconnected', + 'health_status': 'abnormal', + 'location': 'B3_hostport_B3', + 'storage_id': 'kkk', + 'speed': 0, + 'max_speed': 0, + 'wwn': '', + 'mac_address': '00:C0:FF:35:BA:BC', + 'ipv4': '0.0.0.0' + }, { + 'native_port_id': 'hostport_B4', + 'name': 'B4', + 'type': 'eth', + 'connection_status': 'disconnected', + 'health_status': 'abnormal', + 'location': 'B4_hostport_B4', + 'storage_id': 'kkk', + 'speed': 0, + 'max_speed': 0, + 'wwn': '', + 'mac_address': '00:C0:FF:35:BA:BD', + 'ipv4': '0.0.0.0' + } +] + +disks_result = [ + { + 'native_disk_id': '1.1', + 'name': '1.1', + 'physical_type': 'sas', + 'status': 'normal', + 'storage_id': 'kkk', + 'native_disk_group_id': 'dgA01', + 'serial_number': '6SL9CD560000N51404EF', + 'manufacturer': 'SEAGATE', + 'model': 'ST3600057SS', + 'speed': '15', + 'capacity': 644352468582, + 'health_score': 'normal' + }, { + 'native_disk_id': '1.2', + 'name': '1.2', + 'physical_type': 'sas', + 'status': 'normal', + 'storage_id': 'kkk', + 'native_disk_group_id': 'dgA01', + 'serial_number': '6SL7X4RE0000B42601SF', + 'manufacturer': 'SEAGATE', + 'model': 'ST3600057SS', + 'speed': '15', + 'capacity': 644352468582, + 'health_score': 'normal' + }, { + 'native_disk_id': '1.3', + 'name': '1.3', + 'physical_type': 'sas', + 'status': 'normal', + 'storage_id': 'kkk', + 'native_disk_group_id': 'dgA01', + 'serial_number': '6SL9QR5T0000N52120SK', + 'manufacturer': 'SEAGATE', + 'model': 'ST3600057SS', + 'speed': '15', 'capacity': 644352468582, + 'health_score': 'normal' + }, { + 'native_disk_id': '1.4', + 'name': '1.4', + 'physical_type': 'sas', + 'status': 'normal', + 'storage_id': 'kkk', + 'native_disk_group_id': 'dgA01', + 'serial_number': '3SL0WT7G00009051YBTF', + 'manufacturer': 'SEAGATE', + 'model': 'ST3600057SS', + 'speed': '15', + 'capacity': 644352468582, + 'health_score': 'normal' + } +] + +system_info = { + 'name': 'msa2040', + 'vendor': 'HP', + 'model': 'MSA 2040 SAN', + 'status': 'normal', + 'serial_number': '00C0FF26DCB0', + 'firmware_version': 'GL210R004', + 'location': 'Uninitialized Location', + 'raw_capacity': 2577409874328, + 'total_capacity': 1285054214963, + 'used_capacity': 214533616434, + 'free_capacity': 1070520598529 +} + +controller_result = [ + { + 'native_controller_id': 'A', + 'name': 'controller_a', + 'storage_id': 'kkk', + 'status': 'normal', + 'location': 'Top', + 'soft_version': 'GLS210R04-01', + 'cpu_info': 'Gladden', + 'memory_size': 6442450944 + }, + { + 'native_controller_id': 'B', + 'name': 'controller_b', + 'storage_id': 'kkk', + 'status': 'normal', + 'location': 'Bottom', + 'soft_version': 'GLS210R04-01', + 'cpu_info': 'Gladden', + 'memory_size': 6442450944 + } +] diff --git a/delfin/tests/unit/drivers/hpe/hpe_msa/test_hpe_msastor.py b/delfin/tests/unit/drivers/hpe/hpe_msa/test_hpe_msastor.py new file mode 100644 index 000000000..8ea1c6daa --- /dev/null +++ b/delfin/tests/unit/drivers/hpe/hpe_msa/test_hpe_msastor.py @@ -0,0 +1,101 @@ +import sys +import paramiko + +from delfin import context +from unittest import TestCase, mock +from delfin.tests.unit.drivers.hpe.hpe_msa import test_constans +from delfin.drivers.utils.ssh_client import SSHPool +from delfin.drivers.hpe.hpe_msa.ssh_handler import SSHHandler +from delfin.drivers.hpe.hpe_msa.hpe_msastor import HpeMsaStorDriver + +sys.modules['delfin.cryptor'] = mock.Mock() + +ACCESS_INFO = { + "storage_id": "kkk", + "ssh": { + "host": "110.143.132.231", + "port": 22, + "username": "user", + "password": "pass", + "pub_key": "ddddddddddddddddddddddddd" + } +} + + +class Request: + def __init__(self): + self.environ = {'delfin.context': context.RequestContext()} + pass + + +class TestHpeMsaStorageDriver(TestCase): + + @mock.patch.object(SSHPool, 'do_exec') + @mock.patch.object(SSHPool, 'get') + def test_list_ports(self, mock_ssh_get, mock_control): + mock_ssh_get.return_value = {paramiko.SSHClient()} + mock_control.side_effect = [test_constans.LIST_PORTS] + ports = HpeMsaStorDriver(**ACCESS_INFO).list_ports(context) + self.assertEqual(ports, test_constans.ports_result) + + @mock.patch.object(SSHPool, 'do_exec') + @mock.patch.object(SSHPool, 'get') + def test_list_disks(self, mock_ssh_get, mock_control): + mock_ssh_get.return_value = {paramiko.SSHClient()} + mock_control.side_effect = [test_constans.LIST_DISKS] + disks = HpeMsaStorDriver(**ACCESS_INFO).list_disks(context) + self.assertEqual(disks, test_constans.disks_result) + + @mock.patch.object(SSHPool, 'do_exec') + @mock.patch.object(SSHPool, 'get') + def test_list_controllers(self, mock_ssh_get, mock_control): + mock_ssh_get.return_value = {paramiko.SSHClient()} + mock_control.side_effect = [test_constans.LIST_CONTROLLERS] + controller = HpeMsaStorDriver(**ACCESS_INFO).\ + list_controllers(context) + self.assertEqual(controller, test_constans.controller_result) + + @mock.patch.object(SSHPool, 'do_exec') + @mock.patch.object(SSHPool, 'get') + def test_list_volumes(self, mock_ssh_get, mock_control): + mock_ssh_get.return_value = {paramiko.SSHClient()} + mock_control.side_effect = [test_constans.LIST_VOLUMES, + test_constans.LIST_POOLS] + volumes = HpeMsaStorDriver(**ACCESS_INFO).list_volumes(context) + self.assertEqual(volumes, test_constans.volume_result) + + @mock.patch.object(SSHPool, 'do_exec') + @mock.patch.object(SSHPool, 'get') + @mock.patch.object(SSHHandler, 'list_storage_pools') + @mock.patch.object(SSHHandler, 'list_storage_disks') + @mock.patch.object(SSHHandler, 'list_storage_volume') + def test_list_storage(self, mock_system, mock_ssh_get, + mock_pools, mock_disks, mock_volume): + mock_volume.side_effect = [test_constans.LIST_SYSTEM, + test_constans.LIST_VISION] + mock_disks.return_value = {paramiko.SSHClient()} + mock_pools.side_effect = [test_constans.pools_result] + mock_ssh_get.side_effect = [test_constans.disks_result] + mock_system.side_effect = [test_constans.volume_result] + system = HpeMsaStorDriver(**ACCESS_INFO).get_storage(context) + self.assertEqual(system, test_constans.system_info) + + @mock.patch.object(SSHPool, 'do_exec') + @mock.patch.object(SSHPool, 'get') + @mock.patch.object(SSHHandler, 'list_storage_volume') + def test_list_storage_pools(self, mock_ssh_get, mock_control, + mock_volume): + mock_ssh_get.return_value = test_constans.volume_result + mock_control.side_effect = {paramiko.SSHClient()} + mock_volume.side_effect = [test_constans.LIST_POOLS] + pools = HpeMsaStorDriver(**ACCESS_INFO).list_storage_pools(context) + self.assertEqual(pools, test_constans.pools_result) + + @mock.patch.object(SSHPool, 'do_exec') + @mock.patch.object(SSHPool, 'get') + def test_list_alerts(self, mock_ssh_get, mock_control): + query_para = None + mock_ssh_get.return_value = {paramiko.SSHClient()} + mock_control.side_effect = [test_constans.LIST_ERROR] + alerts = HpeMsaStorDriver(**ACCESS_INFO).list_alerts(query_para) + self.assertEqual(alerts, test_constans.error_result)