Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Emc vplex add controller port interface #572

Merged
merged 23 commits into from
Jun 4, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
7260671
add vplex controller port interface 0517
liuxiaohuan-ghca May 17, 2021
5f0f318
Merge pull request #68 from liuxiaohuan-ghca/emc_vplex_0517
luopan-code May 17, 2021
b420074
Merge branch 'master' into emc_vplex_0517
liuxiaohuan-ghca May 19, 2021
b38f7a2
Merge branch 'master' into emc_vplex_0517
liuxiaohuan-ghca May 24, 2021
ec2ac5b
update vplex port default value setting method
liuxiaohuan-ghca May 26, 2021
e03cd3b
Merge pull request #101 from liuxiaohuan-ghca/emc_vplex_0517
liuxiaohuan-ghca May 26, 2021
c5e90f0
Revert "update vplex port default value setting method"
liuxiaohuan-ghca May 27, 2021
3f17808
update vplex port default value setting method
liuxiaohuan-ghca May 27, 2021
9411773
update vplex port default value setting method
liuxiaohuan-ghca May 27, 2021
3a6f2fa
Merge pull request #104 from liuxiaohuan-ghca/emc_vplex_0517
luopan-code May 27, 2021
067133d
Merge branch 'master' into emc_vplex_0517
liuxiaohuan-ghca May 31, 2021
30a8590
update vplex port default value setting method
liuxiaohuan-ghca May 31, 2021
a0dd46a
Merge pull request #111 from liuxiaohuan-ghca/emc_vplex_0517
luopan-code May 31, 2021
6128a9a
Merge branch 'master' into emc_vplex_0517
liuxiaohuan-ghca Jun 2, 2021
7cc2564
Merge branch 'master' into emc_vplex_0517
liuxiaohuan-ghca Jun 3, 2021
f918ac6
Merge branch 'master' into emc_vplex_0517
liuxiaohuan-ghca Jun 4, 2021
fa84903
update vplex port default value setting method
liuxiaohuan-ghca Jun 4, 2021
3ded8b9
Merge pull request #137 from liuxiaohuan-ghca/emc_vplex_0517
luopan-code Jun 4, 2021
38c5a48
Merge branch 'master' into emc_vplex_0517
liuxiaohuan-ghca Jun 4, 2021
4395895
update vplex port default value setting method
liuxiaohuan-ghca Jun 4, 2021
0f4e96e
update vplex port default value setting method
liuxiaohuan-ghca Jun 4, 2021
30e5f08
Merge pull request #141 from liuxiaohuan-ghca/emc_vplex_0517
luopan-code Jun 4, 2021
d243f4e
Merge branch 'master' into emc_vplex_0517
yuanyu-ghca Jun 4, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions delfin/drivers/dell_emc/vplex/alert_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import hashlib
import time

from oslo_log import log

from delfin import exception
from delfin import exception, utils
from delfin.common import constants
from delfin.i18n import _

Expand Down Expand Up @@ -49,8 +48,7 @@ def parse_alert(context, alert):
constants.Severity.INFORMATIONAL)
alert_model['category'] = constants.Category.FAULT
alert_model['type'] = constants.EventType.EQUIPMENT_ALARM
occur_time = int(time.time()) * AlertHandler.SECONDS_TO_MS
alert_model['occur_time'] = occur_time
alert_model['occur_time'] = utils.utcnow_ms()
alert_model['description'] = description
alert_model['resource_type'] = constants.DEFAULT_RESOURCE_TYPE
alert_model['location'] = ''
Expand Down
41 changes: 41 additions & 0 deletions delfin/drivers/dell_emc/vplex/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,48 @@
# 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

SOCKET_TIMEOUT = 10
BASE_CONTEXT = '/vplex'
REST_AUTH_URL = '/vplex/clusters'

PORT_TYPE_MAP = {
'fc': constants.PortType.FC,
'iscsi': constants.PortType.ISCSI,
'ficon': constants.PortType.FICON,
'fcoe': constants.PortType.FCOE,
'eth': constants.PortType.ETH,
'sas': constants.PortType.SAS,
'ib': constants.PortType.IB,
'other': constants.PortType.OTHER,
}
PORT_LOGICAL_TYPE_MAP = {
'front-end': constants.PortLogicalType.FRONTEND,
'back-end': constants.PortLogicalType.BACKEND,
'service': constants.PortLogicalType.SERVICE,
'management': constants.PortLogicalType.MANAGEMENT,
'internal': constants.PortLogicalType.INTERNAL,
'maintenance': constants.PortLogicalType.MAINTENANCE,
'inter-director-communication': constants.PortLogicalType.INTERCONNECT,
'other': constants.PortLogicalType.OTHER,
'local-com': constants.PortLogicalType.OTHER,
'wan-com': constants.PortLogicalType.OTHER
}
PORT_CONNECT_STATUS_MAP = {
'up': constants.PortConnectionStatus.CONNECTED,
'down': constants.PortConnectionStatus.DISCONNECTED,
'no-link': constants.PortConnectionStatus.UNKNOWN
}
PORT_HEALTH_STATUS_MAP = {
'ok': constants.PortHealthStatus.NORMAL,
'error': constants.PortHealthStatus.ABNORMAL,
'stopped': constants.PortHealthStatus.UNKNOWN
}
CONTROLLER_STATUS_MAP = {
"ok": constants.ControllerStatus.NORMAL,
"busy": constants.ControllerStatus.NORMAL,
"no contact": constants.ControllerStatus.OFFLINE,
"lost communication": constants.ControllerStatus.OFFLINE,
"unknown": constants.ControllerStatus.UNKNOWN
}
25 changes: 24 additions & 1 deletion delfin/drivers/dell_emc/vplex/rest_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ def login(self):
if 'User authentication failed' in res.text:
raise exception.InvalidUsernameOrPassword()
else:
raise exception.BadResponse(res.text)
raise exception.StorageBackendException(
six.text_type(res.text))
except Exception as e:
LOG.error("Login error: %s", six.text_type(e))
raise e
Expand Down Expand Up @@ -124,3 +125,25 @@ def logout(self):
err_msg = "Logout error: %s" % (six.text_type(e))
LOG.error(err_msg)
raise e

