cinder/cinder/tests/unit/volume/drivers/test_datera.py

1237 lines
49 KiB
Python

# Copyright 2017 Datera
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, 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.
import mock
import six
from cinder import context
from cinder import exception
from cinder import test
from cinder.volume import configuration as conf
from cinder.volume.drivers.datera import datera_common as datc
from cinder.volume.drivers.datera import datera_iscsi as datera
from cinder.volume import volume_types
datc.DEFAULT_SI_SLEEP = 0
datc.DEFAULT_SI_SLEEP_API_2 = 0
datc.DEFAULT_SNAP_SLEEP = 0
URL_TEMPLATES = datera.datc.URL_TEMPLATES
OS_PREFIX = datera.datc.OS_PREFIX
UNMANAGE_PREFIX = datera.datc.UNMANAGE_PREFIX
class DateraVolumeTestCasev2(test.TestCase):
def setUp(self):
super(DateraVolumeTestCasev2, self).setUp()
self.cfg = mock.Mock(spec=conf.Configuration)
self.cfg.san_ip = '127.0.0.1'
self.cfg.san_is_local = True
self.cfg.datera_api_token = 'secret'
self.cfg.datera_api_port = '7717'
self.cfg.datera_num_replicas = '2'
self.cfg.datera_503_timeout = 0.01
self.cfg.datera_503_interval = 0.001
self.cfg.datera_acl_allow_all = False
self.cfg.datera_debug = False
self.cfg.san_login = 'user'
self.cfg.san_password = 'pass'
self.cfg.datera_tenant_id = 'test-tenant'
self.cfg.driver_client_cert = None
self.cfg.driver_client_cert_key = None
self.cfg.datera_disable_profiler = False
self.cfg.driver_use_ssl = False
mock_exec = mock.Mock()
mock_exec.return_value = ('', '')
self.driver = datera.DateraDriver(execute=mock_exec,
configuration=self.cfg)
self.driver.set_initialized()
self.driver.configuration.get = _config_getter
self.volume = _stub_volume()
self.driver._request = mock.Mock()
m = mock.Mock()
m.json.return_value = {'api_versions': ['v2']}
self.driver._request.return_value = m
self.mock_api = mock.Mock()
self.driver._issue_api_request = self.mock_api
self._apiv = "2"
self._tenant = None
# self.addCleanup(self.api_patcher.stop)
def test_volume_create_success(self):
self.mock_api.return_value = stub_single_ai
self.assertIsNone(self.driver.create_volume(self.volume))
def test_volume_create_fails(self):
self.mock_api.side_effect = datc.DateraAPIException
self.assertRaises(datc.DateraAPIException,
self.driver.create_volume, self.volume)
def test_volume_create_delay(self):
"""Verify after 1st retry volume becoming available is a success."""
def _progress_api_return(mock_api):
if mock_api.retry_count == 1:
_bad_vol_ai = stub_single_ai.copy()
_bad_vol_ai['storage_instances']['storage-1'][
'volumes']['volume-1']['op_status'] = 'unavailable'
return _bad_vol_ai
else:
self.mock_api.retry_count += 1
return stub_single_ai
self.mock_api.retry_count = 0
self.mock_api.return_value = _progress_api_return(self.mock_api)
self.assertEqual(1, self.mock_api.retry_count)
self.assertIsNone(self.driver.create_volume(self.volume))
@mock.patch.object(volume_types, 'get_volume_type')
def test_create_volume_with_extra_specs(self, mock_get_type):
self.mock_api.return_value = stub_single_ai
mock_get_type.return_value = {
'name': u'The Best',
'qos_specs_id': None,
'deleted': False,
'created_at': '2015-08-14 04:18:11',
'updated_at': None,
'extra_specs': {
u'volume_backend_name': u'datera',
u'qos:max_iops_read': u'2000',
u'qos:max_iops_write': u'4000',
u'qos:max_iops_total': u'4000'
},
'is_public': True,
'deleted_at': None,
'id': u'dffb4a83-b8fb-4c19-9f8c-713bb75db3b1',
'description': None
}
mock_volume = _stub_volume(
volume_type_id='dffb4a83-b8fb-4c19-9f8c-713bb75db3b1'
)
self.assertIsNone(self.driver.create_volume(mock_volume))
self.assertTrue(mock_get_type.called)
def test_create_cloned_volume_success(self):
source_volume = _stub_volume(
id='7f91abfa-7964-41ed-88fc-207c3a290b4f',
display_name='foo'
)
self.assertIsNone(self.driver.create_cloned_volume(self.volume,
source_volume))
def test_create_cloned_volume_success_larger(self):
cloned_volume = _stub_volume(
id='7f91abfa-7964-41ed-88fc-207c3a290b4f',
display_name='foo',
size=2
)
mock_extend = mock.Mock()
if self._apiv == '2':
self.driver._extend_volume_2 = mock_extend
self.driver.create_cloned_volume(cloned_volume, self.volume)
mock_extend.assert_called_with(
cloned_volume, cloned_volume['size'])
else:
self.driver._extend_volume_2_1 = mock_extend
self.driver.create_cloned_volume(cloned_volume, self.volume)
mock_extend.assert_called_with(
cloned_volume, cloned_volume['size'])
def test_create_cloned_volume_fails(self):
self.mock_api.side_effect = datc.DateraAPIException
source_volume = _stub_volume(
id='7f91abfa-7964-41ed-88fc-207c3a290b4f',
display_name='foo'
)
self.assertRaises(datc.DateraAPIException,
self.driver.create_cloned_volume, self.volume,
source_volume)
def test_delete_volume_success(self):
if self._apiv == '2':
self.mock_api.side_effect = [
{},
self._generate_fake_api_request()(
"acl_policy", api_version=self._apiv, tenant=self._tenant),
self._generate_fake_api_request()(
"ig_group", api_version=self._apiv, tenant=self._tenant),
{},
{},
{},
{},
{}]
else:
self.mock_api.side_effect = [
{},
{},
self._generate_fake_api_request()(
"acl_policy", api_version=self._apiv, tenant=self._tenant),
self._generate_fake_api_request()(
"ig_group", api_version=self._apiv, tenant=self._tenant),
{},
{},
{},
{},
{}]
self.assertIsNone(self.driver.delete_volume(self.volume))
def test_delete_volume_not_found(self):
if self._apiv == '2':
self.mock_api.side_effect = exception.NotFound
else:
self.mock_api.side_effect = [
self._generate_fake_api_request("tenant"),
{},
exception.NotFound,
self._generate_fake_api_request()(
"acl_policy", api_version=self._apiv, tenant=self._tenant),
self._generate_fake_api_request()(
"ig_group", api_version=self._apiv, tenant=self._tenant),
{},
{},
{},
{},
]
self.assertIsNone(self.driver.delete_volume(self.volume))
def test_delete_volume_fails(self):
self.mock_api.side_effect = datc.DateraAPIException
self.assertRaises(datc.DateraAPIException,
self.driver.delete_volume, self.volume)
def test_ensure_export_success(self):
self.mock_api.side_effect = self._generate_fake_api_request()
ctxt = context.get_admin_context()
self.assertIsNone(self.driver.ensure_export(ctxt,
self.volume,
None))
def test_ensure_export_fails(self):
self.mock_api.side_effect = datc.DateraAPIException
ctxt = context.get_admin_context()
self.assertRaises(datc.DateraAPIException,
self.driver.ensure_export, ctxt, self.volume, None)
def test_create_export_target_does_not_exist_success(self):
self.mock_api.side_effect = self._generate_fake_api_request(
targets_exist=False)
ctxt = context.get_admin_context()
self.assertIsNone(self.driver.create_export(ctxt,
self.volume,
None))
def test_create_export_fails(self):
self.mock_api.side_effect = datc.DateraAPIException
ctxt = context.get_admin_context()
self.assertRaises(datc.DateraAPIException,
self.driver.create_export,
ctxt,
self.volume,
None)
def test_initialize_connection_success(self):
self.mock_api.side_effect = self._generate_fake_api_request()
connector = {}
expected = {
'driver_volume_type': 'iscsi',
'data': {
'target_discovered': False,
'volume_id': self.volume['id'],
'target_iqn': ('iqn.2013-05.com.daterainc:tc:01:sn:'
'3bbb080aab7d9abc'),
'target_portal': '172.28.41.63:3260',
'target_lun': 0,
'discard': False}}
self.assertEqual(expected,
self.driver.initialize_connection(self.volume,
connector))
def test_initialize_connection_fails(self):
self.mock_api.side_effect = datc.DateraAPIException
connector = {}
self.assertRaises(datc.DateraAPIException,
self.driver.initialize_connection,
self.volume,
connector)
def test_detach_volume_success(self):
if self._apiv == '2':
self.mock_api.side_effect = [
{},
self._generate_fake_api_request()(
"acl_policy", api_version=self._apiv, tenant=self._tenant),
self._generate_fake_api_request()(
"ig_group", api_version=self._apiv, tenant=self._tenant),
{},
{},
{},
{}]
else:
self.mock_api.side_effect = [
{},
{},
self._generate_fake_api_request()(
"acl_policy", api_version=self._apiv, tenant=self._tenant),
self._generate_fake_api_request()(
"ig_group", api_version=self._apiv, tenant=self._tenant),
{},
{},
{},
{}]
ctxt = context.get_admin_context()
volume = _stub_volume(status='in-use')
self.assertIsNone(self.driver.detach_volume(ctxt, volume))
def test_detach_volume_fails(self):
self.mock_api.side_effect = datc.DateraAPIException
ctxt = context.get_admin_context()
volume = _stub_volume(status='in-use')
self.assertRaises(datc.DateraAPIException,
self.driver.detach_volume, ctxt, volume)
def test_detach_volume_not_found(self):
if self._apiv == '2':
self.mock_api.side_effect = exception.NotFound
else:
self.mock_api.side_effect = [
self._generate_fake_api_request("tenant"),
exception.NotFound,
self._generate_fake_api_request()(
"acl_policy", api_version=self._apiv, tenant=self._tenant),
self._generate_fake_api_request()(
"ig_group", api_version=self._apiv, tenant=self._tenant),
{},
{},
{},
{}]
ctxt = context.get_admin_context()
volume = _stub_volume(status='in-use')
self.assertIsNone(self.driver.detach_volume(ctxt, volume))
def test_create_snapshot_success(self):
snapshot = _stub_snapshot(volume_id=self.volume['id'])
self.mock_api.side_effect = self._generate_fake_api_request()
self.assertIsNone(self.driver.create_snapshot(snapshot))
def test_create_snapshot_fails(self):
self.mock_api.side_effect = datc.DateraAPIException
snapshot = _stub_snapshot(volume_id=self.volume['id'])
self.assertRaises(datc.DateraAPIException,
self.driver.create_snapshot, snapshot)
def test_delete_snapshot_success(self):
if self._apiv == '2':
self.mock_api.return_value = stub_return_snapshots
else:
self.mock_api.return_value = stub_return_snapshots_21
snapshot = _stub_snapshot(volume_id=self.volume['id'])
self.assertIsNone(self.driver.delete_snapshot(snapshot))
def test_delete_snapshot_not_found(self):
if self._apiv == '2':
self.mock_api.side_effect = [
stub_return_snapshots,
exception.NotFound]
else:
self.mock_api.side_effect = [
self._generate_fake_api_request("tenant"),
stub_return_snapshots_21,
exception.NotFound]
snapshot = _stub_snapshot(self.volume['id'], volume_id="test")
self.assertIsNone(self.driver.delete_snapshot(snapshot))
def test_delete_snapshot_fails(self):
self.mock_api.side_effect = datc.DateraAPIException
snapshot = _stub_snapshot(volume_id=self.volume['id'])
self.assertRaises(datc.DateraAPIException,
self.driver.delete_snapshot, snapshot)
def test_create_volume_from_snapshot_success(self):
snapshot = _stub_snapshot(volume_id=self.volume['id'])
if self._apiv == '2':
self.mock_api.side_effect = [
stub_return_snapshots,
list(stub_return_snapshots.values())[0],
None]
else:
self.mock_api.side_effect = [
self._generate_fake_api_request("tenant"),
stub_return_snapshots_21,
{'data': stub_return_snapshots_21['data'][0]},
None]
self.assertIsNone(
self.driver.create_volume_from_snapshot(self.volume, snapshot))
@mock.patch.object(datera.DateraDriver, 'extend_volume')
def test_create_volume_from_snapshot_success_larger(self, mock_extend):
snapshot = _stub_snapshot(volume_id=self.volume['id'])
extend_volume = _stub_volume(size=2)
mock_extend = mock.Mock()
if self._apiv == '2':
self.driver._extend_volume_2 = mock_extend
self.mock_api.side_effect = [
stub_return_snapshots,
list(stub_return_snapshots.values())[0],
None]
self.driver.create_volume_from_snapshot(extend_volume, snapshot)
mock_extend.assert_called_once_with(extend_volume,
extend_volume['size'])
else:
self.driver._extend_volume_2_1 = mock_extend
self.mock_api.side_effect = [
self._generate_fake_api_request("tenant"),
stub_return_snapshots_21,
{'data': stub_return_snapshots_21['data'][0]},
None]
self.driver.create_volume_from_snapshot(extend_volume, snapshot)
mock_extend.assert_called_once_with(extend_volume,
extend_volume['size'])
def test_create_volume_from_snapshot_fails(self):
self.mock_api.side_effect = datc.DateraAPIException
snapshot = _stub_snapshot(volume_id=self.volume['id'])
self.assertRaises(datc.DateraAPIException,
self.driver.create_volume_from_snapshot, self.volume,
snapshot)
def test_extend_volume_success(self):
volume = _stub_volume(size=1)
self.mock_api.side_effect = [
stub_get_export,
{'data': stub_get_export},
self._generate_fake_api_request()(
"acl_policy", api_version=self._apiv, tenant=self._tenant),
self._generate_fake_api_request()(
"ig_group", api_version=self._apiv, tenant=self._tenant),
self._generate_fake_api_request()(
"acl_policy", api_version=self._apiv, tenant=self._tenant),
{}, {}, {}, {}, {}, {}, stub_get_export,
{'data': stub_get_export}]
self.assertIsNone(self.driver.extend_volume(volume, 2))
def test_extend_volume_fails(self):
self.mock_api.side_effect = datc.DateraAPIException
volume = _stub_volume(size=1)
self.assertRaises(datc.DateraAPIException,
self.driver.extend_volume, volume, 2)
def test_login_successful(self):
self.mock_api.return_value = {
'key': 'dd2469de081346c28ac100e071709403'
}
self.assertIsNone(self.driver.login())
self.assertEqual(1, self.mock_api.call_count)
def test_login_unsuccessful(self):
self.mock_api.side_effect = exception.NotAuthorized
self.assertRaises(exception.NotAuthorized, self.driver.login)
self.assertEqual(1, self.mock_api.call_count)
def test_manage_existing(self):
self.mock_api.return_value = {}
if self._apiv == '2':
test_name = {"source-name": "test-app:test-si:test-vol"}
self.assertIsNone(
self.driver.manage_existing(
_stub_volume(),
test_name))
self.mock_api.assert_called_with(
URL_TEMPLATES['ai_inst']().format(
test_name["source-name"].split(":")[0]),
method='put',
body={'name': OS_PREFIX + _stub_volume()['id']},
api_version=self._apiv)
else:
tenant = 'tenant'
test_name = {"source-name": "{}:test-app:test-si:test-vol".format(
tenant)}
self.assertIsNone(
self.driver.manage_existing(
_stub_volume(),
test_name))
self.mock_api.assert_called_with(
URL_TEMPLATES['ai_inst']().format(
test_name["source-name"].split(":")[1]),
method='put',
body={'name': OS_PREFIX + _stub_volume()['id']},
api_version=self._apiv,
tenant='tenant')
def test_manage_existing_wrong_ref(self):
TEST_NAME = {"source-name": "incorrect-reference"}
self.assertRaises(
exception.ManageExistingInvalidReference,
self.driver.manage_existing,
_stub_volume(),
TEST_NAME)
def test_manage_existing_get_size(self):
TEST_NAME = {"source-name": "test-app:storage-1:volume-1"}
self.mock_api.side_effect = self._generate_fake_api_request()
self.assertEqual(
self.driver.manage_existing_get_size(
_stub_volume(),
TEST_NAME), 500)
if self._apiv == '2':
self.mock_api.assert_called_with(
URL_TEMPLATES['ai_inst']().format(
TEST_NAME["source-name"].split(":")[0]),
api_version=self._apiv)
else:
self.mock_api.assert_called_with(
URL_TEMPLATES['ai_inst']().format(
TEST_NAME["source-name"].split(":")[0]),
api_version=self._apiv,
tenant=self._tenant)
def test_manage_existing_get_size_wrong_ref(self):
TEST_NAME = {"source-name": "incorrect-reference"}
self.assertRaises(
exception.ManageExistingInvalidReference,
self.driver.manage_existing_get_size,
_stub_volume(),
TEST_NAME)
def test_get_manageable_volumes(self):
if self._apiv == '2':
self.mock_api.return_value = non_cinder_ais
six.assertCountEqual(
self,
self.driver.get_manageable_volumes(
{}, "", 10, 0, "", ""),
[{'cinder_id': None,
'extra_info': None,
'reason_not_safe': None,
'reference': {
"source-name": 'test-app-inst:storage-1:volume-1'},
'safe_to_manage': True,
'size': 50},
{'cinder_id': 'c20aba21-6ef6-446b-b374-45733b4883ba',
'extra_info': None,
'reason_not_safe': None,
'reference': None,
'safe_to_manage': False,
'size': None}])
else:
self.mock_api.return_value = non_cinder_ais_21
self.assertEqual(
self.driver.get_manageable_volumes(
{}, "", 10, 0, "", ""),
[{'cinder_id': None,
'extra_info': None,
'reason_not_safe': '',
'reference': {
"source-name": 'test-app-inst:storage-1:volume-1'},
'safe_to_manage': True,
'size': 50},
{'cinder_id': 'c20aba21-6ef6-446b-b374-45733b4883ba',
'extra_info': None,
'reason_not_safe': '',
'reference': None,
'safe_to_manage': False,
'size': None}])
def test_unmanage(self):
self.mock_api.return_value = {}
self.assertIsNone(self.driver.unmanage(_stub_volume()))
if self._apiv == '2':
self.mock_api.assert_called_with(
URL_TEMPLATES['ai_inst']().format(
OS_PREFIX + _stub_volume()['id']),
method='put',
body={'name': UNMANAGE_PREFIX + _stub_volume()['id']},
api_version=self._apiv)
else:
self.mock_api.assert_called_with(
URL_TEMPLATES['ai_inst']().format(
OS_PREFIX + _stub_volume()['id']),
method='put',
body={'name': UNMANAGE_PREFIX + _stub_volume()['id']},
api_version=self._apiv,
tenant=self._tenant)
def _generate_fake_api_request(self, targets_exist=True):
def _fake_api_request(resource_type, *args, **kwargs):
if 'api_version' not in kwargs:
raise ValueError("Fix me dummy")
result = None
if resource_type.split('/')[-1] == 'storage-1':
result = stub_get_export
elif (resource_type.split('/')[-1] ==
'c20aba21-6ef6-446b-b374-45733b4883ba'):
result = stub_app_instance[
'c20aba21-6ef6-446b-b374-45733b4883ba']
elif resource_type == 'acl_policy':
result = stub_acl if self._apiv == '2' else stub_acl_21
elif resource_type == 'ig_group':
result = stub_ig if self._apiv == '2' else stub_ig_21
elif resource_type.split('/')[-1] == 'snapshots':
result = {'timestamp': 'test_ts'}
elif resource_type.split('/')[-1] == 'test_ts':
result = {'op_state': 'available'}
elif resource_type == 'tenant':
return {}
else:
if kwargs.get('api_version') == '2':
result = list(stub_app_instance.values())[0]
else:
result = stub_app_instance_21['data']
if kwargs.get('api_version') == '2':
return result
else:
return {'data': result}
return _fake_api_request
class DateraVolumeTestCasev21(DateraVolumeTestCasev2):
def setUp(self):
super(DateraVolumeTestCasev21, self).setUp()
m = mock.Mock()
m.json.return_value = {'api_versions': ['v2.1']}
self.driver._request.return_value = m
self.driver._store_metadata = mock.Mock()
self._apiv = '2.1'
self._tenant = self.cfg.datera_tenant_id
stub_acl = {
'initiator_groups': [
'/initiator_groups/IG-8739f309-dae9-4534-aa02-5b8e9e96eefd'],
'initiators': [],
'path': ('/app_instances/8739f309-dae9-4534-aa02-5b8e9e96eefd/'
'storage_instances/storage-1/acl_policy')}
stub_acl_21 = {
'initiator_groups': [
{'path': '/initiator_groups/IG-8739f309-dae9-4534-aa02-5b8e9e96eefd'}],
'initiators': [],
'path': ('/app_instances/8739f309-dae9-4534-aa02-5b8e9e96eefd/'
'storage_instances/storage-1/acl_policy')}
stub_ig = {
'members': ['/initiators/iqn.1993-08.org.debian:01:ed22de8d75c0'],
'name': 'IG-21e08155-8b95-4108-b148-089f64623963',
'path': '/initiator_groups/IG-21e08155-8b95-4108-b148-089f64623963'}
stub_ig_21 = {
'members': [
{'path': '/initiators/iqn.1993-08.org.debian:01:ed22de8d75c0'}],
'name': 'IG-21e08155-8b95-4108-b148-089f64623963',
'path': '/initiator_groups/IG-21e08155-8b95-4108-b148-089f64623963'}
stub_create_export = {
"_ipColl": ["172.28.121.10", "172.28.120.10"],
"acls": {},
"activeServers": {"4594953e-f97f-e111-ad85-001e6738c0f0": "1"},
"ctype": "TC_BLOCK_ISCSI",
"endpointsExt1": {
"4594953e-f97f-e111-ad85-001e6738c0f0": {
"ipHigh": 0,
"ipLow": "192421036",
"ipStr": "172.28.120.11",
"ipV": 4,
"name": "",
"network": 24
}
},
"endpointsExt2": {
"4594953e-f97f-e111-ad85-001e6738c0f0": {
"ipHigh": 0,
"ipLow": "192486572",
"ipStr": "172.28.121.11",
"ipV": 4,
"name": "",
"network": 24
}
},
"inodes": {"c20aba21-6ef6-446b-b374-45733b4883ba": "1"},
"name": "",
"networkPort": 0,
"serverAllocation": "TS_ALLOC_COMPLETED",
"servers": {"4594953e-f97f-e111-ad85-001e6738c0f0": "1"},
"targetAllocation": "TS_ALLOC_COMPLETED",
"targetIds": {
"4594953e-f97f-e111-ad85-001e6738c0f0": {
"ids": [{
"dev": None,
"id": "iqn.2013-05.com.daterainc::01:sn:fc372bc0490b2dbe"
}]
}
},
"typeName": "TargetIscsiConfig",
"uuid": "7071efd7-9f22-4996-8f68-47e9ab19d0fd"
}
stub_app_instance = {
"c20aba21-6ef6-446b-b374-45733b4883ba": {
"admin_state": "online",
"clone_src": {},
"create_mode": "openstack",
"descr": "",
"health": "ok",
"name": "c20aba21-6ef6-446b-b374-45733b4883ba",
"path": "/app_instances/c20aba21-6ef6-446b-b374-45733b4883ba",
"storage_instances": {
"storage-1": {
"access": {
"ips": [
"172.28.41.63"
],
"iqn": "iqn.2013-05.com.daterainc:tc:01:sn:"
"3bbb080aab7d9abc",
"path": "/app_instances/c20aba21-6ef6-446b-b374"
"-45733b4883ba/storage_instances/storage-1/access"
},
"access_control": {
"initiator_groups": [],
"initiators": [],
"path": "/app_instances/c20aba21-6ef6-446b-b374-"
"45733b4883ba/storage_instances/storage-1"
"/access_control"
},
"access_control_mode": "allow_all",
"active_initiators": [],
"active_storage_nodes": [
"/storage_nodes/1c4feac4-17c7-478b-8928-c76e8ec80b72"
],
"admin_state": "online",
"auth": {
"initiator_pswd": "",
"initiator_user_name": "",
"path": "/app_instances/c20aba21-6ef6-446b-b374-"
"45733b4883ba/storage_instances/storage-1/auth",
"target_pswd": "",
"target_user_name": "",
"type": "none"
},
"creation_type": "user",
"descr": "c20aba21-6ef6-446b-b374-45733b4883ba__ST__storage-1",
"op_state": "available",
"name": "storage-1",
"path": "/app_instances/c20aba21-6ef6-446b-b374-"
"45733b4883ba/storage_instances/storage-1",
"uuid": "b9897b84-149f-43c7-b19c-27d6af8fa815",
"volumes": {
"volume-1": {
"capacity_in_use": 0,
"name": "volume-1",
"op_state": "available",
"path": "/app_instances/c20aba21-6ef6-446b-b374-"
"45733b4883ba/storage_instances/storage-1"
"/volumes/volume-1",
"replica_count": 3,
"size": 500,
"snapshot_policies": {},
"snapshots": {
"1445384931.322468627": {
"op_state": "available",
"path": "/app_instances/c20aba21-6ef6-446b"
"-b374-45733b4883ba/storage_instances"
"/storage-1/volumes/volume-1/snapshots"
"/1445384931.322468627",
"uuid": "0bb34f0c-fea4-48e0-bf96-591120ac7e3c"
}
},
"uuid": "c20aba21-6ef6-446b-b374-45733b4883ba"
}
}
}
},
"uuid": "c20aba21-6ef6-446b-b374-45733b4883ba"
}
}
stub_app_instance_21 = {
"tenant": "/root",
"path": "/app_instances/1e52946a-5c77-45ed-8b4e-b46e7236a8eb",
"version": "v2.1",
"data": {
"tenant": "/root",
"path": "/app_instances/1e52946a-5c77-45ed-8b4e-b46e7236a8eb",
"name": "OS-9b0216bc-8aab-47f2-b746-843f497cb7a6",
"id": "1e52946a-5c77-45ed-8b4e-b46e7236a8eb",
"health": "ok",
"app_template": {
"path": "",
"resolved_path": "",
"resolved_tenant": ""
},
"descr": "",
"admin_state": "online",
"storage_instances": [
{
"health": "ok",
"path": "/app_instances/1e52946a-5c77-45ed-8b4e-b46e7236a8eb/"
"storage_instances/storage-1",
"name": "storage-1",
"admin_state": "online",
"op_state": "available",
"volumes": [
{
"path": "/app_instances/1e52946a-5c77-45ed-8b4e-"
"b46e7236a8eb/"
"storage_instances/storage-1/volumes/volume-1",
"name": "volume-1",
"replica_count": 1,
"uuid": "9b0216bc-8aab-47f2-b746-843f497cb7a6",
"size": 500,
"capacity_in_use": 0,
"snapshot_policies": [],
"snapshots": [],
"placement_mode": "hybrid",
"op_state": "available",
"active_storage_nodes": [
{
"path": "/storage_nodes/75f2cae4-68fb-4236-"
"a90c-b6c480b68816"
}
],
"health": "ok"
}
],
"access_control_mode": "deny_all",
"acl_policy": {
"path": "/app_instances/1e52946a-5c77-45ed-8b4e-"
"b46e7236a8eb/"
"storage_instances/storage-1/acl_policy",
"initiators": [],
"initiator_groups": []
},
"ip_pool": {
"path": "/access_network_ip_pools/default",
"resolved_path": "/access_network_ip_pools/default",
"resolved_tenant": "/root"
},
"access": {
"path": "/app_instances/1e52946a-5c77-45ed-8b4e-"
"b46e7236a8eb/"
"storage_instances/storage-1/access",
"ips": [
"172.28.41.63",
"172.29.41.29"
],
"iqn": "iqn.2013-05.com.daterainc:tc:01:sn:"
"3bbb080aab7d9abc"
},
"auth": {
"path": "/app_instances/1e52946a-5c77-45ed-8b4e-"
"b46e7236a8eb/"
"storage_instances/storage-1/auth",
"type": "none",
"initiator_user_name": "",
"initiator_pswd": "(hidden)",
"target_user_name": "",
"target_pswd": "(hidden)"
},
"active_initiators": [],
"active_storage_nodes": [
{
"path": "/storage_nodes/75f2cae4-68fb-4236-a90c-"
"b6c480b68816"
}
],
"uuid": "eb3d7b07-b520-4cc2-b365-90135b84c356"
}
],
"create_mode": "openstack",
"uuid": "9b0216bc-8aab-47f2-b746-843f497cb7a6",
"snapshots": [],
"snapshot_policies": []
}
}
stub_get_export = stub_app_instance[
'c20aba21-6ef6-446b-b374-45733b4883ba']['storage_instances']['storage-1']
stub_single_ai = stub_app_instance['c20aba21-6ef6-446b-b374-45733b4883ba']
stub_return_snapshots = \
{
"1446076293.118600738": {
"op_state": "available",
"path": "/app_instances/c20aba21-6ef6-446b-b374-45733b4883ba"
"/storage_instances/storage-1/volumes/volume-1/snapshots/"
"1446076293.118600738",
"uuid": "0bb34f0c-fea4-48e0-bf96-591120ac7e3c"
},
"1446076384.00607846": {
"op_state": "available",
"path": "/app_instances/c20aba21-6ef6-446b-b374-45733b4883ba"
"/storage_instances/storage-1/volumes/volume-1/snapshots/"
"1446076384.00607846",
"uuid": "25b4b959-c30a-45f2-a90c-84a40f34f0a1"
}
}
stub_return_snapshots_21 = {
'data': [
{
"op_state": "available",
"path": "/app_instances/c20aba21-6ef6-446b-b374-45733b4883ba"
"/storage_instances/storage-1/volumes/volume-1/snapshots/",
"timestamp": "1446076293.118600738",
"utc_ts": "1446076293.118600738",
"uuid": "0bb34f0c-fea4-48e0-bf96-591120ac7e3c"
},
{
"op_state": "available",
"path": "/app_instances/c20aba21-6ef6-446b-b374-45733b4883ba"
"/storage_instances/storage-1/volumes/volume-1/snapshots/",
"timestamp": "1446076384.00607846",
"utc_ts": "1446076384.00607846",
"uuid": "25b4b959-c30a-45f2-a90c-84a40f34f0a1"
}]
}
non_cinder_ais = {
"75bc1c69-a399-4acb-aade-3514caf13c5e": {
"admin_state": "online",
"create_mode": "normal",
"descr": "",
"health": "ok",
"id": "75bc1c69-a399-4acb-aade-3514caf13c5e",
"name": "test-app-inst",
"path": "/app_instances/75bc1c69-a399-4acb-aade-3514caf13c5e",
"snapshot_policies": {},
"snapshots": {},
"storage_instances": {
"storage-1": {
"access": {
"ips": [
"172.28.41.93"
],
"iqn": "iqn.2013-05.com.daterainc:tc:01:sn:"
"29036682e2d37b98",
"path": "/app_instances/75bc1c69-a399-4acb-aade-"
"3514caf13c5e/storage_instances/storage-1/access"
},
"access_control_mode": "deny_all",
"acl_policy": {
"initiator_groups": [],
"initiators": [],
"path": "/app_instances/75bc1c69-a399-4acb-aade-"
"3514caf13c5e/storage_instances/storage-"
"1/acl_policy"
},
"active_initiators": [],
"active_storage_nodes": [
"/storage_nodes/78b350a8-43f2-453f-a257-8df76d7406b9"
],
"admin_state": "online",
"auth": {
"initiator_pswd": "(hidden)",
"initiator_user_name": "",
"path": "/app_instances/75bc1c69-a399-4acb-aade-"
"3514caf13c5e/storage_instances/storage-1/auth",
"target_pswd": "(hidden)",
"target_user_name": "",
"type": "none"
},
"creation_type": "user",
"ip_pool": "/access_network_ip_pools/default",
"name": "storage-1",
"op_state": "available",
"path": "/app_instances/75bc1c69-a399-4acb-aade-"
"3514caf13c5e/storage_instances/storage-1",
"uuid": "6421237d-e4fc-433a-b535-148d5b6d8586",
"volumes": {
"volume-1": {
"capacity_in_use": 0,
"name": "volume-1",
"op_state": "available",
"path": "/app_instances/75bc1c69-a399-4acb-aade-"
"3514caf13c5e/storage_instances/storage-"
"1/volumes/volume-1",
"replica_count": 1,
"size": 50,
"snapshot_policies": {},
"snapshots": {},
"uuid": "e674d29c-a672-40d1-9577-abe3a504ffe9"
}
}
}
},
"uuid": "00000000-0000-0000-0000-000000000000"
},
"dfdaf8d1-8976-4c13-a829-3345e03cf810": {
"admin_state": "offline",
"create_mode": "openstack",
"descr": "",
"health": "ok",
"id": "dfdaf8d1-8976-4c13-a829-3345e03cf810",
"name": "OS-c20aba21-6ef6-446b-b374-45733b4883ba",
"path": "/app_instances/dfdaf8d1-8976-4c13-a829-3345e03cf810",
"snapshot_policies": {},
"snapshots": {},
"storage_instances": {
"storage-1": {
"access": {
"ips": [
"172.28.41.57"
],
"iqn": "iqn.2013-05.com.daterainc:tc:01:sn:"
"56cd59e754ad02b6",
"path": "/app_instances/dfdaf8d1-8976-4c13-a829-"
"3345e03cf810/storage_instances/storage-1/access"
},
"access_control_mode": "deny_all",
"acl_policy": {
"initiator_groups": [],
"initiators": [],
"path": "/app_instances/dfdaf8d1-8976-4c13-a829-"
"3345e03cf810/storage_instances/storage-"
"1/acl_policy"
},
"active_initiators": [],
"active_storage_nodes": [
"/storage_nodes/78b350a8-43f2-453f-a257-8df76d7406b9"
],
"admin_state": "offline",
"auth": {
"initiator_pswd": "(hidden)",
"initiator_user_name": "",
"path": "/app_instances/dfdaf8d1-8976-4c13-a829-"
"3345e03cf810/storage_instances/storage-1/auth",
"target_pswd": "(hidden)",
"target_user_name": "",
"type": "none"
},
"creation_type": "user",
"ip_pool": "/access_network_ip_pools/default",
"name": "storage-1",
"op_state": "unavailable",
"path": "/app_instances/dfdaf8d1-8976-4c13-a829-3345e03cf810"
"/storage_instances/storage-1",
"uuid": "5620a673-9985-464e-9616-e325a50eac60",
"volumes": {
"volume-1": {
"capacity_in_use": 0,
"name": "volume-1",
"op_state": "available",
"path": "/app_instances/dfdaf8d1-8976-4c13-a829-"
"3345e03cf810/storage_instances/storage-"
"1/volumes/volume-1",
"replica_count": 1,
"size": 5,
"snapshot_policies": {},
"snapshots": {},
"uuid": "c20aba21-6ef6-446b-b374-45733b4883ba"
}
}
}
},
"uuid": "c20aba21-6ef6-446b-b374-45733b4883ba"
}
}
non_cinder_ais_21 = {
'data': [{
"admin_state": "online",
"create_mode": "normal",
"descr": "",
"health": "ok",
"id": "75bc1c69-a399-4acb-aade-3514caf13c5e",
"name": "test-app-inst",
"path": "/app_instances/75bc1c69-a399-4acb-aade-3514caf13c5e",
"snapshot_policies": {},
"snapshots": {},
"storage_instances": {
"storage-1": {
"access": {
"ips": [
"172.28.41.93"
],
"iqn": "iqn.2013-05.com.daterainc:tc:01:sn:"
"29036682e2d37b98",
"path": "/app_instances/75bc1c69-a399-4acb-aade-"
"3514caf13c5e/storage_instances/storage-1/access"
},
"access_control_mode": "deny_all",
"acl_policy": {
"initiator_groups": [],
"initiators": [],
"path": "/app_instances/75bc1c69-a399-4acb-aade-"
"3514caf13c5e/storage_instances/storage-"
"1/acl_policy"
},
"active_initiators": [],
"active_storage_nodes": [
"/storage_nodes/78b350a8-43f2-453f-a257-8df76d7406b9"
],
"admin_state": "online",
"auth": {
"initiator_pswd": "(hidden)",
"initiator_user_name": "",
"path": "/app_instances/75bc1c69-a399-4acb-aade-"
"3514caf13c5e/storage_instances/storage-1/auth",
"target_pswd": "(hidden)",
"target_user_name": "",
"type": "none"
},
"creation_type": "user",
"ip_pool": "/access_network_ip_pools/default",
"name": "storage-1",
"op_state": "available",
"path": "/app_instances/75bc1c69-a399-4acb-aade-"
"3514caf13c5e/storage_instances/storage-1",
"uuid": "6421237d-e4fc-433a-b535-148d5b6d8586",
"volumes": {
"volume-1": {
"capacity_in_use": 0,
"name": "volume-1",
"op_state": "available",
"path": "/app_instances/75bc1c69-a399-4acb-aade-"
"3514caf13c5e/storage_instances/storage-"
"1/volumes/volume-1",
"replica_count": 1,
"size": 50,
"snapshot_policies": {},
"snapshots": {},
"uuid": "e674d29c-a672-40d1-9577-abe3a504ffe9"
}
}
}
},
"uuid": "00000000-0000-0000-0000-000000000000"
},
{
"admin_state": "offline",
"create_mode": "openstack",
"descr": "",
"health": "ok",
"id": "dfdaf8d1-8976-4c13-a829-3345e03cf810",
"name": "OS-c20aba21-6ef6-446b-b374-45733b4883ba",
"path": "/app_instances/dfdaf8d1-8976-4c13-a829-3345e03cf810",
"snapshot_policies": {},
"snapshots": {},
"storage_instances": {
"storage-1": {
"access": {
"ips": [
"172.28.41.57"
],
"iqn": "iqn.2013-05.com.daterainc:tc:01:sn:"
"56cd59e754ad02b6",
"path": "/app_instances/dfdaf8d1-8976-4c13-a829-"
"3345e03cf810/storage_instances/storage-1/access"
},
"access_control_mode": "deny_all",
"acl_policy": {
"initiator_groups": [],
"initiators": [],
"path": "/app_instances/dfdaf8d1-8976-4c13-a829-"
"3345e03cf810/storage_instances/storage-"
"1/acl_policy"
},
"active_initiators": [],
"active_storage_nodes": [
"/storage_nodes/78b350a8-43f2-453f-a257-8df76d7406b9"
],
"admin_state": "offline",
"auth": {
"initiator_pswd": "(hidden)",
"initiator_user_name": "",
"path": "/app_instances/dfdaf8d1-8976-4c13-a829-"
"3345e03cf810/storage_instances/storage-1/auth",
"target_pswd": "(hidden)",
"target_user_name": "",
"type": "none"
},
"creation_type": "user",
"ip_pool": "/access_network_ip_pools/default",
"name": "storage-1",
"op_state": "unavailable",
"path": "/app_instances/dfdaf8d1-8976-4c13-a829-3345e03cf810"
"/storage_instances/storage-1",
"uuid": "5620a673-9985-464e-9616-e325a50eac60",
"volumes": {
"volume-1": {
"capacity_in_use": 0,
"name": "volume-1",
"op_state": "available",
"path": "/app_instances/dfdaf8d1-8976-4c13-a829-"
"3345e03cf810/storage_instances/storage-"
"1/volumes/volume-1",
"replica_count": 1,
"size": 5,
"snapshot_policies": {},
"snapshots": {},
"uuid": "c20aba21-6ef6-446b-b374-45733b4883ba"
}
}
}
},
"uuid": "c20aba21-6ef6-446b-b374-45733b4883ba"
}]
}
def _stub_datera_volume(*args, **kwargs):
return {
"status": "available",
"name": "test",
"num_replicas": "2",
"parent": "00000000-0000-0000-0000-000000000000",
"size": "1024",
"sub_type": "IS_ORIGINAL",
"uuid": "10305aa4-1343-4363-86fe-f49eb421a48c",
"snapshots": [],
"snapshot_configs": [],
"targets": [
kwargs.get('targets', "744e1bd8-d741-4919-86cd-806037d98c8a"),
]
}
def _stub_volume(*args, **kwargs):
uuid = u'c20aba21-6ef6-446b-b374-45733b4883ba'
name = u'volume-00000001'
size = 1
volume = {}
volume['id'] = kwargs.get('id', uuid)
volume['display_name'] = kwargs.get('display_name', name)
volume['size'] = kwargs.get('size', size)
volume['provider_location'] = kwargs.get('provider_location', None)
volume['volume_type_id'] = kwargs.get('volume_type_id', None)
return volume
def _stub_snapshot(*args, **kwargs):
uuid = u'0bb34f0c-fea4-48e0-bf96-591120ac7e3c'
name = u'snapshot-00000001'
size = 1
volume = {}
volume['id'] = kwargs.get('id', uuid)
volume['display_name'] = kwargs.get('display_name', name)
volume['volume_size'] = kwargs.get('size', size)
volume['volume_id'] = kwargs.get('volume_id', None)
return volume
def _config_getter(*args, **kwargs):
return {}