1# Copyright (c) 2015 FUJITSU LIMITED
2# Copyright (c) 2012 EMC Corporation, Inc.
3# All Rights Reserved.
4#
5#    Licensed under the Apache License, Version 2.0 (the "License"); you may
6#    not use this file except in compliance with the License. You may obtain
7#    a copy of the License at
8#
9#         http://www.apache.org/licenses/LICENSE-2.0
10#
11#    Unless required by applicable law or agreed to in writing, software
12#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14#    License for the specific language governing permissions and limitations
15#    under the License.
16
17import mock
18import six
19import tempfile
20
21from oslo_utils import units
22
23from cinder import exception
24from cinder import test
25from cinder.volume import configuration as conf
26
27with mock.patch.dict('sys.modules', pywbem=mock.Mock()):
28    from cinder.volume.drivers.fujitsu import eternus_dx_common as dx_common
29    from cinder.volume.drivers.fujitsu import eternus_dx_fc as dx_fc
30    from cinder.volume.drivers.fujitsu import eternus_dx_iscsi as dx_iscsi
31
32CONFIG_FILE_NAME = 'cinder_fujitsu_eternus_dx.xml'
33STORAGE_SYSTEM = '172.16.0.2'
34
35CONF = """<?xml version='1.0' encoding='UTF-8'?>
36<FUJITSU>
37<EternusIP>172.16.0.2</EternusIP>
38<EternusPort>5988</EternusPort>
39<EternusUser>testuser</EternusUser>
40<EternusPassword>testpass</EternusPassword>
41<EternusISCSIIP>10.0.0.3</EternusISCSIIP>
42<EternusPool>abcd1234_TPP</EternusPool>
43<EternusSnapPool>abcd1234_OSVD</EternusSnapPool>
44</FUJITSU>"""
45
46TEST_VOLUME = {
47    'id': '3d6eeb5d-109b-4435-b891-d01415178490',
48    'name': 'volume1',
49    'display_name': 'volume1',
50    'provider_location': None,
51    'volume_metadata': [],
52    'size': 1,
53}
54
55TEST_SNAP = {
56    'id': 'f47a8da3-d9e2-46aa-831f-0ef04158d5a1',
57    'volume_name': 'volume-3d6eeb5d-109b-4435-b891-d01415178490',
58    'name': 'snap1',
59    'display_name': 'test_snapshot',
60    'volume': TEST_VOLUME,
61    'volume_id': '3d6eeb5d-109b-4435-b891-d01415178490',
62}
63
64TEST_CLONE = {
65    'name': 'clone1',
66    'size': 1,
67    'volume_name': 'vol1',
68    'id': '391fb914-8a55-4384-a747-588641db3b15',
69    'project_id': 'project',
70    'display_name': 'clone1',
71    'display_description': 'volume created from snapshot',
72    'volume_metadata': [],
73}
74
75ISCSI_INITIATOR = 'iqn.1993-08.org.debian:01:8261afe17e4c'
76ISCSI_TARGET_IP = '10.0.0.3'
77ISCSI_TARGET_IQN = 'iqn.2000-09.com.fujitsu:storage-system.eternus-dxl:0'
78FC_TARGET_WWN = ['500000E0DA000001', '500000E0DA000002']
79TEST_WWPN = ['0123456789111111', '0123456789222222']
80TEST_CONNECTOR = {'initiator': ISCSI_INITIATOR, 'wwpns': TEST_WWPN}
81
82
83STOR_CONF_SVC = 'FUJITSU_StorageConfigurationService'
84CTRL_CONF_SVC = 'FUJITSU_ControllerConfigurationService'
85REPL_SVC = 'FUJITSU_ReplicationService'
86STOR_VOL = 'FUJITSU_StorageVolume'
87SCSI_PROT_CTR = 'FUJITSU_AffinityGroupController'
88STOR_HWID = 'FUJITSU_StorageHardwareID'
89STOR_HWID_MNG_SVC = 'FUJITSU_StorageHardwareIDManagementService'
90STOR_POOL = 'FUJITSU_RAIDStoragePool'
91STOR_POOLS = ['FUJITSU_ThinProvisioningPool', 'FUJITSU_RAIDStoragePool']
92AUTH_PRIV = 'FUJITSU_AuthorizedPrivilege'
93STOR_SYNC = 'FUJITSU_StorageSynchronized'
94PROT_CTRL_UNIT = 'CIM_ProtocolControllerForUnit'
95STORAGE_TYPE = 'abcd1234_TPP'
96LUNMASKCTRL_IDS = ['AFG0010_CM00CA00P00', 'AFG0011_CM01CA00P00']
97
98MAP_STAT = '0'
99VOL_STAT = '0'
100
101FAKE_CAPACITY = 1170368102400
102FAKE_LUN_ID1 = '600000E00D2A0000002A011500140000'
103FAKE_LUN_NO1 = '0x0014'
104FAKE_LUN_ID2 = '600000E00D2A0000002A0115001E0000'
105FAKE_LUN_NO2 = '0x001E'
106FAKE_SYSTEM_NAME = 'ET603SA4621302115'
107
108FAKE_STATS = {
109    'vendor_name': 'FUJITSU',
110    'total_capacity_gb': FAKE_CAPACITY / units.Gi,
111    'free_capacity_gb': FAKE_CAPACITY / units.Gi,
112}
113
114FAKE_KEYBIND1 = {
115    'CreationClassName': 'FUJITSU_StorageVolume',
116    'SystemName': STORAGE_SYSTEM,
117    'DeviceID': FAKE_LUN_ID1,
118    'SystemCreationClassName': 'FUJITSU_StorageComputerSystem',
119}
120
121FAKE_LOCATION1 = {
122    'classname': 'FUJITSU_StorageVolume',
123    'keybindings': FAKE_KEYBIND1,
124}
125
126FAKE_LUN_META1 = {
127    'FJ_Pool_Type': 'Thinporvisioning_POOL',
128    'FJ_Volume_No': FAKE_LUN_NO1,
129    'FJ_Volume_Name': u'FJosv_0qJ4rpOHgFE8ipcJOMfBmg==',
130    'FJ_Pool_Name': STORAGE_TYPE,
131    'FJ_Backend': FAKE_SYSTEM_NAME,
132}
133
134FAKE_MODEL_INFO1 = {
135    'provider_location': six.text_type(FAKE_LOCATION1),
136    'metadata': FAKE_LUN_META1,
137}
138
139FAKE_KEYBIND2 = {
140    'CreationClassName': 'FUJITSU_StorageVolume',
141    'SystemName': STORAGE_SYSTEM,
142    'DeviceID': FAKE_LUN_ID2,
143    'SystemCreationClassName': 'FUJITSU_StorageComputerSystem',
144}
145
146FAKE_LOCATION2 = {
147    'classname': 'FUJITSU_StorageVolume',
148    'keybindings': FAKE_KEYBIND2,
149}
150
151FAKE_SNAP_INFO = {'provider_location': six.text_type(FAKE_LOCATION2)}
152
153FAKE_LUN_META2 = {
154    'FJ_Pool_Type': 'Thinporvisioning_POOL',
155    'FJ_Volume_No': FAKE_LUN_NO1,
156    'FJ_Volume_Name': u'FJosv_UkCZqMFZW3SU_JzxjHiKfg==',
157    'FJ_Pool_Name': STORAGE_TYPE,
158    'FJ_Backend': FAKE_SYSTEM_NAME,
159}
160
161FAKE_MODEL_INFO2 = {
162    'provider_location': six.text_type(FAKE_LOCATION1),
163    'metadata': FAKE_LUN_META2,
164}
165
166
167class FJ_StorageVolume(dict):
168    pass
169
170
171class FJ_StoragePool(dict):
172    pass
173
174
175class FJ_AffinityGroupController(dict):
176    pass
177
178
179class FakeCIMInstanceName(dict):
180
181    def fake_create_eternus_instance_name(self, classname, bindings):
182        instancename = FakeCIMInstanceName()
183        for key in bindings:
184            instancename[key] = bindings[key]
185        instancename.classname = classname
186        instancename.namespace = 'root/eternus'
187        return instancename
188
189
190class FakeEternusConnection(object):
191    def InvokeMethod(self, MethodName, Service, ElementName=None, InPool=None,
192                     ElementType=None, TheElement=None, LUNames=None,
193                     Size=None, Type=None, Mode=None, Locality=None,
194                     InitiatorPortIDs=None, TargetPortIDs=None,
195                     DeviceAccesses=None, SyncType=None,
196                     SourceElement=None, TargetElement=None,
197                     Operation=None, CopyType=None,
198                     Synchronization=None, ProtocolControllers=None,
199                     TargetPool=None):
200        global MAP_STAT, VOL_STAT
201        if MethodName == 'CreateOrModifyElementFromStoragePool':
202            VOL_STAT = '1'
203            rc = 0
204            vol = self._enum_volumes()
205            job = {'TheElement': vol[0].path}
206        elif MethodName == 'ReturnToStoragePool':
207            VOL_STAT = '0'
208            rc = 0
209            job = {}
210        elif MethodName == 'GetReplicationRelationships':
211            rc = 0
212            job = {'Synchronizations': []}
213        elif MethodName == 'ExposePaths':
214            MAP_STAT = '1'
215            rc = 0
216            job = {}
217        elif MethodName == 'HidePaths':
218            MAP_STAT = '0'
219            rc = 0
220            job = {}
221        elif MethodName == 'CreateElementReplica':
222            rc = 0
223            snap = self._enum_snapshots()
224            job = {'TargetElement': snap[0].path}
225        elif MethodName == 'CreateReplica':
226            rc = 0
227            snap = self._enum_snapshots()
228            job = {'TargetElement': snap[0].path}
229        elif MethodName == 'ModifyReplicaSynchronization':
230            rc = 0
231            job = {}
232        else:
233            raise exception.VolumeBackendAPIException(data="invoke method")
234
235        return (rc, job)
236
237    def EnumerateInstanceNames(self, name):
238        result = []
239        if name == 'FUJITSU_StorageVolume':
240            result = self._enum_volumes()
241        elif name == 'FUJITSU_StorageConfigurationService':
242            result = self._enum_confservice()
243        elif name == 'FUJITSU_ReplicationService':
244            result = self._enum_repservice()
245        elif name == 'FUJITSU_ControllerConfigurationService':
246            result = self._enum_ctrlservice()
247        elif name == 'FUJITSU_AffinityGroupController':
248            result = self._enum_afntyservice()
249        elif name == 'FUJITSU_StorageHardwareIDManagementService':
250            result = self._enum_sthwidmngsvc()
251        elif name == 'CIM_ProtocolControllerForUnit':
252            result = self._ref_unitnames()
253        elif name == 'CIM_StoragePool':
254            result = self._enum_pools()
255        elif name == 'FUJITSU_SCSIProtocolEndpoint':
256            result = self._enum_scsiport_endpoint()
257        elif name == 'FUJITSU_IPProtocolEndpoint':
258            result = self._enum_ipproto_endpoint()
259
260        return result
261
262    def EnumerateInstances(self, name):
263        result = None
264        if name == 'FUJITSU_StorageProduct':
265            result = self._enum_sysnames()
266        elif name == 'FUJITSU_RAIDStoragePool':
267            result = self._enum_pool_details('RAID')
268        elif name == 'FUJITSU_ThinProvisioningPool':
269            result = self._enum_pool_details('TPP')
270        elif name == 'FUJITSU_SCSIProtocolEndpoint':
271            result = self._enum_scsiport_endpoint()
272        elif name == 'FUJITSU_iSCSIProtocolEndpoint':
273            result = self._enum_iscsiprot_endpoint()
274        elif name == 'FUJITSU_StorageHardwareID':
275            result = self._enum_sthwid()
276        elif name == 'CIM_SCSIProtocolEndpoint':
277            result = self._enum_scsiport_endpoint()
278        elif name == 'FUJITSU_StorageHardwareID':
279            result = None
280        else:
281            result = None
282
283        return result
284
285    def GetInstance(self, objectpath, LocalOnly=False):
286        try:
287            name = objectpath['CreationClassName']
288        except KeyError:
289            name = objectpath.classname
290
291        result = None
292
293        if name == 'FUJITSU_StorageVolume':
294            result = self._getinstance_storagevolume(objectpath)
295        elif name == 'FUJITSU_IPProtocolEndpoint':
296            result = self._getinstance_ipprotocolendpoint(objectpath)
297        elif name == 'CIM_ProtocolControllerForUnit':
298            result = self._getinstance_unit(objectpath)
299        elif name == 'FUJITSU_AffinityGroupController':
300            result = self._getinstance_unit(objectpath)
301
302        return result
303
304    def Associators(self, objectpath, AssocClass=None,
305                    ResultClass='FUJITSU_StorageHardwareID'):
306        result = None
307        if ResultClass == 'FUJITSU_StorageHardwareID':
308            result = self._assoc_hdwid()
309        elif ResultClass == 'FUJITSU_iSCSIProtocolEndpoint':
310            result = self._assoc_endpoint(objectpath)
311        elif ResultClass == 'FUJITSU_StorageVolume':
312            result = self._assoc_storagevolume(objectpath)
313        elif ResultClass == 'FUJITSU_AuthorizedPrivilege':
314            result = self._assoc_authpriv()
315        else:
316            result = self._default_assoc(objectpath)
317
318        return result
319
320    def AssociatorNames(self, objectpath, AssocClass=None,
321                        ResultClass=SCSI_PROT_CTR):
322        result = None
323        if ResultClass == SCSI_PROT_CTR:
324            result = self._assocnames_lunmaskctrl()
325        elif ResultClass == 'FUJITSU_TCPProtocolEndpoint':
326            result = self._assocnames_tcp_endpoint()
327        elif ResultClass == 'FUJITSU_AffinityGroupController':
328            result = self._assocnames_afngroup()
329        else:
330            result = self._default_assocnames(objectpath)
331
332        return result
333
334    def ReferenceNames(self, objectpath,
335                       ResultClass='CIM_ProtocolControllerForUnit'):
336        result = []
337        if ResultClass == 'CIM_ProtocolControllerForUnit':
338            if MAP_STAT == '1':
339                result = self._ref_unitnames()
340            else:
341                result = []
342        elif ResultClass == 'FUJITSU_StorageSynchronized':
343            result = self._ref_storage_sync()
344        else:
345            result = self._default_ref(objectpath)
346
347        return result
348
349    def _ref_unitnames(self):
350        unitnames = []
351
352        unitname = FJ_AffinityGroupController()
353        dependent = {}
354        dependent['CreationClassName'] = STOR_VOL
355        dependent['DeviceID'] = FAKE_LUN_ID1
356        dependent['SystemName'] = STORAGE_SYSTEM
357
358        antecedent = {}
359        antecedent['CreationClassName'] = SCSI_PROT_CTR
360        antecedent['DeviceID'] = LUNMASKCTRL_IDS[0]
361        antecedent['SystemName'] = STORAGE_SYSTEM
362
363        unitname['Dependent'] = dependent
364        unitname['Antecedent'] = antecedent
365        unitname['CreationClassName'] = PROT_CTRL_UNIT
366        unitname.path = unitname
367        unitnames.append(unitname)
368
369        unitname2 = FJ_AffinityGroupController()
370        dependent2 = {}
371        dependent2['CreationClassName'] = STOR_VOL
372        dependent2['DeviceID'] = FAKE_LUN_ID1
373        dependent2['SystemName'] = STORAGE_SYSTEM
374
375        antecedent2 = {}
376        antecedent2['CreationClassName'] = SCSI_PROT_CTR
377        antecedent2['DeviceID'] = LUNMASKCTRL_IDS[1]
378        antecedent2['SystemName'] = STORAGE_SYSTEM
379
380        unitname2['Dependent'] = dependent2
381        unitname2['Antecedent'] = antecedent2
382        unitname2['CreationClassName'] = PROT_CTRL_UNIT
383        unitname2.path = unitname2
384        unitnames.append(unitname2)
385
386        return unitnames
387
388    def _ref_storage_sync(self):
389        syncnames = []
390        return syncnames
391
392    def _default_ref(self, objectpath):
393        return objectpath
394
395    def _default_assoc(self, objectpath):
396        return objectpath
397
398    def _assocnames_lunmaskctrl(self):
399        return self._enum_lunmaskctrls()
400
401    def _assocnames_tcp_endpoint(self):
402        return self._enum_tcp_endpoint()
403
404    def _assocnames_afngroup(self):
405        return self._enum_afntyservice()
406
407    def _default_assocnames(self, objectpath):
408        return objectpath
409
410    def _assoc_authpriv(self):
411        authprivs = []
412        iscsi = {}
413        iscsi['InstanceID'] = ISCSI_INITIATOR
414        authprivs.append(iscsi)
415
416        fc = {}
417        fc['InstanceID'] = TEST_WWPN[0]
418        authprivs.append(fc)
419
420        fc1 = {}
421        fc1['InstanceID'] = TEST_WWPN[1]
422        authprivs.append(fc1)
423
424        return authprivs
425
426    def _assoc_endpoint(self, objectpath):
427        targetlist = []
428        tgtport1 = {}
429        tgtport1['CreationClassName'] = 'FUJITSU_IPProtocolEndpoint'
430        tgtport1['Name'] = ('iqn.2000-09.com.fujitsu:storage-system.'
431                            'eternus-dxl:0123456789,t,0x0009')
432        targetlist.append(tgtport1)
433
434        return targetlist
435
436    def _getinstance_unit(self, objectpath):
437        unit = FJ_AffinityGroupController()
438        unit.path = None
439
440        if MAP_STAT == '0':
441            return unit
442        dependent = {}
443        dependent['CreationClassName'] = STOR_VOL
444        dependent['DeviceID'] = FAKE_LUN_ID1
445        dependent['ElementName'] = TEST_VOLUME['name']
446        dependent['SystemName'] = STORAGE_SYSTEM
447
448        antecedent = {}
449        antecedent['CreationClassName'] = SCSI_PROT_CTR
450        antecedent['DeviceID'] = LUNMASKCTRL_IDS[0]
451        antecedent['SystemName'] = STORAGE_SYSTEM
452
453        unit['Dependent'] = dependent
454        unit['Antecedent'] = antecedent
455        unit['CreationClassName'] = PROT_CTRL_UNIT
456        unit['DeviceNumber'] = '0'
457        unit.path = unit
458
459        return unit
460
461    def _enum_sysnames(self):
462        sysnamelist = []
463        sysname = {}
464        sysname['IdentifyingNumber'] = FAKE_SYSTEM_NAME
465        sysnamelist.append(sysname)
466        return sysnamelist
467
468    def _enum_confservice(self):
469        services = []
470        service = {}
471        service['Name'] = 'FUJITSU:ETERNUS SMI-S Agent'
472        service['SystemCreationClassName'] = 'FUJITSU_StorageComputerSystem'
473        service['SystemName'] = STORAGE_SYSTEM
474        service['CreationClassName'] = 'FUJITSU_StorageConfigurationService'
475        services.append(service)
476        return services
477
478    def _enum_ctrlservice(self):
479        services = []
480        service = {}
481        service['SystemName'] = STORAGE_SYSTEM
482        service['CreationClassName'] = 'FUJITSU_ControllerConfigurationService'
483        services.append(service)
484        return services
485
486    def _enum_afntyservice(self):
487        services = []
488        service = {}
489        service['SystemName'] = STORAGE_SYSTEM
490        service['CreationClassName'] = 'FUJITSU_AffinityGroupController'
491        services.append(service)
492        return services
493
494    def _enum_repservice(self):
495        services = []
496        service = {}
497        service['Name'] = 'FUJITSU:ETERNUS SMI-S Agent'
498        service['SystemCreationClassName'] = 'FUJITSU_StorageComputerSystem'
499        service['SystemName'] = STORAGE_SYSTEM
500        service['CreationClassName'] = 'FUJITSU_ReplicationService'
501        services.append(service)
502        return services
503
504    def _enum_pools(self):
505        pools = []
506        pool = {}
507        pool['InstanceID'] = 'FUJITSU:RSP0004'
508        pool['CreationClassName'] = 'FUJITSU_RAIDStoragePool'
509        pools.append(pool)
510
511        pool2 = {}
512        pool2['InstanceID'] = 'FUJITSU:TPP0004'
513        pool2['CreationClassName'] = 'FUJITSU_ThinProvisioningPool'
514        pools.append(pool2)
515        return pools
516
517    def _enum_pool_details(self, pooltype):
518        pools = []
519        pool = FJ_StoragePool()
520
521        if pooltype == 'RAID':
522            pool['InstanceID'] = 'FUJITSU:RSP0004'
523            pool['CreationClassName'] = 'FUJITSU_RAIDStoragePool'
524            pool['ElementName'] = 'abcd1234_OSVD'
525            pool['TotalManagedSpace'] = 1170368102400
526            pool['RemainingManagedSpace'] = 1170368102400
527            pool.path = pool
528            pool.path.classname = 'FUJITSU_RAIDStoragePool'
529        else:
530            pool = FJ_StoragePool()
531            pool['InstanceID'] = 'FUJITSU:TPP0004'
532            pool['CreationClassName'] = 'FUJITSU_ThinProvisioningPool'
533            pool['ElementName'] = 'abcd1234_TPP'
534            pool['TotalManagedSpace'] = 1170368102400
535            pool['RemainingManagedSpace'] = 1170368102400
536            pool.path = pool
537            pool.path.classname = 'FUJITSU_ThinProvisioningPool'
538
539        pools.append(pool)
540        return pools
541
542    def _enum_volumes(self):
543        volumes = []
544        if VOL_STAT == '0':
545            return volumes
546        volume = FJ_StorageVolume()
547        volume['name'] = TEST_VOLUME['name']
548        volume['CreationClassName'] = 'FUJITSU_StorageVolume'
549        volume['Name'] = FAKE_LUN_ID1
550        volume['DeviceID'] = FAKE_LUN_ID1
551        volume['SystemCreationClassName'] = 'FUJITSU_StorageComputerSystem'
552        volume['SystemName'] = STORAGE_SYSTEM
553        volume['ElementName'] = 'FJosv_0qJ4rpOHgFE8ipcJOMfBmg=='
554        volume['volume_type_id'] = None
555        volume.path = volume
556        volume.path.classname = volume['CreationClassName']
557
558        name = {}
559        name['classname'] = 'FUJITSU_StorageVolume'
560        keys = {}
561        keys['CreationClassName'] = 'FUJITSU_StorageVolume'
562        keys['SystemName'] = STORAGE_SYSTEM
563        keys['DeviceID'] = volume['DeviceID']
564        keys['SystemCreationClassName'] = 'FUJITSU_StorageComputerSystem'
565        name['keybindings'] = keys
566        volume['provider_location'] = str(name)
567
568        volumes.append(volume)
569
570        snap_vol = FJ_StorageVolume()
571        snap_vol['name'] = TEST_SNAP['name']
572        snap_vol['CreationClassName'] = 'FUJITSU_StorageVolume'
573        snap_vol['Name'] = FAKE_LUN_ID2
574        snap_vol['DeviceID'] = FAKE_LUN_ID2
575        snap_vol['SystemCreationClassName'] = 'FUJITSU_StorageComputerSystem'
576        snap_vol['SystemName'] = STORAGE_SYSTEM
577        snap_vol['ElementName'] = 'FJosv_OgEZj1mSvKRvIKOExKktlg=='
578        snap_vol.path = snap_vol
579        snap_vol.path.classname = snap_vol['CreationClassName']
580
581        name2 = {}
582        name2['classname'] = 'FUJITSU_StorageVolume'
583        keys2 = {}
584        keys2['CreationClassName'] = 'FUJITSU_StorageVolume'
585        keys2['SystemName'] = STORAGE_SYSTEM
586        keys2['DeviceID'] = snap_vol['DeviceID']
587        keys2['SystemCreationClassName'] = 'FUJITSU_StorageComputerSystem'
588        name2['keybindings'] = keys2
589        snap_vol['provider_location'] = str(name2)
590
591        volumes.append(snap_vol)
592
593        clone_vol = FJ_StorageVolume()
594        clone_vol['name'] = TEST_CLONE['name']
595        clone_vol['CreationClassName'] = 'FUJITSU_StorageVolume'
596        clone_vol['ElementName'] = TEST_CLONE['name']
597        clone_vol['DeviceID'] = FAKE_LUN_ID2
598        clone_vol['SystemName'] = STORAGE_SYSTEM
599        clone_vol['SystemCreationClassName'] = 'FUJITSU_StorageComputerSystem'
600        clone_vol.path = clone_vol
601        clone_vol.path.classname = clone_vol['CreationClassName']
602        volumes.append(clone_vol)
603
604        return volumes
605
606    def _enum_snapshots(self):
607        snapshots = []
608        snap = FJ_StorageVolume()
609        snap['CreationClassName'] = 'FUJITSU_StorageVolume'
610        snap['SystemName'] = STORAGE_SYSTEM
611        snap['DeviceID'] = FAKE_LUN_ID2
612        snap['SystemCreationClassName'] = 'FUJITSU_StorageComputerSystem'
613        snap.path = snap
614        snap.path.classname = snap['CreationClassName']
615
616        snapshots.append(snap)
617
618        return snapshots
619
620    def _enum_lunmaskctrls(self):
621        ctrls = []
622        ctrl = {}
623        ctrl2 = {}
624        if MAP_STAT == '1':
625            ctrl['CreationClassName'] = SCSI_PROT_CTR
626            ctrl['SystemName'] = STORAGE_SYSTEM
627            ctrl['DeviceID'] = LUNMASKCTRL_IDS[0]
628            ctrls.append(ctrl)
629
630            ctrl2['CreationClassName'] = SCSI_PROT_CTR
631            ctrl2['SystemName'] = STORAGE_SYSTEM
632            ctrl2['DeviceID'] = LUNMASKCTRL_IDS[1]
633            ctrls.append(ctrl2)
634
635        return ctrls
636
637    def _enum_scsiport_endpoint(self):
638        targetlist = []
639        tgtport1 = {}
640        tgtport1['Name'] = '1234567890000021'
641        tgtport1['CreationClassName'] = 'FUJITSU_SCSIProtocolEndpoint'
642        tgtport1['ConnectionType'] = 2
643        tgtport1['RAMode'] = 0
644        targetlist.append(tgtport1)
645
646        return targetlist
647
648    def _enum_ipproto_endpoint(self):
649        targetlist = []
650        tgtport1 = {}
651        tgtport1['CreationClassName'] = 'FUJITSU_IPProtocolEndpoint'
652        tgtport1['NAME'] = 'IP_CM01CA00P00_00'
653        targetlist.append(tgtport1)
654
655        return targetlist
656
657    def _enum_tcp_endpoint(self):
658        targetlist = []
659        tgtport1 = {}
660        tgtport1['CreationClassName'] = 'FUJITSU_TCPProtocolEndpoint'
661        tgtport1['NAME'] = 'TCP_CM01CA00P00_00'
662        targetlist.append(tgtport1)
663
664        return targetlist
665
666    def _enum_iscsiprot_endpoint(self):
667        targetlist = []
668        tgtport1 = {}
669        tgtport1['Name'] = ('iqn.2000-09.com.fujitsu:storage-system.'
670                            'eternus-dxl:0123456789,t,0x0009')
671        tgtport1['ConnectionType'] = 7
672        tgtport1['RAMode'] = 0
673        targetlist.append(tgtport1)
674
675        return targetlist
676
677    def _getinstance_storagevolume(self, objpath):
678        foundinstance = None
679        instance = FJ_StorageVolume()
680        volumes = self._enum_volumes()
681        for volume in volumes:
682            if volume['DeviceID'] == objpath['DeviceID']:
683                instance = volume
684                break
685        if not instance:
686            foundinstance = None
687        else:
688            foundinstance = instance
689        return foundinstance
690
691    def _getinstance_ipprotocolendpoint(self, objpath):
692        instance = {}
693        instance['IPv4Address'] = '10.0.0.3'
694        return instance
695
696
697class FJFCDriverTestCase(test.TestCase):
698    def __init__(self, *args, **kwargs):
699        super(FJFCDriverTestCase, self).__init__(*args, **kwargs)
700
701    def setUp(self):
702        super(FJFCDriverTestCase, self).setUp()
703
704        # Make fake xml-configuration file.
705        self.config_file = tempfile.NamedTemporaryFile("w+", suffix='.xml')
706        self.addCleanup(self.config_file.close)
707        self.config_file.write(CONF)
708        self.config_file.flush()
709
710        # Make fake Object by using mock as configuration object.
711        self.configuration = mock.Mock(spec=conf.Configuration)
712        self.configuration.cinder_eternus_config_file = self.config_file.name
713
714        self.mock_object(dx_common.FJDXCommon, '_get_eternus_connection',
715                         self.fake_eternus_connection)
716
717        instancename = FakeCIMInstanceName()
718        self.mock_object(dx_common.FJDXCommon, '_create_eternus_instance_name',
719                         instancename.fake_create_eternus_instance_name)
720
721        # Set iscsi driver to self.driver.
722        driver = dx_fc.FJDXFCDriver(configuration=self.configuration)
723        self.driver = driver
724
725    def fake_eternus_connection(self):
726        conn = FakeEternusConnection()
727        return conn
728
729    def test_get_volume_stats(self):
730        ret = self.driver.get_volume_stats(True)
731        stats = {'vendor_name': ret['vendor_name'],
732                 'total_capacity_gb': ret['total_capacity_gb'],
733                 'free_capacity_gb': ret['free_capacity_gb']}
734        self.assertEqual(FAKE_STATS, stats)
735
736    def test_create_and_delete_volume(self):
737        model_info = self.driver.create_volume(TEST_VOLUME)
738        self.assertEqual(FAKE_MODEL_INFO1, model_info)
739
740        self.driver.delete_volume(TEST_VOLUME)
741
742    @mock.patch.object(dx_common.FJDXCommon, '_get_mapdata')
743    def test_map_unmap(self, mock_mapdata):
744        fake_data = {'target_wwn': FC_TARGET_WWN,
745                     'target_lun': 0}
746
747        mock_mapdata.return_value = fake_data
748        fake_mapdata = dict(fake_data)
749        fake_mapdata['initiator_target_map'] = {
750            initiator: FC_TARGET_WWN for initiator in TEST_WWPN
751        }
752
753        fake_mapdata['volume_id'] = TEST_VOLUME['id']
754        fake_mapdata['target_discovered'] = True
755        fake_info = {'driver_volume_type': 'fibre_channel',
756                     'data': fake_mapdata}
757
758        model_info = self.driver.create_volume(TEST_VOLUME)
759        self.assertEqual(FAKE_MODEL_INFO1, model_info)
760
761        info = self.driver.initialize_connection(TEST_VOLUME,
762                                                 TEST_CONNECTOR)
763        self.assertEqual(fake_info, info)
764        # Call terminate_connection with connector.
765        self.driver.terminate_connection(TEST_VOLUME,
766                                         TEST_CONNECTOR)
767
768        info = self.driver.initialize_connection(TEST_VOLUME,
769                                                 TEST_CONNECTOR)
770        self.assertEqual(fake_info, info)
771        # Call terminate_connection without connector.
772        self.driver.terminate_connection(TEST_VOLUME,
773                                         None)
774
775        self.driver.delete_volume(TEST_VOLUME)
776
777    def test_create_and_delete_snapshot(self):
778        model_info = self.driver.create_volume(TEST_VOLUME)
779        self.assertEqual(FAKE_MODEL_INFO1, model_info)
780
781        snap_info = self.driver.create_snapshot(TEST_SNAP)
782        self.assertEqual(FAKE_SNAP_INFO, snap_info)
783
784        self.driver.delete_snapshot(TEST_SNAP)
785        self.driver.delete_volume(TEST_VOLUME)
786
787    def test_create_volume_from_snapshot(self):
788        model_info = self.driver.create_volume(TEST_VOLUME)
789        self.assertEqual(FAKE_MODEL_INFO1, model_info)
790
791        snap_info = self.driver.create_snapshot(TEST_SNAP)
792        self.assertEqual(FAKE_SNAP_INFO, snap_info)
793
794        model_info = self.driver.create_volume_from_snapshot(TEST_CLONE,
795                                                             TEST_SNAP)
796        self.assertEqual(FAKE_MODEL_INFO2, model_info)
797
798        self.driver.delete_snapshot(TEST_SNAP)
799        self.driver.delete_volume(TEST_CLONE)
800        self.driver.delete_volume(TEST_VOLUME)
801
802    def test_create_cloned_volume(self):
803        model_info = self.driver.create_volume(TEST_VOLUME)
804        self.assertEqual(FAKE_MODEL_INFO1, model_info)
805
806        model_info = self.driver.create_cloned_volume(TEST_CLONE, TEST_VOLUME)
807        self.assertEqual(FAKE_MODEL_INFO2, model_info)
808
809        self.driver.delete_volume(TEST_CLONE)
810        self.driver.delete_volume(TEST_VOLUME)
811
812    def test_extend_volume(self):
813        model_info = self.driver.create_volume(TEST_VOLUME)
814        self.assertEqual(FAKE_MODEL_INFO1, model_info)
815
816        self.driver.extend_volume(TEST_VOLUME, 10)
817
818
819class FJISCSIDriverTestCase(test.TestCase):
820    def __init__(self, *args, **kwargs):
821        super(FJISCSIDriverTestCase, self).__init__(*args, **kwargs)
822
823    def setUp(self):
824        super(FJISCSIDriverTestCase, self).setUp()
825
826        # Make fake xml-configuration file.
827        self.config_file = tempfile.NamedTemporaryFile("w+", suffix='.xml')
828        self.addCleanup(self.config_file.close)
829        self.config_file.write(CONF)
830        self.config_file.flush()
831
832        # Make fake Object by using mock as configuration object.
833        self.configuration = mock.Mock(spec=conf.Configuration)
834        self.configuration.cinder_eternus_config_file = self.config_file.name
835
836        self.mock_object(dx_common.FJDXCommon, '_get_eternus_connection',
837                         self.fake_eternus_connection)
838
839        instancename = FakeCIMInstanceName()
840        self.mock_object(dx_common.FJDXCommon, '_create_eternus_instance_name',
841                         instancename.fake_create_eternus_instance_name)
842
843        self.mock_object(dx_common.FJDXCommon, '_get_mapdata_iscsi',
844                         self.fake_get_mapdata)
845
846        # Set iscsi driver to self.driver.
847        driver = dx_iscsi.FJDXISCSIDriver(configuration=self.configuration)
848        self.driver = driver
849
850    def fake_eternus_connection(self):
851        conn = FakeEternusConnection()
852        return conn
853
854    def fake_get_mapdata(self, vol_instance, connector, target_portlist):
855        multipath = connector.get('multipath', False)
856        if multipath:
857            return {'target_portals': [ISCSI_TARGET_IP],
858                    'target_iqns': [ISCSI_TARGET_IQN],
859                    'target_luns': [0]}
860        else:
861            return {'target_portal': ISCSI_TARGET_IP,
862                    'target_iqns': ISCSI_TARGET_IQN,
863                    'target_lun': 0}
864
865    def test_get_volume_stats(self):
866        ret = self.driver.get_volume_stats(True)
867        stats = {'vendor_name': ret['vendor_name'],
868                 'total_capacity_gb': ret['total_capacity_gb'],
869                 'free_capacity_gb': ret['free_capacity_gb']}
870        self.assertEqual(FAKE_STATS, stats)
871
872    def test_create_and_delete_volume(self):
873        model_info = self.driver.create_volume(TEST_VOLUME)
874        self.assertEqual(FAKE_MODEL_INFO1, model_info)
875
876        self.driver.delete_volume(TEST_VOLUME)
877
878    def test_map_unmap(self):
879        fake_mapdata = self.fake_get_mapdata(None, {}, None)
880        fake_mapdata['volume_id'] = TEST_VOLUME['id']
881        fake_mapdata['target_discovered'] = True
882        fake_info = {'driver_volume_type': 'iscsi',
883                     'data': fake_mapdata}
884
885        model_info = self.driver.create_volume(TEST_VOLUME)
886        self.assertEqual(FAKE_MODEL_INFO1, model_info)
887
888        info = self.driver.initialize_connection(TEST_VOLUME,
889                                                 TEST_CONNECTOR)
890        self.assertEqual(fake_info, info)
891        # Call terminate_connection with connector.
892        self.driver.terminate_connection(TEST_VOLUME,
893                                         TEST_CONNECTOR)
894
895        info = self.driver.initialize_connection(TEST_VOLUME,
896                                                 TEST_CONNECTOR)
897        self.assertEqual(fake_info, info)
898        # Call terminate_connection without connector.
899        self.driver.terminate_connection(TEST_VOLUME,
900                                         None)
901        self.driver.delete_volume(TEST_VOLUME)
902
903    def test_create_and_delete_snapshot(self):
904        model_info = self.driver.create_volume(TEST_VOLUME)
905        self.assertEqual(FAKE_MODEL_INFO1, model_info)
906
907        snap_info = self.driver.create_snapshot(TEST_SNAP)
908        self.assertEqual(FAKE_SNAP_INFO, snap_info)
909
910        self.driver.delete_snapshot(TEST_SNAP)
911        self.driver.delete_volume(TEST_VOLUME)
912
913    def test_create_volume_from_snapshot(self):
914        model_info = self.driver.create_volume(TEST_VOLUME)
915        self.assertEqual(FAKE_MODEL_INFO1, model_info)
916
917        snap_info = self.driver.create_snapshot(TEST_SNAP)
918        self.assertEqual(FAKE_SNAP_INFO, snap_info)
919
920        model_info = self.driver.create_volume_from_snapshot(TEST_CLONE,
921                                                             TEST_SNAP)
922        self.assertEqual(FAKE_MODEL_INFO2, model_info)
923
924        self.driver.delete_snapshot(TEST_SNAP)
925        self.driver.delete_volume(TEST_CLONE)
926        self.driver.delete_volume(TEST_VOLUME)
927
928    def test_create_cloned_volume(self):
929        model_info = self.driver.create_volume(TEST_VOLUME)
930        self.assertEqual(FAKE_MODEL_INFO1, model_info)
931
932        model_info = self.driver.create_cloned_volume(TEST_CLONE, TEST_VOLUME)
933        self.assertEqual(FAKE_MODEL_INFO2, model_info)
934
935        self.driver.delete_volume(TEST_CLONE)
936        self.driver.delete_volume(TEST_VOLUME)
937
938    def test_extend_volume(self):
939        model_info = self.driver.create_volume(TEST_VOLUME)
940        self.assertEqual(FAKE_MODEL_INFO1, model_info)
941
942        self.driver.extend_volume(TEST_VOLUME, 10)
943