def get_engine_director_resp(self):
url = '%s/engines/*/directors/*' % consts.BASE_CONTEXT
response = self.get_rest_info(url)
return response

def get_version_verbose(self):
url = '%s/version' % consts.BASE_CONTEXT
args = '-a --verbose'
data = {"args": args}
response = self.get_rest_info(url, data, method='POST')
return response

def get_cluster_export_port_resp(self):
url = '%s/clusters/*/exports/ports/*' % consts.BASE_CONTEXT
response = self.get_rest_info(url)
return response

def get_engine_director_hardware_port_resp(self):
url = '%s/engines/*/directors/*/hardware/ports/*' % consts.BASE_CONTEXT
response = self.get_rest_info(url)
return response
228 changes: 224 additions & 4 deletions delfin/drivers/dell_emc/vplex/vplex_stor.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from delfin.drivers import driver
from delfin.drivers.dell_emc.vplex import alert_handler
from delfin.drivers.dell_emc.vplex import rest_handler
from delfin.drivers.dell_emc.vplex import consts

LOG = log.getLogger(__name__)

Expand Down Expand Up @@ -80,8 +81,7 @@ def get_storage(self, context):
'raw_capacity': int(raw_capacity),
'total_capacity': int(total_capacity),
'used_capacity': int(used_capacity),
'free_capacity': int(free_capacity),
'subscribed_capacity': 0
'free_capacity': int(free_capacity)
}
break
return cluster
Expand Down Expand Up @@ -324,16 +324,236 @@ def get_cluster_used_capacity(self, cluster_name):

def list_controllers(self, context):
"""List all storage controllers from storage system."""
pass
ct_list = []
director_version_map = {}
version_resp = self.rest_handler.get_version_verbose()
all_director = self.rest_handler.get_engine_director_resp()
ct_context_list = VplexStorageDriver.get_context_list(all_director)
VplexStorageDriver.analyse_director_version(version_resp,
director_version_map)
for ct_context in ct_context_list:
ct_attr_map = ct_context.get("attributes")
communication_status = ct_attr_map.get('communication-status')
name = ct_attr_map.get('name')
ct = {
'native_controller_id ': ct_attr_map.get('director-id'),
'name': name,
'status': VplexStorageDriver.analyse_director_status(
communication_status),
'location ': '',
'storage_id ': self.storage_id,
'soft_version ': self.get_value_from_nest_map(
director_version_map, name, "Director Software"),
'cpu_info': '',
'memory_size': ''
}
ct_list.append(ct)
return ct_list

def list_ports(self, context):
"""List all ports from storage system."""
pass
port_list = []
hardware_port_map = {}
hardware_port_resp = self.rest_handler. \
get_engine_director_hardware_port_resp()
export_port_resp = self.rest_handler.get_cluster_export_port_resp()
VplexStorageDriver.analyse_hardware_port(hardware_port_resp,
hardware_port_map)
port_context_list = VplexStorageDriver. \
get_context_list(export_port_resp)
for port_context in port_context_list:
port_attr = port_context.get('attributes')
port_name = port_attr.get('name')
speed, max_speed, protocols, role, port_status, \
operational_status = self.get_hardware_port_info(
hardware_port_map, port_name, 'attributes')
connection_status = VplexStorageDriver.analyse_port_connect_status(
port_status)
port = {
'native_port_id': port_attr.get('name'),
'name': port_attr.get('name'),
'type': VplexStorageDriver.analyse_port_type(protocols),
'logical_type': VplexStorageDriver.analyse_port_logical_type(
role),
'connection_status': connection_status,
'health_status': VplexStorageDriver.analyse_port_health_status(
operational_status),
'location': '',
'storage_id': self.storage_id,
'native_parent_id': port_attr.get('director-id'),
'speed': VplexStorageDriver.analyse_speed(speed),
'max_speed': VplexStorageDriver.analyse_speed(max_speed),
'wwn': port_attr.get('port-wwn'),
'mac_address': '',
'ipv4': '',
'ipv4_mask': '',
'ipv6': '',
'ipv6_mask': ''
}
port_list.append(port)
return port_list

