Add support for Purity Protection Groups to PureISCSIDriver

We will be needing access to the Protection Group features of Purity to
enable features like Replication and Consistency Groups. To do this we
need to add new helpers for the FlashArray object for the required REST
API methods.

DocImpact: To bring in pgroup support we will need to bump up the
required REST API version to 1.2+ and remove support for 1.0 and 1.1

Implements: blueprint pure-iscsi-add-pgroup-support
Change-Id: Ia446615e0c03b91fc1da75489855e77c29639efa
This commit is contained in:
Patrick East 2014-12-05 10:18:46 -08:00
parent 9ad858c9c9
commit 55857055fe
2 changed files with 88 additions and 5 deletions

View File

@ -614,16 +614,16 @@ class FlashArrayHttpRequestTestCase(FlashArrayBaseTestCase):
# Test with _http_requests rather than rest calls to ensure
# root_url change happens properly
def test_choose_rest_version(self):
response_string = '{"version": ["0.1", "1.3", "1.1", "1.0"]}'
response_string = '{"version": ["0.1", "1.4", "1.3", "1.0"]}'
self.response.read.return_value = response_string
self.array._opener.open.return_value = self.response
result = self.array._choose_rest_version()
self.assertEqual(result, "1.1")
self.assertEqual(result, "1.3")
self.array._opener.open.assert_called_with(FakeRequest(
"GET", "https://%s/api/api_version" % TARGET,
headers=self.headers), "null")
self.array._opener.open.reset_mock()
self.response.read.return_value = '{"version": ["0.1", "1.3"]}'
self.response.read.return_value = '{"version": ["0.1", "1.4"]}'
self.assertRaises(exception.PureDriverException,
self.array._choose_rest_version)
@ -765,6 +765,68 @@ class FlashArrayRESTTestCase(FlashArrayBaseTestCase):
self.assert_error_propagates([mock_req], self.array.list_volume_hosts,
"vol-name")
def test_create_pgroup(self, mock_req):
mock_req.return_value = self.result
pgroup_name = "cgroup_id"
result = self.array.create_pgroup(pgroup_name)
self.assertEqual(self.result, result)
req_url = "pgroup/" + pgroup_name
mock_req.assert_called_with(self.array, "POST", req_url)
self.assert_error_propagates([mock_req], self.array.create_pgroup,
pgroup_name)
def test_delete_pgroup(self, mock_req):
mock_req.return_value = self.result
pgroup_name = "cgroup_id"
result = self.array.delete_pgroup(pgroup_name)
self.assertEqual(self.result, result)
req_url = "pgroup/" + pgroup_name
mock_req.assert_called_with(self.array, "DELETE", req_url)
self.assert_error_propagates([mock_req], self.array.delete_pgroup,
pgroup_name)
def test_create_pgroup_snapshot(self, mock_req):
mock_req.return_value = self.result
pgroup_name = "cgroup_id"
snap_suffix = "snap_suffix"
result = self.array.create_pgroup_snapshot(pgroup_name, snap_suffix)
self.assertEqual(self.result, result)
expected_params = {
"snap": True,
"suffix": snap_suffix,
"source": [pgroup_name]
}
mock_req.assert_called_with(self.array, "POST", "pgroup",
expected_params)
self.assert_error_propagates([mock_req],
self.array.create_pgroup_snapshot,
pgroup_name, snap_suffix)
def test_delete_pgroup_snapshot(self, mock_req):
mock_req.return_value = self.result
snapshot_name = "snap1"
result = self.array.delete_pgroup_snapshot(snapshot_name)
self.assertEqual(self.result, result)
req_url = "pgroup/" + snapshot_name
mock_req.assert_called_with(self.array, "DELETE", req_url)
self.assert_error_propagates([mock_req],
self.array.delete_pgroup_snapshot,
snapshot_name)
def test_add_volume_to_pgroup(self, mock_req):
mock_req.return_value = self.result
pgroup_name = "cgroup_id"
volume_name = "myvol-1"
expected_params = {"addvollist": [volume_name]}
result = self.array.add_volume_to_pgroup(pgroup_name, volume_name)
self.assertEqual(self.result, result)
req_url = "pgroup/" + pgroup_name
mock_req.assert_called_with(self.array, "PUT", req_url,
expected_params)
self.assert_error_propagates([mock_req],
self.array.add_volume_to_pgroup,
pgroup_name, volume_name)
class FakeFlashArray(pure.FlashArray):

View File

@ -71,7 +71,7 @@ def _generate_purity_host_name(name):
class PureISCSIDriver(san.SanISCSIDriver):
"""Performs volume management on Pure Storage FlashArray."""
VERSION = "1.0.0"
VERSION = "2.0.0"
def __init__(self, *args, **kwargs):
execute = kwargs.pop("execute", utils.execute)
@ -323,7 +323,7 @@ class PureISCSIDriver(san.SanISCSIDriver):
class FlashArray(object):
"""Wrapper for Pure Storage REST API."""
SUPPORTED_REST_API_VERSIONS = ["1.2", "1.1", "1.0"]
SUPPORTED_REST_API_VERSIONS = ["1.3", "1.2"]
def __init__(self, target, api_token):
cookie_handler = urllib2.HTTPCookieProcessor(cookielib.CookieJar())
@ -463,3 +463,24 @@ class FlashArray(object):
def list_volume_hosts(self, volume):
"""Return a list of dictionaries describing connected hosts."""
return self._http_request("GET", "volume/%s/host" % volume)
def create_pgroup(self, name):
return self._http_request("POST", "pgroup/%s" % name)
def delete_pgroup(self, name):
return self._http_request("DELETE", "pgroup/%s" % name)
def create_pgroup_snapshot(self, pgroup_name, pgsnapshot_suffix):
params = {
"snap": True,
"suffix": pgsnapshot_suffix,
"source": [pgroup_name]
}
return self._http_request("POST", "pgroup", params)
def delete_pgroup_snapshot(self, name):
return self._http_request("DELETE", "pgroup/%s" % name)
def add_volume_to_pgroup(self, pgroup_name, volume_name):
return self._http_request("PUT", "pgroup/%s" % pgroup_name,
{"addvollist": [volume_name]})