1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
3
# Copyright (c) 2012 EMC Corporation, Inc.
4
# Copyright (c) 2012 OpenStack LLC.
7
# Licensed under the Apache License, Version 2.0 (the "License"); you may
8
# not use this file except in compliance with the License. You may obtain
9
# a copy of the License at
11
# http://www.apache.org/licenses/LICENSE-2.0
13
# Unless required by applicable law or agreed to in writing, software
14
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16
# License for the specific language governing permissions and limitations
19
from cinder.openstack.common import log as logging
20
from cinder import test
21
from cinder.volume.drivers.emc import EMCISCSIDriver
23
LOG = logging.getLogger(__name__)
25
storage_system = 'CLARiiON+APM00123456789'
26
lunmaskctrl_id = 'CLARiiON+APM00123456789+00aa11bb22cc33dd44ff55gg66hh77ii88jj'
27
initiator1 = 'iqn.1993-08.org.debian:01:1a2b3c4d5f6g'
28
stconf_service_creationclass = 'Clar_StorageConfigurationService'
29
ctrlconf_service_creationclass = 'Clar_ControllerConfigurationService'
30
rep_service_creationclass = 'Clar_ReplicationService'
31
vol_creationclass = 'Clar_StorageVolume'
32
pool_creationclass = 'Clar_UnifiedStoragePool'
33
lunmask_creationclass = 'Clar_LunMaskingSCSIProtocolController'
34
unit_creationclass = 'CIM_ProtocolControllerForUnit'
37
test_volume = {'name': 'vol1',
39
'volume_name': 'vol1',
41
'provider_auth': None,
42
'project_id': 'project',
43
'display_name': 'vol1',
44
'display_description': 'test volume',
45
'volume_type_id': None}
46
test_snapshot = {'name': 'snapshot1',
49
'volume_name': 'vol1',
51
'project_id': 'project'}
52
test_clone = {'name': 'clone1',
54
'volume_name': 'vol1',
56
'provider_auth': None,
57
'project_id': 'project',
58
'display_name': 'clone1',
59
'display_description': 'volume created from snapshot',
60
'volume_type_id': None}
63
class EMC_StorageVolume(dict):
67
class FakeEcomConnection():
69
def InvokeMethod(self, MethodName, Service, ElementName=None, InPool=None,
70
ElementType=None, Size=None,
71
SyncType=None, SourceElement=None,
72
Operation=None, Synchronization=None,
74
LUNames=None, InitiatorPortIDs=None, DeviceAccesses=None,
75
ProtocolControllers=None,
76
MaskingGroup=None, Members=None):
78
job = {'status': 'success'}
81
def EnumerateInstanceNames(self, name):
83
if name == 'EMC_ReplicationService':
84
result = self._enum_replicationservices()
85
elif name == 'EMC_StorageConfigurationService':
86
result = self._enum_stconfsvcs()
87
elif name == 'EMC_ControllerConfigurationService':
88
result = self._enum_ctrlconfsvcs()
89
elif name == 'EMC_VirtualProvisioningPool':
90
result = self._enum_pools()
91
elif name == 'EMC_UnifiedStoragePool':
92
result = self._enum_pools()
93
elif name == 'EMC_StorageVolume':
94
result = self._enum_storagevolumes()
95
elif name == 'Clar_StorageVolume':
96
result = self._enum_storagevolumes()
97
elif name == 'SE_StorageSynchronized_SV_SV':
98
result = self._enum_syncsvsvs()
99
elif name == 'CIM_ProtocolControllerForUnit':
100
result = self._enum_unitnames()
101
elif name == 'EMC_LunMaskingSCSIProtocolController':
102
result = self._enum_lunmaskctrls()
104
result = self._default_enum()
107
def GetInstance(self, objectpath, LocalOnly=False):
108
name = objectpath['CreationClassName']
110
if name == 'Clar_StorageVolume':
111
result = self._getinstance_storagevolume(objectpath)
112
elif name == 'CIM_ProtocolControllerForUnit':
113
result = self._getinstance_unit(objectpath)
114
elif name == 'Clar_LunMaskingSCSIProtocolController':
115
result = self._getinstance_lunmask()
117
result = self._default_getinstance(objectpath)
120
def Associators(self, objectpath, resultClass='EMC_StorageHardwareID'):
122
if resultClass == 'EMC_StorageHardwareID':
123
result = self._assoc_hdwid()
125
result = self._default_assoc(objectpath)
128
def AssociatorNames(self, objectpath,
129
resultClass='EMC_LunMaskingSCSIProtocolController'):
131
if resultClass == 'EMC_LunMaskingSCSIProtocolController':
132
result = self._assocnames_lunmaskctrl()
134
result = self._default_assocnames(objectpath)
137
def ReferenceNames(self, objectpath,
138
ResultClass='CIM_ProtocolControllerForUnit'):
140
if ResultClass == 'CIM_ProtocolControllerForUnit':
141
result = self._ref_unitnames()
143
result = self._default_ref(objectpath)
146
def _ref_unitnames(self):
151
dependent['CreationClassName'] = vol_creationclass
152
dependent['DeviceID'] = test_volume['id']
153
dependent['ElementName'] = test_volume['name']
154
dependent['SystemName'] = storage_system
157
antecedent['CreationClassName'] = lunmask_creationclass
158
antecedent['DeviceID'] = lunmaskctrl_id
159
antecedent['SystemName'] = storage_system
161
unit['Dependent'] = dependent
162
unit['Antecedent'] = antecedent
163
unit['CreationClassName'] = unit_creationclass
168
def _default_ref(self, objectpath):
171
def _assoc_hdwid(self):
174
assoc['StorageID'] = initiator1
178
def _default_assoc(self, objectpath):
181
def _assocnames_lunmaskctrl(self):
182
return self._enum_lunmaskctrls()
184
def _default_assocnames(self, objectpath):
187
def _getinstance_storagevolume(self, objectpath):
188
instance = EMC_StorageVolume()
189
vols = self._enum_storagevolumes()
191
if vol['DeviceID'] == objectpath['DeviceID']:
196
def _getinstance_lunmask(self):
198
lunmask['CreationClassName'] = lunmask_creationclass
199
lunmask['DeviceID'] = lunmaskctrl_id
200
lunmask['SystemName'] = storage_system
203
def _getinstance_unit(self, objectpath):
207
dependent['CreationClassName'] = vol_creationclass
208
dependent['DeviceID'] = test_volume['id']
209
dependent['ElementName'] = test_volume['name']
210
dependent['SystemName'] = storage_system
213
antecedent['CreationClassName'] = lunmask_creationclass
214
antecedent['DeviceID'] = lunmaskctrl_id
215
antecedent['SystemName'] = storage_system
217
unit['Dependent'] = dependent
218
unit['Antecedent'] = antecedent
219
unit['CreationClassName'] = unit_creationclass
220
unit['DeviceNumber'] = '0'
224
def _default_getinstance(self, objectpath):
227
def _enum_replicationservices(self):
230
rep_service['SystemName'] = storage_system
231
rep_service['CreationClassName'] = rep_service_creationclass
232
rep_services.append(rep_service)
235
def _enum_stconfsvcs(self):
238
conf_service['SystemName'] = storage_system
239
conf_service['CreationClassName'] = stconf_service_creationclass
240
conf_services.append(conf_service)
243
def _enum_ctrlconfsvcs(self):
246
conf_service['SystemName'] = storage_system
247
conf_service['CreationClassName'] = ctrlconf_service_creationclass
248
conf_services.append(conf_service)
251
def _enum_pools(self):
254
pool['InstanceID'] = storage_system + '+U+' + storage_type
255
pool['CreationClassName'] = 'Clar_UnifiedStoragePool'
259
def _enum_storagevolumes(self):
261
vol = EMC_StorageVolume()
262
vol['CreationClassName'] = 'Clar_StorageVolume'
263
vol['ElementName'] = test_volume['name']
264
vol['DeviceID'] = test_volume['id']
265
vol['SystemName'] = storage_system
266
vol.path = {'DeviceID': vol['DeviceID']}
269
snap_vol = EMC_StorageVolume()
270
snap_vol['CreationClassName'] = 'Clar_StorageVolume'
271
snap_vol['ElementName'] = test_snapshot['name']
272
snap_vol['DeviceID'] = test_snapshot['id']
273
snap_vol['SystemName'] = storage_system
274
snap_vol.path = {'DeviceID': snap_vol['DeviceID']}
275
vols.append(snap_vol)
277
clone_vol = EMC_StorageVolume()
278
clone_vol['CreationClassName'] = 'Clar_StorageVolume'
279
clone_vol['ElementName'] = test_clone['name']
280
clone_vol['DeviceID'] = test_clone['id']
281
clone_vol['SystemName'] = storage_system
282
clone_vol.path = {'DeviceID': clone_vol['DeviceID']}
283
vols.append(clone_vol)
287
def _enum_syncsvsvs(self):
291
vols = self._enum_storagevolumes()
294
sync['SyncedElement'] = objpath2
295
sync['SystemElement'] = objpath1
296
sync['CreationClassName'] = 'SE_StorageSynchronized_SV_SV'
301
def _enum_unitnames(self):
302
return self._ref_unitnames()
304
def _enum_lunmaskctrls(self):
307
ctrl['CreationClassName'] = lunmask_creationclass
308
ctrl['DeviceID'] = lunmaskctrl_id
309
ctrl['SystemName'] = storage_system
313
def _default_enum(self):
316
name['Name'] = 'default'
321
class EMCISCSIDriverTestCase(test.TestCase):
324
super(EMCISCSIDriverTestCase, self).setUp()
325
driver = EMCISCSIDriver()
327
self.stubs.Set(EMCISCSIDriver, '_get_iscsi_properties',
328
self.fake_get_iscsi_properties)
329
self.stubs.Set(EMCISCSIDriver, '_get_ecom_connection',
330
self.fake_ecom_connection)
331
self.stubs.Set(EMCISCSIDriver, '_get_storage_type',
332
self.fake_storage_type)
334
def fake_ecom_connection(self):
335
conn = FakeEcomConnection()
338
def fake_get_iscsi_properties(self, volume):
339
LOG.info('Fake _get_iscsi_properties.')
341
properties['target_discovered'] = True
342
properties['target_portal'] = '10.10.10.10'
343
properties['target_iqn'] = 'iqn.1993-08.org.debian:01:a1b2c3d4e5f6'
344
device_number = '000008'
345
properties['target_lun'] = device_number
346
properties['volume_id'] = volume['id']
347
auth = volume['provider_auth']
349
(auth_method, auth_username, auth_secret) = auth.split()
350
properties['auth_method'] = auth_method
351
properties['auth_username'] = auth_username
352
properties['auth_password'] = auth_secret
353
LOG.info(_("Fake ISCSI properties: %s") % (properties))
356
def fake_storage_type(self, filename=None):
359
def test_create_destroy(self):
360
self.driver.create_volume(test_volume)
361
self.driver.delete_volume(test_volume)
363
def test_create_volume_snapshot_destroy(self):
364
self.driver.create_volume(test_volume)
365
self.driver.create_snapshot(test_snapshot)
366
self.driver.create_volume_from_snapshot(
367
test_clone, test_snapshot)
368
self.driver.delete_volume(test_clone)
369
self.driver.delete_snapshot(test_snapshot)
370
self.driver.delete_volume(test_volume)
372
def test_map_unmap(self):
373
self.driver.create_volume(test_volume)
374
export = self.driver.create_export(None, test_volume)
375
test_volume['provider_location'] = export['provider_location']
376
connector = {'initiator': initiator1}
377
connection_info = self.driver.initialize_connection(test_volume,
379
self.driver.terminate_connection(test_volume, connector)
380
self.driver.remove_export(None, test_volume)
381
self.driver.delete_volume(test_volume)