Skip to content

Commit

Permalink
Merge pull request #340 from zhilong-xu/pure
Browse files Browse the repository at this point in the history
Pure Modifying field Values
  • Loading branch information
ghca-cxl authored Dec 4, 2021
2 parents ae58678 + 6fbbfe7 commit 6138692
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 63 deletions.
14 changes: 11 additions & 3 deletions delfin/drivers/pure/flasharray/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@
# Normal value of the controller status
NORMAL_CONTROLLER_STATUS = 'ready'

# disk type
DISK_TYPE_NVRAM = 'NVRAM'

# The account password is incorrect during login.
LOGIN_PASSWORD_ERR = 'invalid credentials'

# list_port: Add ":" to the WWN every 2 sequences.
SPLICE_WWN_SERIAL = 2
SPLICE_WWN_COLON = ':'
Expand All @@ -64,18 +70,20 @@
'recovery': constants.Category.RECOVERY,
'notSpecified': constants.Category.NOT_SPECIFIED}
CONTROLLER_STATUS_MAP = {'normal': constants.ControllerStatus.NORMAL,
'ready': constants.ControllerStatus.NORMAL,
'ok': constants.ControllerStatus.NORMAL,
'offline': constants.ControllerStatus.OFFLINE,
'not_installed': constants.ControllerStatus.OFFLINE,
'fault': constants.ControllerStatus.FAULT,
'degraded': constants.ControllerStatus.DEGRADED,
'unknown': constants.ControllerStatus.UNKNOWN,
'unready': constants.ControllerStatus.UNKNOWN}
DISK_STATUS_MAP = {'normal': constants.DiskStatus.NORMAL,
'healthy': constants.DiskStatus.NORMAL,
'abnormal': constants.DiskStatus.ABNORMAL,
'unhealthy': constants.DiskStatus.ABNORMAL,
'offline': constants.DiskStatus.OFFLINE}

PORT_STATUS_MAP = {'ok': constants.PortHealthStatus.NORMAL,
'not_installed': constants.PortHealthStatus.ABNORMAL
}

PARSE_ALERT_ALERT_ID = '1.3.6.1.2.1.1.3.0'
PARSE_ALERT_STORAGE_NAME = '1.3.6.1.4.1.40482.3.1'
Expand Down
119 changes: 64 additions & 55 deletions delfin/drivers/pure/flasharray/pure_flasharray.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import datetime
import hashlib
import time

from oslo_log import log

