Browse Source

Merge "Critical fix for MSA 2060 and MSA 1060"

changes/53/756453/1
Zuul 1 year ago
committed by Gerrit Code Review
parent
commit
6ad1ab0c72
  1. 17
      cinder/tests/unit/volume/drivers/test_seagate.py
  2. 79
      cinder/volume/drivers/stx/client.py
  3. 6
      doc/source/configuration/block-storage/drivers/hp-msa-driver.rst
  4. 7
      releasenotes/notes/msa2060-99150398a9c416f6.yaml

17
cinder/tests/unit/volume/drivers/test_seagate.py

@ -50,6 +50,9 @@ resp_fw_ti = '''<RESPONSE><PROPERTY name="sc-fw">T252R07</PROPERTY>
resp_fw = '''<RESPONSE><PROPERTY name="sc-fw">GLS220R001</PROPERTY>
<PROPERTY name="return-code">0</PROPERTY></RESPONSE>'''
resp_fw_nomatch = '''<RESPONSE><PROPERTY name="sc-fw">Z</PROPERTY>
<PROPERTY name="return-code">0</PROPERTY></RESPONSE>'''
resp_system = '''<RESPONSE>
<PROPERTY name="midplane-serial-number">00C0FFEEEEEE</PROPERTY>
<PROPERTY name="return-code">0</PROPERTY>
@ -186,6 +189,12 @@ class TestSeagateClient(test.TestCase):
self.assertRaises(stx_exception.AuthenticationError,
self.client.login)
m.text.encode.side_effect = [resp_login, resp_fw_nomatch, resp_system]
self.client.login()
self.assertEqual('Z', self.client._fw_type)
self.assertEqual(0, self.client._fw_rev)
self.assertEqual(False, self.client.is_g5_fw())
m.text.encode.side_effect = [resp_login, resp_fw, resp_system]
self.client.login()
self.assertEqual(session_key, self.client._session_key)
@ -313,11 +322,15 @@ class TestSeagateClient(test.TestCase):
@mock.patch.object(STXClient, '_request')
def test_list_luns_for_host(self, mock_request):
mock_request.side_effect = [etree.XML(response_no_lun),
etree.XML(response_lun),
etree.XML(response_lun)]
self.client._fw = 'T100'
self.client._fw_type = 'T'
self.client.list_luns_for_host('dummy')
mock_request.assert_called_with('/show/host-maps', 'dummy')
self.client._fw = 'G221'
self.client._fw_type = 'G'
self.client.list_luns_for_host('dummy')
mock_request.assert_called_with('/show/maps/initiator', 'dummy')
self.client._fw_type = 'I'
self.client.list_luns_for_host('dummy')
mock_request.assert_called_with('/show/maps/initiator', 'dummy')

79
cinder/volume/drivers/stx/client.py