def list_disks(self, context):
"""List all disks from storage system."""
pass

@staticmethod
def get_context_list(response):
context_list = []
if response:
contexts = response.get("context")
for context in contexts:
type = context.get("type")
parent = context.get("parent")
attributes = context.get("attributes")
context_map = {}
attr_map = {}
for attribute in attributes:
key = attribute.get("name")
value = attribute.get("value")
attr_map[key] = value
context_map["type"] = type
context_map["parent"] = parent
context_map["attributes"] = attr_map
context_list.append(context_map)
return context_list

@staticmethod
def analyse_director_version(version_resp, director_version_map):
custom_data = version_resp.get('custom-data')
detail_arr = custom_data.split('\n')
director_name = ''
version_name = ''
for detail in detail_arr:
if detail is not None and detail != '':
if "For director" in detail:
match_obj = re.search(
r'For director.+?directors/(.*?):', detail)
if match_obj:
director_name = match_obj.group(1)
continue
if director_name:
if "What:" in detail:
match_obj = re.search(r'What:\s+(.+?)$', detail)
if match_obj:
version_name = match_obj.group(1)
continue
if version_name:
match_obj = re.search(r'Version:\s+(.+?)$', detail)
if match_obj:
version_value = match_obj.group(1)
if director_version_map.get(director_name):
director_version_map.get(director_name)[
version_name] = version_value
else:
version_map = {}
version_map[version_name] = version_value
director_version_map[
director_name] = version_map

@staticmethod
def analyse_director_status(status):
controller_status = constants.ControllerStatus.UNKNOWN
if status:
status_value = consts.CONTROLLER_STATUS_MAP.get(status)
if status_value:
controller_status = status_value
return controller_status

def get_director_specified_version(self, version_map, director_name,
specified_name):
version_value = ''
if version_map:
director_map = version_map.get(director_name)
if director_map:
version_value = director_map.get(specified_name)
return version_value

def get_value_from_nest_map(self, nest_map, first_key, second_key):
final_value = ''
if nest_map:
second_map = nest_map.get(first_key)
if second_map:
final_value = second_map.get(second_key)
return final_value

def get_hardware_port_info(self, nest_map, first_key, second_key):
speed = ''
max_speed = ''
protocols = []
role = ''
port_status = ''
operational_status = ''

if nest_map:
second_map = nest_map.get(first_key)
if second_map:
third_map = second_map.get(second_key)
if third_map:
speed = third_map.get('current-speed')
max_speed = third_map.get('max-speed')
protocols = third_map.get('protocols')
role = third_map.get('role')
port_status = third_map.get('port-status')
operational_status = third_map.get('operational-status')
return (speed, max_speed, protocols, role, port_status,
operational_status)

@staticmethod
def analyse_hardware_port(resp, hardware_port_map):
port_list = VplexStorageDriver.get_context_list(resp)
if port_list:
for port in port_list:
port_name = port.get("attributes").get("target-port")
liuxiaohuan-ghca marked this conversation as resolved.
Show resolved Hide resolved
hardware_port_map[port_name] = port

@staticmethod
def analyse_port_type(protocols):
port_type = constants.PortType.OTHER
if protocols:
for protocol in protocols:
port_type_value = consts.PORT_TYPE_MAP.get(protocol)
if port_type_value:
port_type = port_type_value
break
return port_type

@staticmethod
def analyse_port_logical_type(role):
port_logic_type = constants.PortLogicalType.OTHER
if role:
port_type_value = consts.PORT_LOGICAL_TYPE_MAP.get(role)
if port_type_value:
port_logic_type = port_type_value
return port_logic_type
liuxiaohuan-ghca marked this conversation as resolved.
Show resolved Hide resolved

@staticmethod
def analyse_port_connect_status(status):
liuxiaohuan-ghca marked this conversation as resolved.
Show resolved Hide resolved
port_connect_status = constants.PortConnectionStatus.UNKNOWN
if status:
port_status_value = consts.PORT_CONNECT_STATUS_MAP.get(status)
if port_status_value:
port_connect_status = port_status_value
return port_connect_status

@staticmethod
def analyse_port_health_status(status):
liuxiaohuan-ghca marked this conversation as resolved.
Show resolved Hide resolved
port_health_status = constants.PortHealthStatus.UNKNOWN
if status:
port_status_value = consts.PORT_HEALTH_STATUS_MAP.get(status)
if port_status_value:
port_health_status = port_status_value
return port_health_status

@staticmethod
def analyse_speed(speed):
liuxiaohuan-ghca marked this conversation as resolved.
Show resolved Hide resolved
speed_value = 0
if speed:
match_obj = re.search(r'([1-9]\d*\.?\d*)|(0\.\d*[1-9])', speed)
if match_obj:
speed_value = int(match_obj.group(0)) * units.G
return speed_value


@staticmethod
def handle_detail_list(detail_info, detail_map, split):
Expand Down
Loading