Expand Down Expand Up @@ -55,22 +56,18 @@ def get_storage(self, context):
self.rest_handler.REST_STORAGE_URL)
total_capacity = None
used_capacity = None
raw_capacity = None
if storages:
for storage in storages:
used_capacity = int(storage.get('volumes',
used_capacity = int(storage.get('total',
consts.DEFAULT_CAPACITY))
raw_capacity = int(storage.get('capacity',
consts.DEFAULT_CAPACITY))
shared_space = int(storage.get('shared_space',
consts.DEFAULT_CAPACITY))
system = int(storage.get('system', consts.DEFAULT_CAPACITY))
snapshots = int(storage.get('snapshots',
consts.DEFAULT_CAPACITY))
total_capacity =\
raw_capacity - shared_space - system - snapshots
total_capacity = int(storage.get('capacity',
consts.DEFAULT_CAPACITY))
break

raw_capacity = consts.DEFAULT_CAPACITY
disks = self.list_disks(context)
if disks:
for disk in disks:
raw_capacity = raw_capacity + disk.get('capacity')
arrays = self.rest_handler.rest_call(self.rest_handler.REST_ARRAY_URL)
storage_name = None
serial_number = None
Expand All @@ -79,7 +76,6 @@ def get_storage(self, context):
storage_name = arrays.get('array_name')
serial_number = arrays.get('id')
version = arrays.get('version')

model = None
status = constants.StorageStatus.NORMAL
controllers = self.rest_handler.rest_call(
Expand All @@ -88,8 +84,9 @@ def get_storage(self, context):
for controller in controllers:
if controller.get('mode') == consts.CONTROLLER_PRIMARY:
model = controller.get('model')
if controller.get('status') != consts.NORMAL_CONTROLLER_STATUS:
status = constants.StorageStatus.ABNORMAL
if controller.get('status') != \
consts.NORMAL_CONTROLLER_STATUS:
status = constants.StorageStatus.ABNORMAL
if not all((storages, arrays, controllers)):
LOG.error('get_storage error, Unable to obtain data.')
raise exception.StorageBackendException('Unable to obtain data')
Expand All @@ -113,26 +110,37 @@ def list_alerts(self, context, query_para=None):
if alerts:
for alert in alerts:
alerts_model = dict()
opened = alert.get('opened')
time_difference = time.mktime(
time.localtime()) - time.mktime(time.gmtime())
timestamp = (int(datetime.datetime.strptime
(opened, '%Y-%m-%dT%H:%M:%SZ').timestamp()
+ time_difference) *
consts.DEFAULT_LIST_ALERTS_TIME_CONVERSION) if\
opened is not None else None
if query_para is not None:
try:
if timestamp is None or timestamp \
< int(query_para.get('begin_time')) or \
timestamp > int(query_para.get('end_time')):
continue
except Exception as e:
LOG.error(e)
alerts_model['occur_time'] = timestamp
alerts_model['alert_id'] = alert.get('id')
alerts_model['severity'] = consts.SEVERITY_MAP.get(
alert.get('current_severity'),
constants.Severity.NOT_SPECIFIED)
alerts_model['category'] = constants.Category.FAULT
time = alert.get('opened')
alerts_model['occur_time'] = int(datetime.datetime.strptime(
time, '%Y-%m-%dT%H:%M:%SZ').timestamp()
* consts.DEFAULT_LIST_ALERTS_TIME_CONVERSION) \
if time is not None else None
component_name = alert.get('component_name')
alerts_model['location'] = component_name
alerts_model['type'] = constants.EventType.EQUIPMENT_ALARM
alerts_model['resource_type'] = constants.DEFAULT_RESOURCE_TYPE
event = alert.get('event')
alerts_model['alert_name'] = event
alerts_model['sequence_number'] = alert.get('id')
alerts_model['match_key'] = hashlib.md5(str(alert.get('id')).
encode()).hexdigest()
alerts_model['description'] = '({}:{}): {}'.\
alerts_model['description'] = '({}:{}): {}'. \
format(alert.get('component_type'), component_name, event)
alerts_list.append(alerts_model)
return alerts_list
Expand Down Expand Up @@ -171,14 +179,17 @@ def list_controllers(self, context):
list_controllers = []
controllers = self.rest_handler.rest_call(
self.rest_handler.REST_CONTROLLERS_URL)
hardware = self.get_hardware()
if controllers:
for controller in controllers:
controllers_dict = dict()
controller_name = controller.get('name')
controllers_dict['name'] = controller_name
controllers_dict['status'] = consts.CONTROLLER_STATUS_MAP. \
get(controller.get('status'),
constants.ControllerStatus.UNKNOWN)
controllers_dict['status'] = hardware.get(
controller_name, {}).get('status')
controllers_dict['status'] = consts.CONTROLLER_STATUS_MAP.get(
hardware.get(controller_name, {}).get('status'),
constants.ControllerStatus.UNKNOWN)
controllers_dict['soft_version'] = controller.get('version')
controllers_dict['storage_id'] = self.storage_id
controllers_dict['id'] = controller_name
Expand All @@ -193,10 +204,14 @@ def list_disks(self, context):
disks = self.rest_handler.rest_call(self.rest_handler.REST_DISK_URL)
if disks:
for disk in disks:
disk_type = disk.get('type')
if disk_type == consts.DISK_TYPE_NVRAM or disk_type is None:
continue
disk_dict = dict()
drive_name = disk.get('name')
disk_dict['name'] = drive_name
physical_type = disk.get('type', "").lower()
physical_type = disk_type.lower() if disk_type is not None \
else None
disk_dict['physical_type'] = physical_type \
if physical_type in constants.DiskPhysicalType.ALL else \
constants.DiskPhysicalType.UNKNOWN
Expand All @@ -211,7 +226,6 @@ def list_disks(self, context):
disk_dict['model'] = hardware_object.get('model')
disk_dict['serial_number'] = hardware_object. \
get('serial_number')

disk_dict['native_disk_id'] = drive_name
disk_dict['id'] = drive_name
disk_dict['location'] = drive_name
Expand All @@ -230,6 +244,7 @@ def get_hardware(self):
hardware_map['speed'] = hardware_value.get('speed')
hardware_map['serial_number'] = hardware_value.get('serial')
hardware_map['model'] = hardware_value.get('model')
hardware_map['status'] = hardware_value.get('status')
hardware_dict[hardware_value.get('name')] = hardware_map
return hardware_dict

Expand Down Expand Up @@ -260,25 +275,19 @@ def list_ports(self, context):
if speed is None:
hardware_result['connection_status'] = \
constants.PortConnectionStatus.UNKNOWN
hardware_result['health_status'] = constants.PortHealthStatus.\
UNKNOWN
elif speed == consts.CONSTANT_ZERO:
hardware_result['connection_status'] = \
constants.PortConnectionStatus.DISCONNECTED
hardware_result['health_status'] = constants.PortHealthStatus.\
ABNORMAL
hardware_result['speed'] = speed
else:
hardware_result['connection_status'] = \
constants.PortConnectionStatus.CONNECTED
hardware_result['health_status'] = constants.PortHealthStatus.\
NORMAL
hardware_result['speed'] = int(speed)

hardware_result['health_status'] = consts.PORT_STATUS_MAP.get(
hardware.get('status'), constants.PortHealthStatus.UNKNOWN)
port = ports.get(hardware_name)
if port:
hardware_result['wwn'] = port.get('wwn')

network = networks.get(hardware_name)
if network:
hardware_result['mac_address'] = network.get('mac_address')
Expand All @@ -288,6 +297,26 @@ def list_ports(self, context):
list_ports.append(hardware_result)
return list_ports

def get_network(self):
networks_object = dict()
networks = self.rest_handler.rest_call(
self.rest_handler.REST_NETWORK_URL)
if networks:
for network in networks:
network_dict = dict()
network_dict['mac_address'] = network.get('hwaddr')
services_list = network.get('services')
if services_list:
for services in services_list:
network_dict['logical_type'] = services if \
services in constants.PortLogicalType.ALL else None
break
network_dict['ipv4_mask'] = network.get('netmask')
network_dict['ipv4'] = network.get('address')
network_name = network.get('name').upper()
networks_object[network_name] = network_dict
return networks_object

def get_ports(self):
ports_dict = dict()
ports = self.rest_handler.rest_call(self.rest_handler.REST_PORT_URL)
Expand All @@ -311,26 +340,6 @@ def get_splice_wwn(wwn):
wwn_splice = '{}{}'.format(wwn_splice, wwn_list[serial])
return wwn_splice

def get_network(self):
networks_object = dict()
networks = self.rest_handler.rest_call(
self.rest_handler.REST_NETWORK_URL)
if networks:
for network in networks:
network_dict = dict()
network_dict['mac_address'] = network.get('hwaddr')
services_list = network.get('services')
if services_list:
for services in services_list:
network_dict['logical_type'] = services if \
services in constants.PortLogicalType.ALL else None
break
network_dict['ipv4_mask'] = network.get('netmask')
network_dict['ipv4'] = network.get('address')
network_name = network.get('name').upper()
networks_object[network_name] = network_dict
return networks_object

def list_storage_pools(self, context):
return []

Expand Down
11 changes: 8 additions & 3 deletions delfin/drivers/pure/flasharray/rest_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class RestHandler(RestClient):
REST_DISK_URL = '/api/1.17/drive'
REST_HARDWARE_URL = '/api/1.17/hardware'
REST_CONTROLLERS_URL = '/api/1.17/array?controllers=true'
REST_ALERTS_URL = '/api/1.17/message?flagged=true'
REST_ALERTS_URL = '/api/1.17/message?flagged=true&open=true'
REST_AUTH_URL = '/api/1.17/auth/apitoken'
REST_SESSION_URL = '/api/1.17/auth/session'

Expand All @@ -33,6 +33,12 @@ def login(self):
self.init_http_head()
token_res = self.do_call(RestHandler.REST_AUTH_URL, data,
method='POST')
if token_res.json().get('msg') == consts.LOGIN_PASSWORD_ERR:
LOG.error("Login error, Obtaining the token is abnormal. "
"status_code:%s, URL: %s",
token_res.status_code, RestHandler.REST_AUTH_URL)
raise exception.InvalidUsernameOrPassword(
'Obtaining the token is abnormal')
if token_res.status_code != consts.SUCCESS_STATUS_CODE or not \
token_res.json().get('api_token'):
LOG.error("Login error, Obtaining the token is abnormal. "
Expand All @@ -45,8 +51,7 @@ def login(self):
if session_res.status_code != consts.SUCCESS_STATUS_CODE or not \
session_res.json().get('username'):
LOG.error("Login error, Obtaining the session is abnormal."
"status_code:%s, URL: %s",
session_res.status_code,
"status_code:%s, URL: %s", session_res.status_code,
RestHandler.REST_SESSION_URL)
raise exception.StorageBackendException(
'Obtaining the session is abnormal.')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,8 @@ def test_list_volumes(self):

def test_get_storage(self):
RestHandler.rest_call = mock.Mock(
side_effect=[storage_info, storage_id_info, controllers_info])
side_effect=[storage_info, hardware_info, drive_info,
storage_id_info, controllers_info])
storage_object = self.driver.get_storage(context)
self.assertEqual(storage_object.get('name'),
storage_id_info.get('array_name'))
Expand All @@ -319,7 +320,7 @@ def test_parse_alert(self):

def test_list_controllers(self):
RestHandler.rest_call = mock.Mock(
side_effect=[controllers_info])
side_effect=[controllers_info, hardware_info])
list_controllers = self.driver.list_controllers(context)
self.assertEqual(list_controllers[0].get('name'),
controllers_info[0].get('name'))
Expand Down

0 comments on commit 6138692

Please sign in to comment.