@ -17,6 +17,7 @@
import hashlib
import math
import re
import time
from lxml import etree
@ -44,7 +45,8 @@ class STXClient(object):
self._session_key = None
self.ssl_verify = ssl_verify
self._set_host(self._mgmt_ip_addrs[0])
self._fw = ''
self._fw_type = ''
self._fw_rev = 0
self._driver_name = self.__class__.__name__.split('.')[0]
self._array_name = 'unknown'
self._luns_in_use_by_host = {}
@ -245,8 +247,19 @@ class STXClient(object):
return False
def is_titanium(self):
"""True if array is an older generation."""
return True if len(self._fw) > 0 and self._fw[0] == 'T' else False
"""True for older array firmware."""
return self._fw_type == 'T'
def is_g5_fw(self):
"""Identify firmware updated in/after 2020.
Long-deprecated commands have or will be removed.
"""
if self._fw_type in ['I', 'V']:
return True
if self._fw_type == 'G' and self._fw_rev >= 280:
return True
return False
def create_volume(self, name, size, backend_name, backend_type):
# NOTE: size is in this format: [0-9]+GiB
@ -390,7 +403,8 @@ class STXClient(object):
if not isinstance(ids, list):
ids = [ids]
try:
xml = self._request('/show/volume-maps', volume_name)
cmd = "/show/volume-maps" if self.is_titanium() else "/show/maps"
xml = self._request(cmd, volume_name)
for obj in xml.xpath("//OBJECT[@basetype='volume-view-mappings']"):
lun = obj.findtext("PROPERTY[@name='lun']")
@ -420,7 +434,11 @@ class STXClient(object):
if host_status != 0:
hostname = self._safe_hostname(connector['host'])
try:
self._request("/create/host", hostname, id=host)
if self.is_g5_fw():
self._request("/set/initiator", nickname=hostname,
id=host)
else:
self._request("/create/host", hostname, id=host)
except stx_exception.RequestError as e:
# -10058: The host identifier or nickname is already in use
if '(-10058)' in e.msg:
@ -434,11 +452,18 @@ class STXClient(object):
while lun < 255:
try:
self._request("/map/volume",
volume_name,
lun=str(lun),
host=host,
access="rw")
if self.is_g5_fw():
self._request("/map/volume",
volume_name,
lun=str(lun),
initiator=host,
access="rw")
else:
self._request("/map/volume",
volume_name,
lun=str(lun),
host=host,
access="rw")
return lun
except stx_exception.RequestError as e:
# -3177 => "The specified LUN overlaps a previously defined LUN
@ -468,7 +493,10 @@ class STXClient(object):
else:
host = connector['initiator']
try:
self._request("/unmap/volume", volume_name, host=host)
if self.is_g5_fw():
self._request("/unmap/volume", volume_name, initiator=host)
else:
self._request("/unmap/volume", volume_name, host=host)
except stx_exception.RequestError as e:
# -10050 => The volume was not found on this system.
# This can occur during controller failover.
@ -574,12 +602,20 @@ class STXClient(object):
return True
def _check_host(self, host):
host_status = -1
"""Return 0 if initiator id found in the array's host table."""
if self.is_g5_fw():
tree = self._request("/show/initiators")
for prop in tree.xpath("//PROPERTY[@name='id' and text()='%s']"
% host):
return 0
return -1
# Use older syntax for older firmware
tree = self._request("/show/hosts")
for prop in tree.xpath("//PROPERTY[@name='host-id' and text()='%s']"
% host):
host_status = 0
return host_status
return 0
return -1
def _safe_hostname(self, hostname):
"""Modify an initiator name to match firmware requirements.
@ -650,7 +686,16 @@ class STXClient(object):
return self._get_size(size)
def get_firmware_version(self):
"""Get the array firmware version"""
tree = self._request("/show/controllers")
self._fw = tree.xpath("//PROPERTY[@name='sc-fw']")[0].text
LOG.debug("Array firmware is %s\n", self._fw)
return self._fw
s = tree.xpath("//PROPERTY[@name='sc-fw']")[0].text
if len(s):
self._fw_type = s[0]
fw_rev_match = re.match('^[^0-9]*([0-9]+).*', s)
if not fw_rev_match:
LOG.error('firmware revision not found in "%s"', s)
return s
self._fw_rev = int(fw_rev_match.groups()[0])
LOG.debug("Array firmware is %s (%s%d)\n",
s, self._fw_type, self._fw_rev)
return s

6
doc/source/configuration/block-storage/drivers/hp-msa-driver.rst

@ -2,9 +2,9 @@
HPE MSA Fibre Channel and iSCSI drivers
=======================================
The ``HPMSAFCDriver`` and ``HPMSAISCSIDriver`` Cinder drivers allow the
HPE MSA 2050, 1050, 2040, and 1040 arrays to be used for Block Storage in
OpenStack deployments.
The ``HPMSAFCDriver`` and ``HPMSAISCSIDriver`` Cinder drivers allow
the HPE MSA 2060, 1060, 2050, 1050, 2040, and 1040 arrays to be used
for Block Storage in OpenStack deployments.
System requirements
~~~~~~~~~~~~~~~~~~~

7
releasenotes/notes/msa2060-99150398a9c416f6.yaml

@ -0,0 +1,7 @@
---
fixes:
- |
HPMSA driver: The HPE MSA driver was updated to avoid using
deprecated command syntax that has been removed in the latest
version of the MSA API. This is required to support the newest
firmware in the MSA 2060/1060.
Loading…
Cancel
Save